Line data Source code
1 : /* 2 : This program is free software: you can redistribute it and/or modify 3 : it under the terms of the GNU General Public License as published by 4 : the Free Software Foundation, either version 3 of the License, or 5 : (at your option) any later version. 6 : 7 : This program is distributed in the hope that it will be useful, 8 : but WITHOUT ANY WARRANTY; without even the implied warranty of 9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 : GNU General Public License for more details. 11 : 12 : You should have received a copy of the GNU General Public License 13 : along with this program. If not, see <http://www.gnu.org/licenses/>. 14 : */ 15 : #include "AP_Baro_BMP581.h" 16 : 17 : #if AP_BARO_BMP581_ENABLED 18 : 19 : #include <AP_Math/AP_Math.h> 20 : 21 : extern const AP_HAL::HAL &hal; 22 : 23 : #define BMP581_ID 0x50 24 : 25 : #define BMP581_REG_CHIP_ID 0x01 26 : #define BMP581_REG_REV_ID 0x02 27 : #define BMP581_REG_CHIP_STATUS 0x11 28 : #define BMP581_REG_DRIVE_CONFIG 0x13 29 : #define BMP581_REG_INT_CONFIG 0x14 30 : #define BMP581_REG_INT_SOURCE 0x15 31 : #define BMP581_REG_FIFO_CONFIG 0x16 32 : #define BMP581_REG_FIFO_COUNT 0x17 33 : #define BMP581_REG_FIFO_SEL 0x18 34 : #define BMP581_REG_TEMP_DATA_XLSB 0x1D 35 : #define BMP581_REG_TEMP_DATA_LSB 0x1E 36 : #define BMP581_REG_TEMP_DATA_MSB 0x1F 37 : #define BMP581_REG_PRESS_DATA_XLSB 0x20 38 : #define BMP581_REG_PRESS_DATA_LSB 0x21 39 : #define BMP581_REG_PRESS_DATA_MSB 0x22 40 : #define BMP581_REG_INT_STATUS 0x27 41 : #define BMP581_REG_STATUS 0x28 42 : #define BMP581_REG_FIFO_DATA 0x29 43 : #define BMP581_REG_NVM_ADDR 0x2B 44 : #define BMP581_REG_NVM_DATA_LSB 0x2C 45 : #define BMP581_REG_NVM_DATA_MSB 0x2D 46 : #define BMP581_REG_DSP_CONFIG 0x30 47 : #define BMP581_REG_DSP_IIR 0x31 48 : #define BMP581_REG_OOR_THR_P_LSB 0x32 49 : #define BMP581_REG_OOR_THR_P_MSB 0x33 50 : #define BMP581_REG_OOR_RANGE 0x34 51 : #define BMP581_REG_OOR_CONFIG 0x35 52 : #define BMP581_REG_OSR_CONFIG 0x36 53 : #define BMP581_REG_ODR_CONFIG 0x37 54 : #define BMP581_REG_OSR_EFF 0x38 55 : #define BMP581_REG_CMD 0x7E 56 : 57 0 : AP_Baro_BMP581::AP_Baro_BMP581(AP_Baro &baro, AP_HAL::Device &dev) 58 : : AP_Baro_Backend(baro) 59 0 : , _dev(&dev) 60 : { 61 0 : } 62 : 63 0 : AP_Baro_Backend *AP_Baro_BMP581::probe(AP_Baro &baro, AP_HAL::Device &dev) 64 : { 65 0 : AP_Baro_BMP581 *sensor = NEW_NOTHROW AP_Baro_BMP581(baro, dev); 66 0 : if (!sensor || !sensor->init()) { 67 0 : delete sensor; 68 0 : return nullptr; 69 : } 70 0 : return sensor; 71 : } 72 : 73 0 : bool AP_Baro_BMP581::init() 74 : { 75 0 : if (!_dev) { 76 0 : return false; 77 : } 78 : 79 0 : WITH_SEMAPHORE(_dev->get_semaphore()); 80 : 81 0 : _dev->set_speed(AP_HAL::Device::SPEED_HIGH); 82 : 83 : uint8_t whoami; 84 : 85 : // setup to allow reads on SPI 86 0 : if (_dev->bus_type() == AP_HAL::Device::BUS_TYPE_SPI) { 87 0 : _dev->set_read_flag(0x80); 88 : 89 0 : if (!_dev->read_registers(BMP581_REG_CHIP_ID, &whoami, 1)) { 90 0 : return false; 91 : } 92 : } 93 : 94 0 : if (!_dev->read_registers(BMP581_REG_CHIP_ID, &whoami, 1)) { 95 0 : return false; 96 : } 97 : 98 0 : switch (whoami) { 99 0 : case BMP581_ID: 100 0 : _dev->set_device_type(DEVTYPE_BARO_BMP581); 101 0 : break; 102 0 : default: 103 0 : return false; 104 : } 105 : 106 : uint8_t status; 107 0 : if (!_dev->read_registers(BMP581_REG_STATUS, &status, 1)) { 108 0 : return false; 109 : } 110 : 111 0 : if ((status & 0b10) == 0 || (status & 0b100)) { 112 0 : return false; 113 : } 114 : 115 : uint8_t int_status; 116 0 : if (!_dev->read_registers(BMP581_REG_INT_STATUS, &int_status, 1)) { 117 0 : return false; 118 : } 119 : 120 0 : if ((int_status & 0x10) == 0) { 121 0 : return false; 122 : } 123 : 124 0 : _dev->setup_checked_registers(4); 125 : 126 : // Standby mode 127 0 : _dev->write_register(BMP581_REG_ODR_CONFIG, 0, true); 128 : 129 : // Press EN | osr_p 64X | osr_t 4X 130 0 : _dev->write_register(BMP581_REG_OSR_CONFIG, 0b01110010, true); 131 : 132 : // ORD 50Hz | Normal Mode 133 0 : _dev->write_register(BMP581_REG_ODR_CONFIG, 0b0111101, true); 134 : 135 0 : instance = _frontend.register_sensor(); 136 : 137 0 : set_bus_id(instance, _dev->get_bus_id()); 138 : 139 : // request 50Hz update 140 0 : _dev->register_periodic_callback(20 * AP_USEC_PER_MSEC, FUNCTOR_BIND_MEMBER(&AP_Baro_BMP581::timer, void)); 141 : 142 0 : return true; 143 0 : } 144 : 145 : // acumulate a new sensor reading 146 0 : void AP_Baro_BMP581::timer(void) 147 : { 148 : uint8_t buf[6]; 149 : uint8_t buf2[6]; 150 : 151 : // read twice, make sure results are consistent; corruption has 152 : // been seen from data on this sensor 153 0 : if (!_dev->read_registers(BMP581_REG_TEMP_DATA_XLSB, buf, sizeof(buf))) { 154 0 : return; 155 : } 156 0 : if (!_dev->read_registers(BMP581_REG_TEMP_DATA_XLSB, buf2, sizeof(buf2))) { 157 0 : return; 158 : } 159 0 : if (memcmp(buf, buf2, ARRAY_SIZE(buf)) != 0) { 160 : // we didn't get the same data twice. Reject. 161 0 : return; 162 : } 163 : 164 0 : WITH_SEMAPHORE(_sem); 165 : 166 0 : if (buf[0] != 0x7f || buf[1] != 0x7f || buf[2] != 0x7f) { 167 : // we have temperature data 168 0 : temperature = (float)((int32_t)(((uint32_t)buf[2] << 24) | ((uint32_t)buf[1] << 16) | ((uint32_t)buf[0] << 8)) >> 8) * (1.0f / 65536.0f); 169 : } 170 : 171 0 : if (buf[3] != 0x7f || buf[4] != 0x7f || buf[5] != 0x7f) { 172 : // we have pressure data 173 0 : pressure_sum += (float)(((uint32_t)buf[5] << 16) | ((uint32_t)buf[4] << 8) | (uint32_t)buf[3]) * (1.0f / 64.0f); 174 0 : pressure_count++; 175 : } 176 : 177 0 : _dev->check_next_register(); 178 0 : } 179 : 180 : // transfer data to the frontend 181 0 : void AP_Baro_BMP581::update(void) 182 : { 183 0 : WITH_SEMAPHORE(_sem); 184 : 185 0 : if (pressure_count == 0) { 186 0 : return; 187 : } 188 : 189 0 : _copy_to_frontend(instance, 190 0 : pressure_sum/pressure_count, 191 : temperature); 192 : 193 0 : pressure_sum = 0; 194 0 : pressure_count = 0; 195 0 : } 196 : 197 : #endif // AP_BARO_BMP581_ENABLED