From 8fb7907a4e0a7bb91a7cd9a0ee62da6a168d1947 Mon Sep 17 00:00:00 2001 From: Jon Trulson Date: Fri, 6 May 2016 17:56:51 -0600 Subject: [PATCH] bmx055, bmi055, bmc160, bma250e, bmg150, bmm150: Initial implementation This module (bmx055) implements support for the following core Bosch chipsets: bma250e - accelerometer, 3 variants (chip id's 0x03, 0xf9, and 0xfa) bmm150 - magnetometer bmg160 - gyroscope The other 3 devices are combinations of the above: bmx055 - accel/gyro/mag bmc160 - accel/mag bmi055 - accel/gyro ...for 6 devices total. For the combination devices, all of the sub-devices appear as individual independent devices on the I2C/SPI bus. The combination drivers provide basic configuration and data output. For more detailed control as well as interrupt support, you should use the core device drivers (accel/gyro/mag) directly. These devices support both I2C and SPI communications. They must be powered at 3.3vdc. Signed-off-by: Jon Trulson --- examples/c++/CMakeLists.txt | 6 + examples/c++/bma250e.cxx | 83 ++ examples/c++/bmc150.cxx | 82 ++ examples/c++/bmg160.cxx | 83 ++ examples/c++/bmi055.cxx | 82 ++ examples/c++/bmm150.cxx | 78 ++ examples/c++/bmx055.cxx | 89 ++ examples/java/BMA250E_Example.java | 64 ++ examples/java/BMC150_Example.java | 61 ++ examples/java/BMG160_Example.java | 64 ++ examples/java/BMI055_Example.java | 61 ++ examples/java/BMM150_Example.java | 58 ++ examples/java/BMX055_Example.java | 69 ++ examples/java/CMakeLists.txt | 6 + examples/javascript/bma250e.js | 72 ++ examples/javascript/bmc150.js | 69 ++ examples/javascript/bmg160.js | 72 ++ examples/javascript/bmi055.js | 69 ++ examples/javascript/bmm150.js | 65 ++ examples/javascript/bmx055.js | 76 ++ examples/python/bma250e.py | 66 ++ examples/python/bmc150.py | 65 ++ examples/python/bmg160.py | 66 ++ examples/python/bmi055.py | 65 ++ examples/python/bmm150.py | 62 ++ examples/python/bmx055.py | 71 ++ src/bmx055/CMakeLists.txt | 5 + src/bmx055/bma250e.cxx | 735 ++++++++++++++ src/bmx055/bma250e.hpp | 1461 ++++++++++++++++++++++++++++ src/bmx055/bmc150.cxx | 120 +++ src/bmx055/bmc150.hpp | 196 ++++ src/bmx055/bmg160.cxx | 581 +++++++++++ src/bmx055/bmg160.hpp | 1223 +++++++++++++++++++++++ src/bmx055/bmi055.cxx | 122 +++ src/bmx055/bmi055.hpp | 193 ++++ src/bmx055/bmm150.cxx | 675 +++++++++++++ src/bmx055/bmm150.hpp | 614 ++++++++++++ src/bmx055/bmx055.cxx | 158 +++ src/bmx055/bmx055.hpp | 248 +++++ src/bmx055/javaupm_bmx055.i | 77 ++ src/bmx055/jsupm_bmx055.i | 37 + src/bmx055/pyupm_bmx055.i | 47 + 42 files changed, 8196 insertions(+) create mode 100644 examples/c++/bma250e.cxx create mode 100644 examples/c++/bmc150.cxx create mode 100644 examples/c++/bmg160.cxx create mode 100644 examples/c++/bmi055.cxx create mode 100644 examples/c++/bmm150.cxx create mode 100644 examples/c++/bmx055.cxx create mode 100644 examples/java/BMA250E_Example.java create mode 100644 examples/java/BMC150_Example.java create mode 100644 examples/java/BMG160_Example.java create mode 100644 examples/java/BMI055_Example.java create mode 100644 examples/java/BMM150_Example.java create mode 100644 examples/java/BMX055_Example.java create mode 100644 examples/javascript/bma250e.js create mode 100644 examples/javascript/bmc150.js create mode 100644 examples/javascript/bmg160.js create mode 100644 examples/javascript/bmi055.js create mode 100644 examples/javascript/bmm150.js create mode 100644 examples/javascript/bmx055.js create mode 100644 examples/python/bma250e.py create mode 100644 examples/python/bmc150.py create mode 100644 examples/python/bmg160.py create mode 100644 examples/python/bmi055.py create mode 100644 examples/python/bmm150.py create mode 100644 examples/python/bmx055.py create mode 100644 src/bmx055/CMakeLists.txt create mode 100644 src/bmx055/bma250e.cxx create mode 100644 src/bmx055/bma250e.hpp create mode 100644 src/bmx055/bmc150.cxx create mode 100644 src/bmx055/bmc150.hpp create mode 100644 src/bmx055/bmg160.cxx create mode 100644 src/bmx055/bmg160.hpp create mode 100644 src/bmx055/bmi055.cxx create mode 100644 src/bmx055/bmi055.hpp create mode 100644 src/bmx055/bmm150.cxx create mode 100644 src/bmx055/bmm150.hpp create mode 100644 src/bmx055/bmx055.cxx create mode 100644 src/bmx055/bmx055.hpp create mode 100644 src/bmx055/javaupm_bmx055.i create mode 100644 src/bmx055/jsupm_bmx055.i create mode 100644 src/bmx055/pyupm_bmx055.i diff --git a/examples/c++/CMakeLists.txt b/examples/c++/CMakeLists.txt index 4f6a127b..524ec973 100644 --- a/examples/c++/CMakeLists.txt +++ b/examples/c++/CMakeLists.txt @@ -269,6 +269,7 @@ add_example (ds18b20) add_example (bmp280) add_example (bno055) add_example (l3gd20) +add_example (bmx055) # These are special cases where you specify example binary, source file and module(s) include_directories (${PROJECT_SOURCE_DIR}/src) @@ -295,3 +296,8 @@ add_custom_example (adc-example adc-sensor.cxx "ads1x15") add_custom_example (light-sensor-example light-sensor.cxx "si1132;max44009") add_custom_example (light-controller-example light-controller.cxx "lp8860;ds1808lc;hlg150h") add_custom_example (bme280-example bme280.cxx bmp280) +add_custom_example (bma250e-example bma250e.cxx bmx055) +add_custom_example (bmg160-example bmg160.cxx bmx055) +add_custom_example (bmm150-example bmm150.cxx bmx055) +add_custom_example (bmc150-example bmc150.cxx bmx055) +add_custom_example (bmi055-example bmi055.cxx bmx055) diff --git a/examples/c++/bma250e.cxx b/examples/c++/bma250e.cxx new file mode 100644 index 00000000..0391617d --- /dev/null +++ b/examples/c++/bma250e.cxx @@ -0,0 +1,83 @@ +/* + * 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 "bma250e.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 BMA250E using default I2C parameters + upm::BMA250E *sensor = new upm::BMA250E(); + + // For SPI, bus 0, you would pass -1 as the address, and a valid pin + // for CS: BMA250E(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; + + // 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; + + delete sensor; + + return 0; +} diff --git a/examples/c++/bmc150.cxx b/examples/c++/bmc150.cxx new file mode 100644 index 00000000..46006436 --- /dev/null +++ b/examples/c++/bmc150.cxx @@ -0,0 +1,82 @@ +/* + * 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 "bmc150.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 BMC150 using default I2C parameters + upm::BMC150 *sensor = new upm::BMC150(); + + // 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->getMagnetometer(&x, &y, &z); + cout << "Magnetometer x: " << x + << " y: " << y + << " z: " << z + << " uT" + << endl; + + cout << endl; + + usleep(250000); + } + +//! [Interesting] + + cout << "Exiting..." << endl; + + delete sensor; + + return 0; +} diff --git a/examples/c++/bmg160.cxx b/examples/c++/bmg160.cxx new file mode 100644 index 00000000..c305b272 --- /dev/null +++ b/examples/c++/bmg160.cxx @@ -0,0 +1,83 @@ +/* + * 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 "bmg160.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 BMG160 using default I2C parameters + upm::BMG160 *sensor = new upm::BMG160(); + + // For SPI, bus 0, you would pass -1 as the address, and a valid pin + // for CS: BMG160(0, -1, 10); + + // now output data every 250 milliseconds + while (shouldRun) + { + float x, y, z; + + sensor->update(); + + sensor->getGyroscope(&x, &y, &z); + cout << "Gyroscope x: " << x + << " y: " << y + << " z: " << z + << " degrees/s" + << 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; + + delete sensor; + + return 0; +} diff --git a/examples/c++/bmi055.cxx b/examples/c++/bmi055.cxx new file mode 100644 index 00000000..e88fe167 --- /dev/null +++ b/examples/c++/bmi055.cxx @@ -0,0 +1,82 @@ +/* + * 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 "bmi055.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 BMI055 using default I2C parameters + upm::BMI055 *sensor = new upm::BMI055(); + + // 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 + << " degrees/s" + << endl; + + cout << endl; + + usleep(250000); + } + +//! [Interesting] + + cout << "Exiting..." << endl; + + delete sensor; + + return 0; +} diff --git a/examples/c++/bmm150.cxx b/examples/c++/bmm150.cxx new file mode 100644 index 00000000..400f1a9c --- /dev/null +++ b/examples/c++/bmm150.cxx @@ -0,0 +1,78 @@ +/* + * 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 "bmm150.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 BMM150 using default I2C parameters + upm::BMM150 *sensor = new upm::BMM150(); + + // For SPI, bus 0, you would pass -1 as the address, and a valid pin + // for CS: BMM150(0, -1, 10); + + // now output data every 250 milliseconds + while (shouldRun) + { + float x, y, z; + + sensor->update(); + + sensor->getMagnetometer(&x, &y, &z); + cout << "Magnetometer x: " << x + << " y: " << y + << " z: " << z + << " uT" + << endl; + + cout << endl; + + usleep(250000); + } + +//! [Interesting] + + cout << "Exiting..." << endl; + + delete sensor; + + return 0; +} diff --git a/examples/c++/bmx055.cxx b/examples/c++/bmx055.cxx new file mode 100644 index 00000000..31626f49 --- /dev/null +++ b/examples/c++/bmx055.cxx @@ -0,0 +1,89 @@ +/* + * 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 "bmx055.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 BMX055 using default I2C parameters + upm::BMX055 *sensor = new upm::BMX055(); + + // 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 + << " degrees/s" + << endl; + + sensor->getMagnetometer(&x, &y, &z); + cout << "Magnetometer x: " << x + << " y: " << y + << " z: " << z + << " uT" + << endl; + + cout << endl; + + usleep(250000); + } + +//! [Interesting] + + cout << "Exiting..." << endl; + + delete sensor; + + return 0; +} diff --git a/examples/java/BMA250E_Example.java b/examples/java/BMA250E_Example.java new file mode 100644 index 00000000..dd138ad3 --- /dev/null +++ b/examples/java/BMA250E_Example.java @@ -0,0 +1,64 @@ +/* + * 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. + */ + +import upm_bmx055.BMA250E; + +public class BMA250E_Example +{ + public static void main(String[] args) throws InterruptedException + { +// ! [Interesting] + + // Instantiate a BMA250E instance using default i2c bus and address + BMA250E sensor = new BMA250E(); + + // For SPI, bus 0, you would pass -1 as the address, and a + // valid pin for CS: + // BMA250E(0, -1, 10); + + while (true) + { + // update our values from the sensor + sensor.update(); + + float dataA[] = sensor.getAccelerometer(); + + System.out.println("Accelerometer x: " + dataA[0] + + " y: " + dataA[1] + + " z: " + dataA[2] + + " g"); + + System.out.println("Compensation Temperature: " + + sensor.getTemperature() + + " C / " + + sensor.getTemperature(true) + + " F"); + + System.out.println(); + Thread.sleep(250); + } + +// ! [Interesting] + } +} diff --git a/examples/java/BMC150_Example.java b/examples/java/BMC150_Example.java new file mode 100644 index 00000000..bcd37af6 --- /dev/null +++ b/examples/java/BMC150_Example.java @@ -0,0 +1,61 @@ +/* + * 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. + */ + +import upm_bmx055.BMC150; + +public class BMC150_Example +{ + public static void main(String[] args) throws InterruptedException + { +// ! [Interesting] + + // Instantiate a BMC150 instance using default i2c bus and address + BMC150 sensor = new BMC150(); + + while (true) + { + // update our values from the sensor + sensor.update(); + + float data[] = sensor.getAccelerometer(); + + System.out.println("Accelerometer x: " + data[0] + + " y: " + data[1] + + " z: " + data[2] + + " g"); + + data = sensor.getMagnetometer(); + + System.out.println("Magnetometer x: " + data[0] + + " y: " + data[1] + + " z: " + data[2] + + " uT"); + + System.out.println(); + Thread.sleep(250); + } + +// ! [Interesting] + } +} diff --git a/examples/java/BMG160_Example.java b/examples/java/BMG160_Example.java new file mode 100644 index 00000000..09667b94 --- /dev/null +++ b/examples/java/BMG160_Example.java @@ -0,0 +1,64 @@ +/* + * 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. + */ + +import upm_bmx055.BMG160; + +public class BMG160_Example +{ + public static void main(String[] args) throws InterruptedException + { +// ! [Interesting] + + // Instantiate a BMG160 instance using default i2c bus and address + BMG160 sensor = new BMG160(); + + // For SPI, bus 0, you would pass -1 as the address, and a + // valid pin for CS: + // BMG160(0, -1, 10); + + while (true) + { + // update our values from the sensor + sensor.update(); + + float dataA[] = sensor.getGyroscope(); + + System.out.println("Gyroscope x: " + dataA[0] + + " y: " + dataA[1] + + " z: " + dataA[2] + + " degrees/s"); + + System.out.println("Compensation Temperature: " + + sensor.getTemperature() + + " C / " + + sensor.getTemperature(true) + + " F"); + + System.out.println(); + Thread.sleep(250); + } + +// ! [Interesting] + } +} diff --git a/examples/java/BMI055_Example.java b/examples/java/BMI055_Example.java new file mode 100644 index 00000000..fc11696f --- /dev/null +++ b/examples/java/BMI055_Example.java @@ -0,0 +1,61 @@ +/* + * 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. + */ + +import upm_bmx055.BMI055; + +public class BMI055_Example +{ + public static void main(String[] args) throws InterruptedException + { +// ! [Interesting] + + // Instantiate a BMI055 instance using default i2c bus and address + BMI055 sensor = new BMI055(); + + while (true) + { + // update our values from the sensor + sensor.update(); + + float data[] = sensor.getAccelerometer(); + + System.out.println("Accelerometer x: " + data[0] + + " y: " + data[1] + + " z: " + data[2] + + " g"); + + data = sensor.getGyroscope(); + + System.out.println("Gyroscope x: " + data[0] + + " y: " + data[1] + + " z: " + data[2] + + " degrees/s"); + + System.out.println(); + Thread.sleep(250); + } + +// ! [Interesting] + } +} diff --git a/examples/java/BMM150_Example.java b/examples/java/BMM150_Example.java new file mode 100644 index 00000000..fc34ac75 --- /dev/null +++ b/examples/java/BMM150_Example.java @@ -0,0 +1,58 @@ +/* + * 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. + */ + +import upm_bmx055.BMM150; + +public class BMM150_Example +{ + public static void main(String[] args) throws InterruptedException + { +// ! [Interesting] + + // Instantiate a BMM150 instance using default i2c bus and address + BMM150 sensor = new BMM150(); + + // For SPI, bus 0, you would pass -1 as the address, and a + // valid pin for CS: + // BMM150(0, -1, 10); + + while (true) + { + // update our values from the sensor + sensor.update(); + + float dataA[] = sensor.getMagnetometer(); + + System.out.println("Magnetometer x: " + dataA[0] + + " y: " + dataA[1] + + " z: " + dataA[2] + + " uT"); + + System.out.println(); + Thread.sleep(250); + } + +// ! [Interesting] + } +} diff --git a/examples/java/BMX055_Example.java b/examples/java/BMX055_Example.java new file mode 100644 index 00000000..2abb0da2 --- /dev/null +++ b/examples/java/BMX055_Example.java @@ -0,0 +1,69 @@ +/* + * 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. + */ + +import upm_bmx055.BMX055; + +public class BMX055_Example +{ + public static void main(String[] args) throws InterruptedException + { +// ! [Interesting] + + // Instantiate a BMX055 instance using default i2c bus and address + BMX055 sensor = new BMX055(); + + while (true) + { + // update our values from the sensor + sensor.update(); + + float data[] = sensor.getAccelerometer(); + + System.out.println("Accelerometer x: " + data[0] + + " y: " + data[1] + + " z: " + data[2] + + " g"); + + data = sensor.getGyroscope(); + + System.out.println("Gyroscope x: " + data[0] + + " y: " + data[1] + + " z: " + data[2] + + " degrees/s"); + + + data = sensor.getMagnetometer(); + + System.out.println("Magnetometer x: " + data[0] + + " y: " + data[1] + + " z: " + data[2] + + " uT"); + + System.out.println(); + Thread.sleep(250); + } + +// ! [Interesting] + } +} diff --git a/examples/java/CMakeLists.txt b/examples/java/CMakeLists.txt index c91553e3..7a6bf615 100644 --- a/examples/java/CMakeLists.txt +++ b/examples/java/CMakeLists.txt @@ -128,6 +128,7 @@ endif() add_example(VCAP_Example vcap) add_example(BMP280_Example bmp280) add_example(BNO055_Example bno055) +add_example(BMX055_Example bmx055) add_example_with_path(Jhd1313m1_lcdSample lcd i2clcd) add_example_with_path(Jhd1313m1Sample lcd i2clcd) @@ -136,4 +137,9 @@ add_example_with_path(Lcm1602_parallelSample lcd i2clcd) add_example_with_path(SSD1308_oledSample lcd i2clcd) add_example_with_path(SSD1327_oledSample lcd i2clcd) add_example_with_path(BME280_Example bmp280 bmp280) +add_example_with_path(BMA250E_Example bmx055 bmx055) +add_example_with_path(BMG160_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 new file mode 100644 index 00000000..55780d76 --- /dev/null +++ b/examples/javascript/bma250e.js @@ -0,0 +1,72 @@ +/*jslint node:true, vars:true, bitwise:true, unparam:true */ +/*jshint unused:true */ + +/* + * 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. + */ + +var sensorObj = require('jsupm_bmx055'); + +// Instantiate a BMA250E instance using default i2c bus and address +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); + console.log("Accelerometer x: " + + sensorObj.floatp_value(x) + + " y: " + sensorObj.floatp_value(y) + + " z: " + sensorObj.floatp_value(z) + + " g"); + + // 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/javascript/bmc150.js b/examples/javascript/bmc150.js new file mode 100644 index 00000000..a3e29008 --- /dev/null +++ b/examples/javascript/bmc150.js @@ -0,0 +1,69 @@ +/*jslint node:true, vars:true, bitwise:true, unparam:true */ +/*jshint unused:true */ + +/* + * 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. + */ + +var sensorObj = require('jsupm_bmx055'); + +// Instantiate a BMC150 instance using default i2c bus and address +var sensor = new sensorObj.BMC150(); + +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); + console.log("Accelerometer x: " + + sensorObj.floatp_value(x) + + " y: " + sensorObj.floatp_value(y) + + " z: " + sensorObj.floatp_value(z) + + " g"); + + sensor.getMagnetometer(x, y, z); + console.log("Magnetometer x: " + + sensorObj.floatp_value(x) + + " y: " + sensorObj.floatp_value(y) + + " z: " + sensorObj.floatp_value(z) + + " uT"); + + 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/javascript/bmg160.js b/examples/javascript/bmg160.js new file mode 100644 index 00000000..96f46a1b --- /dev/null +++ b/examples/javascript/bmg160.js @@ -0,0 +1,72 @@ +/*jslint node:true, vars:true, bitwise:true, unparam:true */ +/*jshint unused:true */ + +/* + * 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. + */ + +var sensorObj = require('jsupm_bmx055'); + +// Instantiate a BMG160 instance using default i2c bus and address +var sensor = new sensorObj.BMG160(); + +// For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS: +// BMG160(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.getGyroscope(x, y, z); + console.log("Gyroscope x: " + + sensorObj.floatp_value(x) + + " y: " + sensorObj.floatp_value(y) + + " z: " + sensorObj.floatp_value(z) + + " degrees/s"); + + // 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/javascript/bmi055.js b/examples/javascript/bmi055.js new file mode 100644 index 00000000..47110716 --- /dev/null +++ b/examples/javascript/bmi055.js @@ -0,0 +1,69 @@ +/*jslint node:true, vars:true, bitwise:true, unparam:true */ +/*jshint unused:true */ + +/* + * 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. + */ + +var sensorObj = require('jsupm_bmx055'); + +// Instantiate a BMI055 instance using default i2c bus and address +var sensor = new sensorObj.BMI055(); + +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); + console.log("Accelerometer x: " + + sensorObj.floatp_value(x) + + " y: " + sensorObj.floatp_value(y) + + " z: " + sensorObj.floatp_value(z) + + " g"); + + sensor.getGyroscope(x, y, z); + console.log("Gyroscope x: " + + sensorObj.floatp_value(x) + + " y: " + sensorObj.floatp_value(y) + + " z: " + sensorObj.floatp_value(z) + + " degrees/s"); + + 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/javascript/bmm150.js b/examples/javascript/bmm150.js new file mode 100644 index 00000000..8274aa9b --- /dev/null +++ b/examples/javascript/bmm150.js @@ -0,0 +1,65 @@ +/*jslint node:true, vars:true, bitwise:true, unparam:true */ +/*jshint unused:true */ + +/* + * 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. + */ + +var sensorObj = require('jsupm_bmx055'); + +// Instantiate a BMM150 instance using default i2c bus and address +var sensor = new sensorObj.BMM150(); + +// For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS: +// BMM150(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.getMagnetometer(x, y, z); + console.log("Magnetometer x: " + + sensorObj.floatp_value(x) + + " y: " + sensorObj.floatp_value(y) + + " z: " + sensorObj.floatp_value(z) + + " uT"); + + 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/javascript/bmx055.js b/examples/javascript/bmx055.js new file mode 100644 index 00000000..7b0e9b9b --- /dev/null +++ b/examples/javascript/bmx055.js @@ -0,0 +1,76 @@ +/*jslint node:true, vars:true, bitwise:true, unparam:true */ +/*jshint unused:true */ + +/* + * 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. + */ + +var sensorObj = require('jsupm_bmx055'); + +// Instantiate a BMX055 instance using default i2c bus and address +var sensor = new sensorObj.BMX055(); + +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); + console.log("Accelerometer x: " + + sensorObj.floatp_value(x) + + " y: " + sensorObj.floatp_value(y) + + " z: " + sensorObj.floatp_value(z) + + " g"); + + sensor.getGyroscope(x, y, z); + console.log("Gyroscope x: " + + sensorObj.floatp_value(x) + + " y: " + sensorObj.floatp_value(y) + + " z: " + sensorObj.floatp_value(z) + + " degrees/s"); + + sensor.getMagnetometer(x, y, z); + console.log("Magnetometer x: " + + sensorObj.floatp_value(x) + + " y: " + sensorObj.floatp_value(y) + + " z: " + sensorObj.floatp_value(z) + + " uT"); + + 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/bma250e.py b/examples/python/bma250e.py new file mode 100644 index 00000000..051273c2 --- /dev/null +++ b/examples/python/bma250e.py @@ -0,0 +1,66 @@ +#!/usr/bin/python +# 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. + +import time, sys, signal, atexit +import pyupm_bmx055 as sensorObj + +# Instantiate a BMP250E instance using default i2c bus and address +sensor = sensorObj.BMA250E() + +# For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS: +# BMA250E(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) + +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), + print " y:", sensorObj.floatp_value(y), + print " z:", sensorObj.floatp_value(z), + print " g" + + # we show both C and F for temperature + print "Compensation Temperature:", sensor.getTemperature(), "C /", + print sensor.getTemperature(True), "F" + + print + time.sleep(.250) diff --git a/examples/python/bmc150.py b/examples/python/bmc150.py new file mode 100644 index 00000000..efb1d99e --- /dev/null +++ b/examples/python/bmc150.py @@ -0,0 +1,65 @@ +#!/usr/bin/python +# 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. + +import time, sys, signal, atexit +import pyupm_bmx055 as sensorObj + +# Instantiate a BMC150 instance using default i2c bus and address +sensor = sensorObj.BMC150() + +## 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) + +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), + print " y:", sensorObj.floatp_value(y), + print " z:", sensorObj.floatp_value(z), + print " g" + + sensor.getMagnetometer(x, y, z) + print "Magnetometer x:", sensorObj.floatp_value(x), + print " y:", sensorObj.floatp_value(y), + print " z:", sensorObj.floatp_value(z), + print " uT" + + print + time.sleep(.250) diff --git a/examples/python/bmg160.py b/examples/python/bmg160.py new file mode 100644 index 00000000..112e3d68 --- /dev/null +++ b/examples/python/bmg160.py @@ -0,0 +1,66 @@ +#!/usr/bin/python +# 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. + +import time, sys, signal, atexit +import pyupm_bmx055 as sensorObj + +# Instantiate a BMP250E instance using default i2c bus and address +sensor = sensorObj.BMG160() + +# For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS: +# BMG160(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) + +x = sensorObj.new_floatp() +y = sensorObj.new_floatp() +z = sensorObj.new_floatp() + +# now output data every 250 milliseconds +while (1): + sensor.update() + + sensor.getGyroscope(x, y, z) + print "Gyroscope x:", sensorObj.floatp_value(x), + print " y:", sensorObj.floatp_value(y), + print " z:", sensorObj.floatp_value(z), + print " degrees/s" + + # we show both C and F for temperature + print "Compensation Temperature:", sensor.getTemperature(), "C /", + print sensor.getTemperature(True), "F" + + print + time.sleep(.250) diff --git a/examples/python/bmi055.py b/examples/python/bmi055.py new file mode 100644 index 00000000..96ddac29 --- /dev/null +++ b/examples/python/bmi055.py @@ -0,0 +1,65 @@ +#!/usr/bin/python +# 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. + +import time, sys, signal, atexit +import pyupm_bmx055 as sensorObj + +# Instantiate a BMI055 instance using default i2c bus and address +sensor = sensorObj.BMI055() + +## 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) + +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), + print " y:", sensorObj.floatp_value(y), + print " z:", sensorObj.floatp_value(z), + print " g" + + sensor.getGyroscope(x, y, z) + print "Gyroscope x:", sensorObj.floatp_value(x), + print " y:", sensorObj.floatp_value(y), + print " z:", sensorObj.floatp_value(z), + print " degrees/s" + + print + time.sleep(.250) diff --git a/examples/python/bmm150.py b/examples/python/bmm150.py new file mode 100644 index 00000000..69f36bf3 --- /dev/null +++ b/examples/python/bmm150.py @@ -0,0 +1,62 @@ +#!/usr/bin/python +# 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. + +import time, sys, signal, atexit +import pyupm_bmx055 as sensorObj + +# Instantiate a BMP250E instance using default i2c bus and address +sensor = sensorObj.BMM150() + +# For SPI, bus 0, you would pass -1 as the address, and a valid pin for CS: +# BMM150(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) + +x = sensorObj.new_floatp() +y = sensorObj.new_floatp() +z = sensorObj.new_floatp() + +# now output data every 250 milliseconds +while (1): + sensor.update() + + sensor.getMagnetometer(x, y, z) + print "Magnetometer x:", sensorObj.floatp_value(x), + print " y:", sensorObj.floatp_value(y), + print " z:", sensorObj.floatp_value(z), + print " uT" + + print + time.sleep(.250) diff --git a/examples/python/bmx055.py b/examples/python/bmx055.py new file mode 100644 index 00000000..45012cfb --- /dev/null +++ b/examples/python/bmx055.py @@ -0,0 +1,71 @@ +#!/usr/bin/python +# 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. + +import time, sys, signal, atexit +import pyupm_bmx055 as sensorObj + +# Instantiate a BMX055 instance using default i2c bus and address +sensor = sensorObj.BMX055() + +## 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) + +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), + print " y:", sensorObj.floatp_value(y), + print " z:", sensorObj.floatp_value(z), + print " g" + + sensor.getGyroscope(x, y, z) + print "Gyroscope x:", sensorObj.floatp_value(x), + print " y:", sensorObj.floatp_value(y), + print " z:", sensorObj.floatp_value(z), + print " degrees/s" + + sensor.getMagnetometer(x, y, z) + print "Magnetometer x:", sensorObj.floatp_value(x), + print " y:", sensorObj.floatp_value(y), + print " z:", sensorObj.floatp_value(z), + print " uT" + + print + time.sleep(.250) diff --git a/src/bmx055/CMakeLists.txt b/src/bmx055/CMakeLists.txt new file mode 100644 index 00000000..5e968a5a --- /dev/null +++ b/src/bmx055/CMakeLists.txt @@ -0,0 +1,5 @@ +set (libname "bmx055") +set (libdescription "Bosch bmx055, bmi055, bma250e, bmc150, bmg160, bmm150") +set (module_src ${libname}.cxx bma250e.cxx bmg160.cxx bmm150.cxx bmc150.cxx bmi055.cxx) +set (module_hpp ${libname}.hpp bma250e.hpp bmg160.hpp bmm150.hpp bmc150.cxx bmi055.hpp) +upm_module_init() diff --git a/src/bmx055/bma250e.cxx b/src/bmx055/bma250e.cxx new file mode 100644 index 00000000..bdf41ca1 --- /dev/null +++ b/src/bmx055/bma250e.cxx @@ -0,0 +1,735 @@ +/* + * 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 +#include + +#include "bma250e.hpp" + +using namespace upm; +using namespace std; + +// conversion from celcius to fahrenheit + +static float c2f(float c) +{ + return (c * (9.0 / 5.0) + 32.0); +} + +BMA250E::BMA250E(int bus, uint8_t addr, int cs) : + m_i2c(0), m_spi(0), m_gpioIntr1(0), m_gpioIntr2(0), m_gpioCS(0) +{ + m_addr = addr; + m_isSPI = false; + + m_accX = 0; + m_accY = 0; + m_accZ = 0; + m_accScale = 0; + m_temperature = 0.0; + + if (addr < 0) + m_isSPI = true; + + if (m_isSPI) + { + m_spi = new mraa::Spi(bus); + + // Only create cs context if we are actually using a valid pin. + // A hardware controlled pin should specify cs as -1. + if (cs >= 0) + { + m_gpioCS = new mraa::Gpio(cs); + m_gpioCS->dir(mraa::DIR_OUT); + } + + m_spi->mode(mraa::SPI_MODE0); + m_spi->frequency(5000000); + } + else + { + // I2C + m_i2c = new mraa::I2c(bus); + + mraa::Result rv; + if ((rv = m_i2c->address(m_addr)) != mraa::SUCCESS) + { + throw std::runtime_error(string(__FUNCTION__) + + ": I2c.address() failed"); + } + } + + // check the chip id + + uint8_t chipID = getChipID(); + + m_useFIFO = false; + + // check the various chips id's and set appropriate capabilities. + // Bail if the chip id is unknown. + switch (chipID) + { + case 0xf9: // standalone bma250e + m_resolution = RESOLUTION_10BITS; + m_fifoAvailable = true; + + break; + + case 0xfa: // bmx055, bmi055 variants, 12b resolution + m_resolution = RESOLUTION_12BITS; + m_fifoAvailable = true; + + break; + + case 0x03: // bmc050 variant, no FIFO, 12b resolution + m_resolution = RESOLUTION_12BITS; + m_fifoAvailable = false; + + break; + + default: + throw std::runtime_error(string(__FUNCTION__) + + ": invalid chip ID. Expected " + + "3, 249, or 250 " + + ", got " + + std::to_string(int(chipID))); + } + + // call init with default options + init(); +} + +BMA250E::~BMA250E() +{ + uninstallISR(INTERRUPT_INT1); + uninstallISR(INTERRUPT_INT2); +} + +void BMA250E::init(POWER_MODE_T pwr, RANGE_T range, BW_T bw) +{ + setPowerMode(pwr); + usleep(50000); // 50ms, in case we are waking up + + // set our range and bandwidth + setRange(range); + setBandwidth(bw); + + // make sure register shadowing is enabled + enableRegisterShadowing(true); + + // enable output filtering + enableOutputFiltering(true); + + // use the FIFO by default, if we have one + fifoConfig(FIFO_MODE_BYPASS, FIFO_DATA_SEL_XYZ); + enableFIFO(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. + setLowPowerMode2(); + + // settle + usleep(50000); +} + +void BMA250E::update() +{ + int bufLen = 0; + uint8_t startReg = 0; + + if (m_useFIFO) + { + bufLen = 6; + startReg = REG_FIFO_DATA; + } + else + { + // non FIFO, read acc regs directly (including temp) + bufLen = 7; + startReg = REG_ACCD_X_LSB; + } + + uint8_t buf[bufLen]; + + if (readRegs(startReg, buf, bufLen) != bufLen) + { + throw std::runtime_error(string(__FUNCTION__) + + ": readRegs() failed to read " + + std::to_string(bufLen) + + " bytes"); + } + + uint8_t mask, shift; + float divisor; + + switch (m_resolution) + { + case RESOLUTION_10BITS: + mask = _ACCD10_LSB_MASK; + shift = _ACCD10_LSB_SHIFT; + divisor = 64.0; + + break; + + case RESOLUTION_12BITS: + mask = _ACCD12_LSB_MASK; + shift = _ACCD12_LSB_SHIFT; + divisor = 16.0; + + break; + + default: + throw std::logic_error(string(__FUNCTION__) + + ": internal error: invalid resolution " + + std::to_string(int(m_resolution))); + } + + int16_t val; + + // x + val = int16_t(buf[1] << 8 | (buf[0] & (mask << shift))); + m_accX = float(val / divisor); + + // y + val = int16_t(buf[3] << 8 | (buf[2] & (mask << shift))); + m_accY = float(val / divisor); + + // z + val = int16_t(buf[5] << 8 | (buf[4] & (mask << shift))); + m_accZ = float(val / divisor); + + // get the temperature... + + uint8_t temp = 0; + if (m_useFIFO) + { + // we have to read temperature separately... + temp = readReg(REG_TEMP); + } + else + { + // we've already got it + temp = buf[6]; + } + + // .5K/LSB, 23C center point + m_temperature = (float(temp) / 2.0) + 23.0; +} + +void BMA250E::enableFIFO(bool useFIFO) +{ + if (m_fifoAvailable) + m_useFIFO = useFIFO; +} + +uint8_t BMA250E::readReg(uint8_t reg) +{ + if (m_isSPI) + { + reg |= 0x80; // needed for read + uint8_t pkt[2] = {reg, 0}; + + csOn(); + if (m_spi->transfer(pkt, pkt, 2)) + { + csOff(); + throw std::runtime_error(string(__FUNCTION__) + + ": Spi.transfer() failed"); + } + csOff(); + + return pkt[1]; + } + else + return m_i2c->readReg(reg); +} + +int BMA250E::readRegs(uint8_t reg, uint8_t *buffer, int len) +{ + if (m_isSPI) + { + reg |= 0x80; // needed for read + + uint8_t sbuf[len + 1]; + memset((char *)sbuf, 0, len + 1); + sbuf[0] = reg; + + // We need to do it this way for edison - ie: use a single + // transfer rather than breaking it up into two like we used to. + // This means a buffer copy is now required, but that's the way + // it goes. + + csOn(); + if (m_spi->transfer(sbuf, sbuf, len + 1)) + { + csOff(); + throw std::runtime_error(string(__FUNCTION__) + + ": Spi.transfer(buf) failed"); + } + csOff(); + + // now copy it into user buffer + for (int i=0; ireadBytesReg(reg, buffer, len); +} + +void BMA250E::writeReg(uint8_t reg, uint8_t val) +{ + if (m_isSPI) + { + reg &= 0x7f; // mask off 0x80 for writing + uint8_t pkt[2] = {reg, val}; + + csOn(); + if (m_spi->transfer(pkt, NULL, 2)) + { + csOff(); + throw std::runtime_error(string(__FUNCTION__) + + ": Spi.transfer() failed"); + } + csOff(); + } + else + { + if (m_i2c->writeReg(reg, val) != mraa::SUCCESS) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": I2c.writeReg() failed"); + } + } +} + +void BMA250E::csOn() +{ + if (m_gpioCS) + m_gpioCS->write(0); +} + +void BMA250E::csOff() +{ + if (m_gpioCS) + m_gpioCS->write(1); +} + +uint8_t BMA250E::getChipID() +{ + return readReg(REG_CHIP_ID); +} + +void BMA250E::getAccelerometer(float *x, float *y, float *z) +{ + if (x) + *x = (m_accX * m_accScale) / 1000.0; + + if (y) + *y = (m_accY * m_accScale) / 1000.0; + + if (z) + *z = (m_accZ * m_accScale) / 1000.0; +} + +float *BMA250E::getAccelerometer() +{ + static float v[3]; + + getAccelerometer(&v[0], &v[1], &v[2]); + return v; +} + +float BMA250E::getTemperature(bool fahrenheit) +{ + if (fahrenheit) + return c2f(m_temperature); + else + return m_temperature; +} + +void BMA250E::reset() +{ + writeReg(REG_SOFTRESET, BMA250E_RESET_BYTE); + sleep(1); +} + +void BMA250E::setRange(RANGE_T range) +{ + switch (m_resolution) + { + case RESOLUTION_10BITS: + switch(range) + { + case RANGE_2G: + m_accScale = 3.91; // milli-gravities + break; + + case RANGE_4G: + m_accScale = 7.81; + break; + + case RANGE_8G: + m_accScale = 15.63; + break; + + case RANGE_16G: + m_accScale = 31.25; + break; + } + + break; + + case RESOLUTION_12BITS: + switch(range) + { + case RANGE_2G: + m_accScale = 0.98; // milli-gravities + break; + + case RANGE_4G: + m_accScale = 1.95; + break; + + case RANGE_8G: + m_accScale = 3.91; + break; + + case RANGE_16G: + m_accScale = 7.81; + break; + } + + break; + } + + writeReg(REG_PMU_RANGE, range); +} + +void BMA250E::setBandwidth(BW_T bw) +{ + writeReg(REG_PMU_BW, bw); +} + +void BMA250E::setPowerMode(POWER_MODE_T power) +{ + // mask off reserved bits + uint8_t reg = readReg(REG_PMU_LPW) & ~_PMU_LPW_RESERVED_MASK; + + reg &= ~(_PMU_LPW_POWER_MODE_MASK << _PMU_LPW_POWER_MODE_SHIFT); + reg |= (power << _PMU_LPW_POWER_MODE_SHIFT); + + writeReg(REG_PMU_LPW, power); +} + +void BMA250E::fifoSetWatermark(int wm) +{ + // do nothing if we don't have a FIFO + if (!m_fifoAvailable) + return; + + // mask off illegal values + uint8_t reg = uint8_t(wm) & _FIFO_CONFIG_0_WATER_MARK_MASK; + + writeReg(REG_FIFO_CONFIG_0, reg); +} + +void BMA250E::fifoConfig(FIFO_MODE_T mode, FIFO_DATA_SEL_T axes) +{ + // do nothing if we don't have a FIFO + if (!m_fifoAvailable) + return; + + uint8_t reg = ( (mode << _FIFO_CONFIG_1_FIFO_MODE_SHIFT) | + (axes << _FIFO_CONFIG_1_FIFO_DATA_SHIFT) ); + + writeReg(REG_FIFO_CONFIG_1, reg); +} + +void BMA250E::setSelfTest(bool sign, bool amp, SELFTTEST_AXIS_T axis) +{ + uint8_t reg = (axis << _PMU_SELFTTEST_AXIS_SHIFT); + + if (amp) + reg |= PMU_SELFTTEST_AMP; + + if (sign) + reg |= PMU_SELFTTEST_SIGN; + + writeReg(REG_PMU_SELFTEST, reg); +} + +uint8_t BMA250E::getInterruptEnable0() +{ + return readReg(REG_INT_EN_0) & ~_INT_EN_0_RESERVED_BITS; +} + +void BMA250E::setInterruptEnable0(uint8_t bits) +{ + uint8_t reg = bits & ~_INT_EN_0_RESERVED_BITS; + + writeReg(REG_INT_EN_0, reg); +} + +uint8_t BMA250E::getInterruptEnable1() +{ + return readReg(REG_INT_EN_1) & ~_INT_EN_1_RESERVED_BITS; +} + +void BMA250E::setInterruptEnable1(uint8_t bits) +{ + uint8_t reg = bits & ~_INT_EN_1_RESERVED_BITS; + + writeReg(REG_INT_EN_1, reg); +} + +uint8_t BMA250E::getInterruptEnable2() +{ + return readReg(REG_INT_EN_2) & ~_INT_EN_2_RESERVED_BITS; +} + +void BMA250E::setInterruptEnable2(uint8_t bits) +{ + uint8_t reg = bits & ~_INT_EN_2_RESERVED_BITS; + + writeReg(REG_INT_EN_2, reg); +} + +uint8_t BMA250E::getInterruptMap0() +{ + return readReg(REG_INT_MAP_0); +} + +void BMA250E::setInterruptMap0(uint8_t bits) +{ + writeReg(REG_INT_MAP_0, bits); +} + +uint8_t BMA250E::getInterruptMap1() +{ + return readReg(REG_INT_MAP_1) & ~_INT_MAP_1_INT1_RESERVED_BITS; +} + +void BMA250E::setInterruptMap1(uint8_t bits) +{ + uint8_t reg = bits & ~_INT_MAP_1_INT1_RESERVED_BITS; + + writeReg(REG_INT_MAP_1, reg); +} + +uint8_t BMA250E::getInterruptMap2() +{ + return readReg(REG_INT_MAP_2); +} + +void BMA250E::setInterruptMap2(uint8_t bits) +{ + writeReg(REG_INT_MAP_2, bits); +} + +uint8_t BMA250E::getInterruptSrc() +{ + return readReg(REG_INT_SRC) & ~_INT_SRC_RESERVED_BITS; +} + +void BMA250E::setInterruptSrc(uint8_t bits) +{ + uint8_t reg = bits & ~_INT_SRC_RESERVED_BITS; + + writeReg(REG_INT_SRC, reg); +} + +uint8_t BMA250E::getInterruptOutputControl() +{ + return readReg(REG_INT_OUT_CTRL) & ~_INT_OUT_CTRL_INT1_RESERVED_BITS; +} + +void BMA250E::setInterruptOutputControl(uint8_t bits) +{ + uint8_t reg = bits & ~_INT_OUT_CTRL_INT1_RESERVED_BITS; + + writeReg(REG_INT_OUT_CTRL, reg); +} + +void BMA250E::clearInterruptLatches() +{ + uint8_t reg = readReg(REG_INT_RST_LATCH) & ~_INT_RST_LATCH_RESERVED_BITS; + + reg |= INT_RST_LATCH_RESET_INT; + + writeReg(REG_INT_RST_LATCH, reg); +} + +BMA250E::RST_LATCH_T BMA250E::getInterruptLatchBehavior() +{ + uint8_t reg = readReg(REG_INT_RST_LATCH) & ~_INT_RST_LATCH_RESERVED_BITS; + + reg &= (_INT_RST_LATCH_MASK << _INT_RST_LATCH_SHIFT); + + return static_cast(reg); +} + +void BMA250E::setInterruptLatchBehavior(RST_LATCH_T latch) +{ + uint8_t reg = readReg(REG_INT_RST_LATCH) & ~_INT_RST_LATCH_RESERVED_BITS; + + reg &= ~(_INT_RST_LATCH_MASK << _INT_RST_LATCH_SHIFT); + reg |= (latch << _INT_RST_LATCH_SHIFT); + + writeReg(REG_INT_RST_LATCH, reg); +} + +void BMA250E::enableRegisterShadowing(bool shadow) +{ + uint8_t reg = readReg(REG_ACC_HBW) & ~_ACC_HBW_RESERVED_BITS; + + if (shadow) + reg &= ~ACC_HBW_SHADOW_DIS; + else + reg |= ACC_HBW_SHADOW_DIS; + + writeReg(REG_ACC_HBW, reg); +} + +void BMA250E::enableOutputFiltering(bool filter) +{ + uint8_t reg = readReg(REG_ACC_HBW) & ~_ACC_HBW_RESERVED_BITS; + + if (filter) + reg &= ~ACC_HBW_DATA_HIGH_BW; + else + reg |= ACC_HBW_DATA_HIGH_BW; + + writeReg(REG_ACC_HBW, reg); +} + +uint8_t BMA250E::getInterruptStatus0() +{ + return readReg(REG_INT_STATUS_0); +} + +uint8_t BMA250E::getInterruptStatus1() +{ + return readReg(REG_INT_STATUS_1) & ~_INT_STATUS_1_RESERVED_BITS; +} + +uint8_t BMA250E::getInterruptStatus2() +{ + return readReg(REG_INT_STATUS_2); +} + +uint8_t BMA250E::getInterruptStatus3Bits() +{ + // filter out the orientation bitfield.. + return readReg(REG_INT_STATUS_3) & + ~(_INT_STATUS_3_ORIENT_MASK << _INT_STATUS_3_ORIENT_SHIFT); +} + +BMA250E::ORIENT_T BMA250E::getInterruptStatus3Orientation() +{ + // grab just the orientation bitfield + uint8_t reg = readReg(REG_INT_STATUS_3) & + (_INT_STATUS_3_ORIENT_MASK << _INT_STATUS_3_ORIENT_SHIFT); + + reg >>= _INT_STATUS_3_ORIENT_SHIFT; + + return static_cast(reg); +} + +void BMA250E::setLowPowerMode2() +{ + uint8_t reg = readReg(REG_PMU_LOW_POWER) & ~_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 |= LOW_POWER_LOWPOWER_MODE; + + writeReg(REG_PMU_LOW_POWER, reg); +} + +#if defined(SWIGJAVA) || (JAVACALLBACK) +void BMA250E::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level, + jobject runnable) +{ + // delete any existing ISR and GPIO context + uninstallISR(intr); + + // create gpio context + getPin(intr) = new mraa::Gpio(gpio); + + getPin(intr)->dir(mraa::DIR_IN); + getPin(intr)->isr(level, runnable); +} +#else +void BMA250E::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level, + void (*isr)(void *), void *arg) +{ + // delete any existing ISR and GPIO context + uninstallISR(intr); + + // create gpio context + getPin(intr) = new mraa::Gpio(gpio); + + getPin(intr)->dir(mraa::DIR_IN); + getPin(intr)->isr(level, isr, arg); +} +#endif + +void BMA250E::uninstallISR(INTERRUPT_PINS_T intr) +{ + if (getPin(intr)) + { + getPin(intr)->isrExit(); + delete getPin(intr); + + getPin(intr) = 0; + } +} + +mraa::Gpio*& BMA250E::getPin(INTERRUPT_PINS_T intr) +{ + switch(intr) + { + case INTERRUPT_INT1: + return m_gpioIntr1; + break; + + case INTERRUPT_INT2: + return m_gpioIntr2; + break; + + default: + throw std::out_of_range(string(__FUNCTION__) + + ": Invalid interrupt enum passed"); + } +} diff --git a/src/bmx055/bma250e.hpp b/src/bmx055/bma250e.hpp new file mode 100644 index 00000000..46ae471f --- /dev/null +++ b/src/bmx055/bma250e.hpp @@ -0,0 +1,1461 @@ +/* + * 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. + */ +#pragma once + +#include +#include +#include +#include + +#define BMA250E_I2C_BUS 0 +#define BMA250E_SPI_BUS 0 +#define BMA250E_DEFAULT_ADDR 0x18 + + +namespace upm { + + /** + * @library bmx050 + * @sensor bma250e + * @comname BMA250E 10 bit Trixial Accelerometer + * @type accelerometer + * @man bosch + * @con i2c spi gpio + * + * @brief API for the BMA250E 10 bit Trixial 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: + // special reset byte + static const uint8_t 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 : uint8_t { + REG_CHIP_ID = 0x00, + + // 0x01 reserved + + REG_ACCD_X_LSB = 0x02, + REG_ACCD_X_MSB = 0x03, + REG_ACCD_Y_LSB = 0x04, + REG_ACCD_Y_MSB = 0x05, + REG_ACCD_Z_LSB = 0x06, + REG_ACCD_Z_MSB = 0x07, + + REG_TEMP = 0x08, + + REG_INT_STATUS_0 = 0x09, + REG_INT_STATUS_1 = 0x0a, + REG_INT_STATUS_2 = 0x0b, + REG_INT_STATUS_3 = 0x0c, + + // 0x0d reserved + + REG_FIFO_STATUS = 0x0e, + + REG_PMU_RANGE = 0x0f, + REG_PMU_BW = 0x10, + REG_PMU_LPW = 0x11, + REG_PMU_LOW_POWER = 0x12, + + REG_ACC_HBW = 0x13, + + REG_SOFTRESET = 0x14, + + // 0x15 reserved + + REG_INT_EN_0 = 0x16, + REG_INT_EN_1 = 0x17, + REG_INT_EN_2 = 0x18, + + REG_INT_MAP_0 = 0x19, + REG_INT_MAP_1 = 0x1a, + REG_INT_MAP_2 = 0x1b, + + // 0x1c-0x1d reserved + + REG_INT_SRC = 0x1e, + + // 0x1f reserved + + REG_INT_OUT_CTRL = 0x20, + REG_INT_RST_LATCH = 0x21, + + REG_INT_0 = 0x22, + REG_INT_1 = 0x23, + REG_INT_2 = 0x24, + REG_INT_3 = 0x25, + REG_INT_4 = 0x26, + REG_INT_5 = 0x27, + REG_INT_6 = 0x28, + REG_INT_7 = 0x29, + REG_INT_8 = 0x2a, + REG_INT_9 = 0x2b, + REG_INT_A = 0x2c, + REG_INT_B = 0x2d, + REG_INT_C = 0x2e, + REG_INT_D = 0x2f, + + REG_FIFO_CONFIG_0 = 0x30, + + // 0x31 reserved + + REG_PMU_SELFTEST = 0x32, + + REG_TRIM_NVM_CTRL = 0x33, + + REG_SPI3_WDT = 0x34, + + // 0x35 reserved + + REG_OFC_CTRL = 0x36, + REG_OFC_SETTING = 0x37, + + REG_OFC_OFFSET_X = 0x38, + REG_OFC_OFFSET_Y = 0x39, + REG_OFC_OFFSET_Z = 0x3a, + + REG_TRIM_GP0 = 0x3b, + REG_TRIM_GP1 = 0x3c, + + // 0x3d reserved + + REG_FIFO_CONFIG_1 = 0x3e, + REG_FIFO_DATA = 0x3f + + } BMA250E_REGS_T; + + /** + * REG_ACCD_*_LSB bits - handle X, Y, and Z LSB regs, for 10 bit + * resolution + */ + typedef enum { + ACCD10_LSB_NEW_DATA = 0x01, // data updated since last read + + // 0x02-0x20 reserved + + ACCD10_LSB0 = 0x40, // lower 2 bits of LSB data + ACCD10_LSB1 = 0x80, + _ACCD10_LSB_MASK = 3, + _ACCD10_LSB_SHIFT = 6 + } ACCD10_LSB_BITS_T; + + /** + * REG_ACCD_*_LSB bits - handle X, Y, and Z LSB regs, for 12 bit + * resolution + */ + typedef enum { + ACCD12_LSB_NEW_DATA = 0x01, // data updated since last read + + // 0x02-0x08 reserved + + ACCD12_LSB0 = 0x10, // lower 4 bits of LSB data + ACCD12_LSB1 = 0x20, + ACCD12_LSB2 = 0x40, + ACCD12_LSB3 = 0x80, + _ACCD12_LSB_MASK = 15, + _ACCD12_LSB_SHIFT = 4 + } ACCD12_LSB_BITS_T; + + /** + * REG_INT_STATUS_0 bits + */ + typedef enum { + INT_STATUS_0_LOW = 0x01, + INT_STATUS_0_HIGH = 0x02, + INT_STATUS_0_SLOPE = 0x04, + INT_STATUS_0_SLO_NOT_MOT = 0x08, + INT_STATUS_0_D_TAP = 0x10, + INT_STATUS_0_S_TAP = 0x20, + INT_STATUS_0_ORIENT = 0x40, + INT_STATUS_0_FLAT = 0x80 + } INT_STATUS_0_BITS_T; + + /** + * REG_INT_STATUS_1 bits + */ + typedef enum { + _INT_STATUS_1_RESERVED_BITS = 0x0f | 0x10, + // 0x01-0x10 reserved + INT_STATUS_1_FIFO_FULL = 0x20, + INT_STATUS_1_FIFO_WM = 0x40, + INT_STATUS_1_DATA = 0x80 // data ready int + } INT_STATUS_1_BITS_T; + + /** + * REG_INT_STATUS_2 bits + */ + typedef enum { + INT_STATUS_2_SLOPE_FIRST_X = 0x01, + INT_STATUS_2_SLOPE_FIRST_Y = 0x02, + INT_STATUS_2_SLOPE_FIRST_Z = 0x04, + INT_STATUS_2_SLOPE_SIGN = 0x08, + INT_STATUS_2_TAP_FIRST_X = 0x10, + INT_STATUS_2_TAP_FIRST_Y = 0x20, + INT_STATUS_2_TAP_FIRST_Z = 0x40, + INT_STATUS_2_TAP_SIGN = 0x80 + } INT_STATUS_2_BITS_T; + + /** + * REG_INT_STATUS_3 bits + */ + typedef enum { + INT_STATUS_3_HIGH_FIRST_X = 0x01, + INT_STATUS_3_HIGH_FIRST_Y = 0x02, + INT_STATUS_3_HIGH_FIRST_Z = 0x04, + INT_STATUS_3_HIGH_SIGN = 0x08, + + INT_STATUS_3_ORIENT0 = 0x10, + INT_STATUS_3_ORIENT1 = 0x20, + INT_STATUS_3_ORIENT2 = 0x40, + _INT_STATUS_3_ORIENT_MASK = 7, + _INT_STATUS_3_ORIENT_SHIFT = 4, + + INT_STATUS_3_FLAT = 0x80 + } INT_STATUS_3_BITS_T; + + /** + * INT_STATUS_3_ORIENT values + */ + typedef enum { + ORIENT_POTRAIT_UPRIGHT = 0, + ORIENT_POTRAIT_UPSIDE_DOWN = 1, + ORIENT_LANDSCAPE_LEFT = 2, + ORIENT_LANDSCAPE_RIGHT = 3, + } ORIENT_T; + + /** + * REG_FIFO_STATUS bits + */ + typedef enum { + FIFO_STATUS_FRAME_COUNTER0 = 0x01, + FIFO_STATUS_FRAME_COUNTER1 = 0x02, + FIFO_STATUS_FRAME_COUNTER2 = 0x04, + FIFO_STATUS_FRAME_COUNTER3 = 0x08, + FIFO_STATUS_FRAME_COUNTER4 = 0x10, + FIFO_STATUS_FRAME_COUNTER5 = 0x20, + FIFO_STATUS_FRAME_COUNTER6 = 0x40, + _FIFO_STATUS_FRAME_COUNTER_MASK = 127, + _FIFO_STATUS_FRAME_COUNTER_SHIFT = 0, + + FIFO_STATUS_FIFO_OVERRUN = 0x80 + } FIFO_STATUS_BITS_T; + + /** + * REG_PMU_RANGE bits + */ + typedef enum { + PMU_RANGE0 = 0x01, + PMU_RANGE1 = 0x02, + PMU_RANGE2 = 0x04, + PMU_RANGE3 = 0x08, + _PMU_RANGE_MASK = 15, + _PMU_RANGE_SHIFT = 0 + + // 0x10-0x80 reserved + } PMU_RANGE_BITS_T; + + /** + * PMU_RANGE (accelerometer g-range) values + */ + typedef enum { + RANGE_2G = 3, + RANGE_4G = 5, + RANGE_8G = 8, + RANGE_16G = 12 + } RANGE_T; + + /** + * REG_PMU_BW bits + */ + typedef enum { + PMU_BW0 = 0x01, + PMU_BW1 = 0x02, + PMU_BW2 = 0x04, + PMU_BW3 = 0x08, + PMU_BW4 = 0x10, + _PMU_BW_MASK = 31, + _PMU_BW_SHIFT = 0 + + // 0x20-0x80 reserved + } PMU_BW_BITS_T; + + /** + * PMU_BW (accelerometer filter bandwidth) values + */ + typedef enum { + BW_7_81 = 8, // 7.81 Hz + BW_15_63 = 9, + BW_31_25 = 10, + BW_62_5 = 11, + BW_125 = 12, + BW_250 = 13, + BW_500 = 14, + BW_1000 = 15 + } BW_T; + + /** + * REG_PMU_LPW bits + */ + typedef enum { + // 0x01 reserved + _PMU_LPW_RESERVED_MASK = 0x01, + + PMU_LPW_SLEEP_DUR0 = 0x02, // sleep dur in low power mode + PMU_LPW_SLEEP_DUR1 = 0x04, + PMU_LPW_SLEEP_DUR2 = 0x08, + PMU_LPW_SLEEP_DUR3 = 0x10, + _PMU_LPW_SLEEP_MASK = 15, + _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. + PMU_LPW_POWER_MODE0 = 0x20, // deep_suspend + PMU_LPW_POWER_MODE1 = 0x40, // lowpower_en + PMU_LPW_POWER_MODE2 = 0x80, // suspend + _PMU_LPW_POWER_MODE_MASK = 7, + _PMU_LPW_POWER_MODE_SHIFT = 5 + } PMU_LPW_BITS_T; + + /** + * SLEEP_DUR values + */ + typedef enum { + SLEEP_DUR_0_5 = 0, // 0.5ms + SLEEP_DUR_1 = 6, + SLEEP_DUR_2 = 7, + SLEEP_DUR_4 = 8, + SLEEP_DUR_6 = 9, + SLEEP_DUR_10 = 10, + SLEEP_DUR_25 = 11, + SLEEP_DUR_50 = 12, + SLEEP_DUR_100 = 13, + SLEEP_DUR_500 = 14, + SLEEP_DUR_1000 = 15 + } SLEEP_DUR_T; + + /** + * POWER_MODE values + */ + typedef enum { + POWER_MODE_NORMAL = 0, + POWER_MODE_DEEP_SUSPEND = 1, + POWER_MODE_LOW_POWER = 2, + POWER_MODE_SUSPEND = 4 + } POWER_MODE_T; + + /** + * REG_PMU_LOW_POWER bits + */ + typedef enum { + _LOW_POWER_RESERVED_BITS = 0x0f | 0x10 | 0x80, + + // 0x01-0x10 reserved + LOW_POWER_SLEEPTIMER_MODE = 0x20, + LOW_POWER_LOWPOWER_MODE = 0x40 // LPM1 or LPM2 mode. see DS. + // 0x80 reserved + } LOW_POWER_BITS_T; + + /** + * REG_ACC_HBW bits + */ + typedef enum { + _ACC_HBW_RESERVED_BITS = 0x0f | 0x10 | 0x20, + + // 0x01-0x20 reserved + ACC_HBW_SHADOW_DIS = 0x40, + ACC_HBW_DATA_HIGH_BW = 0x80 + } ACC_HBW_BITS_T; + + /** + * REG_INT_EN_0 bits + */ + typedef enum { + _INT_EN_0_RESERVED_BITS = 0x08, + + INT_EN_0_SLOPE_EN_X = 0x01, + INT_EN_0_SLOPE_EN_Y = 0x02, + INT_EN_0_SLOPE_EN_Z = 0x04, + + // 0x08 reserved + + INT_EN_0_D_TAP_EN = 0x10, + INT_EN_0_S_TAP_EN = 0x20, + INT_EN_0_ORIENT_EN = 0x40, + INT_EN_0_FLAT_EN = 0x80 + } INT_EN_0_BITS_T; + + /** + * REG_INT_EN_1 bits + */ + typedef enum { + _INT_EN_1_RESERVED_BITS = 0x80, + + INT_EN_1_HIGH_EN_X = 0x01, + INT_EN_1_HIGH_EN_Y = 0x02, + INT_EN_1_HIGH_EN_Z = 0x04, + INT_EN_1_LOW_EN = 0x08, + INT_EN_1_DATA_EN = 0x10, + INT_EN_1_INT_FFULL_EN = 0x20, // fifo full + INT_EN_1_INT_FWM_EN = 0x40 // fifo watermark + + // 0x80 reserved + } INT_EN_1_BITS_T; + + /** + * REG_INT_EN_2 bits + */ + typedef enum { + _INT_EN_2_RESERVED_BITS = 0xf0, + + INT_EN_2_SLO_NO_MOT_EN_X = 0x01, + INT_EN_2_SLO_NO_MOT_EN_Y = 0x02, + INT_EN_2_SLO_NO_MOT_EN_Z = 0x04, + INT_EN_2_SLO_NO_MOT_SEL = 0x08 + + // 0x10-0x80 reserved + } INT_EN_2_BITS_T; + + /** + * REG_INT_MAP_0 bits + */ + typedef enum { + INT_MAP_0_INT1_LOW = 0x01, + INT_MAP_0_INT1_HIGH = 0x02, + INT_MAP_0_INT1_SLOPE = 0x04, + INT_MAP_0_INT1_SLO_NO_MOT = 0x08, + INT_MAP_0_INT1_D_TAP = 0x10, + INT_MAP_0_INT1_S_TAP = 0x20, + INT_MAP_0_INT1_ORIENT = 0x40, + INT_MAP_0_INT1_FLAT = 0x80 + } INT_MAP_0_BITS_T; + + /** + * REG_INT_MAP_1 bits + */ + typedef enum { + _INT_MAP_1_INT1_RESERVED_BITS = 0x08 | 0x10, + + INT_MAP_1_INT1_DATA = 0x01, + INT_MAP_1_INT1_FWM = 0x02, + INT_MAP_1_INT1_FFULL = 0x04, + + // 0x08-0x10 reserved + + INT_MAP_1_INT2_FFULL = 0x20, + INT_MAP_1_INT2_FWM = 0x40, + INT_MAP_1_INT2_DATA = 0x80 + } INT_MAP_1_BITS_T; + + /** + * REG_INT_MAP_2 bits + */ + typedef enum { + INT_MAP_2_INT2_LOW = 0x01, + INT_MAP_2_INT2_HIGH = 0x02, + INT_MAP_2_INT2_SLOPE = 0x04, + INT_MAP_2_INT2_SLO_NO_MOT = 0x08, + INT_MAP_2_INT2_D_TAP = 0x10, + INT_MAP_2_INT2_S_TAP = 0x20, + INT_MAP_2_INT2_ORIENT = 0x40, + INT_MAP_2_INT2_FLAT = 0x80 + } INT_MAP_2_BITS_T; + + /** + * REG_INT_SRC bits + */ + typedef enum { + _INT_SRC_RESERVED_BITS = 0x40 | 0x80, + + INT_SRC_LOW = 0x01, + INT_SRC_HIGH = 0x02, + INT_SRC_SLO_NO_MOT = 0x04, + INT_SRC_SLOPE = 0x08, + INT_SRC_TAP = 0x10, + INT_SRC_DATA = 0x20 + + // 0x40-0x80 reserved + } INT_SRC_BITS_T; + + /** + * REG_INT_OUT_CTRL bits + */ + typedef enum { + _INT_OUT_CTRL_INT1_RESERVED_BITS = 0xf0, + + INT_OUT_CTRL_INT1_LVL = 0x01, // level or edge + INT_OUT_CTRL_INT1_OD = 0x02, // push-pull or open drain + INT_OUT_CTRL_INT2_LVL = 0x04, + INT_OUT_CTRL_INT2_OD = 0x08 + + // 0x10-0x80 reserved + } INT_OUT_CTRL_BITS_T; + + /** + * REG_INT_RST_LATCH bits + */ + typedef enum { + _INT_RST_LATCH_RESERVED_BITS = 0x10 | 0x20 | 0x40, + + INT_RST_LATCH0 = 0x01, + INT_RST_LATCH1 = 0x02, + INT_RST_LATCH2 = 0x04, + INT_RST_LATCH3 = 0x08, + _INT_RST_LATCH_MASK = 15, + _INT_RST_LATCH_SHIFT = 0, + + // 0x10-0x40 reserved + + INT_RST_LATCH_RESET_INT = 0x80 + } INT_RST_LATCH_BITS_T; + + /** + * RST_LATCH values + */ + typedef enum { + RST_LATCH_NON_LATCHED = 0, + RST_LATCH_TEMPORARY_250MS = 1, + RST_LATCH_TEMPORARY_500MS = 2, + RST_LATCH_TEMPORARY_1S = 3, + RST_LATCH_TEMPORARY_2S = 4, + RST_LATCH_TEMPORARY_4S = 5, + RST_LATCH_TEMPORARY_8S = 6, + RST_LATCH_LATCHED = 7, + + // 8 == non latched + + RST_LATCH_TEMPORARY_250US = 9, + RST_LATCH_TEMPORARY_500US = 10, + RST_LATCH_TEMPORARY_1MS = 11, + RST_LATCH_TEMPORARY_12_5MS = 12, + RST_LATCH_TEMPORARY_25MS = 13, + RST_LATCH_TEMPORARY_50MS = 14 + + // 15 == latched + } RST_LATCH_T; + + /** + * REG_INT_2 bits + */ + typedef enum { + INT_2_LOW_HY0 = 0x01, + INT_2_LOW_HY1 = 0x02, + _INT_2_LOW_HY_MASK = 3, + _INT_2_LOW_HY_SHIFT = 0, + + INT_2_LOW_MODE = 0x04, + + // 0x08-0x20 reserved + + INT_2_HIGH_HY0 = 0x40, + INT_2_HIGH_HY1 = 0x80, + _INT_2_HIGH_HY_MASK = 3, + _INT_2_HIGH_HY_SHIFT = 6 + } INT_2_BITS_T; + + /** + * REG_INT_5 bits + */ + typedef enum { + INT_5_SLOPE_DUR0 = 0x01, + INT_5_SLOPE_DUR1 = 0x02, + _INT_5_SLOPE_DUR_MASK = 3, + _INT_5_SLOPE_DUR_SHIFT = 0, + + INT_5_SLO_NO_MOT_DUR0 = 0x04, + INT_5_SLO_NO_MOT_DUR1 = 0x08, + INT_5_SLO_NO_MOT_DUR2 = 0x10, + INT_5_SLO_NO_MOT_DUR3 = 0x20, + INT_5_SLO_NO_MOT_DUR4 = 0x40, + INT_5_SLO_NO_MOT_DUR5 = 0x80, + _INT_5_SLO_NO_MOT_DUR_MASK = 63, + _INT_5_SLO_NO_MOT_DUR_SHIFT = 2 + } INT_5_BITS_T; + + /** + * REG_INT_8 bits + */ + typedef enum { + INT_8_TAP_DUR0 = 0x01, + INT_8_TAP_DUR1 = 0x02, + INT_8_TAP_DUR2 = 0x04, + _INT_8_TAP_DUR_MASK = 7, + _INT_8_TAP_DUR_SHIFT = 0, + + // 0x08-0x20 reserved + + INT_8_TAP_SHOCK = 0x40, + INT_8_TAP_QUIET = 0x80 + } INT_8_BITS_T; + + /** + * REG_INT_9 bits + */ + typedef enum { + INT_9_TAP_TH0 = 0x01, + INT_9_TAP_TH1 = 0x02, + INT_9_TAP_TH2 = 0x04, + INT_9_TAP_TH3 = 0x08, + INT_9_TAP_TH4 = 0x10, + _INT_5_TAP_TH_MASK = 31, + _INT_5_TAP_TH_SHIFT = 0, + + // 0x20 reserved + + INT_9_TAP_SAMP0 = 0x40, + INT_9_TAP_SAMP1 = 0x80, + INT_9_TAP_SAMP1_MASK = 3, + INT_9_TAP_SAMP1_SHIFT = 6 + } INT_9_BITS_T; + + /** + * REG_INT_A bits + */ + typedef enum { + INT_A_ORIENT_MODE0 = 0x01, + INT_A_ORIENT_MODE1 = 0x02, + _INT_A_ORIENT_MODE_MASK = 3, + _INT_A_ORIENT_MODE_SHIFT = 0, + + INT_A_ORIENT_BLOCKING0 = 0x04, + INT_A_ORIENT_BLOCKING1 = 0x08, + _INT_A_ORIENT_BLOCKING_MASK = 3, + _INT_A_ORIENT_BLOCKING_SHIFT = 2, + + INT_A_ORIENT_HYST0 = 0x10, + INT_A_ORIENT_HYST1 = 0x20, + INT_A_ORIENT_HYST2 = 0x40, + _INT_A_ORIENT_HYST_MASK = 7, + _INT_A_ORIENT_HYST_SHIFT = 4 + + // 0x80 reserved + } INT_A_BITS_T; + + /** + * INT_A_ORIENT_MODE values + */ + typedef enum { + ORIENT_MODE_SYMETRICAL = 0, + ORIENT_MODE_HIGH_ASYMETRICAL = 1, + ORIENT_MODE_LOW_ASYMETRICAL = 2 + } ORIENT_MODE_T; + + /** + * INT_A_ORIENT_BLOCKING values + */ + typedef enum { + ORIENT_BLOCKING_NONE = 0, + ORIENT_BLOCKING_THETA_ACC_1_5G = 1, + ORIENT_BLOCKING_THETA_ACC_0_2G_1_5G = 2, + ORIENT_BLOCKING_THETA_ACC_0_4G_1_5G = 3 + } ORIENT_BLOCKING_T; + + /** + * REG_INT_B bits + */ + typedef enum { + INT_B_ORIENT_THETA0 = 0x01, + INT_B_ORIENT_THETA1 = 0x02, + INT_B_ORIENT_THETA2 = 0x04, + INT_B_ORIENT_THETA3 = 0x08, + INT_B_ORIENT_THETA4 = 0x10, + INT_B_ORIENT_THETA5 = 0x20, + _INT_B_ORIENT_THETA_MASK = 63, + _INT_B_ORIENT_THETA_SHIFT = 0, + + INT_B_ORIENT_UD_EN = 0x40 + // 0x80 reserved + } INT_B_BITS_T; + + /** + * REG_INT_C bits + */ + typedef enum { + INT_B_FLAT_THETA0 = 0x01, + INT_B_FLAT_THETA1 = 0x02, + INT_B_FLAT_THETA2 = 0x04, + INT_B_FLAT_THETA3 = 0x08, + INT_B_FLAT_THETA4 = 0x10, + INT_B_FLAT_THETA5 = 0x20, + _INT_B_FLAT_THETA_MASK = 63, + _INT_B_FLAT_THETA_SHIFT = 0, + + // 0x40-0x80 reserved + } INT_C_BITS_T; + + /** + * REG_INT_D bits + */ + typedef enum { + INT_D_FLAT_HY0 = 0x01, + INT_D_FLAT_HY1 = 0x02, + INT_D_FLAT_HY2 = 0x04, + _INT_B_FLAT_HY_MASK = 7, + _INT_B_FLAT_HY_SHIFT = 0, + + // 0x08 reserved + + INT_D_FLAT_HOLD_TIME0 = 0x10, + INT_D_FLAT_HOLD_TIME1 = 0x20, + _INT_B_FLAT_HOLD_TIME_MASK = 3, + _INT_B_FLAT_HOLD_TIME_SHIFT = 4 + + // 0x40-0x80 reserved + } INT_D_BITS_T; + + /** + * REG_FIFO_CONFIG_0 bits + */ + typedef enum { + _FIFO_CONFIG_0_RESERVED_BITS = 0x80 | 0x40, + + FIFO_CONFIG_0_WATER_MARK0 = 0x01, + FIFO_CONFIG_0_WATER_MARK1 = 0x02, + FIFO_CONFIG_0_WATER_MARK2 = 0x04, + FIFO_CONFIG_0_WATER_MARK3 = 0x08, + FIFO_CONFIG_0_WATER_MARK4 = 0x10, + FIFO_CONFIG_0_WATER_MARK5 = 0x20, + _FIFO_CONFIG_0_WATER_MARK_MASK = 63, + _FIFO_CONFIG_0_WATER_MARK_SHIFT = 0 + } FIFO_CONFIG_0_BITS_T; + + /** + * REG_PMU_SELFTTEST bits + */ + typedef enum { + PMU_SELFTTEST_AXIS0 = 0x01, + PMU_SELFTTEST_AXIS1 = 0x02, + _PMU_SELFTTEST_AXIS_MASK = 3, + _PMU_SELFTTEST_AXIS_SHIFT = 0, + + PMU_SELFTTEST_SIGN = 0x04, + + // 0x08 reserved + + PMU_SELFTTEST_AMP = 0x10, + + // 0x20-0x80 reserved + } PMU_SELFTTEST_BITS_T; + + /** + * PMU_SELFTTEST_AXIS values + */ + typedef enum { + SELFTTEST_AXIS_NONE = 0, + SELFTTEST_AXIS_X = 1, + SELFTTEST_AXIS_Y = 2, + SELFTTEST_AXIS_Z = 3, + } SELFTTEST_AXIS_T; + + /** + * REG_TRIM_NVM_CTRL bits + */ + typedef enum { + TRIM_NVM_CTRL_NVM_PROG_MODE = 0x01, + TRIM_NVM_CTRL_NVM_PROG_TRIG = 0x02, + TRIM_NVM_CTRL_NVM_PROG_RDY = 0x04, + TRIM_NVM_CTRL_NVM_PROG_LOAD = 0x08, + + TRIM_NVM_CTRL_NVM_REMAIN0 = 0x10, + TRIM_NVM_CTRL_NVM_REMAIN1 = 0x20, + TRIM_NVM_CTRL_NVM_REMAIN2 = 0x40, + TRIM_NVM_CTRL_NVM_REMAIN3 = 0x80, + _TRIM_NVM_CTRL_NVM_REMAIN_MASK = 15, + _TRIM_NVM_CTRL_NVM_REMAIN_SHIFT = 4 + } TRIM_NVM_CTRL_BITS_T; + + /** + * REG_SPI3_WDT bits + */ + typedef enum { + _SPI3_WDT_RESERVED_BITS = 0xf0 | 0x08, + + SPI3_WDT_SPI3 = 0x01, // 3-wire SPI - NOT SUPPORTED + + SPI3_WDT_I2C_WDT_SEL = 0x02, + SPI3_WDT_I2C_WDT_EN = 0x04 + + // 0x08-0x80 reserved + } SPI3_WDT_BITS_T; + + /** + * REG_OFC_CTRL bits + */ + typedef enum { + OFC_CTRL_HP_X_EN = 0x01, + OFC_CTRL_HP_Y_EN = 0x02, + OFC_CTRL_HP_Z_EN = 0x04, + + // 0x08 reserved + + OFC_CTRL_CAL_RDY = 0x10, + + OFC_CTRL_CAL_TRIGGER0 = 0x20, + OFC_CTRL_CAL_TRIGGER1 = 0x40, + _OFC_CTRL_CAL_TRIGGER_MASK = 3, + _OFC_CTRL_CAL_TRIGGER_SHIFT = 5, + + OFC_CTRL_OFFSET_RESET = 0x80 + + } OFC_CTRL_BITS_T; + + /** + * OFC_CTRL_CAL_TRIGGER values + */ + typedef enum { + CAL_TRIGGER_NONE = 0, + CAL_TRIGGER_X = 1, + CAL_TRIGGER_Y = 2, + CAL_TRIGGER_Z = 3 + } CAL_TRIGGER_T; + + /** + * REG_OFC_SETTING bits + */ + typedef enum { + OFC_SETTING_CUT_OFF = 0x01, + + OFC_SETTING_OFFSET_TARGET_X0 = 0x02, + OFC_SETTING_OFFSET_TARGET_X1 = 0x04, + _OFC_SETTING_OFFSET_TARGET_X_MASK = 3, + _OFC_SETTING_OFFSET_TARGET_X_SHIFT = 1, + + OFC_SETTING_OFFSET_TARGET_Y0 = 0x08, + OFC_SETTING_OFFSET_TARGET_Y1 = 0x10, + _OFC_SETTING_OFFSET_TARGET_Y_MASK = 3, + _OFC_SETTING_OFFSET_TARGET_Y_SHIFT = 3, + + OFC_SETTING_OFFSET_TARGET_Z0 = 0x20, + OFC_SETTING_OFFSET_TARGET_Z1 = 0x40, + _OFC_SETTING_OFFSET_TARGET_Z_MASK = 3, + _OFC_SETTING_OFFSET_TARGET_Z_SHIFT = 5 + + // 0x80 reserved + } OFC_SETTING_BITS_T; + + /** + * OFC_SETTING_OFFSET_TARGET (for X, Y and Z axis) values + */ + typedef enum { + OFFSET_TARGET_0G = 0, + OFFSET_TARGET_PLUS_1G = 1, + OFFSET_TARGET_MINUS_1G = 2, + // 3 == 0G + } OFFSET_TARGET_T; + + /** + * REG_FIFO_CONFIG_1 bits + */ + typedef enum { + FIFO_CONFIG_1_FIFO_DATA_SEL0 = 0x01, + FIFO_CONFIG_1_FIFO_DATA_SEL1 = 0x02, + _FIFO_CONFIG_1_FIFO_DATA_SEL = 3, + _FIFO_CONFIG_1_FIFO_DATA_SHIFT = 0, + + // 0x04-0x20 reserved + + FIFO_CONFIG_1_FIFO_MODE0 = 0x40, + FIFO_CONFIG_1_FIFO_MODE1 = 0x80, + _FIFO_CONFIG_1_FIFO_MODE_MASK = 3, + _FIFO_CONFIG_1_FIFO_MODE_SHIFT = 5 + } FIFO_CONFIG_1_BITS_T; + + /** + * FIFO_DATA_SEL values + */ + typedef enum { + FIFO_DATA_SEL_XYZ = 0, + FIFO_DATA_SEL_X = 1, + FIFO_DATA_SEL_Y = 2, + FIFO_DATA_SEL_Z = 3 + } FIFO_DATA_SEL_T; + + /** + * FIFO_MODE values + */ + typedef enum { + FIFO_MODE_BYPASS = 0, + FIFO_MODE_FIFO = 1, + FIFO_MODE_STREAM = 2 + + // 3 == reserved (execute self-destruct :) + } FIFO_MODE_T; + + // interrupt selection for installISR() and uninstallISR() + typedef enum { + INTERRUPT_INT1, + INTERRUPT_INT2 + } 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 { + RESOLUTION_10BITS, + RESOLUTION_12BITS + } RESOLUTION_T; + + + /** + * 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. + */ + BMA250E(int bus=BMA250E_I2C_BUS, uint8_t addr=BMA250E_DEFAULT_ADDR, + int cs=-1); + + /** + * BMA250E Destructor. + */ + ~BMA250E(); + + /** + * Update the internal stored values from sensor data. + */ + void update(); + + /** + * Return the chip ID. + * + * @return The chip ID (BMA250E_CHIPID). + */ + 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 array. The pointer returned by this function is + * statically allocated and will be rewritten on each call. + * update() must have been called prior to calling this method. + * + * @return A floating point array containing x, y, and z in + * that order. + */ + float *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. Celcius is the default. + * @return The temperature in degrees Celcius 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 POWER_MODE_T values. The default is + * POWER_MODE_NORMAL. + * @param range One of the RANGE_T values. The default is + * RANGE_2G. + * @param bw One of the filtering BW_T values. The default is + * BW_250. + */ + void init(POWER_MODE_T pwr=POWER_MODE_NORMAL, + RANGE_T range=RANGE_2G, BW_T bw=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. + */ + void reset(); + + /** + * Set the acceleration scaling range. This device supports 2, 4, + * 8, and 16g ranges. + * + * @param range One of the RANGE_T values. + */ + void setRange(RANGE_T range); + + /** + * Set the output filtering bandwidth of the device. + * + * @param bw One of the BW_T values. + */ + void setBandwidth(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 POWER_MODE_T values. + */ + void setPowerMode(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. + */ + 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 FIFO_MODE_T values. + * @param axes One of the FIFO_DATA_SEL_T values. + */ + void fifoConfig(FIFO_MODE_T mode, 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 SELFTTEST_AXIS_T values. Note, only one + * axis at a time can be tested. Accelerometer output for other + * axes should be ignored. + */ + void setSelfTest(bool sign, bool amp, SELFTTEST_AXIS_T axis); + + /** + * Return the Interrupt Enables 0 register. These resgisters + * allow you to enable various interrupt conditions. See the + * datasheet for details. + * + * @return A bitmask of 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 INT_EN_0_BITS_T bits. + */ + void setInterruptEnable0(uint8_t bits); + + /** + * Return the Interrupt Enables 1 register. See the datasheet for + * details. + * + * @return A bitmask of 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 INT_EN_1_BITS_T bits. + */ + void setInterruptEnable1(uint8_t bits); + + /** + * Return the Interrupt Enables 2 register. See the datasheet for + * details. + * + * @return A bitmask of 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 INT_EN_2_BITS_T bits. + */ + 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 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 INT_MAP_0_BITS_T bits. + */ + void setInterruptMap0(uint8_t bits); + + /** + * Return the Interrupt Map 1 register. See the datasheet for + * details. + * + * @return A bitmask of INT_MAP_1_BITS_T bits. + */ + uint8_t getInterruptMap1(); + + /** + * Set the Interrupt Map 1 register. See the datasheet for + * details. + * + * @param A bitmask of INT_MAP_1_BITS_T bits. + */ + void setInterruptMap1(uint8_t bits); + + /** + * Return the Interrupt Map 2 register. See the datasheet for + * details. + * + * @return A bitmask of INT_MAP_2_BITS_T bits. + */ + uint8_t getInterruptMap2(); + + /** + * Set the Interrupt Map 2 register. See the datasheet for + * details. + * + * @param A bitmask of INT_MAP_2_BITS_T bits. + */ + 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 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 INT_SRC_BITS_T bits. + */ + 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 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 INT_OUT_CTRL_BITS_T bits. + */ + void setInterruptOutputControl(uint8_t bits); + + /** + * Clear all latched interrupts. See the datasheet for details. + */ + void clearInterruptLatches(); + + /** + * Return the current interrupt latching behavior. See the + * datasheet for details. + * + * @return One of the RST_LATCH_T values. + */ + RST_LATCH_T getInterruptLatchBehavior(); + + /** + * Set the current interrupt latching behavior. See the datasheet + * for details. + * + * @param latch One of the RST_LATCH_T values. + */ + void setInterruptLatchBehavior(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 INT_STATUS_0_BITS_T bits. + */ + uint8_t getInterruptStatus0(); + + /** + * Return the interrupt status 1 register. See the datasheet for + * details. + * + * @return a bitmask of INT_STATUS_1_BITS_T bits. + */ + uint8_t getInterruptStatus1(); + + /** + * Return the interrupt status 2 register. See the datasheet for + * details. + * + * @return a bitmask of 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 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 ORIENT_T values. + */ + 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. + */ + 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. + */ + 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. + */ + void setLowPowerMode2(); + + +#if defined(SWIGJAVA) || defined(JAVACALLBACK) + void installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level, + jobject runnable); +#else + /** + * install an interrupt handler. + * + * @param intr one of the 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 + */ + void installISR(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 INTERRUPT_PINS_T values specifying which + * interrupt pin you are removing. + */ + void uninstallISR(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. + */ + 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. + */ + void writeReg(uint8_t reg, uint8_t val); + + protected: + mraa::I2c *m_i2c; + mraa::Spi *m_spi; + + // spi chip select + mraa::Gpio *m_gpioCS; + + mraa::Gpio *m_gpioIntr1; + mraa::Gpio *m_gpioIntr2; + + uint8_t m_addr; + RESOLUTION_T m_resolution; + + // does this chip support the fifo? + bool m_fifoAvailable; + + // SPI chip select + void csOn(); + void csOff(); + + // acc data + float m_accX; + float m_accY; + float m_accZ; + + float m_accScale; + + float m_temperature; + + private: + bool m_isSPI; + + // use the FIFO by default? + bool m_useFIFO; + + // return a reference to a gpio pin pointer depending on intr + mraa::Gpio*& getPin(INTERRUPT_PINS_T intr); + + // Adding a private function definition for java bindings +#if defined(SWIGJAVA) || defined(JAVACALLBACK) + void installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level, + void (*isr)(void *), void *arg); +#endif + }; +} diff --git a/src/bmx055/bmc150.cxx b/src/bmx055/bmc150.cxx new file mode 100644 index 00000000..26d3f62b --- /dev/null +++ b/src/bmx055/bmc150.cxx @@ -0,0 +1,120 @@ +/* + * 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 + +#include "bmc150.hpp" + +using namespace upm; +using namespace std; + +BMC150::BMC150(int accelBus, uint8_t accelAddr, int accelCS, + int magBus, uint8_t magAddr, int magCS) : + m_accel(0), m_mag(0) +{ + // if -1 is supplied as a bus for any of these, we will not + // instantiate them + + if (accelBus >= 0) + m_accel = new BMA250E(accelBus, accelAddr, accelCS); + + if (magBus >= 0) + m_mag = new BMM150(magBus, magAddr, magCS); + + // now initialize them... + if (m_accel) + m_accel->init(); + + if (m_mag) + m_mag->init(); +} + +BMC150::~BMC150() +{ + if (m_accel) + delete m_accel; + + if (m_mag) + delete m_mag; +} + +void BMC150::initAccelerometer(BMA250E::POWER_MODE_T pwr, + BMA250E::RANGE_T range, + BMA250E::BW_T bw) +{ + if (m_accel) + m_accel->init(pwr, range, bw); +} + +void BMC150::initMagnetometer(BMM150::USAGE_PRESETS_T usage) +{ + if (m_mag) + m_mag->init(usage); +} + +void BMC150::update() +{ + if (m_accel) + m_accel->update(); + + if (m_mag) + m_mag->update(); +} + +void BMC150::getAccelerometer(float *x, float *y, float *z) +{ + if (m_accel) + m_accel->getAccelerometer(x, y, z); +} + +float *BMC150::getAccelerometer() +{ + if (m_accel) + return m_accel->getAccelerometer(); + else + { + static float v[3] = {0.0f, 0.0f, 0.0f}; + return v; + } +} + +void BMC150::getMagnetometer(float *x, float *y, float *z) +{ + if (m_mag) + m_mag->getMagnetometer(x, y, z); +} + +float *BMC150::getMagnetometer() +{ + if (m_mag) + return m_mag->getMagnetometer(); + else + { + static float v[3] = {0.0f, 0.0f, 0.0f}; + return v; + } +} diff --git a/src/bmx055/bmc150.hpp b/src/bmx055/bmc150.hpp new file mode 100644 index 00000000..c570af01 --- /dev/null +++ b/src/bmx055/bmc150.hpp @@ -0,0 +1,196 @@ +/* + * 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. + */ +#pragma once + +#include + +#include "bma250e.hpp" +#include "bmm150.hpp" + +#define BMC150_DEFAULT_BUS 0 +#define BMC150_DEFAULT_ACC_ADDR 0x10 +#define BMC150_DEFAULT_MAG_ADDR 0x12 + +namespace upm { + + /** + * @library bmx055 + * @sensor bmc150 + * @comname BMC150 6-axis eCompass + * @type accelerometer compass + * @man mouser + * @con i2c gpio spi + * @web http://www.mouser.com/ProductDetail/Bosch-Sensortec/0330SB0156/?qs=sGAEpiMZZMsrChSOYEGTCd8nwjostN1SWavW0HYOOXw%3d + * + * @brief API for the BMC150 6-axis eCompass + * + * + * The BMC150 is an integrated electronic compass solution for + * consumer market applications. It comprises a 12bit leading edge + * triaxial, low-g acceleration sensor and an ultra-low power, high + * precision triaxial magnetic field sensor. It allows measurements + * of acceleration and magnetic field in three perpendicular + * axes. Performance and features of both sensing technologies are + * carefully tuned and perfectly match the demanding requirements of + * all 6-axis mobile applications such as electronic compass, + * navigation or augmented reality. + + * The BMC150 is essentially 2 separate devices in one: the BMA250E + * Accelerometer and the BMM150 Magnetometer. They are completely + * independant of each other. + * + * This driver provides a very simple interface to these 2 devices. + * If finer control is desired, you should just use the separate + * BMA25E and BMM150 device classes directly. This driver simply + * initializes both devices, and provides a mechanism to read + * accelerometer and magnetometer data from them. + * + * @snippet bmc150.cxx Interesting + */ + + class BMC150 { + public: + /** + * BMC150 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 accelBus I2C or SPI bus to use. -1 to skip initializing + * this device. + * @param accelAddr The address for this device. -1 for SPI. + * @param accelCS The gpio pin to use for the SPI Chip Select. -1 for + * I2C or for SPI with a hardware controlled pin. + * @param magBus I2C or SPI bus to use. -1 to skip initializing + * this device. + * @param magAddr The address for this device. -1 for SPI. + * @param magCS The gpio pin to use for the SPI Chip Select. -1 for + * I2C or for SPI with a hardware controlled pin. + */ + BMC150(int accelBus=BMC150_DEFAULT_BUS, + uint8_t accelAddr=BMC150_DEFAULT_ACC_ADDR, + int accelCS=-1, + int magBus=BMC150_DEFAULT_BUS, + uint8_t magAddr=BMC150_DEFAULT_MAG_ADDR, + int magCS=-1); + + /** + * BMC150 Destructor. + */ + ~BMC150(); + + /** + * Update the internal stored values from sensor data. + */ + void update(); + + /** + * Initialize the accelerometer 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 or you + * want to change these values. + * + * @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. + */ + void initAccelerometer(BMA250E::POWER_MODE_T pwr=BMA250E::POWER_MODE_NORMAL, + BMA250E::RANGE_T range=BMA250E::RANGE_2G, + BMA250E::BW_T bw=BMA250E::BW_250); + + /** + * Initialize the magnetometer 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 or you want to + * change these values. This method will call + * BMM150::setPresetMode() with the passed parameter. + * + * @param usage One of the BMM150::USAGE_PRESETS_T values. The default is + * BMM150::USAGE_HIGH_ACCURACY. + */ + void initMagnetometer(BMM150::USAGE_PRESETS_T usage=BMM150::USAGE_HIGH_ACCURACY); + + /** + * 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 array. The pointer returned by this function is + * statically allocated and will be rewritten on each call. + * update() must have been called prior to calling this method. + * + * @return A floating point array containing x, y, and z in + * that order. + */ + float *getAccelerometer(); + + /** + * Return magnetometer data in micro-Teslas (uT). 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 getMagnetometer(float *x, float *y, float *z); + + /** + * Return magnetometer data in micro-Teslas (uT) in the form of a + * floating point array. The pointer returned by this function is + * statically allocated and will be rewritten on each call. + * update() must have been called prior to calling this method. + * + * @return A floating point array containing x, y, and z in + * that order. + */ + float *getMagnetometer(); + + + protected: + BMA250E *m_accel; + BMM150 *m_mag; + + private: + }; +} diff --git a/src/bmx055/bmg160.cxx b/src/bmx055/bmg160.cxx new file mode 100644 index 00000000..45593b6a --- /dev/null +++ b/src/bmx055/bmg160.cxx @@ -0,0 +1,581 @@ +/* + * 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 +#include + +#include "bmg160.hpp" + +using namespace upm; +using namespace std; + +#define BMG160_DEFAULT_CHIPID 0x0f + +// conversion from celcius to fahrenheit + +static float c2f(float c) +{ + return (c * (9.0 / 5.0) + 32.0); +} + +BMG160::BMG160(int bus, uint8_t addr, int cs) : + m_i2c(0), m_spi(0), m_gpioIntr1(0), m_gpioIntr2(0), m_gpioCS(0) +{ + m_addr = addr; + m_isSPI = false; + + m_gyrX = 0; + m_gyrY = 0; + m_gyrZ = 0; + m_gyrScale = 0; + m_temperature = 0.0; + + if (addr < 0) + m_isSPI = true; + + if (m_isSPI) + { + m_spi = new mraa::Spi(bus); + + // Only create cs context if we are actually using a valid pin. + // A hardware controlled pin should specify cs as -1. + if (cs >= 0) + { + m_gpioCS = new mraa::Gpio(cs); + m_gpioCS->dir(mraa::DIR_OUT); + } + + m_spi->mode(mraa::SPI_MODE0); + m_spi->frequency(5000000); + } + else + { + // I2C + m_i2c = new mraa::I2c(bus); + + mraa::Result rv; + if ((rv = m_i2c->address(m_addr)) != mraa::SUCCESS) + { + throw std::runtime_error(string(__FUNCTION__) + + ": I2c.address() failed"); + } + } + + // check the chip id + + uint8_t chipID = getChipID(); + if (chipID != BMG160_DEFAULT_CHIPID) + { + throw std::runtime_error(string(__FUNCTION__) + + ": invalid chip ID. Expected " + + std::to_string(int(BMG160_DEFAULT_CHIPID)) + + ", got " + + std::to_string(int(chipID))); + } + + // call init with default options + init(); +} + +BMG160::~BMG160() +{ + uninstallISR(INTERRUPT_INT1); + uninstallISR(INTERRUPT_INT2); +} + +void BMG160::init(POWER_MODE_T pwr, RANGE_T range, BW_T bw) +{ + setPowerMode(pwr); + usleep(50000); // 50ms, in case we are waking up + + // set our range and bandwidth + setRange(range); + setBandwidth(bw); + + // make sure register shadowing is enabled + enableRegisterShadowing(true); + + // enable output filtering + enableOutputFiltering(true); + + // use the FIFO by default + fifoConfig(FIFO_MODE_BYPASS, FIFO_DATA_SEL_XYZ); + enableFIFO(true); + + // settle + usleep(50000); +} + +void BMG160::update() +{ + int bufLen = 0; + uint8_t startReg = 0; + + if (m_useFIFO) + { + bufLen = 6; + startReg = REG_FIFO_DATA; + } + else + { + // non FIFO, read acc regs directly (including temp) + bufLen = 7; + startReg = REG_RATE_X_LSB; + } + + uint8_t buf[bufLen]; + + if (readRegs(startReg, buf, bufLen) != bufLen) + { + throw std::runtime_error(string(__FUNCTION__) + + ": readRegs() failed to read " + + std::to_string(bufLen) + + " bytes"); + } + + int16_t val; + + // x + val = int16_t(buf[1] << 8 | buf[0]); + m_gyrX = float(val); + + // y + val = int16_t(buf[3] << 8 | buf[2]); + m_gyrY = float(val); + + // z + val = int16_t(buf[5] << 8 | buf[4]); + m_gyrZ = float(val); + + // get the temperature... + + uint8_t temp = 0; + if (m_useFIFO) + { + // we have to read temperature separately... + temp = readReg(REG_TEMP); + } + else + { + // we already got it + temp = buf[6]; + } + + // .5K/LSB, 23C center point + m_temperature = (float(temp) / 2.0) + 23.0; +} + +void BMG160::enableFIFO(bool useFIFO) +{ + m_useFIFO = useFIFO; +} + +uint8_t BMG160::readReg(uint8_t reg) +{ + if (m_isSPI) + { + reg |= 0x80; // needed for read + uint8_t pkt[2] = {reg, 0}; + + csOn(); + if (m_spi->transfer(pkt, pkt, 2)) + { + csOff(); + throw std::runtime_error(string(__FUNCTION__) + + ": Spi.transfer() failed"); + } + csOff(); + + return pkt[1]; + } + else + return m_i2c->readReg(reg); +} + +int BMG160::readRegs(uint8_t reg, uint8_t *buffer, int len) +{ + if (m_isSPI) + { + reg |= 0x80; // needed for read + + uint8_t sbuf[len + 1]; + memset((char *)sbuf, 0, len + 1); + sbuf[0] = reg; + + // We need to do it this way for edison - ie: use a single + // transfer rather than breaking it up into two like we used to. + // This means a buffer copy is now required, but that's the way + // it goes. + + csOn(); + if (m_spi->transfer(sbuf, sbuf, len + 1)) + { + csOff(); + throw std::runtime_error(string(__FUNCTION__) + + ": Spi.transfer(buf) failed"); + } + csOff(); + + // now copy it into user buffer + for (int i=0; ireadBytesReg(reg, buffer, len); +} + +void BMG160::writeReg(uint8_t reg, uint8_t val) +{ + if (m_isSPI) + { + reg &= 0x7f; // mask off 0x80 for writing + uint8_t pkt[2] = {reg, val}; + + csOn(); + if (m_spi->transfer(pkt, NULL, 2)) + { + csOff(); + throw std::runtime_error(string(__FUNCTION__) + + ": Spi.transfer() failed"); + } + csOff(); + } + else + { + + mraa::Result rv; + if ((rv = m_i2c->writeReg(reg, val)) != mraa::SUCCESS) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": I2c.writeReg() failed"); + } + } +} + +void BMG160::csOn() +{ + if (m_gpioCS) + m_gpioCS->write(0); +} + +void BMG160::csOff() +{ + if (m_gpioCS) + m_gpioCS->write(1); +} + +uint8_t BMG160::getChipID() +{ + return readReg(REG_CHIP_ID); +} + +void BMG160::getGyroscope(float *x, float *y, float *z) +{ + if (x) + *x = (m_gyrX * m_gyrScale) / 1000.0; + + if (y) + *y = (m_gyrY * m_gyrScale) / 1000.0; + + if (z) + *z = (m_gyrZ * m_gyrScale) / 1000.0; +} + +float *BMG160::getGyroscope() +{ + static float v[3]; + + getGyroscope(&v[0], &v[1], &v[2]); + return v; +} + +float BMG160::getTemperature(bool fahrenheit) +{ + if (fahrenheit) + return c2f(m_temperature); + else + return m_temperature; +} + +void BMG160::reset() +{ + writeReg(REG_SOFTRESET, BMG160_RESET_BYTE); + sleep(1); +} + +void BMG160::setRange(RANGE_T range) +{ + switch(range) + { + case RANGE_125: + m_gyrScale = 3.8; // milli-degrees + break; + + case RANGE_250: + m_gyrScale = 7.6; + break; + + case RANGE_500: + m_gyrScale = 15.3; + break; + + case RANGE_1000: + m_gyrScale = 30.5; + break; + + case RANGE_2000: + m_gyrScale = 61.0; + break; + } + + // we also have to write a fixed '0x10' to the high-order bits for + // some reason (according to datasheet) + uint8_t reg = range | (_GYR_RANGE_FIXED_VALUE << _GYR_RANGE_FIXED_SHIFT); + writeReg(REG_GYR_RANGE, reg); +} + +void BMG160::setBandwidth(BW_T bw) +{ + writeReg(REG_GYR_BW, bw); +} + +void BMG160::setPowerMode(POWER_MODE_T power) +{ + // mask off reserved bits + uint8_t reg = readReg(REG_LPM1) & ~_LPM1_RESERVED_MASK; + + reg &= ~(_LPM1_POWER_MODE_MASK << _LPM1_POWER_MODE_SHIFT); + reg |= (power << _LPM1_POWER_MODE_SHIFT); + + writeReg(REG_LPM1, power); +} + +void BMG160::fifoSetWatermark(int wm) +{ + // mask off illegal values + uint8_t reg = uint8_t(wm) & _FIFO_CONFIG_0_WATER_MARK_MASK; + + writeReg(REG_FIFO_CONFIG_0, reg); +} + +void BMG160::fifoConfig(FIFO_MODE_T mode, FIFO_DATA_SEL_T axes) +{ + uint8_t reg = ( (mode << _FIFO_CONFIG_1_FIFO_MODE_SHIFT) | + (axes << _FIFO_CONFIG_1_FIFO_DATA_SHIFT) ); + + writeReg(REG_FIFO_CONFIG_1, reg); +} + +uint8_t BMG160::getInterruptEnable0() +{ + return readReg(REG_INT_EN_0) & ~_INT_EN_0_RESERVED_BITS; +} + +void BMG160::setInterruptEnable0(uint8_t bits) +{ + uint8_t reg = bits & ~_INT_EN_0_RESERVED_BITS; + + writeReg(REG_INT_EN_0, reg); +} + +uint8_t BMG160::getInterruptMap0() +{ + return readReg(REG_INT_MAP_0) & ~_INT_MAP_0_RESERVED_BITS; +} + +void BMG160::setInterruptMap0(uint8_t bits) +{ + uint8_t reg = bits & ~_INT_MAP_0_RESERVED_BITS; + + writeReg(REG_INT_MAP_0, reg); +} + +uint8_t BMG160::getInterruptMap1() +{ + return readReg(REG_INT_MAP_1); +} + +void BMG160::setInterruptMap1(uint8_t bits) +{ + writeReg(REG_INT_MAP_1, bits); +} + +// REG_INT_EN1, for some strange reason +uint8_t BMG160::getInterruptSrc() +{ + return readReg(REG_INT_EN_1) & ~_INT_EN_1_INT1_RESERVED_BITS; +} + +void BMG160::setInterruptSrc(uint8_t bits) +{ + uint8_t reg = bits & ~_INT_EN_1_INT1_RESERVED_BITS; + + writeReg(REG_INT_EN_1, reg); +} + +uint8_t BMG160::getInterruptOutputControl() +{ + return readReg(REG_INT_EN_1) & ~_INT_EN_1_INT1_RESERVED_BITS; +} + +void BMG160::setInterruptOutputControl(uint8_t bits) +{ + uint8_t reg = bits & ~_INT_EN_1_INT1_RESERVED_BITS; + + writeReg(REG_INT_EN_1, reg); +} + +void BMG160::clearInterruptLatches() +{ + uint8_t reg = readReg(REG_INT_RST_LATCH) & ~_INT_RST_LATCH_RESERVED_BITS; + + reg |= INT_RST_LATCH_RESET_INT; + + writeReg(REG_INT_RST_LATCH, reg); +} + +BMG160::RST_LATCH_T BMG160::getInterruptLatchBehavior() +{ + uint8_t reg = readReg(REG_INT_RST_LATCH) & ~_INT_RST_LATCH_RESERVED_BITS; + + reg &= (_INT_RST_LATCH_MASK << _INT_RST_LATCH_SHIFT); + + return static_cast(reg); +} + +void BMG160::setInterruptLatchBehavior(RST_LATCH_T latch) +{ + uint8_t reg = readReg(REG_INT_RST_LATCH) & ~_INT_RST_LATCH_RESERVED_BITS; + + reg &= ~(_INT_RST_LATCH_MASK << _INT_RST_LATCH_SHIFT); + reg |= (latch << _INT_RST_LATCH_SHIFT); + + writeReg(REG_INT_RST_LATCH, reg); +} + +void BMG160::enableRegisterShadowing(bool shadow) +{ + uint8_t reg = readReg(REG_RATE_HBW) & ~_RATE_HBW_RESERVED_BITS; + + if (shadow) + reg &= ~RATE_HBW_SHADOW_DIS; + else + reg |= RATE_HBW_SHADOW_DIS; + + writeReg(REG_RATE_HBW, reg); +} + +void BMG160::enableOutputFiltering(bool filter) +{ + uint8_t reg = readReg(REG_RATE_HBW) & ~_RATE_HBW_RESERVED_BITS; + + if (filter) + reg &= ~RATE_HBW_DATA_HIGH_BW; + else + reg |= RATE_HBW_DATA_HIGH_BW; + + writeReg(REG_RATE_HBW, reg); +} + +uint8_t BMG160::getInterruptStatus0() +{ + return readReg(REG_INT_STATUS_0) & ~_INT_STATUS_0_RESERVED_BITS; +} + +uint8_t BMG160::getInterruptStatus1() +{ + return readReg(REG_INT_STATUS_1) & ~_INT_STATUS_1_RESERVED_BITS; +} + +uint8_t BMG160::getInterruptStatus2() +{ + return readReg(REG_INT_STATUS_2) & ~_INT_STATUS_2_RESERVED_BITS; +} + +uint8_t BMG160::getInterruptStatus3() +{ + return readReg(REG_INT_STATUS_3) & ~_INT_STATUS_3_RESERVED_BITS; +} + +#if defined(SWIGJAVA) || (JAVACALLBACK) +void BMG160::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level, + jobject runnable) +{ + // delete any existing ISR and GPIO context + uninstallISR(intr); + + // create gpio context + getPin(intr) = new mraa::Gpio(gpio); + + getPin(intr)->dir(mraa::DIR_IN); + getPin(intr)->isr(level, runnable); +} +#else +void BMG160::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level, + void (*isr)(void *), void *arg) +{ + // delete any existing ISR and GPIO context + uninstallISR(intr); + + // create gpio context + getPin(intr) = new mraa::Gpio(gpio); + + getPin(intr)->dir(mraa::DIR_IN); + getPin(intr)->isr(level, isr, arg); +} +#endif + +void BMG160::uninstallISR(INTERRUPT_PINS_T intr) +{ + if (getPin(intr)) + { + getPin(intr)->isrExit(); + delete getPin(intr); + + getPin(intr) = 0; + } +} + +mraa::Gpio*& BMG160::getPin(INTERRUPT_PINS_T intr) +{ + switch(intr) + { + case INTERRUPT_INT1: + return m_gpioIntr1; + break; + + case INTERRUPT_INT2: + return m_gpioIntr2; + break; + + default: + throw std::out_of_range(string(__FUNCTION__) + + ": Invalid interrupt enum passed"); + } +} diff --git a/src/bmx055/bmg160.hpp b/src/bmx055/bmg160.hpp new file mode 100644 index 00000000..9b7b3893 --- /dev/null +++ b/src/bmx055/bmg160.hpp @@ -0,0 +1,1223 @@ +/* + * 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. + */ +#pragma once + +#include +#include +#include +#include + +#define BMG160_I2C_BUS 0 +#define BMG160_SPI_BUS 0 +#define BMG160_DEFAULT_ADDR 0x68 + + +namespace upm { + + /** + * @library bmx050 + * @sensor bmg160 + * @comname BMG160 16 bit Trixial Gyroscope + * @type gyro + * @man bosch + * @con i2c spi gpio + * + * @brief API for the BMG160 16 bit Trixial Gyroscope + * + * The BMG160 is a 3-axis angular rate sensor that is made of a + * surface micro machined sensing element and an evaluation ASIC. + * Both parts are packed into one single LGA 3.0mm x 3.0mm x 0.95mm + * housing. The BMG160 is designed to meet requirements for + * consumer applications such as image stabilization (DSC and + * camera-phone), gaming and pointing devices. It is capable to + * measure angular rates in three perpendicular room dimensions, the + * x-, y- and z-axis, and to provide the corresponding output + * signals. The BMG160 is fitted with digital bi-directional SPI and + * I2C interfaces for optimum system integration. + * + * 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 device requires 3.3v operation. + * + * @snippet bmg160.cxx Interesting + */ + + class BMG160 { + public: + // special reset byte + static const uint8_t BMG160_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. + + /** + * BMG160 registers + */ + typedef enum : uint8_t { + REG_CHIP_ID = 0x00, + + // 0x01 reserved + + REG_RATE_X_LSB = 0x02, + REG_RATE_X_MSB = 0x03, + REG_RATE_Y_LSB = 0x04, + REG_RATE_Y_MSB = 0x05, + REG_RATE_Z_LSB = 0x06, + REG_RATE_Z_MSB = 0x07, + + REG_TEMP = 0x08, + + REG_INT_STATUS_0 = 0x09, + REG_INT_STATUS_1 = 0x0a, + REG_INT_STATUS_2 = 0x0b, + REG_INT_STATUS_3 = 0x0c, + + // 0x0d reserved + + REG_FIFO_STATUS = 0x0e, + + REG_GYR_RANGE = 0x0f, + REG_GYR_BW = 0x10, + REG_LPM1 = 0x11, + REG_LPM2 = 0x12, + + REG_RATE_HBW = 0x13, + + REG_SOFTRESET = 0x14, + + REG_INT_EN_0 = 0x15, + REG_INT_EN_1 = 0x16, + + REG_INT_MAP_0 = 0x17, + REG_INT_MAP_1 = 0x18, + REG_INT_MAP_2 = 0x19, + + REG_INT_1A = 0x1a, + REG_INT_1B = 0x1b, + REG_INT_1C = 0x1c, + + // 0x1d reserved + + REG_INT_1E = 0x1e, + + // 0x1f-0x20 reserved + + REG_INT_RST_LATCH = 0x21, + + REG_HIGH_TH_X = 0x22, + REG_HIGH_DUR_X = 0x23, + REG_HIGH_TH_Y = 0x24, + REG_HIGH_DUR_Y = 0x25, + REG_HIGH_TH_Z = 0x26, + REG_HIGH_DUR_Z = 0x27, + + // 0x28-0x30 reserved + + REG_SOC = 0x31, + REG_A_FOC = 0x32, + + REG_TRIM_NVM_CTRL = 0x33, + + REG_SPI3_WDT = 0x34, + + // 0x35 reserved + + REG_OFC1 = 0x36, + REG_OFC2 = 0x37, + REG_OFC3 = 0x38, + REG_OFC4 = 0x39, + + REG_TRIM_GP0 = 0x3a, + REG_TRIM_GP1 = 0x3b, + + REG_BIST = 0x3c, + + REG_FIFO_CONFIG_0 = 0x3d, + REG_FIFO_CONFIG_1 = 0x3e, + + REG_FIFO_DATA = 0x3f + + } BMG160_REGS_T; + + /** + * REG_INT_STATUS_0 bits + */ + typedef enum { + _INT_STATUS_0_RESERVED_BITS = 0xf0 | 0x08 | 0x01, + + INT_STATUS_0_HIGH_INT = 0x02, + INT_STATUS_0_ANY_INT = 0x04 + } INT_STATUS_0_BITS_T; + + /** + * REG_INT_STATUS_1 bits + */ + typedef enum { + _INT_STATUS_1_RESERVED_BITS = 0x0f, + + INT_STATUS_1_FIFO_INT = 0x10, + INT_STATUS_1_FAST_OFFSET_INT = 0x20, + INT_STATUS_1_AUTO_OFFSET_INT = 0x40, + INT_STATUS_1_DATA_INT = 0x80 + } INT_STATUS_1_BITS_T; + + /** + * REG_INT_STATUS_2 bits + */ + typedef enum { + _INT_STATUS_2_RESERVED_BITS = 0xf0, + + INT_STATUS_2_ANY_FIRST_X = 0x01, + INT_STATUS_2_ANY_FIRST_Y = 0x02, + INT_STATUS_2_ANY_FIRST_Z = 0x04, + INT_STATUS_2_ANY_SIGN = 0x08 + } INT_STATUS_2_BITS_T; + + /** + * REG_INT_STATUS_3 bits + */ + typedef enum { + _INT_STATUS_3_RESERVED_BITS = 0xf0, + + INT_STATUS_3_HIGH_FIRST_X = 0x01, + INT_STATUS_3_HIGH_FIRST_Y = 0x02, + INT_STATUS_3_HIGH_FIRST_Z = 0x04, + INT_STATUS_3_HIGH_SIGN = 0x08 + } INT_STATUS_3_BITS_T; + + /** + * REG_FIFO_STATUS bits + */ + typedef enum { + FIFO_STATUS_FRAME_COUNTER0 = 0x01, + FIFO_STATUS_FRAME_COUNTER1 = 0x02, + FIFO_STATUS_FRAME_COUNTER2 = 0x04, + FIFO_STATUS_FRAME_COUNTER3 = 0x08, + FIFO_STATUS_FRAME_COUNTER4 = 0x10, + FIFO_STATUS_FRAME_COUNTER5 = 0x20, + FIFO_STATUS_FRAME_COUNTER6 = 0x40, + _FIFO_STATUS_FRAME_COUNTER_MASK = 127, + _FIFO_STATUS_FRAME_COUNTER_SHIFT = 0, + + FIFO_STATUS_FIFO_OVERRUN = 0x80 + } FIFO_STATUS_BITS_T; + + /** + * REG_GYR_RANGE bits + */ + typedef enum { + _GYR_RANGE_RESERVED_BITS = 0x20 | 0x10 | 0x08, + + GYR_RANGE0 = 0x01, + GYR_RANGE1 = 0x02, + GYR_RANGE2 = 0x04, + _GYR_RANGE_MASK = 7, + _GYR_RANGE_SHIFT = 0, + + GYR_RANGE_FIXED0 = 0x40, // bits need hardcoding to 0b10 + GYR_RANGE_FIXED1 = 0x80, // for some odd reason... + _GYR_RANGE_FIXED_MASK = 3, + _GYR_RANGE_FIXED_SHIFT = 6, + _GYR_RANGE_FIXED_VALUE = 2 // 0b10 + } GYR_RANGE_BITS_T; + + /** + * GYR_RANGE (gyroscope deg/s range) values + */ + typedef enum { + RANGE_2000 = 0, // degrees/sec + RANGE_1000 = 1, + RANGE_500 = 2, + RANGE_250 = 3, + RANGE_125 = 4 + } RANGE_T; + + /** + * REG_GYR_BW bits + */ + typedef enum { + _GYR_BW_RESERVED_BITS = 0xf0, + + GYR_BW0 = 0x01, + GYR_BW1 = 0x02, + GYR_BW2 = 0x04, + GYR_BW3 = 0x08, + _GYR_BW_MASK = 15, + _GYR_BW_SHIFT = 0 + } GYR_BW_BITS_T; + + /** + * GYR_BW (gyroscope filter bandwidth) values + */ + typedef enum { + BW_2000_UNFILTERED = 0, // ODR/Filter BW + BW_2000_230 = 1, // ODR 2000Hz, Filter BW 230Hz + BW_1000_116 = 2, + BW_400_47 = 3, + BW_200_23 = 4, + BW_100_12 = 5, + BW_200_64 = 6, + BW_100_32 = 7 + } BW_T; + + /** + * REG_LPM1 bits + */ + typedef enum { + // 0x01 reserved + _LPM1_RESERVED_MASK = 0x40 | 0x10 | 0x01, + + LPM1_SLEEP_DUR0 = 0x02, // sleep dur in low power mode + LPM1_SLEEP_DUR1 = 0x04, + LPM1_SLEEP_DUR2 = 0x08, + _LPM1_SLEEP_MASK = 7, + _LPM1_SLEEP_SHIFT = 1, + + // These are separate bits, deep_suspend 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. + LPM1_POWER_MODE0 = 0x20, // deep_suspend + LPM1_POWER_MODE1 = 0x40, // must always be 0! + LPM1_POWER_MODE2 = 0x80, // suspend + _LPM1_POWER_MODE_MASK = 7, + _LPM1_POWER_MODE_SHIFT = 5 + } LPM1_BITS_T; + + /** + * SLEEP_DUR values + */ + typedef enum { + SLEEP_DUR_2 = 0, // 2ms + SLEEP_DUR_4 = 1, + SLEEP_DUR_5 = 2, + SLEEP_DUR_8 = 3, + SLEEP_DUR_10 = 4, + SLEEP_DUR_15 = 5, + SLEEP_DUR_18 = 6, + SLEEP_DUR_20 = 7 + } SLEEP_DUR_T; + + /** + * POWER_MODE values + */ + typedef enum { + POWER_MODE_NORMAL = 0, + POWER_MODE_DEEP_SUSPEND = 1, + POWER_MODE_SUSPEND = 4 + } POWER_MODE_T; + + /** + * REG_LPM2 bits + */ + typedef enum { + _LPM2_RESERVED_BITS = 0x08, + + LPM2_AUTOSLEEP_DUR0 = 0x01, + LPM2_AUTOSLEEP_DUR1 = 0x02, + LPM2_AUTOSLEEP_DUR2 = 0x04, + _LPM2_AUTOSLEEP_DUR_MASK = 7, + _LPM2_AUTOSLEEP_DUR_SHIFT = 0, + + LPM2_EXT_TRIG_SEL0 = 0x10, + LPM2_EXT_TRIG_SEL1 = 0x20, + _LPM2_EXT_TRIG_SEL_MASK = 3, + _LPM2_EXT_TRIG_SEL_SHIFT = 4, + + LPM2_POWER_SAVE_MODE = 0x40, + LPM2_FAST_POWERUP = 0x80 + } LPM2_BITS_T; + + + /** + * LPM2_AUTOSLEEP_DUR values + */ + typedef enum { + AUTOSLEEP_DUR_NONE = 0, + AUTOSLEEP_DUR_4MS = 1, + AUTOSLEEP_DUR_5MS = 2, + AUTOSLEEP_DUR_8MS = 3, + AUTOSLEEP_DUR_10MS = 4, + AUTOSLEEP_DUR_15MS = 5, + AUTOSLEEP_DUR_20MS = 6, + AUTOSLEEP_DUR_40MS = 7 + } AUTOSLEEP_DUR_T; + + /** + * LPM2_EXT_TRIG_SEL values + */ + typedef enum { + EXT_TRIG_SEL_NONE = 0, + EXT_TRIG_SEL_INT1 = 1, + EXT_TRIG_SEL_INT2 = 2, + EXT_TRIG_SEL_SDO = 3 // if SPI3 mode (unsupported) + } EXT_TRIG_SEL_T; + + /** + * REG_RATE_HBW bits + */ + typedef enum { + _RATE_HBW_RESERVED_BITS = 0x0f | 0x10 | 0x20, + + RATE_HBW_SHADOW_DIS = 0x40, + RATE_HBW_DATA_HIGH_BW = 0x80 + } RATE_HBW_BITS_T; + + /** + * REG_INT_EN_0 bits + */ + typedef enum { + _INT_EN_0_RESERVED_BITS = 0x20 | 0x10 | 0x08 | 0x02 | 0x01, + + INT_EN_0_AUTO_OFFSET_EN = 0x04, + + INT_EN_0_FIFO_EN = 0x40, + INT_EN_0_DATA_EN = 0x80 + } INT_EN_0_BITS_T; + + /** + * REG_INT_EN_1 bits + */ + typedef enum { + _INT_EN_1_INT1_RESERVED_BITS = 0xf0, + + INT_EN_1_INT1_LVL = 0x01, // level or edge + INT_EN_1_INT1_OD = 0x02, // push-pull or open drain + INT_EN_1_INT2_LVL = 0x04, + INT_EN_1_INT2_OD = 0x08 + } INT_EN_1_BITS_T; + + /** + * REG_INT_MAP_0 bits + */ + typedef enum { + _INT_MAP_0_RESERVED_BITS = 0xf0 | 0x04 | 0x01, + + INT_MAP_0_INT1_ANY = 0x02, + INT_MAP_0_INT1_HIGH = 0x08 + } INT_MAP_0_BITS_T; + + /** + * REG_INT_MAP_1 bits + */ + typedef enum { + INT_MAP_1_INT1_DATA = 0x01, + INT_MAP_1_INT1_FAST_OFFSET = 0x02, + INT_MAP_1_INT1_FIFO = 0x04, + INT_MAP_1_INT1_AUTO_OFFSET = 0x08, + INT_MAP_1_INT2_AUTO_OFFSET = 0x10, + INT_MAP_1_INT2_FIFO = 0x20, + INT_MAP_1_INT2_FAST_OFFSET = 0x40, + INT_MAP_1_INT2_DATA = 0x80 + } INT_MAP_1_BITS_T; + + /** + * REG_INT_1A bits + */ + typedef enum { + _INT_1A_RESERVED_BITS = 0xd5, + + INT_1A_ANY_UNFILT_DATA = 0x02, + INT_1A_HIGH_UNFILT_DATA = 0x08, + INT_1A_SLOW_OFFSET_UNFILT = 0x20 + } INT_1A_BITS_T; + + /** + * REG_INT_1B bits + */ + typedef enum { + INT_1B_ANY_TH0 = 0x01, + INT_1B_ANY_TH1 = 0x02, + INT_1B_ANY_TH2 = 0x04, + INT_1B_ANY_TH3 = 0x08, + INT_1B_ANY_TH4 = 0x10, + INT_1B_ANY_TH5 = 0x20, + INT_1B_ANY_TH6 = 0x40, + _INT_1B_ANY_TH_MASK = 127, + _INT_1B_ANY_TH_SHIFT = 0, + + INT_1B_FAST_OFFSET_UNFILT = 0x80 + } INT_1B_BITS_T; + + /** + * REG_INT_1C bits + */ + typedef enum { + _INT_1C_RESERVED_BITS = 0x08, + + INT_1C_ANY_EN_X = 0x01, + INT_1C_ANY_EN_Y = 0x02, + INT_1C_ANY_EN_Z = 0x04, + + INT_1C_ANY_DUR_SAMPLE0 = 0x10, + INT_1C_ANY_DUR_SAMPLE1 = 0x20, + INT_1C_ANY_DUR_SAMPLE_MASK = 3, + INT_1C_ANY_DUR_SAMPLE_SHIFT = 4, + + INT_1C_AWAKE_DUR0 = 0x40, + INT_1C_AWAKE_DUR1 = 0x80, + INT_1C_AWAKE_DUR_MASK = 3, + INT_1C_AWAKE_DUR_SHIFT = 6 + } INT_1C_BITS_T; + + /** + * INT_1C_ANY_DUR_SAMPLE values + */ + typedef enum { + ANY_DUR_SAMPLE_4 = 0, // samples + ANY_DUR_SAMPLE_8 = 1, + ANY_DUR_SAMPLE_12 = 2, + ANY_DUR_SAMPLE_16 = 3 + } ANY_DUR_SAMPLE_T; + + /** + * INT_1C_AWAKE_DUR values + */ + typedef enum { + AWAKE_DUR_SAMPLE_8 = 0, // samples + AWAKE_DUR_SAMPLE_16 = 1, + AWAKE_DUR_SAMPLE_32 = 2, + AWAKE_DUR_SAMPLE_64 = 3 + } AWAKE_DUR_SAMPLE_T; + + /** + * REG_INT_1E bits + */ + typedef enum { + _INT_1E_RESERVED_BITS = 0x7f, + + INT_1E_FIFO_WM_EN = 0x80 + } INT_1E_BITS_T; + + /** + * REG_INT_RST_LATCH bits + */ + typedef enum { + _INT_RST_LATCH_RESERVED_BITS = 0x20, + + INT_RST_LATCH0 = 0x01, + INT_RST_LATCH1 = 0x02, + INT_RST_LATCH2 = 0x04, + INT_RST_LATCH3 = 0x08, + _INT_RST_LATCH_MASK = 15, + _INT_RST_LATCH_SHIFT = 0, + + INT_RST_LATCH_STATUS_BIT = 0x10, + + INT_RST_LATCH_OFFSET_RESET = 0x40, + INT_RST_LATCH_RESET_INT = 0x80 + } INT_RST_LATCH_BITS_T; + + /** + * RST_LATCH values + */ + typedef enum { + RST_LATCH_NON_LATCHED = 0, + RST_LATCH_TEMPORARY_250MS = 1, + RST_LATCH_TEMPORARY_500MS = 2, + RST_LATCH_TEMPORARY_1S = 3, + RST_LATCH_TEMPORARY_2S = 4, + RST_LATCH_TEMPORARY_4S = 5, + RST_LATCH_TEMPORARY_8S = 6, + RST_LATCH_LATCHED = 7, + + // 8 == non latched + + RST_LATCH_TEMPORARY_250US = 9, + RST_LATCH_TEMPORARY_500US = 10, + RST_LATCH_TEMPORARY_1MS = 11, + RST_LATCH_TEMPORARY_12_5MS = 12, + RST_LATCH_TEMPORARY_25MS = 13, + RST_LATCH_TEMPORARY_50MS = 14 + + // 15 == latched + } RST_LATCH_T; + + /** + * REG_HIGH_TH_* (X, Y, and Z) register bits + */ + typedef enum { + HIGH_TH_EN = 0x01, + + HIGH_TH_TH0 = 0x02, + HIGH_TH_TH1 = 0x04, + HIGH_TH_TH2 = 0x08, + HIGH_TH_TH3 = 0x10, + HIGH_TH_TH4 = 0x20, + _HIGH_TH_TH_MASK = 31, + _HIGH_TH_TH_SHIFT = 1, + + HIGH_TH_HY0 = 0x40, + HIGH_TH_HY1 = 0x80, + _HIGH_TH_HY_MASK = 3, + _HIGH_TH_HY_SHIFT = 6 + } HIGH_TH_BITS_T; + + /** + * REG_SOC bits + */ + typedef enum { + SOC_SLOW_OFFSET_EN_X = 0x01, + SOC_SLOW_OFFSET_EN_Y = 0x02, + SOC_SLOW_OFFSET_EN_Z = 0x04, + + SOC_SLOW_OFFSET_DUR0 = 0x08, + SOC_SLOW_OFFSET_DUR1 = 0x10, + SOC_SLOW_OFFSET_DUR2 = 0x20, + _SOC_SLOW_OFFSET_DUR_MASK = 7, + _SOC_SLOW_OFFSET_DUR_SHIFT = 3, + + SOC_SLOW_OFFSET_TH0 = 0x40, + SOC_SLOW_OFFSET_TH1 = 0x80, + _SOC_SLOW_OFFSET_TH_MASK = 3, + _SOC_SLOW_OFFSET_TH_SHIFT = 6 + } SOC_BITS_T; + + /** + * SOC_SLOW_OFFSET_DUR values + */ + typedef enum { + SLOW_OFFSET_DUR_40MS = 0, // 40ms + SLOW_OFFSET_DUR_80MS = 1, + SLOW_OFFSET_DUR_160MS = 2, + SLOW_OFFSET_DUR_320MS = 3, + SLOW_OFFSET_DUR_640MS = 4, + SLOW_OFFSET_DUR_1280MS = 5 + } SLOW_OFFSET_DUR_T; + + /** + * SOC_SLOW_OFFSET_TH values + */ + typedef enum { + SLOW_OFFSET_TH_0_1 = 0, // 0.1 degree/s + SLOW_OFFSET_TH_0_2 = 1, + SLOW_OFFSET_TH_0_5 = 2, + SLOW_OFFSET_TH_1 = 3 + } SLOW_OFFSET_TH_T; + + /** + * REG_A_FOC bits + */ + typedef enum { + A_FOC_FAST_OFFSET_EN_X = 0x01, + A_FOC_FAST_OFFSET_EN_Y = 0x02, + A_FOC_FAST_OFFSET_EN_Z = 0x04, + + A_FOC_FAST_OFFSET_EN = 0x08, + + A_FOC_FAST_OFFSET_WORDLENGTH0 = 0x10, + A_FOC_FAST_OFFSET_WORDLENGTH1 = 0x20, + _A_FOC_FAST_OFFSET_WORDLENGTH_MASK = 3, + _A_FOC_FAST_OFFSET_WORDLENGTH_SHIFT = 4, + + A_FOC_AUTO_OFFSET_WORDLENGTH0 = 0x40, + A_FOC_AUTO_OFFSET_WORDLENGTH1 = 0x80, + _A_FOC_AUTO_OFFSET_WORDLENGTH_MASK = 3, + _A_FOC_AUTO_OFFSET_WORDLENGTH_SHIFT = 6 + } A_FOC_BITS_T; + + /** + * FAST_OFFSET_WORDLENGTH values + */ + typedef enum { + FAST_OFFSET_WORDLENGTH_32 = 0, // samples + FAST_OFFSET_WORDLENGTH_64 = 1, + FAST_OFFSET_WORDLENGTH_128 = 2, + FAST_OFFSET_WORDLENGTH_256 = 3 + } FAST_OFFSET_WORDLENGTH_T; + + /** + * AUTO_OFFSET_WORDLENGTH values + */ + typedef enum { + AUTO_OFFSET_WORDLENGTH_32 = 0, // samples + AUTO_OFFSET_WORDLENGTH_64 = 1, + AUTO_OFFSET_WORDLENGTH_128 = 2, + AUTO_OFFSET_WORDLENGTH_256 = 3 + } AUTO_OFFSET_WORDLENGTH_T; + + /** + * REG_TRIM_NVM_CTRL bits + */ + typedef enum { + TRIM_NVM_CTRL_NVM_PROG_MODE = 0x01, + TRIM_NVM_CTRL_NVM_PROG_TRIG = 0x02, + TRIM_NVM_CTRL_NVM_PROG_RDY = 0x04, + TRIM_NVM_CTRL_NVM_PROG_LOAD = 0x08, + + TRIM_NVM_CTRL_NVM_REMAIN0 = 0x10, + TRIM_NVM_CTRL_NVM_REMAIN1 = 0x20, + TRIM_NVM_CTRL_NVM_REMAIN2 = 0x40, + TRIM_NVM_CTRL_NVM_REMAIN3 = 0x80, + _TRIM_NVM_CTRL_NVM_REMAIN_MASK = 15, + _TRIM_NVM_CTRL_NVM_REMAIN_SHIFT = 4 + } TRIM_NVM_CTRL_BITS_T; + + /** + * REG_SPI3_WDT bits + */ + typedef enum { + _SPI3_WDT_RESERVED_BITS = 0xf0 | 0x08, + + SPI3_WDT_SPI3 = 0x01, // 3-wire SPI - NOT SUPPORTED + + SPI3_WDT_I2C_WDT_SEL = 0x02, + SPI3_WDT_I2C_WDT_EN = 0x04 + + // 0x08-0x80 reserved + } SPI3_WDT_BITS_T; + + /** + * REG_OFC1 bits, the missing x, y, and z llsb bits are in GP0 + */ + typedef enum { + OFC1_OFFSET_Z0 = 0x01, // Z lsb (3:1) + OFC1_OFFSET_Z1 = 0x02, + OFC1_OFFSET_Z2 = 0x04, + _OFC1_OFFSET_Z_MASK = 7, + _OFC1_OFFSET_Z_SHIFT = 0, + + OFC1_OFFSET_Y0 = 0x08, // Y lsb (3:1) + OFC1_OFFSET_Y1 = 0x10, + OFC1_OFFSET_Y2 = 0x20, + _OFC1_OFFSET_Y_MASK = 7, + _OFC1_OFFSET_Y_SHIFT = 3, + + OFC1_OFFSET_X0 = 0x08, // bits 3:2 of X lsb. geez + OFC1_OFFSET_X1 = 0x10, + _OFC1_OFFSET_X_MASK = 3, + _OFC1_OFFSET_X_SHIFT = 6 + } OFC1_OFFSET_BITS_T; + + /** + * REG_GP0 bits + */ + typedef enum { + GP0_OFFSET_Z = 0x01, // Z llsb (bit 0) + GP0_OFFSET_Y = 0x02, // Y llsb (bit 0) + + GP0_OFFSET_X0 = 0x04, // X llsbs (bits 1:0) + GP0_OFFSET_X1 = 0x08, + _GP0_OFFSET_X_MASK = 3, + _GP0_OFFSET_X_SHIFT = 2, + + GP0_GP00 = 0x10, + GP0_GP01 = 0x20, + GP0_GP02 = 0x40, + GP0_GP03 = 0x80, + _GP0_GP0_MASK = 15, + _GP0_GP0_SHIFT = 4 + } GP0_BITS_T; + + /** + * REG_BIST bits + */ + typedef enum { + _BIST_RESERVED_BITS = 0x80 | 0x40 | 0x20 | 0x08, + + BIST_TRIG_BIST = 0x01, + BIST_BIST_RDY = 0x02, + BIST_BIST_FAIL = 0x04, + + BIST_RATE_OK = 0x10 + } BIST_BITS_T; + + /** + * REG_FIFO_CONFIG_0 bits + */ + typedef enum { + FIFO_CONFIG_0_WATER_MARK0 = 0x01, + FIFO_CONFIG_0_WATER_MARK1 = 0x02, + FIFO_CONFIG_0_WATER_MARK2 = 0x04, + FIFO_CONFIG_0_WATER_MARK3 = 0x08, + FIFO_CONFIG_0_WATER_MARK4 = 0x10, + FIFO_CONFIG_0_WATER_MARK5 = 0x20, + FIFO_CONFIG_0_WATER_MARK6 = 0x40, + _FIFO_CONFIG_0_WATER_MARK_MASK = 127, + _FIFO_CONFIG_0_WATER_MARK_SHIFT = 0, + + FIFO_CONFIG_0_TAG = 0x80 + } FIFO_CONFIG_0_BITS_T; + + /** + * REG_FIFO_CONFIG_1 bits + */ + typedef enum { + _FIFO_CONFIG_1_RESERVED_BITS = 0x20 | 0x10 |0x08 | 0x04, + + FIFO_CONFIG_1_FIFO_DATA_SEL0 = 0x01, + FIFO_CONFIG_1_FIFO_DATA_SEL1 = 0x02, + _FIFO_CONFIG_1_FIFO_DATA_SEL = 3, + _FIFO_CONFIG_1_FIFO_DATA_SHIFT = 0, + + FIFO_CONFIG_1_FIFO_MODE0 = 0x40, + FIFO_CONFIG_1_FIFO_MODE1 = 0x80, + _FIFO_CONFIG_1_FIFO_MODE_MASK = 3, + _FIFO_CONFIG_1_FIFO_MODE_SHIFT = 6 + } FIFO_CONFIG_1_BITS_T; + + /** + * FIFO_DATA_SEL values + */ + typedef enum { + FIFO_DATA_SEL_XYZ = 0, + FIFO_DATA_SEL_X = 1, + FIFO_DATA_SEL_Y = 2, + FIFO_DATA_SEL_Z = 3 + } FIFO_DATA_SEL_T; + + /** + * FIFO_MODE values + */ + typedef enum { + FIFO_MODE_BYPASS = 0, + FIFO_MODE_FIFO = 1, + FIFO_MODE_STREAM = 2 + } FIFO_MODE_T; + + // interrupt selection for installISR() and uninstallISR() + typedef enum { + INTERRUPT_INT1, + INTERRUPT_INT2 + } INTERRUPT_PINS_T; + + + /** + * BMG160 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. + * @param theChipID The chip ID to use for validation + */ + BMG160(int bus=BMG160_I2C_BUS, uint8_t addr=BMG160_DEFAULT_ADDR, + int cs=-1); + + /** + * BMG160 Destructor. + */ + ~BMG160(); + + /** + * Update the internal stored values from sensor data. + */ + void update(); + + /** + * Return the chip ID. + * + * @return The chip ID (BMG160_CHIPID). + */ + uint8_t getChipID(); + + /** + * Return gyroscope data in degrees per second. 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 array. The pointer returned by this function is + * statically allocated and will be rewritten on each call. + * update() must have been called prior to calling this method. + * + * @return A floating point array containing x, y, and z in + * that order. + */ + float *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. Celcius is the default. + * @return The temperature in degrees Celcius 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 POWER_MODE_T values. The default is + * POWER_MODE_NORMAL. + * @param range One of the RANGE_T values. The default is + * RANGE_250. + * @param bw One of the filtering BW_T values. The default is + * BW_400_47. + */ + void init(POWER_MODE_T pwr=POWER_MODE_NORMAL, + RANGE_T range=RANGE_250, BW_T bw=BW_400_47); + + /** + * 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. + */ + void reset(); + + /** + * Set the gyroscope detection scaling range. This device + * supports 125, 250, 500, 100, and 2000 degree/s ranges. + * + * @param range One of the RANGE_T values. + */ + void setRange(RANGE_T range); + + /** + * Set the output filtering bandwidth of the device. + * + * @param bw One of the BW_T values. + */ + void setBandwidth(BW_T bw); + + /** + * Set the power mode of the device. Care must be taken when + * setting a low power or suspend mode. See the datasheet for + * details. I ncertain power modes, register write must be + * drastically slowed down. which we cannot support. + * + * @param power One of the POWER_MODE_T values. + */ + void setPowerMode(POWER_MODE_T power); + + /** + * Enable update() to read from the FIFO rather than the gyroscope + * axis registers directly. init() 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 gyroscope + * output registers, it's possible for one axis to be updated + * while another is being read, causing a temporal + * inconsistancy.. + * + * Using the FIFO removes this problem. + * + * @param useFIFO true to enable update() to read from the FIFO. + * When false, update will read from the gyroscope output + * registers directly. + */ + void enableFIFO(bool useFIFO); + + /** + * Set the FIFO watermark. When the watermark is reached an + * interrupt (if enabled) will be generated. + * + * @param wm The FIFO watermark to use. The maximum value is 63. + */ + 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. + * + * @param mode One of the FIFO_MODE_T values. + * @param axes One of the FIFO_DATA_SEL_T values. + */ + void fifoConfig(FIFO_MODE_T mode, FIFO_DATA_SEL_T axes); + + /** + * Return the Interrupt Enables 0 register. These resgisters + * allow you to enable various interrupt conditions. See the + * datasheet for details. + * + * @return A bitmask of 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 INT_EN_0_BITS_T bits. + */ + void setInterruptEnable0(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 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 INT_MAP_0_BITS_T bits. + */ + void setInterruptMap0(uint8_t bits); + + /** + * Return the Interrupt Map 1 register. See the datasheet for + * details. + * + * @return A bitmask of INT_MAP_1_BITS_T bits. + */ + uint8_t getInterruptMap1(); + + /** + * Set the Interrupt Map 1 register. See the datasheet for + * details. + * + * @param A bitmask of INT_MAP_1_BITS_T bits. + */ + void setInterruptMap1(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 INT_1A_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 INT_1A_BITS_T bits. + */ + 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 INT_EN_1_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 INT_EN_1_BITS_T bits. + */ + void setInterruptOutputControl(uint8_t bits); + + /** + * Clear all latched interrupts. See the datasheet for details. + */ + void clearInterruptLatches(); + + /** + * Return the current interrupt latching behavior. See the + * datasheet for details. + * + * @return One of the RST_LATCH_T values. + */ + RST_LATCH_T getInterruptLatchBehavior(); + + /** + * Set the current interrupt latching behavior. See the datasheet + * for details. + * + * @param latch One of the RST_LATCH_T values. + */ + void setInterruptLatchBehavior(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 INT_STATUS_0_BITS_T bits. + */ + uint8_t getInterruptStatus0(); + + /** + * Return the interrupt status 1 register. See the datasheet for + * details. + * + * @return a bitmask of INT_STATUS_1_BITS_T bits. + */ + uint8_t getInterruptStatus1(); + + /** + * Return the interrupt status 2 register. See the datasheet for + * details. + * + * @return a bitmask of INT_STATUS_2_BITS_T bits. + */ + uint8_t getInterruptStatus2(); + + /** + * Return the interrupt status 3 register. See the datasheet for + * details. + * + * @return a bitmask of INT_STATUS_3_BITS_T bits. + */ + uint8_t getInterruptStatus3(); + + /** + * Enable shadowing of the gyroscope 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. + */ + void enableRegisterShadowing(bool shadow); + + /** + * Enable filtering of the gyroscope axis data. init() + * enables this by default. If disabled, then gyroscope 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. + */ + void enableOutputFiltering(bool filter); + +#if defined(SWIGJAVA) || defined(JAVACALLBACK) + void installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level, + jobject runnable); +#else + /** + * install an interrupt handler. + * + * @param intr one of the 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 + */ + void installISR(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 INTERRUPT_PINS_T values specifying which + * interrupt pin you are removing. + */ + void uninstallISR(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. + */ + 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. + */ + void writeReg(uint8_t reg, uint8_t val); + + protected: + mraa::I2c *m_i2c; + mraa::Spi *m_spi; + + // spi chip select + mraa::Gpio *m_gpioCS; + + mraa::Gpio *m_gpioIntr1; + mraa::Gpio *m_gpioIntr2; + + uint8_t m_addr; + + // SPI chip select + void csOn(); + void csOff(); + + // acc data + float m_gyrX; + float m_gyrY; + float m_gyrZ; + + float m_gyrScale; + + float m_temperature; + + private: + bool m_isSPI; + // use the FIFO by default? + bool m_useFIFO; + + // return a reference to a gpio pin pointer depending on intr + mraa::Gpio*& getPin(INTERRUPT_PINS_T intr); + + // Adding a private function definition for java bindings +#if defined(SWIGJAVA) || defined(JAVACALLBACK) + void installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level, + void (*isr)(void *), void *arg); +#endif + }; +} diff --git a/src/bmx055/bmi055.cxx b/src/bmx055/bmi055.cxx new file mode 100644 index 00000000..0b348f76 --- /dev/null +++ b/src/bmx055/bmi055.cxx @@ -0,0 +1,122 @@ +/* + * 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 + +#include "bmi055.hpp" + +using namespace upm; +using namespace std; + +BMI055::BMI055(int accelBus, uint8_t accelAddr, int accelCS, + int gyroBus, uint8_t gyroAddr, int gyroCS) : + m_accel(0), m_gyro(0) +{ + // if -1 is supplied as a bus for any of these, we will not + // instantiate them + + if (accelBus >= 0) + m_accel = new BMA250E(accelBus, accelAddr, accelCS); + + if (gyroBus >= 0) + m_gyro = new BMG160(gyroBus, gyroAddr, gyroCS); + + // now initialize them... + if (m_accel) + m_accel->init(); + + if (m_gyro) + m_gyro->init(); +} + +BMI055::~BMI055() +{ + if (m_accel) + delete m_accel; + + if (m_gyro) + delete m_gyro; +} + +void BMI055::initAccelerometer(BMA250E::POWER_MODE_T pwr, + BMA250E::RANGE_T range, + BMA250E::BW_T bw) +{ + if (m_accel) + m_accel->init(pwr, range, bw); +} + +void BMI055::initGyroscope(BMG160::POWER_MODE_T pwr, + BMG160::RANGE_T range, + BMG160::BW_T bw) +{ + if (m_gyro) + m_gyro->init(pwr, range, bw); +} + +void BMI055::update() +{ + if (m_accel) + m_accel->update(); + + if (m_gyro) + m_gyro->update(); +} + +void BMI055::getAccelerometer(float *x, float *y, float *z) +{ + if (m_accel) + m_accel->getAccelerometer(x, y, z); +} + +float *BMI055::getAccelerometer() +{ + if (m_accel) + return m_accel->getAccelerometer(); + else + { + static float v[3] = {0.0f, 0.0f, 0.0f}; + return v; + } +} + +void BMI055::getGyroscope(float *x, float *y, float *z) +{ + if (m_gyro) + m_gyro->getGyroscope(x, y, z); +} + +float *BMI055::getGyroscope() +{ + if (m_gyro) + return m_gyro->getGyroscope(); + else + { + static float v[3] = {0.0f, 0.0f, 0.0f}; + return v; + } +} diff --git a/src/bmx055/bmi055.hpp b/src/bmx055/bmi055.hpp new file mode 100644 index 00000000..4212643c --- /dev/null +++ b/src/bmx055/bmi055.hpp @@ -0,0 +1,193 @@ +/* + * 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. + */ +#pragma once + +#include + +#include "bma250e.hpp" +#include "bmg160.hpp" + +namespace upm { + + /** + * @library bmx055 + * @sensor bmi055 + * @comname BMI055 6-axis Sensor Module + * @type accelerometer compass + * @man mouser + * @con i2c gpio spi + * @web http://www.mouser.com/ProductDetail/Bosch-Sensortec/0330SB0134/?qs=sGAEpiMZZMsrChSOYEGTCVIRbo47L7ys6GxSnxRPEhU%3d + * + * @brief API for the BMI055 6-axis Sensor Module + * + * The BMI055 is an inertial measurement unit (IMU) for the + * detection of movements and rotations in 6 degrees of freedom + * (6DoF). It reflects the full functionality of a triaxial, low-g + * acceleration sensor and at the same time it is capable to measure + * angular rates. Both – acceleration and angular rate – in three + * perpendicular room dimensions, the x-, y- and z-axis. + * + * The BMI055 is essentially 2 separate devices in one: the BMA250E + * Accelerometer and the BMG160 Gyroscope. They are completely + * independant of each other. + * + * This driver provides a very simple interface to these two devices. + * If finer control is desired, you should just use the separate + * BMA25E and BMG160 device classes directly. This driver + * simply initializes both devices, and provides a mechanism to + * read accelerometer and gyroscope data from them. + * + * @snippet bmi055.cxx Interesting + */ + + class BMI055 { + public: + /** + * BMI055 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 accelBus I2C or SPI bus to use. -1 to skip initializing + * this device. + * @param accelAddr The address for this device. -1 for SPI. + * @param accelCS The gpio pin to use for the SPI Chip Select. -1 for + * I2C or for SPI with a hardware controlled pin. + * @param gyroBus I2C or SPI bus to use. -1 to skip initializing + * this device. + * @param gyroAddr The address for this device. -1 for SPI. + * @param gyroCS The gpio pin to use for the SPI Chip Select. -1 for + * I2C or for SPI with a hardware controlled pin. + */ + BMI055(int accelBus=BMA250E_I2C_BUS, + uint8_t accelAddr=BMA250E_DEFAULT_ADDR, + int accelCS=-1, + int gyroBus=BMG160_I2C_BUS, + uint8_t gyroAddr=BMG160_DEFAULT_ADDR, + int gyroCS=-1); + + /** + * BMI055 Destructor. + */ + ~BMI055(); + + /** + * Update the internal stored values from sensor data. + */ + void update(); + + /** + * Initialize the accelerometer 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 or you + * want to change these values. + * + * @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. + */ + void initAccelerometer(BMA250E::POWER_MODE_T pwr=BMA250E::POWER_MODE_NORMAL, + BMA250E::RANGE_T range=BMA250E::RANGE_2G, + BMA250E::BW_T bw=BMA250E::BW_250); + + /** + * Initialize the gyroscope 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 or you want to + * change these values. + * + * @param pwr One of the BMG160::POWER_MODE_T values. The default is + * BMG160::POWER_MODE_NORMAL. + * @param range One of the BMG160::RANGE_T values. The default is + * BMG160::RANGE_250. + * @param bw One of the filtering BMG160::BW_T values. The default is + * BMG160::BW_400_47. + */ + void initGyroscope(BMG160::POWER_MODE_T pwr=BMG160::POWER_MODE_NORMAL, + BMG160::RANGE_T range=BMG160::RANGE_250, + BMG160::BW_T bw=BMG160::BW_400_47); + + /** + * 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 array. The pointer returned by this function is + * statically allocated and will be rewritten on each call. + * update() must have been called prior to calling this method. + * + * @return A floating point array containing x, y, and z in + * that order. + */ + float *getAccelerometer(); + + /** + * Return gyroscope data in degrees per second. 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 array. The pointer returned by this function is + * statically allocated and will be rewritten on each call. + * update() must have been called prior to calling this method. + * + * @return A floating point array containing x, y, and z in + * that order. + */ + float *getGyroscope(); + + + protected: + BMA250E *m_accel; + BMG160 *m_gyro; + + private: + }; +} diff --git a/src/bmx055/bmm150.cxx b/src/bmx055/bmm150.cxx new file mode 100644 index 00000000..2e98ab2f --- /dev/null +++ b/src/bmx055/bmm150.cxx @@ -0,0 +1,675 @@ +/* + * 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. + */ + +// The trimming algorithms are taken from the Bosch BMM050 driver code + +/**************************************************************************** +* Copyright (C) 2015 - 2016 Bosch Sensortec GmbH +* +* File : bmm050.h +* +* Date : 2016/03/17 +* +* Revision : 2.0.5 $ +* +* Usage: Sensor Driver for BMM050 and BMM150 sensor +* +**************************************************************************** +* +* section License +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* +* Neither the name of the copyright holder nor the names of the +* contributors may be used to endorse or promote products derived from +* this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER +* OR CONTRIBUTORS BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +* OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, +* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +* ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE +* +* The information provided is believed to be accurate and reliable. +* The copyright holder assumes no responsibility +* for the consequences of use +* of such information nor for any infringement of patents or +* other rights of third parties which may result from its use. +* No license is granted by implication or otherwise under any patent or +* patent rights of the copyright holder. +**************************************************************************/ + + +#include +#include +#include +#include +#include + +#include "bmm150.hpp" + +#define BMM150_DEFAULT_CHIPID 0x32 + +using namespace upm; +using namespace std; + +BMM150::BMM150(int bus, uint8_t addr, int cs) : + m_i2c(0), m_spi(0), m_gpioIntr(0), m_gpioDR(0), m_gpioCS(0) +{ + m_addr = addr; + m_isSPI = false; + + m_magX = 0; + m_magY = 0; + m_magZ = 0; + + m_hall = 0; + + m_dig_x1 = 0; + m_dig_y1 = 0; + + m_dig_z4 = 0; + m_dig_x2 = 0; + m_dig_y2 = 0; + + m_dig_z2 = 0; + m_dig_z1 = 0; + m_dig_xyz1 = 0; + m_dig_z3 = 0; + m_dig_xy2 = 0; + m_dig_xy1 = 0; + + if (addr < 0) + m_isSPI = true; + + if (m_isSPI) + { + m_spi = new mraa::Spi(bus); + + // Only create cs context if we are actually using a valid pin. + // A hardware controlled pin should specify cs as -1. + if (cs >= 0) + { + m_gpioCS = new mraa::Gpio(cs); + m_gpioCS->dir(mraa::DIR_OUT); + } + + m_spi->mode(mraa::SPI_MODE0); + m_spi->frequency(5000000); + } + else + { + // I2C + m_i2c = new mraa::I2c(bus); + + mraa::Result rv; + if ((rv = m_i2c->address(m_addr)) != mraa::SUCCESS) + { + throw std::runtime_error(string(__FUNCTION__) + + ": I2c.address() failed"); + } + } + + // power bit must be on for chip ID to be accessable + setPowerBit(true); + m_opmode = OPERATION_MODE_SLEEP; + + usleep(50000); + + // check the chip id + uint8_t chipID = getChipID(); + if (chipID != BMM150_DEFAULT_CHIPID) + { + throw std::runtime_error(string(__FUNCTION__) + + ": invalid chip ID. Expected " + + std::to_string(int(BMM150_DEFAULT_CHIPID)) + + ", got " + + std::to_string(int(chipID))); + } + + // get trim data + readTrimData(); + + // call init with default options + init(); +} + +BMM150::~BMM150() +{ + uninstallISR(INTERRUPT_INT); + uninstallISR(INTERRUPT_DR); +} + +void BMM150::init(USAGE_PRESETS_T usage) +{ + setPowerBit(true); + setOpmode(OPERATION_MODE_NORMAL); + + usleep(50000); // 50ms, in case we are waking up + + setPresetMode(usage); + + // settle + usleep(50000); +} + +void BMM150::update() +{ + // special care when in a forced mode - need to trigger a + // measurement, and wait for the opmode to return to OPMODE_SLEEP, + // then we can read the values. + + if (m_opmode == OPERATION_MODE_FORCED) + { + // trigger measurement + setOpmode(OPERATION_MODE_FORCED); + + // opmode will return to sleep after measurement is complete + do { + usleep(5000); + } while (getOpmode() == OPERATION_MODE_FORCED); + } + + const int bufLen = 8; + uint8_t buf[bufLen]; + + if (readRegs(REG_MAG_X_LSB, buf, bufLen) != bufLen) + { + throw std::runtime_error(string(__FUNCTION__) + + ": readRegs() failed to read " + + std::to_string(bufLen) + + " bytes"); + } + + // we need to get the hall data first, since it's needed for the + // bosch compensation functions for each of the xyz axes + + m_hall = uint16_t(buf[7] << 8 | (buf[6] & + (_MAG_RHALL_LSB_LSB_MASK << + _MAG_RHALL_LSB_LSB_SHIFT))); + m_hall /= 4; + + int16_t val; + + // x + val = int16_t(buf[1] << 8 | (buf[0] & (_MAG_XY_LSB_LSB_MASK << + _MAG_XY_LSB_LSB_SHIFT))); + val /= 8; + m_magX = bmm050_compensate_X_float(val, m_hall); + + // y + val = int16_t(buf[3] << 8 | (buf[2] & (_MAG_XY_LSB_LSB_MASK << + _MAG_XY_LSB_LSB_SHIFT))); + val /= 8; + m_magY = bmm050_compensate_Y_float(val, m_hall); + + // z + val = int16_t(buf[5] << 8 | (buf[4] & (_MAG_Z_LSB_LSB_MASK << + _MAG_Z_LSB_LSB_SHIFT))); + val /= 2; + m_magZ = bmm050_compensate_Z_float(val, m_hall); +} + +uint8_t BMM150::readReg(uint8_t reg) +{ + if (m_isSPI) + { + reg |= 0x80; // needed for read + uint8_t pkt[2] = {reg, 0}; + + csOn(); + if (m_spi->transfer(pkt, pkt, 2)) + { + csOff(); + throw std::runtime_error(string(__FUNCTION__) + + ": Spi.transfer() failed"); + } + csOff(); + + return pkt[1]; + } + else + return m_i2c->readReg(reg); +} + +int BMM150::readRegs(uint8_t reg, uint8_t *buffer, int len) +{ + if (m_isSPI) + { + reg |= 0x80; // needed for read + + uint8_t sbuf[len + 1]; + memset((char *)sbuf, 0, len + 1); + sbuf[0] = reg; + + // We need to do it this way for edison - ie: use a single + // transfer rather than breaking it up into two like we used to. + // This means a buffer copy is now required, but that's the way + // it goes. + + csOn(); + if (m_spi->transfer(sbuf, sbuf, len + 1)) + { + csOff(); + throw std::runtime_error(string(__FUNCTION__) + + ": Spi.transfer(buf) failed"); + } + csOff(); + + // now copy it into user buffer + for (int i=0; ireadBytesReg(reg, buffer, len); +} + +void BMM150::writeReg(uint8_t reg, uint8_t val) +{ + if (m_isSPI) + { + reg &= 0x7f; // mask off 0x80 for writing + uint8_t pkt[2] = {reg, val}; + + csOn(); + if (m_spi->transfer(pkt, NULL, 2)) + { + csOff(); + throw std::runtime_error(string(__FUNCTION__) + + ": Spi.transfer() failed"); + } + csOff(); + } + else + { + + mraa::Result rv; + if ((rv = m_i2c->writeReg(reg, val)) != mraa::SUCCESS) + { + throw std::runtime_error(std::string(__FUNCTION__) + + ": I2c.writeReg() failed"); + } + } +} + +void BMM150::csOn() +{ + if (m_gpioCS) + m_gpioCS->write(0); +} + +void BMM150::csOff() +{ + if (m_gpioCS) + m_gpioCS->write(1); +} + +uint8_t BMM150::getChipID() +{ + return readReg(REG_CHIP_ID); +} + +void BMM150::getMagnetometer(float *x, float *y, float *z) +{ + if (x) + *x = m_magX; + + if (y) + *y = m_magY; + + if (z) + *z = m_magZ; +} + +float *BMM150::getMagnetometer() +{ + static float v[3]; + + getMagnetometer(&v[0], &v[1], &v[2]); + return v; +} + +void BMM150::reset() +{ + // mask off reserved bits + uint8_t reg = readReg(REG_POWER_CTRL) & ~_POWER_CTRL_RESERVED_BITS; + + reg |= POWER_CTRL_SOFT_RESET0 | POWER_CTRL_SOFT_RESET1; + + writeReg(REG_POWER_CTRL, reg); + sleep(1); + // device will return to SLEEP mode... +} + +void BMM150::setOutputDataRate(DATA_RATE_T odr) +{ + uint8_t reg = readReg(REG_OPMODE); + + reg &= ~(_OPMODE_DATA_RATE_MASK << _OPMODE_DATA_RATE_SHIFT); + reg |= (odr << _OPMODE_DATA_RATE_SHIFT); + + writeReg(REG_OPMODE, reg); +} + +void BMM150::setPowerBit(bool power) +{ + // mask off reserved bits + uint8_t reg = readReg(REG_POWER_CTRL) & ~_POWER_CTRL_RESERVED_BITS; + + if (power) + reg |= POWER_CTRL_POWER_CTRL_BIT; + else + reg &= ~POWER_CTRL_POWER_CTRL_BIT; + + writeReg(REG_POWER_CTRL, reg); +} + +void BMM150::setOpmode(OPERATION_MODE_T opmode) +{ + uint8_t reg = readReg(REG_OPMODE); + + reg &= ~(_OPMODE_OPERATION_MODE_MASK << _OPMODE_OPERATION_MODE_SHIFT); + reg |= (opmode << _OPMODE_OPERATION_MODE_SHIFT); + + writeReg(REG_OPMODE, reg); + m_opmode = opmode; +} + +BMM150::OPERATION_MODE_T BMM150::getOpmode() +{ + uint8_t reg = readReg(REG_OPMODE); + + reg &= (_OPMODE_OPERATION_MODE_MASK << _OPMODE_OPERATION_MODE_SHIFT); + reg >>= _OPMODE_OPERATION_MODE_SHIFT; + + return static_cast(reg); +} + +uint8_t BMM150::getInterruptEnable() +{ + return readReg(REG_INT_EN); +} + +void BMM150::setInterruptEnable(uint8_t bits) +{ + writeReg(REG_INT_EN, bits); +} + +uint8_t BMM150::getInterruptConfig() +{ + return readReg(REG_INT_CONFIG); +} + +void BMM150::setInterruptConfig(uint8_t bits) +{ + writeReg(REG_INT_CONFIG, bits); +} + +uint8_t BMM150::getInterruptStatus() +{ + return readReg(REG_INT_STATUS); +} + +void BMM150::readTrimData() +{ + int bufLen = 10; + uint8_t calibData[bufLen]; + + // 2 bytes first + readRegs(REG_TRIM_DIG_X1, calibData, 2); + + m_dig_x1 = int8_t(calibData[0]); + m_dig_y1 = int8_t(calibData[1]); + + // next block of 4 bytes + readRegs(REG_TRIM_DIG_Z4_LSB, calibData, 4); + + m_dig_z4 = int16_t((calibData[1] << 8) | calibData[0]); + m_dig_x2 = int8_t(calibData[2]); + m_dig_y2 = int8_t(calibData[3]); + + // final block of 10 bytes + readRegs(REG_TRIM_DIG_Z2_LSB, calibData, 10); + + m_dig_z2 = int16_t((calibData[1] << 8) | calibData[0]); + m_dig_z1 = uint16_t((calibData[3] << 8) | calibData[2]); + m_dig_xyz1 = uint16_t((calibData[5] << 8) | calibData[4]); + m_dig_z3 = int16_t((calibData[7] << 8) | calibData[6]); + m_dig_xy2 = int8_t(calibData[8]); + m_dig_xy1 = calibData[9]; +} + +void BMM150::setRepetitionsXY(uint8_t reps) +{ + writeReg(REG_REP_XY, reps); +} + +void BMM150::setRepetitionsZ(uint8_t reps) +{ + writeReg(REG_REP_Z, reps); +} + +void BMM150::setPresetMode(USAGE_PRESETS_T usage) +{ + // these recommended presets come from the datasheet, Table 3, + // Section 4.2 + switch (usage) + { + case USAGE_LOW_POWER: + setRepetitionsXY(3); + setRepetitionsZ(3); + setOutputDataRate(DATA_RATE_10HZ); + + break; + + case USAGE_REGULAR: + setRepetitionsXY(9); + setRepetitionsZ(15); + setOutputDataRate(DATA_RATE_10HZ); + + break; + + case USAGE_ENHANCED_REGULAR: + setRepetitionsXY(15); + setRepetitionsZ(27); + setOutputDataRate(DATA_RATE_10HZ); + + break; + + case USAGE_HIGH_ACCURACY: + setRepetitionsXY(47); + setRepetitionsZ(83); + setOutputDataRate(DATA_RATE_20HZ); + + break; + + default: + throw std::out_of_range(string(__FUNCTION__) + + ": Invalid usage enum passed"); + } +} + +#if defined(SWIGJAVA) || (JAVACALLBACK) +void BMM150::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level, + jobject runnable) +{ + // delete any existing ISR and GPIO context + uninstallISR(intr); + + // create gpio context + getPin(intr) = new mraa::Gpio(gpio); + + getPin(intr)->dir(mraa::DIR_IN); + getPin(intr)->isr(level, runnable); +} +#else +void BMM150::installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level, + void (*isr)(void *), void *arg) +{ + // delete any existing ISR and GPIO context + uninstallISR(intr); + + // create gpio context + getPin(intr) = new mraa::Gpio(gpio); + + getPin(intr)->dir(mraa::DIR_IN); + getPin(intr)->isr(level, isr, arg); +} +#endif + +void BMM150::uninstallISR(INTERRUPT_PINS_T intr) +{ + if (getPin(intr)) + { + getPin(intr)->isrExit(); + delete getPin(intr); + + getPin(intr) = 0; + } +} + +mraa::Gpio*& BMM150::getPin(INTERRUPT_PINS_T intr) +{ + switch(intr) + { + case INTERRUPT_INT: + return m_gpioIntr; + break; + + case INTERRUPT_DR: + return m_gpioDR; + break; + + default: + throw std::out_of_range(string(__FUNCTION__) + + ": Invalid interrupt enum passed"); + } +} + +// Bosch compensation functions + +float BMM150::bmm050_compensate_X_float(int16_t mag_data_x, uint16_t data_r) +{ + float inter_retval = 0; + + if (mag_data_x != -4096 /* no overflow */ + ) { + if ((data_r != 0) + && (m_dig_xyz1 != 0)) { + inter_retval = ((((float)m_dig_xyz1) + * 16384.0 / data_r) - 16384.0); + } else { + inter_retval = 0.0f; + return inter_retval; + } + inter_retval = (((mag_data_x * ((((((float)m_dig_xy2) * + (inter_retval*inter_retval / + 268435456.0) + + inter_retval * ((float)m_dig_xy1) + / 16384.0)) + 256.0) * + (((float)m_dig_x2) + 160.0))) + / 8192.0) + + (((float)m_dig_x1) * + 8.0)) / 16.0; + } else { + inter_retval = 0.0f; + } + return inter_retval; +} + +float BMM150::bmm050_compensate_Y_float(int16_t mag_data_y, uint16_t data_r) +{ + float inter_retval = 0; + + if (mag_data_y != -4096 /* no overflow */ + ) { + if ((data_r != 0) + && (m_dig_xyz1 != 0)) { + inter_retval = ((((float)m_dig_xyz1) + * 16384.0 + /data_r) - 16384.0); + } else { + inter_retval = 0.0f; + return inter_retval; + } + inter_retval = (((mag_data_y * ((((((float)m_dig_xy2) * + (inter_retval*inter_retval + / 268435456.0) + + inter_retval * ((float)m_dig_xy1) + / 16384.0)) + + 256.0) * + (((float)m_dig_y2) + 160.0))) + / 8192.0) + + (((float)m_dig_y1) * 8.0)) + / 16.0; + } else { + /* overflow, set output to 0.0f */ + inter_retval = 0.0f; + } + return inter_retval; +} + +float BMM150::bmm050_compensate_Z_float(int16_t mag_data_z, uint16_t data_r) +{ + float inter_retval = 0; + /* no overflow */ + if (mag_data_z != -16384) { + if ((m_dig_z2 != 0) + && (m_dig_z1 != 0) + && (m_dig_xyz1 != 0) + && (data_r != 0)) { + inter_retval = ((((((float)mag_data_z)- + ((float)m_dig_z4)) * 131072.0)- + (((float)m_dig_z3)*(((float)data_r) + -((float)m_dig_xyz1)))) + /((((float)m_dig_z2)+ + ((float)m_dig_z1)*((float)data_r) / + 32768.0) * 4.0)) / 16.0; + } + } else { + /* overflow, set output to 0.0f */ + inter_retval = 0.0f; + } + return inter_retval; +} diff --git a/src/bmx055/bmm150.hpp b/src/bmx055/bmm150.hpp new file mode 100644 index 00000000..ab20e8cf --- /dev/null +++ b/src/bmx055/bmm150.hpp @@ -0,0 +1,614 @@ +/* + * 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. + */ +#pragma once + +#include +#include +#include +#include + +#define BMM150_I2C_BUS 0 +#define BMM150_SPI_BUS 0 +#define BMM150_DEFAULT_ADDR 0x10 + + +namespace upm { + + /** + * @library bmx050 + * @sensor bmm150 + * @comname BMM150 3-Axis Geomagnetic Sensor + * @altname bmm050 + * @type compass + * @man bosch + * @con i2c spi gpio + * + * @brief API for the BMM150 3-Axis Geomagnetic Sensor + * + * The BMM150 is a standalone geomagnetic sensor for consumer market + * applications. It allows measurements of the magnetic field in + * three perpendicular axes. Based on Bosch’s proprietary FlipCore + * technology, performance and features of BMM150 are carefully + * tuned and perfectly match the demanding requirements of all + * 3-axis mobile applications such as electronic compass, navigation + * or augmented reality. + * + * An evaluation circuitry (ASIC) converts the output of the + * geomagnetic sensor to digital results which can be read out over + * the industry standard digital interfaces (SPI and I2C). + * + * 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 device requires 3.3v operation. + * + * @snippet bmm150.cxx Interesting + */ + + class BMM150 { + public: + + // 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. + + /** + * BMM150 registers + */ + typedef enum : uint8_t { + REG_CHIP_ID = 0x40, + + // 0x41 reserved + + REG_MAG_X_LSB = 0x42, + REG_MAG_X_MSB = 0x43, + REG_MAG_Y_LSB = 0x44, + REG_MAG_Y_MSB = 0x45, + REG_MAG_Z_LSB = 0x46, + REG_MAG_Z_MSB = 0x47, + + REG_RHALL_LSB = 0x48, + REG_RHALL_MSB = 0x49, + + REG_INT_STATUS = 0x4a, + + REG_POWER_CTRL = 0x4b, + + REG_OPMODE = 0x4c, + + REG_INT_EN = 0x4d, + REG_INT_CONFIG = 0x4e, + + REG_LOW_THRES = 0x4f, + REG_HIGH_THRES = 0x50, + + REG_REP_XY = 0x51, + REG_REP_Z = 0x52, + + // 0x53-0x71 reserved (mostly) + + // TRIM registers from Bosch BMM050 driver + REG_TRIM_DIG_X1 = 0x5d, + REG_TRIM_DIG_Y1 = 0x5e, + + REG_TRIM_DIG_Z4_LSB = 0x62, + REG_TRIM_DIG_Z4_MSB = 0x63, + REG_TRIM_DIG_X2 = 0x64, + REG_TRIM_DIG_Y2 = 0x65, + + REG_TRIM_DIG_Z2_LSB = 0x68, + REG_TRIM_DIG_Z2_MSB = 0x69, + REG_TRIM_DIG_Z1_LSB = 0x6a, + REG_TRIM_DIG_Z1_MSB = 0x6b, + REG_TRIM_DIG_XYZ1_LSB = 0x6c, + REG_TRIM_DIG_XYZ1_MSB = 0x6d, + REG_TRIM_DIG_Z3_LSB = 0x6e, + REG_TRIM_DIG_Z3_MSB = 0x6f, + REG_TRIM_DIG_XY2 = 0x70, + REG_TRIM_DIG_XY1 = 0x71 + + } BMM150_REGS_T; + + /** + * REG_MAG_XY_LSB bits (for X and Y mag data LSB's only) + */ + typedef enum { + _MAG_XY_LSB_RESERVED_BITS = 0x02 | 0x04, + + MAG_XY_LSB_SELFTEST_XY = 0x01, + + MAG_XY_LSB_LSB0 = 0x08, + MAG_XY_LSB_LSB1 = 0x10, + MAG_XY_LSB_LSB2 = 0x20, + MAG_XY_LSB_LSB3 = 0x40, + MAG_XY_LSB_LSB4 = 0x80, + _MAG_XY_LSB_LSB_MASK = 31, + _MAG_XY_LSB_LSB_SHIFT = 3 + } MAG_XY_LSB_BITS_T; + + /** + * REG_MAG_Z_LSB bits (for Z LSB only) + */ + typedef enum { + MAG_Z_LSB_SELFTEST_Z = 0x01, + + MAG_Z_LSB_LSB0 = 0x02, + MAG_Z_LSB_LSB1 = 0x04, + MAG_Z_LSB_LSB2 = 0x08, + MAG_Z_LSB_LSB3 = 0x10, + MAG_Z_LSB_LSB4 = 0x20, + MAG_Z_LSB_LSB5 = 0x40, + MAG_Z_LSB_LSB6 = 0x80, + _MAG_Z_LSB_LSB_MASK = 127, + _MAG_Z_LSB_LSB_SHIFT = 1 + } MAG_Z_LSB_BITS_T; + + /** + * REG_MAG_RHALL_LSB bits (for RHALL LSB only) + */ + typedef enum { + _MAG_RHALL_LSB_RESERVED_BITS = 0x02, + + MAG_RHALL_LSB_DATA_READY_STATUS = 0x01, + + MAG_RHALL_LSB_LSB0 = 0x04, + MAG_RHALL_LSB_LSB1 = 0x08, + MAG_RHALL_LSB_LSB2 = 0x10, + MAG_RHALL_LSB_LSB3 = 0x20, + MAG_RHALL_LSB_LSB4 = 0x40, + MAG_RHALL_LSB_LSB5 = 0x80, + _MAG_RHALL_LSB_LSB_MASK = 63, + _MAG_RHALL_LSB_LSB_SHIFT = 2 + } MAG_RHALL_LSB_BITS_T; + + /** + * REG_INT_STATUS bits + */ + typedef enum { + INT_STATUS_LOW_INT_X = 0x01, + INT_STATUS_LOW_INT_Y = 0x02, + INT_STATUS_LOW_INT_Z = 0x04, + INT_STATUS_HIGH_INT_X = 0x08, + INT_STATUS_HIGH_INT_Y = 0x10, + INT_STATUS_HIGH_INT_Z = 0x20, + INT_STATUS_OVERFLOW = 0x40, + INT_STATUS_DATA_OVERRUN = 0x80 + } INT_STATUS_BITS_T; + + /** + * REG_POWER_CTRL bits + */ + typedef enum { + _POWER_CTRL_RESERVED_BITS = 0x40 | 0x20 | 0x10 | 0x08, + + POWER_CTRL_POWER_CTRL_BIT = 0x01, + POWER_CTRL_SOFT_RESET0 = 0x02, + POWER_CTRL_SPI3EN = 0x04, // not supported + + POWER_CTRL_SOFT_RESET1 = 0x80 + } POWER_CTRL_BITS_T; + + /** + * REG_OPMODE bits + */ + typedef enum { + OPMODE_SELFTTEST = 0x01, + + OPMODE_OPERATION_MODE0 = 0x02, + OPMODE_OPERATION_MODE1 = 0x04, + _OPMODE_OPERATION_MODE_MASK = 3, + _OPMODE_OPERATION_MODE_SHIFT = 1, + + OPMODE_DATA_RATE0 = 0x08, + OPMODE_DATA_RATE1 = 0x10, + OPMODE_DATA_RATE2 = 0x20, + _OPMODE_DATA_RATE_MASK = 7, + _OPMODE_DATA_RATE_SHIFT = 3, + + OPMODE_ADV_SELFTEST0 = 0x40, + OPMODE_ADV_SELFTEST1 = 0x80, + _OPMODE_ADV_SELFTEST_MASK = 3, + _OPMODE_ADV_SELFTEST_SHIFT = 6 + } OPMODE_BITS_T; + + /** + * OPMODE_OPERATION_MODE values + */ + typedef enum { + OPERATION_MODE_NORMAL = 0, + OPERATION_MODE_FORCED = 1, + OPERATION_MODE_SLEEP = 3 + } OPERATION_MODE_T; + + /** + * OPMODE_DATA_RATE values + */ + typedef enum { + DATA_RATE_10HZ = 0, + DATA_RATE_2HZ = 1, + DATA_RATE_6HZ = 2, + DATA_RATE_8HZ = 3, + DATA_RATE_15HZ = 4, + DATA_RATE_20HZ = 5, + DATA_RATE_25HZ = 6, + DATA_RATE_30HZ = 7 + } DATA_RATE_T; + + /** + * REG_INT_EN bits + */ + typedef enum { + INT_EN_LOW_INT_X_EN = 0x01, + INT_EN_LOW_INT_Y_EN = 0x02, + INT_EN_LOW_INT_Z_EN = 0x04, + INT_EN_HIGH_INT_X_EN = 0x08, + INT_EN_HIGH_INT_Y_EN = 0x10, + INT_EN_HIGH_INT_Z_EN = 0x20, + INT_EN_OVERFLOW_INT_EN = 0x40, + INT_EN_DATA_OVERRUN_INT_EN = 0x80 + } INT_EN_T; + + /** + * REG_INT_CONFIG bits + */ + typedef enum { + INT_CONFIG_INT_POLARITY = 0x01, + INT_CONFIG_INT_LATCH = 0x02, + INT_CONFIG_DR_POLARITY = 0x04, + INT_CONFIG_CHANNEL_X = 0x08, + INT_CONFIG_CHANNEL_Y = 0x10, + INT_CONFIG_CHANNEL_Z = 0x20, + INT_CONFIG_INT_PIN_EN = 0x40, + INT_CONFIG_DR_PIN_EN = 0x80 + } INT_CONFIG_T; + + /** + * Interrupt selection for installISR() and uninstallISR() + */ + typedef enum { + INTERRUPT_INT, + INTERRUPT_DR + } INTERRUPT_PINS_T; + + /** + * Bosch recommended usage preset modes + */ + typedef enum { + USAGE_LOW_POWER, + USAGE_REGULAR, + USAGE_ENHANCED_REGULAR, + USAGE_HIGH_ACCURACY + } USAGE_PRESETS_T; + + /** + * BMM150 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. + * @param theChipID The chip ID to use for validation + */ + BMM150(int bus=BMM150_I2C_BUS, uint8_t addr=BMM150_DEFAULT_ADDR, + int cs=-1); + + /** + * BMM150 Destructor. + */ + ~BMM150(); + + /** + * Update the internal stored values from sensor data. + */ + void update(); + + /** + * Return the chip ID. + * + * @return The chip ID (BMM150_CHIPID). + */ + uint8_t getChipID(); + + /** + * Return magnetometer data in micro-Teslas (uT). 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 getMagnetometer(float *x, float *y, float *z); + + /** + * Return magnetometer data in micro-Teslas (uT) in the form of a + * floating point array. The pointer returned by this function is + * statically allocated and will be rewritten on each call. + * update() must have been called prior to calling this method. + * + * @return A floating point array containing x, y, and z in + * that order. + */ + float *getMagnetometer(); + + /** + * 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. This method will + * call setPresetMode() with the passed parameter. + * + * @param usage One of the USAGE_PRESETS_T values. The default is + * USAGE_HIGH_ACCURACY. + */ + void init(USAGE_PRESETS_T usage=USAGE_HIGH_ACCURACY); + + /** + * Set one of the Bosch recommended preset modes. These modes + * configure the sensor for varying use cases. + * + * @param usage One of the USAGE_PRESETS_T values. The default is + * USAGE_HIGH_ACCURACY. + */ + void setPresetMode(USAGE_PRESETS_T usage); + + /** + * Perform a device soft-reset. The device will be placed in + * SUSPEND mode afterward with all configured setting lost, so + * some re-initialization will be required to get data from the + * sensor. Calling init() will get everything running again. + */ + void reset(); + + /** + * Set the magnetometer Output Data Rate. See the datasheet for + * details. + * + * @param odr One of the DATA_RATE_T values. + */ + void setOutputDataRate(DATA_RATE_T odr); + + /** + * Set or clear the Power bit. When the power bit is cleared, the + * device enters a deep suspend mode where only the REG_POWER_CTRL + * register can be accessed. This bit needs to be enabled for the + * device to operate. See the datasheet for details. The + * constructor enables this by default. After a deep suspend mode + * has been entered, all configured data is lost and the device + * must be reconfigured (as via init()). + * + * @param power true to enable the bit, false otherwise. + */ + void setPowerBit(bool power); + + /** + * Set the operating mode of the device. See the datasheet for + * details. + * + * @param power One of the POWER_MODE_T values. + */ + void setOpmode(OPERATION_MODE_T opmode); + + /** + * Get the current operating mode of the device. See the datasheet for + * details. The power bit must be one for this method to succeed. + * + * @return One of the OPERATION_MODE_T values. + */ + OPERATION_MODE_T getOpmode(); + + /** + * Return the Interrupt Enables register. This resgister + * allows you to enable various interrupt conditions. See the + * datasheet for details. + * + * @return A bitmask of INT_EN_BITS_T bits. + */ + uint8_t getInterruptEnable(); + + /** + * Set the Interrupt Enables register. See the datasheet for + * details. + * + * @param bits A bitmask of INT_EN_BITS_T bits. + */ + void setInterruptEnable(uint8_t bits); + + /** + * Return the Interrupt Config register. This register allows + * determining the electrical characteristics of the 2 interrupt + * pins (open-drain/push-pull and level/edge triggering) as well + * as other options. See the datasheet for details. + * + * @return A bitmask of INT_CONFIG_BITS_T bits. + */ + uint8_t getInterruptConfig(); + + /** + * Set the Interrupt Config 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 INT_CONFIG_BITS_T bits. + */ + void setInterruptConfig(uint8_t bits); + + /** + * Return the interrupt status register. This register + * indicates which interrupts have been triggered. See the + * datasheet for details. + * + * @return a bitmask of INT_STATUS_BITS_T bits. + */ + uint8_t getInterruptStatus(); + + /** + * Set the repetion counter for the X and Y axes. This allows the + * device to average a number of measurements for a more stable + * output. See the datasheet for details. + * + * @param reps A coefficient for specifying the number of + * repititions to perform. (1 + 2(reps)) + */ + void setRepetitionsXY(uint8_t reps); + + /** + * Set the repetion counter for the Z axis. This allows the + * device to average a number of measurements for a more stable + * output. See the datasheet for details. + * + * @param reps A coefficient for specifying the number of + * repititions to perform. (1 + (reps)) + */ + void setRepetitionsZ(uint8_t reps); + +#if defined(SWIGJAVA) || defined(JAVACALLBACK) + void installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level, + jobject runnable); +#else + /** + * install an interrupt handler. + * + * @param intr one of the 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 + */ + void installISR(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 INTERRUPT_PINS_T values specifying which + * interrupt pin you are removing. + */ + void uninstallISR(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. + */ + 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. + */ + void writeReg(uint8_t reg, uint8_t val); + + protected: + mraa::I2c *m_i2c; + mraa::Spi *m_spi; + + // spi chip select + mraa::Gpio *m_gpioCS; + + mraa::Gpio *m_gpioIntr; + mraa::Gpio *m_gpioDR; + + uint8_t m_addr; + + OPERATION_MODE_T m_opmode; + + // SPI chip select + void csOn(); + void csOff(); + + // acc data + float m_magX; + float m_magY; + float m_magZ; + + // hall resistance + uint16_t m_hall; + + // trimming data + int8_t m_dig_x1; + int8_t m_dig_y1; + + int16_t m_dig_z4; + int8_t m_dig_x2; + int8_t m_dig_y2; + + int16_t m_dig_z2; + uint16_t m_dig_z1; + uint16_t m_dig_xyz1; + int16_t m_dig_z3; + int8_t m_dig_xy2; + uint8_t m_dig_xy1; + + // read trim data for compensation + void readTrimData(); + + private: + bool m_isSPI; + // use the FIFO by default? + bool m_useFIFO; + + // return a reference to a gpio pin pointer depending on intr + mraa::Gpio*& getPin(INTERRUPT_PINS_T intr); + + // Adding a private function definition for java bindings +#if defined(SWIGJAVA) || defined(JAVACALLBACK) + void installISR(INTERRUPT_PINS_T intr, int gpio, mraa::Edge level, + void (*isr)(void *), void *arg); +#endif + + // bosch compensation algorithms + float bmm050_compensate_X_float(int16_t mag_data_x, uint16_t data_r); + float bmm050_compensate_Y_float(int16_t mag_data_y, uint16_t data_r); + float bmm050_compensate_Z_float(int16_t mag_data_z, uint16_t data_r); + }; +} diff --git a/src/bmx055/bmx055.cxx b/src/bmx055/bmx055.cxx new file mode 100644 index 00000000..9d36a5b1 --- /dev/null +++ b/src/bmx055/bmx055.cxx @@ -0,0 +1,158 @@ +/* + * 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 + +#include "bmx055.hpp" + +using namespace upm; +using namespace std; + +BMX055::BMX055(int accelBus, uint8_t accelAddr, int accelCS, + int gyroBus, uint8_t gyroAddr, int gyroCS, + int magBus, uint8_t magAddr, int magCS) : + m_accel(0), m_gyro(0), m_mag(0) +{ + // if -1 is supplied as a bus for any of these, we will not + // instantiate them + + if (accelBus >= 0) + m_accel = new BMA250E(accelBus, accelAddr, accelCS); + + if (gyroBus >= 0) + m_gyro = new BMG160(gyroBus, gyroAddr, gyroCS); + + if (magBus >= 0) + m_mag = new BMM150(magBus, magAddr, magCS); + + // now initialize them... + if (m_accel) + m_accel->init(); + + if (m_gyro) + m_gyro->init(); + + if (m_mag) + m_mag->init(); +} + +BMX055::~BMX055() +{ + if (m_accel) + delete m_accel; + + if (m_gyro) + delete m_gyro; + + if (m_mag) + delete m_mag; +} + +void BMX055::initAccelerometer(BMA250E::POWER_MODE_T pwr, + BMA250E::RANGE_T range, + BMA250E::BW_T bw) +{ + if (m_accel) + m_accel->init(pwr, range, bw); +} + +void BMX055::initGyroscope(BMG160::POWER_MODE_T pwr, + BMG160::RANGE_T range, + BMG160::BW_T bw) +{ + if (m_gyro) + m_gyro->init(pwr, range, bw); +} + +void BMX055::initMagnetometer(BMM150::USAGE_PRESETS_T usage) +{ + if (m_mag) + m_mag->init(usage); +} + +void BMX055::update() +{ + if (m_accel) + m_accel->update(); + + if (m_gyro) + m_gyro->update(); + + if (m_mag) + m_mag->update(); +} + +void BMX055::getAccelerometer(float *x, float *y, float *z) +{ + if (m_accel) + m_accel->getAccelerometer(x, y, z); +} + +float *BMX055::getAccelerometer() +{ + if (m_accel) + return m_accel->getAccelerometer(); + else + { + static float v[3] = {0.0f, 0.0f, 0.0f}; + return v; + } +} + +void BMX055::getGyroscope(float *x, float *y, float *z) +{ + if (m_gyro) + m_gyro->getGyroscope(x, y, z); +} + +float *BMX055::getGyroscope() +{ + if (m_gyro) + return m_gyro->getGyroscope(); + else + { + static float v[3] = {0.0f, 0.0f, 0.0f}; + return v; + } +} + +void BMX055::getMagnetometer(float *x, float *y, float *z) +{ + if (m_mag) + m_mag->getMagnetometer(x, y, z); +} + +float *BMX055::getMagnetometer() +{ + if (m_mag) + return m_mag->getMagnetometer(); + else + { + static float v[3] = {0.0f, 0.0f, 0.0f}; + return v; + } +} diff --git a/src/bmx055/bmx055.hpp b/src/bmx055/bmx055.hpp new file mode 100644 index 00000000..3f03d602 --- /dev/null +++ b/src/bmx055/bmx055.hpp @@ -0,0 +1,248 @@ +/* + * 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. + */ +#pragma once + +#include + +#include "bma250e.hpp" +#include "bmg160.hpp" +#include "bmm150.hpp" + +namespace upm { + + /** + * @brief BMX055 9-axis Sensor Module + * @defgroup bmx055 libupm-bmx055 + * @ingroup i2c spi accelerometer compass + */ + + /** + * @library bmx055 + * @sensor bmx055 + * @comname BMX055 9-axis Sensor Module + * @type accelerometer compass + * @man mouser + * @con i2c gpio spi + * @web http://www.mouser.com/ProductDetail/Bosch-Sensortec/0330SB0179/?qs=sGAEpiMZZMsrChSOYEGTCZo8d3KRE6KPUk8gVuWS2Ho%3d + * + * @brief API for the BMX055 9-axis Sensor Module + * + * The BMX055 is an integrated 9-axis sensor for the detection of + * movements and rotations and magnetic heading. It comprises the + * full functionality of a triaxial, low-g acceleration sensor, a + * triaxial angular rate sensor and a triaxial geomagnetic sensor. + * + * The BMX055 senses orientation, tilt, motion, acceleration, + * rotation, shock, vibration and heading in cell phones, handhelds, + * computer peripherals, man-machine interfaces, virtual reality + * features and game controllers. + * + * The BMX055 is essentially 3 separate devices in one: the BMA250E + * Accelerometer, the BMG160 Gyroscope, and the BMM150 Magnetometer. + * They are completely independant of each other. + * + * This driver provides a very simple interface to these 3 devices. + * If finer control is desired, you should just use the separate + * BMA25E, BMG160, and BMM150 device classes directly. This driver + * simply initializes all three devices, and provides a mechanism to + * read accelerometer, gyroscope and magnetometer data from them. + * + * @snippet bmx055.cxx Interesting + */ + + class BMX055 { + public: + /** + * BMX055 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 accelBus I2C or SPI bus to use. -1 to skip initializing + * this device. + * @param accelAddr The address for this device. -1 for SPI. + * @param accelCS The gpio pin to use for the SPI Chip Select. -1 for + * I2C or for SPI with a hardware controlled pin. + * @param gyroBus I2C or SPI bus to use. -1 to skip initializing + * this device. + * @param gyroAddr The address for this device. -1 for SPI. + * @param gyroCS The gpio pin to use for the SPI Chip Select. -1 for + * I2C or for SPI with a hardware controlled pin. + * @param magBus I2C or SPI bus to use. -1 to skip initializing + * this device. + * @param magAddr The address for this device. -1 for SPI. + * @param magCS The gpio pin to use for the SPI Chip Select. -1 for + * I2C or for SPI with a hardware controlled pin. + */ + BMX055(int accelBus=BMA250E_I2C_BUS, + uint8_t accelAddr=BMA250E_DEFAULT_ADDR, + int accelCS=-1, + int gyroBus=BMG160_I2C_BUS, + uint8_t gyroAddr=BMG160_DEFAULT_ADDR, + int gyroCS=-1, + int magBus=BMM150_I2C_BUS, + uint8_t magAddr=BMM150_DEFAULT_ADDR, + int magCS=-1); + + /** + * BMX055 Destructor. + */ + ~BMX055(); + + /** + * Update the internal stored values from sensor data. + */ + void update(); + + /** + * Initialize the accelerometer 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 or you + * want to change these values. + * + * @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. + */ + void initAccelerometer(BMA250E::POWER_MODE_T pwr=BMA250E::POWER_MODE_NORMAL, + BMA250E::RANGE_T range=BMA250E::RANGE_2G, + BMA250E::BW_T bw=BMA250E::BW_250); + + /** + * Initialize the gyroscope 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 or you want to + * change these values. + * + * @param pwr One of the BMG160::POWER_MODE_T values. The default is + * BMG160::POWER_MODE_NORMAL. + * @param range One of the BMG160::RANGE_T values. The default is + * BMG160::RANGE_250. + * @param bw One of the filtering BMG160::BW_T values. The default is + * BMG160::BW_400_47. + */ + void initGyroscope(BMG160::POWER_MODE_T pwr=BMG160::POWER_MODE_NORMAL, + BMG160::RANGE_T range=BMG160::RANGE_250, + BMG160::BW_T bw=BMG160::BW_400_47); + + /** + * Initialize the magnetometer 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 or you want to + * change these values. This method will call + * BMM150::setPresetMode() with the passed parameter. + * + * @param usage One of the BMM150::USAGE_PRESETS_T values. The default is + * BMM150::USAGE_HIGH_ACCURACY. + */ + void initMagnetometer(BMM150::USAGE_PRESETS_T usage=BMM150::USAGE_HIGH_ACCURACY); + + /** + * 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 array. The pointer returned by this function is + * statically allocated and will be rewritten on each call. + * update() must have been called prior to calling this method. + * + * @return A floating point array containing x, y, and z in + * that order. + */ + float *getAccelerometer(); + + /** + * Return gyroscope data in degrees per second. 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 array. The pointer returned by this function is + * statically allocated and will be rewritten on each call. + * update() must have been called prior to calling this method. + * + * @return A floating point array containing x, y, and z in + * that order. + */ + float *getGyroscope(); + + /** + * Return magnetometer data in micro-Teslas (uT). 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 getMagnetometer(float *x, float *y, float *z); + + /** + * Return magnetometer data in micro-Teslas (uT) in the form of a + * floating point array. The pointer returned by this function is + * statically allocated and will be rewritten on each call. + * update() must have been called prior to calling this method. + * + * @return A floating point array containing x, y, and z in + * that order. + */ + float *getMagnetometer(); + + + protected: + BMA250E *m_accel; + BMG160 *m_gyro; + BMM150 *m_mag; + + private: + }; +} diff --git a/src/bmx055/javaupm_bmx055.i b/src/bmx055/javaupm_bmx055.i new file mode 100644 index 00000000..4a160cc3 --- /dev/null +++ b/src/bmx055/javaupm_bmx055.i @@ -0,0 +1,77 @@ +%module javaupm_bmx055 +%include "../upm.i" +%include "cpointer.i" +%include "typemaps.i" +%include "arrays_java.i"; +%include "../java_buffer.i" + +%apply int {mraa::Edge}; +%apply float *INOUT { float *x, float *y, float *z }; + +%typemap(jni) float* "jfloatArray" +%typemap(jstype) float* "float[]" +%typemap(jtype) float* "float[]" + +%typemap(javaout) float* { + return $jnicall; +} + +%typemap(out) float *getAccelerometer { + $result = JCALL1(NewFloatArray, jenv, 3); + JCALL4(SetFloatArrayRegion, jenv, $result, 0, 3, $1); +} + +%typemap(out) float *getGyroscope { + $result = JCALL1(NewFloatArray, jenv, 3); + JCALL4(SetFloatArrayRegion, jenv, $result, 0, 3, $1); +} + +%typemap(out) float *getMagnetometer { + $result = JCALL1(NewFloatArray, jenv, 3); + JCALL4(SetFloatArrayRegion, jenv, $result, 0, 3, $1); +} + +%ignore getAccelerometer(float *, float *, float *); +%ignore getGyroscope(float *, float *, float *); +%ignore getMagnetometer(float *, float *, float *); + +%include "bma250e.hpp" +%{ + #include "bma250e.hpp" +%} + +%include "bmg160.hpp" +%{ + #include "bmg160.hpp" +%} + +%include "bmm150.hpp" +%{ + #include "bmm150.hpp" +%} + +%include "bmx055.hpp" +%{ + #include "bmx055.hpp" +%} + +%include "bmc150.hpp" +%{ + #include "bmc150.hpp" +%} + +%include "bmi055.hpp" +%{ + #include "bmi055.hpp" +%} + +%pragma(java) jniclasscode=%{ + static { + try { + System.loadLibrary("javaupm_bmx055"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. \n" + e); + System.exit(1); + } + } +%} diff --git a/src/bmx055/jsupm_bmx055.i b/src/bmx055/jsupm_bmx055.i new file mode 100644 index 00000000..b59ccd65 --- /dev/null +++ b/src/bmx055/jsupm_bmx055.i @@ -0,0 +1,37 @@ +%module jsupm_bmx055 +%include "../upm.i" +%include "cpointer.i" + +/* Send "int *" and "float *" to JavaScript as intp and floatp */ +%pointer_functions(int, intp); +%pointer_functions(float, floatp); + +%include "bma250e.hpp" +%{ + #include "bma250e.hpp" +%} + +%include "bmg160.hpp" +%{ + #include "bmg160.hpp" +%} + +%include "bmm150.hpp" +%{ + #include "bmm150.hpp" +%} + +%include "bmx055.hpp" +%{ + #include "bmx055.hpp" +%} + +%include "bmc150.hpp" +%{ + #include "bmc150.hpp" +%} + +%include "bmi055.hpp" +%{ + #include "bmi055.hpp" +%} diff --git a/src/bmx055/pyupm_bmx055.i b/src/bmx055/pyupm_bmx055.i new file mode 100644 index 00000000..8250a66e --- /dev/null +++ b/src/bmx055/pyupm_bmx055.i @@ -0,0 +1,47 @@ +// Include doxygen-generated documentation +%include "pyupm_doxy2swig.i" +%module pyupm_bmx055 +%include "../upm.i" +%include "cpointer.i" + +%include "stdint.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 "bmx055_doc.i" +#endif + +%include "bma250e.hpp" +%{ + #include "bma250e.hpp" +%} + +%include "bmg160.hpp" +%{ + #include "bmg160.hpp" +%} + +%include "bmm150.hpp" +%{ + #include "bmm150.hpp" +%} + +%include "bmx055.hpp" +%{ + #include "bmx055.hpp" +%} + +%include "bmc150.hpp" +%{ + #include "bmc150.hpp" +%} + +%include "bmi055.hpp" +%{ + #include "bmi055.hpp" +%}