diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt index 56133308..f2a7c073 100644 --- a/examples/c/CMakeLists.txt +++ b/examples/c/CMakeLists.txt @@ -154,6 +154,7 @@ add_example (bmp280) add_example (abpdrrt005pg2a5) add_example (lcdks) add_example (bmg160) +add_example (bma250e) # Custom examples add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps) diff --git a/examples/c/bma250e.c b/examples/c/bma250e.c new file mode 100644 index 00000000..aca8c8a6 --- /dev/null +++ b/examples/c/bma250e.c @@ -0,0 +1,99 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2017 Intel Corporation. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include + +#include "upm_utilities.h" +#include "bma250e.h" + +bool shouldRun = true; + +void sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + + +int main(int argc, char **argv) +{ + signal(SIGINT, sig_handler); +//! [Interesting] + +#if defined(CONFIG_BOARD_ARDUINO_101_SSS) + // ARDUINO_101_SSS (ARC core) must use I2C + // Instantiate a BMA250E instance using default i2c bus and address + bma250e_context sensor = bma250e_init(BMA250E_DEFAULT_I2C_BUS, + BMA250E_DEFAULT_ADDR, -1); +#elif defined(CONFIG_BOARD_ARDUINO_101) + // ARDUINO_101 (Quark core) where you must use SPI + // Instantiate a BMA250E instance using default SPI bus and pin 10 as CS + bma250e_context sensor = bma250e_init(BMA250E_DEFAULT_SPI_BUS, + -1, 10); +#else + // everything else use I2C by default + // Instantiate a BMA250E instance using default i2c bus and address + bma250e_context sensor = bma250e_init(BMA250E_DEFAULT_I2C_BUS, + BMA250E_DEFAULT_ADDR, -1); +#endif + + if (!sensor) + { + printf("bma250e_init() failed.\n"); + return 1; + } + + // now output data every 250 milliseconds + while (shouldRun) + { + float x, y, z; + + if (bma250e_update(sensor)) + { + printf("bma250e_update() failed\n"); + return 1; + } + + bma250e_get_accelerometer(sensor, &x, &y, &z); + printf("Acceleration x: %f y: %f z: %f g\n", + x, y, z); + + printf("Compensation Temperature: %f C\n\n", + bma250e_get_temperature(sensor)); + + upm_delay_ms(250); + } + + printf("Exiting...\n"); + + bma250e_close(sensor); + +//! [Interesting] + + return 0; +} diff --git a/examples/java/BMA250E_Example.java b/examples/java/BMA250E_Example.java index dd138ad3..cb5811fb 100644 --- a/examples/java/BMA250E_Example.java +++ b/examples/java/BMA250E_Example.java @@ -1,6 +1,6 @@ /* * Author: Jon Trulson - * Copyright (c) 2016 Intel Corporation. + * Copyright (c) 2016-2017 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -22,7 +22,7 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -import upm_bmx055.BMA250E; +import upm_bma250e.BMA250E; public class BMA250E_Example { @@ -42,11 +42,11 @@ public class BMA250E_Example // update our values from the sensor sensor.update(); - float dataA[] = sensor.getAccelerometer(); + upm_bma250e.floatVector dataA = sensor.getAccelerometer(); - System.out.println("Accelerometer x: " + dataA[0] - + " y: " + dataA[1] - + " z: " + dataA[2] + System.out.println("Accelerometer x: " + dataA.get(0) + + " y: " + dataA.get(1) + + " z: " + dataA.get(2) + " g"); System.out.println("Compensation Temperature: " diff --git a/examples/java/CMakeLists.txt b/examples/java/CMakeLists.txt index 98f1adce..ffa0018e 100644 --- a/examples/java/CMakeLists.txt +++ b/examples/java/CMakeLists.txt @@ -167,6 +167,7 @@ add_example(Ads1115Sample ads1x15) add_example(SensorTemplateSample sensortemplate) add_example(P9813Sample p9813) add_example(BMG160_Example bmg160) +add_example(BMA250E_Example bma250e) add_example_with_path(Jhd1313m1_lcdSample jhd1313m1 jhd1313m1) add_example_with_path(Jhd1313m1Sample jhd1313m1 jhd1313m1) @@ -180,7 +181,6 @@ if(SWIG_VERSION VERSION_GREATER 3.0.8) add_example_with_path(BME280_InterfaceExample bmp280 bmp280) endif() -add_example_with_path(BMA250E_Example bmx055 bmx055) add_example_with_path(BMM150_Example bmx055 bmx055) add_example_with_path(BMC150_Example bmx055 bmx055) add_example_with_path(BMI055_Example bmx055 bmx055) diff --git a/examples/javascript/bma250e.js b/examples/javascript/bma250e.js index 8a140c1e..f4898759 100644 --- a/examples/javascript/bma250e.js +++ b/examples/javascript/bma250e.js @@ -1,6 +1,6 @@ /* * Author: Jon Trulson - * Copyright (c) 2016 Intel Corporation. + * Copyright (c) 2016-2017 Intel Corporation. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -22,7 +22,7 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -var sensorObj = require('jsupm_bmx055'); +var sensorObj = require('jsupm_bma250e'); // Instantiate a BMA250E instance using default i2c bus and address var sensor = new sensorObj.BMA250E(); @@ -30,21 +30,17 @@ var sensor = new sensorObj.BMA250E(); // For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS: // BMA250E(0, -1, 10); -var x = new sensorObj.new_floatp(); -var y = new sensorObj.new_floatp(); -var z = new sensorObj.new_floatp(); - // now output data every 250 milliseconds setInterval(function() { // update our values from the sensor sensor.update(); - sensor.getAccelerometer(x, y, z); + var data = sensor.getAccelerometer(); console.log("Accelerometer x: " - + sensorObj.floatp_value(x) - + " y: " + sensorObj.floatp_value(y) - + " z: " + sensorObj.floatp_value(z) + + data.get(0) + + " y: " + data.get(1) + + " z: " + data.get(2) + " g"); // we show both C and F for temperature diff --git a/examples/python/bma250e.py b/examples/python/bma250e.py index 24b25488..9eace673 100755 --- a/examples/python/bma250e.py +++ b/examples/python/bma250e.py @@ -1,6 +1,6 @@ #!/usr/bin/python # Author: Jon Trulson -# Copyright (c) 2016 Intel Corporation. +# Copyright (c) 2016-2017 Intel Corporation. # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -23,7 +23,7 @@ from __future__ import print_function import time, sys, signal, atexit -from upm import pyupm_bmx055 as sensorObj +from upm import pyupm_bma250e as sensorObj def main(): # Instantiate a BMP250E instance using default i2c bus and address @@ -46,18 +46,14 @@ def main(): atexit.register(exitHandler) signal.signal(signal.SIGINT, SIGINTHandler) - x = sensorObj.new_floatp() - y = sensorObj.new_floatp() - z = sensorObj.new_floatp() - # now output data every 250 milliseconds while (1): sensor.update() - sensor.getAccelerometer(x, y, z) - print("Accelerometer x:", sensorObj.floatp_value(x), end=' ') - print(" y:", sensorObj.floatp_value(y), end=' ') - print(" z:", sensorObj.floatp_value(z), end=' ') + data = sensor.getAccelerometer() + print("Accelerometer x:", data[0], end=' ') + print(" y:", data[1], end=' ') + print(" z:", data[2], end=' ') print(" g") # we show both C and F for temperature diff --git a/src/bma250e/CMakeLists.txt b/src/bma250e/CMakeLists.txt new file mode 100644 index 00000000..c4ed3bae --- /dev/null +++ b/src/bma250e/CMakeLists.txt @@ -0,0 +1,9 @@ +upm_mixed_module_init (NAME bma250e + DESCRIPTION "3-Axis Digital Accelerometer" + C_HDR bma250e.h bma250e_defs.h + C_SRC bma250e.c + CPP_HDR bma250e.hpp + CPP_SRC bma250e.cxx + FTI_SRC bma250e_fti.c + CPP_WRAPS_C + REQUIRES mraa) diff --git a/src/bma250e/bma250e.c b/src/bma250e/bma250e.c new file mode 100644 index 00000000..aab8dd76 --- /dev/null +++ b/src/bma250e/bma250e.c @@ -0,0 +1,967 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2017 Intel Corporation. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include "upm_utilities.h" +#include "bma250e.h" + +// macro for converting a uint8_t low/high pair into a float +#define INT16_TO_FLOAT(h, l) \ + (float)( (int16_t)( (l) | ((h) << 8) ) ) + +// SPI CS on and off functions +static void _csOn(const bma250e_context dev) +{ + assert(dev != NULL); + + if (dev->gpioCS) + mraa_gpio_write(dev->gpioCS, 0); +} + +static void _csOff(const bma250e_context dev) +{ + assert(dev != NULL); + + if (dev->gpioCS) + mraa_gpio_write(dev->gpioCS, 1); +} + +// init +bma250e_context bma250e_init(int bus, int addr, int cs) +{ + bma250e_context dev = + (bma250e_context)malloc(sizeof(struct _bma250e_context)); + + if (!dev) + return NULL; + + // zero out context + memset((void *)dev, 0, sizeof(struct _bma250e_context)); + + // make sure MRAA is initialized + if (mraa_init() != MRAA_SUCCESS) + { + printf("%s: mraa_init() failed.\n", __FUNCTION__); + bma250e_close(dev); + return NULL; + } + + if (addr < 0) + dev->isSPI = true; + + if (dev->isSPI) + { + if (!(dev->spi = mraa_spi_init(bus))) + { + printf("%s: mraa_spi_init() failed.\n", __FUNCTION__); + bma250e_close(dev); + return NULL; + } + + // Only create cs context if we are actually using a valid pin. + // A hardware controlled pin should specify cs as -1. + if (cs >= 0) + { + if (!(dev->gpioCS = mraa_gpio_init(cs))) + { + printf("%s: mraa_gpio_init() failed.\n", __FUNCTION__); + bma250e_close(dev); + return NULL; + } + mraa_gpio_dir(dev->gpioCS, MRAA_GPIO_OUT); + } + + mraa_spi_mode(dev->spi, MRAA_SPI_MODE0); + if (mraa_spi_frequency(dev->spi, 5000000)) + { + printf("%s: mraa_spi_frequency() failed.\n", __FUNCTION__); + bma250e_close(dev); + return NULL; + } + } + else + { + // I2C + + if (!(dev->i2c = mraa_i2c_init(bus))) + { + printf("%s: mraa_i2c_init() failed.\n", __FUNCTION__); + bma250e_close(dev); + return NULL; + } + + if (mraa_i2c_address(dev->i2c, addr)) + { + printf("%s: mraa_i2c_address() failed.\n", __FUNCTION__); + bma250e_close(dev); + return NULL; + } + } + + // check the chip id + + uint8_t chipID = bma250e_get_chip_id(dev); + + // check the various chips id's and set appropriate capabilities. + // Bail if the chip id is unknown. + switch (chipID) + { + case 0xf9: // standalone bma250e + dev->resolution = BMA250E_RESOLUTION_10BITS; + dev->fifoAvailable = true; + + break; + + case 0xfa: // bmx055, bmi055 variants, 12b resolution + dev->resolution = BMA250E_RESOLUTION_12BITS; + dev->fifoAvailable = true; + + break; + + case 0x03: // bmc050 variant, no FIFO, 12b resolution + dev->resolution = BMA250E_RESOLUTION_12BITS; + dev->fifoAvailable = false; + + break; + + default: + printf("%s: invalid chip id: %02x. Expected f9, fa, or 03\n", + __FUNCTION__, chipID); + bma250e_close(dev); + return NULL; + } + + // call devinit with default options + if (bma250e_devinit(dev, BMA250E_POWER_MODE_NORMAL, BMA250E_RANGE_2G, + BMA250E_BW_250)) + { + printf("%s: bma250e_devinit() failed.\n", __FUNCTION__); + bma250e_close(dev); + return NULL; + } + + return dev; +} + +void bma250e_close(bma250e_context dev) +{ + assert(dev != NULL); + + bma250e_uninstall_isr(dev, BMA250E_INTERRUPT_INT1); + bma250e_uninstall_isr(dev, BMA250E_INTERRUPT_INT2); + + if (dev->i2c) + mraa_i2c_stop(dev->i2c); + if (dev->spi) + mraa_spi_stop(dev->spi); + if (dev->gpioCS) + mraa_gpio_close(dev->gpioCS); + + free(dev); +} + +upm_result_t bma250e_devinit(const bma250e_context dev, + BMA250E_POWER_MODE_T pwr, + BMA250E_RANGE_T range, + BMA250E_BW_T bw) +{ + assert(dev != NULL); + + if (bma250e_set_power_mode(dev, pwr)) + { + printf("%s: bma250e_set_power_mode() failed.\n", __FUNCTION__); + return UPM_ERROR_OPERATION_FAILED; + } + + upm_delay_ms(50); // 50ms, in case we are waking up + + // set our range and bandwidth, make sure register shadowing is + // enabled, enable output filtering, and set our FIFO config + + if (bma250e_set_range(dev, range) + || bma250e_set_bandwidth(dev, bw) + || bma250e_enable_register_shadowing(dev, true) + || bma250e_enable_output_filtering(dev, true) + || bma250e_fifo_config(dev, BMA250E_FIFO_MODE_BYPASS, + BMA250E_FIFO_DATA_SEL_XYZ)) + { + printf("%s: failed to set configuration parameters.\n", + __FUNCTION__); + return UPM_ERROR_OPERATION_FAILED; + } + + bma250e_enable_fifo(dev, true); + + // make sure low power mode LPM2 is enabled in case we go to low + // power or suspend mode. LPM1 mode (the default) requires register + // writes to be drastically slowed down when enabled, which we + // cannot handle. + bma250e_set_low_power_mode2(dev); + + // settle + upm_delay_ms(50); + + return UPM_SUCCESS; +} + +upm_result_t bma250e_update(const bma250e_context dev) +{ + assert(dev != NULL); + + int bufLen = 7; // max, non-FIFO + uint8_t startReg = BMA250E_REG_ACCD_X_LSB; + + if (dev->useFIFO) + { + bufLen = 6; + startReg = BMA250E_REG_FIFO_DATA; + } + + uint8_t buf[bufLen]; + + if (bma250e_read_regs(dev, startReg, buf, bufLen) != bufLen) + { + printf("%s: bma250e_read_regs() failed to read %d bytes\n", + __FUNCTION__, bufLen); + return UPM_ERROR_OPERATION_FAILED; + } + + uint8_t mask = 0, shift = 0; + float divisor = 1; + + switch (dev->resolution) + { + case BMA250E_RESOLUTION_10BITS: + mask = _BMA250E_ACCD10_LSB_MASK; + shift = _BMA250E_ACCD10_LSB_SHIFT; + divisor = 64.0; + + break; + + case BMA250E_RESOLUTION_12BITS: + mask = _BMA250E_ACCD12_LSB_MASK; + shift = _BMA250E_ACCD12_LSB_SHIFT; + divisor = 16.0; + + break; + } + + // x msb lsb + dev->accX = INT16_TO_FLOAT(buf[1], (buf[0] & (mask << shift))) / divisor; + + // y + dev->accY = INT16_TO_FLOAT(buf[3], (buf[2] & (mask << shift))) / divisor; + + // z + dev->accZ = INT16_TO_FLOAT(buf[5], (buf[4] & (mask << shift))) / divisor; + + // get the temperature... + + int8_t temp = 0; + if (dev->useFIFO) + { + // we have to read temperature separately... + temp = (int8_t)bma250e_read_reg(dev, BMA250E_REG_TEMP); + } + else + { + // we already got it + temp = (int8_t)buf[6]; + } + + // .5K/LSB, 23C center point + dev->temperature = ((float)temp / 2.0) + 23.0; + + return UPM_SUCCESS; +} + +void bma250e_enable_fifo(const bma250e_context dev, bool useFIFO) +{ + assert(dev != NULL); + + if (dev->fifoAvailable) + dev->useFIFO = useFIFO; +} + +uint8_t bma250e_read_reg(const bma250e_context dev, uint8_t reg) +{ + assert(dev != NULL); + + if (dev->isSPI) + { + reg |= 0x80; // needed for read + uint8_t pkt[2] = {reg, 0}; + + _csOn(dev); + if (mraa_spi_transfer_buf(dev->spi, pkt, pkt, 2)) + { + _csOff(dev); + printf("%s: mraa_spi_transfer_buf() failed.\n", __FUNCTION__); + return 0xff; + } + _csOff(dev); + + return pkt[1]; + } + else + return (uint8_t)mraa_i2c_read_byte_data(dev->i2c, reg); +} + +int bma250e_read_regs(const bma250e_context dev, uint8_t reg, + uint8_t *buffer, int len) +{ + assert(dev != NULL); + + if (dev->isSPI) + { + reg |= 0x80; // needed for read + + uint8_t sbuf[len + 1]; + memset((char *)sbuf, 0, len + 1); + sbuf[0] = reg; + + _csOn(dev); + if (mraa_spi_transfer_buf(dev->spi, sbuf, sbuf, len + 1)) + { + _csOff(dev); + printf("%s: mraa_spi_transfer_buf() failed.\n", __FUNCTION__); + return -1; + } + _csOff(dev); + + // now copy it into user buffer + for (int i=0; ii2c, reg, buffer, len) != len) + return -1; + } + + return len; +} + +upm_result_t bma250e_write_reg(const bma250e_context dev, + uint8_t reg, uint8_t val) +{ + assert(dev != NULL); + + if (dev->isSPI) + { + reg &= 0x7f; // mask off 0x80 for writing + uint8_t pkt[2] = {reg, val}; + + _csOn(dev); + if (mraa_spi_transfer_buf(dev->spi, pkt, NULL, 2)) + { + _csOff(dev); + printf("%s: mraa_spi_transfer_buf() failed.", + __FUNCTION__); + + return UPM_ERROR_OPERATION_FAILED; + } + _csOff(dev); + } + else + { + if (mraa_i2c_write_byte_data(dev->i2c, val, reg)) + { + printf("%s: mraa_i2c_write_byte_data() failed.", + __FUNCTION__); + return UPM_ERROR_OPERATION_FAILED; + } + } + + return UPM_SUCCESS; +} + +uint8_t bma250e_get_chip_id(const bma250e_context dev) +{ + assert(dev != NULL); + + return bma250e_read_reg(dev, BMA250E_REG_CHIP_ID); +} + +void bma250e_get_accelerometer(const bma250e_context dev, + float *x, float *y, float *z) +{ + assert(dev != NULL); + + if (x) + *x = (dev->accX * dev->accScale) / 1000.0; + + if (y) + *y = (dev->accY * dev->accScale) / 1000.0; + + if (z) + *z = (dev->accZ * dev->accScale) / 1000.0; +} + +float bma250e_get_temperature(const bma250e_context dev) +{ + assert(dev != NULL); + + return dev->temperature; +} + +upm_result_t bma250e_reset(const bma250e_context dev) +{ + assert(dev != NULL); + + if (bma250e_write_reg(dev, BMA250E_REG_SOFTRESET, BMA250E_RESET_BYTE)) + return UPM_ERROR_OPERATION_FAILED; + + upm_delay(1); + + return UPM_SUCCESS; +} + +upm_result_t bma250e_set_range(const bma250e_context dev, + BMA250E_RANGE_T range) +{ + assert(dev != NULL); + + if (bma250e_write_reg(dev, BMA250E_REG_PMU_RANGE, range)) + return UPM_ERROR_OPERATION_FAILED; + + switch (dev->resolution) + { + case BMA250E_RESOLUTION_10BITS: + switch(range) + { + case BMA250E_RANGE_2G: + dev->accScale = 3.91; // milli-gravities + break; + + case BMA250E_RANGE_4G: + dev->accScale = 7.81; + break; + + case BMA250E_RANGE_8G: + dev->accScale = 15.63; + break; + + case BMA250E_RANGE_16G: + dev->accScale = 31.25; + break; + } + + break; + + case BMA250E_RESOLUTION_12BITS: + switch(range) + { + case BMA250E_RANGE_2G: + dev->accScale = 0.98; // milli-gravities + break; + + case BMA250E_RANGE_4G: + dev->accScale = 1.95; + break; + + case BMA250E_RANGE_8G: + dev->accScale = 3.91; + break; + + case BMA250E_RANGE_16G: + dev->accScale = 7.81; + break; + } + + break; + } + + return UPM_SUCCESS; +} + +upm_result_t bma250e_set_bandwidth(const bma250e_context dev, + BMA250E_BW_T bw) +{ + assert(dev != NULL); + + if (bma250e_write_reg(dev, BMA250E_REG_PMU_BW, bw)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t bma250e_set_power_mode(const bma250e_context dev, + BMA250E_POWER_MODE_T power) +{ + assert(dev != NULL); + + // mask off reserved bits first + uint8_t reg = + bma250e_read_reg(dev, BMA250E_REG_PMU_LPW) + & ~_BMA250E_PMU_LPW_RESERVED_MASK; + + reg &= ~(_BMA250E_PMU_LPW_POWER_MODE_MASK + << _BMA250E_PMU_LPW_POWER_MODE_SHIFT); + reg |= (power << _BMA250E_PMU_LPW_POWER_MODE_SHIFT); + + if (bma250e_write_reg(dev, BMA250E_REG_PMU_LPW, power)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t bma250e_fifo_set_watermark(const bma250e_context dev, int wm) +{ + assert(dev != NULL); + + if (!dev->fifoAvailable) + return UPM_ERROR_NOT_SUPPORTED; + + // mask off illegal values + uint8_t reg = ((uint8_t)wm) & _BMA250E_FIFO_CONFIG_0_WATER_MARK_MASK; + + if (bma250e_write_reg(dev, BMA250E_REG_FIFO_CONFIG_0, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t bma250e_fifo_config(const bma250e_context dev, + BMA250E_FIFO_MODE_T mode, + BMA250E_FIFO_DATA_SEL_T axes) +{ + assert(dev != NULL); + + if (!dev->fifoAvailable) + return UPM_ERROR_NOT_SUPPORTED; + + uint8_t reg = ( (mode << _BMA250E_FIFO_CONFIG_1_FIFO_MODE_SHIFT) | + (axes << _BMA250E_FIFO_CONFIG_1_FIFO_DATA_SHIFT) ); + + if (bma250e_write_reg(dev, BMA250E_REG_FIFO_CONFIG_1, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t bma250e_set_self_test(const bma250e_context dev, + bool sign, bool amp, + BMA250E_SELFTTEST_AXIS_T axis) +{ + assert(dev != NULL); + + uint8_t reg = (axis << _BMA250E_PMU_SELFTTEST_AXIS_SHIFT); + + if (amp) + reg |= BMA250E_PMU_SELFTTEST_AMP; + + if (sign) + reg |= BMA250E_PMU_SELFTTEST_SIGN; + + if (bma250e_write_reg(dev, BMA250E_REG_PMU_SELFTEST, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +uint8_t bma250e_get_interrupt_enable0(const bma250e_context dev) +{ + assert(dev != NULL); + + return (bma250e_read_reg(dev, BMA250E_REG_INT_EN_0) + & ~_BMA250E_INT_EN_0_RESERVED_BITS); +} + +upm_result_t bma250e_set_interrupt_enable0(const bma250e_context dev, + uint8_t bits) +{ + assert(dev != NULL); + + uint8_t reg = bits & ~_BMA250E_INT_EN_0_RESERVED_BITS; + + if (bma250e_write_reg(dev, BMA250E_REG_INT_EN_0, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +uint8_t bma250e_get_interrupt_enable1(const bma250e_context dev) +{ + assert(dev != NULL); + + return (bma250e_read_reg(dev, BMA250E_REG_INT_EN_1) + & ~_BMA250E_INT_EN_1_RESERVED_BITS); +} + +upm_result_t bma250e_set_interrupt_enable1(const bma250e_context dev, + uint8_t bits) +{ + assert(dev != NULL); + + uint8_t reg = bits & ~_BMA250E_INT_EN_1_RESERVED_BITS; + + if (bma250e_write_reg(dev, BMA250E_REG_INT_EN_1, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +uint8_t bma250e_get_interrupt_enable2(const bma250e_context dev) +{ + assert(dev != NULL); + + return (bma250e_read_reg(dev, BMA250E_REG_INT_EN_2) + & ~_BMA250E_INT_EN_2_RESERVED_BITS); +} + +upm_result_t bma250e_set_interrupt_enable2(const bma250e_context dev, + uint8_t bits) +{ + assert(dev != NULL); + + uint8_t reg = bits & ~_BMA250E_INT_EN_2_RESERVED_BITS; + + if (bma250e_write_reg(dev, BMA250E_REG_INT_EN_2, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +uint8_t bma250e_get_interrupt_map0(const bma250e_context dev) +{ + assert(dev != NULL); + + return bma250e_read_reg(dev, BMA250E_REG_INT_MAP_0); +} + +upm_result_t bma250e_set_interrupt_map0(const bma250e_context dev, uint8_t bits) +{ + assert(dev != NULL); + + if (bma250e_write_reg(dev, BMA250E_REG_INT_MAP_0, bits)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +uint8_t bma250e_get_interrupt_map1(const bma250e_context dev) +{ + assert(dev != NULL); + + return (bma250e_read_reg(dev, BMA250E_REG_INT_MAP_1) + & ~_BMA250E_INT_MAP_1_INT1_RESERVED_BITS); +} + +upm_result_t bma250e_set_interrupt_map1(const bma250e_context dev, uint8_t bits) +{ + assert(dev != NULL); + + uint8_t reg = bits & ~_BMA250E_INT_MAP_1_INT1_RESERVED_BITS; + + if (bma250e_write_reg(dev, BMA250E_REG_INT_MAP_1, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +uint8_t bma250e_get_interrupt_map2(const bma250e_context dev) +{ + assert(dev != NULL); + + return bma250e_read_reg(dev, BMA250E_REG_INT_MAP_2); +} + +upm_result_t bma250e_set_interrupt_map2(const bma250e_context dev, uint8_t bits) +{ + assert(dev != NULL); + + if (bma250e_write_reg(dev, BMA250E_REG_INT_MAP_2, bits)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +uint8_t bma250e_get_interrupt_src(const bma250e_context dev) +{ + assert(dev != NULL); + + return (bma250e_read_reg(dev, BMA250E_REG_INT_SRC) + & ~_BMA250E_INT_SRC_RESERVED_BITS); +} + +upm_result_t bma250e_set_interrupt_src(const bma250e_context dev, uint8_t bits) +{ + assert(dev != NULL); + + uint8_t reg = bits & ~_BMA250E_INT_SRC_RESERVED_BITS; + + if (bma250e_write_reg(dev, BMA250E_REG_INT_SRC, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +uint8_t bma250e_get_interrupt_output_control(const bma250e_context dev) +{ + assert(dev != NULL); + + return (bma250e_read_reg(dev, BMA250E_REG_INT_OUT_CTRL) + & ~_BMA250E_INT_OUT_CTRL_INT1_RESERVED_BITS); +} + +upm_result_t bma250e_set_interrupt_output_control(const bma250e_context dev, + uint8_t bits) +{ + assert(dev != NULL); + + uint8_t reg = bits & ~_BMA250E_INT_OUT_CTRL_INT1_RESERVED_BITS; + + if (bma250e_write_reg(dev, BMA250E_REG_INT_OUT_CTRL, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t bma250e_clear_interrupt_latches(const bma250e_context dev) +{ + assert(dev != NULL); + + uint8_t reg = + (bma250e_read_reg(dev, BMA250E_REG_INT_RST_LATCH) + & ~_BMA250E_INT_RST_LATCH_RESERVED_BITS); + + reg |= BMA250E_INT_RST_LATCH_RESET_INT; + + if (bma250e_write_reg(dev, BMA250E_REG_INT_RST_LATCH, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +BMA250E_RST_LATCH_T bma250e_get_interrupt_latch_behavior( + const bma250e_context dev) +{ + assert(dev != NULL); + + uint8_t reg = (bma250e_read_reg(dev, BMA250E_REG_INT_RST_LATCH) + & ~_BMA250E_INT_RST_LATCH_RESERVED_BITS); + + reg &= (_BMA250E_INT_RST_LATCH_MASK << _BMA250E_INT_RST_LATCH_SHIFT); + + return (BMA250E_RST_LATCH_T)reg; +} + +upm_result_t bma250e_set_interrupt_latch_behavior(const bma250e_context dev, + BMA250E_RST_LATCH_T latch) +{ + assert(dev != NULL); + + uint8_t reg = + (bma250e_read_reg(dev, BMA250E_REG_INT_RST_LATCH) + & ~_BMA250E_INT_RST_LATCH_RESERVED_BITS); + + reg &= ~(_BMA250E_INT_RST_LATCH_MASK << _BMA250E_INT_RST_LATCH_SHIFT); + reg |= (latch << _BMA250E_INT_RST_LATCH_SHIFT); + + if (bma250e_write_reg(dev, BMA250E_REG_INT_RST_LATCH, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t bma250e_enable_register_shadowing(const bma250e_context dev, + bool shadow) +{ + assert(dev != NULL); + + uint8_t reg = + (bma250e_read_reg(dev, BMA250E_REG_ACC_HBW) + & ~_BMA250E_ACC_HBW_RESERVED_BITS); + + if (shadow) + reg &= ~BMA250E_ACC_HBW_SHADOW_DIS; + else + reg |= BMA250E_ACC_HBW_SHADOW_DIS; + + if (bma250e_write_reg(dev, BMA250E_REG_ACC_HBW, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t bma250e_enable_output_filtering(const bma250e_context dev, + bool filter) +{ + assert(dev != NULL); + + uint8_t reg = + (bma250e_read_reg(dev, BMA250E_REG_ACC_HBW) + & ~_BMA250E_ACC_HBW_RESERVED_BITS); + + if (filter) + reg &= ~BMA250E_ACC_HBW_DATA_HIGH_BW; + else + reg |= BMA250E_ACC_HBW_DATA_HIGH_BW; + + if (bma250e_write_reg(dev, BMA250E_REG_ACC_HBW, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +uint8_t bma250e_get_interrupt_status0(const bma250e_context dev) +{ + assert(dev != NULL); + + return bma250e_read_reg(dev, BMA250E_REG_INT_STATUS_0); +} + +uint8_t bma250e_get_interrupt_status1(const bma250e_context dev) +{ + assert(dev != NULL); + + return (bma250e_read_reg(dev, BMA250E_REG_INT_STATUS_1) + & ~_BMA250E_INT_STATUS_1_RESERVED_BITS); +} + +uint8_t bma250e_get_interrupt_status2(const bma250e_context dev) +{ + assert(dev != NULL); + + return bma250e_read_reg(dev, BMA250E_REG_INT_STATUS_2); +} + +uint8_t bma250e_get_interrupt_status3_bits(const bma250e_context dev) +{ + assert(dev != NULL); + + // filter out the orientation bitfield.. + return (bma250e_read_reg(dev, BMA250E_REG_INT_STATUS_3) + & ~(_BMA250E_INT_STATUS_3_ORIENT_MASK + << _BMA250E_INT_STATUS_3_ORIENT_SHIFT)); +} + +BMA250E_ORIENT_T bma250e_get_interrupt_status3_orientation( + const bma250e_context dev) +{ + assert(dev != NULL); + + // grab just the orientation bitfield + uint8_t reg = (bma250e_read_reg(dev, BMA250E_REG_INT_STATUS_3) + & (_BMA250E_INT_STATUS_3_ORIENT_MASK + << _BMA250E_INT_STATUS_3_ORIENT_SHIFT)); + + reg >>= _BMA250E_INT_STATUS_3_ORIENT_SHIFT; + + return (BMA250E_ORIENT_T)reg; +} + +upm_result_t bma250e_set_low_power_mode2(const bma250e_context dev) +{ + assert(dev != NULL); + + uint8_t reg = (bma250e_read_reg(dev, BMA250E_REG_PMU_LOW_POWER) + & ~_BMA250E_LOW_POWER_RESERVED_BITS); + + // we simply set the low power mode to 2. Low power mode 1 slows + // down register write accesses, and we can't handle that. In the + // words of the late Admiral Akbar: "We cannot handle firepower of + // that magnitude!" :( + + reg |= BMA250E_LOW_POWER_LOWPOWER_MODE; + + if (bma250e_write_reg(dev, BMA250E_REG_PMU_LOW_POWER, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t bma250e_install_isr(const bma250e_context dev, + BMA250E_INTERRUPT_PINS_T intr, int gpio, + mraa_gpio_edge_t level, + void (*isr)(void *), void *arg) +{ + assert(dev != NULL); + + // delete any existing ISR and GPIO context for this interrupt + bma250e_uninstall_isr(dev, intr); + + mraa_gpio_context gpio_isr = NULL; + + // create gpio context + if (!(gpio_isr = mraa_gpio_init(gpio))) + { + printf("%s: mraa_gpio_init() failed.\n", __FUNCTION__); + return UPM_ERROR_OPERATION_FAILED; + } + + mraa_gpio_dir(gpio_isr, MRAA_GPIO_IN); + + if (mraa_gpio_isr(gpio_isr, level, isr, arg)) + { + mraa_gpio_close(gpio_isr); + printf("%s: mraa_gpio_isr() failed.\n", __FUNCTION__); + return UPM_ERROR_OPERATION_FAILED; + } + + switch (intr) + { + case BMA250E_INTERRUPT_INT1: + dev->gpio1 = gpio_isr; + break; + + case BMA250E_INTERRUPT_INT2: + dev->gpio2 = gpio_isr; + break; + } + + return UPM_SUCCESS; +} + +void bma250e_uninstall_isr(const bma250e_context dev, + BMA250E_INTERRUPT_PINS_T intr) +{ + assert(dev != NULL); + + switch (intr) + { + case BMA250E_INTERRUPT_INT1: + if (dev->gpio1) + { + mraa_gpio_isr_exit(dev->gpio1); + mraa_gpio_close(dev->gpio1); + dev->gpio1 = NULL; + } + break; + + case BMA250E_INTERRUPT_INT2: + if (dev->gpio2) + { + mraa_gpio_isr_exit(dev->gpio2); + mraa_gpio_close(dev->gpio2); + dev->gpio2 = NULL; + } + break; + } +} diff --git a/src/bma250e/bma250e.cxx b/src/bma250e/bma250e.cxx new file mode 100644 index 00000000..9575d5cc --- /dev/null +++ b/src/bma250e/bma250e.cxx @@ -0,0 +1,350 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016-2017 Intel Corporation. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "bma250e.hpp" + +using namespace upm; +using namespace std; + +// conversion from celsius to fahrenheit + +static float c2f(float c) +{ + return (c * (9.0 / 5.0) + 32.0); +} + +BMA250E::BMA250E(int bus, int addr, int cs) : + m_bma250e(bma250e_init(bus, addr, cs)) +{ + if (!m_bma250e) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_init() failed"); +} + +BMA250E::~BMA250E() +{ + bma250e_close(m_bma250e); +} + +void BMA250E::init(BMA250E_POWER_MODE_T pwr, BMA250E_RANGE_T range, + BMA250E_BW_T bw) +{ + if (bma250e_devinit(m_bma250e, pwr, range, bw)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_devinit() failed"); +} + +void BMA250E::update() +{ + if (bma250e_update(m_bma250e)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_update() failed"); +} + +void BMA250E::enableFIFO(bool useFIFO) +{ + bma250e_enable_fifo(m_bma250e, useFIFO); +} + +uint8_t BMA250E::readReg(uint8_t reg) +{ + return bma250e_read_reg(m_bma250e, reg); +} + +int BMA250E::readRegs(uint8_t reg, uint8_t *buffer, int len) +{ + int rv = bma250e_read_regs(m_bma250e, reg, buffer, len); + if (rv < 0) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_read_regs() failed"); + + return rv; +} + +void BMA250E::writeReg(uint8_t reg, uint8_t val) +{ + if (bma250e_write_reg(m_bma250e, reg, val)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_write_reg() failed"); +} + +uint8_t BMA250E::getChipID() +{ + return bma250e_get_chip_id(m_bma250e); +} + +void BMA250E::getAccelerometer(float *x, float *y, float *z) +{ + bma250e_get_accelerometer(m_bma250e, x, y, z); +} + +std::vector BMA250E::getAccelerometer() +{ + float v[3]; + + getAccelerometer(&v[0], &v[1], &v[2]); + return std::vector(v, v+3); +} + +float BMA250E::getTemperature(bool fahrenheit) +{ + float temperature = bma250e_get_temperature(m_bma250e); + if (fahrenheit) + return c2f(temperature); + else + return temperature; +} + +void BMA250E::reset() +{ + if (bma250e_reset(m_bma250e)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_reset() failed"); +} + +void BMA250E::setRange(BMA250E_RANGE_T range) +{ + if (bma250e_set_range(m_bma250e, range)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_set_range() failed"); +} + +void BMA250E::setBandwidth(BMA250E_BW_T bw) +{ + if (bma250e_set_bandwidth(m_bma250e, bw)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_set_power_mode() failed"); +} + +void BMA250E::setPowerMode(BMA250E_POWER_MODE_T power) +{ + if (bma250e_set_power_mode(m_bma250e, power)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_set_power_mode() failed"); +} + +void BMA250E::fifoSetWatermark(int wm) +{ + if (bma250e_fifo_set_watermark(m_bma250e, wm)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_fifo_set_watermark() failed"); +} + +void BMA250E::fifoConfig(BMA250E_FIFO_MODE_T mode, + BMA250E_FIFO_DATA_SEL_T axes) +{ + if (bma250e_fifo_config(m_bma250e, mode, axes)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_fifo_config() failed"); +} + +void BMA250E::setSelfTest(bool sign, bool amp, BMA250E_SELFTTEST_AXIS_T axis) +{ + if (bma250e_set_self_test(m_bma250e, sign, amp, axis)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_fifo_config() failed"); +} + +uint8_t BMA250E::getInterruptEnable0() +{ + return bma250e_get_interrupt_enable0(m_bma250e); +} + +void BMA250E::setInterruptEnable0(uint8_t bits) +{ + if (bma250e_set_interrupt_enable0(m_bma250e, bits)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_set_interrupt_enable0() failed"); +} + +uint8_t BMA250E::getInterruptEnable1() +{ + return bma250e_get_interrupt_enable1(m_bma250e); +} + +void BMA250E::setInterruptEnable1(uint8_t bits) +{ + if (bma250e_set_interrupt_enable1(m_bma250e, bits)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_set_interrupt_enable1() failed"); +} + +uint8_t BMA250E::getInterruptEnable2() +{ + return bma250e_get_interrupt_enable2(m_bma250e); +} + +void BMA250E::setInterruptEnable2(uint8_t bits) +{ + if (bma250e_set_interrupt_enable2(m_bma250e, bits)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_set_interrupt_enable2() failed"); +} + +uint8_t BMA250E::getInterruptMap0() +{ + return bma250e_get_interrupt_map0(m_bma250e); +} + +void BMA250E::setInterruptMap0(uint8_t bits) +{ + if (bma250e_set_interrupt_map0(m_bma250e, bits)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_set_interrupt_map0() failed"); +} + +uint8_t BMA250E::getInterruptMap1() +{ + return bma250e_get_interrupt_map1(m_bma250e); +} + +void BMA250E::setInterruptMap1(uint8_t bits) +{ + if (bma250e_set_interrupt_map1(m_bma250e, bits)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_set_interrupt_map1() failed"); +} + +uint8_t BMA250E::getInterruptMap2() +{ + return bma250e_get_interrupt_map2(m_bma250e); +} + +void BMA250E::setInterruptMap2(uint8_t bits) +{ + if (bma250e_set_interrupt_map2(m_bma250e, bits)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_set_interrupt_map2() failed"); +} + +uint8_t BMA250E::getInterruptSrc() +{ + return bma250e_get_interrupt_src(m_bma250e); +} + +void BMA250E::setInterruptSrc(uint8_t bits) +{ + if (bma250e_set_interrupt_src(m_bma250e, bits)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_set_interrupt_src() failed"); +} + +uint8_t BMA250E::getInterruptOutputControl() +{ + return bma250e_get_interrupt_output_control(m_bma250e); +} + +void BMA250E::setInterruptOutputControl(uint8_t bits) +{ + if (bma250e_set_interrupt_output_control(m_bma250e, bits)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_set_interrupt_output_control() failed"); +} + +void BMA250E::clearInterruptLatches() +{ + if (bma250e_clear_interrupt_latches(m_bma250e)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_clear_interrupt_latches() failed"); +} + +BMA250E_RST_LATCH_T BMA250E::getInterruptLatchBehavior() +{ + return bma250e_get_interrupt_latch_behavior(m_bma250e); +} + +void BMA250E::setInterruptLatchBehavior(BMA250E_RST_LATCH_T latch) +{ + if (bma250e_set_interrupt_latch_behavior(m_bma250e, latch)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_set_interrupt_latch_behavior() failed"); +} + +void BMA250E::enableRegisterShadowing(bool shadow) +{ + if (bma250e_enable_register_shadowing(m_bma250e, shadow)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_enable_register_shadowing() failed"); +} + +void BMA250E::enableOutputFiltering(bool filter) +{ + if (bma250e_enable_output_filtering(m_bma250e, filter)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_enable_output_filtering() failed"); +} + +uint8_t BMA250E::getInterruptStatus0() +{ + return bma250e_get_interrupt_status0(m_bma250e); +} + +uint8_t BMA250E::getInterruptStatus1() +{ + return bma250e_get_interrupt_status1(m_bma250e); +} + +uint8_t BMA250E::getInterruptStatus2() +{ + return bma250e_get_interrupt_status2(m_bma250e); +} + +uint8_t BMA250E::getInterruptStatus3Bits() +{ + return bma250e_get_interrupt_status3_bits(m_bma250e); +} + +BMA250E_ORIENT_T BMA250E::getInterruptStatus3Orientation() +{ + return bma250e_get_interrupt_status3_orientation(m_bma250e); +} + +void BMA250E::setLowPowerMode2() +{ + if (bma250e_set_low_power_mode2(m_bma250e)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_set_low_power_mode2() failed"); +} + +void BMA250E::installISR(BMA250E_INTERRUPT_PINS_T intr, int gpio, + mraa::Edge level, + void (*isr)(void *), void *arg) +{ + if (bma250e_install_isr(m_bma250e, intr, gpio, + (mraa_gpio_edge_t)level, isr, arg)) + throw std::runtime_error(string(__FUNCTION__) + + ": bma250e_install_isr() failed"); +} + +void BMA250E::uninstallISR(BMA250E_INTERRUPT_PINS_T intr) +{ + bma250e_uninstall_isr(m_bma250e, intr); +} diff --git a/src/bma250e/bma250e.h b/src/bma250e/bma250e.h new file mode 100644 index 00000000..0cdeb6c0 --- /dev/null +++ b/src/bma250e/bma250e.h @@ -0,0 +1,634 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2017 Intel Corporation. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +#include +#include + +#include +#include +#include + +#include "upm.h" + +#include "bma250e_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * @file bma250e.h + * @library bma250e + * @brief C API for the bma250e driver + * + * @include bma250e.c + */ + + /** + * Device context + */ + typedef struct _bma250e_context { + mraa_i2c_context i2c; + mraa_spi_context spi; + mraa_gpio_context gpioCS; // SPI CS pin + mraa_gpio_context gpio1; // intr 1 + mraa_gpio_context gpio2; // intr 2 + + // using SPI? + bool isSPI; + // use the FIFO? + bool useFIFO; + + // always stored in C + float temperature; + + // does this chip support the fifo? + bool fifoAvailable; + + // supported resolution + BMA250E_RESOLUTION_T resolution; + + // acc data + float accX; + float accY; + float accZ; + + // acceleration scaling + float accScale; + } *bma250e_context; + + /** + * BMA250E initialization. + * + * This device can support both I2C and SPI. For SPI, set the addr + * to -1, and specify a positive integer representing the Chip + * Select (CS) pin for the cs argument. If you are using a + * hardware CS pin (like edison with arduino breakout), then you + * can connect the proper pin to the hardware CS pin on your MCU + * and supply -1 for cs. The default operating mode is I2C. + * + * @param bus I2C or SPI bus to use. + * @param addr The address for this device, or -1 for SPI. + * @param cs The gpio pin to use for the SPI Chip Select. Use -1 + * for I2C or for SPI with a hardware controlled pin. + */ + bma250e_context bma250e_init(int bus, int addr, int cs); + + /** + * BMA250E Destructor. + * + * @param dev The device context. + */ + void bma250e_close(bma250e_context dev); + + /** + * Update the internal stored values from sensor data. + * + * @param dev The device context. + * @return UPM result. + */ + upm_result_t bma250e_update(const bma250e_context dev); + + /** + * Return the chip ID. + * + * @param dev The device context. + * @return The chip ID. + */ + uint8_t bma250e_get_chip_id(const bma250e_context dev); + + /** + * Return accelerometer data in gravities. bma250e_update() must + * have been called prior to calling this method. + * + * @param dev The device context. + * @param x Pointer to a floating point value that will have the + * current x component placed into it. + * @param y Pointer to a floating point value that will have the + * current y component placed into it. + * @param z Pointer to a floating point value that will have the + * current z component placed into it. + */ + void bma250e_get_accelerometer(const bma250e_context dev, + float *x, float *y, float *z); + + /** + * Return the current measured temperature. Note, this is not + * ambient temperature. bma250e_update() must have been called prior to + * calling this method. + * + * @param dev The device context. + * @return The temperature in degrees Celsius. + */ + float bma250e_get_temperature(const bma250e_context dev); + + /** + * Initialize the device and start operation. This function is + * called from bma250e_init(), so it will not need to be called by + * a user unless the device is reset. + * + * @param dev The device context. + * @param pwr One of the BMA250E_POWER_MODE_T values. + * @param range One of the BMA250E_RANGE_T values. + * @param bw One of the filtering BMA250E_BW_T values. + * @return UPM result. + */ + upm_result_t bma250e_devinit(const bma250e_context dev, + BMA250E_POWER_MODE_T pwr, + BMA250E_RANGE_T range, + BMA250E_BW_T bw); + + /** + * Reset the device as if during a power on reset. All configured + * values are lost when this happens. You should call + * bma250e_devinit() afterwards, or at least perform the same + * initialization bma250e_devinit() does before continuing. + * + * @param dev The device context. + * @return UPM result. + */ + upm_result_t bma250e_reset(const bma250e_context dev); + + /** + * Set the acceleration scaling range. This device supports 2, 4, + * 8, and 16g ranges. + * + * @param dev The device context. + * @param range One of the BMA250E_RANGE_T values. + * @return UPM result. + */ + upm_result_t bma250e_set_range(const bma250e_context dev, + BMA250E_RANGE_T range); + + /** + * Set the output filtering bandwidth of the device. + * + * @param dev The device context. + * @param bw One of the BMA250E_BW_T values. + * @return UPM result. + */ + upm_result_t bma250e_set_bandwidth(const bma250e_context dev, + BMA250E_BW_T bw); + + /** + * Set the power mode of the device. Care must be taken when + * setting a low power or suspend mode. By default + * bma250e_devinit() calls bma250e_set_low_power_mode2() to ensure + * that if any of these modes are entered we can still talk to the + * device. The default low power mode is LPM1, which requires + * slowing down register writes, which we cannot support. + * bma250e_set_low_power_mode2() enables LPM2 which keeps the + * digital interface operational in low power or suspend modes. + * See the datasheet for details. + * + * In short, if you reset your device and don't call + * bma250e_devinit() or bma250e_set_low_power_mode2(), you could + * lose control of the device by calling this function with + * anything other than BMA250E_POWER_MODE_NORMAL. You've been + * warned :) + * + * @param dev The device context. + * @param power One of the BMA250E_POWER_MODE_T values. + * @return UPM result. + */ + upm_result_t bma250e_set_power_mode(const bma250e_context dev, + BMA250E_POWER_MODE_T power); + + /** + * Enable bma250e_update() to read from the FIFO rather than the + * accelerometer axis registers directly, if the device supports a + * FIFO. bma250e_devinit() enables this mode by default. An + * advantage to this mode that all axis data is sampled from the + * same timeslice. When reading directly from the accelerometer + * output registers, it's possible for one axis to be updated + * while another is being read, causing a temporal inconsistency. + * + * Using the FIFO removes this problem. + * + * @param dev The device context. + * @param useFIFO true to enable bma250e_update() to read from the FIFO. + * When false, update will read from the accelerometer output + * registers directly. + */ + void bma250e_enable_fifo(const bma250e_context dev, bool useFIFO); + + /** + * Set the FIFO watermark. When the watermark is reached an + * interrupt (if enabled) will be generated. + * + * @param dev The device context. + * @param wm The FIFO watermark to use. The maximum value is 63. + * @return UPM result. + */ + upm_result_t bma250e_fifo_set_watermark(const bma250e_context dev, int wm); + + /** + * Set the FIFO configuration. bma250e_devinit() uses the + * BMA250E_FIFO_MODE_BYPASS mode with axes set to + * BMA250E_FIFO_DATA_SEL_XYZ by default. + * + * @param dev The device context. + * @param mode One of the BMA250E_FIFO_MODE_T values. + * @param axes One of the BMA250E_FIFO_DATA_SEL_T values. + * @return UPM result. + */ + upm_result_t bma250e_fifo_config(const bma250e_context dev, + BMA250E_FIFO_MODE_T mode, + BMA250E_FIFO_DATA_SEL_T axes); + + /** + * Enable, disable, and configure the built in self test on a per + * axis basis. See the datasheet for details. + * + * @param sign True for a positive deflection, false for negative. + * @param amp True for a high deflection, false for a low deflection. + * @param axis One of the BMA250E_SELFTTEST_AXIS_T values. Note, + * only one axis at a time can be tested. Accelerometer output + * for other axes should be ignored. + * @return UPM result. + */ + upm_result_t bma250e_set_self_test(const bma250e_context dev, + bool sign, bool amp, + BMA250E_SELFTTEST_AXIS_T axis); + + /** + * Return the Interrupt Enables 0 register. These registers + * allow you to enable various interrupt conditions. See the + * datasheet for details. + * + * @param dev The device context. + * @return A bitmask of BMA250E_INT_EN_0_BITS_T bits. + */ + uint8_t bma250e_get_interrupt_enable0(const bma250e_context dev); + + /** + * Set the Interrupt Enables 0 register. See the datasheet for + * details. + * + * @param dev The device context. + * @param bits A bitmask of BMA250E_INT_EN_0_BITS_T bits. + * @return UPM result. + */ + upm_result_t bma250e_set_interrupt_enable0(const bma250e_context dev, + uint8_t bits); + + /** + * Return the Interrupt Enables 1 register. These registers + * allow you to enable various interrupt conditions. See the + * datasheet for details. + * + * @param dev The device context. + * @return A bitmask of BMA250E_INT_EN_1_BITS_T bits. + */ + uint8_t bma250e_get_interrupt_enable1(const bma250e_context dev); + + /** + * Set the Interrupt Enables 1 register. See the datasheet for + * details. + * + * @param dev The device context. + * @param bits A bitmask of BMA250E_INT_EN_1_BITS_T bits. + * @return UPM result. + */ + upm_result_t bma250e_set_interrupt_enable1(const bma250e_context dev, + uint8_t bits); + /** + * Return the Interrupt Enables 2 register. These registers + * allow you to enable various interrupt conditions. See the + * datasheet for details. + * + * @param dev The device context. + * @return A bitmask of BMA250E_INT_EN_2_BITS_T bits. + */ + uint8_t bma250e_get_interrupt_enable2(const bma250e_context dev); + + /** + * Set the Interrupt Enables 2 register. See the datasheet for + * details. + * + * @param dev The device context. + * @param bits A bitmask of BMA250E_INT_EN_2_BITS_T bits. + * @return UPM result. + */ + upm_result_t bma250e_set_interrupt_enable2(const bma250e_context dev, + uint8_t bits); + + /** + * Return the Interrupt Map 0 register. These registers allow you + * to map specific interrupts to the interrupt 1 or interrupt 2 + * pin. See the datasheet for details. + * + * @param dev The device context. + * @return A bitmask of BMA250E_INT_MAP_0_BITS_T bits. + */ + uint8_t bma250e_get_interrupt_map0(const bma250e_context dev); + + /** + * Set the Interrupt Map 0 register. These registers allow you + * to map specific interrupts to the interrupt 1 or interrupt 2 + * pin. See the datasheet for details. + * + * @param dev The device context. + * @param A bitmask of BMA250E_INT_MAP_0_BITS_T bits. + * @return UPM result. + */ + upm_result_t bma250e_set_interrupt_map0(const bma250e_context dev, + uint8_t bits); + + /** + * Return the Interrupt Map 1 register. See the datasheet for + * details. + * + * @param dev The device context. + * @return A bitmask of BMA250E_INT_MAP_1_BITS_T bits. + */ + uint8_t bma250e_get_interrupt_map1(const bma250e_context dev); + + /** + * Set the Interrupt Map 1 register. See the datasheet for + * details. + * + * @param dev The device context. + * @param A bitmask of BMA250E_INT_MAP_1_BITS_T bits. + * @return UPM result. + */ + upm_result_t bma250e_set_interrupt_map1(const bma250e_context dev, + uint8_t bits); + + /** + * Return the Interrupt Map 2 register. See the datasheet for + * details. + * + * @param dev The device context. + * @return A bitmask of BMA250E_INT_MAP_2_BITS_T bits. + */ + uint8_t bma250e_get_interrupt_map2(const bma250e_context dev); + + /** + * Set the Interrupt Map 2 register. See the datasheet for + * details. + * + * @param dev The device context. + * @param A bitmask of BMA250E_INT_MAP_2_BITS_T bits. + * @return UPM result. + */ + upm_result_t bma250e_set_interrupt_map2(const bma250e_context dev, + uint8_t bits); + + /** + * Return the Interrupt source register. This register allows + * determining where data comes from (filtered/unfiltered) for + * those interrupt sources where this is selectable. See the + * datasheet for details. + * + * @param dev The device context. + * @return A bitmask of BMA250E_INT_SRC_BITS_T bits. + */ + uint8_t bma250e_get_interrupt_src(const bma250e_context dev); + + /** + * Set the Interrupt source register. This register allows + * determining where data comes from (filtered/unfiltered) for + * those interrupt sources where this is selectable. See the + * datasheet for details. + * + * @param dev The device context. + * @param bits A bitmask of BMA250E_INT_SRC_BITS_T bits. + * @return UPM result. + */ + upm_result_t bma250e_set_interrupt_src(const bma250e_context dev, + uint8_t bits); + + /** + * Return the Interrupt output control register. This register + * allows determining the electrical characteristics of the 2 + * interrupt pins (open-drain/push-pull and level/edge + * triggering). See the datasheet for details. + * + * @param dev The device context. + * @return A bitmask of BMA250E_INT_OUT_CTRL_BITS_T bits. + */ + uint8_t bma250e_get_interrupt_output_control(const bma250e_context dev); + + /** + * Set the Interrupt output control register. This register + * allows determining the electrical characteristics of the 2 + * interrupt pins (open-drain/push-pull and level/edge + * triggering). See the datasheet for details. + * + * @param dev The device context. + * @param bits A bitmask of BMA250E_INT_OUT_CTRL_BITS_T bits. + * @return UPM result. + */ + upm_result_t bma250e_set_interrupt_output_control(const bma250e_context dev, + uint8_t bits); + + /** + * Clear all latched interrupts. See the datasheet for details. + * + * @param dev The device context. + * @return UPM result. + */ + upm_result_t bma250e_clear_interrupt_latches(const bma250e_context dev); + + /** + * Return the current interrupt latching behavior. See the + * datasheet for details. + * + * @param dev The device context. + * @return One of the BMA250E_RST_LATCH_T values. + */ + BMA250E_RST_LATCH_T bma250e_get_interrupt_latch_behavior( + const bma250e_context dev); + + /** + * Set the current interrupt latching behavior. See the datasheet + * for details. + * + * @param dev The device context. + * @param latch One of the BMA250E_RST_LATCH_T values. + * @return UPM result. + */ + upm_result_t bma250e_set_interrupt_latch_behavior( + const bma250e_context dev, + BMA250E_RST_LATCH_T latch); + + /** + * Return the interrupt status 0 register. These registers + * indicate which interrupts have been triggered. See the + * datasheet for details. + * + * @param dev The device context. + * @return a bitmask of BMA250E_INT_STATUS_0_BITS_T bits. + */ + uint8_t bma250e_get_interrupt_status0(const bma250e_context dev); + + /** + * Return the interrupt status 1 register. See the datasheet for + * details. + * + * @param dev The device context. + * @return a bitmask of BMA250E_INT_STATUS_1_BITS_T bits. + */ + uint8_t bma250e_get_interrupt_status1(const bma250e_context dev); + + /** + * Return the interrupt status 2 register. See the datasheet for + * details. + * + * @param dev The device context. + * @return a bitmask of BMA250E_INT_STATUS_2_BITS_T bits. + */ + uint8_t bma250e_get_interrupt_status2(const bma250e_context dev); + + /** + * Return the interrupt status 3 register bitfields. See the + * datasheet for details. The Orientation value is not returned + * by this function, see + * bma250e_get_interrupt_status3_orientation() for that + * information. + * + * @param dev The device context. + * @return a bitmask of BMA250E_INT_STATUS_3_BITS_T bits only. + */ + uint8_t bma250e_get_interrupt_status3_bits(const bma250e_context dev); + + /** + * Return the interrupt status 3 register Orientation value. See the + * datasheet for details. + * + * @param dev The device context. + * @return One of the BMA250E_ORIENT_T values. + */ + BMA250E_ORIENT_T bma250e_get_interrupt_status3_orientation( + const bma250e_context dev); + + /** + * Enable shadowing of the accelerometer output registers. When + * enabled, a read of an axis LSB register automatically locks the + * MSB register of that axis until it has been read. This is + * usually a good thing to have enabled. bma250e_devinit() enables + * this by default. If disabled, then it becomes possible for + * part of an axis value to change while another part is being + * read, causing inconsistent data. + * + * @param dev The device context. + * @param shadow true to enable axis register shadowing, false otherwise. + * @return UPM result. + */ + upm_result_t bma250e_enable_register_shadowing(const bma250e_context dev, + bool shadow); + + /** + * Enable filtering of the accelerometer axis data. + * bma250e_devinit() enables this by default. If disabled, then + * accelerometer data that is read will be raw and unfiltered + * (rated NC-17, mature audiences only). See the datasheet for + * details. + * + * @param dev The device context. + * @param filter true to enable filtering, false to disable. + * @return UPM result. + */ + upm_result_t bma250e_enable_output_filtering(const bma250e_context dev, + bool filter); + + /** + * Make sure low power mode config (LPM2) is set in case we later + * go into the low power or suspend power modes. LPM1 mode (the + * default) requires drastically slowed register writes which we + * cannot handle. + * + * @param dev The device context. + * @return UPM result. + */ + upm_result_t bma250e_set_low_power_mode2(const bma250e_context dev); + + /** + * install an interrupt handler. + * + * @param dev The device context. + * @param intr One of the BMA250E_INTERRUPT_PINS_T values + * specifying which interrupt pin you are installing. + * @param gpio GPIO pin to use as interrupt pin + * @param level The interrupt trigger level (one of mraa_gpio_edge_t + * values). Make sure that you have configured the interrupt pin + * properly for whatever level you choose. + * @param isr The interrupt handler, accepting a void * argument + * @param arg The argument to pass to the interrupt handler + * @return UPM result. + */ + upm_result_t bma250e_install_isr(const bma250e_context dev, + BMA250E_INTERRUPT_PINS_T intr, int gpio, + mraa_gpio_edge_t level, + void (*isr)(void *), void *arg); + + /** + * uninstall a previously installed interrupt handler + * + * @param dev The device context. + * @param intr One of the BMA250E_INTERRUPT_PINS_T values + * specifying which interrupt pin you are removing. + */ + void bma250e_uninstall_isr(const bma250e_context dev, + BMA250E_INTERRUPT_PINS_T intr); + + /** + * Read a register. + * + * @param dev The device context. + * @param reg The register to read. + * @return The value of the register. + */ + uint8_t bma250e_read_reg(const bma250e_context dev, uint8_t reg); + + /** + * Read contiguous registers into a buffer. + * + * @param dev The device context. + * @param buffer The buffer to store the results. + * @param len The number of registers to read. + * @return The number of bytes read, or -1 on error. + */ + int bma250e_read_regs(const bma250e_context dev, uint8_t reg, + uint8_t *buffer, int len); + + /** + * Write to a register. + * + * @param dev The device context. + * @param reg The register to write to. + * @param val The value to write. + * @return UPM result. + */ + upm_result_t bma250e_write_reg(const bma250e_context dev, + uint8_t reg, uint8_t val); + + +#ifdef __cplusplus +} +#endif diff --git a/src/bma250e/bma250e.hpp b/src/bma250e/bma250e.hpp new file mode 100644 index 00000000..2ae1c73b --- /dev/null +++ b/src/bma250e/bma250e.hpp @@ -0,0 +1,586 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016-2017 Intel Corporation. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +#include +#include + +#include +#include "bma250e.h" + +namespace upm { + + /** + * @library bma250e + * @sensor bma250e + * @comname Digital Triaxial Acceleration Sensor + * @type accelerometer + * @man bosch + * @con i2c spi gpio + * @web https://www.bosch-sensortec.com/bst/products/all_products/bma250e + * + * @brief API for the BMA250E 10 bit Triaxial Accelerometer + * + * The BMA250E is a triaxial, low-g acceleration sensor with digital + * output for consumer applications. It allows measurements of + * acceleration in three perpendicular axes. An evaluation circuitry + * (ASIC) converts the output of a micromechanical + * acceleration-sensing structure (MEMS) that works according to the + * differential capacitance principle. + * + * Not all functionality of this chip has been implemented in this + * driver, however all the pieces are present to add any desired + * functionality. This driver supports both I2C (default) and SPI + * operation. + * + * This driver attempts to support verious flavors of this chip, + * such as the version on the BMX050, BMI050 (chipid 0xfa) and the + * version on the bmc050 (chipid 0x03). Not all functionality is + * appropriate, or even present on all chips. Consult the relevant + * datasheets. + * + * This device requires 3.3v operation. + * + * @snippet bma250e.cxx Interesting + */ + + class BMA250E { + public: + + /** + * BMA250E constructor. + * + * This device can support both I2C and SPI. For SPI, set the addr + * to -1, and specify a positive integer representing the Chip + * Select (CS) pin for the cs argument. If you are using a + * hardware CS pin (like edison with arduino breakout), then you + * can connect the proper pin to the hardware CS pin on your MCU + * and supply -1 for cs. The default operating mode is I2C. + * + * @param bus I2C or SPI bus to use. + * @param addr The address for this device. -1 for SPI. + * @param cs The gpio pin to use for the SPI Chip Select. -1 for + * I2C or for SPI with a hardware controlled pin. + * @throws std::runtime_error on initialization failure. + */ + BMA250E(int bus=BMA250E_DEFAULT_I2C_BUS, + int addr=BMA250E_DEFAULT_ADDR, + int cs=-1); + + /** + * BMA250E Destructor. + */ + ~BMA250E(); + + /** + * Update the internal stored values from sensor data. + * + * @throws std::runtime_error on failure. + */ + void update(); + + /** + * Return the chip ID. + * + * @return The chip ID. + */ + uint8_t getChipID(); + + /** + * Return accelerometer data in gravities. update() must have + * been called prior to calling this method. + * + * @param x Pointer to a floating point value that will have the + * current x component placed into it. + * @param y Pointer to a floating point value that will have the + * current y component placed into it. + * @param z Pointer to a floating point value that will have the + * current z component placed into it. + */ + void getAccelerometer(float *x, float *y, float *z); + + /** + * Return accelerometer data in gravities in the form of a + * floating point vector. update() must have been called + * prior to calling this method. + * + * @return A floating point vector containing x, y, and z in + * that order. + */ + std::vector getAccelerometer(); + + /** + * Return the current measured temperature. Note, this is not + * ambient temperature. update() must have been called prior to + * calling this method. + * + * @param fahrenheit true to return data in Fahrenheit, false for + * Celicus. Celsius is the default. + * @return The temperature in degrees Celsius or Fahrenheit. + */ + float getTemperature(bool fahrenheit=false); + + /** + * Initialize the device and start operation. This function is + * called from the constructor so will not typically need to be + * called by a user unless the device is reset. + * + * @param pwr One of the BMA250E_POWER_MODE_T values. The default is + * BMA250E_POWER_MODE_NORMAL. + * @param range One of the BMA250E_RANGE_T values. The default is + * BMA250E_RANGE_2G. + * @param bw One of the filtering BMA250E_BW_T values. The default is + * BMA250E_BW_250. + * @throws std::runtime_error on failure. + */ + void init(BMA250E_POWER_MODE_T pwr=BMA250E_POWER_MODE_NORMAL, + BMA250E_RANGE_T range=BMA250E_RANGE_2G, + BMA250E_BW_T bw=BMA250E_BW_250); + + /** + * Reset the device as if during a power on reset. All configured + * values are lost when this happens. You should call init() + * afterwards, or at least perform the same initialization init() + * does before continuing. + * + * @throws std::runtime_error on failure. + */ + void reset(); + + /** + * Set the acceleration scaling range. This device supports 2, 4, + * 8, and 16g ranges. + * + * @param range One of the BMA250E_RANGE_T values. + * @throws std::runtime_error on failure. + */ + void setRange(BMA250E_RANGE_T range); + + /** + * Set the output filtering bandwidth of the device. + * + * @param bw One of the BMA250E_BW_T values. + * @throws std::runtime_error on failure. + */ + void setBandwidth(BMA250E_BW_T bw); + + /** + * Set the power mode of the device. Care must be taken when + * setting a low power or suspend mode. By default init() calls + * setLowPowerMode2() to ensure that if any of these modes are + * entered we can still talk to the device. The default low power + * mode is LPM1, which requires slowing down register writes, + * which we cannot support. setLowPowerMode2() enables LPM2 which + * keeps the digital interface operational in low power or suspend + * modes. See the datasheet for details. + * + * So if you reset your device and don't call init() or + * setLowPowerMode2(), you could lose control of the device by + * calling this function with anything other than + * POWER_MODE_NORMAL. You've been warned :) + * + * @param power One of the BMA250E_POWER_MODE_T values. + * @throws std::runtime_error on failure. + */ + void setPowerMode(BMA250E_POWER_MODE_T power); + + /** + * Enable update() to read from the FIFO rather than the + * acceleration axis registers directly. init() enables this mode + * by default if the chip variant supports a FIFO. An advantage + * to this mode that all axis data is sampled from the same + * timeslice. When reading directly from the acceleration output + * registers, it's possible for one axis to be updated while + * another is being read, causing a temporal anomaly that even + * Captain Picard can't resolve. If there is no FIFO present, + * this call is ignored. + * + * Using the FIFO removes this problem. + * + * @param useFIFO True to enable update() to read from the FIFO. + * When false, update will read from the acceleration output + * registers directly. + */ + void enableFIFO(bool useFIFO); + + /** + * Set the FIFO watermark. When the watermark is reached an + * interrupt (if enabled) will be generated. If there is no FIFO + * present, this call is ignored. + * + * @param wm The FIFO watermark to use. The maximum value is 63. + * @throws std::runtime_error on failure. + */ + void fifoSetWatermark(int wm); + + /** + * Set the FIFO configuration. init() uses the FIFO_MODE_BYPASS + * mode with axes set to FIFO_DATA_SEL_XYZ by default. If there + * is no FIFO present, this call is ignored. + * + * @param mode One of the BMA250E_FIFO_MODE_T values. + * @param axes One of the BMA250E_FIFO_DATA_SEL_T values. + * @throws std::runtime_error on failure. + */ + void fifoConfig(BMA250E_FIFO_MODE_T mode, + BMA250E_FIFO_DATA_SEL_T axes); + + /** + * Enable, disable, and configure the built in self test on a per + * axis basis. See the datasheet for details. + * + * @param sign True for a positive deflection, false for negative + * @param amp True for a high deflection, false for a low deflection + * @param axis One of the BMA250E_SELFTTEST_AXIS_T values. + * Note, only one axis at a time can be tested. Accelerometer + * output for other axes should be ignored. + * @throws std::runtime_error on failure. + */ + void setSelfTest(bool sign, bool amp, BMA250E_SELFTTEST_AXIS_T axis); + + /** + * Return the Interrupt Enables 0 register. These registers + * allow you to enable various interrupt conditions. See the + * datasheet for details. + * + * @return A bitmask of BMA250E_INT_EN_0_BITS_T bits. + */ + uint8_t getInterruptEnable0(); + + /** + * Set the Interrupt Enables 0 register. See the datasheet for + * details. + * + * @param bits A bitmask of BMA250E_INT_EN_0_BITS_T bits. + * @throws std::runtime_error on failure. + */ + void setInterruptEnable0(uint8_t bits); + + /** + * Return the Interrupt Enables 1 register. See the datasheet for + * details. + * + * @return A bitmask of BMA250E_INT_EN_1_BITS_T bits. + */ + uint8_t getInterruptEnable1(); + + /** + * Set the Interrupt Enables 1 register. See the datasheet for + * details. + * + * @param bits A bitmask of BMA250E_INT_EN_1_BITS_T bits. + * @throws std::runtime_error on failure. + */ + void setInterruptEnable1(uint8_t bits); + + /** + * Return the Interrupt Enables 2 register. See the datasheet for + * details. + * + * @return A bitmask of BMA250E_INT_EN_2_BITS_T bits. + */ + uint8_t getInterruptEnable2(); + + /** + * Set the Interrupt Enables 2 register. See the datasheet for + * details. + * + * @param bits A bitmask of BMA250E_INT_EN_2_BITS_T bits. + * @throws std::runtime_error on failure. + */ + void setInterruptEnable2(uint8_t bits); + + /** + * Return the Interrupt Map 0 register. These registers allow you + * to map specific interrupts to the interrupt 1 or interrupt 2 + * pin. See the datasheet for details. + * + * @return A bitmask of BMA250E_INT_MAP_0_BITS_T bits. + */ + uint8_t getInterruptMap0(); + + /** + * Set the Interrupt Map 0 register. These registers allow you + * to map specific interrupts to the interrupt 1 or interrupt 2 + * pin. See the datasheet for details. + * + * @param A bitmask of BMA250E_INT_MAP_0_BITS_T bits. + * @throws std::runtime_error on failure. + */ + void setInterruptMap0(uint8_t bits); + + /** + * Return the Interrupt Map 1 register. See the datasheet for + * details. + * + * @return A bitmask of BMA250E_INT_MAP_1_BITS_T bits. + */ + uint8_t getInterruptMap1(); + + /** + * Set the Interrupt Map 1 register. See the datasheet for + * details. + * + * @param A bitmask of BMA250E_INT_MAP_1_BITS_T bits. + * @throws std::runtime_error on failure. + */ + void setInterruptMap1(uint8_t bits); + + /** + * Return the Interrupt Map 2 register. See the datasheet for + * details. + * + * @return A bitmask of BMA250E_INT_MAP_2_BITS_T bits. + */ + uint8_t getInterruptMap2(); + + /** + * Set the Interrupt Map 2 register. See the datasheet for + * details. + * + * @param A bitmask of BMA250E_INT_MAP_2_BITS_T bits. + * @throws std::runtime_error on failure. + */ + void setInterruptMap2(uint8_t bits); + + /** + * Return the Interrupt source register. This register allows + * determining where data comes from (filtered/unfiltered) for + * those interrupt sources where this is selectable. See the + * datasheet for details. + * + * @return A bitmask of BMA250E_INT_SRC_BITS_T bits. + */ + uint8_t getInterruptSrc(); + + /** + * Set the Interrupt source register. This register allows + * determining where data comes from (filtered/unfiltered) for + * those interrupt sources where this is selectable. See the + * datasheet for details. + * + * @param bits A bitmask of BMA250E_INT_SRC_BITS_T bits. + * @throws std::runtime_error on failure. + */ + void setInterruptSrc(uint8_t bits); + + /** + * Return the Interrupt output control register. This register + * allows determining the electrical characteristics of the 2 + * interrupt pins (open-drain/push-pull and level/edge + * triggering). See the datasheet for details. + * + * @return A bitmask of BMA250E_INT_OUT_CTRL_BITS_T bits. + */ + uint8_t getInterruptOutputControl(); + + /** + * Set the Interrupt output control register. This register + * allows determining the electrical characteristics of the 2 + * interrupt pins (open-drain/push-pull and level/edge + * triggering). See the datasheet for details. + * + * @param bits A bitmask of BMA250E_INT_OUT_CTRL_BITS_T bits. + * @throws std::runtime_error on failure. + */ + void setInterruptOutputControl(uint8_t bits); + + /** + * Clear all latched interrupts. See the datasheet for details. + * + * @throws std::runtime_error on failure. + */ + void clearInterruptLatches(); + + /** + * Return the current interrupt latching behavior. See the + * datasheet for details. + * + * @return One of the BMA250E_RST_LATCH_T values. + */ + BMA250E_RST_LATCH_T getInterruptLatchBehavior(); + + /** + * Set the current interrupt latching behavior. See the datasheet + * for details. + * + * @param latch One of the BMA250E_RST_LATCH_T values. + * @throws std::runtime_error on failure. + */ + void setInterruptLatchBehavior(BMA250E_RST_LATCH_T latch); + + /** + * Return the interrupt status 0 register. These registers + * indicate which interrupts have been triggered. See the + * datasheet for details. + * + * @return A bitmask of BMA250E_INT_STATUS_0_BITS_T bits. + */ + uint8_t getInterruptStatus0(); + + /** + * Return the interrupt status 1 register. See the datasheet for + * details. + * + * @return A bitmask of BMA250E_INT_STATUS_1_BITS_T bits. + */ + uint8_t getInterruptStatus1(); + + /** + * Return the interrupt status 2 register. See the datasheet for + * details. + * + * @return A bitmask of BMA250E_INT_STATUS_2_BITS_T bits. + */ + uint8_t getInterruptStatus2(); + + /** + * Return the interrupt status 3 register bitfields. See the + * datasheet for details. The Orientation value is not returned by + * this function, see getInterruptStatus3Orientation() for that + * information. + * + * @return A bitmask of BMA250E_INT_STATUS_3_BITS_T bits ONLY. + */ + uint8_t getInterruptStatus3Bits(); + + /** + * Return the interrupt status 3 register Orientation value. See the + * datasheet for details. + * + * @return One of the BMA250E_ORIENT_T values. + */ + BMA250E_ORIENT_T getInterruptStatus3Orientation(); + + /** + * Enable shadowing of the accelerometer output registers. When + * enabled, a read of an axis LSB register automatically locks the + * MSB register of that axis until it has been read. This is + * usually a good thing to have enabled. init() enables this by + * default. If disabled, then it becomes possible for part of an + * axis value to change while another part is being read, causing + * inconsistent data. + * + * @param shadow True to enable axis register shadowing, false + * otherwise. + * @throws std::runtime_error on failure. + */ + void enableRegisterShadowing(bool shadow); + + /** + * Enable filtering of the accelerometer axis data. init() + * enables this by default. If disabled, then accelerometer data + * that is read will be raw and unfiltered (rated R). See the + * datasheet for details. + * + * @param filter True to enable filtering, false to disable. + * @throws std::runtime_error on failure. + */ + void enableOutputFiltering(bool filter); + + /** + * Make sure low power mode config (LPM2) is set in case we later + * go into the low power or suspend power modes. LPM1 mode (the + * default) requires drastically slowed register writes which we + * cannot handle. + * + * @throws std::runtime_error on failure. + */ + void setLowPowerMode2(); + + +#if defined(SWIGJAVA) || defined(JAVACALLBACK) + void installISR(BMA250E_INTERRUPT_PINS_T intr, int gpio, + mraa::Edge level, jobject runnable) + { + installISR(intr, gpio, level, mraa_java_isr_callback, runnable); + } +#else + /** + * install an interrupt handler. + * + * @param intr One of the BMA250E_INTERRUPT_PINS_T values + * specifying which interrupt pin you are installing. + * @param gpio GPIO pin to use as interrupt pin. + * @param level The interrupt trigger level (one of mraa::Edge + * values). Make sure that you have configured the interrupt pin + * properly for whatever level you choose. + * @param isr The interrupt handler, accepting a void * argument. + * @param arg The argument to pass the the interrupt handler. + * @throws std::runtime_error on failure. + */ + void installISR(BMA250E_INTERRUPT_PINS_T intr, int gpio, + mraa::Edge level, + void (*isr)(void *), void *arg); +#endif + + /** + * uninstall a previously installed interrupt handler + * + * @param intr One of the BMA250E_INTERRUPT_PINS_T values + * specifying which interrupt pin you are removing. + */ + void uninstallISR(BMA250E_INTERRUPT_PINS_T intr); + + /** + * Read a register. + * + * @param reg The register to read. + * @return The value of the register. + */ + uint8_t readReg(uint8_t reg); + + /** + * Read contiguous registers into a buffer. + * + * @param buffer The buffer to store the results. + * @param len The number of registers to read. + * @return The number of bytes read. + * @throws std::runtime_error on failure. + */ + int readRegs(uint8_t reg, uint8_t *buffer, int len); + + /** + * Write to a register. + * + * @param reg The register to write to. + * @param val The value to write. + * @throws std::runtime_error on failure. + */ + void writeReg(uint8_t reg, uint8_t val); + + protected: + bma250e_context m_bma250e; + + private: + // Adding a private function definition for java bindings +#if defined(SWIGJAVA) || defined(JAVACALLBACK) + void installISR(BMA250E_INTERRUPT_PINS_T intr, int gpio, + mraa::Edge level, + void (*isr)(void *), void *arg); +#endif + }; +} diff --git a/src/bma250e/bma250e_defs.h b/src/bma250e/bma250e_defs.h new file mode 100644 index 00000000..4a4e33b6 --- /dev/null +++ b/src/bma250e/bma250e_defs.h @@ -0,0 +1,932 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2017 Intel Corporation. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#define BMA250E_DEFAULT_I2C_BUS 0 +#define BMA250E_DEFAULT_SPI_BUS 0 +#define BMA250E_DEFAULT_ADDR 0x18 + +// special reset byte +#define BMA250E_RESET_BYTE 0xb6 + + // NOTE: Reserved registers must not be written into. Reading + // from them may return indeterminate values. Registers + // containing reserved bitfields must be written as 0. Reading + // reserved bitfields may return indeterminate values. + + /** + * BMA250E registers + */ + typedef enum { + BMA250E_REG_CHIP_ID = 0x00, + + // 0x01 reserved + + BMA250E_REG_ACCD_X_LSB = 0x02, + BMA250E_REG_ACCD_X_MSB = 0x03, + BMA250E_REG_ACCD_Y_LSB = 0x04, + BMA250E_REG_ACCD_Y_MSB = 0x05, + BMA250E_REG_ACCD_Z_LSB = 0x06, + BMA250E_REG_ACCD_Z_MSB = 0x07, + + BMA250E_REG_TEMP = 0x08, + + BMA250E_REG_INT_STATUS_0 = 0x09, + BMA250E_REG_INT_STATUS_1 = 0x0a, + BMA250E_REG_INT_STATUS_2 = 0x0b, + BMA250E_REG_INT_STATUS_3 = 0x0c, + + // 0x0d reserved + + BMA250E_REG_FIFO_STATUS = 0x0e, + + BMA250E_REG_PMU_RANGE = 0x0f, + BMA250E_REG_PMU_BW = 0x10, + BMA250E_REG_PMU_LPW = 0x11, + BMA250E_REG_PMU_LOW_POWER = 0x12, + + BMA250E_REG_ACC_HBW = 0x13, + + BMA250E_REG_SOFTRESET = 0x14, + + // 0x15 reserved + + BMA250E_REG_INT_EN_0 = 0x16, + BMA250E_REG_INT_EN_1 = 0x17, + BMA250E_REG_INT_EN_2 = 0x18, + + BMA250E_REG_INT_MAP_0 = 0x19, + BMA250E_REG_INT_MAP_1 = 0x1a, + BMA250E_REG_INT_MAP_2 = 0x1b, + + // 0x1c-0x1d reserved + + BMA250E_REG_INT_SRC = 0x1e, + + // 0x1f reserved + + BMA250E_REG_INT_OUT_CTRL = 0x20, + BMA250E_REG_INT_RST_LATCH = 0x21, + + BMA250E_REG_INT_0 = 0x22, + BMA250E_REG_INT_1 = 0x23, + BMA250E_REG_INT_2 = 0x24, + BMA250E_REG_INT_3 = 0x25, + BMA250E_REG_INT_4 = 0x26, + BMA250E_REG_INT_5 = 0x27, + BMA250E_REG_INT_6 = 0x28, + BMA250E_REG_INT_7 = 0x29, + BMA250E_REG_INT_8 = 0x2a, + BMA250E_REG_INT_9 = 0x2b, + BMA250E_REG_INT_A = 0x2c, + BMA250E_REG_INT_B = 0x2d, + BMA250E_REG_INT_C = 0x2e, + BMA250E_REG_INT_D = 0x2f, + + BMA250E_REG_FIFO_CONFIG_0 = 0x30, + + // 0x31 reserved + + BMA250E_REG_PMU_SELFTEST = 0x32, + + BMA250E_REG_TRIM_NVM_CTRL = 0x33, + + BMA250E_REG_SPI3_WDT = 0x34, + + // 0x35 reserved + + BMA250E_REG_OFC_CTRL = 0x36, + BMA250E_REG_OFC_SETTING = 0x37, + + BMA250E_REG_OFC_OFFSET_X = 0x38, + BMA250E_REG_OFC_OFFSET_Y = 0x39, + BMA250E_REG_OFC_OFFSET_Z = 0x3a, + + BMA250E_REG_TRIM_GP0 = 0x3b, + BMA250E_REG_TRIM_GP1 = 0x3c, + + // 0x3d reserved + + BMA250E_REG_FIFO_CONFIG_1 = 0x3e, + BMA250E_REG_FIFO_DATA = 0x3f + + } BMA250E_REGS_T; + + /** + * REG_ACCD_*_LSB bits - handle X, Y, and Z LSB regs, for 10 bit + * resolution + */ + typedef enum { + BMA250E_ACCD10_LSB_NEW_DATA = 0x01, // data + // updated + // since last + // read + + // 0x02-0x20 reserved + + BMA250E_ACCD10_LSB0 = 0x40, // lower 2 + // bits of + // LSB data + BMA250E_ACCD10_LSB1 = 0x80, + _BMA250E_ACCD10_LSB_MASK = 3, + _BMA250E_ACCD10_LSB_SHIFT = 6 + } BMA250E_ACCD10_LSB_BITS_T; + + /** + * REG_ACCD_*_LSB bits - handle X, Y, and Z LSB regs, for 12 bit + * resolution + */ + typedef enum { + BMA250E_ACCD12_LSB_NEW_DATA = 0x01, // data + // updated + // since last + // read + + // 0x02-0x08 reserved + + BMA250E_ACCD12_LSB0 = 0x10, // lower 4 + // bits of + // LSB data + BMA250E_ACCD12_LSB1 = 0x20, + BMA250E_ACCD12_LSB2 = 0x40, + BMA250E_ACCD12_LSB3 = 0x80, + _BMA250E_ACCD12_LSB_MASK = 15, + _BMA250E_ACCD12_LSB_SHIFT = 4 + } BMA250E_ACCD12_LSB_BITS_T; + + /** + * REG_INT_STATUS_0 bits + */ + typedef enum { + BMA250E_INT_STATUS_0_LOW = 0x01, + BMA250E_INT_STATUS_0_HIGH = 0x02, + BMA250E_INT_STATUS_0_SLOPE = 0x04, + BMA250E_INT_STATUS_0_SLO_NOT_MOT = 0x08, + BMA250E_INT_STATUS_0_D_TAP = 0x10, + BMA250E_INT_STATUS_0_S_TAP = 0x20, + BMA250E_INT_STATUS_0_ORIENT = 0x40, + BMA250E_INT_STATUS_0_FLAT = 0x80 + } BMA250E_INT_STATUS_0_BITS_T; + + /** + * REG_INT_STATUS_1 bits + */ + typedef enum { + _BMA250E_INT_STATUS_1_RESERVED_BITS = 0x0f | 0x10, + // 0x01-0x10 reserved + BMA250E_INT_STATUS_1_FIFO_FULL = 0x20, + BMA250E_INT_STATUS_1_FIFO_WM = 0x40, + BMA250E_INT_STATUS_1_DATA = 0x80 // data ready int + } BMA250E_INT_STATUS_1_BITS_T; + + /** + * REG_INT_STATUS_2 bits + */ + typedef enum { + BMA250E_INT_STATUS_2_SLOPE_FIRST_X = 0x01, + BMA250E_INT_STATUS_2_SLOPE_FIRST_Y = 0x02, + BMA250E_INT_STATUS_2_SLOPE_FIRST_Z = 0x04, + BMA250E_INT_STATUS_2_SLOPE_SIGN = 0x08, + BMA250E_INT_STATUS_2_TAP_FIRST_X = 0x10, + BMA250E_INT_STATUS_2_TAP_FIRST_Y = 0x20, + BMA250E_INT_STATUS_2_TAP_FIRST_Z = 0x40, + BMA250E_INT_STATUS_2_TAP_SIGN = 0x80 + } BMA250E_INT_STATUS_2_BITS_T; + + /** + * REG_INT_STATUS_3 bits + */ + typedef enum { + BMA250E_INT_STATUS_3_HIGH_FIRST_X = 0x01, + BMA250E_INT_STATUS_3_HIGH_FIRST_Y = 0x02, + BMA250E_INT_STATUS_3_HIGH_FIRST_Z = 0x04, + BMA250E_INT_STATUS_3_HIGH_SIGN = 0x08, + + BMA250E_INT_STATUS_3_ORIENT0 = 0x10, + BMA250E_INT_STATUS_3_ORIENT1 = 0x20, + BMA250E_INT_STATUS_3_ORIENT2 = 0x40, + _BMA250E_INT_STATUS_3_ORIENT_MASK = 7, + _BMA250E_INT_STATUS_3_ORIENT_SHIFT = 4, + + BMA250E_INT_STATUS_3_FLAT = 0x80 + } INT_STATUS_3_BITS_T; + + /** + * INT_STATUS_3_ORIENT values + */ + typedef enum { + BMA250E_ORIENT_POTRAIT_UPRIGHT = 0, + BMA250E_ORIENT_POTRAIT_UPSIDE_DOWN = 1, + BMA250E_ORIENT_LANDSCAPE_LEFT = 2, + BMA250E_ORIENT_LANDSCAPE_RIGHT = 3, + } BMA250E_ORIENT_T; + + /** + * REG_FIFO_STATUS bits + */ + typedef enum { + BMA250E_FIFO_STATUS_FRAME_COUNTER0 = 0x01, + BMA250E_FIFO_STATUS_FRAME_COUNTER1 = 0x02, + BMA250E_FIFO_STATUS_FRAME_COUNTER2 = 0x04, + BMA250E_FIFO_STATUS_FRAME_COUNTER3 = 0x08, + BMA250E_FIFO_STATUS_FRAME_COUNTER4 = 0x10, + BMA250E_FIFO_STATUS_FRAME_COUNTER5 = 0x20, + BMA250E_FIFO_STATUS_FRAME_COUNTER6 = 0x40, + _BMA250E_FIFO_STATUS_FRAME_COUNTER_MASK = 127, + _BMA250E_FIFO_STATUS_FRAME_COUNTER_SHIFT = 0, + + BMA250E_FIFO_STATUS_FIFO_OVERRUN = 0x80 + } BMA250E_FIFO_STATUS_BITS_T; + + /** + * REG_PMU_RANGE bits + */ + typedef enum { + BMA250E_PMU_RANGE0 = 0x01, + BMA250E_PMU_RANGE1 = 0x02, + BMA250E_PMU_RANGE2 = 0x04, + BMA250E_PMU_RANGE3 = 0x08, + _BMA250E_PMU_RANGE_MASK = 15, + _BMA250E_PMU_RANGE_SHIFT = 0 + + // 0x10-0x80 reserved + } BMA250E_PMU_RANGE_BITS_T; + + /** + * PMU_RANGE (accelerometer g-range) values + */ + typedef enum { + BMA250E_RANGE_2G = 3, + BMA250E_RANGE_4G = 5, + BMA250E_RANGE_8G = 8, + BMA250E_RANGE_16G = 12 + } BMA250E_RANGE_T; + + /** + * REG_PMU_BW bits + */ + typedef enum { + BMA250E_PMU_BW0 = 0x01, + BMA250E_PMU_BW1 = 0x02, + BMA250E_PMU_BW2 = 0x04, + BMA250E_PMU_BW3 = 0x08, + BMA250E_PMU_BW4 = 0x10, + _BMA250E_PMU_BW_MASK = 31, + _BMA250E_PMU_BW_SHIFT = 0 + + // 0x20-0x80 reserved + } BMA250E_PMU_BW_BITS_T; + + /** + * PMU_BW (accelerometer filter bandwidth) values + */ + typedef enum { + BMA250E_BW_7_81 = 8, // 7.81 Hz + BMA250E_BW_15_63 = 9, + BMA250E_BW_31_25 = 10, + BMA250E_BW_62_5 = 11, + BMA250E_BW_125 = 12, + BMA250E_BW_250 = 13, + BMA250E_BW_500 = 14, + BMA250E_BW_1000 = 15 + } BMA250E_BW_T; + + /** + * REG_PMU_LPW bits + */ + typedef enum { + // 0x01 reserved + _BMA250E_PMU_LPW_RESERVED_MASK = 0x01, + + BMA250E_PMU_LPW_SLEEP_DUR0 = 0x02, // sleep dur + // in low + // power mode + BMA250E_PMU_LPW_SLEEP_DUR1 = 0x04, + BMA250E_PMU_LPW_SLEEP_DUR2 = 0x08, + BMA250E_PMU_LPW_SLEEP_DUR3 = 0x10, + _BMA250E_PMU_LPW_SLEEP_MASK = 15, + _BMA250E_PMU_LPW_SLEEP_SHIFT = 1, + + // These are separate bits, deep_suspend, lowpower_en and + // suspend (and if all 0, normal). Since only specific + // combinations are allowed, we will treat this as a 3 bit + // bitfield called POWER_MODE. + BMA250E_PMU_LPW_POWER_MODE0 = 0x20, // deep_suspend + BMA250E_PMU_LPW_POWER_MODE1 = 0x40, // lowpower_en + BMA250E_PMU_LPW_POWER_MODE2 = 0x80, // suspend + _BMA250E_PMU_LPW_POWER_MODE_MASK = 7, + _BMA250E_PMU_LPW_POWER_MODE_SHIFT = 5 + } BMA250E_PMU_LPW_BITS_T; + + /** + * SLEEP_DUR values + */ + typedef enum { + BMA250E_SLEEP_DUR_0_5 = 0, // 0.5ms + BMA250E_SLEEP_DUR_1 = 6, + BMA250E_SLEEP_DUR_2 = 7, + BMA250E_SLEEP_DUR_4 = 8, + BMA250E_SLEEP_DUR_6 = 9, + BMA250E_SLEEP_DUR_10 = 10, + BMA250E_SLEEP_DUR_25 = 11, + BMA250E_SLEEP_DUR_50 = 12, + BMA250E_SLEEP_DUR_100 = 13, + BMA250E_SLEEP_DUR_500 = 14, + BMA250E_SLEEP_DUR_1000 = 15 + } BMA250E_SLEEP_DUR_T; + + /** + * POWER_MODE values + */ + typedef enum { + BMA250E_POWER_MODE_NORMAL = 0, + BMA250E_POWER_MODE_DEEP_SUSPEND = 1, + BMA250E_POWER_MODE_LOW_POWER = 2, + BMA250E_POWER_MODE_SUSPEND = 4 + } BMA250E_POWER_MODE_T; + + /** + * REG_PMU_LOW_POWER bits + */ + typedef enum { + _BMA250E_LOW_POWER_RESERVED_BITS = 0x0f | 0x10 | 0x80, + + // 0x01-0x10 reserved + BMA250E_LOW_POWER_SLEEPTIMER_MODE = 0x20, + BMA250E_LOW_POWER_LOWPOWER_MODE = 0x40 // LPM1 or LPM2 mode. see DS. + // 0x80 reserved + } BMA250E_LOW_POWER_BITS_T; + + /** + * REG_ACC_HBW bits + */ + typedef enum { + _BMA250E_ACC_HBW_RESERVED_BITS = 0x0f | 0x10 | 0x20, + + // 0x01-0x20 reserved + BMA250E_ACC_HBW_SHADOW_DIS = 0x40, + BMA250E_ACC_HBW_DATA_HIGH_BW = 0x80 + } BMA250E_ACC_HBW_BITS_T; + + /** + * REG_INT_EN_0 bits + */ + typedef enum { + _BMA250E_INT_EN_0_RESERVED_BITS = 0x08, + + BMA250E_INT_EN_0_SLOPE_EN_X = 0x01, + BMA250E_INT_EN_0_SLOPE_EN_Y = 0x02, + BMA250E_INT_EN_0_SLOPE_EN_Z = 0x04, + + // 0x08 reserved + + BMA250E_INT_EN_0_D_TAP_EN = 0x10, + BMA250E_INT_EN_0_S_TAP_EN = 0x20, + BMA250E_INT_EN_0_ORIENT_EN = 0x40, + BMA250E_INT_EN_0_FLAT_EN = 0x80 + } BMA250E_INT_EN_0_BITS_T; + + /** + * REG_INT_EN_1 bits + */ + typedef enum { + _BMA250E_INT_EN_1_RESERVED_BITS = 0x80, + + BMA250E_INT_EN_1_HIGH_EN_X = 0x01, + BMA250E_INT_EN_1_HIGH_EN_Y = 0x02, + BMA250E_INT_EN_1_HIGH_EN_Z = 0x04, + BMA250E_INT_EN_1_LOW_EN = 0x08, + BMA250E_INT_EN_1_DATA_EN = 0x10, + BMA250E_INT_EN_1_INT_FFULL_EN = 0x20, // fifo full + BMA250E_INT_EN_1_INT_FWM_EN = 0x40 // fifo watermark + + // 0x80 reserved + } BMA250E_INT_EN_1_BITS_T; + + /** + * REG_INT_EN_2 bits + */ + typedef enum { + _BMA250E_INT_EN_2_RESERVED_BITS = 0xf0, + + BMA250E_INT_EN_2_SLO_NO_MOT_EN_X = 0x01, + BMA250E_INT_EN_2_SLO_NO_MOT_EN_Y = 0x02, + BMA250E_INT_EN_2_SLO_NO_MOT_EN_Z = 0x04, + BMA250E_INT_EN_2_SLO_NO_MOT_SEL = 0x08 + + // 0x10-0x80 reserved + } BMA250E_INT_EN_2_BITS_T; + + /** + * REG_INT_MAP_0 bits + */ + typedef enum { + BMA250E_INT_MAP_0_INT1_LOW = 0x01, + BMA250E_INT_MAP_0_INT1_HIGH = 0x02, + BMA250E_INT_MAP_0_INT1_SLOPE = 0x04, + BMA250E_INT_MAP_0_INT1_SLO_NO_MOT = 0x08, + BMA250E_INT_MAP_0_INT1_D_TAP = 0x10, + BMA250E_INT_MAP_0_INT1_S_TAP = 0x20, + BMA250E_INT_MAP_0_INT1_ORIENT = 0x40, + BMA250E_INT_MAP_0_INT1_FLAT = 0x80 + } BMA250E_INT_MAP_0_BITS_T; + + /** + * REG_INT_MAP_1 bits + */ + typedef enum { + _BMA250E_INT_MAP_1_INT1_RESERVED_BITS = 0x08 | 0x10, + + BMA250E_INT_MAP_1_INT1_DATA = 0x01, + BMA250E_INT_MAP_1_INT1_FWM = 0x02, + BMA250E_INT_MAP_1_INT1_FFULL = 0x04, + + // 0x08-0x10 reserved + + BMA250E_INT_MAP_1_INT2_FFULL = 0x20, + BMA250E_INT_MAP_1_INT2_FWM = 0x40, + BMA250E_INT_MAP_1_INT2_DATA = 0x80 + } BMA250E_INT_MAP_1_BITS_T; + + /** + * REG_INT_MAP_2 bits + */ + typedef enum { + BMA250E_INT_MAP_2_INT2_LOW = 0x01, + BMA250E_INT_MAP_2_INT2_HIGH = 0x02, + BMA250E_INT_MAP_2_INT2_SLOPE = 0x04, + BMA250E_INT_MAP_2_INT2_SLO_NO_MOT = 0x08, + BMA250E_INT_MAP_2_INT2_D_TAP = 0x10, + BMA250E_INT_MAP_2_INT2_S_TAP = 0x20, + BMA250E_INT_MAP_2_INT2_ORIENT = 0x40, + BMA250E_INT_MAP_2_INT2_FLAT = 0x80 + } BMA250E_INT_MAP_2_BITS_T; + + /** + * REG_INT_SRC bits + */ + typedef enum { + _BMA250E_INT_SRC_RESERVED_BITS = 0x40 | 0x80, + + BMA250E_INT_SRC_LOW = 0x01, + BMA250E_INT_SRC_HIGH = 0x02, + BMA250E_INT_SRC_SLO_NO_MOT = 0x04, + BMA250E_INT_SRC_SLOPE = 0x08, + BMA250E_INT_SRC_TAP = 0x10, + BMA250E_INT_SRC_DATA = 0x20 + + // 0x40-0x80 reserved + } BMA250E_INT_SRC_BITS_T; + + /** + * REG_INT_OUT_CTRL bits + */ + typedef enum { + _BMA250E_INT_OUT_CTRL_INT1_RESERVED_BITS = 0xf0, + + BMA250E_INT_OUT_CTRL_INT1_LVL = 0x01, // level or edge + BMA250E_INT_OUT_CTRL_INT1_OD = 0x02, // push-pull + // or open + // drain + BMA250E_INT_OUT_CTRL_INT2_LVL = 0x04, + BMA250E_INT_OUT_CTRL_INT2_OD = 0x08 + + // 0x10-0x80 reserved + } BMA250E_INT_OUT_CTRL_BITS_T; + + /** + * REG_INT_RST_LATCH bits + */ + typedef enum { + _BMA250E_INT_RST_LATCH_RESERVED_BITS = 0x10 | 0x20 | 0x40, + + BMA250E_INT_RST_LATCH0 = 0x01, + BMA250E_INT_RST_LATCH1 = 0x02, + BMA250E_INT_RST_LATCH2 = 0x04, + BMA250E_INT_RST_LATCH3 = 0x08, + _BMA250E_INT_RST_LATCH_MASK = 15, + _BMA250E_INT_RST_LATCH_SHIFT = 0, + + // 0x10-0x40 reserved + + BMA250E_INT_RST_LATCH_RESET_INT = 0x80 + } BMA250E_INT_RST_LATCH_BITS_T; + + /** + * RST_LATCH values + */ + typedef enum { + BMA250E_RST_LATCH_NON_LATCHED = 0, + BMA250E_RST_LATCH_TEMPORARY_250MS = 1, + BMA250E_RST_LATCH_TEMPORARY_500MS = 2, + BMA250E_RST_LATCH_TEMPORARY_1S = 3, + BMA250E_RST_LATCH_TEMPORARY_2S = 4, + BMA250E_RST_LATCH_TEMPORARY_4S = 5, + BMA250E_RST_LATCH_TEMPORARY_8S = 6, + BMA250E_RST_LATCH_LATCHED = 7, + + // 8 == non latched + + BMA250E_RST_LATCH_TEMPORARY_250US = 9, + BMA250E_RST_LATCH_TEMPORARY_500US = 10, + BMA250E_RST_LATCH_TEMPORARY_1MS = 11, + BMA250E_RST_LATCH_TEMPORARY_12_5MS = 12, + BMA250E_RST_LATCH_TEMPORARY_25MS = 13, + BMA250E_RST_LATCH_TEMPORARY_50MS = 14 + + // 15 == latched + } BMA250E_RST_LATCH_T; + + /** + * REG_INT_2 bits + */ + typedef enum { + BMA250E_INT_2_LOW_HY0 = 0x01, + BMA250E_INT_2_LOW_HY1 = 0x02, + _BMA250E_INT_2_LOW_HY_MASK = 3, + _BMA250E_INT_2_LOW_HY_SHIFT = 0, + + BMA250E_INT_2_LOW_MODE = 0x04, + + // 0x08-0x20 reserved + + BMA250E_INT_2_HIGH_HY0 = 0x40, + BMA250E_INT_2_HIGH_HY1 = 0x80, + _BMA250E_INT_2_HIGH_HY_MASK = 3, + _BMA250E_INT_2_HIGH_HY_SHIFT = 6 + } BMA250E_INT_2_BITS_T; + + /** + * REG_INT_5 bits + */ + typedef enum { + BMA250E_INT_5_SLOPE_DUR0 = 0x01, + BMA250E_INT_5_SLOPE_DUR1 = 0x02, + _BMA250E_INT_5_SLOPE_DUR_MASK = 3, + _BMA250E_INT_5_SLOPE_DUR_SHIFT = 0, + + BMA250E_INT_5_SLO_NO_MOT_DUR0 = 0x04, + BMA250E_INT_5_SLO_NO_MOT_DUR1 = 0x08, + BMA250E_INT_5_SLO_NO_MOT_DUR2 = 0x10, + BMA250E_INT_5_SLO_NO_MOT_DUR3 = 0x20, + BMA250E_INT_5_SLO_NO_MOT_DUR4 = 0x40, + BMA250E_INT_5_SLO_NO_MOT_DUR5 = 0x80, + _BMA250E_INT_5_SLO_NO_MOT_DUR_MASK = 63, + _BMA250E_INT_5_SLO_NO_MOT_DUR_SHIFT = 2 + } BMA250E_INT_5_BITS_T; + + /** + * REG_INT_8 bits + */ + typedef enum { + BMA250E_INT_8_TAP_DUR0 = 0x01, + BMA250E_INT_8_TAP_DUR1 = 0x02, + BMA250E_INT_8_TAP_DUR2 = 0x04, + _BMA250E_INT_8_TAP_DUR_MASK = 7, + _BMA250E_INT_8_TAP_DUR_SHIFT = 0, + + // 0x08-0x20 reserved + + BMA250E_INT_8_TAP_SHOCK = 0x40, + BMA250E_INT_8_TAP_QUIET = 0x80 + } BMA250E_INT_8_BITS_T; + + /** + * REG_INT_9 bits + */ + typedef enum { + BMA250E_INT_9_TAP_TH0 = 0x01, + BMA250E_INT_9_TAP_TH1 = 0x02, + BMA250E_INT_9_TAP_TH2 = 0x04, + BMA250E_INT_9_TAP_TH3 = 0x08, + BMA250E_INT_9_TAP_TH4 = 0x10, + _BMA250E_INT_5_TAP_TH_MASK = 31, + _BMA250E_INT_5_TAP_TH_SHIFT = 0, + + // 0x20 reserved + + BMA250E_INT_9_TAP_SAMP0 = 0x40, + BMA250E_INT_9_TAP_SAMP1 = 0x80, + BMA250E_INT_9_TAP_SAMP1_MASK = 3, + BMA250E_INT_9_TAP_SAMP1_SHIFT = 6 + } BMA250E_INT_9_BITS_T; + + /** + * REG_INT_A bits + */ + typedef enum { + BMA250E_INT_A_ORIENT_MODE0 = 0x01, + BMA250E_INT_A_ORIENT_MODE1 = 0x02, + _BMA250E_INT_A_ORIENT_MODE_MASK = 3, + _BMA250E_INT_A_ORIENT_MODE_SHIFT = 0, + + BMA250E_INT_A_ORIENT_BLOCKING0 = 0x04, + BMA250E_INT_A_ORIENT_BLOCKING1 = 0x08, + _BMA250E_INT_A_ORIENT_BLOCKING_MASK = 3, + _BMA250E_INT_A_ORIENT_BLOCKING_SHIFT = 2, + + BMA250E_INT_A_ORIENT_HYST0 = 0x10, + BMA250E_INT_A_ORIENT_HYST1 = 0x20, + BMA250E_INT_A_ORIENT_HYST2 = 0x40, + _BMA250E_INT_A_ORIENT_HYST_MASK = 7, + _BMA250E_INT_A_ORIENT_HYST_SHIFT = 4 + + // 0x80 reserved + } BMA250E_INT_A_BITS_T; + + /** + * INT_A_ORIENT_MODE values + */ + typedef enum { + BMA250E_ORIENT_MODE_SYMETRICAL = 0, + BMA250E_ORIENT_MODE_HIGH_ASYMETRICAL = 1, + BMA250E_ORIENT_MODE_LOW_ASYMETRICAL = 2 + } BMA250E_ORIENT_MODE_T; + + /** + * INT_A_ORIENT_BLOCKING values + */ + typedef enum { + BMA250E_ORIENT_BLOCKING_NONE = 0, + BMA250E_ORIENT_BLOCKING_THETA_ACC_1_5G = 1, + BMA250E_ORIENT_BLOCKING_THETA_ACC_0_2G_1_5G = 2, + BMA250E_ORIENT_BLOCKING_THETA_ACC_0_4G_1_5G = 3 + } BMA250E_ORIENT_BLOCKING_T; + + /** + * REG_INT_B bits + */ + typedef enum { + BMA250E_INT_B_ORIENT_THETA0 = 0x01, + BMA250E_INT_B_ORIENT_THETA1 = 0x02, + BMA250E_INT_B_ORIENT_THETA2 = 0x04, + BMA250E_INT_B_ORIENT_THETA3 = 0x08, + BMA250E_INT_B_ORIENT_THETA4 = 0x10, + BMA250E_INT_B_ORIENT_THETA5 = 0x20, + _BMA250E_INT_B_ORIENT_THETA_MASK = 63, + _BMA250E_INT_B_ORIENT_THETA_SHIFT = 0, + + BMA250E_INT_B_ORIENT_UD_EN = 0x40 + // 0x80 reserved + } BMA250E_INT_B_BITS_T; + + /** + * REG_INT_C bits + */ + typedef enum { + BMA250E_INT_B_FLAT_THETA0 = 0x01, + BMA250E_INT_B_FLAT_THETA1 = 0x02, + BMA250E_INT_B_FLAT_THETA2 = 0x04, + BMA250E_INT_B_FLAT_THETA3 = 0x08, + BMA250E_INT_B_FLAT_THETA4 = 0x10, + BMA250E_INT_B_FLAT_THETA5 = 0x20, + _BMA250E_INT_B_FLAT_THETA_MASK = 63, + _BMA250E_INT_B_FLAT_THETA_SHIFT = 0, + + // 0x40-0x80 reserved + } BMA250E_INT_C_BITS_T; + + /** + * REG_INT_D bits + */ + typedef enum { + BMA250E_INT_D_FLAT_HY0 = 0x01, + BMA250E_INT_D_FLAT_HY1 = 0x02, + BMA250E_INT_D_FLAT_HY2 = 0x04, + _BMA250E_INT_B_FLAT_HY_MASK = 7, + _BMA250E_INT_B_FLAT_HY_SHIFT = 0, + + // 0x08 reserved + + BMA250E_INT_D_FLAT_HOLD_TIME0 = 0x10, + BMA250E_INT_D_FLAT_HOLD_TIME1 = 0x20, + _BMA250E_INT_B_FLAT_HOLD_TIME_MASK = 3, + _BMA250E_INT_B_FLAT_HOLD_TIME_SHIFT = 4 + + // 0x40-0x80 reserved + } BMA250E_INT_D_BITS_T; + + /** + * REG_FIFO_CONFIG_0 bits + */ + typedef enum { + _BMA250E_FIFO_CONFIG_0_RESERVED_BITS = 0x80 | 0x40, + + BMA250E_FIFO_CONFIG_0_WATER_MARK0 = 0x01, + BMA250E_FIFO_CONFIG_0_WATER_MARK1 = 0x02, + BMA250E_FIFO_CONFIG_0_WATER_MARK2 = 0x04, + BMA250E_FIFO_CONFIG_0_WATER_MARK3 = 0x08, + BMA250E_FIFO_CONFIG_0_WATER_MARK4 = 0x10, + BMA250E_FIFO_CONFIG_0_WATER_MARK5 = 0x20, + _BMA250E_FIFO_CONFIG_0_WATER_MARK_MASK = 63, + _BMA250E_FIFO_CONFIG_0_WATER_MARK_SHIFT = 0 + } BMA250E_FIFO_CONFIG_0_BITS_T; + + /** + * REG_PMU_SELFTTEST bits + */ + typedef enum { + BMA250E_PMU_SELFTTEST_AXIS0 = 0x01, + BMA250E_PMU_SELFTTEST_AXIS1 = 0x02, + _BMA250E_PMU_SELFTTEST_AXIS_MASK = 3, + _BMA250E_PMU_SELFTTEST_AXIS_SHIFT = 0, + + BMA250E_PMU_SELFTTEST_SIGN = 0x04, + + // 0x08 reserved + + BMA250E_PMU_SELFTTEST_AMP = 0x10, + + // 0x20-0x80 reserved + } BMA250E_PMU_SELFTTEST_BITS_T; + + /** + * PMU_SELFTTEST_AXIS values + */ + typedef enum { + BMA250E_SELFTTEST_AXIS_NONE = 0, + BMA250E_SELFTTEST_AXIS_X = 1, + BMA250E_SELFTTEST_AXIS_Y = 2, + BMA250E_SELFTTEST_AXIS_Z = 3, + } BMA250E_SELFTTEST_AXIS_T; + + /** + * REG_TRIM_NVM_CTRL bits + */ + typedef enum { + BMA250E_TRIM_NVM_CTRL_NVM_PROG_MODE = 0x01, + BMA250E_TRIM_NVM_CTRL_NVM_PROG_TRIG = 0x02, + BMA250E_TRIM_NVM_CTRL_NVM_PROG_RDY = 0x04, + BMA250E_TRIM_NVM_CTRL_NVM_PROG_LOAD = 0x08, + + BMA250E_TRIM_NVM_CTRL_NVM_REMAIN0 = 0x10, + BMA250E_TRIM_NVM_CTRL_NVM_REMAIN1 = 0x20, + BMA250E_TRIM_NVM_CTRL_NVM_REMAIN2 = 0x40, + BMA250E_TRIM_NVM_CTRL_NVM_REMAIN3 = 0x80, + _BMA250E_TRIM_NVM_CTRL_NVM_REMAIN_MASK = 15, + _BMA250E_TRIM_NVM_CTRL_NVM_REMAIN_SHIFT = 4 + } BMA250E_TRIM_NVM_CTRL_BITS_T; + + /** + * REG_SPI3_WDT bits + */ + typedef enum { + _BMA250E_SPI3_WDT_RESERVED_BITS = 0xf0 | 0x08, + + BMA250E_SPI3_WDT_SPI3 = 0x01, // 3-wire SPI + // - NOT + // SUPPORTED + + BMA250E_SPI3_WDT_I2C_WDT_SEL = 0x02, + BMA250E_SPI3_WDT_I2C_WDT_EN = 0x04 + + // 0x08-0x80 reserved + } BMA250E_SPI3_WDT_BITS_T; + + /** + * REG_OFC_CTRL bits + */ + typedef enum { + BMA250E_OFC_CTRL_HP_X_EN = 0x01, + BMA250E_OFC_CTRL_HP_Y_EN = 0x02, + BMA250E_OFC_CTRL_HP_Z_EN = 0x04, + + // 0x08 reserved + + BMA250E_OFC_CTRL_CAL_RDY = 0x10, + + BMA250E_OFC_CTRL_CAL_TRIGGER0 = 0x20, + BMA250E_OFC_CTRL_CAL_TRIGGER1 = 0x40, + _BMA250E_OFC_CTRL_CAL_TRIGGER_MASK = 3, + _BMA250E_OFC_CTRL_CAL_TRIGGER_SHIFT = 5, + + BMA250E_OFC_CTRL_OFFSET_RESET = 0x80 + + } BMA250E_OFC_CTRL_BITS_T; + + /** + * OFC_CTRL_CAL_TRIGGER values + */ + typedef enum { + BMA250E_CAL_TRIGGER_NONE = 0, + BMA250E_CAL_TRIGGER_X = 1, + BMA250E_CAL_TRIGGER_Y = 2, + BMA250E_CAL_TRIGGER_Z = 3 + } BMA250E_CAL_TRIGGER_T; + + /** + * REG_OFC_SETTING bits + */ + typedef enum { + BMA250E_OFC_SETTING_CUT_OFF = 0x01, + + BMA250E_OFC_SETTING_OFFSET_TARGET_X0 = 0x02, + BMA250E_OFC_SETTING_OFFSET_TARGET_X1 = 0x04, + _BMA250E_OFC_SETTING_OFFSET_TARGET_X_MASK = 3, + _BMA250E_OFC_SETTING_OFFSET_TARGET_X_SHIFT = 1, + + BMA250E_OFC_SETTING_OFFSET_TARGET_Y0 = 0x08, + BMA250E_OFC_SETTING_OFFSET_TARGET_Y1 = 0x10, + _BMA250E_OFC_SETTING_OFFSET_TARGET_Y_MASK = 3, + _BMA250E_OFC_SETTING_OFFSET_TARGET_Y_SHIFT = 3, + + BMA250E_OFC_SETTING_OFFSET_TARGET_Z0 = 0x20, + BMA250E_OFC_SETTING_OFFSET_TARGET_Z1 = 0x40, + _BMA250E_OFC_SETTING_OFFSET_TARGET_Z_MASK = 3, + _BMA250E_OFC_SETTING_OFFSET_TARGET_Z_SHIFT = 5 + + // 0x80 reserved + } BMA250E_OFC_SETTING_BITS_T; + + /** + * OFC_SETTING_OFFSET_TARGET (for X, Y and Z axis) values + */ + typedef enum { + BMA250E_OFFSET_TARGET_0G = 0, + BMA250E_OFFSET_TARGET_PLUS_1G = 1, + BMA250E_OFFSET_TARGET_MINUS_1G = 2, + // 3 == 0G + } BMA250E_OFFSET_TARGET_T; + + /** + * REG_FIFO_CONFIG_1 bits + */ + typedef enum { + BMA250E_FIFO_CONFIG_1_FIFO_DATA_SEL0 = 0x01, + BMA250E_FIFO_CONFIG_1_FIFO_DATA_SEL1 = 0x02, + _BMA250E_FIFO_CONFIG_1_FIFO_DATA_SEL = 3, + _BMA250E_FIFO_CONFIG_1_FIFO_DATA_SHIFT = 0, + + // 0x04-0x20 reserved + + BMA250E_FIFO_CONFIG_1_FIFO_MODE0 = 0x40, + BMA250E_FIFO_CONFIG_1_FIFO_MODE1 = 0x80, + _BMA250E_FIFO_CONFIG_1_FIFO_MODE_MASK = 3, + _BMA250E_FIFO_CONFIG_1_FIFO_MODE_SHIFT = 5 + } BMA250E_FIFO_CONFIG_1_BITS_T; + + /** + * FIFO_DATA_SEL values + */ + typedef enum { + BMA250E_FIFO_DATA_SEL_XYZ = 0, + BMA250E_FIFO_DATA_SEL_X = 1, + BMA250E_FIFO_DATA_SEL_Y = 2, + BMA250E_FIFO_DATA_SEL_Z = 3 + } BMA250E_FIFO_DATA_SEL_T; + + /** + * FIFO_MODE values + */ + typedef enum { + BMA250E_FIFO_MODE_BYPASS = 0, + BMA250E_FIFO_MODE_FIFO = 1, + BMA250E_FIFO_MODE_STREAM = 2 + + // 3 == reserved (execute self-destruct :) + } BMA250E_FIFO_MODE_T; + + // interrupt selection for installISR() and uninstallISR() + typedef enum { + BMA250E_INTERRUPT_INT1, + BMA250E_INTERRUPT_INT2 + } BMA250E_INTERRUPT_PINS_T; + + // Different variants of this chip support different resolutions. + // The 0xf9 variant supports 10b, while the 0xfa variant (bmx050) + // supports 12 bits. + typedef enum { + BMA250E_RESOLUTION_10BITS, + BMA250E_RESOLUTION_12BITS + } BMA250E_RESOLUTION_T; + +#ifdef __cplusplus +} +#endif diff --git a/src/bma250e/bma250e_fti.c b/src/bma250e/bma250e_fti.c new file mode 100644 index 00000000..2f25dc4b --- /dev/null +++ b/src/bma250e/bma250e_fti.c @@ -0,0 +1,113 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2017 Intel Corporation. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "bma250e.h" +#include "upm_fti.h" + +/** + * This file implements the Function Table Interface (FTI) for this sensor + */ + +const char upm_bma250e_name[] = "BMA250E"; +const char upm_bma250e_description[] = "Triple Axis Digital Accelerometer"; +const upm_protocol_t upm_bma250e_protocol[] = {UPM_I2C, UPM_SPI, UPM_GPIO}; +const upm_sensor_t upm_bma250e_category[] = {UPM_ACCELEROMETER}; + +// forward declarations +const void* upm_bma250e_get_ft(upm_sensor_t sensor_type); +void* upm_bma250e_init_name(); +void upm_bma250e_close(void *dev); +upm_result_t upm_bma250e_get_value(void *dev, float *value, + upm_acceleration_u unit); + +const upm_sensor_descriptor_t upm_bma250e_get_descriptor() +{ + upm_sensor_descriptor_t usd; + usd.name = upm_bma250e_name; + usd.description = upm_bma250e_description; + usd.protocol_size = 3; + usd.protocol = upm_bma250e_protocol; + usd.category_size = 1; + usd.category = upm_bma250e_category; + return usd; +} + +static const upm_sensor_ft ft = +{ + .upm_sensor_init_name = &upm_bma250e_init_name, + .upm_sensor_close = &upm_bma250e_close, +}; + +static const upm_acceleration_ft aft = +{ + .upm_acceleration_get_value = &upm_bma250e_get_value +}; + +const void* upm_bma250e_get_ft(upm_sensor_t sensor_type) +{ + switch(sensor_type) + { + case UPM_SENSOR: + return &ft; + + case UPM_ACCELEROMETER: + return &aft; + + default: + return NULL; + } +} + +void* upm_bma250e_init_name() +{ + return NULL; +} + + +void upm_bma250e_close(void *dev) +{ + bma250e_close((bma250e_context)dev); +} + +upm_result_t upm_bma250e_get_value(void *dev, float *value, + upm_acceleration_u unit) +{ + if (bma250e_update((bma250e_context)dev)) + return UPM_ERROR_OPERATION_FAILED; + + // no conversion facility in place yet, so we don't do anything + // with units + + float x, y, z; + + bma250e_get_accelerometer(dev, &x, &y, &z); + + value[0] = x; + value[1] = y; + value[2] = z; + + return UPM_SUCCESS; +} diff --git a/src/bma250e/javaupm_bma250e.i b/src/bma250e/javaupm_bma250e.i new file mode 100644 index 00000000..daa85b12 --- /dev/null +++ b/src/bma250e/javaupm_bma250e.i @@ -0,0 +1,23 @@ +%module javaupm_bma250e +%include "../upm.i" +%include "typemaps.i" +%include "../upm_vectortypes.i" + +%ignore getAccelerometer(float *, float *, float *); + +%include "bma250e_defs.h" +%include "bma250e.hpp" +%{ + #include "bma250e.hpp" +%} + +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("javaupm_bma250e"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. \n" + e); + System.exit(1); + } + } +%} diff --git a/src/bma250e/jsupm_bma250e.i b/src/bma250e/jsupm_bma250e.i new file mode 100644 index 00000000..306c89e1 --- /dev/null +++ b/src/bma250e/jsupm_bma250e.i @@ -0,0 +1,14 @@ +%module jsupm_bma250e +%include "../upm.i" +%include "cpointer.i" +%include "../upm_vectortypes.i" + +/* Send "int *" and "float *" to JavaScript as intp and floatp */ +%pointer_functions(int, intp); +%pointer_functions(float, floatp); + +%include "bma250e_defs.h" +%include "bma250e.hpp" +%{ + #include "bma250e.hpp" +%} diff --git a/src/bma250e/pyupm_bma250e.i b/src/bma250e/pyupm_bma250e.i new file mode 100644 index 00000000..7539f05c --- /dev/null +++ b/src/bma250e/pyupm_bma250e.i @@ -0,0 +1,22 @@ +// Include doxygen-generated documentation +%include "pyupm_doxy2swig.i" +%module pyupm_bma250e +%include "../upm.i" +%include "cpointer.i" +%include "../upm_vectortypes.i" + +/* Send "int *" and "float *" to python as intp and floatp */ +%pointer_functions(int, intp); +%pointer_functions(float, floatp); + +%feature("autodoc", "3"); + +#ifdef DOXYGEN +%include "bma250e_doc.i" +#endif + +%include "bma250e_defs.h" +%include "bma250e.hpp" +%{ + #include "bma250e.hpp" +%}