BMP581: Add Bosch BMP581 barometer (#23064)

* BMP581: Add Bosch BMP581 barometer

* Copyright:fix copyright header year

* style: not use pointers and Bool returns, Check the failed condition return

* delay: Replace usleep() with ScheduleDelayed()

* definitions: Delete unused definitions

* comment: Delet redundant comments

* constants: Change to uppercase

* BMP581: run make format
This commit is contained in:
Liu1
2024-07-14 14:08:20 -08:00
committed by GitHub
parent e2b31454a3
commit b1b0032b8d
10 changed files with 1425 additions and 2 deletions
+2 -1
View File
@@ -1,6 +1,6 @@
############################################################################
#
# Copyright (c) 2017 PX4 Development Team. All rights reserved.
# Copyright (c) 2017-2024 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -33,6 +33,7 @@
add_subdirectory(bmp280)
add_subdirectory(bmp388)
add_subdirectory(bmp581)
add_subdirectory(dps310)
add_subdirectory(lps22hb)
#add_subdirectory(lps25h) # not ready for general inclusion
+1
View File
@@ -4,6 +4,7 @@ menu "barometer"
default n
select DRIVERS_BAROMETER_BMP280
select DRIVERS_BAROMETER_BMP388
select DRIVERS_BAROMETER_BMP581
select DRIVERS_BAROMETER_DPS310
select DRIVERS_BAROMETER_LPS22HB
select DRIVERS_BAROMETER_LPS33HW
@@ -0,0 +1,44 @@
############################################################################
#
# Copyright (c) 2024 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
px4_add_module(
MODULE drivers__barometer__bmp581
MAIN bmp581
SRCS
bmp581_spi.cpp
bmp581_i2c.cpp
bmp581.cpp
bmp581_main.cpp
DEPENDS
px4_work_queue
)
+5
View File
@@ -0,0 +1,5 @@
menuconfig DRIVERS_BAROMETER_BMP581
bool "bmp581"
default n
---help---
Enable support for bmp581
+727
View File
@@ -0,0 +1,727 @@
/****************************************************************************
*
* Copyright (c) 2024 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESSf
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#include "bmp581.h"
#include <cstdint>
BMP581::BMP581(const I2CSPIDriverConfig &config, IBMP581 *interface) :
I2CSPIDriver(config),
_interface(interface),
_sample_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": read")),
_measure_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": measure")),
_comms_errors(perf_alloc(PC_COUNT, MODULE_NAME": comms_errors"))
{
}
BMP581::~BMP581()
{
/* free perf counters */
perf_free(_sample_perf);
perf_free(_measure_perf);
perf_free(_comms_errors);
delete _interface;
}
int BMP581::init()
{
int ret;
ret = soft_reset();
if (ret != PX4_OK) {
PX4_DEBUG("failed to reset baro during init");
return -EIO;
}
_chip_id = _interface->get_reg(BMP5_REG_CHIP_ID_ADDR);
if ((_chip_id != BMP581_CHIP_ID_PRIM) && (_chip_id != BMP581_CHIP_ID_SEC)) {
PX4_WARN("id of your baro is not: 0x%02x or 0x%02x", BMP581_CHIP_ID_PRIM, BMP581_CHIP_ID_SEC);
return -EIO;
}
_chip_rev_id = _interface->get_reg(BMP5_REG_REV_ID_ADDR);
ret = set_config();
if (ret != PX4_OK) {
PX4_WARN("failed to set_config");
return -EIO;
}
start();
return PX4_OK;
}
void BMP581::print_status()
{
I2CSPIDriverBase::print_status();
printf("chip id: 0x%02x rev id: 0x%02x\n", _chip_id, _chip_rev_id);
perf_print_counter(_sample_perf);
perf_print_counter(_measure_perf);
perf_print_counter(_comms_errors);
printf("measurement interval: %u us \n", _measure_interval);
}
void BMP581::start()
{
_collect_phase = false;
ScheduleOnInterval(_measure_interval, _measure_interval * 3);
}
void BMP581::RunImpl()
{
if (_collect_phase) {
collect();
}
measure();
}
int BMP581::measure()
{
int ret;
_collect_phase = true;
perf_begin(_measure_perf);
/* start measurement */
ret = set_power_mode(BMP5_POWERMODE_FORCED);
if (ret != PX4_OK) {
PX4_DEBUG("failed to set power mode");
perf_count(_comms_errors);
perf_cancel(_measure_perf);
return -EIO;
}
perf_end(_measure_perf);
return PX4_OK;
}
int BMP581::collect()
{
_collect_phase = false;
bmp5_sensor_data data{};
uint8_t int_status;
int ret;
perf_begin(_sample_perf);
/* this should be fairly close to the end of the conversion, so the best approximation of the time */
const hrt_abstime timestamp_sample = hrt_absolute_time();
int_status = get_interrupt_status();
if (int_status & BMP5_INT_ASSERTED_DRDY) {
ret = get_sensor_data(&data);
if (ret != PX4_OK) {
perf_count(_comms_errors);
perf_cancel(_sample_perf);
return -EIO;
}
}
//publish
sensor_baro_s sensor_baro{};
sensor_baro.timestamp_sample = timestamp_sample;
sensor_baro.device_id = _interface->get_device_id();
sensor_baro.pressure = data.pressure;
sensor_baro.temperature = data.temperature;
sensor_baro.error_count = perf_event_count(_comms_errors);
sensor_baro.timestamp = hrt_absolute_time();
_sensor_baro_pub.publish(sensor_baro);
perf_end(_sample_perf);
return PX4_OK;
}
/*!
* @brief This API performs the soft reset of the sensor
*
* https://github.com/boschsensortec/BMP5-Sensor-API/blob/master/bmp5.c
*/
int BMP581::soft_reset()
{
uint8_t status;
int ret;
if (intf == BMP5_SPI_INTF) {
/* Performing a single read via SPI of registers,
* e.g. registers CHIP_ID, before the actual
* SPI communication with the device.
*/
status = _interface->get_reg(BMP5_REG_CHIP_ID_ADDR);
}
ret = _interface->set_reg(BMP5_SOFT_RESET_CMD, BMP5_REG_CMD_ADDR);
if (ret != PX4_OK) {
return PX4_ERROR;
}
usleep(BMP5_DELAY_US_SOFT_RESET);
if (intf == BMP5_SPI_INTF) {
/* Performing a single read via SPI of registers,
* e.g. registers CHIP_ID, before the actual
* SPI communication with the device.
*/
status = _interface->get_reg(BMP5_REG_CHIP_ID_ADDR);
}
status = _interface->get_reg(BMP5_REG_STATUS_ADDR);
/* Check if nvm_rdy status = 1 and nvm_err status = 0 to proceed */
if (!((status & BMP5_INT_NVM_RDY) && (!(status & BMP5_INT_NVM_ERR)))) {
return PX4_ERROR;
}
status = _interface->get_reg(BMP5_REG_INT_STATUS_ADDR);
if (status & BMP5_INT_ASSERTED_POR_SOFTRESET_COMPLETE) {
return PX4_OK;
} else {
return PX4_ERROR;
}
}
int BMP581::set_config()
{
int ret;
ret = set_power_mode(BMP5_POWERMODE_STANDBY);
if (ret != PX4_OK) {
return PX4_ERROR;
}
ret = set_osr_odr_press_config();
if (ret != PX4_OK) {
return PX4_ERROR;
}
ret = set_iir_config();
if (ret != PX4_OK) {
return PX4_ERROR;
}
ret = configure_interrupt();
if (ret != PX4_OK) {
return PX4_ERROR;
}
ret = int_source_select();
if (ret != PX4_OK) {
return PX4_ERROR;
}
return PX4_OK;
}
/*!
* @brief This API is used to get interrupt status.
*/
uint8_t BMP581::get_interrupt_status()
{
uint8_t status = 0xFF;
status = _interface->get_reg(BMP5_REG_INT_STATUS_ADDR);
return status;
}
uint8_t BMP581::check_deepstandby_mode()
{
int rslt;
uint8_t fifo_frame_sel;
uint8_t reg_data[2];
uint8_t powermode = 0xFF;
fifo_frame_sel = _interface->get_reg(BMP5_REG_FIFO_SEL_ADDR);
fifo_frame_sel = BMP5_GET_BITS_POS_0(fifo_frame_sel, BMP5_FIFO_FRAME_SEL);
rslt = _interface->get_reg_buf(BMP5_REG_OSR_CONFIG_ADDR, reg_data, 2);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
uint8_t odr_reg = 0xFF;
odr_reg = BMP5_GET_BITSLICE(reg_data[1], BMP5_ODR);
rslt = _interface->get_reg_buf(BMP5_REG_DSP_CONFIG_ADDR, reg_data, 2);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
uint8_t set_iir_t_reg = 0xFF;
uint8_t set_iir_p_reg = 0xFF;
set_iir_t_reg = BMP5_GET_BITS_POS_0(reg_data[1], BMP5_SET_IIR_TEMP);
set_iir_p_reg = BMP5_GET_BITSLICE(reg_data[1], BMP5_SET_IIR_PRESS);
/* As per datasheet odr should be less than 5Hz. But register value for 5Hz is less than 4Hz and so,
* thus in this below condition odr is checked whether greater than 5Hz macro.
*/
if ((odr_reg > BMP5_ODR_05_HZ) && (fifo_frame_sel == BMP5_DISABLE) &&
(set_iir_t_reg == BMP5_IIR_FILTER_BYPASS) && (set_iir_p_reg == BMP5_IIR_FILTER_BYPASS)) {
powermode = BMP5_POWERMODE_DEEP_STANDBY;
}
return powermode;
}
/*!
* @brief This API is used to get powermode of the sensor.
*/
uint8_t BMP581::get_power_mode()
{
uint8_t deep_dis;
uint8_t reg_data;
uint8_t powermode;
reg_data = _interface->get_reg(BMP5_REG_ODR_CONFIG_ADDR);
powermode = BMP5_GET_BITS_POS_0(reg_data, BMP5_POWERMODE);
if (powermode == BMP5_POWERMODE_STANDBY) {
deep_dis = BMP5_GET_BITSLICE(reg_data, BMP5_DEEP_DISABLE);
if (deep_dis == BMP5_DEEP_ENABLED) {
powermode = check_deepstandby_mode();
}
}
return powermode;
}
/*!
* @brief This API is used to set powermode of the sensor.
*/
int BMP581::set_power_mode(uint8_t power_mode)
{
uint8_t lst_pwrmode;
uint8_t reg_data;
int rslt;
lst_pwrmode = get_power_mode();
if (lst_pwrmode != BMP5_POWERMODE_STANDBY) {
reg_data = _interface->get_reg(BMP5_REG_ODR_CONFIG_ADDR);
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_DEEP_DISABLE, BMP5_DEEP_DISABLED);
reg_data = BMP5_SET_BITS_POS_0(reg_data, BMP5_POWERMODE, BMP5_POWERMODE_STANDBY);
rslt = _interface->set_reg(reg_data, BMP5_REG_ODR_CONFIG_ADDR);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
ScheduleDelayed(BMP5_DELAY_US_STANDBY);
}
switch (power_mode) {
case BMP5_POWERMODE_DEEP_STANDBY:
rslt = set_deep_standby_mode();
if (rslt != PX4_OK) {
return PX4_ERROR;
}
break;
case BMP5_POWERMODE_STANDBY:
break;
case BMP5_POWERMODE_NORMAL:
case BMP5_POWERMODE_FORCED:
case BMP5_POWERMODE_CONTINOUS:
reg_data = _interface->get_reg(BMP5_REG_ODR_CONFIG_ADDR);
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_DEEP_DISABLE, BMP5_DEEP_DISABLED);
reg_data = BMP5_SET_BITS_POS_0(reg_data, BMP5_POWERMODE, power_mode);
rslt = _interface->set_reg(reg_data, BMP5_REG_ODR_CONFIG_ADDR);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
break;
}
return PX4_OK;
}
/*!
* @brief This internal API is used to set sensor in deep standby mode.
*/
int BMP581::set_deep_standby_mode()
{
uint8_t reg_data;
int rslt;
reg_data = _interface->get_reg(BMP5_REG_ODR_CONFIG_ADDR);
reg_data = BMP5_SET_BIT_VAL_0(reg_data, BMP5_DEEP_DISABLE);
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_ODR, BMP5_ODR_01_HZ);
rslt = _interface->set_reg(reg_data, BMP5_REG_ODR_CONFIG_ADDR);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
reg_data = _interface->get_reg(BMP5_REG_DSP_IIR_ADDR);
reg_data = reg_data & BMP5_IIR_BYPASS;
rslt = _interface->set_reg(reg_data, BMP5_REG_DSP_IIR_ADDR);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
reg_data = _interface->get_reg(BMP5_REG_FIFO_SEL_ADDR);
reg_data = BMP5_SET_BIT_VAL_0(reg_data, BMP5_FIFO_FRAME_SEL);
rslt = _interface->set_reg(reg_data, BMP5_REG_FIFO_SEL_ADDR);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
return PX4_OK;
}
/*!
* @brief This internal API is used to set sensor in standby powermode when powermode is deepstandby mode.
*/
int BMP581::set_standby_mode()
{
uint8_t powermode;
int ret;
powermode = get_power_mode();
if (powermode == BMP5_POWERMODE_DEEP_STANDBY) {
ret = set_power_mode(BMP5_POWERMODE_STANDBY);
if (ret != PX4_OK) {
return PX4_ERROR;
}
}
return PX4_OK;
}
uint32_t BMP581::get_measurement_time()
{
/*
From BST-BMP3581-DS004-04.pdf, page 19, table 9
Pressure Temperature Measurement
Oversample Oversample Time
1x 1x 2.7 ms
2x 1x 3.3 ms
4x 1x 4.6 ms
8x 1x 7.2 ms
16x 1x 12.5 ms
32x 2x 23.3 ms
64x 4x 44.2 ms
128x 8x 88.0 ms
*/
uint32_t meas_time_us = 0; // unsupported value by default
if (OVERSAMPLING_TEMPERATURE == BMP5_OVERSAMPLING_1X) {
switch (OVERSAMPLING_PRESSURE) {
case BMP5_OVERSAMPLING_1X:
meas_time_us = 2700;
break;
case BMP5_OVERSAMPLING_2X:
meas_time_us = 3300;
break;
case BMP5_OVERSAMPLING_4X:
meas_time_us = 4600;
break;
case BMP5_OVERSAMPLING_8X:
meas_time_us = 7200;
break;
case BMP5_OVERSAMPLING_16X:
meas_time_us = 12500;
break;
}
} else if (OVERSAMPLING_TEMPERATURE == BMP5_OVERSAMPLING_2X) {
switch (OVERSAMPLING_PRESSURE) {
case BMP5_OVERSAMPLING_32X:
meas_time_us = 23300;
break;
}
} else if (OVERSAMPLING_TEMPERATURE == BMP5_OVERSAMPLING_4X) {
switch (OVERSAMPLING_PRESSURE) {
case BMP5_OVERSAMPLING_64X:
meas_time_us = 44200;
break;
}
} else if (OVERSAMPLING_TEMPERATURE == BMP5_OVERSAMPLING_8X) {
switch (OVERSAMPLING_PRESSURE) {
case BMP5_OVERSAMPLING_128X:
meas_time_us = 88000;
break;
}
}
return meas_time_us;
}
/*!
* @brief This API sets the configuration for oversampling temperature, oversampling of
* pressure and ODR configuration along with pressure enable.
*
* @note If ODR is set to a value higher than 5Hz then powermode is set as standby mode, as ODR value greater than 5HZ
* without disabling deep-standby mode makes powermode invalid.
*/
int BMP581::set_osr_odr_press_config()
{
uint8_t reg_data[2] = {0};
int rslt;
_measure_interval = get_measurement_time();
if (_measure_interval == 0) {
PX4_WARN("unsupported oversampling selected");
return false;
}
if (OUTPUT_DATA_RATE < BMP5_ODR_05_HZ) {
rslt = set_standby_mode();
if (rslt != PX4_OK) {
return PX4_ERROR;
}
}
rslt = _interface->get_reg_buf(BMP5_REG_OSR_CONFIG_ADDR, reg_data, 2);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
reg_data[0] = BMP5_SET_BITS_POS_0(reg_data[0], BMP5_TEMP_OS, OVERSAMPLING_TEMPERATURE);
reg_data[0] = BMP5_SET_BITSLICE(reg_data[0], BMP5_PRESS_OS, OVERSAMPLING_PRESSURE);
reg_data[0] = BMP5_SET_BITSLICE(reg_data[0], BMP5_PRESS_EN, PRESSURE_ENABLE);
reg_data[1] = BMP5_SET_BITSLICE(reg_data[1], BMP5_ODR, OUTPUT_DATA_RATE);
rslt = _interface->set_reg(reg_data[0], BMP5_REG_OSR_CONFIG_ADDR);
rslt = _interface->set_reg(reg_data[1], BMP5_REG_ODR_CONFIG_ADDR);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
return PX4_OK;
}
/*!
* @brief This API sets the configuration for IIR of temperature and pressure.
*
* @note If IIR value for both temperature and pressure is set a value other than bypass then powermode is set
* as standby mode, as IIR with value other than bypass without disabling deep-standby mode makes powermode invalid.
*/
int BMP581::set_iir_config()
{
uint8_t curr_powermdoe;
uint8_t reg_data[2];
int rslt;
if ((IIR_FILTER_COEFF_TEMPERATURE != BMP5_IIR_FILTER_BYPASS) || (IIR_FILTER_COEFF_PRESSURE != BMP5_IIR_FILTER_BYPASS)) {
rslt = set_standby_mode();
if (rslt != PX4_OK) {
return PX4_ERROR;
}
}
curr_powermdoe = get_power_mode();
if (curr_powermdoe != BMP5_POWERMODE_STANDBY) {
rslt = set_power_mode(BMP5_POWERMODE_STANDBY);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
}
rslt = _interface->get_reg_buf(BMP5_REG_DSP_CONFIG_ADDR, reg_data, 2);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
reg_data[0] = BMP5_SET_BITSLICE(reg_data[0], BMP5_SHDW_SET_IIR_TEMP, BMP5_ENABLE);
reg_data[0] = BMP5_SET_BITSLICE(reg_data[0], BMP5_SHDW_SET_IIR_PRESS, BMP5_ENABLE);
reg_data[0] = BMP5_SET_BITSLICE(reg_data[0], BMP5_IIR_FLUSH_FORCED_EN, BMP5_ENABLE);
reg_data[1] = IIR_FILTER_COEFF_TEMPERATURE;
reg_data[1] = BMP5_SET_BITSLICE(reg_data[1], BMP5_SET_IIR_PRESS, IIR_FILTER_COEFF_PRESSURE);
rslt = _interface->set_reg(reg_data[0], BMP5_REG_DSP_CONFIG_ADDR);
rslt = _interface->set_reg(reg_data[1], BMP5_REG_DSP_IIR_ADDR);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
/* Since IIR works only in standby mode we are not re-writing to deepstandby mode
* as deep standby mode resets the IIR settings to default
*/
if ((curr_powermdoe != BMP5_POWERMODE_STANDBY) && (curr_powermdoe != BMP5_POWERMODE_DEEP_STANDBY)) {
if (!set_power_mode(curr_powermdoe)) {
return PX4_ERROR;
}
}
return PX4_OK;
}
/*!
* @brief This API is used to configure the interrupt settings.
*/
int BMP581::configure_interrupt()
{
uint8_t reg_data = 0;
uint8_t int_source = 0;
int rslt;
reg_data = _interface->get_reg(BMP5_REG_INT_CONFIG_ADDR);
/* Any change between latched/pulsed mode has to be applied while interrupt is disabled */
/* Step 1 : Turn off all INT sources (INT_SOURCE -> 0x00) */
rslt = _interface->set_reg(int_source, BMP5_REG_INT_SOURCE_ADDR);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
/* Step 2 : Read the INT_STATUS register to clear the status */
_interface->get_reg(BMP5_REG_INT_STATUS_ADDR);
/* Step 3 : Set the desired mode in INT_CONFIG.int_mode */
reg_data = BMP5_SET_BITS_POS_0(reg_data, BMP5_INT_MODE, INTERRUPT_MODE);
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_INT_POL, INTERRUPT_POLARITY);
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_INT_OD, INTERRUPT_DRIVE);
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_INT_EN, BMP5_ENABLE);
rslt = _interface->set_reg(reg_data, BMP5_REG_INT_CONFIG_ADDR);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
return PX4_OK;
}
int BMP581::int_source_select()
{
uint8_t reg_data;
int rslt;
reg_data = _interface->get_reg(BMP5_REG_INT_SOURCE_ADDR);
reg_data = BMP5_SET_BITS_POS_0(reg_data, BMP5_INT_DRDY_EN, BMP5_ENABLE);
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_INT_FIFO_FULL_EN, BMP5_DISABLE);
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_INT_FIFO_THRES_EN, BMP5_DISABLE);
reg_data = BMP5_SET_BITSLICE(reg_data, BMP5_INT_OOR_PRESS_EN, BMP5_DISABLE);
rslt = _interface->set_reg(reg_data, BMP5_REG_INT_SOURCE_ADDR);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
return PX4_OK;
}
/*!
* @brief This API reads the temperature(deg C) or both pressure(Pa) and temperature(deg C) data from the
* sensor and store it in the bmp5_sensor_data structure instance passed by the user.
*/
int BMP581::get_sensor_data(bmp5_sensor_data *sensor_data)
{
uint8_t reg_data[6] = {0};
int32_t raw_data_t;
uint32_t raw_data_p;
int8_t rslt;
rslt = _interface->get_reg_buf(BMP5_REG_TEMP_DATA_XLSB_ADDR, reg_data, 6);
if (rslt != PX4_OK) {
return PX4_ERROR;
}
raw_data_t = (int32_t)((int32_t)((uint32_t)(((uint32_t)reg_data[2] << 16) | ((uint16_t)reg_data[1] << 8) | reg_data[0])
<< 8) >> 8);
/* Division by 2^16(whose equivalent value is 65536) is performed to get temperature data in deg C */
sensor_data->temperature = (float)(raw_data_t / 65536.0);
if (PRESSURE_ENABLE == BMP5_ENABLE) {
raw_data_p = (uint32_t)((uint32_t)(reg_data[5] << 16) | (uint16_t)(reg_data[4] << 8) | reg_data[3]);
/* Division by 2^6(whose equivalent value is 64) is performed to get pressure data in Pa */
sensor_data->pressure = (float)(raw_data_p / 64.0);
} else {
sensor_data->pressure = 0.0;
}
return PX4_OK;
}
+320
View File
@@ -0,0 +1,320 @@
/****************************************************************************
*
* Copyright (C) 2024 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file bmp581.h
*
* Shared defines for the bmp581 driver.
*/
#pragma once
#include <math.h>
#include <drivers/drv_hrt.h>
#include <lib/cdev/CDev.hpp>
#include <perf/perf_counter.h>
#include <px4_platform_common/i2c_spi_buses.h>
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
#include <uORB/PublicationMulti.hpp>
#include <uORB/topics/sensor_baro.h>
#include "board_config.h"
// From https://github.com/boschsensortec/BMP5-Sensor-API/blob/master/bmp5_defs.h
/* BIT SLICE GET AND SET FUNCTIONS */
#define BMP5_GET_BITSLICE(regvar, bitname) \
((regvar & bitname##_MSK) >> bitname##_POS)
#define BMP5_SET_BITSLICE(regvar, bitname, val) \
((regvar & ~bitname##_MSK) | \
((val << bitname##_POS) & bitname##_MSK))
#define BMP5_SET_BIT_VAL_0(reg_data, bitname) (reg_data & ~(bitname##_MSK))
#define BMP5_SET_BITS_POS_0(reg_data, bitname, data) \
((reg_data & ~(bitname##_MSK)) | \
(data & bitname##_MSK))
#define BMP5_GET_BITS_POS_0(reg_data, bitname) (reg_data & (bitname##_MSK))
/* Chip id of BMP5 */
#define BMP581_CHIP_ID_PRIM (0x50)
#define BMP581_CHIP_ID_SEC (0x51)
#define BMP5_ENABLE (0x01)
#define BMP5_DISABLE (0x00)
/* Register addresses */
#define BMP5_REG_CHIP_ID_ADDR (0x01)
#define BMP5_REG_REV_ID_ADDR (0x02)
#define BMP5_REG_INT_CONFIG_ADDR (0x14)
#define BMP5_REG_INT_SOURCE_ADDR (0x15)
#define BMP5_REG_FIFO_SEL_ADDR (0x18)
#define BMP5_REG_TEMP_DATA_XLSB_ADDR (0x1D)
#define BMP5_REG_INT_STATUS_ADDR (0x27)
#define BMP5_REG_STATUS_ADDR (0x28)
#define BMP5_REG_NVM_ADDR (0x2B)
#define BMP5_REG_DSP_CONFIG_ADDR (0x30)
#define BMP5_REG_DSP_IIR_ADDR (0x31)
#define BMP5_REG_OSR_CONFIG_ADDR (0x36)
#define BMP5_REG_ODR_CONFIG_ADDR (0x37)
#define BMP5_REG_CMD_ADDR (0x7E)
/* Delay definition */
#define BMP5_DELAY_US_SOFT_RESET (2000)
#define BMP5_DELAY_US_STANDBY (2500)
/* Soft reset command */
#define BMP5_SOFT_RESET_CMD (0xB6)
/* Deepstandby enable/disable */
#define BMP5_DEEP_ENABLED (0)
#define BMP5_DEEP_DISABLED (1)
/* ODR settings */
#define BMP5_ODR_50_HZ (0x0F)
#define BMP5_ODR_05_HZ (0x18)
#define BMP5_ODR_01_HZ (0x1C)
/* Oversampling for temperature and pressure */
#define BMP5_OVERSAMPLING_1X (0x00)
#define BMP5_OVERSAMPLING_2X (0x01)
#define BMP5_OVERSAMPLING_4X (0x02)
#define BMP5_OVERSAMPLING_8X (0x03)
#define BMP5_OVERSAMPLING_16X (0x04)
#define BMP5_OVERSAMPLING_32X (0x05)
#define BMP5_OVERSAMPLING_64X (0x06)
#define BMP5_OVERSAMPLING_128X (0x07)
/* IIR filter for temperature and pressure */
#define BMP5_IIR_FILTER_BYPASS (0x00)
#define BMP5_IIR_FILTER_COEFF_1 (0x01)
/* Macro is used to bypass both iir_t and iir_p together */
#define BMP5_IIR_BYPASS (0xC0)
/* Interrupt configurations */
#define BMP5_INT_MODE_PULSED (0)
#define BMP5_INT_POL_ACTIVE_HIGH (1)
#define BMP5_INT_OD_PUSHPULL (0)
/* NVM and Interrupt status asserted macros */
#define BMP5_INT_ASSERTED_POR_SOFTRESET_COMPLETE (0x10)
#define BMP5_INT_NVM_RDY (0x02)
#define BMP5_INT_NVM_ERR (0x04)
/* Interrupt configurations */
#define BMP5_INT_MODE_MSK (0x01)
#define BMP5_INT_POL_MSK (0x02)
#define BMP5_INT_POL_POS (1)
#define BMP5_INT_OD_MSK (0x04)
#define BMP5_INT_OD_POS (2)
#define BMP5_INT_EN_MSK (0x08)
#define BMP5_INT_EN_POS (3)
#define BMP5_INT_DRDY_EN_MSK (0x01)
#define BMP5_INT_FIFO_FULL_EN_MSK (0x02)
#define BMP5_INT_FIFO_FULL_EN_POS (1)
#define BMP5_INT_FIFO_THRES_EN_MSK (0x04)
#define BMP5_INT_FIFO_THRES_EN_POS (2)
#define BMP5_INT_OOR_PRESS_EN_MSK (0x08)
#define BMP5_INT_OOR_PRESS_EN_POS (3)
/* ODR configuration */
#define BMP5_ODR_MSK (0x7C)
#define BMP5_ODR_POS (2)
/* OSR configurations */
#define BMP5_TEMP_OS_MSK (0x07)
#define BMP5_PRESS_OS_MSK (0x38)
#define BMP5_PRESS_OS_POS (3)
/* Pressure enable */
#define BMP5_PRESS_EN_MSK (0x40)
#define BMP5_PRESS_EN_POS (6)
/* IIR configurations */
#define BMP5_SET_IIR_TEMP_MSK (0x07)
#define BMP5_SET_IIR_PRESS_MSK (0x38)
#define BMP5_SET_IIR_PRESS_POS (3)
#define BMP5_SHDW_SET_IIR_TEMP_MSK (0x08)
#define BMP5_SHDW_SET_IIR_TEMP_POS (3)
#define BMP5_SHDW_SET_IIR_PRESS_MSK (0x20)
#define BMP5_SHDW_SET_IIR_PRESS_POS (5)
#define BMP5_IIR_FLUSH_FORCED_EN_MSK (0x04)
#define BMP5_IIR_FLUSH_FORCED_EN_POS (2)
/* Powermode */
#define BMP5_POWERMODE_MSK (0x03)
#define BMP5_DEEP_DISABLE_MSK (0x80)
#define BMP5_DEEP_DISABLE_POS (7)
/* Fifo configurations */
#define BMP5_FIFO_FRAME_SEL_MSK (0x03)
/* NVM and Interrupt status asserted macros */
#define BMP5_INT_ASSERTED_DRDY (0x01)
/*!
* @brief Enumerator for powermode selection
*/
enum bmp5_powermode {
BMP5_POWERMODE_STANDBY,
BMP5_POWERMODE_NORMAL,
BMP5_POWERMODE_FORCED,
BMP5_POWERMODE_CONTINOUS,
BMP5_POWERMODE_DEEP_STANDBY
};
/*!
* @brief Enumerator for interface selection
*/
enum bmp5_intf {
BMP5_SPI_INTF,
BMP5_I2C_INTF,
};
/*!
* @brief BMP5 sensor data structure which comprises of temperature and pressure in floating point with data type as
* float for pressure and temperature.
*/
struct bmp5_sensor_data {
float pressure;
float temperature;
};
/*
* BMP581 internal constants and data structures.
*/
class IBMP581
{
public:
virtual ~IBMP581() = default;
virtual int init() = 0;
// read reg value
virtual uint8_t get_reg(uint8_t addr) = 0;
// bulk read reg value
virtual int get_reg_buf(uint8_t addr, uint8_t *buf, uint8_t len) = 0;
// write reg value
virtual int set_reg(uint8_t value, uint8_t addr) = 0;
virtual uint32_t get_device_id() const = 0;
virtual uint8_t get_device_address() const = 0;
};
class BMP581 : public I2CSPIDriver<BMP581>
{
public:
BMP581(const I2CSPIDriverConfig &config, IBMP581 *interface);
virtual ~BMP581();
static I2CSPIDriverBase *instantiate(const I2CSPIDriverConfig &config, int runtime_instance);
static void print_usage();
virtual int init();
void print_status();
void RunImpl();
private:
static constexpr uint8_t OVERSAMPLING_TEMPERATURE{BMP5_OVERSAMPLING_2X};
static constexpr uint8_t OVERSAMPLING_PRESSURE{BMP5_OVERSAMPLING_32X};
static constexpr uint8_t OUTPUT_DATA_RATE{BMP5_ODR_50_HZ};
static constexpr uint8_t PRESSURE_ENABLE{BMP5_ENABLE};
static constexpr uint8_t IIR_FILTER_COEFF_TEMPERATURE{BMP5_IIR_FILTER_COEFF_1};
static constexpr uint8_t IIR_FILTER_COEFF_PRESSURE{BMP5_IIR_FILTER_COEFF_1};
static constexpr uint8_t INTERRUPT_MODE{BMP5_INT_MODE_PULSED};
static constexpr uint8_t INTERRUPT_POLARITY{BMP5_INT_POL_ACTIVE_HIGH};
static constexpr uint8_t INTERRUPT_DRIVE{BMP5_INT_OD_PUSHPULL};
uORB::PublicationMulti<sensor_baro_s> _sensor_baro_pub{ORB_ID(sensor_baro)};
IBMP581 *_interface{nullptr};
unsigned _measure_interval{0}; // interval in microseconds needed to measure
perf_counter_t _sample_perf;
perf_counter_t _measure_perf;
perf_counter_t _comms_errors;
bool _collect_phase{false};
uint8_t _chip_id{0};
uint8_t _chip_rev_id{0};
void start();
int measure();
int collect(); // get results and publish
uint32_t get_measurement_time();
int soft_reset();
int set_config();
uint8_t get_interrupt_status();
int configure_interrupt();
int int_source_select();
uint8_t get_power_mode();
int set_power_mode(uint8_t power_mode);
uint8_t check_deepstandby_mode();
int set_standby_mode();
int set_deep_standby_mode();
int set_osr_odr_press_config();
int set_iir_config();
int get_sensor_data(bmp5_sensor_data *sensor_data);
};
/* interface factories */
extern IBMP581 *bmp581_spi_interface(uint8_t busnum, uint32_t device, int bus_frequency, spi_mode_e spi_mode);
extern IBMP581 *bmp581_i2c_interface(uint8_t busnum, uint32_t device, int bus_frequency);
extern enum bmp5_intf intf;
@@ -0,0 +1,95 @@
/****************************************************************************
*
* Copyright (c) 2024 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file bmp581_i2c.cpp
*
* I2C interface for BMP581
*/
#include <drivers/device/i2c.h>
#include "bmp581.h"
class BMP581_I2C: public device::I2C, public IBMP581
{
public:
BMP581_I2C(uint8_t bus, uint32_t device, int bus_frequency);
virtual ~BMP581_I2C() = default;
int init();
uint8_t get_reg(uint8_t addr);
int get_reg_buf(uint8_t addr, uint8_t *buf, uint8_t len);
int set_reg(uint8_t value, uint8_t addr);
uint32_t get_device_id() const override { return device::I2C::get_device_id(); }
uint8_t get_device_address() const override { return device::I2C::get_device_address(); }
};
IBMP581 *bmp581_i2c_interface(uint8_t busnum, uint32_t device, int bus_frequency)
{
return new BMP581_I2C(busnum, device, bus_frequency);
}
BMP581_I2C::BMP581_I2C(uint8_t bus, uint32_t device, int bus_frequency) :
I2C(DRV_BARO_DEVTYPE_BMP581, MODULE_NAME, bus, device, bus_frequency)
{
}
int BMP581_I2C::init()
{
return I2C::init();
}
uint8_t BMP581_I2C::get_reg(uint8_t addr)
{
uint8_t cmd[2] = { (uint8_t)(addr), 0};
transfer(&cmd[0], 1, &cmd[1], 1);
return cmd[1];
}
int BMP581_I2C::get_reg_buf(uint8_t addr, uint8_t *buf, uint8_t len)
{
const uint8_t cmd = (uint8_t)(addr);
return transfer(&cmd, sizeof(cmd), buf, len);
}
int BMP581_I2C::set_reg(uint8_t value, uint8_t addr)
{
uint8_t cmd[2] = { (uint8_t)(addr), value};
return transfer(cmd, sizeof(cmd), nullptr, 0);
}
@@ -0,0 +1,127 @@
/****************************************************************************
*
* Copyright (c) 2024 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/getopt.h>
#include <px4_platform_common/module.h>
#include "bmp581.h"
enum bmp5_intf intf;
void BMP581::print_usage()
{
PRINT_MODULE_USAGE_NAME("bmp581", "driver");
PRINT_MODULE_USAGE_SUBCATEGORY("baro");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, true);
PRINT_MODULE_USAGE_PARAMS_I2C_ADDRESS(0x46);
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
}
I2CSPIDriverBase *BMP581::instantiate(const I2CSPIDriverConfig &config, int runtime_instance)
{
IBMP581 *interface = nullptr;
if (config.bus_type == BOARD_I2C_BUS) {
interface = bmp581_i2c_interface(config.bus, config.i2c_address, config.bus_frequency);
intf = BMP5_I2C_INTF;
} else if (config.bus_type == BOARD_SPI_BUS) {
interface = bmp581_spi_interface(config.bus, config.spi_devid, config.bus_frequency, config.spi_mode);
intf = BMP5_SPI_INTF;
}
if (interface == nullptr) {
PX4_ERR("failed creating interface for bus %i (devid 0x%" PRIx32 ")", config.bus, config.spi_devid);
return nullptr;
}
if (interface->init() != OK) {
delete interface;
PX4_DEBUG("no device on bus %i (devid 0x%" PRIx32 ")", config.bus, config.spi_devid);
return nullptr;
}
BMP581 *dev = new BMP581(config, interface);
if (dev == nullptr) {
delete interface;
return nullptr;
}
if (dev->init() != OK) {
delete dev;
return nullptr;
}
return dev;
}
extern "C" int bmp581_main(int argc, char *argv[])
{
using ThisDriver = BMP581;
BusCLIArguments cli{true, true};
cli.i2c_address = 0x46;
cli.default_i2c_frequency = 100 * 1000;
cli.default_spi_frequency = 10 * 1000 * 1000;
const char *verb = cli.parseDefaultArguments(argc, argv);
if (!verb) {
ThisDriver::print_usage();
return -1;
}
BusInstanceIterator iterator(MODULE_NAME, cli, DRV_BARO_DEVTYPE_BMP581);
if (!strcmp(verb, "start")) {
return ThisDriver::module_start(cli, iterator);
}
if (!strcmp(verb, "stop")) {
return ThisDriver::module_stop(iterator);
}
if (!strcmp(verb, "status")) {
return ThisDriver::module_status(iterator);
}
ThisDriver::print_usage();
return -1;
}
+102
View File
@@ -0,0 +1,102 @@
/****************************************************************************
*
* Copyright (c) 2024 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file bmp581_spi.cpp
*
* SPI interface for BMP 581 (NOTE: untested!)
*/
#include <drivers/device/spi.h>
#include "bmp581.h"
/* SPI protocol address bits */
#define DIR_READ (1<<7) //for set
#define DIR_WRITE ~(1<<7) //for clear
class BMP581_SPI: public device::SPI, public IBMP581
{
public:
BMP581_SPI(uint8_t bus, uint32_t device, int bus_frequency, spi_mode_e spi_mode);
virtual ~BMP581_SPI() = default;
int init();
uint8_t get_reg(uint8_t addr);
int get_reg_buf(uint8_t addr, uint8_t *buf, uint8_t len);
int set_reg(uint8_t value, uint8_t addr);
uint32_t get_device_id() const override { return device::SPI::get_device_id(); }
uint8_t get_device_address() const override { return device::SPI::get_device_address(); }
};
IBMP581 *bmp581_spi_interface(uint8_t busnum, uint32_t device, int bus_frequency, spi_mode_e spi_mode)
{
return new BMP581_SPI(busnum, device, bus_frequency, spi_mode);
}
BMP581_SPI::BMP581_SPI(uint8_t bus, uint32_t device, int bus_frequency, spi_mode_e spi_mode) :
SPI(DRV_BARO_DEVTYPE_BMP581, MODULE_NAME, bus, device, spi_mode, bus_frequency)
{
}
int BMP581_SPI::init()
{
return SPI::init();
}
uint8_t BMP581_SPI::get_reg(uint8_t addr)
{
uint8_t cmd[2] = { (uint8_t)(addr | DIR_READ), 0}; //set MSB bit
transfer(&cmd[0], &cmd[0], 2);
return cmd[1];
}
int BMP581_SPI::get_reg_buf(uint8_t addr, uint8_t *buf, uint8_t len)
{
uint8_t cmd[len + 1] = {(uint8_t)(addr | DIR_READ)};
int ret;
ret = transfer(&cmd[0], &cmd[0], (len + 1));
memcpy(buf, &cmd[1], len);
return ret;
}
int BMP581_SPI::set_reg(uint8_t value, uint8_t addr)
{
uint8_t cmd[2] = { (uint8_t)(addr & DIR_WRITE), value}; //clear MSB bit
return transfer(&cmd[0], nullptr, 2);
}
+2 -1
View File
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2012-2023 PX4 Development Team. All rights reserved.
* Copyright (c) 2012-2024 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -151,6 +151,7 @@
#define DRV_ACC_DEVTYPE_BMI085 0x6C
#define DRV_GYR_DEVTYPE_BMI085 0x6D
#define DRV_BARO_DEVTYPE_BMP390 0x6E
#define DRV_BARO_DEVTYPE_BMP581 0x6F
#define DRV_DIST_DEVTYPE_LL40LS 0x70
#define DRV_DIST_DEVTYPE_MAPPYDOT 0x71