diff --git a/src/bmp280/bmp280.c b/src/bmp280/bmp280.c index ffeba973..098a61e4 100644 --- a/src/bmp280/bmp280.c +++ b/src/bmp280/bmp280.c @@ -47,7 +47,7 @@ // #define BMP280_USE_TEST_DATA // SPI CS on and off functions -static void _csOn(const bmp280_context dev) +void _csOn(const bmp280_context dev) { assert(dev != NULL); @@ -55,7 +55,7 @@ static void _csOn(const bmp280_context dev) mraa_gpio_write(dev->gpio, 0); } -static void _csOff(const bmp280_context dev) +void _csOff(const bmp280_context dev) { assert(dev != NULL); @@ -130,7 +130,7 @@ static uint32_t _bme280_compensate_H_int32(const bmp280_context dev, } // read the calibration data -static upm_result_t _read_calibration_data(const bmp280_context dev) +upm_result_t _read_calibration_data(const bmp280_context dev) { assert(dev != NULL); diff --git a/src/bmp280/bmp280.cxx b/src/bmp280/bmp280.cxx index b9d338fc..f37d04fd 100644 --- a/src/bmp280/bmp280.cxx +++ b/src/bmp280/bmp280.cxx @@ -30,11 +30,12 @@ #include #include "bmp280.hpp" +#include "upm_string_parser.hpp" +#include "upm_utilities.h" using namespace upm; using namespace std; - // conversion from Celsius to Fahrenheit. static float c2f(float c) @@ -50,6 +51,157 @@ BMP280::BMP280(int bus, int addr, int cs) : + ": bmp280_init() failed"); } +BMP280::BMP280(std::string initStr) : mraaIo(initStr) +{ + mraa_io_descriptor* descs = mraaIo.getMraaDescriptors(); + std::vector upmTokens; + + if(!mraaIo.getLeftoverStr().empty()) { + upmTokens = UpmStringParser::parse(mraaIo.getLeftoverStr()); + } + + m_bmp280 = (bmp280_context)malloc(sizeof(struct _bmp280_context)); + if(!m_bmp280) { + throw std::runtime_error(std::string(__FUNCTION__) + + ": bmp280_init() failed"); + } + + // zero out context + memset((void *)m_bmp280, 0, sizeof(struct _bmp280_context)); + + // make sure MRAA is initialized + int mraa_rv; + if ((mraa_rv = mraa_init()) != MRAA_SUCCESS) + { + bmp280_close(m_bmp280); + throw std::runtime_error(std::string(__FUNCTION__) + + ": mraa_init() failed"); + } + + if(descs->spis) { + m_bmp280->isSPI = true; + if( !(m_bmp280->spi = descs->spis[0]) ) { + bmp280_close(m_bmp280); + throw std::runtime_error(std::string(__FUNCTION__) + + ": mraa_spi_init() failed"); + } + if(descs->gpios) { + if( !(m_bmp280->gpio = descs->gpios[0]) ) { + bmp280_close(m_bmp280); + throw std::runtime_error(std::string(__FUNCTION__) + + ": mraa_gpio_init() failed"); + } + mraa_gpio_dir(m_bmp280->gpio, MRAA_GPIO_OUT); + } else { + throw std::runtime_error(std::string(__FUNCTION__) + + ": mraa_gpio_init() failed"); + } + mraa_spi_mode(m_bmp280->spi, MRAA_SPI_MODE0); + if (mraa_spi_frequency(m_bmp280->spi, 5000000)) { + bmp280_close(m_bmp280); + throw std::runtime_error(std::string(__FUNCTION__) + + ": mraa_spi_frequency() failed"); + } + // toggle CS on/off so chip switches into SPI mode. For a hw + // CS pin, the first SPI transaction should accomplish this. + _csOn(m_bmp280); + upm_delay_ms(10); + _csOff(m_bmp280); + } else { + // init the i2c context + if(!descs->i2cs) { + throw std::runtime_error(std::string(__FUNCTION__) + + ": mraa_i2c_init() failed"); + } else { + if( !(m_bmp280->i2c = descs->i2cs[0]) ) + { + bmp280_close(m_bmp280); + throw std::runtime_error(std::string(__FUNCTION__) + + ": mraa_i2c_init() failed"); + } + } + } + // check the chip id + + uint8_t chipID = bmp280_read_reg(m_bmp280, BMP280_REG_CHIPID); + + switch(chipID) + { + case BMP280_CHIPID: // BMP280 + m_bmp280->isBME = false; + break; + + case BME280_CHIPID: // BME280 + m_bmp280->isBME = true; + break; + + default: // ?? + printf("%s: invalid chip id: %02x. Expected either %02x " + "(bmp280) or %02x (bme280)\n", + __FUNCTION__, chipID, BMP280_CHIPID, BME280_CHIPID); + bmp280_close(m_bmp280); + throw std::runtime_error(std::string(__FUNCTION__) + + ": bmp280_init() failed"); + + } + + // set sleep mode for now + bmp280_set_measure_mode(m_bmp280, BMP280_MODE_SLEEP); + + // read calibration data + if (_read_calibration_data(m_bmp280)) + { + printf("%s: _read_calibration_data() failed.", __FUNCTION__); + bmp280_close(m_bmp280); + throw std::runtime_error(std::string(__FUNCTION__) + + ": bmp280_init() failed"); + } + + // set the default mode to the highest resolution mode + bmp280_set_usage_mode(m_bmp280, BMP280_USAGE_MODE_INDOOR_NAV); + + // set the default sea level pressure in hPA + m_bmp280->sea_level_hPA = BMP280_SEA_LEVEL_HPA; + + std::string::size_type sz; + for(std::string tok:upmTokens) { + if(tok.substr(0,21) == "setSeaLevelPreassure:") { + float seaLevelhPA = std::stof(tok.substr(21)); + setSeaLevelPreassure(seaLevelhPA); + } + if(tok.substr(0,9) == "writeReg:") { + uint8_t reg = std::stoi(tok.substr(9),&sz,0); + tok = tok.substr(9); + uint8_t val = std::stoi(tok.substr(sz+1),nullptr,0); + writeReg(reg, val); + } + if(tok.substr(0,10) == "setFilter:") { + BMP280_FILTER_T filter = (BMP280_FILTER_T)std::stoi(tok.substr(10),nullptr,0); + setFilter(filter); + } + if(tok.substr(0,16) == "setTimerStandby:") { + BMP280_T_SB_T tsb = (BMP280_T_SB_T)std::stoi(tok.substr(16),nullptr,0); + setTimerStandby(tsb); + } + if(tok.substr(0,15) == "setMeasureMode:") { + BMP280_MODES_T mode = (BMP280_MODES_T)std::stoi(tok.substr(15),nullptr,0); + setMeasureMode(mode); + } + if(tok.substr(0,26) == "setOversampleRatePressure:") { + BMP280_OSRS_P_T rate = (BMP280_OSRS_P_T)std::stoi(tok.substr(26),nullptr,0); + setOversampleRatePressure(rate); + } + if(tok.substr(0,29) == "setOversampleRateTemperature:") { + BMP280_OSRS_T_T rate = (BMP280_OSRS_T_T)std::stoi(tok.substr(29),nullptr,0); + setOversampleRateTemperature(rate); + } + if(tok.substr(0,13) == "setUsageMode:") { + BMP280_USAGE_MODE_T mode = (BMP280_USAGE_MODE_T)std::stoi(tok.substr(13),nullptr,0); + setUsageMode(mode); + } + } +} + BMP280::~BMP280() { bmp280_close(m_bmp280); diff --git a/src/bmp280/bmp280.h b/src/bmp280/bmp280.h index ec4379e3..66766318 100644 --- a/src/bmp280/bmp280.h +++ b/src/bmp280/bmp280.h @@ -341,6 +341,18 @@ extern "C" { upm_result_t bmp280_write_reg(const bmp280_context dev, uint8_t reg, uint8_t val); + /** + * SPI CS on and off functions + */ + void _csOn(const bmp280_context dev); + void _csOff(const bmp280_context dev); + + /** + * Read the calibration data + */ + upm_result_t _read_calibration_data(const bmp280_context dev); + + #ifdef __cplusplus } #endif diff --git a/src/bmp280/bmp280.hpp b/src/bmp280/bmp280.hpp index 18889681..1d677a43 100644 --- a/src/bmp280/bmp280.hpp +++ b/src/bmp280/bmp280.hpp @@ -27,6 +27,7 @@ #include #include "bmp280.h" +#include "mraa/initio.hpp" #include "interfaces/iPressureSensor.hpp" #include "interfaces/iTemperatureSensor.hpp" @@ -93,6 +94,13 @@ namespace upm { BMP280(int bus=BMP280_DEFAULT_I2C_BUS, int addr=BMP280_DEFAULT_ADDR, int cs=-1); + /** + * Instantiates BMP280/BME280 Digital Pressure Sensors based on a given string. + * + * @param initStr string containing specific information for BMP280/BME280 initialization. + */ + BMP280(std::string initStr); + /** * BMP280 Destructor. */ @@ -235,6 +243,7 @@ namespace upm { protected: bmp280_context m_bmp280; + mraa::MraaIo mraaIo; /** * Return the value of the BMP280_REG_STATUS register.