From e4bdd6d759d0bc5e9d30db302fb7e7a6a45e03d3 Mon Sep 17 00:00:00 2001 From: Theodore Ateba Date: Fri, 22 Sep 2017 20:49:12 +0000 Subject: Add Bosch digital barometer driver to ChibiOS/EX. git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@10684 35acf78f-673a-0410-8e92-d51de3d6d3f4 --- os/ex/Bosch/bmp085.c | 815 ++++++++++++++++++++++++++++++++++++++++++++++++++ os/ex/Bosch/bmp085.h | 400 +++++++++++++++++++++++++ os/ex/Bosch/bmp085.mk | 6 + 3 files changed, 1221 insertions(+) create mode 100644 os/ex/Bosch/bmp085.c create mode 100644 os/ex/Bosch/bmp085.h create mode 100644 os/ex/Bosch/bmp085.mk diff --git a/os/ex/Bosch/bmp085.c b/os/ex/Bosch/bmp085.c new file mode 100644 index 000000000..82676dc4c --- /dev/null +++ b/os/ex/Bosch/bmp085.c @@ -0,0 +1,815 @@ +/* + ChibiOS - Copyright (C) 2016..2017 Theodore Ateba + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +/** + * @file bmp085.c + * + * @brief BMP085 Digital pressure sensor interface module code. + * + * @author Theodore Ateba, tf.ateba@gmail.com + * + * @date 19 July 2016 + * + * TODO: Read the altitude with the sensor. + * + * @{ + */ + +/*==========================================================================*/ +/* Include files. */ +/*==========================================================================*/ + +/* ChibiOS HAL file. */ +#include "hal.h" + +/* ChibiOS EX file. */ +#include "bmp085.h" + +/*==========================================================================*/ +/* Driver local definitions. */ +/*==========================================================================*/ + +/*==========================================================================*/ +/* Driver exported variables. */ +/*==========================================================================*/ + +/*==========================================================================*/ +/* Driver local variables and types. */ +/*==========================================================================*/ + +/** + * @brief Variables for Temperature and Pressure measurement. + */ +static int16_t ac1; +static int16_t ac2; +static int16_t ac3; +static int16_t b1; +static int16_t b2; +static int16_t mb; +static int16_t mc; +static int16_t md; +static uint16_t ac4; +static uint16_t ac5; +static uint16_t ac6; +static int32_t b5; + +/*==========================================================================*/ +/* Driver local functions. */ +/*==========================================================================*/ + +#if (BMP085_USE_I2C) || defined(__DOXYGEN__) +/** + * @brief Reads registers value using I2C. + * @pre The I2C interface must be initialized and the driver started. + * + * @param[in] i2cp pointer to the I2C interface + * @param[in] reg first sub-register address + * @param[out] rxbufp pointer to an output buffer + * @param[in] n number of consecutive register to read + * + * @return the operation status + * @notapi + */ +msg_t bmp085I2CReadRegister(I2CDriver *i2cp, uint8_t reg, uint8_t *rxbufp, + size_t n) { + uint8_t txbuf = reg; + + return i2cMasterTransmitTimeout(i2cp, BMP085_SAD, &txbuf, 1, rxbufp, n, + TIME_INFINITE); +} + +/** + * @brief Writes a value into a register using I2C. + * @pre The I2C interface must be initialized and the driver started. + * + * @param[in] i2cp pointer to the I2C interface + * @param[in] txbufp buffer containing sub-address value in first position + * and values to write + * @param[in] n size of txbuf less one (not considering the first + * element) + * + * @return the operation status + * @notapi + */ +msg_t bmp085I2CWriteRegister(I2CDriver *i2cp, uint8_t *txbufp, size_t n) { + + return i2cMasterTransmitTimeout(i2cp, BMP085_SAD, txbufp, n + 1, NULL, 0, + TIME_INFINITE); +} +#endif /* BMP085_USE_I2C */ + +/** + * @brief Read all the calibration data from the BMP085 EEPROM. + * @pre The I2C interface must be initialized and the driver started. + * + * @param[in] devp pointer to the BMP085 device driver sensor + * @param[in] reg first calibration coefficient register to read + * + * @return msg the operation status + */ +static msg_t bmp085ReadCoefficient(BMP085Driver *devp, uint8_t reg) { + + uint8_t rxbuf[22]; + +#if BMP085_SHARED_I2C + i2cAcquireBus(devp->config->i2cp); +#endif /* BMP085_SHARED_I2C */ + + msg_t msg = bmp085I2CReadRegister(devp->config->i2cp, reg, rxbuf, 22); + +#if BMP085_SHARED_I2C + i2cReleaseBus(devp->config->i2cp); +#endif /* BMP085_SHARED_I2C */ + + if (msg == MSG_OK) { + ac1 = ((rxbuf[ 0] << 8) | rxbuf[ 1]); + ac2 = ((rxbuf[ 2] << 8) | rxbuf[ 3]); + ac3 = ((rxbuf[ 4] << 8) | rxbuf[ 5]); + ac4 = ((rxbuf[ 6] << 8) | rxbuf[ 7]); + ac5 = ((rxbuf[ 8] << 8) | rxbuf[ 9]); + ac6 = ((rxbuf[10] << 8) | rxbuf[11]); + b1 = ((rxbuf[12] << 8) | rxbuf[13]); + b2 = ((rxbuf[14] << 8) | rxbuf[15]); + mb = ((rxbuf[16] << 8) | rxbuf[17]); + mc = ((rxbuf[18] << 8) | rxbuf[19]); + md = ((rxbuf[20] << 8) | rxbuf[21]); + } + + return msg; +} + +/** + * @brief Calcul the true temperature. + * + * @param[in] ut uncompensated temperature + * @param[out] ctp pointer of the compensated temperature + */ +static void calcul_t(int32_t ut, float *ctp) { + + int32_t x1, x2; + + /* Converting the temperature value. */ + x1 = ((ut - ac6) * ac5) >> 15; + x2 = (mc << 11) / (x1 + md); + b5 = x1 + x2; + *ctp = (float)((b5 + 8) >> 4)*BMP085_T_RES; +} + +/** + * @brief Calcul the true pressure. + * + * @param[in] up uncompensated pressure + * @param[out] cpp pointer of the compensated pressure + */ +static void calcul_p(int32_t up, uint8_t oss, float *cpp) { + + int32_t press; + int32_t x1,x2,x3; + int32_t b3,b6; + uint32_t b4,b7; + + /* Converting the pressure value. */ + b6 = b5 - 4000; + x1 = (b2 * ((b6 * b6) >> 12)) >> 11; + x2 = (ac2 * b6) >> 11; + x3 = x1 + x2; + b3 = ((((int32_t)ac1 * 4 + x3) << oss) + 2) >> 2; + x1 = ((ac3)*b6) >> 13; + x2 = (b1 * (b6*b6 >> 12)) >> 16; + x3 = ((x1 + x2) + 2) >> 2; + b4 = ac4 * (uint32_t)(x3 + 32768) >> 15; + b7 = ((uint32_t)up - b3)*(50000 >> oss); + + if (b7 < 0x80000000) + press = (b7*2)/b4; + else + press = (b7/b4)*2; + + x1 = (press >> 8)*(press >> 8); + x1 = (x1*3038) >> 16; + x2 = (-7357*press) >> 16; + *cpp =(float)((press + ((x1 + x2 + 3791) >> 4))*BMP085_P_RES); +} + +/** + * @brief Start temperature measurement. + * + * @param[in] devp pointer to the BMP085 device driver + * + * @return the operation status + */ +static msg_t start_t_measurement(BMP085Driver *devp) { + + uint8_t txbuf[2] = {BMP085_AD_CR, BMP085_CR_T_VAL}; + + if ((devp)->config->thermocfg != NULL) { + i2cAcquireBus(devp->config->i2cp); + msg_t msg = bmp085I2CWriteRegister(devp->config->i2cp, txbuf, 2); + i2cReleaseBus(devp->config->i2cp); + + /* Conversion time for the temperature. */ + chThdSleepMilliseconds(BMP085_THERMO_CT_LOW); + + return msg; + } + else + return MSG_RESET; +} + +/** + * @brief Start the pressure measurment. + * + * @param[in] devp pointer to the BMP085 driver + * @return msg the operation status + */ +static msg_t start_p_measurement(BMP085Driver *devp) { + + uint8_t oss, delay; + uint8_t txbuf[2]; + + oss = devp->config->barocfg->oss; + txbuf[0] = BMP085_AD_CR; + + /* Check the oss according the bmp085 mode. */ + if (oss == BMP085_BARO_OSS_0) { + txbuf[1] = BMP085_CR_P_VAL0 + (oss << 6); + delay = BMP085_BARO_CT_LOW; + } + else if (oss == BMP085_BARO_OSS_1) { + txbuf[1] = BMP085_CR_P_VAL1 + (oss << 6); + delay = BMP085_BARO_CT_STD; + } + else if (oss == BMP085_BARO_OSS_2) { + txbuf[1] = BMP085_CR_P_VAL2 + (oss << 6); + delay = BMP085_BARO_CT_HR; + } + else { + txbuf[1] = BMP085_CR_P_VAL3 + (oss << 6); + delay = BMP085_BARO_CT_LUHR; + } + + /* Start the sensor for sampling. */ +#if BMP085_SHARED_I2C + i2cAcquireBus(devp->config->i2cp); +#endif /* BMP085_SHARED_I2C */ + + msg_t msg = bmp085I2CWriteRegister(devp->config->i2cp, txbuf, 2); + +#if BMP085_SHARED_I2C + i2cReleaseBus(devp->config->i2cp); +#endif /* BMP085_SHARED_I2C */ + + /* Conversion time for the pressure, max time for the moment. */ + chThdSleepMilliseconds(delay); + + return msg; +} + +/** + * @brief Read the uncompensated temperature from the BMP085 register. + * + * @param[in] devp pointer to the BMP085 driver + * @param[out] utemp uncompensated temperature read from the sensor register + * + * @return msg the operation status + */ +msg_t acquire_ut(BMP085Driver *devp, int32_t *utemp) { + + uint8_t rxbuf[2]; + msg_t msg; + + /* Start the temperature measurement. */ + start_t_measurement(devp); + + /* Start the sensor for sampling. */ +#if BMP085_SHARED_I2C + i2cAcquireBus(devp->config->i2cp); +#endif /* BMP085_SHARED_I2C */ + + /* Get the temperature. */ + msg = bmp085I2CReadRegister(devp->config->i2cp, BMP085_AD_T_DR_MSB, rxbuf, + 2); + +#if BMP085_SHARED_I2C + i2cReleaseBus(devp->config->i2cp); +#endif /* BMP085_SHARED_I2C */ + + if(msg == MSG_OK){ + /* Building the uncompensated temperature value. */ + *utemp = (int32_t)((rxbuf[0] << 8) | rxbuf[1]); + } + + return msg; +} + +/** + * @brief Read the uncompensated pressure from the BMP085 register. + * + * @param[in] devp pointer to the BMP085 driver + * @param[out] upress uncompensated pressure read from the sensor register + * + * @return msg the operation status + */ +msg_t acquire_up(BMP085Driver *devp, int32_t *upress) { + + uint8_t rxbuf[3]; + uint8_t oss; + msg_t msg; + + /* Get the oversampling setting from the driver configuratioin. */ + oss = devp->config->barocfg->oss; + + /* Start the pressure measurement. */ + start_p_measurement(devp); + + /* Start the sensor for sampling. */ +#if BMP085_SHARED_I2C + i2cAcquireBus(devp->config->i2cp); +#endif /* BMP085_SHARED_I2C */ + + /* Get the pressure */ + msg = bmp085I2CReadRegister(devp->config->i2cp, BMP085_AD_P_DR_MSB, rxbuf, + 3); + +#if BMP085_SHARED_I2C + i2cReleaseBus(devp->config->i2cp); +#endif /* BMP085_SHARED_I2C */ + + if (msg == MSG_OK) { + /* Building the uncompensated pressure value. */ + *upress = (int32_t)((rxbuf[0] << 16)|(rxbuf[1] << 8)|rxbuf[2]); + *upress = *upress >> (8-oss); + } + + return msg; +} + +/*==========================================================================*/ +/* Interface implementation. */ +/*==========================================================================*/ + +/** + * @brief Get the barometer number of axes. + * + * @param[in] ip interface pointer of the BMP085 sensor + * + * @return barometer number of axes + */ +static size_t baro_get_axes_number(void *ip) { + + osalDbgCheck(ip != NULL); + + return BMP085_BARO_NUMBER_OF_AXES; +} + +/** + * @brief Get the thermometer number of axes. + * + * @param[in] ip interface pointer of the BMP085 sensor + * + * @return thermometer number of axes + */ +static size_t thermo_get_axes_number(void *ip) { + + osalDbgCheck(ip != NULL); + + return BMP085_THERMO_NUMBER_OF_AXES; +} + +/** + * @brief Get the sensor number of axes. + * + * @param[in] ip interface pointer of the BMP085 sensor + * + * @return sensor number of axes + */ +static size_t sens_get_axes_number(void *ip) { + + osalDbgCheck(ip != NULL); + + return (baro_get_axes_number(ip) + thermo_get_axes_number(ip)); +} + +/** + * @brief Read baromether raw data. + * + * @param[in] ip interface pointer of the sensor + * @param[in] axes buffer for various axes data + * + * @return msg the result of the reading operation + */ +static msg_t baro_read_raw(void *ip, int32_t axes[]) { + + osalDbgCheck((ip != NULL) && (axes != NULL)); + osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY), + "baro_read_raw(), invalid state"); + +#if BMP085_USE_I2C + osalDbgAssert((((BMP085Driver *)ip)->config->i2cp->state == I2C_READY), + "baro_read_raw(), channel not ready"); +#if BMP085_SHARED_I2C + i2cAcquireBus(((BMP085Driver *)ip)->config->i2cp); + i2cStart(((BMP085Driver *)ip)->config->i2cp, + ((BMP085Driver *)ip)->config->i2ccfg); +#endif /* BMP085_SHARED_I2C. */ + + /* Measure the uncompensated pressure. */ + msg_t msg = acquire_up(((BMP085Driver *)ip), axes); + +#if BMP085_SHARED_I2C + i2cReleaseBus(((BMP085Driver *)ip)->config->i2cp); +#endif /* BMP085_SHARED_I2C. */ +#endif /* BMP085_USE_I2C. */ + + return msg; +} + +/** + * @brief Read thermometer raw data. + * + * @param[in] ip interface pointer of the BMP085 sensor + * @param[in] axes buffer for various axes data + * + * @return msg the result of the reading operation + */ +static msg_t thermo_read_raw(void *ip, int32_t axes[]) { + + osalDbgCheck((ip != NULL) && (axes != NULL)); + osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY), + "thermo_read_raw(), invalid state"); + +#if BMP085_USE_I2C + osalDbgAssert((((BMP085Driver *)ip)->config->i2cp->state == I2C_READY), + "thermo_read_raw(), channel not ready"); +#if BMP085_SHARED_I2C + i2cAcquireBus(((BMP085Driver *)ip)->config->i2cp); + i2cStart(((BMP085Driver *)ip)->config->i2cp, + ((BMP085Driver *)ip)->config->i2ccfg); +#endif /* BMP085_SHARED_I2C. */ + + /* Measure the uncompensated temperature. */ + msg_t msg = acquire_ut(((BMP085Driver *)ip), axes); + +#if BMP085_SHARED_I2C + i2cReleaseBus(((LSM303DLHCDriver *)ip)->config->i2cp); +#endif /* BMP085_SHARED_I2C. */ +#endif /* BMP085_USE_I2C. */ + + return msg; +} + +/** + * @brief Read BMP085 sensor raw data. + * + * @param[in] ip interface pointer of the BMP085 sensor + * @param[in] axes buffer for various axes data + * + * @return msg the result of the reading operation + */ +static msg_t sens_read_raw(void *ip, int32_t axes[]) { + + int32_t* bp = axes; + msg_t msg; + + if (((BMP085Driver *)ip)->config->barocfg != NULL) { + msg = baro_read_raw(ip, bp); + + if (msg != MSG_OK) + return msg; + + bp += BMP085_BARO_NUMBER_OF_AXES; + } + + if (((BMP085Driver *)ip)->config->thermocfg != NULL) { + msg = thermo_read_raw(ip, bp); + } + + return msg; +} + +/** + * @brief Read barometer cooked data. + * + * @param[in] ip interface pointer of the BMP085 sensor + * @param[in] axes buffer for various axes data + * + * @return msg the result of the reading operation + */ +static msg_t baro_read_cooked(void *ip, float axes[]) { + + uint32_t i; + int32_t raw[BMP085_BARO_NUMBER_OF_AXES]; + msg_t msg; + uint8_t oss; + + osalDbgCheck((ip != NULL) && (axes != NULL)); + osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY), + "baro_read_cooked(), invalid state"); + + msg = baro_read_raw(ip, raw); + oss = ((BMP085Driver *)ip)->config->barocfg->oss; + + for (i = 0; i < BMP085_BARO_NUMBER_OF_AXES; i++) + calcul_p(raw[i], oss, &axes[i]); + + return msg; +} + +/** + * @brief Read thermometer cooked data. + * + * @param[in] ip interface pointer of the BMP085 sensor + * @param[in] axes buffer for various axes data + * + * @return msg the result of the reading operation + */ +static msg_t thermo_read_cooked(void *ip, float axes[]) { + + uint32_t i; + int32_t raw[BMP085_THERMO_NUMBER_OF_AXES]; + msg_t msg; + + osalDbgCheck(((ip != NULL) && (axes != NULL))); + osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY), + "thermo_read_cooked(), invalid state"); + msg = thermo_read_raw(ip, raw); + + for (i = 0; i < BMP085_THERMO_NUMBER_OF_AXES; i++) + calcul_t(raw[i], &axes[i]); + + return msg; +} + +/** + * @brief Read BMP085 sensor cooked data. + * + * @param[in] ip interface pointer of the BMP085 sensor + * @param[in] axes buffer for various axes data + * + * @return msg the result of the reading operation + */ +static msg_t sens_read_cooked(void *ip, float axes[]) { + + float* bp = axes; + msg_t msg; + + if (((BMP085Driver *)ip)->config->barocfg != NULL) { + msg = baro_read_cooked(ip, bp); + + if (msg != MSG_OK) + return msg; + + bp += BMP085_BARO_NUMBER_OF_AXES; + } + + if (((BMP085Driver *)ip)->config->thermocfg != NULL) + msg = thermo_read_cooked(ip, bp); + + return msg; +} + +/** + * @brief Set the barometer bias. + * + * @param[in] ip interface pointer of the BMP085 sensor + * @param[in] bp pointer to the bias value + * + * @return msg the result of the setting operation + */ +static msg_t baro_set_bias(void *ip, float *bp) { + + osalDbgCheck((ip != NULL) && (bp !=NULL)); + osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY) || + (((BMP085Driver *)ip)->state == BMP085_STOP), + "baro_set_bias(), invalid state"); + return MSG_OK; +} + +/** + * @brief Set the thermometer bias. + * + * @param[in] ip interface pointer of the BMP085 sensor + * @param[in] bp pointer to the bias value + * + * @return msg the result of the setting operation + */ +static msg_t thermo_set_bias(void *ip, float *bp) { + + osalDbgCheck((ip != NULL) && (bp !=NULL)); + osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY) || + (((BMP085Driver *)ip)->state == BMP085_STOP), + "thermo_set_bias(), invalid state"); + return MSG_OK; +} + +/** + * @brief Reset the barometer bias. + * + * @param[in] ip interface pointer of the BMP085 sensor + * + * @return msg the result of the reset operation + */ +static msg_t baro_reset_bias(void *ip) { + + osalDbgCheck(ip != NULL); + osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY) || + (((BMP085Driver *)ip)->state == BMP085_STOP), + "baro_reset_bias(), invalid state"); + + return MSG_OK; +} + +/** + * @brief Reset the thermometer bias. + * + * @param[in] ip interface pointer of the BMP085 sensor + * + * @return msg the result of the reset operation + */ +static msg_t thermo_reset_bias(void *ip) { + + osalDbgCheck(ip != NULL); + osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY) || + (((BMP085Driver *)ip)->state == BMP085_STOP), + "thermo_reset_bias(), invalid state"); + + return MSG_OK; +} + +/** + * @brief Set the barometer sensivity. + * + * @param[in] ip interface pointer of the BMP085 sensor + * @param[in] sp pointer to the sensivity value + * + * @return msg the result of the setting operation + */ +static msg_t baro_set_sensivity(void *ip, float *sp) { + + osalDbgCheck((ip != NULL) && (sp !=NULL)); + osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY), + "baro_set_sensivity(), invalid state"); + + return MSG_OK; +} + +/** + * @brief Set the thermometer sensivity. + * + * @param[in] ip interface pointer of the BMP085 sensor + * @param[in] sp pointer to the sensivity value + * + * @return msg the result of the setting operation + */ +static msg_t thermo_set_sensivity(void *ip, float *sp) { + + osalDbgCheck((ip != NULL) && (sp !=NULL)); + osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY), + "thermo_set_sensivity(), invalid state"); + + return MSG_OK; +} + +/** + * @brief Reset the barometer sensivity. + * + * @param[in] ip interface pointer of the BMP085 sensor + * + * @return msg the result of the reset operation + */ +static msg_t baro_reset_sensivity(void *ip) { + + osalDbgCheck(ip != NULL); + osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY), + "baro_reset_sensivity(), invalid state"); + + return MSG_OK; +} + +/** + * @brief Reset the thermometer sensivity. + * + * @param[in] ip interface pointer of the BMP085 sensor + * + * @return msg the result of the reset operation + */ +static msg_t thermo_reset_sensivity(void *ip) { + + osalDbgCheck(ip != NULL); + osalDbgAssert((((BMP085Driver *)ip)->state == BMP085_READY), + "thermo_reset_sensivity(), invalid state"); + + return MSG_OK; +} + +static const struct BaseSensorVMT vmt_basesensor = { + sens_get_axes_number, sens_read_raw, sens_read_cooked +}; + +static const struct BaseBarometerVMT vmt_basebarometer = { + baro_get_axes_number, baro_read_raw, baro_read_cooked, + baro_set_bias, baro_reset_bias, + baro_set_sensivity, baro_reset_sensivity +}; + +static const struct BaseThermometerVMT vmt_basethermometer = { + thermo_get_axes_number, thermo_read_raw, thermo_read_cooked, + thermo_set_bias, thermo_reset_bias, + thermo_set_sensivity, thermo_reset_sensivity +}; + +/*==========================================================================*/ +/* Driver exported functions. */ +/*==========================================================================*/ + +/** + * @brief Initializes an instance. + * + * @param[out] devp pointer to the @p BMP085Driver object + * + * @init + */ +void bmp085ObjectInit(BMP085Driver *devp) { + + devp->vmt_basesensor = &vmt_basesensor; + devp->vmt_basebarometer = &vmt_basebarometer; + devp->vmt_basethermometer = &vmt_basethermometer; + devp->config = NULL; + devp->state = BMP085_STOP; +} + +/** + * @brief Configures and activates BMP085 Complex Driver peripheral. + * + * @param[in] devp pointer to the @p BMP085Driver object + * @param[in] config pointer to the @p BMP085Config object + * + * @api + */ +void bmp085Start(BMP085Driver *devp, const BMP085Config *config) { + + osalDbgCheck((devp != NULL) && (config != NULL)); + osalDbgAssert((devp->state == BMP085_STOP) || + (devp->state == BMP085_READY), + "bmp085cStart(), invalid state"); + devp->config = config; +#if BMP085_USE_I2C +#if BMP085_SHARED_I2C + i2cAcquireBus((devp)->config->i2cp); +#endif /* BMP085_SHARED_I2C. */ + /* Read the Calibrations data. */ + i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg); + bmp085ReadCoefficient(devp, BMP085_AD_CC_AC1_MSB); +#if BMP085_SHARED_I2C + i2cReleaseBus((devp)->config->i2cp); +#endif /* BMP085_SHARED_I2C. */ +#endif /* BMP085_USE_I2C. */ + if(devp->state != BMP085_READY) + devp->state = BMP085_READY; +} + +/** + * @brief Deactivates the BMP085 Complex Driver peripheral. + * + * @param[in] devp pointer to the @p BMP085Driver object + * + * @api + */ +void bmp085Stop(BMP085Driver *devp) { + + osalDbgCheck(devp != NULL); + osalDbgAssert((devp->state == BMP085_STOP) || + (devp->state == BMP085_READY), + "bmp085Stop(), invalid state"); +#if (BMP085_USE_I2C) + if (devp->state == BMP085_STOP) { +#if BMP085_SHARED_I2C + i2cAcquireBus((devp)->config->i2cp); + i2cStart((devp)->config->i2cp, (devp)->config->i2ccfg); +#endif /* BMP085_SHARED_I2C. */ +#if BMP085_SHARED_I2C + i2cReleaseBus((devp)->config->i2cp); +#endif /* BMP085_SHARED_I2C. */ + } +#endif /* BMP085_USE_I2C. */ + if (devp->state != BMP085_STOP) + devp->state = BMP085_STOP; +} +/** @} */ diff --git a/os/ex/Bosch/bmp085.h b/os/ex/Bosch/bmp085.h new file mode 100644 index 000000000..9bfa5b99e --- /dev/null +++ b/os/ex/Bosch/bmp085.h @@ -0,0 +1,400 @@ +/* + ChibiOS - Copyright (C) 2016..2017 Theodore Ateba + + This file is part of ChibiOS. + + ChibiOS is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +/** + * @file bmp085.h + * + * @brief BMP085 Digital pressure sensor interface module header. + * + * @author Theodore Ateba, tf.ateba@gmail.com + * + * @date 19 July 2016 + * + * @{ + */ + +#ifndef BMP085_H +#define BMP085_H + +#include "hal_barometer.h" +#include "hal_thermometer.h" + +/*==========================================================================*/ +/* Driver constants. */ +/*==========================================================================*/ + +/** + * @name Version identification + * @{ + */ + +/** + * @brief BMP085 driver version string. + */ +#define EX_BMP085_VERSION "1.0.0" + +/** + * @brief BMP085 driver version major number. + */ +#define EX_BMP085_MAJOR 1 + +/** + * @brief BMP085 driver version minor number. + */ +#define EX_BMP085_MINOR 0 + +/** + * @brief BMP085 driver version patch number. + */ +#define EX_BMP085_PATCH 0 +/** @}*/ + +/** + * @brief BMP085 barometer subsystem characteristics. + * @{ + */ +#define BMP085_BARO_NUMBER_OF_AXES 1U /**< Number of axes. */ + +#define BMP085_P_RES 0.01 /**< Press resolution. */ + +#define BMP085_CR_P_VAL0 0x34 /**< Press control reg value 0. */ +#define BMP085_CR_P_VAL1 0x74 /**< Press control reg value 1. */ +#define BMP085_CR_P_VAL2 0xB4 /**< Press control reg value 2. */ +#define BMP085_CR_P_VAL3 0xF4 /**< Press control reg value 3. */ +/** @} */ + +/** + * @brief BMP085 thermometer subsystem characteristics. + * @{ + */ +#define BMP085_THERMO_NUMBER_OF_AXES 1U /**< Number of axis. */ + +#define BMP085_T_RES 0.1 /**< Temp resolution. */ + +#define BMP085_CR_T_VAL 0x2E /**< Temp control register value. */ +/** @} */ + +#define BMP085_SAD 0x77 /**< Slave address. */ + +/** + * @name BMP085 Registers addresses. + * @{ + */ +#define BMP085_AD_CR 0xF4 /**< Control register address. */ +#define BMP085_AD_T_DR_MSB 0xF6 /**< Temp MSB data register addr. */ +#define BMP085_AD_T_DR_LSB 0xF7 /**< Temp LSB data register addr. */ +#define BMP085_AD_P_DR_MSB 0xF6 /**< Press MSB data register addr. */ +#define BMP085_AD_P_DR_LSB 0xF7 /**< Press LSB data register addr. */ +#define BMP085_AD_P_DR_XLSB 0xF8 /**< Press XLSB data register addr.*/ +#define BMP085_AD_CC_AC1_MSB 0xAA /**< AC1 MSB calib coef reg addr. */ +#define BMP085_AD_CC_AC1_LSB 0xAB /**< AC1 LSB calib coef reg addr. */ +#define BMP085_AD_CC_AC2_MSB 0xAC /**< AC2 MSB calib coef reg addr. */ +#define BMP085_AD_CC_AC2_LSB 0xAD /**< AC2 LSB calib coef reg addr. */ +#define BMP085_AD_CC_AC3_MSB 0xAE /**< AC3 MSB calib coef reg addr. */ +#define BMP085_AD_CC_AC3_LSB 0xAF /**< AC3 LSB calib coef reg addr. */ +#define BMP085_AD_CC_AC4_MSB 0xB0 /**< AC4 MSB calib coef reg addr. */ +#define BMP085_AD_CC_AC4_LSB 0xB1 /**< AC4 LSB calib coef reg addr. */ +#define BMP085_AD_CC_AC5_MSB 0xB2 /**< AC5 MSB calib coef reg addr. */ +#define BMP085_AD_CC_AC5_LSB 0xB3 /**< AC5 LSB calib coef reg addr. */ +#define BMP085_AD_CC_AC6_MSB 0xB4 /**< AC6 MSB calib coef reg addr. */ +#define BMP085_AD_CC_AC6_LSB 0xB5 /**< AC6 LSB calib coef reg addr. */ +#define BMP085_AD_CC_B1_MSB 0xB6 /**< B1 MSB calib coef reg addr. */ +#define BMP085_AD_CC_B1_LSB 0xB7 /**< B1 LSB calib coef reg addr. */ +#define BMP085_AD_CC_B2_MSB 0xB8 /**< B2 MSB calib coef reg addr. */ +#define BMP085_AD_CC_B2_LSB 0xB9 /**< B2 LSB calib coef reg addr. */ +#define BMP085_AD_CC_MB_MSB 0xBA /**< MB MSB calib coef reg addr. */ +#define BMP085_AD_CC_MB_LSB 0xBB /**< MB LSB calib coef reg addr. */ +#define BMP085_AD_CC_MC_MSB 0xBC /**< MC MSB calib coef reg addr. */ +#define BMP085_AD_CC_MC_LSB 0xBD /**< MC LSB calib coef reg addr. */ +#define BMP085_AD_CC_MD_MSB 0xBE /**< MD MSB calib coef reg addr. */ +#define BMP085_AD_CC_MD_LSB 0xBF /**< MD LSB calib coef reg addr. */ +/** @} */ + +/*==========================================================================*/ +/* Driver pre-compile time settings. */ +/*==========================================================================*/ + +/** + * @name Configuration options + * @{ + */ + +/** + * @brief BMP085 I2C interface selector. + * @details If set to @p TRUE the support for I2C is included. + * @note The default is @p TRUE. + */ +#if !defined(BMP085_USE_I2C) || defined(__DOXYGEN__) +#define BMP085_USE_I2C TRUE +#endif + +/** + * @brief BMP085 barometer subsystem advanced configurations switch. + * @details If set to @p TRUE more configurations are available. + * @note The default is @p FALSE. + */ +#if !defined(BMP085_BARO_USE_ADVANCED) || defined(__DOXYGEN__) +#define BMP085_BARO_USE_AVANCED FALSE +#endif + +/** + * @brief BMP085 termomether subsystem advanced configurations switch. + * @details If set to @p TRUE more configurations are available. + * @note The default is @p FALSE. + */ +#if !defined(BMP085_THERMO_USE_ADVANCED) || defined(__DOXYGEN__) +#define BMP085_THERMO_USE_AVANCED FALSE +#endif + +/** + * @brief BMP085 shared I2C switch. + * @details If set to @p TRUE the device acquires I2C bus ownership + * on each transaction. + * @note The default is @p FALSE. Requires I2C_USE_MUTUAL_EXCLUSION. + */ +#if !defined(BMP085_SHARED_I2C) || defined(__DOXYGEN__) +#define BMP085_SHARED_I2C FALSE +#endif +/** @} */ + +/*==========================================================================*/ +/* Derived constants and error checks. */ +/*==========================================================================*/ + +#if !HAL_USE_I2C +#error "BMP085_USE_I2C requires HAL_USE_I2C" +#endif + +#if BMP085_SHARED_I2C && !I2C_USE_MUTUAL_EXCLUSION +#error "BMP085_SHARED_I2C requires I2C_USE_MUTUAL_EXCLUSION" +#endif + +/*==========================================================================*/ +/* Driver data structures and types. */ +/*==========================================================================*/ + +/** + * @name BMP085 barometer subsystem data structures and types. + * @{ + */ + +/** + * @brief BMP085 barometer subsystem pressure conversion time. + */ +typedef enum { + BMP085_BARO_CT_LOW = 0x05, /**< Convers time in ultra low power mode. */ + BMP085_BARO_CT_STD = 0x18, /**< Convers time in standard mode. */ + BMP085_BARO_CT_HR = 0x0E, /**< Convers time in high resolution mode. */ + BMP085_BARO_CT_LUHR = 0x1A /**< Convers time in ultra high res. mode. */ +} bmp085_baro_ct_t; + +/** + * @brief BMP085 barometer subsystem mode. + */ +typedef enum { + BMP085_BARO_MODE_LOW = 0x00, /**< BMP085 ultra low power mode. */ + BMP085_BARO_MODE_STD = 0x01, /**< BMP085 standard mode. */ + BMP085_BARO_MODE_HR = 0x02, /**< BMP085 high resolution mode. */ + BMP085_BARO_MODE_LUHR = 0x03 /**< BMP085 ultra high res. mode. */ +} bmp085_baro_mode_t; + +/** + * @brief BMP085 barometer oversampling setting. + */ +typedef enum { + BMP085_BARO_OSS_0 = 0x00, /**< Ultra low power sampling rate. */ + BMP085_BARO_OSS_1 = 0x01, /**< Standard mode sampling rate. */ + BMP085_BARO_OSS_2 = 0x02, /**< High resolution sampling rate. */ + BMP085_BARO_OSS_3 = 0x04 /**< ultra high resolution sampling rate. */ +}bmp085_baro_oss_t; + +/** + * @brief BMP085 barometer subsystem configuration structure. + */ +typedef struct { + /** + * @brief BMP085 barometer subsystem pressure conversion time. + */ + bmp085_baro_ct_t ct; + + /** + * @brief BMP085 barometer subsystem mode. + */ + bmp085_baro_mode_t mode; + + /** + * @brief BMP085 barometer subsystem oversampling setting. + */ + bmp085_baro_oss_t oss; +} BMP085BaroConfig; +/** @} */ + +/** + * @name BMP085 thermometer subsystem data structures and types. + * @{ + */ + +/** + * @brief BMP085 thermometer subsystem temperature conversion time. + */ +typedef enum { + BMP085_THERMO_CT_LOW = 0x05, /**< Conv time in ultra low power mode. */ + BMP085_THERMO_CT_STD = 0x18, /**< Conv time in standard mode. */ + BMP085_THERMO_CT_HR = 0x0E, /**< Conv time in high resolution mode. */ + BMP085_THERMO_CT_LUHR = 0x1A /**< Conv time in ultra high res. mode. */ +} bmp085_thermo_ct_t; + +/** + * @brief BMP085 thermometer subsystem configuration structure. + */ +typedef struct { + /** + * @brief BMP085 thermometer subsystem temperature conversion time. + */ + bmp085_thermo_ct_t conversionTime; +} BMP085ThermoConfig; +/** @} */ + +/** + * @name BMP085 main system data structures and types. + * @{ + */ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + BMP085_UNINIT = 0, /**< Not initialized. */ + BMP085_STOP = 1, /**< Stopped. */ + BMP085_READY = 2 /**< Ready. */ +} bmp085_state_t; + +/** + * @brief BMP085 configuration structure. + */ +typedef struct { + /** + * @brief I2C driver associated to this BMP085. + */ + I2CDriver *i2cp; + + /** + * @brief I2C configuration associated to this BMP085 subsystem. + */ + const I2CConfig *i2ccfg; + + /** + * @brief BMP085 barometer subsystem configuration structure + */ + const BMP085BaroConfig *barocfg; + + /** + * @brief BMP085 thermometer subsystem configuration structure + */ + const BMP085ThermoConfig *thermocfg; +} BMP085Config; + +/** + * @brief Structure representing a BMP085 driver. + */ +typedef struct BMP085Driver BMP085Driver; + +/** + * @brief @p BMP085 barometer subsystem specific methods. + */ +#define _bmp085_baro_methods \ + _base_barometer_methods + +/** + * @brief @p BMP085 thermometer subsystem specific methods. + */ +#define _bmp085_thermo_methods \ + _base_thermometer_methods + +/** + * @extends BaseBarometerVMT + * + * @brief @p BMP085 barometer virtual methods table. + */ +struct BMP085BAROVMT { + _bmp085_baro_methods +}; + +/** + * @extends BaseThermometerVMT + * + * @brief @p BMP085 thermometer virtual methods table. + */ +struct BMP085THERMOVMT { + _bmp085_thermo_methods +}; + +/** + * @brief @p BMP085Driver specific data. + */ +#define _bmp085_data \ + _base_barometer_data \ + _base_thermometer_data \ + /* Driver state. */ \ + bmp085_state_t state; \ + /* Current configuration data. */ \ + const BMP085Config *config; \ + /* Current barometer sensitivity. */ \ + float barosensitivity[BMP085_BARO_NUMBER_OF_AXES]; \ + /* Barometer bias data. */ \ + int32_t barobias[BMP085_BARO_NUMBER_OF_AXES]; \ + /* Current thermometer sensitivity. */ \ + float thermosensitivity[BMP085_THERMO_NUMBER_OF_AXES]; \ + /* Thermometer bias data. */ \ + int32_t thermobias[BMP085_THERMO_NUMBER_OF_AXES]; + +struct BMP085Driver { + /** @brief BaseSensor Virtual Methods Table. */ + const struct BaseSensorVMT *vmt_basesensor; + /** @brief BaseBarometer Virtual Methods Table. */ + const struct BaseBarometerVMT *vmt_basebarometer; + /** @brief BaseThermometer Virtual Methods Table. */ + const struct BaseThermometerVMT *vmt_basethermometer; + _bmp085_data +}; + +/** @} */ + +/*==========================================================================*/ +/* Driver macros. */ +/*==========================================================================*/ + +/*==========================================================================*/ +/* External declarations. */ +/*==========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void bmp085ObjectInit(BMP085Driver *devp); + void bmp085Start(BMP085Driver *devp, const BMP085Config *config); + void bmp085Stop(BMP085Driver *devp); +#ifdef __cplusplus +} +#endif + +#endif /* BMP085_H */ + +/** @} */ diff --git a/os/ex/Bosch/bmp085.mk b/os/ex/Bosch/bmp085.mk new file mode 100644 index 000000000..1f3c166b6 --- /dev/null +++ b/os/ex/Bosch/bmp085.mk @@ -0,0 +1,6 @@ +# List of all the BMP085 device files. +BMP085SRC := $(CHIBIOS)/os/ex/Bosch/bmp085.c + +# Required include directories +BMP085INC := $(CHIBIOS)/os/hal/lib/peripherals/sensors \ + $(CHIBIOS)/os/ex/Bosch -- cgit v1.2.3