diff --git a/conf/firmwares/rotorcraft.makefile b/conf/firmwares/rotorcraft.makefile index 5694950be0..d3b184c04c 100644 --- a/conf/firmwares/rotorcraft.makefile +++ b/conf/firmwares/rotorcraft.makefile @@ -147,17 +147,18 @@ ap.srcs += $(SRC_BOARD)/baro_board.c # Lisa/M and Lia baro else ifeq ($(BOARD), lisa_m) -# defaults to i2c baro -LISA_M_BARO ?= BARO_I2C - ifeq ($(LISA_M_BARO), BARO_SPI) +# defaults to i2c baro bmp085 on the board +LISA_M_BARO ?= BARO_BOARD_BMP085 + ifeq ($(LISA_M_BARO), BARO_MS5611_SPI) include $(CFG_SHARED)/spi.makefile ap.CFLAGS += -DUSE_SPI2 -DUSE_SPI_SLAVE3 - ap.srcs += $(SRC_BOARD)/baro_board_spi.c - else ifeq ($(LISA_M_BARO), BARO_I2C) + ap.srcs += $(SRC_BOARD)/baro_ms5611_spi.c + else ifeq ($(LISA_M_BARO), BARO_MS5611_I2C) ap.CFLAGS += -DUSE_I2C2 - ap.srcs += $(SRC_BOARD)/baro_board_i2c.c - else ifeq ($(LISA_M_BARO), BARO_ASPIRIN) + ap.srcs += $(SRC_BOARD)/baro_ms5611_i2c.c + else ifeq ($(LISA_M_BARO), BARO_BOARD_BMP085) ap.srcs += $(SRC_BOARD)/baro_board.c + ap.CFLAGS += -DUSE_I2C2 endif ap.CFLAGS += -D$(LISA_M_BARO) diff --git a/sw/airborne/boards/lisa_m/baro_board.c b/sw/airborne/boards/lisa_m/baro_board.c index 1ba5652ddb..ed67ad16d2 100644 --- a/sw/airborne/boards/lisa_m/baro_board.c +++ b/sw/airborne/boards/lisa_m/baro_board.c @@ -1,24 +1,195 @@ -/** - * Generic barometer interface, assuming the barometer is read through Aspirin IMU directly - * - * Edit by: Michal Podhradsky, michal.podhradsky@aggiemail.usu.edu - * Utah State University, http://aggieair.usu.edu/ - */ #include "subsystems/sensors/baro.h" -#include "baro_board.h" +#include struct Baro baro; +struct BaroBoard baro_board; +struct i2c_transaction baro_trans; +struct bmp085_baro_calibration calibration; + +#define BMP085_SAMPLE_PERIOD_MS (3 + (2 << BMP085_OSS) * 3) +#define BMP085_SAMPLE_PERIOD (BMP075_SAMPLE_PERIOD_MS >> 1) + +// FIXME: BARO DRDY connected to PB0 for lisa/m + +static inline void bmp085_write_reg(uint8_t addr, uint8_t value) +{ + baro_trans.buf[0] = addr; + baro_trans.buf[1] = value; + + I2CTransmit(i2c2, baro_trans, BMP085_ADDR, 2); + + // FIXME, no while loops without timeout!! + while (baro_trans.status == I2CTransPending || baro_trans.status == I2CTransRunning); +} + +static inline void bmp085_read_reg16(uint8_t addr) +{ + baro_trans.buf[0] = addr; + I2CTransceive(i2c2, baro_trans, BMP085_ADDR, 1, 2); +} + +static inline int16_t bmp085_read_reg16_blocking(uint8_t addr, uint32_t timeout) +{ + uint32_t time = 0; + + bmp085_read_reg16(addr); + + while (baro_trans.status == I2CTransPending || baro_trans.status == I2CTransRunning) { + if ((time == timeout) && (timeout != 0)) { + return 0; /* Timeout of the i2c read */ + } else { + time++; + } + } + + return ((baro_trans.buf[0] << 8) | baro_trans.buf[1]); +} + +static inline void bmp085_read_reg24(uint8_t addr) +{ + baro_trans.buf[0] = addr; + I2CTransceive(i2c2, baro_trans, BMP085_ADDR, 1, 3); +} + +static void bmp085_baro_read_calibration(void) +{ + calibration.ac1 = bmp085_read_reg16_blocking(0xAA, 10000); // AC1 + calibration.ac2 = bmp085_read_reg16_blocking(0xAC, 10000); // AC2 + calibration.ac3 = bmp085_read_reg16_blocking(0xAE, 10000); // AC3 + calibration.ac4 = bmp085_read_reg16_blocking(0xB0, 10000); // AC4 + calibration.ac5 = bmp085_read_reg16_blocking(0xB2, 10000); // AC5 + calibration.ac6 = bmp085_read_reg16_blocking(0xB4, 10000); // AC6 + calibration.b1 = bmp085_read_reg16_blocking(0xB6, 10000); // B1 + calibration.b2 = bmp085_read_reg16_blocking(0xB8, 10000); // B2 + calibration.mb = bmp085_read_reg16_blocking(0xBA, 10000); // MB + calibration.mc = bmp085_read_reg16_blocking(0xBC, 10000); // MC + calibration.md = bmp085_read_reg16_blocking(0xBE, 10000); // MD +} void baro_init(void) { baro.status = BS_UNINITIALIZED; baro.absolute = 0; baro.differential = 0; + baro_board.status = LBS_UNINITIALIZED; + bmp085_baro_read_calibration(); + + /* STM32 specific (maybe this is a LISA/M specific driver anyway?) */ + gpio_clear(GPIOB, GPIO0); + gpio_set_mode(GPIOB, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0); } -void baro_periodic(void) {} - -void baro_event(void (*b_abs_handler)(void), void (*b_diff_handler)(void)){ - b_abs_handler(); - b_diff_handler(); +static inline int baro_eoc(void) +{ + return gpio_get(GPIOB, GPIO0); +} + +static inline void bmp085_request_pressure(void) +{ + bmp085_write_reg(0xF4, 0x34 + (BMP085_OSS << 6)); +} + +static inline void bmp085_request_temp(void) +{ + bmp085_write_reg(0xF4, 0x2E); +} + +static inline void bmp085_read_pressure(void) +{ + bmp085_read_reg24(0xF6); +} + +static inline void bmp085_read_temp(void) +{ + bmp085_read_reg16(0xF6); +} + +void baro_periodic(void) { + // check that nothing is in progress + if (baro_trans.status == I2CTransPending) return; + if (baro_trans.status == I2CTransRunning) return; + if (!i2c_idle(&i2c2)) return; + + switch (baro_board.status) { + case LBS_UNINITIALIZED: + baro_board_send_reset(); + baro_board.status = LBS_REQUEST; + baro.status = BS_RUNNING; + break; + case LBS_REQUEST: + bmp085_request_pressure(); + baro_board.status = LBS_READ; + break; + case LBS_READ: + if (baro_eoc()) { + bmp085_read_pressure(); + baro_board.status = LBS_READING; + } + break; + case LBS_REQUEST_TEMP: + bmp085_request_temp(); + baro_board.status = LBS_READ_TEMP; + break; + case LBS_READ_TEMP: + if (baro_eoc()) { + bmp085_read_temp(); + baro_board.status = LBS_READING_TEMP; + } + break; + default: + break; + } + +} + +void baro_board_send_reset(void) { + // This is a NOP at the moment +} + +// Apply temp calibration and sensor calibration to raw measurement to get Pa (from BMP085 datasheet) +int32_t baro_apply_calibration(int32_t raw) +{ + int32_t b6 = calibration.b5 - 4000; + int x1 = (calibration.b2 * (b6 * b6 >> 12)) >> 11; + int x2 = calibration.ac2 * b6 >> 11; + int32_t x3 = x1 + x2; + int32_t b3 = (((calibration.ac1 * 4 + x3) << BMP085_OSS) + 2)/4; + x1 = calibration.ac3 * b6 >> 13; + x2 = (calibration.b1 * (b6 * b6 >> 12)) >> 16; + x3 = ((x1 + x2) + 2) >> 2; + uint32_t b4 = (calibration.ac4 * (uint32_t) (x3 + 32768)) >> 15; + uint32_t b7 = (raw - b3) * (50000 >> BMP085_OSS); + int32_t p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2; + x1 = (p >> 8) * (p >> 8); + x1 = (x1 * 3038) >> 16; + x2 = (-7357 * p) >> 16; + return p + ((x1 + x2 + 3791) >> 4); +} + +void baro_event(void (*b_abs_handler)(void), void (*b_diff_handler)(void)) +{ + if (baro_board.status == LBS_READING && + baro_trans.status != I2CTransPending && baro_trans.status != I2CTransRunning) { + baro_board.status = LBS_REQUEST_TEMP; + if (baro_trans.status == I2CTransSuccess) { + int32_t tmp = (baro_trans.buf[0]<<16) | (baro_trans.buf[1] << 8) | baro_trans.buf[2]; + tmp = tmp >> (8 - BMP085_OSS); + baro.absolute = baro_apply_calibration(tmp); + b_abs_handler(); + } + } + if (baro_board.status == LBS_READING_TEMP && + baro_trans.status != I2CTransPending && baro_trans.status != I2CTransRunning) { + baro_board.status = LBS_REQUEST; + if (baro_trans.status == I2CTransSuccess) { + // abuse differential to store temp in 0.1C for now + int32_t tmp = (baro_trans.buf[0] << 8) | baro_trans.buf[1]; + int32_t x1 = ((tmp - calibration.ac6) * calibration.ac5) >> 15; + int32_t x2 = (calibration.mc << 11) / (x1 + calibration.md); + calibration.b5 = x1 + x2; + baro.differential = (calibration.b5 + 8) >> 4; + b_diff_handler(); + } + } } diff --git a/sw/airborne/boards/lisa_m/baro_board.h b/sw/airborne/boards/lisa_m/baro_board.h index 4498eef51b..8f0ffb5fc3 100644 --- a/sw/airborne/boards/lisa_m/baro_board.h +++ b/sw/airborne/boards/lisa_m/baro_board.h @@ -1,15 +1,67 @@ -/** - * Generic barometer interface, assuming the barometer is read through Aspirin IMU directly + +/* + * board specific fonctions for the lisa_m board * - * Edit by: Michal Podhradsky, michal.podhradsky@aggiemail.usu.edu - * Utah State University, http://aggieair.usu.edu/ */ -#ifndef BOARDS_LIA_BARO_H -#define BOARDS_LIA_BARO_H +#ifndef BOARDS_LISA_M_BARO_H +#define BOARDS_LISA_M_BARO_H + +#include "std.h" + +// for right now we abuse this file for the ms5611 baro on aspirin as well +#if !BARO_MS5611_I2C && !BARO_MS5611 + +#include "mcu_periph/i2c.h" + +// absolute addr +#define BMP085_ADDR 0xEE +// Over sample setting (0-3) +#define BMP085_OSS 3 + +enum LisaBaroStatus { + LBS_UNINITIALIZED, + LBS_REQUEST, + LBS_READING, + LBS_READ, + LBS_REQUEST_TEMP, + LBS_READING_TEMP, + LBS_READ_TEMP, +}; + +struct BaroBoard { + enum LisaBaroStatus status; +}; + +struct bmp085_baro_calibration { + // These values come from EEPROM on sensor + int16_t ac1; + int16_t ac2; + int16_t ac3; + uint16_t ac4; + uint16_t ac5; + uint16_t ac6; + int16_t b1; + int16_t b2; + int16_t mb; + int16_t mc; + int16_t md; + + // These values are calculated + int32_t b5; +}; + +extern struct BaroBoard baro_board; +extern struct i2c_transaction baro_trans; +extern struct bmp085_baro_calibration calibration; + +extern void baro_board_send_reset(void); +extern void baro_board_send_config(void); + +#endif // !BARO_MS5611_xx extern void baro_event(void (*b_abs_handler)(void), void (*b_diff_handler)(void)); #define BaroEvent(_b_abs_handler, _b_diff_handler) baro_event(_b_abs_handler,_b_diff_handler) -#endif /* BOARDS_LIA_BARO_H */ +#endif /* BOARDS_LISA_M_BARO_H */ diff --git a/sw/airborne/boards/lisa_m/baro_board_i2c.c b/sw/airborne/boards/lisa_m/baro_ms5611_i2c.c similarity index 99% rename from sw/airborne/boards/lisa_m/baro_board_i2c.c rename to sw/airborne/boards/lisa_m/baro_ms5611_i2c.c index 30550e167b..6200fda7bc 100644 --- a/sw/airborne/boards/lisa_m/baro_board_i2c.c +++ b/sw/airborne/boards/lisa_m/baro_ms5611_i2c.c @@ -190,7 +190,7 @@ void baro_event(void (*b_abs_handler)(void), void (*b_diff_handler)(void)){ b_abs_handler(); b_diff_handler(); - #ifdef EBUG + #ifdef DEBUG ftempms = tempms / 100.; fbaroms = baroms / 100.; DOWNLINK_SEND_BARO_MS5611(DefaultChannel, DefaultDevice, diff --git a/sw/airborne/boards/lisa_m/baro_board_spi.c b/sw/airborne/boards/lisa_m/baro_ms5611_spi.c similarity index 100% rename from sw/airborne/boards/lisa_m/baro_board_spi.c rename to sw/airborne/boards/lisa_m/baro_ms5611_spi.c