Path: blob/master/libraries/AP_Baro/AP_Baro_BMP581.cpp
9532 views
/*1This program is free software: you can redistribute it and/or modify2it under the terms of the GNU General Public License as published by3the Free Software Foundation, either version 3 of the License, or4(at your option) any later version.56This program is distributed in the hope that it will be useful,7but WITHOUT ANY WARRANTY; without even the implied warranty of8MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9GNU General Public License for more details.1011You should have received a copy of the GNU General Public License12along with this program. If not, see <http://www.gnu.org/licenses/>.13*/14#include "AP_Baro_BMP581.h"1516#if AP_BARO_BMP581_ENABLED1718#include <AP_Math/AP_Math.h>1920extern const AP_HAL::HAL &hal;2122#define BMP581_ID 0x502324#define BMP581_REG_CHIP_ID 0x0125#define BMP581_REG_REV_ID 0x0226#define BMP581_REG_CHIP_STATUS 0x1127#define BMP581_REG_DRIVE_CONFIG 0x1328#define BMP581_REG_INT_CONFIG 0x1429#define BMP581_REG_INT_SOURCE 0x1530#define BMP581_REG_FIFO_CONFIG 0x1631#define BMP581_REG_FIFO_COUNT 0x1732#define BMP581_REG_FIFO_SEL 0x1833#define BMP581_REG_TEMP_DATA_XLSB 0x1D34#define BMP581_REG_TEMP_DATA_LSB 0x1E35#define BMP581_REG_TEMP_DATA_MSB 0x1F36#define BMP581_REG_PRESS_DATA_XLSB 0x2037#define BMP581_REG_PRESS_DATA_LSB 0x2138#define BMP581_REG_PRESS_DATA_MSB 0x2239#define BMP581_REG_INT_STATUS 0x2740#define BMP581_REG_STATUS 0x2841#define BMP581_REG_FIFO_DATA 0x2942#define BMP581_REG_NVM_ADDR 0x2B43#define BMP581_REG_NVM_DATA_LSB 0x2C44#define BMP581_REG_NVM_DATA_MSB 0x2D45#define BMP581_REG_DSP_CONFIG 0x3046#define BMP581_REG_DSP_IIR 0x3147#define BMP581_REG_OOR_THR_P_LSB 0x3248#define BMP581_REG_OOR_THR_P_MSB 0x3349#define BMP581_REG_OOR_RANGE 0x3450#define BMP581_REG_OOR_CONFIG 0x3551#define BMP581_REG_OSR_CONFIG 0x3652#define BMP581_REG_ODR_CONFIG 0x3753#define BMP581_REG_OSR_EFF 0x3854#define BMP581_REG_CMD 0x7E5556AP_Baro_BMP581::AP_Baro_BMP581(AP_Baro &baro, AP_HAL::Device &dev)57: AP_Baro_Backend(baro)58, _dev(&dev)59{60}6162AP_Baro_Backend *AP_Baro_BMP581::probe(AP_Baro &baro, AP_HAL::Device &dev)63{64AP_Baro_BMP581 *sensor = NEW_NOTHROW AP_Baro_BMP581(baro, dev);65if (!sensor || !sensor->init()) {66delete sensor;67return nullptr;68}69return sensor;70}7172bool AP_Baro_BMP581::init()73{74if (!_dev) {75return false;76}7778WITH_SEMAPHORE(_dev->get_semaphore());7980_dev->set_speed(AP_HAL::Device::SPEED_HIGH);8182uint8_t whoami;8384// setup to allow reads on SPI85if (_dev->bus_type() == AP_HAL::Device::BUS_TYPE_SPI) {86_dev->set_read_flag(0x80);8788if (!_dev->read_registers(BMP581_REG_CHIP_ID, &whoami, 1)) {89return false;90}91}9293if (!_dev->read_registers(BMP581_REG_CHIP_ID, &whoami, 1)) {94return false;95}9697switch (whoami) {98case BMP581_ID:99_dev->set_device_type(DEVTYPE_BARO_BMP581);100break;101default:102return false;103}104105uint8_t status;106if (!_dev->read_registers(BMP581_REG_STATUS, &status, 1)) {107return false;108}109110if ((status & 0b10) == 0 || (status & 0b100)) {111return false;112}113114uint8_t int_status;115if (!_dev->read_registers(BMP581_REG_INT_STATUS, &int_status, 1)) {116return false;117}118119if ((int_status & 0x10) == 0) {120return false;121}122123_dev->setup_checked_registers(4);124125// Standby mode126_dev->write_register(BMP581_REG_ODR_CONFIG, 0, true);127128// Press EN | osr_p 64X | osr_t 4X129_dev->write_register(BMP581_REG_OSR_CONFIG, 0b01110010, true);130131// ORD 50Hz | Normal Mode132_dev->write_register(BMP581_REG_ODR_CONFIG, 0b0111101, true);133134instance = _frontend.register_sensor();135136set_bus_id(instance, _dev->get_bus_id());137138// request 50Hz update139_dev->register_periodic_callback(20 * AP_USEC_PER_MSEC, FUNCTOR_BIND_MEMBER(&AP_Baro_BMP581::timer, void));140141return true;142}143144// acumulate a new sensor reading145void AP_Baro_BMP581::timer(void)146{147uint8_t buf[6];148149if (!_dev->read_registers(BMP581_REG_TEMP_DATA_XLSB, buf, sizeof(buf))) {150return;151}152153WITH_SEMAPHORE(_sem);154155if (buf[0] != 0x7f || buf[1] != 0x7f || buf[2] != 0x7f) {156// we have temperature data157temperature = (float)((int32_t)(((uint32_t)buf[2] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[0] << 8)) >> 8) * (1.0f / 65536.0f);158}159160if (buf[3] != 0x7f || buf[4] != 0x7f || buf[5] != 0x7f) {161// we have pressure data162pressure_sum += (float)(((uint32_t)buf[5] << 16) | ((uint32_t)buf[4] << 8) | (uint32_t)buf[3]) * (1.0f / 64.0f);163pressure_count++;164}165166_dev->check_next_register();167}168169// transfer data to the frontend170void AP_Baro_BMP581::update(void)171{172WITH_SEMAPHORE(_sem);173174if (pressure_count == 0) {175return;176}177178_copy_to_frontend(instance,179pressure_sum/pressure_count,180temperature);181182pressure_sum = 0;183pressure_count = 0;184}185186#endif // AP_BARO_BMP581_ENABLED187188189