diff --git a/examples/c++/lsm6ds3h.cxx b/examples/c++/lsm6ds3h.cxx new file mode 100644 index 00000000..55b8b5f5 --- /dev/null +++ b/examples/c++/lsm6ds3h.cxx @@ -0,0 +1,88 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 Intel Corporation. + * + * 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 "lsm6ds3h.hpp" + +using namespace std; + +int shouldRun = true; + +void sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + + +int main(int argc, char **argv) +{ + signal(SIGINT, sig_handler); +//! [Interesting] + + // Instantiate an LSM6DS3H using default I2C parameters + upm::LSM6DS3H sensor; + + // For SPI, bus 0, you would pass -1 as the address, and a valid pin + // for CS: LSM6DS3H(0, -1, 10); + + // now output data every 250 milliseconds + while (shouldRun) + { + float x, y, z; + + sensor.update(); + + sensor.getAccelerometer(&x, &y, &z); + cout << "Accelerometer x: " << x + << " y: " << y + << " z: " << z + << " g" + << endl; + + sensor.getGyroscope(&x, &y, &z); + cout << "Gyroscope x: " << x + << " y: " << y + << " z: " << z + << " dps" + << endl; + + // we show both C and F for temperature + cout << "Compensation Temperature: " << sensor.getTemperature() + << " C / " << sensor.getTemperature(true) << " F" + << endl; + + cout << endl; + + usleep(250000); + } + +//! [Interesting] + + cout << "Exiting..." << endl; + + return 0; +} diff --git a/examples/c/lsm6ds3h.c b/examples/c/lsm6ds3h.c new file mode 100644 index 00000000..971eb278 --- /dev/null +++ b/examples/c/lsm6ds3h.c @@ -0,0 +1,104 @@ +/* + * 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 "lsm6ds3h.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 LSM6DS3H instance using default i2c bus and address + lsm6ds3h_context sensor = lsm6ds3h_init(LSM6DS3H_DEFAULT_I2C_BUS, + LSM6DS3H_DEFAULT_I2C_ADDR, -1); +#elif defined(CONFIG_BOARD_ARDUINO_101) + // ARDUINO_101 (Quark core) must use SPI + // Instantiate a LSM6DS3H instance using default SPI bus and pin 10 as CS + lsm6ds3h_context sensor = lsm6ds3h_init(LSM6DS3H_DEFAULT_SPI_BUS, + -1, 10); +#else + // everything else use I2C by default + // Instantiate a LSM6DS3H instance using default i2c bus and address + lsm6ds3h_context sensor = lsm6ds3h_init(LSM6DS3H_DEFAULT_I2C_BUS, + LSM6DS3H_DEFAULT_I2C_ADDR, -1); +#endif + + if (!sensor) + { + printf("lsm6ds3h_init() failed.\n"); + return 1; + } + + // now output data every 250 milliseconds + while (shouldRun) + { + float x, y, z; + + if (lsm6ds3h_update(sensor)) + { + printf("lsm6ds3h_update() failed\n"); + lsm6ds3h_close(sensor); + return 1; + } + + lsm6ds3h_get_accelerometer(sensor, &x, &y, &z); + printf("Acceleration x: %f y: %f z: %f g\n", + x, y, z); + + lsm6ds3h_get_gyroscope(sensor, &x, &y, &z); + printf("Gyroscope x: %f y: %f z: %f dps\n", + x, y, z); + + printf("Compensation Temperature: %f C\n\n", + lsm6ds3h_get_temperature(sensor)); + + upm_delay_ms(250); + } + + printf("Exiting...\n"); + + lsm6ds3h_close(sensor); + +//! [Interesting] + + return 0; +} diff --git a/examples/java/CMakeLists.txt b/examples/java/CMakeLists.txt index 3437fd02..400b0cb2 100644 --- a/examples/java/CMakeLists.txt +++ b/examples/java/CMakeLists.txt @@ -191,6 +191,7 @@ add_example(LSM303D_Example lsm303d) add_example(VEML6070Sample veml6070) add_example(RN2903_Example rn2903) add_example(LIS2DS12_Example lis2ds12) +add_example(LSM6DS3H_Example lsm6ds3h) add_example_with_path(Jhd1313m1_lcdSample jhd1313m1 jhd1313m1) add_example_with_path(Jhd1313m1Sample jhd1313m1 jhd1313m1) diff --git a/examples/java/LSM6DS3H_Example.java b/examples/java/LSM6DS3H_Example.java new file mode 100644 index 00000000..b705cb09 --- /dev/null +++ b/examples/java/LSM6DS3H_Example.java @@ -0,0 +1,71 @@ +/* + * Author: Jon Trulson + * 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 + * "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. + */ + +import upm_lsm6ds3h.*; + +public class LSM6DS3H_Example +{ + public static void main(String[] args) throws InterruptedException + { +// ! [Interesting] + + // Instantiate a LSM6DS3H instance using default i2c bus and address + LSM6DS3H sensor = new LSM6DS3H(); + + // For SPI, bus 0, you would pass -1 as the address, and a + // valid pin for CS: + // LSM6DS3H(0, -1, 10); + + while (true) + { + // update our values from the sensor + sensor.update(); + + floatVector data = sensor.getAccelerometer(); + + System.out.println("Accelerometer x: " + data.get(0) + + " y: " + data.get(1) + + " z: " + data.get(2) + + " g"); + + data = sensor.getGyroscope(); + + System.out.println("Gyroscope x: " + data.get(0) + + " y: " + data.get(1) + + " z: " + data.get(2) + + " dps"); + + System.out.println("Compensation Temperature: " + + sensor.getTemperature() + + " C / " + + sensor.getTemperature(true) + + " F"); + + System.out.println(); + Thread.sleep(250); + } + +// ! [Interesting] + } +} diff --git a/examples/javascript/lsm6ds3h.js b/examples/javascript/lsm6ds3h.js new file mode 100644 index 00000000..7e278f84 --- /dev/null +++ b/examples/javascript/lsm6ds3h.js @@ -0,0 +1,72 @@ +/* + * Author: Jon Trulson + * 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 + * "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. + */ + +var sensorObj = require('jsupm_lsm6ds3h'); + +// Instantiate a LSM6DS3H instance using default i2c bus and address +var sensor = new sensorObj.LSM6DS3H(); + +// For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS: +// LSM6DS3H(0, -1, 10); + +// now output data every 250 milliseconds +setInterval(function() +{ + // update our values from the sensor + sensor.update(); + + var data = sensor.getAccelerometer(); + console.log("Accelerometer x: " + + data.get(0) + + " y: " + data.get(1) + + " z: " + data.get(2) + + " g"); + + data = sensor.getGyroscope(); + console.log("Gyroscope x: " + + data.get(0) + + " y: " + data.get(1) + + " z: " + data.get(2) + + " dps"); + + // we show both C and F for temperature + console.log("Compensation Temperature: " + + sensor.getTemperature() + + " C / " + + sensor.getTemperature(true) + + " F"); + + console.log(); + +}, 250); + +// exit on ^C +process.on('SIGINT', function() +{ + sensor = null; + sensorObj.cleanUp(); + sensorObj = null; + console.log("Exiting."); + process.exit(0); +}); diff --git a/examples/python/lsm6ds3h.py b/examples/python/lsm6ds3h.py new file mode 100755 index 00000000..baec8d36 --- /dev/null +++ b/examples/python/lsm6ds3h.py @@ -0,0 +1,74 @@ +#!/usr/bin/python +# Author: Jon Trulson +# 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 +# "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. + +from __future__ import print_function +import time, sys, signal, atexit +from upm import pyupm_lsm6ds3h as sensorObj + +def main(): + # Instantiate a BMP250E instance using default i2c bus and address + sensor = sensorObj.LSM6DS3H() + + # For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS: + # LSM6DS3H(0, -1, 10); + + ## Exit handlers ## + # This function stops python from printing a stacktrace when you + # hit control-C + def SIGINTHandler(signum, frame): + raise SystemExit + + # This function lets you run code on exit + def exitHandler(): + print("Exiting") + sys.exit(0) + + # Register exit handlers + atexit.register(exitHandler) + signal.signal(signal.SIGINT, SIGINTHandler) + + # now output data every 250 milliseconds + while (1): + sensor.update() + + data = sensor.getAccelerometer() + print("Accelerometer x:", data[0], end=' ') + print(" y:", data[1], end=' ') + print(" z:", data[2], end=' ') + print(" g") + + data = sensor.getGyroscope() + print("Gyroscope x:", data[0], end=' ') + print(" y:", data[1], end=' ') + print(" z:", data[2], end=' ') + print(" dps") + + # we show both C and F for temperature + print("Compensation Temperature:", sensor.getTemperature(), "C /", end=' ') + print(sensor.getTemperature(True), "F") + + print() + time.sleep(.250) + +if __name__ == '__main__': + main() diff --git a/src/lsm6ds3h/CMakeLists.txt b/src/lsm6ds3h/CMakeLists.txt new file mode 100644 index 00000000..25b0baaa --- /dev/null +++ b/src/lsm6ds3h/CMakeLists.txt @@ -0,0 +1,9 @@ +upm_mixed_module_init (NAME lsm6ds3h + DESCRIPTION "3-Axis Digital Accelerometer and Gyroscope" + C_HDR lsm6ds3h.h lsm6ds3h_defs.h + C_SRC lsm6ds3h.c + CPP_HDR lsm6ds3h.hpp + CPP_SRC lsm6ds3h.cxx + FTI_SRC lsm6ds3h_fti.c + CPP_WRAPS_C + REQUIRES mraa utilities-c) diff --git a/src/lsm6ds3h/javaupm_lsm6ds3h.i b/src/lsm6ds3h/javaupm_lsm6ds3h.i new file mode 100644 index 00000000..50f07359 --- /dev/null +++ b/src/lsm6ds3h/javaupm_lsm6ds3h.i @@ -0,0 +1,24 @@ +%module javaupm_lsm6ds3h +%include "../upm.i" +%include "typemaps.i" +%include "../upm_vectortypes.i" + +%ignore getAccelerometer(float *, float *, float *); +%ignore getGyroscope(float *, float *, float *); + +%include "lsm6ds3h_defs.h" +%include "lsm6ds3h.hpp" +%{ + #include "lsm6ds3h.hpp" +%} + +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("javaupm_lsm6ds3h"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. \n" + e); + System.exit(1); + } + } +%} diff --git a/src/lsm6ds3h/jsupm_lsm6ds3h.i b/src/lsm6ds3h/jsupm_lsm6ds3h.i new file mode 100644 index 00000000..e57b820f --- /dev/null +++ b/src/lsm6ds3h/jsupm_lsm6ds3h.i @@ -0,0 +1,10 @@ +%module jsupm_lsm6ds3h +%include "../upm.i" +%include "../upm_vectortypes.i" + + +%include "lsm6ds3h_defs.h" +%include "lsm6ds3h.hpp" +%{ + #include "lsm6ds3h.hpp" +%} diff --git a/src/lsm6ds3h/lsm6ds3h.c b/src/lsm6ds3h/lsm6ds3h.c new file mode 100644 index 00000000..ca8b0fbd --- /dev/null +++ b/src/lsm6ds3h/lsm6ds3h.c @@ -0,0 +1,640 @@ +/* + * 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 "lsm6ds3h.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) ) ) + +// some useful macros to save on typing and text wrapping +#undef _SHIFT +#define _SHIFT(x) (_LSM6DS3H_##x##_SHIFT) + +#undef _MASK +#define _MASK(x) (_LSM6DS3H_##x##_MASK) + +#undef _SHIFTMASK +#define _SHIFTMASK(x) (_MASK(x) << _SHIFT(x)) + +// SPI CS on and off functions +static void _csOn(const lsm6ds3h_context dev) +{ + assert(dev != NULL); + + if (dev->gpioCS) + mraa_gpio_write(dev->gpioCS, 0); +} + +static void _csOff(const lsm6ds3h_context dev) +{ + assert(dev != NULL); + + if (dev->gpioCS) + mraa_gpio_write(dev->gpioCS, 1); +} + +// init +lsm6ds3h_context lsm6ds3h_init(int bus, int addr, int cs) +{ + lsm6ds3h_context dev = + (lsm6ds3h_context)malloc(sizeof(struct _lsm6ds3h_context)); + + if (!dev) + return NULL; + + // zero out context + memset((void *)dev, 0, sizeof(struct _lsm6ds3h_context)); + + // make sure MRAA is initialized + if (mraa_init() != MRAA_SUCCESS) + { + printf("%s: mraa_init() failed.\n", __FUNCTION__); + lsm6ds3h_close(dev); + return NULL; + } + + if (addr < 0) + { + // SPI + if (!(dev->spi = mraa_spi_init(bus))) + { + printf("%s: mraa_spi_init() failed.\n", __FUNCTION__); + lsm6ds3h_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__); + lsm6ds3h_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__); + lsm6ds3h_close(dev); + return NULL; + } + } + else + { + // I2C + if (!(dev->i2c = mraa_i2c_init(bus))) + { + printf("%s: mraa_i2c_init() failed.\n", __FUNCTION__); + lsm6ds3h_close(dev); + return NULL; + } + + if (mraa_i2c_address(dev->i2c, addr)) + { + printf("%s: mraa_i2c_address() failed.\n", __FUNCTION__); + lsm6ds3h_close(dev); + return NULL; + } + } + + // check the chip id + + uint8_t chipID = lsm6ds3h_get_chip_id(dev); + if (chipID != LSM6DS3H_CHIPID) + { + printf("%s: invalid chip id: %02x. Expected %02x\n", + __FUNCTION__, chipID, LSM6DS3H_CHIPID); + lsm6ds3h_close(dev); + return NULL; + } + + // reset + if (lsm6ds3h_reset(dev)) + { + printf("%s: lsm6ds3h_reset() failed.\n", __FUNCTION__); + lsm6ds3h_close(dev); + return NULL; + } + + // call devinit with default options + if (lsm6ds3h_devinit(dev, LSM6DS3H_XL_ODR_104HZ, LSM6DS3H_XL_FS_2G, + LSM6DS3H_G_ODR_104HZ, LSM6DS3H_G_FS_245DPS)) + { + printf("%s: lsm6ds3h_devinit() failed.\n", __FUNCTION__); + lsm6ds3h_close(dev); + return NULL; + } + + return dev; +} + +void lsm6ds3h_close(lsm6ds3h_context dev) +{ + assert(dev != NULL); + + lsm6ds3h_uninstall_isr(dev, LSM6DS3H_INTERRUPT_INT1); + lsm6ds3h_uninstall_isr(dev, LSM6DS3H_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 lsm6ds3h_devinit(const lsm6ds3h_context dev, + LSM6DS3H_XL_ODR_T acc_odr, + LSM6DS3H_XL_FS_T acc_fs, + LSM6DS3H_G_ODR_T gyr_odr, + LSM6DS3H_G_FS_T gyr_fs) +{ + assert(dev != NULL); + + // enable register auto-increment and BDU (block data update) + uint8_t reg = lsm6ds3h_read_reg(dev, LSM6DS3H_REG_CTRL3_C); + reg |= (LSM6DS3H_CTRL3_IF_INC | LSM6DS3H_CTRL3_BDU); + + if (lsm6ds3h_write_reg(dev, LSM6DS3H_REG_CTRL3_C, reg)) + return UPM_ERROR_OPERATION_FAILED; + + // set our ODR, FS, and HP mode + if (lsm6ds3h_set_acc_odr(dev, acc_odr) + || lsm6ds3h_set_acc_full_scale(dev, acc_fs) + || lsm6ds3h_set_gyr_odr(dev, gyr_odr) + || lsm6ds3h_set_gyr_full_scale(dev, gyr_fs) + || lsm6ds3h_high_performance(dev, true)) + { + printf("%s: failed to set configuration parameters.\n", + __FUNCTION__); + return UPM_ERROR_OPERATION_FAILED; + } + + // settle + upm_delay_ms(50); + + return UPM_SUCCESS; +} + +upm_result_t lsm6ds3h_set_acc_odr(const lsm6ds3h_context dev, + LSM6DS3H_XL_ODR_T odr) +{ + assert(dev != NULL); + + uint8_t reg = lsm6ds3h_read_reg(dev, LSM6DS3H_REG_CTRL1_XL); + + // mask out ODR bits, add our own + reg &= ~_SHIFTMASK(CTRL1_XL_ODR); + reg |= (odr << _SHIFT(CTRL1_XL_ODR)); + + if (lsm6ds3h_write_reg(dev, LSM6DS3H_REG_CTRL1_XL, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t lsm6ds3h_set_gyr_odr(const lsm6ds3h_context dev, + LSM6DS3H_G_ODR_T odr) +{ + assert(dev != NULL); + + uint8_t reg = lsm6ds3h_read_reg(dev, LSM6DS3H_REG_CTRL2_G); + + // mask out ODR bits, add our own + reg &= ~_SHIFTMASK(CTRL2_G_ODR); + reg |= (odr << _SHIFT(CTRL2_G_ODR)); + + if (lsm6ds3h_write_reg(dev, LSM6DS3H_REG_CTRL2_G, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t lsm6ds3h_set_acc_full_scale(const lsm6ds3h_context dev, + LSM6DS3H_XL_FS_T fs) +{ + assert(dev != NULL); + + uint8_t reg = lsm6ds3h_read_reg(dev, LSM6DS3H_REG_CTRL1_XL); + + // mask out FS bits, add our own + reg &= ~_SHIFTMASK(CTRL1_XL_FS); + reg |= (fs << _SHIFT(CTRL1_XL_FS)); + + if (lsm6ds3h_write_reg(dev, LSM6DS3H_REG_CTRL1_XL, reg)) + return UPM_ERROR_OPERATION_FAILED; + + // 16b resolution + switch(fs) + { + case LSM6DS3H_XL_FS_2G: + dev->accScale = 0.061; + break; + + case LSM6DS3H_XL_FS_4G: + dev->accScale = 0.122; + break; + + case LSM6DS3H_XL_FS_8G: + dev->accScale = 0.244; + break; + + case LSM6DS3H_XL_FS_16G: + dev->accScale = 0.488; + break; + } + + return UPM_SUCCESS; +} + +upm_result_t lsm6ds3h_set_gyr_full_scale(const lsm6ds3h_context dev, + LSM6DS3H_G_FS_T fs) +{ + assert(dev != NULL); + + uint8_t reg = lsm6ds3h_read_reg(dev, LSM6DS3H_REG_CTRL2_G); + + // mask out FS bits, add our own + reg &= ~_SHIFTMASK(CTRL2_G_FS); + + if ((int)fs > (int)_MASK(CTRL2_G_FS)) + reg |= LSM6DS3H_CTRL2_G_FS_125; + else + reg &= ~LSM6DS3H_CTRL2_G_FS_125; + + // mask off the virtual bit. The end result will be 245dps (0), + // if it was tagged with the virtual bit. + fs &= _MASK(CTRL2_G_FS); + // add it to the register + reg |= (fs << _SHIFT(CTRL2_G_FS)); + + if (lsm6ds3h_write_reg(dev, LSM6DS3H_REG_CTRL2_G, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t lsm6ds3h_update(const lsm6ds3h_context dev) +{ + assert(dev != NULL); + + int bufLen = 14; + uint8_t buf[bufLen]; + + if (lsm6ds3h_read_regs(dev, LSM6DS3H_REG_OUT_TEMP_L, + buf, bufLen) != bufLen) + { + printf("%s: lsm6ds3h_read_regs() failed to read %d bytes\n", + __FUNCTION__, bufLen); + return UPM_ERROR_OPERATION_FAILED; + } + + // temperature is first msb lsb + dev->temperature = INT16_TO_FLOAT(buf[1], buf[0]); + + // gyroscope + dev->gyrX = INT16_TO_FLOAT(buf[3], buf[2]); + dev->gyrY = INT16_TO_FLOAT(buf[5], buf[4]); + dev->gyrZ = INT16_TO_FLOAT(buf[7], buf[6]); + + // accelerometer + dev->accX = INT16_TO_FLOAT(buf[9], buf[8]); + dev->accY = INT16_TO_FLOAT(buf[11], buf[10]); + dev->accZ = INT16_TO_FLOAT(buf[13], buf[12]); + + return UPM_SUCCESS; +} + +uint8_t lsm6ds3h_read_reg(const lsm6ds3h_context dev, uint8_t reg) +{ + assert(dev != NULL); + + if (dev->spi) + { + 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 lsm6ds3h_read_regs(const lsm6ds3h_context dev, uint8_t reg, + uint8_t *buffer, int len) +{ + assert(dev != NULL); + + if (dev->spi) + { + 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 lsm6ds3h_write_reg(const lsm6ds3h_context dev, + uint8_t reg, uint8_t val) +{ + assert(dev != NULL); + + if (dev->spi) + { + 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 lsm6ds3h_get_chip_id(const lsm6ds3h_context dev) +{ + assert(dev != NULL); + + return lsm6ds3h_read_reg(dev, LSM6DS3H_REG_WHO_AM_I); +} + +void lsm6ds3h_get_accelerometer(const lsm6ds3h_context dev, + float *x, float *y, float *z) +{ + assert(dev != NULL); + + if (x) + *x = dev->accX * dev->accScale / 1000.00; + + if (y) + *y = dev->accY * dev->accScale / 1000.00; + + if (z) + *z = dev->accZ * dev->accScale / 1000.00; +} + +void lsm6ds3h_get_gyroscope(const lsm6ds3h_context dev, + float *x, float *y, float *z) +{ + assert(dev != NULL); + + if (x) + *x = dev->gyrX / 1000.00; + + if (y) + *y = dev->gyrY / 1000.00; + + if (z) + *z = dev->gyrZ / 1000.00; +} + +float lsm6ds3h_get_temperature(const lsm6ds3h_context dev) +{ + assert(dev != NULL); + + // this seems to work, but I sure wish they would document this in + // their DS's + return (dev->temperature / 65536.0) + 25.0; +} + +upm_result_t lsm6ds3h_high_performance(const lsm6ds3h_context dev, + bool enable) +{ + assert(dev != NULL); + + uint8_t reg = lsm6ds3h_read_reg(dev, LSM6DS3H_REG_CTRL6_C); + + // acc + if (enable) + reg &= ~LSM6DS3H_CTRL6_XL_HM_MODE; + else + reg |= LSM6DS3H_CTRL6_XL_HM_MODE; + + if (lsm6ds3h_write_reg(dev, LSM6DS3H_REG_CTRL6_C, reg)) + return UPM_ERROR_OPERATION_FAILED; + + // gyr + reg = lsm6ds3h_read_reg(dev, LSM6DS3H_REG_CTRL7_G); + + if (enable) + reg &= ~LSM6DS3H_CTRL7_G_HM_MODE; + else + reg |= LSM6DS3H_CTRL7_G_HM_MODE; + + if (lsm6ds3h_write_reg(dev, LSM6DS3H_REG_CTRL7_G, reg)) + return UPM_ERROR_OPERATION_FAILED; + + upm_delay_ms(100); + + return UPM_SUCCESS; +} + +upm_result_t lsm6ds3h_reset(const lsm6ds3h_context dev) +{ + assert(dev != NULL); + + uint8_t reg = lsm6ds3h_read_reg(dev, LSM6DS3H_REG_CTRL3_C); + + reg |= LSM6DS3H_CTRL3_SW_RESET; + + if (lsm6ds3h_write_reg(dev, LSM6DS3H_REG_CTRL3_C, reg)) + return UPM_ERROR_OPERATION_FAILED; + + upm_delay_ms(100); + + return UPM_SUCCESS; +} + +upm_result_t lsm6ds3h_set_interrupt_active_high(const lsm6ds3h_context dev, + bool high) +{ + assert(dev != NULL); + + uint8_t reg = lsm6ds3h_read_reg(dev, LSM6DS3H_REG_CTRL3_C); + + if (high) + reg &= ~LSM6DS3H_CTRL3_H_LACTIVE; + else + reg |= LSM6DS3H_CTRL3_H_LACTIVE; + + if (lsm6ds3h_write_reg(dev, LSM6DS3H_REG_CTRL3_C, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t lsm6ds3h_set_interrupt_push_pull(const lsm6ds3h_context dev, + bool pp) +{ + assert(dev != NULL); + + uint8_t reg = lsm6ds3h_read_reg(dev, LSM6DS3H_REG_CTRL3_C); + + if (pp) + reg &= ~LSM6DS3H_CTRL3_PP_OD; + else + reg |= LSM6DS3H_CTRL3_PP_OD; + + if (lsm6ds3h_write_reg(dev, LSM6DS3H_REG_CTRL3_C, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +uint8_t lsm6ds3h_get_status(const lsm6ds3h_context dev) +{ + assert(dev != NULL); + + return lsm6ds3h_read_reg(dev, LSM6DS3H_REG_STATUS); +} + +upm_result_t lsm6ds3h_install_isr(const lsm6ds3h_context dev, + LSM6DS3H_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 + lsm6ds3h_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 LSM6DS3H_INTERRUPT_INT1: + dev->gpioINT1 = gpio_isr; + break; + + case LSM6DS3H_INTERRUPT_INT2: + dev->gpioINT2 = gpio_isr; + break; + } + + return UPM_SUCCESS; +} + +void lsm6ds3h_uninstall_isr(const lsm6ds3h_context dev, + LSM6DS3H_INTERRUPT_PINS_T intr) +{ + assert(dev != NULL); + + switch (intr) + { + case LSM6DS3H_INTERRUPT_INT1: + if (dev->gpioINT1) + { + mraa_gpio_isr_exit(dev->gpioINT1); + mraa_gpio_close(dev->gpioINT1); + dev->gpioINT1 = NULL; + } + break; + + case LSM6DS3H_INTERRUPT_INT2: + if (dev->gpioINT2) + { + mraa_gpio_isr_exit(dev->gpioINT2); + mraa_gpio_close(dev->gpioINT2); + dev->gpioINT2 = NULL; + } + break; + } +} diff --git a/src/lsm6ds3h/lsm6ds3h.cxx b/src/lsm6ds3h/lsm6ds3h.cxx new file mode 100644 index 00000000..150abaa8 --- /dev/null +++ b/src/lsm6ds3h/lsm6ds3h.cxx @@ -0,0 +1,208 @@ +/* + * 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 "lsm6ds3h.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); +} + +LSM6DS3H::LSM6DS3H(int bus, int addr, int cs) : + m_lsm6ds3h(lsm6ds3h_init(bus, addr, cs)) +{ + if (!m_lsm6ds3h) + throw std::runtime_error(string(__FUNCTION__) + + ": lsm6ds3h_init() failed"); +} + +LSM6DS3H::~LSM6DS3H() +{ + lsm6ds3h_close(m_lsm6ds3h); +} + +void LSM6DS3H::init(LSM6DS3H_XL_ODR_T acc_odr, LSM6DS3H_XL_FS_T acc_fs, + LSM6DS3H_G_ODR_T gyr_odr, LSM6DS3H_G_FS_T gyr_fs) +{ + if (lsm6ds3h_devinit(m_lsm6ds3h, acc_odr, acc_fs, gyr_odr, gyr_fs)) + throw std::runtime_error(string(__FUNCTION__) + + ": lsm6ds3h_devinit() failed"); +} + +void LSM6DS3H::update() +{ + if (lsm6ds3h_update(m_lsm6ds3h)) + throw std::runtime_error(string(__FUNCTION__) + + ": lsm6ds3h_update() failed"); +} + +uint8_t LSM6DS3H::readReg(uint8_t reg) +{ + return lsm6ds3h_read_reg(m_lsm6ds3h, reg); +} + +int LSM6DS3H::readRegs(uint8_t reg, uint8_t *buffer, int len) +{ + int rv = lsm6ds3h_read_regs(m_lsm6ds3h, reg, buffer, len); + if (rv != len) + throw std::runtime_error(string(__FUNCTION__) + + ": lsm6ds3h_read_regs() failed"); + + return rv; +} + +void LSM6DS3H::writeReg(uint8_t reg, uint8_t val) +{ + if (lsm6ds3h_write_reg(m_lsm6ds3h, reg, val)) + throw std::runtime_error(string(__FUNCTION__) + + ": lsm6ds3h_write_reg() failed"); +} + +uint8_t LSM6DS3H::getChipID() +{ + return lsm6ds3h_get_chip_id(m_lsm6ds3h); +} + +void LSM6DS3H::getAccelerometer(float *x, float *y, float *z) +{ + lsm6ds3h_get_accelerometer(m_lsm6ds3h, x, y, z); +} + +std::vector LSM6DS3H::getAccelerometer() +{ + float v[3]; + + getAccelerometer(&v[0], &v[1], &v[2]); + return std::vector(v, v+3); +} + +void LSM6DS3H::getGyroscope(float *x, float *y, float *z) +{ + lsm6ds3h_get_gyroscope(m_lsm6ds3h, x, y, z); +} + +std::vector LSM6DS3H::getGyroscope() +{ + float v[3]; + + getGyroscope(&v[0], &v[1], &v[2]); + return std::vector(v, v+3); +} + +float LSM6DS3H::getTemperature(bool fahrenheit) +{ + float temperature = lsm6ds3h_get_temperature(m_lsm6ds3h); + if (fahrenheit) + return c2f(temperature); + else + return temperature; +} + +void LSM6DS3H::reset() +{ + if (lsm6ds3h_reset(m_lsm6ds3h)) + throw std::runtime_error(string(__FUNCTION__) + + ": lsm6ds3h_reset() failed"); +} + +void LSM6DS3H::setAccelerometerODR(LSM6DS3H_XL_ODR_T odr) +{ + if (lsm6ds3h_set_acc_odr(m_lsm6ds3h, odr)) + throw std::runtime_error(string(__FUNCTION__) + + ": lsm6ds3h_set_acc_odr() failed"); +} + +void LSM6DS3H::setAccelerometerFullScale(LSM6DS3H_XL_FS_T fs) +{ + if (lsm6ds3h_set_acc_full_scale(m_lsm6ds3h, fs)) + throw std::runtime_error(string(__FUNCTION__) + + ": lsm6ds3h_set_acc_full_scale() failed"); +} + +void LSM6DS3H::setGyroscopeODR(LSM6DS3H_G_ODR_T odr) +{ + if (lsm6ds3h_set_gyr_odr(m_lsm6ds3h, odr)) + throw std::runtime_error(string(__FUNCTION__) + + ": lsm6ds3h_set_gyr_odr() failed"); +} + +void LSM6DS3H::setGyroscopeFullScale(LSM6DS3H_G_FS_T fs) +{ + if (lsm6ds3h_set_gyr_full_scale(m_lsm6ds3h, fs)) + throw std::runtime_error(string(__FUNCTION__) + + ": lsm6ds3h_set_gyr_full_scale() failed"); +} + +void LSM6DS3H::setHighPerformance(bool enable) +{ + if (lsm6ds3h_high_performance(m_lsm6ds3h, enable)) + throw std::runtime_error(string(__FUNCTION__) + + ": lsm6ds3h_high_performance() failed"); +} + +void LSM6DS3H::setInterruptActiveHigh(bool high) +{ + if (lsm6ds3h_set_interrupt_active_high(m_lsm6ds3h, high)) + throw std::runtime_error(string(__FUNCTION__) + + ": lsm6ds3h_set_interrupt_active_high() failed"); +} + +void LSM6DS3H::setInterruptPushPull(bool pp) +{ + if (lsm6ds3h_set_interrupt_push_pull(m_lsm6ds3h, pp)) + throw std::runtime_error(string(__FUNCTION__) + + ": lsm6ds3h_set_interrupt_push_pull() failed"); +} + +uint8_t LSM6DS3H::getStatus() +{ + return lsm6ds3h_get_status(m_lsm6ds3h); +} + +void LSM6DS3H::installISR(LSM6DS3H_INTERRUPT_PINS_T intr, int gpio, + mraa::Edge level, + void (*isr)(void *), void *arg) +{ + if (lsm6ds3h_install_isr(m_lsm6ds3h, intr, gpio, + (mraa_gpio_edge_t)level, isr, arg)) + throw std::runtime_error(string(__FUNCTION__) + + ": lsm6ds3h_install_isr() failed"); +} + +void LSM6DS3H::uninstallISR(LSM6DS3H_INTERRUPT_PINS_T intr) +{ + lsm6ds3h_uninstall_isr(m_lsm6ds3h, intr); +} diff --git a/src/lsm6ds3h/lsm6ds3h.h b/src/lsm6ds3h/lsm6ds3h.h new file mode 100644 index 00000000..398c2e6e --- /dev/null +++ b/src/lsm6ds3h/lsm6ds3h.h @@ -0,0 +1,340 @@ +/* + * 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 "lsm6ds3h_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * @file lsm6ds3h.h + * @library lsm6ds3h + * @brief C API for the lsm6ds3h driver + * + * @include lsm6ds3h.c + */ + + /** + * Device context + */ + typedef struct _lsm6ds3h_context { + mraa_i2c_context i2c; + mraa_spi_context spi; + + mraa_gpio_context gpioCS; // SPI CS pin + mraa_gpio_context gpioINT1; // intr 1 + mraa_gpio_context gpioINT2; // intr 2 + + // uncompensated temperature + float temperature; + + // uncompensated acc data + float accX; + float accY; + float accZ; + + // uncompensated gyr data + float gyrX; + float gyrY; + float gyrZ; + + // acc scaling + float accScale; + } *lsm6ds3h_context; + + /** + * LSM6DS3H 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 Intel Edison with Arduino breakout), then + * you can connect the proper pin to the hardware CS pin on your + * MCU and supply -1 for cs. + * + * @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. + * @return The device context, or NULL on error + */ + lsm6ds3h_context lsm6ds3h_init(int bus, int addr, int cs); + + /** + * LSM6DS3H Destructor + * + * @param dev The device context + */ + void lsm6ds3h_close(lsm6ds3h_context dev); + + /** + * Update the internal stored values from sensor data + * + * @param dev The device context + * @return UPM result + */ + upm_result_t lsm6ds3h_update(const lsm6ds3h_context dev); + + /** + * Return the chip ID + * + * @param dev The device context + * @return The chip ID (LSM6DS3H_CHIPID) + */ + uint8_t lsm6ds3h_get_chip_id(const lsm6ds3h_context dev); + + /** + * Initialize the device and start operation. This function is + * called from lsm6ds3h_init(), so it will not need to be called + * by a user unless the device is reset. It sets the + * accelerometer and gyroscope ODR and FS modes, and enables BDU, + * register auto-increment, and high performance mode. + * + * @param dev The device context + * @param acc_odr One of the LSM6DS3H_XL_ODR_T values + * @param acc_fs One of the LSM6DS3H_XL_FS_T values + * @param gyr_odr One of the LSM6DS3H_G_ODR_T values + * @param gyr_fs One of the LSM6DS3H_G_FS_T values + * @return UPM result + */ + upm_result_t lsm6ds3h_devinit(const lsm6ds3h_context dev, + LSM6DS3H_XL_ODR_T acc_odr, + LSM6DS3H_XL_FS_T acc_fs, + LSM6DS3H_G_ODR_T gyr_odr, + LSM6DS3H_G_FS_T gyr_fs); + + /** + * Set the output data rate (ODR) of the accelerometer + * + * @param dev The device context + * @param odr One of the LSM6DS3H_XL_ODR_T values + * @return UPM result + */ + upm_result_t lsm6ds3h_set_acc_odr(const lsm6ds3h_context dev, + LSM6DS3H_XL_ODR_T odr); + + /** + * Set the output data rate (ODR) of the gyroscope + * + * @param dev The device context + * @param odr One of the LSM6DS3H_G_ODR_T values + * @return UPM result + */ + upm_result_t lsm6ds3h_set_gyr_odr(const lsm6ds3h_context dev, + LSM6DS3H_G_ODR_T odr); + + /** + * Set the full scale (FS) of the accelerometer. This device + * supports a full scale of 2, 4, 8, and 16G. + * + * @param dev The device context + * @param fs One of the LSM6DS3H_XL_FS_T values + * @return UPM result + */ + upm_result_t lsm6ds3h_set_acc_full_scale(const lsm6ds3h_context dev, + LSM6DS3H_XL_FS_T fs); + + /** + * Set the full scale (FS) of the gyroscope. This device supports + * a full scale of 125, 245, 500, 1000, and 2000 degrees per + * second (DPS) + * + * @param dev The device context + * @param fs One of the LSM6DS3H_G_FS_T values + * @return UPM result + */ + upm_result_t lsm6ds3h_set_gyr_full_scale(const lsm6ds3h_context dev, + LSM6DS3H_G_FS_T fs); + + /** + * Return accelerometer data in gravities (g). lsm6ds3h_update() + * must have been called prior to calling this function. + * + * @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 lsm6ds3h_get_accelerometer(const lsm6ds3h_context dev, + float *x, float *y, float *z); + + /** + * Return gyroscope data in degrees per second (DPS). + * lsm6ds3h_update() must have been called prior to calling this + * function. + * + * @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 lsm6ds3h_get_gyroscope(const lsm6ds3h_context dev, + float *x, float *y, float *z); + + /** + * Return the current measured temperature. Note, this is not + * ambient temperature. lsm6ds3h_update() must have been called + * prior to calling this function. + * + * @param dev The device context + * @return The temperature in degrees Celsius + */ + float lsm6ds3h_get_temperature(const lsm6ds3h_context dev); + + /** + * Enable accelerometer and gyroscope high performance modes. + * These are further defined by the respective ODR settings to + * allow low power, and normal/high-performance modes. + * + * @param dev The device context + * @param enable true to enable high performance mode, false otherwise + * @return UPM result + */ + upm_result_t lsm6ds3h_high_performance(const lsm6ds3h_context dev, + bool enable); + + /** + * Reset the device as if during a power on reset. All configured + * values are lost when this happens. You should call + * lsm6ds3h_devinit() afterwards, or at least perform the same + * initialization lsm6ds3h_devinit() does before continuing. + * + * @param dev The device context + * @return UPM result + */ + upm_result_t lsm6ds3h_reset(const lsm6ds3h_context dev); + + /** + * Indicate whether the interrupt should be active high (default) + * or active low. See the datasheet for details. + * + * @param dev The device context + * @param high true for active high, false for active low + * @return UPM result + */ + upm_result_t lsm6ds3h_set_interrupt_active_high(const lsm6ds3h_context dev, + bool high); + + /** + * Indicate whether interrupts are push-pull (default) or open + * drain. See the datasheet for details. + * + * @param dev The device context + * @param pp true for push-pull, false for open-drain + * @return UPM result + */ + upm_result_t lsm6ds3h_set_interrupt_push_pull(const lsm6ds3h_context dev, + bool pp); + + /** + * Return the contents of the status register + * + * @param dev The device context + * @return A bitmask of values from LSM6DS3H_STATUS_BITS_T + */ + uint8_t lsm6ds3h_get_status(const lsm6ds3h_context dev); + + /** + * Install an interrupt handler + * + * @param dev The device context + * @param intr One of the LSM6DS3H_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 the the interrupt handler + * @return UPM result + */ + upm_result_t lsm6ds3h_install_isr(const lsm6ds3h_context dev, + LSM6DS3H_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 LSM6DS3H_INTERRUPT_PINS_T values + * specifying which interrupt pin you are removing + */ + void lsm6ds3h_uninstall_isr(const lsm6ds3h_context dev, + LSM6DS3H_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 lsm6ds3h_read_reg(const lsm6ds3h_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 lsm6ds3h_read_regs(const lsm6ds3h_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 lsm6ds3h_write_reg(const lsm6ds3h_context dev, + uint8_t reg, uint8_t val); + + +#ifdef __cplusplus +} +#endif diff --git a/src/lsm6ds3h/lsm6ds3h.hpp b/src/lsm6ds3h/lsm6ds3h.hpp new file mode 100644 index 00000000..d34e44d4 --- /dev/null +++ b/src/lsm6ds3h/lsm6ds3h.hpp @@ -0,0 +1,336 @@ +/* + * 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 "lsm6ds3h.h" + +namespace upm { + + /** + * @brief ST Micro 3-axis Accelerometer + * @defgroup lsm6ds3h libupm-lsm6ds3h + * @ingroup i2c spi gpio stmicro accelerometer + */ + + /** + * @library lsm6ds3h + * @sensor lsm6ds3h + * @comname Digital 3-axis Accelerometer and Gyroscope + * @type accelerometer gyro + * @man stmicro + * @con i2c spi gpio + * @web http://www.st.com/en/mems-and-sensors/lsm6ds3h.html + * + * @brief API for the LSM6DS3H 3-axis Accelerometer and Gyroscope + * + * The LSM6DS3H is a system-in-package featuring a 3D digital + * accelerometer and a 3D digital gyroscope performing at 1.1 mA + * (up to 1.6 kHz ODR) in high performance mode and enabling + * always-on low-power features for an optimal motion experience + * for the consumer. + + * 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. + * + * @snippet lsm6ds3h.cxx Interesting + */ + + class LSM6DS3H { + public: + + /** + * LSM6DS3H 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 + */ + LSM6DS3H(int bus=LSM6DS3H_DEFAULT_I2C_BUS, + int addr=LSM6DS3H_DEFAULT_I2C_ADDR, + int cs=-1); + + /** + * LSM6DS3H destructor + */ + virtual ~LSM6DS3H(); + + /** + * 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 gyroscope data in degrees per second (DPS). + * 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 getGyroscope(float *x, float *y, float *z); + + /** + * Return gyroscope data in degrees per second 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 getGyroscope(); + + /** + * 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 it will not need to be + * called by a user unless the device is reset. It sets the + * accelerometer and gyroscope ODR and FS modes, and enables + * BDU, register auto-increment, and high performance mode. + * + * @param acc_odr One of the LSM6DS3H_XL_ODR_T values + * @param acc_fs One of the LSM6DS3H_XL_FS_T values + * @param gyr_odr One of the LSM6DS3H_G_ODR_T values + * @param gyr_fs One of the LSM6DS3H_G_FS_T values + * @throws std::runtime_error on failure + */ + void init(LSM6DS3H_XL_ODR_T acc_odr=LSM6DS3H_XL_ODR_104HZ, + LSM6DS3H_XL_FS_T acc_fs=LSM6DS3H_XL_FS_2G, + LSM6DS3H_G_ODR_T gyr_odr=LSM6DS3H_G_ODR_104HZ, + LSM6DS3H_G_FS_T gyr_fs=LSM6DS3H_G_FS_245DPS); + + /** + * 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 output data rate (ODR) of the accelerometer + * + * @param odr One of the LSM6DS3H_XL_ODR_T values + * @throws std::runtime_error on failure + */ + void setAccelerometerODR(LSM6DS3H_XL_ODR_T odr); + + /** + * Set the full scale (FS) of the accelerometer. This device + * supports a full scale of 2, 4, 8, and 16G. + * + * @param fs One of the LSM6DS3H_XL_FS_T values + * @throws std::runtime_error on failure + */ + void setAccelerometerFullScale(LSM6DS3H_XL_FS_T fs); + + /** + * Set the output data rate (ODR) of the gyroscope + * + * @param odr One of the LSM6DS3H_G_ODR_T values + * @throws std::runtime_error on failure + */ + void setGyroscopeODR(LSM6DS3H_G_ODR_T odr); + + /** + * Set the full scale (FS) of the gyroscope + * + * @param fs One of the LSM6DS3H_G_FS_T values + * @throws std::runtime_error on failure + */ + void setGyroscopeFullScale(LSM6DS3H_G_FS_T fs); + + /** + * Enable accelerometer and gyroscope high performance modes. + * These are further defined by the respective ODR settings to + * allow low power, and normal/high-performance modes. This + * is enabled by default in init(). + * + * @param enable true to enable high performance mode, false otherwise + * @throws std::runtime_error on failure + */ + void setHighPerformance(bool enable); + + /** + * Indicate whether the interrupt should be active high (default) + * or active low. See the datasheet for details. + * + * @param high true for active high, false for active low + * @throws std::runtime_error on failure + */ + void setInterruptActiveHigh(bool high); + + /** + * Indicate whether interrupts are push-pull (default) or open + * drain. See the datasheet for details. + * + * @param pp true for push-pull, false for open-drain + * @throws std::runtime_error on failure + */ + void setInterruptPushPull(bool pp); + + /** + * Return the contents of the status register + * + * @return A bitmask of values from LSM6DS3H_STATUS_BITS_T + */ + uint8_t getStatus(); + +#if defined(SWIGJAVA) || defined(JAVACALLBACK) + void installISR(LSM6DS3H_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 LSM6DS3H_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(LSM6DS3H_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 LSM6DS3H_INTERRUPT_PINS_T values + * specifying which interrupt pin you are removing + */ + void uninstallISR(LSM6DS3H_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: + lsm6ds3h_context m_lsm6ds3h; + + private: + // Adding a private function definition for java bindings +#if defined(SWIGJAVA) || defined(JAVACALLBACK) + void installISR(LSM6DS3H_INTERRUPT_PINS_T intr, int gpio, + mraa::Edge level, + void (*isr)(void *), void *arg); +#endif + }; +} diff --git a/src/lsm6ds3h/lsm6ds3h_defs.h b/src/lsm6ds3h/lsm6ds3h_defs.h new file mode 100644 index 00000000..6738c9ec --- /dev/null +++ b/src/lsm6ds3h/lsm6ds3h_defs.h @@ -0,0 +1,646 @@ +/* + * 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 + +#define LSM6DS3H_DEFAULT_I2C_BUS 0 +#define LSM6DS3H_DEFAULT_SPI_BUS 0 +#define LSM6DS3H_DEFAULT_I2C_ADDR 0x6a + +#define LSM6DS3H_CHIPID 0x69 + +#ifdef __cplusplus +extern "C" { +#endif + + // NOTE: Reserved registers must not be written into or permanent + // damage can result. Reading from them may return indeterminate + // values. Registers containing reserved bitfields must be + // written as 0. + + // This register map is not complete -- all registers are + // enumerated, however not all register bitmaps are enumerated + // here. Feel free to add any you need that are missing. + + /** + * LSM6DS3H registers + */ + typedef enum { + // 0x00 reserved + + LSM6DS3H_REG_FUNC_CFG_ACCESS = 0x01, + + // 0x02-0x03 reserved + + LSM6DS3H_REG_SENSOR_SYNC_TIME_FRAME = 0x04, + + // 0x05 reserved + + LSM6DS3H_REG_FIFO_CTRL1 = 0x06, + LSM6DS3H_REG_FIFO_CTRL2 = 0x07, + LSM6DS3H_REG_FIFO_CTRL3 = 0x08, + LSM6DS3H_REG_FIFO_CTRL4 = 0x09, + LSM6DS3H_REG_FIFO_CTRL5 = 0x0a, + + LSM6DS3H_REG_ORIENT_CFG_G = 0x0b, + + // 0x0c reserved + + LSM6DS3H_REG_INT1_CTRL = 0x0d, + LSM6DS3H_REG_INT2_CTRL = 0x0e, + + LSM6DS3H_REG_WHO_AM_I = 0x0f, + + LSM6DS3H_REG_CTRL1_XL = 0x10, + LSM6DS3H_REG_CTRL2_G = 0x11, + LSM6DS3H_REG_CTRL3_C = 0x12, + LSM6DS3H_REG_CTRL4_C = 0x13, + LSM6DS3H_REG_CTRL5_C = 0x14, + LSM6DS3H_REG_CTRL6_C = 0x15, + LSM6DS3H_REG_CTRL7_G = 0x16, + LSM6DS3H_REG_CTRL8_XL = 0x17, + LSM6DS3H_REG_CTRL9_XL = 0x18, + LSM6DS3H_REG_CTRL10_C = 0x19, + + LSM6DS3H_REG_MASTER_CFG = 0x1a, + LSM6DS3H_REG_WAKE_UP_SRC = 0x1b, + LSM6DS3H_REG_TAP_SRC = 0x1c, + LSM6DS3H_REG_TAP_D6D = 0x1d, + + // also STATUS_SPIAux + LSM6DS3H_REG_STATUS = 0x1e, + + // 0x1f reserved + + LSM6DS3H_REG_OUT_TEMP_L = 0x20, + LSM6DS3H_REG_OUT_TEMP_H = 0x21, + + LSM6DS3H_REG_OUTX_L_G = 0x22, + LSM6DS3H_REG_OUTX_H_G = 0x23, + LSM6DS3H_REG_OUTY_L_G = 0x24, + LSM6DS3H_REG_OUTY_H_G = 0x25, + LSM6DS3H_REG_OUTZ_L_G = 0x26, + LSM6DS3H_REG_OUTZ_H_G = 0x27, + + LSM6DS3H_REG_OUTX_L_XL = 0x28, + LSM6DS3H_REG_OUTX_H_XL = 0x29, + LSM6DS3H_REG_OUTY_L_XL = 0x2a, + LSM6DS3H_REG_OUTY_H_XL = 0x2b, + LSM6DS3H_REG_OUTZ_L_XL = 0x2c, + LSM6DS3H_REG_OUTZ_H_XL = 0x2d, + + LSM6DS3H_REG_SENSORHUB1_REG = 0x2e, + LSM6DS3H_REG_SENSORHUB2_REG = 0x2f, + LSM6DS3H_REG_SENSORHUB3_REG = 0x30, + LSM6DS3H_REG_SENSORHUB4_REG = 0x31, + LSM6DS3H_REG_SENSORHUB5_REG = 0x32, + LSM6DS3H_REG_SENSORHUB6_REG = 0x33, + LSM6DS3H_REG_SENSORHUB7_REG = 0x34, + LSM6DS3H_REG_SENSORHUB8_REG = 0x35, + LSM6DS3H_REG_SENSORHUB9_REG = 0x36, + LSM6DS3H_REG_SENSORHUB10_REG = 0x37, + LSM6DS3H_REG_SENSORHUB11_REG = 0x38, + LSM6DS3H_REG_SENSORHUB12_REG = 0x39, + + LSM6DS3H_REG_FIFO_STATUS1 = 0x3a, + LSM6DS3H_REG_FIFO_STATUS2 = 0x3b, + LSM6DS3H_REG_FIFO_STATUS3 = 0x3c, + LSM6DS3H_REG_FIFO_STATUS4 = 0x3d, + + LSM6DS3H_REG_FIFO_DATA_OUT_L = 0x3e, + LSM6DS3H_REG_FIFO_DATA_OUT_H = 0x3f, + + LSM6DS3H_REG_TIMESTAMP0_REG = 0x40, + LSM6DS3H_REG_TIMESTAMP1_REG = 0x41, + LSM6DS3H_REG_TIMESTAMP2_REG = 0x42, + + // 0x43-0x48 reserved + + LSM6DS3H_REG_STEP_TIMESTAMP_L = 0x49, + LSM6DS3H_REG_STEP_TIMESTAMP_H = 0x4a, + + LSM6DS3H_REG_STEP_COUNTER_L = 0x4b, + LSM6DS3H_REG_STEP_COUNTER_H = 0x4c, + + LSM6DS3H_REG_SENSORHUB13_REG = 0x4d, + LSM6DS3H_REG_SENSORHUB14_REG = 0x4e, + LSM6DS3H_REG_SENSORHUB15_REG = 0x4f, + LSM6DS3H_REG_SENSORHUB16_REG = 0x50, + LSM6DS3H_REG_SENSORHUB17_REG = 0x51, + LSM6DS3H_REG_SENSORHUB18_REG = 0x52, + + LSM6DS3H_REG_FUNC_SRC = 0x53, + + // 0x54-0x57 reserved + + LSM6DS3H_REG_TAP_CFG = 0x58, + LSM6DS3H_REG_TAP_THS_6D = 0x59, + + // where is int_dur1? + LSM6DS3H_REG_INT_DUR2 = 0x5a, + + LSM6DS3H_REG_WAKE_UP_THS = 0x5b, + LSM6DS3H_REG_WAKE_UP_DUR = 0x5c, + + LSM6DS3H_REG_FREE_FALL = 0x5d, + + LSM6DS3H_REG_MD1_CFG = 0x5e, + LSM6DS3H_REG_MD2_CFG = 0x5f, + + // 0x60-0x65 reserved + + LSM6DS3H_REG_OUT_MAG_RAW_X_L = 0x66, + LSM6DS3H_REG_OUT_MAG_RAW_X_H = 0x67, + LSM6DS3H_REG_OUT_MAG_RAW_Y_L = 0x68, + LSM6DS3H_REG_OUT_MAG_RAW_Y_H = 0x69, + LSM6DS3H_REG_OUT_MAG_RAW_Z_L = 0x6a, + LSM6DS3H_REG_OUT_MAG_RAW_Z_H = 0x6b, + + // 0x6c-0x6f assume reserved, but not listed in DS + + LSM6DS3H_REG_CTRL_SPIAUX = 0x70, + } LSM6DS3H_REGS_T; + + /** + * REG_FUNC_CFG_ACCESS bits + */ + typedef enum { + // 0x00 - 0x40 reserved + LSM6DS3H_FUNC_CFG_EN = 0x80, + } LSM6DS3H_FUNC_CFG_ACCESS_BITS_T; + + /** + * REG_ORIENT_CFG_G bits + */ + typedef enum { + // 0x00 - 0x40 reserved + LSM6DS3H_ORIENT_CFG_G_ORIENT0 = 0x01, + LSM6DS3H_ORIENT_CFG_G_ORIENT1 = 0x02, + LSM6DS3H_ORIENT_CFG_G_ORIENT2 = 0x04, + _LSM6DS3H_ORIENT_CFG_G_ORIENT_MASK = 7, + _LSM6DS3H_ORIENT_CFG_G_ORIENT_SHIFT = 0, + + LSM6DS3H_ORIENT_CFG_G_SIGNZ = 0x08, + LSM6DS3H_ORIENT_CFG_G_SIGNY = 0x10, + LSM6DS3H_ORIENT_CFG_G_SIGNX = 0x20, + + // 0x40-0x80 reserved + } LSM6DS3H_ORIENT_CFG_G_BITS_T; + + /** + * ORIENT_CFG_G_ORIENT values + */ + typedef enum { + LSM6DS3H_ORIENT_CFG_G_XYZ = 0, + LSM6DS3H_ORIENT_CFG_G_XZY = 1, + LSM6DS3H_ORIENT_CFG_G_YXZ = 2, + LSM6DS3H_ORIENT_CFG_G_YZX = 3, + LSM6DS3H_ORIENT_CFG_G_ZXY = 4, + LSM6DS3H_ORIENT_CFG_G_ZYX = 5, + } LSM6DS3H_ORIENT_G_ORIENT_T; + + /** + * REG_INT1_CTRL bits + */ + typedef enum { + LSM6DS3H_INT1_CTRL_DRDY_XL = 0x01, + LSM6DS3H_INT1_CTRL_DRDY_G = 0x02, + LSM6DS3H_INT1_CTRL_BOOT = 0x04, + LSM6DS3H_INT1_CTRL_FTH = 0x08, + LSM6DS3H_INT1_CTRL_FIFO_OVR = 0x10, + LSM6DS3H_INT1_CTRL_FULL_FLAG = 0x20, + LSM6DS3H_INT1_CTRL_SIGN_MOT = 0x40, + LSM6DS3H_INT1_CTRL_STEP_DETECTOR = 0x80, + } LSM6DS3H_INT1_CTRL_BITS_T; + + /** + * REG_INT2_CTRL bits + */ + typedef enum { + LSM6DS3H_INT2_CTRL_DRDY_XL = 0x01, + LSM6DS3H_INT2_CTRL_DRDY_G = 0x02, + LSM6DS3H_INT2_CTRL_DRDY_TEMP = 0x04, + LSM6DS3H_INT2_CTRL_FTH = 0x08, + LSM6DS3H_INT2_CTRL_FIFO_OVR = 0x10, + LSM6DS3H_INT2_CTRL_FULL_FLAG = 0x20, + LSM6DS3H_INT2_CTRL_COUNT_OV = 0x40, + LSM6DS3H_INT2_CTRL_STEP_DELTA = 0x80, + } LSM6DS3H_INT2_CTRL_BITS_T; + + /** + * REG_CTRL1_XL (accelerometer) bits + */ + typedef enum { + LSM6DS3H_CTRL1_XL_BW0 = 0x01, + LSM6DS3H_CTRL1_XL_BW1 = 0x02, + _LSM6DS3H_CTRL1_XL_BW_MASK = 3, + _LSM6DS3H_CTRL1_XL_BW_SHIFT = 0, + + LSM6DS3H_CTRL1_XL_FS0 = 0x04, + LSM6DS3H_CTRL1_XL_FS1 = 0x08, + _LSM6DS3H_CTRL1_XL_FS_MASK = 3, + _LSM6DS3H_CTRL1_XL_FS_SHIFT = 2, + + LSM6DS3H_CTRL1_XL_ODR0 = 0x10, + LSM6DS3H_CTRL1_XL_ODR1 = 0x20, + LSM6DS3H_CTRL1_XL_ODR2 = 0x40, + LSM6DS3H_CTRL1_XL_ODR3 = 0x80, + _LSM6DS3H_CTRL1_XL_ODR_MASK = 15, + _LSM6DS3H_CTRL1_XL_ODR_SHIFT = 4, + } LSM6DS3H_CTRL1_XL_BITS_T; + + /** + * CTRL1_XL_BW values (anti-aliasing filter bw) + */ + typedef enum { + LSM6DS3H_XL_BW_400HZ = 0, + LSM6DS3H_XL_BW_200HZ = 1, + LSM6DS3H_XL_BW_100HZ = 2, + LSM6DS3H_XL_BW_50HZ = 3, + } LSM6DS3H_XL_BW_T; + + /** + * CTRL1_XL_FS values (full scale) + */ + typedef enum { + LSM6DS3H_XL_FS_2G = 0, + LSM6DS3H_XL_FS_16G = 1, + LSM6DS3H_XL_FS_4G = 2, + LSM6DS3H_XL_FS_8G = 3, + } LSM6DS3H_XL_FS_T; + + /** + * CTRL1_XL_ODR values (output data rate) + */ + typedef enum { + LSM6DS3H_XL_ODR_POWER_DOWN = 0, + LSM6DS3H_XL_ODR_12_5HZ = 1, + LSM6DS3H_XL_ODR_26HZ = 2, + LSM6DS3H_XL_ODR_52HZ = 3, + LSM6DS3H_XL_ODR_104HZ = 4, + LSM6DS3H_XL_ODR_208HZ = 5, + LSM6DS3H_XL_ODR_416HZ = 6, + LSM6DS3H_XL_ODR_833HZ = 7, + LSM6DS3H_XL_ODR_1_66KHZ = 8, + LSM6DS3H_XL_ODR_3_33KHZ = 9, + LSM6DS3H_XL_ODR_6_66KHZ = 10, + } LSM6DS3H_XL_ODR_T; + + /** + * REG_CTRL2_G (gyroscope) bits + */ + typedef enum { + // 0x01 reserved + + LSM6DS3H_CTRL2_G_FS_125 = 0x02, + + LSM6DS3H_CTRL2_G_FS0 = 0x04, + LSM6DS3H_CTRL2_G_FS1 = 0x08, + _LSM6DS3H_CTRL2_G_FS_MASK = 3, + _LSM6DS3H_CTRL2_G_FS_SHIFT = 2, + + LSM6DS3H_CTRL2_G_ODR0 = 0x10, + LSM6DS3H_CTRL2_G_ODR1 = 0x20, + LSM6DS3H_CTRL2_G_ODR2 = 0x40, + LSM6DS3H_CTRL2_G_ODR3 = 0x80, + _LSM6DS3H_CTRL2_G_ODR_MASK = 0x15, + _LSM6DS3H_CTRL2_G_ODR_SHIFT = 0x4, + } LSM6DS3H_CTRL2_G_BITS_T; + + /** + * CTRL2_G_FS values (full scale) + */ + typedef enum { + LSM6DS3H_G_FS_245DPS = 0, // degrees per second + LSM6DS3H_G_FS_500DPS = 1, + LSM6DS3H_G_FS_1000DPS = 2, + LSM6DS3H_G_FS_2000DPS = 3, + + // 125dps is a special case - it's just a bit you set or clear + // to enable 125 or disable it. We add a virtual bit 3 (4) + // here as a flag to the driver to enable/disable this + // "special" FS setting. + LSM6DS3H_G_FS_125DPS = (4 + 0), + } LSM6DS3H_G_FS_T; + + /** + * CTRL2_G_ODR values (output data rate) + */ + typedef enum { + LSM6DS3H_G_ODR_POWER_DOWN = 0, + LSM6DS3H_G_ODR_12_5HZ = 1, + LSM6DS3H_G_ODR_26HZ = 2, + LSM6DS3H_G_ODR_52HZ = 3, + LSM6DS3H_G_ODR_104HZ = 4, + LSM6DS3H_G_ODR_208HZ = 5, + LSM6DS3H_G_ODR_416HZ = 6, + LSM6DS3H_G_ODR_833HZ = 7, + LSM6DS3H_G_ODR_1_66KHZ = 8, + } LSM6DS3H_G_ODR_T; + + /** + * REG_CTRL3 (_C, common) bits + */ + typedef enum { + LSM6DS3H_CTRL3_SW_RESET = 0x01, + LSM6DS3H_CTRL3_BLE = 0x02, + LSM6DS3H_CTRL3_IF_INC = 0x04, + LSM6DS3H_CTRL3_SIM = 0x08, + LSM6DS3H_CTRL3_PP_OD = 0x10, + LSM6DS3H_CTRL3_H_LACTIVE = 0x20, + LSM6DS3H_CTRL3_BDU = 0x40, + LSM6DS3H_CTRL3_BOOT = 0x80, + } LSM6DS3H_CTRL3_BITS_T; + + /** + * REG_CTRL4 (_C, common) bits + */ + typedef enum { + LSM6DS3H_CTRL4_STOP_ON_FTH = 0x01, + LSM6DS3H_CTRL4_3_3KHZ_ODR = 0x02, + LSM6DS3H_CTRL4_I2C_DISABLE = 0x04, + LSM6DS3H_CTRL4_DRDY_MASK = 0x08, + LSM6DS3H_CTRL4_FIFO_TEMP_EN = 0x10, + LSM6DS3H_CTRL4_INT2_ON_INT1 = 0x20, + LSM6DS3H_CTRL4_SLEEP_G = 0x40, + LSM6DS3H_CTRL4_XL_BW_SCAL_ODR = 0x80, + } LSM6DS3H_CTRL4_BITS_T; + + /** + * REG_CTRL5 (_C, common) bits + */ + typedef enum { + LSM6DS3H_CTRL5_ST_XL0 = 0x01, + LSM6DS3H_CTRL5_ST_XL1 = 0x02, + _LSM6DS3H_CTRL5_ST_XL_MASK = 3, + _LSM6DS3H_CTRL5_ST_XL_SHIFT = 0, + + LSM6DS3H_CTRL5_ST_G0 = 0x04, + LSM6DS3H_CTRL5_ST_G1 = 0x08, + _LSM6DS3H_CTRL5_ST_G_MASK = 3, + _LSM6DS3H_CTRL5_ST_G_SHIFT = 2, + + // 0x10 reserved + + LSM6DS3H_CTRL5_ROUNDING0 = 0x20, + LSM6DS3H_CTRL5_ROUNDING1 = 0x40, + LSM6DS3H_CTRL5_ROUNDING2 = 0x80, + LSM6DS3H_CTRL5_ROUNDING_MASK = 7, + LSM6DS3H_CTRL5_ROUNDING_SHIFT = 5, + } LSM6DS3H_CTRL5_BITS_T; + + /** + * CTRL5_ST_XL values (self test accelerometer) + */ + typedef enum { + LSM6DS3H_ST_XL_NORMAL = 0, + LSM6DS3H_ST_XL_POSITIVE = 1, + LSM6DS3H_ST_XL_NEGATIVE = 2, + } LSM6DS3H_ST_XL_T; + + /** + * CTRL5_ST_G values (self test gyroscope) + */ + typedef enum { + LSM6DS3H_ST_G_NORMAL = 0, + LSM6DS3H_ST_G_POSITIVE = 1, + LSM6DS3H_ST_G_NEGATIVE = 3, + } LSM6DS3H_ST_G_T; + + /** + * REG_CTRL6 (_C, common) bits + */ + typedef enum { + // 0x01-0x08 reserved + LSM6DS3H_CTRL6_XL_HM_MODE = 0x10, + LSM6DS3H_CTRL6_LVL2_EN = 0x20, + LSM6DS3H_CTRL6_LVLEN = 0x40, + LSM6DS3H_CTRL6_TRIG_EN = 0x80, + } LSM6DS3H_CTRL6_BITS_T; + + /** + * REG_CTRL7_G bits + */ + typedef enum { + // 0x01-0x02 reserved + LSM6DS3H_CTRL7_G_ROUNDING_STATUS = 0x04, + LSM6DS3H_CTRL7_G_HP_RST = 0x08, + + LSM6DS3H_CTRL7_G_HPCF0 = 0x10, + LSM6DS3H_CTRL7_G_HPCF1 = 0x20, + _LSM6DS3H_CTRL7_G_HPCF_MASK = 3, + _LSM6DS3H_CTRL7_G_HPCF_SHIFT = 4, + + LSM6DS3H_CTRL7_G_HP_EN = 0x40, + LSM6DS3H_CTRL7_G_HM_MODE = 0x80, + } LSM6DS3H_CTRL7_G_BITS_T; + + /** + * CTRL7_G_HPCF values (high pass cutoff, in high performance mode only) + */ + typedef enum { + LSM6DS3H_G_HPCF_0_0081HZ = 0, // 0.0081hz + LSM6DS3H_G_HPCF_0_0324HZ = 1, + LSM6DS3H_G_HPCF_2_07HZ = 2, + LSM6DS3H_G_HPCF_16_32HZ = 3, + } LSM6DS3H_G_HPCF_T; + + /** + * REG_CTRL8_XL bits + */ + typedef enum { + LSM6DS3H_CTRL8_XL_LOW_PASS_ON_6D = 0x01, + + // 0x02 reserved + + LSM6DS3H_CTRL8_XL_HP_SLOPE_EN = 0x04, + + // 0x08-0x10 reserved + + LSM6DS3H_CTRL8_XL_HPCF0 = 0x20, + LSM6DS3H_CTRL8_XL_HPCF1 = 0x40, + _LSM6DS3H_CTRL8_XL_HPCF_MASK = 3, + _LSM6DS3H_CTRL8_XL_HPCF_SHIFT = 5, + + LSM6DS3H_CTRL8_XL_LPF2_EN = 0x80, + } LSM6DS3H_CTRL8_XL_BITS_T; + + /** + * REG_CTRL9_XL bits + */ + typedef enum { + // 0x01-0x02 reserved + + LSM6DS3H_CTRL9_XL_SOFT_EN = 0x04, + LSM6DS3H_CTRL9_XL_XEN = 0x08, + LSM6DS3H_CTRL9_XL_YEN = 0x10, + LSM6DS3H_CTRL9_XL_ZEN = 0x20, + + // 0x40-0x80 reserved + } LSM6DS3H_CTRL9_XL_BITS_T; + + /** + * REG_CTRL10_G bits + */ + typedef enum { + LSM6DS3H_CTRL10_G_SIGN_MOT_EN = 0x01, + LSM6DS3H_CTRL10_G_PEDO_RST_STEP = 0x02, + LSM6DS3H_CTRL10_G_FUNC_EN = 0x04, + LSM6DS3H_CTRL10_G_XEN = 0x08, + LSM6DS3H_CTRL10_G_YEN = 0x10, + LSM6DS3H_CTRL10_G_ZEN = 0x20, + + // 0x40-0x80 reserved + } LSM6DS3H_CTRL10_G_BITS_T; + + /** + * REG_MASTER_CONFIG bits + */ + typedef enum { + LSM6DS3H_MASTER_CONFIG_MASTER_ON = 0x01, + LSM6DS3H_MASTER_CONFIG_IRON_EN = 0x02, + LSM6DS3H_MASTER_CONFIG_PASS_THROUGH_MODE = 0x04, + LSM6DS3H_MASTER_CONFIG_PULL_UP_EN = 0x08, + LSM6DS3H_MASTER_CONFIG_START_CONFIG = 0x10, + + // 0x20 reserved + + LSM6DS3H_MASTER_CONFIG_DATA_VALID_SEL_FIFO = 0x40, + LSM6DS3H_MASTER_CONFIG_DRDY_ON_INT1 = 0x80, + + // 0x40-0x80 reserved + } LSM6DS3H_MASTER_CONFIG_BITS_T; + + /** + * REG_WAKE_UP_SRC bits + */ + typedef enum { + LSM6DS3H_WAKE_UP_SRC_Z_WU = 0x01, + LSM6DS3H_WAKE_UP_SRC_Y_WU = 0x02, + LSM6DS3H_WAKE_UP_SRC_X_WU = 0x04, + LSM6DS3H_WAKE_UP_SRC_WU_IA = 0x08, + LSM6DS3H_WAKE_UP_SRC_SLEEP_STATE_IA = 0x10, + LSM6DS3H_WAKE_UP_SRC_FF_AA = 0x20, + + // 0x40-0x80 reserved + } LSM6DS3H_WAKE_UP_SRC_BITS_T; + + /** + * REG_TAP_SRC bits + */ + typedef enum { + LSM6DS3H_TAP_SRC_Z_TAP = 0x01, + LSM6DS3H_TAP_SRC_Y_TAP = 0x02, + LSM6DS3H_TAP_SRC_X_TAP = 0x04, + LSM6DS3H_TAP_SRC_TAP_SIGN = 0x08, + LSM6DS3H_TAP_SRC_DOUBLE_TAP = 0x10, + LSM6DS3H_TAP_SRC_SINGLE_TAP = 0x20, + LSM6DS3H_TAP_SRC_TAP_IA = 0x40, + + // 0x80 reserved + } LSM6DS3H_TAP_SRC_BITS_T; + + /** + * REG_D6D_SRC bits + */ + typedef enum { + LSM6DS3H_D6D_SRC_XL = 0x01, + LSM6DS3H_D6D_SRC_XH = 0x02, + LSM6DS3H_D6D_SRC_YL = 0x04, + LSM6DS3H_D6D_SRC_YH = 0x08, + LSM6DS3H_D6D_SRC_ZL = 0x10, + LSM6DS3H_D6D_SRC_ZH = 0x20, + LSM6DS3H_D6D_SRC_D6D_IA = 0x40, + + // 0x80 reserved + } LSM6DS3H_D6D_SRC_BITS_T; + + /** + * REG_STATUS bits + */ + typedef enum { + LSM6DS3H_STATUS_XLDA = 0x01, // acc data avail + LSM6DS3H_STATUS_GDA = 0x02, // gyr data avail + LSM6DS3H_STATUS_TDA = 0x04, // temp data avail + + // 0x08-0x80 reserved + } LSM6DS3H_STATUS_BITS_T; + + /** + * REG_FUNC_SRC bits + */ + typedef enum { + LSM6DS3H_FUNC_SRC_SENSORHUB_END_OP = 0x01, + LSM6DS3H_FUNC_SRC_SI_END_OP = 0x02, + + // 0x04 reserved + + LSM6DS3H_FUNC_SRC_STEP_OVERFLOW = 0x08, + LSM6DS3H_FUNC_SRC_STEP_DETECTED = 0x10, + LSM6DS3H_FUNC_SRC_TILT_IA = 0x20, + LSM6DS3H_FUNC_SRC_SIGN_MOTION_IA = 0x40, + LSM6DS3H_FUNC_SRC_STEP_COUNT_DELTA_IA = 0x80, + } LSM6DS3H_FUNC_SRC_BITS_T; + + /** + * REG_MD1_CFG bits (function routing to INT1). We are omitting + * the "INT1" redundancy in these item names. + */ + typedef enum { + LSM6DS3H_MD1_CFG_TIMER = 0x01, + LSM6DS3H_MD1_CFG_TILT = 0x02, + LSM6DS3H_MD1_CFG_6D = 0x04, + LSM6DS3H_MD1_CFG_DOUBLE_TAP = 0x08, + LSM6DS3H_MD1_CFG_FF = 0x10, + LSM6DS3H_MD1_CFG_WU = 0x20, + LSM6DS3H_MD1_CFG_SINGLE_TAP = 0x40, + LSM6DS3H_MD1_CFG_INACT_STATE = 0x80, + } LSM6DS3H_MD1_CFG_BITS_T; + + /** + * REG_MD2_CFG bits (function routing to INT2). We are omitting + * the "INT2" redundancy in these item names. + */ + typedef enum { + LSM6DS3H_MD2_CFG_IRON = 0x01, + LSM6DS3H_MD2_CFG_TILT = 0x02, + LSM6DS3H_MD2_CFG_6D = 0x04, + LSM6DS3H_MD2_CFG_DOUBLE_TAP = 0x08, + LSM6DS3H_MD2_CFG_FF = 0x10, + LSM6DS3H_MD2_CFG_WU = 0x20, + LSM6DS3H_MD2_CFG_SINGLE_TAP = 0x40, + LSM6DS3H_MD2_CFG_INACT_STATE = 0x80, + } LSM6DS3H_MD2_CFG_BITS_T; + + // interrupt selection for installISR() and uninstallISR() + typedef enum { + LSM6DS3H_INTERRUPT_INT1, + LSM6DS3H_INTERRUPT_INT2 + } LSM6DS3H_INTERRUPT_PINS_T; + + +#ifdef __cplusplus +} +#endif diff --git a/src/lsm6ds3h/lsm6ds3h_fti.c b/src/lsm6ds3h/lsm6ds3h_fti.c new file mode 100644 index 00000000..78d8d486 --- /dev/null +++ b/src/lsm6ds3h/lsm6ds3h_fti.c @@ -0,0 +1,127 @@ +/* + * 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 "lsm6ds3h.h" +#include "upm_fti.h" + +/** + * This file implements the Function Table Interface (FTI) for this sensor + */ + +const char upm_lsm6ds3h_name[] = "LSM6DS3H"; +const char upm_lsm6ds3h_description[] = + "Triple Axis Digital Accelerometer and Gyroscope"; +const upm_protocol_t upm_lsm6ds3h_protocol[] = {UPM_I2C, UPM_SPI, UPM_GPIO}; +const upm_sensor_t upm_lsm6ds3h_category[] = {UPM_ACCELEROMETER, + UPM_GYROSCOPE}; + +// forward declarations +const void *upm_lsm6ds3h_get_ft(upm_sensor_t sensor_type); +void *upm_lsm6ds3h_init_name(); +void upm_lsm6ds3h_close(void *dev); +upm_result_t upm_lsm6ds3h_get_acc_value(void *dev, float *value, + upm_acceleration_u unit); +upm_result_t upm_lsm6ds3h_get_gyr_value(void *dev, float *value); + +const upm_sensor_descriptor_t upm_lsm6ds3h_get_descriptor() +{ + upm_sensor_descriptor_t usd; + usd.name = upm_lsm6ds3h_name; + usd.description = upm_lsm6ds3h_description; + usd.protocol_size = 3; + usd.protocol = upm_lsm6ds3h_protocol; + usd.category_size = 2; + usd.category = upm_lsm6ds3h_category; + return usd; +} + +static const upm_sensor_ft ft = +{ + .upm_sensor_init_name = upm_lsm6ds3h_init_name, + .upm_sensor_close = upm_lsm6ds3h_close, +}; + +static const upm_acceleration_ft aft = +{ + .upm_acceleration_get_value = upm_lsm6ds3h_get_acc_value +}; + +static const upm_gyroscope_ft gft = +{ + .upm_gyroscope_get_value = upm_lsm6ds3h_get_gyr_value +}; + +const void *upm_lsm6ds3h_get_ft(upm_sensor_t sensor_type) +{ + switch(sensor_type) + { + case UPM_SENSOR: + return &ft; + + case UPM_ACCELEROMETER: + return &aft; + + case UPM_GYROSCOPE: + return &gft; + + default: + return NULL; + } +} + +void *upm_lsm6ds3h_init_name() +{ + return NULL; +} + +void upm_lsm6ds3h_close(void *dev) +{ + lsm6ds3h_close((lsm6ds3h_context)dev); +} + +upm_result_t upm_lsm6ds3h_get_acc_value(void *dev, float *value, + upm_acceleration_u unit) +{ + if (lsm6ds3h_update((lsm6ds3h_context)dev)) + return UPM_ERROR_OPERATION_FAILED; + + // no conversion facility in place yet, so we don't do anything + // with units + + lsm6ds3h_get_accelerometer(dev, &value[0], &value[1], &value[2]); + + return UPM_SUCCESS; +} + +upm_result_t upm_lsm6ds3h_get_gyr_value(void *dev, float *value) +{ + if (lsm6ds3h_update((lsm6ds3h_context)dev)) + return UPM_ERROR_OPERATION_FAILED; + + lsm6ds3h_get_gyroscope(dev, &value[0], &value[1], &value[2]); + + return UPM_SUCCESS; +} diff --git a/src/lsm6ds3h/pyupm_lsm6ds3h.i b/src/lsm6ds3h/pyupm_lsm6ds3h.i new file mode 100644 index 00000000..6fb0d375 --- /dev/null +++ b/src/lsm6ds3h/pyupm_lsm6ds3h.i @@ -0,0 +1,17 @@ +// Include doxygen-generated documentation +%include "pyupm_doxy2swig.i" +%module pyupm_lsm6ds3h +%include "../upm.i" +%include "../upm_vectortypes.i" + +%feature("autodoc", "3"); + +#ifdef DOXYGEN +%include "lsm6ds3h_doc.i" +#endif + +%include "lsm6ds3h_defs.h" +%include "lsm6ds3h.hpp" +%{ + #include "lsm6ds3h.hpp" +%}