From d4b536b59317771b7a444fe895598ffa2a0f7d2a Mon Sep 17 00:00:00 2001 From: Jon Trulson Date: Tue, 7 Mar 2017 12:43:44 -0700 Subject: [PATCH] bno055: C port; C++ wraps C The API has been changed in some cases - see the apichanges.md document. In addition, this driver uses a new upm_vectortypes.i SWIG interface file to provide a mechanism for methods that return a vector of floats and ints instead of a pointer to an array. This works much nicer than C array pointers, and results in Python/JS/Java code that looks much more "natural" to the language in use. The Python, JS, and Java examples have been changed to use these methods. Support for the "old" C-style pointer methods are still provided for backward compatibility with existing code. As an example - to retrieve the x, y, and z data for Euler Angles from the bno055, the original python code would look something like: ... x = sensorObj.new_floatp() y = sensorObj.new_floatp() z = sensorObj.new_floatp() ... sensor.getEulerAngles(x, y, z) ... print("Euler: Heading:", sensorObj.floatp_value(x), end=' ') print(" Roll:", sensorObj.floatp_value(y), end=' ') ... Now the equivalent code is simply: floatData = sensor.getEulerAngles() print("Euler: Heading:", floatData[0], ... print(" Roll:", floatData[1], end=' ') ... Additionally, interrupt handling for Java is now implemented completely in the C++ header file now rather than the .cxx file, so no special SWIG processing is required anymore. See Issue #518 . Signed-off-by: Jon Trulson --- docs/apichanges.md | 16 + doxy/samples.mapping.txt | 1 + examples/c/CMakeLists.txt | 1 + examples/c/bno055.c | 119 ++ examples/java/BNO055_Example.java | 54 +- examples/javascript/bno055.js | 64 +- examples/python/bno055.py | 71 +- src/bno055/CMakeLists.txt | 13 +- src/bno055/bno055.c | 910 +++++++++++++ src/bno055/bno055.cxx | 702 ++-------- src/bno055/bno055.h | 676 ++++++++++ src/bno055/bno055.hpp | 2000 +++++++++-------------------- src/bno055/bno055_regs.h | 825 ++++++++++++ src/bno055/javaupm_bno055.i | 68 +- src/bno055/jsupm_bno055.i | 7 +- src/bno055/pyupm_bno055.i | 10 +- 16 files changed, 3382 insertions(+), 2155 deletions(-) create mode 100644 examples/c/bno055.c create mode 100644 src/bno055/bno055.c create mode 100644 src/bno055/bno055.h create mode 100644 src/bno055/bno055_regs.h diff --git a/docs/apichanges.md b/docs/apichanges.md index beac611d..cbe56bba 100644 --- a/docs/apichanges.md +++ b/docs/apichanges.md @@ -4,6 +4,22 @@ API Changes {#apichanges} Here's a list of other API changes made to the library that break source/binary compatibility between releases: +# current master + + * **bno055** This module no longer uses std::strings to pass around + binary data (*read/writeCalibrationData()*). Rather, now *std::vectors* of + the appropriate type are used. In addition, methods that previously + returned certain data in the form of an array, like *getEulerAngles()*, + now return a *std::vector* instead. This simplifies the Python, + Javascript, and Java bindings considerably, and leads to more + "natural" looking Python/Javascript/Java code. For Javascript, Java, + and Python, the examples have been modified to use these methods + rather than the methods that return data in argument pointers or + arrays. The "old style" C pointer API's are still present for + backwards compatibility, but may be removed in the future. + +# v1.1.0 + * **i2clcd/jhd1313m1/lcm1602** LCD devices supported by the i2clcd module are being separated into individual libraries. The APIs will be preserved, but we recommend changing your code to use the new libraries as they become diff --git a/doxy/samples.mapping.txt b/doxy/samples.mapping.txt index e6026fa2..24263780 100644 --- a/doxy/samples.mapping.txt +++ b/doxy/samples.mapping.txt @@ -5,6 +5,7 @@ adc121c021.cxx ADC121C021Sample.java adc121c021.js adc121c021.py adxl345.cxx Adxl345Sample.java adxl345.js adxl345.py biss0001.cxx BISS0001Sample.java biss0001.js biss0001.py bmpx8x.cxx BMPX8XSample.java bmpx8x.js bmpx8x.py +bno055.cxx BNO055_Example.java bno055.js bno055.py button.cxx ButtonSample.java button.js button.py buzzer.cxx BuzzerSample.java buzzer.js buzzer.py cjq4435.cxx CJQ4435Sample.java cjq4435.js cjq4435.py diff --git a/examples/c/CMakeLists.txt b/examples/c/CMakeLists.txt index 5a614b52..459a5a15 100644 --- a/examples/c/CMakeLists.txt +++ b/examples/c/CMakeLists.txt @@ -149,6 +149,7 @@ add_example (hmc5883l) add_example (wfs) add_example (enc03r) add_example (nunchuck) +add_example (bno055) # Custom examples add_custom_example (nmea_gps_i2c-example-c nmea_gps_i2c.c nmea_gps) diff --git a/examples/c/bno055.c b/examples/c/bno055.c new file mode 100644 index 00000000..3018594e --- /dev/null +++ b/examples/c/bno055.c @@ -0,0 +1,119 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2017 Intel Corporation. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include +#include "bno055.h" + +bool shouldRun = true; + +void sig_handler(int signo) +{ + if (signo == SIGINT) + shouldRun = false; +} + + +int main(int argc, char **argv) +{ + signal(SIGINT, sig_handler); +//! [Interesting] + + // Initialize a BNO055 using default parameters (bus 0, addr + // 0x28). The default running mode is NDOF absolute orientation + // mode. + bno055_context sensor = bno055_init(0, BNO055_DEFAULT_ADDR); + + if (!sensor) + { + printf("bno055_init() failed.\n"); + return 1; + } + + // First we need to calibrate.... + printf("First we need to calibrate. 4 numbers will be output every \n" + "second for each sensor. 0 means uncalibrated, and 3 means \n" + "fully calibrated.\n" + "See the UPM documentation on this sensor for instructions on \n" + "what actions are required to calibrate.\n"); + + // do the calibration... + while (shouldRun && !bno055_is_fully_calibrated(sensor)) + { + int mag, acc, gyr, sys; + bno055_get_calibration_status(sensor, &mag, &acc, &gyr, &sys); + + printf("Magnetometer: %d Accelerometer: %d Gyroscope: %d System: %d\n", + mag, acc, gyr, sys); + + upm_delay(1); + } + + printf("\nCalibration complete.\n\n"); + + // now output various fusion data every 250 milliseconds + while (shouldRun) + { + float w, x, y, z; + + if (bno055_update(sensor)) + { + printf("bno055_update() failed.\n"); + return 1; + } + + bno055_get_euler_angles(sensor, &x, &y, &z); + printf("Euler: Heading: %f Roll: %f Pitch: %f degrees\n", + x, y, z); + + bno055_get_quaternions(sensor, &w, &x, &y, &z); + printf("Quaternion: W: %f X: %f Y: %f Z: %f\n", + w, x, y, z); + + bno055_get_linear_acceleration(sensor, &x, &y, &z); + printf("Linear Acceleration: X: %f Y: %f Z: %f m/s^2\n", + x, y, z); + + bno055_get_gravity_vectors(sensor, &x, &y, &z); + printf("Gravity Vector: X: %f Y: %f Z: %f m/s^2\n", + x, y, z); + + printf("\n"); + upm_delay_ms(250); + } + +//! [Interesting] + + printf("Exiting...\n"); + + bno055_close(sensor); + + return 0; +} diff --git a/examples/java/BNO055_Example.java b/examples/java/BNO055_Example.java index 808dbd3c..fd714447 100644 --- a/examples/java/BNO055_Example.java +++ b/examples/java/BNO055_Example.java @@ -1,6 +1,8 @@ /* * Author: Jon Trulson - * Copyright (c) 2016 Intel Corporation. + * Copyright (c) 2016-2017 Intel Corporation. + * + * The MIT License * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -45,12 +47,12 @@ public class BNO055_Example while (!sensor.isFullyCalibrated()) { - int calData[] = sensor.getCalibrationStatus(); + upm_bno055.intVector calData = sensor.getCalibrationStatus(); - System.out.println("Magnetometer: " + calData[0] - + " Accelerometer: " + calData[1] - + " Gyroscope: " + calData[2] - + " System: " + calData[3]); + System.out.println("Magnetometer: " + calData.get(0) + + " Accelerometer: " + calData.get(1) + + " Gyroscope: " + calData.get(2) + + " System: " + calData.get(3)); Thread.sleep(1000); @@ -65,30 +67,30 @@ public class BNO055_Example // update our values from the sensor sensor.update(); - float dataE[] = sensor.getEulerAngles(); - System.out.println("Euler: Heading: " + dataE[0] + - " Roll: " + dataE[1] + - " Pitch: " + dataE[2] + - " degrees"); + upm_bno055.floatVector data = sensor.getEulerAngles(); - float dataQ[] = sensor.getQuaternions(); - System.out.println("Quaternion: W: " + dataQ[0] + - " X:" + dataQ[1] + - " Y: " + dataQ[2] + - " Z: " + dataQ[3]); + System.out.println("Euler: Heading: " + data.get(0) + + " Roll: " + data.get(1) + + " Pitch: " + data.get(2) + + " degrees"); - float dataL[] = sensor.getLinearAcceleration(); - System.out.println("Linear Acceleration: X: " + dataL[0] + - " Y: " + dataL[1] + - " Z: " + dataL[2] + - " m/s^2"); + data = sensor.getQuaternions(); + System.out.println("Quaternion: W: " + data.get(0) + + " X: " + data.get(1) + + " Y: " + data.get(2) + + " Z: " + data.get(3)); - float dataG[] = sensor.getGravityVectors(); - System.out.println("Gravity Vector: X: " + dataG[0] + - " Y: " + dataG[1] + - " Z: " + dataG[2] + - " m/s^2"); + data = sensor.getLinearAcceleration(); + System.out.println("Linear Acceleration: X: " + data.get(0) + + " Y: " + data.get(1) + + " Z: " + data.get(2) + + " m/s^2"); + data = sensor.getGravityVectors(); + System.out.println("Gravity Vector: X: " + data.get(0) + + " Y: " + data.get(1) + + " Z: " + data.get(2) + + " m/s^2"); System.out.println(); Thread.sleep(250); diff --git a/examples/javascript/bno055.js b/examples/javascript/bno055.js index 6878c0ac..3f868d1f 100644 --- a/examples/javascript/bno055.js +++ b/examples/javascript/bno055.js @@ -1,6 +1,8 @@ /* * Author: Jon Trulson - * Copyright (c) 2016 Intel Corporation. + * Copyright (c) 2016-2017 Intel Corporation. + * + * The MIT License * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -30,16 +32,6 @@ var sensorObj = require('jsupm_bno055'); // mode. var sensor = new sensorObj.BNO055(); -var mag = new sensorObj.new_intp(); -var acc = new sensorObj.new_intp(); -var gyr = new sensorObj.new_intp(); -var syst = new sensorObj.new_intp(); - -var w = new sensorObj.new_floatp(); -var x = new sensorObj.new_floatp(); -var y = new sensorObj.new_floatp(); -var z = new sensorObj.new_floatp(); - console.log("First we need to calibrate. 4 numbers will be output every"); console.log("second for each sensor. 0 means uncalibrated, and 3 means"); console.log("fully calibrated."); @@ -61,11 +53,11 @@ var calInterval = setInterval(function() } else { - sensor.getCalibrationStatus(mag, acc, gyr, syst); - console.log("Magnetometer: " + sensorObj.intp_value(mag) + - " Accelerometer: " + sensorObj.intp_value(acc) + - " Gyroscope: " + sensorObj.intp_value(gyr) + - " System: " + sensorObj.intp_value(syst)); + var intData = sensor.getCalibrationStatus(); + console.log("Magnetometer: " + intData.get(0) + + " Accelerometer: " + intData.get(1) + + " Gyroscope: " + intData.get(2) + + " System: " + intData.get(3)); } }, 1000); @@ -76,29 +68,29 @@ function outputData() { sensor.update(); - sensor.getEulerAngles(x, y, z); - console.log("Euler: Heading: " + sensorObj.floatp_value(x) + - " Roll: " + sensorObj.floatp_value(y) + - " Pitch: " + sensorObj.floatp_value(z) + - " degrees"); + var floatData = sensor.getEulerAngles(); + console.log("Euler: Heading: " + floatData.get(0) + + " Roll: " + floatData.get(1) + + " Pitch: " + floatData.get(2) + + " degrees"); - sensor.getQuaternions(w, x, y, z); - console.log("Quaternion: W: " + sensorObj.floatp_value(w) + - " X:" + sensorObj.floatp_value(x) + - " Y: " + sensorObj.floatp_value(y) + - " Z: " + sensorObj.floatp_value(z)); + floatData = sensor.getQuaternions(); + console.log("Quaternion: W: " + floatData.get(0) + + " X:" + floatData.get(1) + + " Y: " + floatData.get(2) + + " Z: " + floatData.get(3)); - sensor.getLinearAcceleration(x, y, z); - console.log("Linear Acceleration: X: " + sensorObj.floatp_value(x) + - " Y: " + sensorObj.floatp_value(y) + - " Z: " + sensorObj.floatp_value(z) + - " m/s^2"); + floatData = sensor.getLinearAcceleration(); + console.log("Linear Acceleration: X: " + floatData.get(0) + + " Y: " + floatData.get(1) + + " Z: " + floatData.get(2) + + " m/s^2"); - sensor.getGravityVectors(x, y, z); - console.log("Gravity Vector: X: " + sensorObj.floatp_value(x) + - " Y: " + sensorObj.floatp_value(y) + - " Z: " + sensorObj.floatp_value(z) + - " m/s^2"); + floatData = sensor.getGravityVectors(); + console.log("Gravity Vector: X: " + floatData.get(0) + + " Y: " + floatData.get(1) + + " Z: " + floatData.get(2) + + " m/s^2"); console.log(""); }; diff --git a/examples/python/bno055.py b/examples/python/bno055.py index 1fb51f7e..ae6d18d6 100755 --- a/examples/python/bno055.py +++ b/examples/python/bno055.py @@ -1,6 +1,8 @@ #!/usr/bin/python # Author: Jon Trulson -# Copyright (c) 2016 Intel Corporation. +# Copyright (c) 2016-2017 Intel Corporation. +# +# The MIT License # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the @@ -32,7 +34,8 @@ def main(): sensor = sensorObj.BNO055() ## Exit handlers ## - # This function stops python from printing a stacktrace when you hit control-C + # This function stops python from printing a stacktrace when you + # hit control-C def SIGINTHandler(signum, frame): raise SystemExit @@ -45,16 +48,6 @@ def main(): atexit.register(exitHandler) signal.signal(signal.SIGINT, SIGINTHandler) - mag = sensorObj.new_intp() - acc = sensorObj.new_intp() - gyr = sensorObj.new_intp() - syst = sensorObj.new_intp() - - w = sensorObj.new_floatp() - x = sensorObj.new_floatp() - y = sensorObj.new_floatp() - z = sensorObj.new_floatp() - print("First we need to calibrate. 4 numbers will be output every") print("second for each sensor. 0 means uncalibrated, and 3 means") print("fully calibrated.") @@ -63,44 +56,54 @@ def main(): print() while (not sensor.isFullyCalibrated()): - sensor.getCalibrationStatus(mag, acc, gyr, syst) - print("Magnetometer:", sensorObj.intp_value(mag), end=' ') - print(" Accelerometer:", sensorObj.intp_value(acc), end=' ') - print(" Gyroscope:", sensorObj.intp_value(gyr), end=' ') - print(" System:", sensorObj.intp_value(syst), end=' ') + intData = sensor.getCalibrationStatus() + print("Magnetometer:", intData[0], end=' ') + print(" Accelerometer:", intData[1], end=' ') + print(" Gyroscope:", intData[2], end=' ') + print(" System:", intData[3]) time.sleep(1) print() print("Calibration complete.") print() +# example - read calibration data, sleep and then write it +# print("Reading calibration data....") +# byteData = sensor.readCalibrationData() +# print("Read data successfully.") +# print("Writing calibration data...") +# time.sleep(1) +# sensor.writeCalibrationData(byteData) +# print("Success!") +# time.sleep(3) + # now output various fusion data every 250 milliseconds while (True): sensor.update() - sensor.getEulerAngles(x, y, z) - print("Euler: Heading:", sensorObj.floatp_value(x), end=' ') - print(" Roll:", sensorObj.floatp_value(y), end=' ') - print(" Pitch:", sensorObj.floatp_value(z), end=' ') + floatData = sensor.getEulerAngles() + print("Euler: Heading:", floatData[0], end=' ') + print(" Roll:", floatData[1], end=' ') + print(" Pitch:", floatData[2], end=' ') print(" degrees") - sensor.getQuaternions(w, x, y, z) - print("Quaternion: W:", sensorObj.floatp_value(w), end=' ') - print(" X:", sensorObj.floatp_value(x), end=' ') - print(" Y:", sensorObj.floatp_value(y), end=' ') - print(" Z:", sensorObj.floatp_value(z)) + floatData = sensor.getQuaternions() + print("Quaternion: W:", floatData[0], end=' ') + print(" X:", floatData[1], end=' ') + print(" Y:", floatData[2], end=' ') + print(" Z:", floatData[3]) - sensor.getLinearAcceleration(x, y, z) - print("Linear Acceleration: X:", sensorObj.floatp_value(x), end=' ') - print(" Y:", sensorObj.floatp_value(y), end=' ') - print(" Z:", sensorObj.floatp_value(z), end=' ') + floatData = sensor.getLinearAcceleration() + print("Linear Acceleration: X:", floatData[0], end=' ') + print(" Y:", floatData[1], end=' ') + print(" Z:", floatData[2], end=' ') print(" m/s^2") - sensor.getGravityVectors(x, y, z) - print("Gravity Vector: X:", sensorObj.floatp_value(x), end=' ') - print(" Y:", sensorObj.floatp_value(y), end=' ') - print(" Z:", sensorObj.floatp_value(z), end=' ') + floatData = sensor.getGravityVectors() + print("Gravity Vector: X:", floatData[0], end=' ') + print(" Y:", floatData[1], end=' ') + print(" Z:", floatData[2], end=' ') print(" m/s^2") print() diff --git a/src/bno055/CMakeLists.txt b/src/bno055/CMakeLists.txt index 9408416d..9a8985f5 100644 --- a/src/bno055/CMakeLists.txt +++ b/src/bno055/CMakeLists.txt @@ -1,5 +1,8 @@ -set (libname "bno055") -set (libdescription "Intelligent 9-axis Absolute Orientation Sensor") -set (module_src ${libname}.cxx) -set (module_hpp ${libname}.hpp) -upm_module_init(mraa) +upm_mixed_module_init (NAME bno055 + DESCRIPTION "Intelligent 9-axis Absolute Orientation Sensor" + C_HDR bno055.h bno055_regs.h + C_SRC bno055.c + CPP_HDR bno055.hpp + CPP_SRC bno055.cxx + CPP_WRAPS_C + REQUIRES mraa) diff --git a/src/bno055/bno055.c b/src/bno055/bno055.c new file mode 100644 index 00000000..37ebac10 --- /dev/null +++ b/src/bno055/bno055.c @@ -0,0 +1,910 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016-2017 Intel Corporation. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include +#include + +#include + +#include "bno055.h" + +// macro for converting a uint8_t low/high pair into a float +#define INT16_TO_FLOAT(l, h) \ + (float)( (int16_t)( (l) | ((h) << 8) ) ) + + +// clear internal data items +static void _clear_data(const bno055_context dev) +{ + assert(dev != NULL); + + dev->magX = dev->magY = dev->magZ = 0; + dev->accX = dev->accY = dev->accZ = 0; + dev->gyrX = dev->gyrY = dev->gyrZ = 0; + dev->eulHeading = dev->eulRoll = dev->eulPitch = 0; + dev->quaW = dev->quaX = dev->quaY = dev->quaZ = 0; + dev->liaX = dev->liaY = dev->liaZ = 0; + dev->grvX = dev->grvY = dev->grvZ = 0; +} + +// load fusion data +static void _update_fusion_data(const bno055_context dev) +{ + assert(dev != NULL); + + // bail if we are in config mode, or aren't in a fusion mode... + if (dev->currentMode == BNO055_OPERATION_MODE_CONFIGMODE || + dev->currentMode < BNO055_OPERATION_MODE_IMU) + return; + + bno055_set_page(dev, 0, false); + + // FIXME/MAYBE? - abort early if SYS calibration is == 0? + + const int fusionBytes = 26; + uint8_t buf[fusionBytes]; + + bno055_read_regs(dev, BNO055_REG_EUL_HEADING_LSB, buf, fusionBytes); + + dev->eulHeading = INT16_TO_FLOAT(buf[0], buf[1]); + dev->eulRoll = INT16_TO_FLOAT(buf[2], buf[3]); + dev->eulPitch = INT16_TO_FLOAT(buf[4], buf[5]); + + dev->quaW = INT16_TO_FLOAT(buf[6], buf[7]); + dev->quaX = INT16_TO_FLOAT(buf[8], buf[9]); + dev->quaY = INT16_TO_FLOAT(buf[10], buf[11]); + dev->quaZ = INT16_TO_FLOAT(buf[12], buf[13]); + + dev->liaX = INT16_TO_FLOAT(buf[14], buf[15]); + dev->liaY = INT16_TO_FLOAT(buf[16], buf[17]); + dev->liaZ = INT16_TO_FLOAT(buf[18], buf[19]); + + dev->grvX = INT16_TO_FLOAT(buf[20], buf[21]); + dev->grvY = INT16_TO_FLOAT(buf[22], buf[23]); + dev->grvZ = INT16_TO_FLOAT(buf[24], buf[25]); +} + +// update non-fusion data +static void _update_non_fusion_data(const bno055_context dev) +{ + assert(dev != NULL); + + // bail if we are in config mode... + if (dev->currentMode == BNO055_OPERATION_MODE_CONFIGMODE) + return; + + bno055_set_page(dev, 0, false); + + const int nonFusionBytes = 18; + uint8_t buf[nonFusionBytes]; + + bno055_read_regs(dev, BNO055_REG_ACC_DATA_X_LSB, buf, nonFusionBytes); + + dev->accX = INT16_TO_FLOAT(buf[0], buf[1]); + dev->accY = INT16_TO_FLOAT(buf[2], buf[3]); + dev->accZ = INT16_TO_FLOAT(buf[4], buf[5]); + + dev->magX = INT16_TO_FLOAT(buf[6], buf[7]); + dev->magY = INT16_TO_FLOAT(buf[8], buf[9]); + dev->magZ = INT16_TO_FLOAT(buf[10], buf[11]); + + dev->gyrX = INT16_TO_FLOAT(buf[12], buf[13]); + dev->gyrY = INT16_TO_FLOAT(buf[14], buf[15]); + dev->gyrZ = INT16_TO_FLOAT(buf[16], buf[17]); +} + +// init +bno055_context bno055_init(int bus, uint8_t addr) +{ + bno055_context dev = + (bno055_context)malloc(sizeof(struct _bno055_context)); + + if (!dev) + return NULL; + + // zero out context + memset((void *)dev, 0, sizeof(struct _bno055_context)); + + // make sure MRAA is initialized + int mraa_rv; + if ((mraa_rv = mraa_init()) != MRAA_SUCCESS) + { + printf("%s: mraa_init() failed (%d).\n", __FUNCTION__, mraa_rv); + bno055_close(dev); + return NULL; + } + + if (!(dev->i2c = mraa_i2c_init(bus))) + { + printf("%s: mraa_i2c_init() failed.\n", __FUNCTION__); + bno055_close(dev); + return NULL; + } + + if (mraa_i2c_address(dev->i2c, addr) != MRAA_SUCCESS) + { + printf("%s: mraa_i2c_address() failed.\n", __FUNCTION__); + bno055_close(dev); + return NULL; + } + + _clear_data(dev); + + // forcibly set page 0, so we are synced with the device + if (bno055_set_page(dev, 0, true)) + { + printf("%s: bno055_set_page() failed.\n", __FUNCTION__); + bno055_close(dev); + return NULL; + } + + // check the chip id. This has to be done after forcibly setting + // page 0, as that is the only page where the chip id is present. + uint8_t chipID = bno055_get_chip_id(dev); + if (chipID != BNO055_CHIPID) + { + printf("%s: Invalid chip ID. Expected 0x%02x, got 0x%02x\n", + __FUNCTION__, BNO055_CHIPID, chipID); + bno055_close(dev); + return NULL; + } + + // if the above two accesses succeeded, the rest should succeed + + // set config mode + bno055_set_operation_mode(dev, BNO055_OPERATION_MODE_CONFIGMODE); + + // default to internal clock + bno055_set_clock_external(dev, false); + + // we specifically avoid doing a reset so that if the device is + // already calibrated, it will remain so. + + // we always use C for temperature + bno055_set_temperature_units_celsius(dev); + + // default to accelerometer temp + bno055_set_temperature_source(dev, BNO055_TEMP_SOURCE_ACC); + + // set accel units to m/s^2 + bno055_set_accelerometer_units(dev, false); + + // set gyro units to degrees + bno055_set_gyroscope_units(dev, false); + + // set Euler units to degrees + bno055_set_euler_units(dev, false); + + // by default, we set the operating mode to the NDOF fusion mode + bno055_set_operation_mode(dev, BNO055_OPERATION_MODE_NDOF); + + return dev; +} + +void bno055_close(bno055_context dev) +{ + assert(dev != NULL); + + bno055_uninstall_isr(dev); + + if (dev->i2c) + mraa_i2c_stop(dev->i2c); + + free(dev); +} + +upm_result_t bno055_update(const bno055_context dev) +{ + assert(dev != NULL); + + upm_result_t rv = UPM_SUCCESS; + if ((rv = bno055_set_page(dev, 0, false))) + return rv; + + // temperature first, always in Celsius + dev->temperature = (float)((int8_t)bno055_read_reg(dev, + BNO055_REG_TEMPERATURE)); + + _update_fusion_data(dev); + _update_non_fusion_data(dev); + + return rv; +} + +uint8_t bno055_read_reg(const bno055_context dev, uint8_t reg) +{ + assert(dev != NULL); + + int rv = mraa_i2c_read_byte_data(dev->i2c, reg); + + if (rv < 0) + { + printf("%s: mraa_i2c_read_byte_data() failed, returning 0\n", + __FUNCTION__); + return 0; + } + + return (uint8_t)rv; +} + +upm_result_t bno055_read_regs(const bno055_context dev, uint8_t reg, + uint8_t *buffer, size_t len) +{ + assert(dev != NULL); + + if (mraa_i2c_read_bytes_data(dev->i2c, reg, buffer, len) < 0) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t bno055_write_reg(const bno055_context dev, + uint8_t reg, uint8_t val) +{ + assert(dev != NULL); + + if (mraa_i2c_write_byte_data(dev->i2c, val, reg)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +upm_result_t bno055_write_regs(const bno055_context dev, uint8_t reg, + uint8_t *buffer, size_t len) +{ + assert(dev != NULL); + + uint8_t buf[len + 1]; + + buf[0] = reg; + for (int i=0; ii2c, buf, len + 1)) + return UPM_ERROR_OPERATION_FAILED; + + return UPM_SUCCESS; +} + +uint8_t bno055_get_chip_id(const bno055_context dev) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + return bno055_read_reg(dev, BNO055_REG_CHIP_ID); +} + +uint8_t bno055_get_acc_id(const bno055_context dev) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + return bno055_read_reg(dev, BNO055_REG_ACC_ID); +} + +uint8_t bno055_get_mag_id(const bno055_context dev) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + return bno055_read_reg(dev, BNO055_REG_MAG_ID); +} + +uint8_t bno055_get_gyr_id(const bno055_context dev) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + return bno055_read_reg(dev, BNO055_REG_GYR_ID); +} + +uint16_t bno055_get_sw_revision(const bno055_context dev) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + + uint8_t lsb, msb; + lsb = bno055_read_reg(dev, BNO055_REG_SW_REV_ID_LSB); + msb = bno055_read_reg(dev, BNO055_REG_SW_REV_ID_MSB); + + return (uint16_t)(lsb | (msb << 8)); +} + +uint8_t bno055_get_bootloader_id(const bno055_context dev) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + return bno055_read_reg(dev, BNO055_REG_BL_REV_ID); +} + +upm_result_t bno055_set_page(const bno055_context dev, uint8_t page, + bool force) +{ + assert(dev != NULL); + + // page can only be 0 or 1 + if (!(page == 0 || page == 1)) + { + printf("%s: page number can only be 0 or 1.\n", + __FUNCTION__); + return UPM_ERROR_INVALID_PARAMETER; + } + + if (force || page != dev->currentPage) + bno055_write_reg(dev, BNO055_REG_PAGE_ID, page); + + dev->currentPage = page; + return UPM_SUCCESS; +} + +void bno055_set_clock_external(const bno055_context dev, bool extClock) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + + // first we need to be in config mode + BNO055_OPERATION_MODES_T currentMode = dev->currentMode; + bno055_set_operation_mode(dev, BNO055_OPERATION_MODE_CONFIGMODE); + + uint8_t reg = bno055_read_reg(dev, BNO055_REG_SYS_TRIGGER); + + if (extClock) + reg |= BNO055_SYS_TRIGGER_CLK_SEL; + else + reg &= ~BNO055_SYS_TRIGGER_CLK_SEL; + + bno055_write_reg(dev, BNO055_REG_SYS_TRIGGER, reg); + + // now reset our operating mode + bno055_set_operation_mode(dev, currentMode); +} + +void bno055_set_temperature_source(const bno055_context dev, + BNO055_TEMP_SOURCES_T src) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + bno055_write_reg(dev, BNO055_REG_TEMP_SOURCE, src); +} + +void bno055_set_temperature_units_celsius(const bno055_context dev) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + + uint8_t reg = bno055_read_reg(dev, BNO055_REG_UNIT_SEL); + + reg &= ~BNO055_UNIT_SEL_TEMP_UNIT; + + bno055_write_reg(dev, BNO055_REG_UNIT_SEL, reg); +} + +void bno055_set_accelerometer_units(const bno055_context dev, bool mg) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + + uint8_t reg = bno055_read_reg(dev, BNO055_REG_UNIT_SEL); + + if (mg) + { + reg |= BNO055_UNIT_SEL_ACC_UNIT; + dev->accUnitScale = 1.0; + } + else + { + reg &= ~BNO055_UNIT_SEL_ACC_UNIT; + dev->accUnitScale = 100.0; + } + + bno055_write_reg(dev, BNO055_REG_UNIT_SEL, reg); +} + +void bno055_set_gyroscope_units(const bno055_context dev, bool radians) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + + uint8_t reg = bno055_read_reg(dev, BNO055_REG_UNIT_SEL); + + if (radians) + { + reg |= BNO055_UNIT_SEL_GYR_UNIT; + dev->gyrUnitScale = 900.0; + } + else + { + reg &= ~BNO055_UNIT_SEL_GYR_UNIT; + dev->gyrUnitScale = 16.0; + } + + bno055_write_reg(dev, BNO055_REG_UNIT_SEL, reg); +} + +void bno055_set_euler_units(const bno055_context dev, bool radians) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + + uint8_t reg = bno055_read_reg(dev, BNO055_REG_UNIT_SEL); + + if (radians) + { + reg |= BNO055_UNIT_SEL_EUL_UNIT; + dev->eulUnitScale = 900.0; + } + else + { + reg &= ~BNO055_UNIT_SEL_EUL_UNIT; + dev->eulUnitScale = 16.0; + } + + bno055_write_reg(dev, BNO055_REG_UNIT_SEL, reg); +} + +void bno055_set_operation_mode(const bno055_context dev, + BNO055_OPERATION_MODES_T mode) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + + // we clear all of our loaded data on mode changes + _clear_data(dev); + + uint8_t reg = bno055_read_reg(dev, BNO055_REG_OPER_MODE); + + reg &= ~(_BNO055_OPR_MODE_OPERATION_MODE_MASK + << _BNO055_OPR_MODE_OPERATION_MODE_SHIFT); + + reg |= (mode << _BNO055_OPR_MODE_OPERATION_MODE_SHIFT); + + bno055_write_reg(dev, BNO055_REG_OPER_MODE, reg); + dev->currentMode = mode; + + upm_delay_us(30); +} + +void bno055_get_calibration_status(const bno055_context dev, + int *mag, int *acc, + int *gyr, int *sys) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + + uint8_t reg = bno055_read_reg(dev, BNO055_REG_CALIB_STAT); + + if (mag) + *mag = (reg >> _BNO055_CALIB_STAT_MAG_SHIFT) + & _BNO055_CALIB_STAT_MAG_MASK; + + if (acc) + *acc = (reg >> _BNO055_CALIB_STAT_ACC_SHIFT) + & _BNO055_CALIB_STAT_ACC_MASK; + + if (gyr) + *gyr = (reg >> _BNO055_CALIB_STAT_GYR_SHIFT) + & _BNO055_CALIB_STAT_GYR_MASK; + + if (sys) + *sys = (reg >> _BNO055_CALIB_STAT_SYS_SHIFT) + & _BNO055_CALIB_STAT_SYS_MASK; +} + +bool bno055_is_fully_calibrated(const bno055_context dev) +{ + assert(dev != NULL); + + int mag, acc, gyr, sys; + + bno055_get_calibration_status(dev, &mag, &acc, &gyr, &sys); + + // all of them equal to 3 means fully calibrated + if (mag == 3 && acc == 3 && gyr == 3 && sys == 3) + return true; + else + return false; +} + +void bno055_reset_system(const bno055_context dev) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + + uint8_t reg = bno055_read_reg(dev, BNO055_REG_SYS_TRIGGER); + + reg |= BNO055_SYS_TRIGGER_RST_SYS; + + bno055_write_reg(dev, BNO055_REG_SYS_TRIGGER, reg); + upm_delay(1); +} + +void bno055_reset_interrupt_status(const bno055_context dev) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + + uint8_t reg = bno055_read_reg(dev, BNO055_REG_SYS_TRIGGER); + + reg |= BNO055_SYS_TRIGGER_RST_INT; + + bno055_write_reg(dev, BNO055_REG_SYS_TRIGGER, reg); +} + +uint8_t bno055_get_interrupt_status(const bno055_context dev) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + + return bno055_read_reg(dev, BNO055_REG_INT_STA); +} + +uint8_t bno055_get_interrupt_enable(const bno055_context dev) +{ + assert(dev != NULL); + + bno055_set_page(dev, 1, false); + + return bno055_read_reg(dev, BNO055_REG_INT_EN); +} + +void bno055_set_interrupt_enable(const bno055_context dev, uint8_t enables) +{ + assert(dev != NULL); + + bno055_set_page(dev, 1, false); + + bno055_write_reg(dev, BNO055_REG_INT_EN, enables); +} + +uint8_t bno055_get_interrupt_mask(const bno055_context dev) +{ + assert(dev != NULL); + + bno055_set_page(dev, 1, false); + + return bno055_read_reg(dev, BNO055_REG_INT_MSK); +} + +void bno055_set_interrupt_mask(const bno055_context dev, uint8_t mask) +{ + assert(dev != NULL); + + bno055_set_page(dev, 1, false); + + bno055_write_reg(dev, BNO055_REG_INT_MSK, mask); +} + +BNO055_SYS_STATUS_T bno055_get_system_status(const bno055_context dev) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + + return (BNO055_SYS_STATUS_T)bno055_read_reg(dev, BNO055_REG_SYS_STATUS); +} + +BNO055_SYS_ERR_T bno055_get_system_error(const bno055_context dev) +{ + assert(dev != NULL); + + bno055_set_page(dev, 0, false); + + return (BNO055_SYS_ERR_T)bno055_read_reg(dev, BNO055_REG_SYS_ERROR); +} + +upm_result_t bno055_read_calibration_data(const bno055_context dev, + uint8_t *data, size_t len) +{ + assert(dev != NULL); + assert(data != NULL); + + if (!bno055_is_fully_calibrated(dev)) + { + printf("%s: Sensor must be fully calibrated first.\n", + __FUNCTION__); + return UPM_ERROR_NO_DATA; + } + + if (len != BNO055_CALIBRATION_DATA_SIZE) + { + printf("%s: len must equal BNO055_CALIBRATION_DATA_SIZE (%d).\n", + __FUNCTION__, BNO055_CALIBRATION_DATA_SIZE); + return UPM_ERROR_INVALID_SIZE; + } + + // should be at page 0, but lets make sure + bno055_set_page(dev, 0, false); + + // first we need to go back into config mode + BNO055_OPERATION_MODES_T currentMode = dev->currentMode; + bno055_set_operation_mode(dev, BNO055_OPERATION_MODE_CONFIGMODE); + + bno055_read_regs(dev, BNO055_REG_ACC_OFFSET_X_LSB, data, + BNO055_CALIBRATION_DATA_SIZE); + + // now reset our operating mode + bno055_set_operation_mode(dev, currentMode); + + return UPM_SUCCESS; +} + +upm_result_t bno055_write_calibration_data(const bno055_context dev, + uint8_t *data, + size_t len) +{ + assert(dev != NULL); + assert(data != NULL); + + if (len != BNO055_CALIBRATION_DATA_SIZE) + { + printf("%s: len must equal BNO055_CALIBRATION_DATA_SIZE " + "(expected %d, got %d).\n", + __FUNCTION__, BNO055_CALIBRATION_DATA_SIZE, (int)len); + return UPM_ERROR_INVALID_SIZE; + } + + // should be at page 0, but lets make sure + bno055_set_page(dev, 0, false); + + // first we need to go back into config mode + BNO055_OPERATION_MODES_T currentMode = dev->currentMode; + bno055_set_operation_mode(dev, BNO055_OPERATION_MODE_CONFIGMODE); + + // write the data + bno055_write_regs(dev, BNO055_REG_ACC_OFFSET_X_LSB, data, + BNO055_CALIBRATION_DATA_SIZE); + + // now reset our operating mode + bno055_set_operation_mode(dev, currentMode); + + return UPM_SUCCESS; +} + +float bno055_get_temperature(const bno055_context dev) +{ + assert(dev != NULL); + + return dev->temperature; +} + +void bno055_get_euler_angles(const bno055_context dev, float *heading, + float *roll, float *pitch) +{ + assert(dev != NULL); + + if (heading) + *heading = dev->eulHeading / dev->eulUnitScale; + + if (roll) + *roll = dev->eulRoll / dev->eulUnitScale; + + if (pitch) + *pitch = dev->eulPitch / dev->eulUnitScale; +} + +void bno055_get_quaternions(const bno055_context dev, float *w, float *x, + float *y, float *z) +{ + assert(dev != NULL); + + // from the datasheet + const float scale = (float)(1.0 / (float)(1 << 14)); + + if (w) + *w = dev->quaW * scale; + + if (x) + *x = dev->quaX * scale; + + if (y) + *y = dev->quaY * scale; + + if (z) + *z = dev->quaZ * scale; +} + +void bno055_get_linear_acceleration(const bno055_context dev, float *x, + float *y, float *z) +{ + assert(dev != NULL); + + if (x) + *x = dev->liaX / dev->accUnitScale; + + if (y) + *y = dev->liaY / dev->accUnitScale; + + if (z) + *z = dev->liaZ / dev->accUnitScale; +} + +void bno055_get_gravity_vectors(const bno055_context dev, + float *x, float *y, float *z) +{ + assert(dev != NULL); + + if (x) + *x = dev->grvX / dev->accUnitScale; + + if (y) + *y = dev->grvY / dev->accUnitScale; + + if (z) + *z = dev->grvZ / dev->accUnitScale; +} + +void bno055_get_accelerometer(const bno055_context dev, float *x, float *y, + float *z) +{ + assert(dev != NULL); + + if (x) + *x = dev->accX / dev->accUnitScale; + + if (y) + *y = dev->accY / dev->accUnitScale; + + if (z) + *z = dev->accZ / dev->accUnitScale; +} + +void bno055_get_magnetometer(const bno055_context dev, float *x, float *y, + float *z) +{ + assert(dev != NULL); + + // from the datasheet - 16 uT's per LSB + const float scale = 16.0; + + if (x) + *x = dev->magX / scale; + + if (y) + *y = dev->magY / scale; + + if (z) + *z = dev->magZ / scale; +} + +void bno055_get_gyroscope(const bno055_context dev, + float *x, float *y, float *z) +{ + assert(dev != NULL); + + if (x) + *x = dev->gyrX / dev->gyrUnitScale; + + if (y) + *y = dev->gyrY / dev->gyrUnitScale; + + if (z) + *z = dev->gyrZ / dev->gyrUnitScale; +} + +void bno055_set_acceleration_config(const bno055_context dev, + BNO055_ACC_RANGE_T range, + BNO055_ACC_BW_T bw, + BNO055_ACC_PWR_MODE_T pwr) +{ + assert(dev != NULL); + + bno055_set_page(dev, 1, false); + + uint8_t reg = ((range << _BNO055_ACC_CONFIG_ACC_RANGE_SHIFT) + | (bw << _BNO055_ACC_CONFIG_ACC_BW_SHIFT) + | (pwr << _BNO055_ACC_CONFIG_ACC_PWR_MODE_SHIFT)); + + bno055_write_reg(dev, BNO055_REG_ACC_CONFIG, reg); +} + +void bno055_set_magnetometer_config(const bno055_context dev, + BNO055_MAG_ODR_T odr, + BNO055_MAG_OPR_T opr, + BNO055_MAG_POWER_T pwr) +{ + assert(dev != NULL); + + bno055_set_page(dev, 1, false); + + uint8_t reg = ((odr << _BNO055_MAG_CONFIG_MAG_ODR_SHIFT) + | (opr << _BNO055_MAG_CONFIG_MAG_OPR_MODE_SHIFT) + | (pwr << _BNO055_MAG_CONFIG_MAG_POWER_MODE_SHIFT)); + + bno055_write_reg(dev, BNO055_REG_MAG_CONFIG, reg); +} + +void bno055_set_gyroscope_config(const bno055_context dev, + BNO055_GYR_RANGE_T range, + BNO055_GYR_BW_T bw, + BNO055_GYR_POWER_MODE_T pwr) +{ + assert(dev != NULL); + + bno055_set_page(dev, 1, false); + + uint8_t reg = ((range << _BNO055_GYR_CONFIG0_GYR_RANGE_SHIFT) + | (bw << _BNO055_GYR_CONFIG0_GYR_BW_SHIFT)); + + bno055_write_reg(dev, BNO055_REG_GYR_CONFIG0, reg); + + reg = (pwr << _BNO055_GYR_CONFIG1_GYR_POWER_MODE_SHIFT); + + bno055_write_reg(dev, BNO055_REG_GYR_CONFIG1, reg); +} + +upm_result_t bno055_install_isr(const bno055_context dev, + int gpio, mraa_gpio_edge_t level, + void (*isr)(void *), void *arg) +{ + assert(dev != NULL); + + // delete any existing ISR and GPIO context + bno055_uninstall_isr(dev); + + // create gpio context + if (!(dev->gpio = mraa_gpio_init(gpio))) + { + printf("%s: mraa_gpio_init() failed.\n", __FUNCTION__); + return UPM_ERROR_OPERATION_FAILED; + } + + mraa_gpio_dir(dev->gpio, MRAA_GPIO_IN); + + if (mraa_gpio_isr(dev->gpio, level, isr, arg)) + { + mraa_gpio_close(dev->gpio); + dev->gpio = NULL; + printf("%s: mraa_gpio_isr() failed.\n", __FUNCTION__); + return UPM_ERROR_OPERATION_FAILED; + } + + return UPM_SUCCESS; +} + +void bno055_uninstall_isr(const bno055_context dev) +{ + assert(dev != NULL); + + if (dev->gpio) + { + mraa_gpio_isr_exit(dev->gpio); + mraa_gpio_close(dev->gpio); + dev->gpio = NULL; + } +} diff --git a/src/bno055/bno055.cxx b/src/bno055/bno055.cxx index 0f3ececc..8ad6533a 100644 --- a/src/bno055/bno055.cxx +++ b/src/bno055/bno055.cxx @@ -1,6 +1,8 @@ /* * Author: Jon Trulson - * Copyright (c) 2016 Intel Corporation. + * Copyright (c) 2016-17 Intel Corporation. + * + * The MIT License * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -22,788 +24,342 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include #include #include -#include -#include #include "bno055.hpp" using namespace upm; using namespace std; -// conversion from fahrenheit to celsius and back - -static float f2c(float f) -{ - return ((f - 32.0) / (9.0 / 5.0)); -} +// conversion from Celsius to Fahrenheit static float c2f(float c) { - return (c * (9.0 / 5.0) + 32.0); + return (c * (9.0 / 5.0) + 32.0); } BNO055::BNO055(int bus, uint8_t addr) : - m_i2c(bus), m_gpioIntr(0) + m_bno055(bno055_init(bus, addr)) { - - m_addr = addr; - - clearData(); - - mraa::Result rv; - if ( (rv = m_i2c.address(m_addr)) != mraa::SUCCESS) - { - throw std::runtime_error(string(__FUNCTION__) + - ": I2c.address() failed"); - return; - } - - // forcibly set page 0, so we are synced - setPage(0, true); - - // set config mode - setOperationMode(OPERATION_MODE_CONFIGMODE); - - // default to internal clock - setClockExternal(false); - - // we specifically avoid doing a reset so that if the device is - // already calibrated, it will remain so. - - // check the chip id - - uint8_t chipID = readReg(REG_CHIP_ID); - if (chipID != BNO055_CHIPID) - { - throw std::runtime_error(string(__FUNCTION__) - + ": invalid chip ID. Expected " - + std::to_string(int(BNO055_CHIPID)) - + ", got " - + std::to_string(int(chipID))); - return; - } - - // default to temperature C - setTemperatureUnits(true); - - // default to accelerometer temp - setTemperatureSource(TEMP_SOURCE_ACC); - - // set accel units to m/s^2 - setAccelerometerUnits(false); - - // set gyro units to degrees - setGyroscopeUnits(false); - - // set Euler units to degrees - setEulerUnits(false); - - // by default, we set the operating mode to the NDOF fusion mode - setOperationMode(OPERATION_MODE_NDOF); + if (!m_bno055) + throw std::runtime_error(string(__FUNCTION__) + + ": bno055_init() failed"); } BNO055::~BNO055() { - uninstallISR(); + bno055_close(m_bno055); } void BNO055::update() { - setPage(0); - - // temperature first, we always store as C - float tmpF = float((int8_t)readReg(REG_TEMPERATURE)); - if (m_tempIsC) - m_temperature = tmpF; - else - m_temperature = f2c(tmpF * 2.0); - - updateFusionData(); - updateNonFusionData(); + if (bno055_update(m_bno055)) + throw std::runtime_error(string(__FUNCTION__) + + ": bno055_update() failed"); } uint8_t BNO055::readReg(uint8_t reg) { - return m_i2c.readReg(reg); + return bno055_read_reg(m_bno055, reg); } void BNO055::readRegs(uint8_t reg, uint8_t *buffer, int len) { - m_i2c.readBytesReg(reg, buffer, len); + if (bno055_read_regs(m_bno055, reg, buffer, len)) + throw std::runtime_error(string(__FUNCTION__) + + ": bno055_read_regs() failed"); } -bool BNO055::writeReg(uint8_t reg, uint8_t val) +void BNO055::writeReg(uint8_t reg, uint8_t val) { - mraa::Result rv; - if ((rv = m_i2c.writeReg(reg, val)) != mraa::SUCCESS) - { - throw std::runtime_error(std::string(__FUNCTION__) - + ": I2c.writeReg() failed"); - } - - return true; + if (bno055_write_reg(m_bno055, reg, val)) + throw std::runtime_error(string(__FUNCTION__) + + ": bno055_write_reg() failed"); } -bool BNO055::writeRegs(uint8_t reg, uint8_t *buffer, int len) +void BNO055::writeRegs(uint8_t reg, uint8_t *buffer, int len) { - uint8_t buf[len + 1]; - - buf[0] = reg; - for (int i=0; i> _CALIB_STAT_MAG_SHIFT) & _CALIB_STAT_MAG_MASK; - - if (acc) - *acc = (reg >> _CALIB_STAT_ACC_SHIFT) & _CALIB_STAT_ACC_MASK; - - if (gyr) - *gyr = (reg >> _CALIB_STAT_GYR_SHIFT) & _CALIB_STAT_GYR_MASK; - - if (sys) - *sys = (reg >> _CALIB_STAT_SYS_SHIFT) & _CALIB_STAT_SYS_MASK; + bno055_get_calibration_status(m_bno055, mag, acc, gyr, sys); } -int *BNO055::getCalibrationStatus() +vector BNO055::getCalibrationStatus() { - static int v[4]; // mag, acc, gyr, sys; + int v[4]; // mag, acc, gyr, sys; - getCalibrationStatus(&v[0], &v[1], &v[2], &v[3]); - return v; + getCalibrationStatus(&v[0], &v[1], &v[2], &v[3]); + return vector(v, v+4); } bool BNO055::isFullyCalibrated() { - int mag, acc, gyr, sys; - - getCalibrationStatus(&mag, &acc, &gyr, &sys); - - // all of them equal to 3 means fully calibrated - if (mag == 3 && acc == 3 && gyr == 3 && sys == 3) - return true; - else - return false; + return bno055_is_fully_calibrated(m_bno055); } void BNO055::resetSystem() { - setPage(0); - - uint8_t reg = readReg(REG_SYS_TRIGGER); - - reg |= SYS_TRIGGER_RST_SYS; - - writeReg(REG_SYS_TRIGGER, reg); - sleep(1); + bno055_reset_system(m_bno055); } void BNO055::resetInterruptStatus() { - setPage(0); - - uint8_t reg = readReg(REG_SYS_TRIGGER); - - reg |= SYS_TRIGGER_RST_INT; - - writeReg(REG_SYS_TRIGGER, reg); + bno055_reset_interrupt_status(m_bno055); } uint8_t BNO055::getInterruptStatus() { - setPage(0); - - return readReg(REG_INT_STA); + return bno055_get_interrupt_status(m_bno055); } uint8_t BNO055::getInterruptEnable() { - setPage(1); - - return readReg(REG_INT_EN); + return bno055_get_interrupt_enable(m_bno055); } void BNO055::setInterruptEnable(uint8_t enables) { - setPage(1); - - writeReg(REG_INT_EN, enables); + return bno055_set_interrupt_enable(m_bno055, enables); } uint8_t BNO055::getInterruptMask() { - setPage(1); - - return readReg(REG_INT_MSK); + return bno055_get_interrupt_mask(m_bno055); } void BNO055::setInterruptMask(uint8_t mask) { - setPage(1); - - writeReg(REG_INT_MSK, mask); + return bno055_set_interrupt_mask(m_bno055, mask); } -BNO055::SYS_STATUS_T BNO055::getSystemStatus() +BNO055_SYS_STATUS_T BNO055::getSystemStatus() { - setPage(0); - - return static_cast(readReg(REG_SYS_STATUS)); + return bno055_get_system_status(m_bno055); } -BNO055::SYS_ERR_T BNO055::getSystemError() +BNO055_SYS_ERR_T BNO055::getSystemError() { - setPage(0); - - return static_cast(readReg(REG_SYS_ERROR)); + return bno055_get_system_error(m_bno055); } -string BNO055::readCalibrationData() +std::vector BNO055::readCalibrationData() { - if (!isFullyCalibrated()) - { - cerr << __FUNCTION__ << ": Sensor must be fully calibrated first." - << endl; - return ""; - } + uint8_t calibrationData[BNO055_CALIBRATION_DATA_SIZE]; - // should be at page 0, but lets make sure - setPage(0); + if (bno055_read_calibration_data(m_bno055, calibrationData, + BNO055_CALIBRATION_DATA_SIZE)) + throw std::runtime_error(string(__FUNCTION__) + + ": bno055_read_calibration_data() failed"); - // first we need to go back into config mode - OPERATION_MODES_T currentMode = m_currentMode; - setOperationMode(OPERATION_MODE_CONFIGMODE); - - uint8_t calibData[calibrationDataNumBytes]; - readRegs(REG_ACC_OFFSET_X_LSB, calibData, calibrationDataNumBytes); - - string rv((char *)calibData, calibrationDataNumBytes); - - // now reset our operating mode - setOperationMode(currentMode); - - return rv; + return vector(calibrationData, + calibrationData+BNO055_CALIBRATION_DATA_SIZE); } -void BNO055::writeCalibrationData(string calibData) +void BNO055::writeCalibrationData(vector calibrationData) { - if (static_cast(calibData.size()) != calibrationDataNumBytes) - { - throw std::invalid_argument(std::string(__FUNCTION__) - + ": calibData string must be exactly " - + std::to_string(calibrationDataNumBytes) - + " bytes long"); - } - - // should be at page 0, but lets make sure - setPage(0); - - // first we need to go back into config mode - OPERATION_MODES_T currentMode = m_currentMode; - setOperationMode(OPERATION_MODE_CONFIGMODE); - - // write the data - writeRegs(REG_ACC_OFFSET_X_LSB, (uint8_t *)calibData.c_str(), - calibData.size()); - - // now reset our operating mode - setOperationMode(currentMode); + if (bno055_write_calibration_data(m_bno055, calibrationData.data(), + calibrationData.size())) + throw std::runtime_error(string(__FUNCTION__) + + ": bno055_write_calibration_data() failed"); } float BNO055::getTemperature(bool fahrenheit) { - if (fahrenheit) - return c2f(m_temperature); - else - return m_temperature; -} + float temperature = bno055_get_temperature(m_bno055); -void BNO055::clearData() -{ - m_magX = m_magY = m_magZ = 0; - m_accX = m_accY = m_accZ = 0; - m_gyrX = m_gyrY = m_gyrZ = 0; - m_eulHeading = m_eulRoll = m_eulPitch = 0; - m_quaW = m_quaX = m_quaY = m_quaZ = 0; - m_liaX = m_liaY = m_liaZ = 0; - m_grvX = m_grvY = m_grvZ = 0; -} - -bool BNO055::updateFusionData() -{ - // bail if we are in config mode, or aren't in a fusion mode... - if (m_currentMode == OPERATION_MODE_CONFIGMODE || - m_currentMode < OPERATION_MODE_IMU) - return false; - - setPage(0); - - // FIXME/MAYBE? - abort early if SYS calibration is == 0? - - const int fusionBytes = 26; - uint8_t buf[fusionBytes]; - - readRegs(REG_EUL_HEADING_LSB, buf, fusionBytes); - - m_eulHeading = float(int16_t(buf[0] | (buf[1] << 8))); - m_eulRoll = float(int16_t(buf[2] | (buf[3] << 8))); - m_eulPitch = float(int16_t(buf[4] | (buf[5] << 8))); - - m_quaW = float(int16_t(buf[6] | (buf[7] << 8))); - m_quaX = float(int16_t(buf[8] | (buf[9] << 8))); - m_quaY = float(int16_t(buf[10] | (buf[11] << 8))); - m_quaZ = float(int16_t(buf[12] | (buf[13] << 8))); - - m_liaX = float(int16_t(buf[14] | (buf[15] << 8))); - m_liaY = float(int16_t(buf[16] | (buf[17] << 8))); - m_liaZ = float(int16_t(buf[18] | (buf[19] << 8))); - - m_grvX = float(int16_t(buf[20] | (buf[21] << 8))); - m_grvY = float(int16_t(buf[22] | (buf[23] << 8))); - m_grvZ = float(int16_t(buf[24] | (buf[25] << 8))); - - return true; -} - -bool BNO055::updateNonFusionData() -{ - // bail if we are in config mode... - if (m_currentMode == OPERATION_MODE_CONFIGMODE) - return false; - - setPage(0); - - const int nonFusionBytes = 18; - uint8_t buf[nonFusionBytes]; - - readRegs(REG_ACC_DATA_X_LSB, buf, nonFusionBytes); - - m_accX = float(int16_t(buf[0] | (buf[1] << 8))); - m_accY = float(int16_t(buf[2] | (buf[3] << 8))); - m_accZ = float(int16_t(buf[4] | (buf[5] << 8))); - - m_magX = float(int16_t(buf[6] | (buf[7] << 8))); - m_magY = float(int16_t(buf[8] | (buf[9] << 8))); - m_magZ = float(int16_t(buf[10] | (buf[11] << 8))); - - m_gyrX = float(int16_t(buf[12] | (buf[13] << 8))); - m_gyrY = float(int16_t(buf[14] | (buf[15] << 8))); - m_gyrZ = float(int16_t(buf[16] | (buf[17] << 8))); - - return true; + if (fahrenheit) + return c2f(temperature); + else + return temperature; } void BNO055::getEulerAngles(float *heading, float *roll, float *pitch) { - if (heading) - *heading = m_eulHeading / m_eulUnitScale; - - if (roll) - *roll = m_eulRoll / m_eulUnitScale; - - if (pitch) - *pitch = m_eulPitch / m_eulUnitScale; + bno055_get_euler_angles(m_bno055, heading, roll, pitch); } -float *BNO055::getEulerAngles() +vector BNO055::getEulerAngles() { - static float v[3]; - getEulerAngles(&v[0], &v[1], &v[2]); - return v; + float v[3]; + getEulerAngles(&v[0], &v[1], &v[2]); + return vector(v, v+3); } void BNO055::getQuaternions(float *w, float *x, float *y, float *z) { - // from the datasheet - const float scale = float(1.0 / (1 << 14)); - - if (w) - *w = m_quaW * scale; - - if (x) - *x = m_quaX * scale; - - if (y) - *y = m_quaY * scale; - - if (z) - *z = m_quaZ * scale; + bno055_get_quaternions(m_bno055, w, x, y, z); } -float *BNO055::getQuaternions() +vector BNO055::getQuaternions() { - static float v[4]; - getQuaternions(&v[0], &v[1], &v[2], &v[3]); - return v; + float v[4]; + getQuaternions(&v[0], &v[1], &v[2], &v[3]); + return vector(v, v+4); } void BNO055::getLinearAcceleration(float *x, float *y, float *z) { - if (x) - *x = m_liaX / m_accUnitScale; - - if (y) - *y = m_liaY / m_accUnitScale; - - if (z) - *z = m_liaZ / m_accUnitScale; + bno055_get_linear_acceleration(m_bno055, x, y, z); } -float *BNO055::getLinearAcceleration() +vector BNO055::getLinearAcceleration() { - static float v[3]; - getLinearAcceleration(&v[0], &v[1], &v[2]); - return v; + float v[3]; + getLinearAcceleration(&v[0], &v[1], &v[2]); + return vector(v, v+3); } void BNO055::getGravityVectors(float *x, float *y, float *z) { - if (x) - *x = m_grvX / m_accUnitScale; - - if (y) - *y = m_grvY / m_accUnitScale; - - if (z) - *z = m_grvZ / m_accUnitScale; + bno055_get_gravity_vectors(m_bno055, x, y, z); } -float *BNO055::getGravityVectors() +vector BNO055::getGravityVectors() { - static float v[3]; - getGravityVectors(&v[0], &v[1], &v[2]); - return v; + static float v[3]; + getGravityVectors(&v[0], &v[1], &v[2]); + return vector(v, v+3); } void BNO055::getAccelerometer(float *x, float *y, float *z) { - if (x) - *x = m_accX / m_accUnitScale; - - if (y) - *y = m_accY / m_accUnitScale; - - if (z) - *z = m_accZ / m_accUnitScale; + bno055_get_accelerometer(m_bno055, x, y, z); } -float *BNO055::getAccelerometer() +vector BNO055::getAccelerometer() { - static float v[3]; - getAccelerometer(&v[0], &v[1], &v[2]); - return v; + static float v[3]; + getAccelerometer(&v[0], &v[1], &v[2]); + return vector(v, v+3); } void BNO055::getMagnetometer(float *x, float *y, float *z) { - // from the datasheet - 16 uT's per LSB - const float scale = 16.0; - - if (x) - *x = m_magX / scale; - - if (y) - *y = m_magY / scale; - - if (z) - *z = m_magZ / scale; + bno055_get_magnetometer(m_bno055, x, y, z); } -float *BNO055::getMagnetometer() +vector BNO055::getMagnetometer() { - static float v[3]; - getMagnetometer(&v[0], &v[1], &v[2]); - return v; + float v[3]; + getMagnetometer(&v[0], &v[1], &v[2]); + return vector(v, v+3); } void BNO055::getGyroscope(float *x, float *y, float *z) { - if (x) - *x = m_gyrX / m_gyrUnitScale; - - if (y) - *y = m_gyrY / m_gyrUnitScale; - - if (z) - *z = m_gyrZ / m_gyrUnitScale; + bno055_get_gyroscope(m_bno055, x, y, z); } -float *BNO055::getGyroscope() +vector BNO055::getGyroscope() { - static float v[3]; - getGyroscope(&v[0], &v[1], &v[2]); - return v; + float v[3]; + getGyroscope(&v[0], &v[1], &v[2]); + return vector(v, v+3); } -void BNO055::setAccelerationConfig(ACC_RANGE_T range, ACC_BW_T bw, - ACC_PWR_MODE_T pwr) +void BNO055::setAccelerationConfig(BNO055_ACC_RANGE_T range, + BNO055_ACC_BW_T bw, + BNO055_ACC_PWR_MODE_T pwr) { - setPage(1); - - uint8_t reg = ((range << _ACC_CONFIG_ACC_RANGE_SHIFT) | - (bw << _ACC_CONFIG_ACC_BW_SHIFT) | - (pwr << _ACC_CONFIG_ACC_PWR_MODE_SHIFT)); - - writeReg(REG_ACC_CONFIG, reg); + bno055_set_acceleration_config(m_bno055, range, bw, pwr); } -void BNO055::setMagnetometerConfig(MAG_ODR_T odr, MAG_OPR_T opr, - MAG_POWER_T pwr) +void BNO055::setMagnetometerConfig(BNO055_MAG_ODR_T odr, + BNO055_MAG_OPR_T opr, + BNO055_MAG_POWER_T pwr) { - setPage(1); - - uint8_t reg = ((odr << _MAG_CONFIG_MAG_ODR_SHIFT) | - (opr << _MAG_CONFIG_MAG_OPR_MODE_SHIFT) | - (pwr << _MAG_CONFIG_MAG_POWER_MODE_SHIFT)); - - writeReg(REG_MAG_CONFIG, reg); + bno055_set_magnetometer_config(m_bno055, odr, opr, pwr); } -void BNO055::setGyroscopeConfig(GYR_RANGE_T range, GYR_BW_T bw, - GYR_POWER_MODE_T pwr) +void BNO055::setGyroscopeConfig(BNO055_GYR_RANGE_T range, + BNO055_GYR_BW_T bw, + BNO055_GYR_POWER_MODE_T pwr) { - setPage(1); - - uint8_t reg = ((range << _GYR_CONFIG0_GYR_RANGE_SHIFT) | - (bw << _GYR_CONFIG0_GYR_BW_SHIFT)); - - writeReg(REG_GYR_CONFIG0, reg); - - reg = (pwr << _GYR_CONFIG1_GYR_POWER_MODE_SHIFT); - - writeReg(REG_GYR_CONFIG1, reg); + bno055_set_gyroscope_config(m_bno055, range, bw, pwr); } -#if defined(SWIGJAVA) || (JAVACALLBACK) -void BNO055::installISR(int gpio, mraa::Edge level, - jobject runnable) -{ - // delete any existing ISR and GPIO context - uninstallISR(); - - // create gpio context - m_gpioIntr = new mraa::Gpio(gpio); - - m_gpioIntr->dir(mraa::DIR_IN); - m_gpioIntr->isr(level, runnable); - -} -#else -void BNO055::installISR(int gpio, mraa::Edge level, +void BNO055::installISR(int gpio, mraa_gpio_edge_t level, void (*isr)(void *), void *arg) { - // delete any existing ISR and GPIO context - uninstallISR(); - - // create gpio context - m_gpioIntr = new mraa::Gpio(gpio); - - m_gpioIntr->dir(mraa::DIR_IN); - m_gpioIntr->isr(level, isr, arg); + if (bno055_install_isr(m_bno055, gpio, level, isr, arg)) + throw std::runtime_error(string(__FUNCTION__) + + ": bno055_install_isr() failed"); } -#endif void BNO055::uninstallISR() { - if (m_gpioIntr) - { - m_gpioIntr->isrExit(); - delete m_gpioIntr; - - m_gpioIntr = 0; - } + bno055_uninstall_isr(m_bno055); } diff --git a/src/bno055/bno055.h b/src/bno055/bno055.h new file mode 100644 index 00000000..e4c86247 --- /dev/null +++ b/src/bno055/bno055.h @@ -0,0 +1,676 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016 Intel Corporation. + * + * The MIT License + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +#include +#include +#include +#include + +#include +#include + +#include "bno055_regs.h" + +#define BNO055_DEFAULT_I2C_BUS 0 +#define BNO055_DEFAULT_ADDR 0x28 + +#ifdef __cplusplus +extern "C" { +#endif + + /** + * @file bno055.h + * @library bno055 + * @brief C API for the bno055 driver + * + * @include bno055.c + */ + + /** + * Device context + */ + typedef struct _bno055_context { + mraa_i2c_context i2c; + mraa_gpio_context gpio; + + // always stored in C + float temperature; + + int currentPage; + BNO055_OPERATION_MODES_T currentMode; + + // uncompensated data + + // mag data + float magX; + float magY; + float magZ; + + // acc data + float accX; + float accY; + float accZ; + + // acc units + float accUnitScale; + + // gyr data + float gyrX; + float gyrY; + float gyrZ; + + // gyr units + float gyrUnitScale; + + // eul (euler angle) data + float eulHeading; + float eulRoll; + float eulPitch; + + // eul units + float eulUnitScale; + + // qua (quaternion) data + float quaW; + float quaX; + float quaY; + float quaZ; + + // lia (linear acceleration) data + float liaX; + float liaY; + float liaZ; + + // grv (gravity vector) data + float grvX; + float grvY; + float grvZ; + } *bno055_context; + + /** + * BNO055 initialization. + * + * By default, this function sets the acceleration units to m/s^2, + * gyro and Euler units to degrees, and temperature to celsius. + * It then enters the NDOF fusion mode. + * + * In addition, the internal clock is used so that compatibility + * with other implementations is assured. If you are using a + * device with an external clock, call setClockExternal(true) to + * enable it. + * + * @param bus I2C bus to use. + * @param address The I2C address for this device. + * @return The device context, or NULL if an error occurred. + */ + bno055_context bno055_init(int bus, uint8_t addr); + + /** + * BNO055 close function. + * + * @param dev The device context. + */ + void bno055_close(bno055_context dev); + + /** + * Update the internal stored values from sensor data. + * + * @param dev The device context. + * @return UPM result. + */ + upm_result_t bno055_update(const bno055_context dev); + + /** + * Return the chip ID. + * + * @param dev The device context. + * @return The chip ID (BNO055_CHIPID). + */ + uint8_t bno055_get_chip_id(const bno055_context dev); + + /** + * Return the accelerometer chip ID. + * + * @param dev The device context. + * @return The chip ID. + */ + uint8_t bno055_get_acc_id(const bno055_context dev); + + /** + * Return the magnetometer chip ID. + * + * @param dev The device context. + * @return The chip ID. + */ + uint8_t bno055_get_mag_id(const bno055_context dev); + + /** + * Return the gyroscope chip ID. + * + * @param dev The device context. + * @return The chip ID. + */ + uint8_t bno055_get_gyr_id(const bno055_context dev); + + /** + * Return the fusion firmware revison. + * + * @param dev The device context. + * @return The firmware revison. + */ + uint16_t bno055_get_sw_revision(const bno055_context dev); + + /** + * Return the bootloader ID. + * + * @param dev The device context. + * @return The bootloader ID. + */ + uint8_t bno055_get_bootloader_id(const bno055_context dev); + + /** + * Enable or disables the use of the external clock. The Adafriut + * device does contain an external clock which might be more + * stable. By default, the internal clock is used. + * + * @param dev The device context. + * @param extClock true to use external clock, false otherwise. + */ + void bno055_set_clock_external(const bno055_context dev, bool extClock); + + /** + * Select the temperature source. This can be the accelerometer + * or the gyroscope. By default, the accelerometer temperature is + * used as the source. + * + * @param dev The device context. + * @param src One of the TEMP_SOURCES_T values. + */ + void bno055_set_temperature_source(const bno055_context dev, + BNO055_TEMP_SOURCES_T src); + + /** + * Set the temperature units of the device to Celsius (always). + * + * @param dev The device context. + */ + void bno055_set_temperature_units_celsius(const bno055_context dev); + + /** + * Set the operating mode for the device. This places the device + * into a config mode, one of 7 non-fusion modes, or one of 5 + * fusion modes. All stored sensor data is cleared when switching + * modes. The device must be in config mode for most + * configuration operations. See the datasheet for details. + * + * @param dev The device context. + * @param mode One of the OPERATION_MODES_T values. + */ + void bno055_set_operation_mode(const bno055_context dev, + BNO055_OPERATION_MODES_T mode); + + /** + * Reboot the sensor. This is equivalent to a power on reset. + * All calibration data will be lost, and the device must be + * re-calibrated. + * + * @param dev The device context. + */ + void bno055_reset_system(const bno055_context dev); + + /** + * Read the calibration status registers and return them. The + * values range from 0 (uncalibrated) to 3 (fully calibrated). + * + * @param dev The device context. + * @param mag The calibration status of the magnetometer. + * @param acc The calibration status of the accelerometer. + * @param mag The calibration status of the gyroscope. + * @param mag The calibration status of the overall system. + */ + void bno055_get_calibration_status(const bno055_context dev, + int *mag, int *acc, + int *gyr, int *sys); + + /** + * Read the calibration status registers and return true or false, + * indicating whether all of the calibration parameters are fully + * calibrated. + * + * @param dev The device context. + * @return true if all 4 calibration parameters are fully + * calibrated, else false. + */ + bool bno055_is_fully_calibrated(const bno055_context dev); + + /** + * Read the calibration data and place it into a buffer. The + * buffer must be BNO055_CALIBRATION_DATA_SIZE bytes in size. + * This data can then be saved for later reuse by + * bno055_write_calibration_data() to restore calibration data + * after a reset. Note: bno055_is_fully_calibrated() (calibration + * is complete) must be true or an error will result. + * + * @param dev The device context. + * @param data A pointer to a buffer to hold the calibration data. + * This buffer must be BNO055_CALIBRATION_DATA_SIZE bytes in + * length. + * @param len The length of the buffer. An error will be returned + * if the length is not equal to BNO055_CALIBRATION_DATA_SIZE. + * @return UPM result. + */ + upm_result_t bno055_read_calibration_data(const bno055_context dev, + uint8_t *data, size_t len); + + /** + * Write previously saved calibration data to the calibration + * registers. The array containing the data must be + * BNO055_CALIBRATION_DATA_SIZE bytes in size. + * + * @param dev The device context. + * @param data uint8_t array representing calibration data, as obtained + * by bno055_read_calibration_data(). + * @param len The length of the supplied buffer. An error will be + * returned if the length is not equal to BNO055_CALIBRATION_DATA_SIZE. + * @return UPM result. + */ + upm_result_t bno055_write_calibration_data(const bno055_context dev, + uint8_t *data, + size_t len); + + /** + * Return the current measured temperature. Note, this is not + * ambient temperature - this is the temperature of the selected + * source on the chip. update() must have been called prior to + * calling this method. + * + * @param dev The device context. + * @return The temperature in degrees Celsius. + */ + float bno055_get_temperature(const bno055_context dev); + + /** + * Return current orientation fusion data in the form of Euler + * Angles. By default, the returned values are in degrees. + * update() must have been called prior to calling this method. + * + * @param dev The device context. + * @param heading Pointer to a floating point value that will have + * the current heading angle placed into it. + * @param roll Pointer to a floating point value that will have + * the current roll angle placed into it. + * @param pitch Pointer to a floating point value that will have + * the current pitch angle placed into it. + */ + void bno055_get_euler_angles(const bno055_context dev, float *heading, + float *roll, float *pitch); + + /** + * Return current orientation fusion data in the form of + * Quaternions. update() must have been called prior to calling + * this method. + * + * @param dev The device context. + * @param w Pointer to a floating point value that will have + * the current w component placed into it. + * @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 bno055_get_quaternions(const bno055_context dev, float *w, float *x, + float *y, float *z); + + /** + * Return current orientation fusion data in the form of Linear + * Acceleration. By default the returned values are in meters + * per-second squared (m/s^2). update() must have been called + * prior to calling this method. + * + * @param dev The device context. + * @param x Pointer to a floating point value that will have + * the current x component placed into it. + * @param y Pointer to a floating point value that will have + * the current y component placed into it. + * @param z Pointer to a floating point value that will have + * the current z component placed into it. + */ + void bno055_get_linear_acceleration(const bno055_context dev, float *x, + float *y, float *z); + + /** + * Return current orientation fusion data in the form of a Gravity + * Vector per-axis. By default the returned values are in meters + * per-second squared (m/s^2). update() must have been called + * prior to calling this method. + * + * @param dev The device context. + * @param x Pointer to a floating point value that will have + * the current x component placed into it. + * @param y Pointer to a floating point value that will have + * the current y component placed into it. + * @param z Pointer to a floating point value that will have + * the current z component placed into it. + */ + void bno055_get_gravity_vectors(const bno055_context dev, + float *x, float *y, float *z); + + /** + * Return accelerometer data (non-fusion). In fusion modes, this + * data will be of little value. By default the returned values + * are in meters per-second squared (m/s^2). update() must have + * been called prior to calling this method. + * + * @param dev The device context. + * @param x Pointer to a floating point value that will have + * the current x component placed into it. + * @param y Pointer to a floating point value that will have + * the current y component placed into it. + * @param z Pointer to a floating point value that will have + * the current z component placed into it. + */ + void bno055_get_accelerometer(const bno055_context dev, float *x, float *y, + float *z); + + /** + * Return magnetometer data (non-fusion). In fusion modes, this + * data will be of little value. The returned values are in + * micro-teslas (uT). update() must have been called prior to + * calling this method. + * + * @param dev The device context. + * @param x Pointer to a floating point value that will have + * the current x component placed into it. + * @param y Pointer to a floating point value that will have + * the current y component placed into it. + * @param z Pointer to a floating point value that will have + * the current z component placed into it. + */ + void bno055_get_magnetometer(const bno055_context dev, float *x, float *y, + float *z); + + /** + * Return gyroscope data (non-fusion). In fusion modes, this data + * will be of little value. By default the returned values are in + * meters per-second squared (m/s^2). update() must have been + * called prior to calling this method. + * + * @param dev The device context. + * @param x Pointer to a floating point value that will have + * the current x component placed into it. + * @param y Pointer to a floating point value that will have + * the current y component placed into it. + * @param z Pointer to a floating point value that will have + * the current z component placed into it. + */ + void bno055_get_gyroscope(const bno055_context dev, + float *x, float *y, float *z); + + /** + * Set the bandwidth, range, and power modes of the accelerometer. + * In fusion modes, these values will be ignored. + * + * @param dev The device context. + * @param range One of the BNO055_ACC_RANGE_T values. + * @param bw One of the BNO055_ACC_BW_T values. + * @param pwr One of the BNO055_ACC_PWR_MODE_T values. + */ + void bno055_set_acceleration_config(const bno055_context dev, + BNO055_ACC_RANGE_T range, + BNO055_ACC_BW_T bw, + BNO055_ACC_PWR_MODE_T pwr); + + /** + * Set the output data rate, operating mode and power mode of the + * magnetometer. In fusion modes, these values will be ignored. + * + * @param dev The device context. + * @param odr One of the BNO055_MAG_ODR_T values. + * @param opr One of the BNO055_MAG_OPR_T values. + * @param pwr One of the BNO055_MAG_POWER_T values. + */ + void bno055_set_magnetometer_config(const bno055_context dev, + BNO055_MAG_ODR_T odr, + BNO055_MAG_OPR_T opr, + BNO055_MAG_POWER_T pwr); + + /** + * Set the range, bandwidth and power modes of the gyroscope. In + * fusion modes, these values will be ignored. + * + * @param dev The device context. + * @param range One of the BNO055_GYR_RANGE_T values. + * @param bw One of the BNO055_GYR_BW_T values. + * @param pwr One of the BNO055_GYR_POWER_MODE_T values. + */ + void bno055_set_gyroscope_config(const bno055_context dev, + BNO055_GYR_RANGE_T range, + BNO055_GYR_BW_T bw, + BNO055_GYR_POWER_MODE_T pwr); + + /** + * Set the unit of measurement for the accelerometer related + * sensor values. The choices are mg (milli-gravities) or meters + * per-second squared (m/s^2). The default is m/s^2. + * + * @param dev The device context. + * @param mg true for mg, false for m/s^2. + */ + void bno055_set_accelerometer_units(const bno055_context dev, bool mg); + + /** + * Set the unit of measurement for the gyroscope related sensor + * values. The choices are degrees and radians. The default is + * degrees. + * + * @param dev The device context. + * @param radians true for radians, false for degrees. + */ + void bno055_set_gyroscope_units(const bno055_context dev, bool radians); + + /** + * Set the unit of measurement for the Euler Angle related sensor + * values. The choices are degrees and radians. The default is + * degrees. + * + * @param dev The device context. + * @param radians true for radians, false for degrees. + */ + void bno055_set_euler_units(const bno055_context dev, bool radians); + + /** + * Reset all interrupt status bits and interrupt output. + * + * @param dev The device context. + */ + void bno055_reset_interrupt_status(const bno055_context dev); + + /** + * Return the interrupt status register. This is a bitmask of the + * INT_STA_BITS_T bits. + * + * @param dev The device context. + * @return a bitmask of INT_STA_BITS_T bits. + */ + uint8_t bno055_get_interrupt_status(const bno055_context dev); + + /** + * Return the interrupt enables register. This is a bitmask of the + * INT_STA_BITS_T bits. + * + * @param dev The device context. + * @return a bitmask of INT_STA_BITS_T bits currently set in the + * enable register. + */ + uint8_t bno055_get_interrupt_enable(const bno055_context dev); + + /** + * Set the interrupt enable register. This is composed of a + * bitmask of the INT_STA_BITS_T bits. + * + * @param dev The device context. + * @param enables a bitmask of INT_STA_BITS_T bits to enable + */ + void bno055_set_interrupt_enable(const bno055_context dev, + uint8_t enables); + + /** + * Return the interrupt mask register. This is a bitmask of the + * INT_STA_BITS_T bits. The interrupt mask is used to mask off + * enabled interrupts from generating a hardware interrupt. The + * interrupt status register can still be used to detect masked + * interrupts if they are enabled. + * + * @param dev The device context. + * @return a bitmask of INT_STA_BITS_T bits currently set in the + * interrupt mask register. + */ + uint8_t bno055_get_interrupt_mask(const bno055_context dev); + + /** + * Set the interrupt mask register. This is a bitmask of the + * INT_STA_BITS_T bits. The interrupt mask is used to mask off + * enabled interrupts from generating a hardware interrupt. The + * interrupt status register can still be used to detect masked + * interrupts if they are enabled. + * + * @param dev The device context. + * @param a bitmask of INT_STA_BITS_T bits to set in the interrupt + * mask register. + */ + void bno055_set_interrupt_mask(const bno055_context dev, uint8_t mask); + + /** + * Return the value of the system status register. This method + * can be used to determine the overall status of the device. + * + * @param dev The device context. + * @return One of the SYS_STATUS_T values. + */ + BNO055_SYS_STATUS_T bno055_get_system_status(const bno055_context dev); + + /** + * Return the value of the system error register. This mathod can + * be used to determine a variety of system related error + * conditions. + * + * @param dev The device context. + * @return One of the SYS_ERR_T values. + */ + BNO055_SYS_ERR_T bno055_get_system_error(const bno055_context dev); + + /** + * install an interrupt handler. + * + * @param dev The device context. + * @param gpio The GPIO pin to use as interrupt pin. + * @param level The interrupt trigger level (one of mraa_gpio_edge_t + * values). Make sure that you have configured the interrupt pin + * properly (on the device) for whatever level method you choose. + * @param isr The interrupt handler, accepting a void * argument. + * @param arg The argument to pass the the interrupt handler. + * @return UPM result. + */ + upm_result_t bno055_install_isr(const bno055_context dev, + int gpio, mraa_gpio_edge_t level, + void (*isr)(void *), void *arg); + + /** + * uninstall a previously installed interrupt handler + * + * @param dev The device context. + */ + void bno055_uninstall_isr(const bno055_context dev); + + /** + * Set the current internal device register page. This is a low + * level function and should not be used unless you know what you + * are doing. + * + * @param dev The device context. + * @param page The page number to set. This can only be 0 or 1. + * @param force If true, force the device page state to match + * indicated internal page state regardless of current state. + * @return UPM result. + */ + upm_result_t bno055_set_page(const bno055_context dev, uint8_t page, + bool force); + + /** + * Read a register. This is a low level function and should not + * be used unless you know what you are doing. + * + * @param dev The device context. + * @param reg The register to read + * @return The value of the register + */ + uint8_t bno055_read_reg(const bno055_context dev, uint8_t reg); + + /** + * Read contiguous registers into a buffer. This is a low level + * function and should not be used unless you know what you are + * doing. + * + * @param dev The device context. + * @param buffer The buffer to store the results + * @param len The number of registers to read + * @return UPM result. + */ + upm_result_t bno055_read_regs(const bno055_context dev, uint8_t reg, + uint8_t *buffer, size_t len); + + /** + * Write to a register. This is a low level function and should + * not be used unless you know what you are doing. + * + * @param dev The device context. + * @param reg The register to write to + * @param val The value to write + * @return UPM result. + */ + upm_result_t bno055_write_reg(const bno055_context dev, + uint8_t reg, uint8_t val); + + /** + * Write data to contiguous registers. This is a low level + * function and should not be used unless you know what you are + * doing. + * + * @param dev The device context. + * @param reg The starting register to write to + * @param buffer The buffer containing the data to write + * @param len The number of bytes to write + * @return UPM result. + */ + upm_result_t bno055_write_regs(const bno055_context dev, uint8_t reg, + uint8_t *buffer, size_t len); + +#ifdef __cplusplus +} +#endif diff --git a/src/bno055/bno055.hpp b/src/bno055/bno055.hpp index f22a016f..3e1ddc8a 100644 --- a/src/bno055/bno055.hpp +++ b/src/bno055/bno055.hpp @@ -1,6 +1,8 @@ /* * Author: Jon Trulson - * Copyright (c) 2016 Intel Corporation. + * Copyright (c) 2016-2017 Intel Corporation. + * + * The MIT License * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -23,1486 +25,660 @@ */ #pragma once -#include -#include -#include - -#define BNO055_I2C_BUS 0 -#define BNO055_DEFAULT_ADDR 0x28 +#include +#include "bno055.h" namespace upm { - /** - * @brief BNO055 Absolute Orientation 9DOF Fusion Hub - * @defgroup bno055 libupm-bno055 - * @ingroup i2c gpio accelerometer compass - */ - - /** - * @library bno055 - * @sensor bno055 - * @comname Intelligent 9-axis Absolute Orientation Sensor - * @type accelerometer compass - * @man adafruit - * @con i2c gpio - * @web https://www.adafruit.com/products/2472 - * - * @brief API for the BNO055 Absolute Orientation 9DOF Fusion Hub - * - * The BNO055 is a System in Package (SiP), integrating a triaxial - * 14-bit accelerometer, a triaxial 16-bit gyroscope with a range of - * +/- 2000 degrees per second, a triaxial geomagnetic sensor and a - * 32-bit cortex M0+ microcontroller running Bosch Sensortec sensor - * fusion software, in a single package. - * - * This sensor handles the hard problem of combining various sensor - * information into a reliable measurement of sensor orientation - * (refered to as 'sensor fusion'). The onboard MCU runs this - * software and can provide fusion output in the form of Euler - * Angles, Quaternions, Linear Acceleration, and Gravity Vectors in - * 3 axes. - * - * The focus on this driver has been on supporting the fusion - * components. Less support is available for use of this device as - * a generic accelerometer, gyroscope and magnetometer, however - * enough infrastructure is available to add any missing - * functionality. - * - * This device requires calibration in order to operate accurately. - * Methods are provided to retrieve calibration data (once - * calibrated) to be stored somewhere else, like in a file. A - * method is provided to load this data as well. Calibration data - * is lost on a power cycle. See one of the examples for a - * description of how to calibrate the device, but in essence: - * - * There is a calibration status register available - * (getCalibrationStatus()) that returns the calibration status of - * the accelerometer (ACC), magnetometer (MAG), gyroscope (GYR), and - * overall system (SYS). Each of these values range from 0 - * (uncalibrated) to 3 (fully calibrated). Calibration involves - * certain motions to get all 4 values at 3. The motions are as - * follows (though see the datasheet for more information): - * - * GYR: Simply let the sensor sit flat for a few seconds. - * - * ACC: Move the sensor in various positions. Start flat, then - * rotate slowly by 45 degrees, hold for a few seconds, then - * continue rotating another 45 degrees and hold, etc. 6 or more - * movements of this type may be required. You can move through any - * axis you desire, but make sure that the device is lying at least - * once perpendicular to the x, y, and z axis. - * - * MAG: Move slowly in a figure 8 pattern in the air, until the - * calibration values reaches 3. - * - * SYS: This will usually reach 3 when the other items have also - * reached 3. If not, continue slowly moving the device though - * various axes until it does. - * - * @snippet bno055.cxx Interesting - */ - - class BNO055 { - public: - // The chip ID, for verification in the ctor. - const uint8_t BNO055_CHIPID = 0xa0; - - // number of bytes of stored calibration data - const int calibrationDataNumBytes = 22; - - // NOTE: Reserved registers should not be written into. Reading - // from them will return indeterminate values. - // - // The register map is divided into two pages - page 1 contains - // sensor specific configuration registers, and page 0 contains all - // other configuration data and sensor output registers. - /** - * BNO055 registers + * @brief BNO055 Absolute Orientation 9DOF Fusion Hub + * @defgroup bno055 libupm-bno055 + * @ingroup i2c gpio accelerometer compass */ - typedef enum : uint8_t { - // The first register listed here is the page ID register. It - // is the same on both pages, and selects or indicates the - // currently active register page. - - REG_PAGE_ID = 0x07, - - // Page 0 - REG_CHIP_ID = 0x00, - REG_ACC_ID = 0x01, // accel id - REG_MAG_ID = 0x02, // mag id - REG_GYR_ID = 0x03, // gyro id - REG_SW_REV_ID_LSB = 0x04, - REG_SW_REV_ID_MSB = 0x05, - REG_BL_REV_ID = 0x06, // bootloader rev - - // REG_PAGE_ID = 0x07 - - REG_ACC_DATA_X_LSB = 0x08, - REG_ACC_DATA_X_MSB = 0x09, - REG_ACC_DATA_Y_LSB = 0x0a, - REG_ACC_DATA_Y_MSB = 0x0b, - REG_ACC_DATA_Z_LSB = 0x0c, - REG_ACC_DATA_Z_MSB = 0x0d, - - REG_MAG_DATA_X_LSB = 0x0e, - REG_MAG_DATA_X_MSB = 0x0f, - REG_MAG_DATA_Y_LSB = 0x10, - REG_MAG_DATA_Y_MSB = 0x11, - REG_MAG_DATA_Z_LSB = 0x12, - REG_MAG_DATA_Z_MSB = 0x13, - - REG_GYR_DATA_X_LSB = 0x14, - REG_GYR_DATA_X_MSB = 0x15, - REG_GYR_DATA_Y_LSB = 0x16, - REG_GYR_DATA_Y_MSB = 0x17, - REG_GYR_DATA_Z_LSB = 0x18, - REG_GYR_DATA_Z_MSB = 0x19, - - // euler angles - REG_EUL_HEADING_LSB = 0x1a, - REG_EUL_HEADING_MSB = 0x1b, - REG_EUL_ROLL_LSB = 0x1c, - REG_EUL_ROLL_MSB = 0x1d, - REG_EUL_PITCH_LSB = 0x1e, - REG_EUL_PITCH_MSB = 0x1f, - - // Quaternions - REG_QUA_DATA_W_LSB = 0x20, - REG_QUA_DATA_W_MSB = 0x21, - REG_QUA_DATA_X_LSB = 0x22, - REG_QUA_DATA_X_MSB = 0x23, - REG_QUA_DATA_Y_LSB = 0x24, - REG_QUA_DATA_Y_MSB = 0x25, - REG_QUA_DATA_Z_LSB = 0x26, - REG_QUA_DATA_Z_MSB = 0x27, - - // linear accel data - REG_LIA_DATA_X_LSB = 0x28, - REG_LIA_DATA_X_MSB = 0x29, - REG_LIA_DATA_Y_LSB = 0x2a, - REG_LIA_DATA_Y_MSB = 0x2b, - REG_LIA_DATA_Z_LSB = 0x2c, - REG_LIA_DATA_Z_MSB = 0x2d, - - // gravity vector - REG_GRV_DATA_X_LSB = 0x2e, - REG_GRV_DATA_X_MSB = 0x2f, - REG_GRV_DATA_Y_LSB = 0x30, - REG_GRV_DATA_Y_MSB = 0x31, - REG_GRV_DATA_Z_LSB = 0x32, - REG_GRV_DATA_Z_MSB = 0x33, - - REG_TEMPERATURE = 0x34, - - REG_CALIB_STAT = 0x35, // calibration status - REG_ST_RESULT = 0x36, // selftest result - - REG_INT_STA = 0x37, // interrupt status - - REG_SYS_CLK_STATUS = 0x38, - - REG_SYS_STATUS = 0x39, - REG_SYS_ERROR = 0x3a, - - REG_UNIT_SEL = 0x3b, - - // 0x3c reserved - - REG_OPER_MODE = 0x3d, // operating mode - REG_POWER_MODE = 0x3e, - - REG_SYS_TRIGGER = 0x3f, - REG_TEMP_SOURCE = 0x40, // temperature src - - REG_AXIS_MAP_CONFIG = 0x41, - REG_AXIS_MAP_SIGN = 0x42, - - // 0x43-0x54 reserved - - // stored configuration data - REG_ACC_OFFSET_X_LSB = 0x55, - REG_ACC_OFFSET_X_MSB = 0x56, - REG_ACC_OFFSET_Y_LSB = 0x57, - REG_ACC_OFFSET_Y_MSB = 0x58, - REG_ACC_OFFSET_Z_LSB = 0x59, - REG_ACC_OFFSET_Z_MSB = 0x5a, - - REG_MAG_OFFSET_X_LSB = 0x5b, - REG_MAG_OFFSET_X_MSB = 0x5c, - REG_MAG_OFFSET_Y_LSB = 0x5d, - REG_MAG_OFFSET_Y_MSB = 0x5e, - REG_MAG_OFFSET_Z_LSB = 0x5f, - REG_MAG_OFFSET_Z_MSB = 0x60, - - REG_GYR_OFFSET_X_LSB = 0x61, - REG_GYR_OFFSET_X_MSB = 0x62, - REG_GYR_OFFSET_Y_LSB = 0x63, - REG_GYR_OFFSET_Y_MSB = 0x64, - REG_GYR_OFFSET_Z_LSB = 0x65, - REG_GYR_OFFSET_Z_MSB = 0x66, - - REG_ACC_RADIUS_LSB = 0x67, - REG_ACC_RADIUS_MSB = 0x68, - - REG_MAG_RADIUS_LSB = 0x69, - REG_MAG_RADIUS_MSB = 0x6a, - - // 0x6b-0x7f reserved - // end of page 0 - - // Page 1 - - // 0x00-0x06 reserved - // 0x07 - page id - - REG_ACC_CONFIG = 0x08, - REG_MAG_CONFIG = 0x09, - REG_GYR_CONFIG0 = 0x0a, - REG_GYR_CONFIG1 = 0x0b, - REG_ACC_SLEEP_CONFIG = 0x0c, - REG_GYR_SLEEP_CONFIG = 0x0d, - - // 0x0e reserved - REG_INT_MSK = 0x0f, - REG_INT_EN = 0x10, - - REG_ACC_AM_THRES = 0x11, - REG_ACC_INT_SETTINGS = 0x12, - REG_ACC_HG_DURATION = 0x13, - REG_ACC_HG_THRES = 0x14, - REG_ACC_NM_THRES = 0x15, - REG_ACC_NM_SET = 0x16, - - REG_GYR_INT_SETTING = 0x17, - REG_GYR_HR_X_SET = 0x18, - REG_GYR_DUR_X = 0x19, - REG_GYR_HR_Y_SET = 0x1a, - REG_GYR_DUR_Y = 0x1b, - REG_GYR_HR_Z_SET = 0x1c, - REG_GYR_DUR_Z = 0x1d, - REG_GYR_AM_THRES = 0x1e, - REG_GYR_AM_SET = 0x1f, - - // 0x20-0x4f reserved - - // 16 byte (0x50-0x5f) unique ID - REG_BNO_UNIQUE_ID = 0x50 - - // 0x60-0x7f reserved - } REGS_T; - - // Page 0 register enumerants /** - * REG_CALIB_STAT bits - */ - typedef enum { - CALIB_STAT_MAG0 = 0x01, - CALIB_STAT_MAG1 = 0x02, - _CALIB_STAT_MAG_MASK = 3, - _CALIB_STAT_MAG_SHIFT = 0, - - CALIB_STAT_ACC0 = 0x04, - CALIB_STAT_ACC1 = 0x08, - _CALIB_STAT_ACC_MASK = 3, - _CALIB_STAT_ACC_SHIFT = 2, - - CALIB_STAT_GYR0 = 0x10, - CALIB_STAT_GYR1 = 0x20, - _CALIB_STAT_GYR_MASK = 3, - _CALIB_STAT_GYR_SHIFT = 4, - - CALIB_STAT_SYS0 = 0x40, - CALIB_STAT_SYS1 = 0x80, - _CALIB_STAT_SYS_MASK = 3, - _CALIB_STAT_SYS_SHIFT = 6 - } CALIB_STAT_BITS_T; - - /** - * REG_ST_RESULT bits - */ - typedef enum { - ST_RESULT_ACC = 0x01, - ST_RESULT_MAG = 0x02, - ST_RESULT_GYR = 0x04, - ST_RESULT_MCU = 0x08 - // 0x10-0x80 reserved - } ST_RESULT_BITS_T; - - /** - * REG_INT_STA bits - */ - typedef enum { - // 0x01-0x02 reserved - INT_STA_GYRO_AM = 0x04, // gyro any-motion - INT_STA_GYR_HIGH_RATE = 0x08, - // 0x010 reserved - INT_STA_ACC_HIGH_G = 0x20, - INT_STA_ACC_AM = 0x40, // accel any-motion - INT_STA_ACC_NM = 0x80 // accel no-motion - } INT_STA_BITS_T; - - /** - * REG_SYS_CLK_STATUS bits - */ - typedef enum { - SYS_CLK_STATUS_ST_MAIN_CLK = 0x01 - // 0x02-0x80 reserved - } SYS_CLK_STATUS_BITS_T; - - /** - * REG_SYS_STATUS values - */ - typedef enum { - SYS_STATUS_IDLE = 0, - SYS_STATUS_SYS_ERR = 1, - SYS_STATUS_INIT_PERIPHERALS = 2, - SYS_STATUS_SYSTEM_INIT = 3, - SYS_STATUS_EXECUTING_SELFTEST = 4, - SYS_STATUS_FUSION_RUNNING = 5, - SYS_STATUS_NO_FUSION_RUNNING = 6 - } SYS_STATUS_T; - - /** - * REG_SYS_ERR values - */ - typedef enum { - SYS_ERR_NOERROR = 0, - SYS_ERR_PERIPH_INIT_ERROR = 1, - SYS_ERR_SYS_INIT_ERROR = 2, - SYS_ERR_SELFTEST_FAIL_ERROR = 3, - SYS_ERR_REG_VAL_OUTOFRANGE_ERROR = 4, - SYS_ERR_REG_ADDR_OUTOFRANGE_ERROR = 5, - SYS_ERR_REG_WRITE_ERROR = 6, - SYS_ERR_LP_MODE_NOT_AVAIL_ERROR = 7, - SYS_ERR_ACC_PWR_MODE_NOT_AVAIL_ERROR = 8, - SYS_ERR_FUSION_CONFIG_ERROR = 9, - SYS_ERR_SENSOR_CONFIG_ERROR = 10 - } SYS_ERR_T; - - - /** - * REG_UNIT_SEL bits - */ - typedef enum { - UNIT_SEL_ACC_UNIT = 0x01, // 0=m/s^2, 1=mg - UNIT_SEL_GYR_UNIT = 0x02, // 0=dps, 1=rps - UNIT_SEL_EUL_UNIT = 0x04, // 0=degrees, 1=radians - // 0x08 reserved - UNIT_SEL_TEMP_UNIT = 0x10, // 0=C, 1=F - // 0x20-0x40 reserved - UNIT_SEL_ORI_ANDROID_WINDOWS = 0x80 // 0=windows orient, 1=android - } UNIT_SEL_BITS_T; - - /** - * REG_OPR_MODE bits - */ - typedef enum { - OPR_MODE_OPERATION_MODE0 = 0x01, - OPR_MODE_OPERATION_MODE1 = 0x02, - OPR_MODE_OPERATION_MODE2 = 0x04, - OPR_MODE_OPERATION_MODE3 = 0x08, - _OPR_MODE_OPERATION_MODE_MASK = 15, - _OPR_MODE_OPERATION_MODE_SHIFT = 0 - // 0x10-0x80 reserved - } OPR_MODE_BITS_T; - - /** - * OPR_MODE_OPERATION values - */ - typedef enum { - OPERATION_MODE_CONFIGMODE = 0, - OPERATION_MODE_ACCONLY = 1, - OPERATION_MODE_MAGONLY = 2, - OPERATION_MODE_GYROONLY = 3, - OPERATION_MODE_ACCMAG = 4, - OPERATION_MODE_ACCGYRO = 5, - OPERATION_MODE_MAGGYRO = 6, - OPERATION_MODE_AMG = 7, - // fusion modes - OPERATION_MODE_IMU = 8, - OPERATION_MODE_COMPASS = 9, - OPERATION_MODE_M4G = 10, - OPERATION_MODE_NDOF_FMC_OFF = 11, - OPERATION_MODE_NDOF = 12 - } OPERATION_MODES_T; - - /** - * REG_PWR_MODE bits - */ - typedef enum { - PWR_MODE_POWER_MODE0 = 0x01, - PWR_MODE_POWER_MODE1 = 0x02, - _PWR_MODE_POWER_MODE_MASK = 3, - _PWR_MODE_POWER_MODE_SHIFT = 0 - // 0x04-0x80 reserved - } PWR_MODE_BITS_T; - - /** - * POWER_MODE values - */ - typedef enum { - POWER_MODE_NORMAL = 0, - POWER_MODE_LOW = 1, - POWER_MODE_SUSPEND = 2 - } POWER_MODES_T; - - /** - * REG_SYS_TRIGGER bits - */ - typedef enum { - SYS_TRIGGER_SELF_TEST = 0x01, - // 0x02-0x10 reserved - SYS_TRIGGER_RST_SYS = 0x20, - SYS_TRIGGER_RST_INT = 0x40, - SYS_TRIGGER_CLK_SEL = 0x80 - } SYS_TRIGGER_BITS_T; - - /** - * REG_TEMP_SOURCE bits - */ - typedef enum { - TEMP_SOURCE_TEMP_SOURCE0 = 0x01, - TEMP_SOURCE_TEMP_SOURCE1 = 0x02, - _TEMP_SOURCE_TEMP_SOURCE_MASK = 3, - _TEMP_SOURCE_TEMP_SOURCE_SHIFT = 0 - // 0x04-0x80 reserved - } TEMP_SOURCE_BITS_T; - - /** - * TEMP_SOURCE values - */ - typedef enum { - TEMP_SOURCE_ACC = 0, - TEMP_SOURCE_GYR = 1 - } TEMP_SOURCES_T; - - /** - * REG_AXIS_MAP_CONFIG bits - */ - typedef enum { - AXIS_MAP_CONFIG_REMAPPED_X_VAL0 = 0x01, - AXIS_MAP_CONFIG_REMAPPED_X_VAL1 = 0x02, - _AXIS_MAP_CONFIG_REMAPPED_X_VAL_MASK = 3, - _AXIS_MAP_CONFIG_REMAPPED_X_VAL_SHIFT = 0, - - AXIS_MAP_CONFIG_REMAPPED_Y_VAL0 = 0x04, - AXIS_MAP_CONFIG_REMAPPED_Y_VAL1 = 0x08, - _AXIS_MAP_CONFIG_REMAPPED_Y_VAL_MASK = 3, - _AXIS_MAP_CONFIG_REMAPPED_Y_VAL_SHIFT = 2, - - AXIS_MAP_CONFIG_REMAPPED_Z_VAL0 = 0x10, - AXIS_MAP_CONFIG_REMAPPED_Z_VAL1 = 0x20, - _AXIS_MAP_CONFIG_REMAPPED_Z_VAL_MASK = 3, - _AXIS_MAP_CONFIG_REMAPPED_Z_VAL_SHIFT = 4 - // 0x40-0x80 reserved - } AXIS_MAP_CONFIG_BITS_T; - - /** - * REMAPPED_AXIS values, applied to X, Y, and Z axes - * (REG_AXIS_MAP_CONFIG) - */ - typedef enum { - REMAPPED_AXIS_X = 0, - REMAPPED_AXIS_Y = 1, - REMAPPED_AXIS_Z = 2 - } REMAPPED_AXIS_T; - - - /** - * REG_AXIS_MAP_SIGN bits - */ - typedef enum { - AXIS_MAP_SIGN_REMAPPED_Z_SIGN = 0x01, - AXIS_MAP_SIGN_REMAPPED_Y_SIGN = 0x02, - AXIS_MAP_SIGN_REMAPPED_X_SIGN = 0x04 - // 0x08-0x80 reserved - } AXIS_MAP_SIGN_BITS_T; - - // Page 1 register enumerants - - /** - * REG_ACC_CONFIG bits - */ - typedef enum { - ACC_CONFIG_ACC_RANGE0 = 0x01, - ACC_CONFIG_ACC_RANGE1 = 0x02, - _ACC_CONFIG_ACC_RANGE_MASK = 3, - _ACC_CONFIG_ACC_RANGE_SHIFT = 0, - - ACC_CONFIG_ACC_BW0 = 0x04, - ACC_CONFIG_ACC_BW1 = 0x08, - ACC_CONFIG_ACC_BW2 = 0x10, - _ACC_CONFIG_ACC_BW_MASK = 7, - _ACC_CONFIG_ACC_BW_SHIFT = 2, - - ACC_CONFIG_ACC_PWR_MODE0 = 0x20, - ACC_CONFIG_ACC_PWR_MODE1 = 0x40, - ACC_CONFIG_ACC_PWR_MODE2 = 0x80, - _ACC_CONFIG_ACC_PWR_MODE_MASK = 7, - _ACC_CONFIG_ACC_PWR_MODE_SHIFT = 5 - } ACC_CONFIG_BITS_T; - - /** - * ACC_CONFIG_ACC_RANGE values - */ - typedef enum { - ACC_RANGE_2G = 0, - ACC_RANGE_4G = 1, - ACC_RANGE_8G = 2, - ACC_RANGE_16G = 3 - } ACC_RANGE_T; - - /** - * ACC_CONFIG_ACC_BW values - */ - typedef enum { - ACC_BW_7_81 = 0, // 7.81 Hz - ACC_BW_15_53 = 1, - ACC_BW_31_25 = 2, - ACC_BW_62_5 = 3, - ACC_BW_125 = 4, // 125 Hz - ACC_BW_250 = 5, - ACC_BW_500 = 6, - ACC_BW_1000 = 7 - } ACC_BW_T; - - /** - * ACC_PWR_MODE values - */ - typedef enum { - ACC_PWR_MODE_NORMAL = 0, - ACC_PWR_MODE_SUSPEND = 1, - ACC_PWR_MODE_LOWPOWER1 = 2, - ACC_PWR_MODE_STANDBY = 3, - ACC_PWR_MODE_LOWPOWER2 = 4, - ACC_PWR_MODE_DEEPSUSPEND = 5 - } ACC_PWR_MODE_T; - - /** - * REG_MAG_CONFIG bits - */ - typedef enum { - MAG_CONFIG_MAG_ODR0 = 0x01, - MAG_CONFIG_MAG_ODR1 = 0x02, - MAG_CONFIG_MAG_ODR2 = 0x04, - _MAG_CONFIG_MAG_ODR_MASK = 7, - _MAG_CONFIG_MAG_ODR_SHIFT = 0, - - MAG_CONFIG_MAG_OPR_MODE0 = 0x08, - MAG_CONFIG_MAG_OPR_MODE1 = 0x10, - _MAG_CONFIG_MAG_OPR_MODE_MASK = 3, - _MAG_CONFIG_MAG_OPR_MODE_SHIFT = 3, - - MAG_CONFIG_MAG_POWER_MODE0 = 0x20, - MAG_CONFIG_MAG_POWER_MODE1 = 0x40, - _MAG_CONFIG_MAG_POWER_MODE_MASK = 3, - _MAG_CONFIG_MAG_POWER_MODE_SHIFT = 5 - // 0x80 reserved - } MAG_CONFIG_BITS_T; - - /** - * MAG_ODR values - */ - typedef enum { - MAG_ODR_2 = 0, // 2Hz - MAG_ODR_6 = 1, - MAG_ODR_8 = 2, - MAG_ODR_10 = 3, - MAG_ODR_15 = 4, - MAG_ODR_20 = 5, - MAG_ODR_25 = 6, - MAG_ODR_30 = 7 - } MAG_ODR_T; - - /** - * MAG_OPR values - */ - typedef enum { - MAG_OPR_LOW = 0, // low power - MAG_OPR_REGULAR = 1, - MAG_OPR_ENHANCED_REGULAR = 2, - MAG_OPR_HIGH_ACCURACY = 3 - } MAG_OPR_T; - - /** - * MAG_POWER values - */ - typedef enum { - MAG_POWER_NORMAL = 0, - MAG_POWER_SLEEP = 1, - MAG_POWER_SUSPEND = 2, - MAG_POWER_FORCE_MODE = 3 - } MAG_POWER_T; - - /** - * REG_GYR_CONFIG0 bits - */ - typedef enum { - GYR_CONFIG0_GYR_RANGE0 = 0x01, - GYR_CONFIG0_GYR_RANGE1 = 0x02, - GYR_CONFIG0_GYR_RANGE2 = 0x04, - _GYR_CONFIG0_GYR_RANGE_MASK = 7, - _GYR_CONFIG0_GYR_RANGE_SHIFT = 0, - - GYR_CONFIG0_GYR_BW0 = 0x08, - GYR_CONFIG0_GYR_BW1 = 0x10, - GYR_CONFIG0_GYR_BW2 = 0x20, - _GYR_CONFIG0_GYR_BW_MASK = 7, - _GYR_CONFIG0_GYR_BW_SHIFT = 3 - // 0x40-0x80 reserved - } GYR_CONFIG0_BITS_T; - - /** - * GYR_RANGE values - */ - typedef enum { - GYR_RANGE_2000 = 0, // degrees/sec - GYR_RANGE_1000 = 1, - GYR_RANGE_500 = 2, - GYR_RANGE_250 = 3, - GYR_RANGE_125 = 4 - } GYR_RANGE_T; - - /** - * GYR_BW values - */ - typedef enum { - GYR_BW_523 = 0, // Hz - GYR_BW_230 = 1, - GYR_BW_116 = 2, - GYR_BW_47 = 3, - GYR_BW_23 = 4, - GYR_BW_12 = 5, - GYR_BW_64 = 6, - GYR_BW_32 = 7 - } GYR_BW_T; - - /** - * REG_GYR_CONFIG1 bits - */ - typedef enum { - GYR_CONFIG1_GYR_POWER_MODE0 = 0x01, - GYR_CONFIG1_GYR_POWER_MODE1 = 0x02, - GYR_CONFIG1_GYR_POWER_MODE2 = 0x04, - _GYR_CONFIG1_GYR_POWER_MODE_MASK = 7, - _GYR_CONFIG1_GYR_POWER_MODE_SHIFT = 0 - // 0x08-0x80 reserved - } GYR_CONFIG1_BITS_T; - - /** - * GYR_POWER_MODE values - */ - typedef enum { - GYR_POWER_MODE_NORMAL = 0, - GYR_POWER_MODE_FAST_POWERUP = 1, - GYR_POWER_MODE_DEEP_SUSPEND = 2, - GYR_POWER_MODE_SUSPEND = 3, - GYR_POWER_MODE_ADVANCED_POWERSAVE= 4 - } GYR_POWER_MODE_T; - - /** - * REG_ACC_SLEEP_CONFIG bits - */ - typedef enum { - ACC_SLEEP_CONFIG_SLP_MODE = 0x01, // 0=event, 1=equidistant sample - - ACC_SLEEP_CONFIG_ACC_SLP_DUR0 = 0x02, - ACC_SLEEP_CONFIG_ACC_SLP_DUR1 = 0x04, - ACC_SLEEP_CONFIG_ACC_SLP_DUR2 = 0x08, - ACC_SLEEP_CONFIG_ACC_SLP_DUR3 = 0x10, - _ACC_SLEEP_CONFIG_ACC_SLP_DUR_MASK = 15, - _ACC_SLEEP_CONFIG_ACC_SLP_DUR_SHIFT = 1 - // 0x20-0x80 reserved - } ACC_SLEEP_CONFIG_BITS_T; - - /** - * ACC_SLP_DUR values - */ - typedef enum { - ACC_SLP_DUR_0_5 = 0, // 0.5ms - // same for 1-5 - - ACC_SLP_DUR_1 = 6, // 1ms - ACC_SLP_DUR_2 = 7, - ACC_SLP_DUR_4 = 8, - ACC_SLP_DUR_6 = 9, - ACC_SLP_DUR_10 = 10, - ACC_SLP_DUR_25 = 11, - ACC_SLP_DUR_50 = 12, - ACC_SLP_DUR_100 = 13, - ACC_SLP_DUR_500 = 14 - // 15 = 1ms - } ACC_SLP_DUR_T; - - /** - * REG_GYR_SLEEP_CONFIG bits - */ - typedef enum { - GYR_SLEEP_CONFIG_GYR_SLEEP_DUR0 = 0x01, - GYR_SLEEP_CONFIG_GYR_SLEEP_DUR1 = 0x02, - GYR_SLEEP_CONFIG_GYR_SLEEP_DUR2 = 0x04, - _GYR_SLEEP_CONFIG_GYR_SLEEP_DUR_MASK = 7, - _GYR_SLEEP_CONFIG_GYR_SLEEP_DUR_SHIFT = 0, - - GYR_SLEEP_CONFIG_GYR_AUTO_SLP_DUR0 = 0x08, - GYR_SLEEP_CONFIG_GYR_AUTO_SLP_DUR1 = 0x10, - GYR_SLEEP_CONFIG_GYR_AUTO_SLP_DUR2 = 0x20, - _GYR_SLEEP_CONFIG_GYR_AUTO_SLP_DUR_MASK = 7, - _GYR_SLEEP_CONFIG_GYR_AUTO_SLP_DUR_SHIFT = 3 - // 0x40-0x80 reserved - } GYR_SLEEP_CONFIG_BITS_T; - - /** - * GYR_SLEEP_DUR values - */ - typedef enum { - GYR_SLEEP_DUR_2 = 0, // 2ms - GYR_SLEEP_DUR_4 = 1, - GYR_SLEEP_DUR_5 = 2, - GYR_SLEEP_DUR_8 = 3, - GYR_SLEEP_DUR_10 = 4, - GYR_SLEEP_DUR_15 = 5, - GYR_SLEEP_DUR_18 = 6, - GYR_SLEEP_DUR_20 = 7 - } GYR_SLEEP_DUR_T; - - /** - * GYR_AUTO_SLP_DUR values - */ - typedef enum { - // 0 = illegal - GYR_AUTO_SLP_DUR_4 = 1, // ms - GYR_AUTO_SLP_DUR_5 = 2, - GYR_AUTO_SLP_DUR_8 = 3, - GYR_AUTO_SLP_DUR_10 = 4, - GYR_AUTO_SLP_DUR_15 = 5, - GYR_AUTO_SLP_DUR_20 = 6, - GYR_AUTO_SLP_DUR_40 = 7 - } GYR_AUTO_SLP_DUR_T; - - /** - * REG_INT_MSK and REG_INT_EN bits - */ - typedef enum { - // 0x00-0x02 reserved - INT_GYRO_AM = 0x04, // gyro any-motion - INT_GYRO_HIGH_RATE = 0x08, - // 0x10 reserved - INT_ACC_HIGH_G = 0x20, - INT_ACC_AM = 0x40, // acc any-motion - INT_ACC_NM = 0x80, // acc no-motion - } INT_BITS_T; - - /** - * REG_ACC_INT_SETTINGS bits - */ - typedef enum { - ACC_INT_SETTINGS_AM_DUR0 = 0x01, - ACC_INT_SETTINGS_AM_DUR1 = 0x02, - _ACC_INT_SETTINGS_AM_DUR_MASK = 3, - _ACC_INT_SETTINGS_AM_DUR_SHIFT = 0, - - ACC_INT_SETTINGS_AM_NM_X_AXIS = 0x04, - ACC_INT_SETTINGS_AM_NM_Y_AXIS = 0x08, - ACC_INT_SETTINGS_AM_NM_Z_AXIS = 0x10, - - ACC_INT_SETTINGS_HG_X_AXIS = 0x20, - ACC_INT_SETTINGS_HG_Y_AXIS = 0x40, - ACC_INT_SETTINGS_HG_Z_AXIS = 0x80 - } ACC_INT_SETTINGS_BITS_T; - - /** - * REG_ACC_NM_SET bits - */ - typedef enum { - ACC_NM_SET_SM_NM = 0x01, // 0=slowmotion, 1=nomotion - - ACC_NM_SET_SM_NM_DUR0 = 0x02, - ACC_NM_SET_SM_NM_DUR1 = 0x04, - ACC_NM_SET_SM_NM_DUR2 = 0x08, - ACC_NM_SET_SM_NM_DUR3 = 0x10, - ACC_NM_SET_SM_NM_DUR4 = 0x20, - ACC_NM_SET_SM_NM_DUR5 = 0x40, - _ACC_NM_SET_SM_NM_DUR_MASK = 63, - _ACC_NM_SET_SM_NM_DUR_SHIFT = 1 - // 0x80 reserved - } ACC_NM_SET_BITS_T; - - /** - * REG_GYR_INT_SETTING bits - */ - typedef enum { - GYR_INT_SETTING_AM_X_AXIS = 0x01, - GYR_INT_SETTING_AM_Y_AXIS = 0x02, - GYR_INT_SETTING_AM_Z_AXIS = 0x04, - - GYR_INT_SETTING_HR_X_AXIS = 0x08, - GYR_INT_SETTING_HR_Y_AXIS = 0x10, - GYR_INT_SETTING_HR_Z_AXIS = 0x20, - - GYR_INT_SETTING_AM_FILT = 0x40, - GYR_INT_SETTING_HR_FILT = 0x80 - } GYR_INT_SETTING_BITS_T; - - /** - * REG_GYR_HR_X_SET, REG_GYR_HR_Y_SET, and REG_GYR_HR_Z_SET bits - */ - typedef enum { - GYR_HR_XYZ_SET_HR_THRESH0 = 0x01, - GYR_HR_XYZ_SET_HR_THRESH1 = 0x02, - GYR_HR_XYZ_SET_HR_THRESH2 = 0x04, - GYR_HR_XYZ_SET_HR_THRESH3 = 0x08, - GYR_HR_XYZ_SET_HR_THRESH4 = 0x10, - _GYR_HR_XYZ_SET_HR_THRESH_MASK = 31, - _GYR_HR_XYZ_SET_HR_THRESH_SHIFT = 0, - - GYR_HR_XYZ_SET_HR_THRESH_HYST0 = 0x20, - GYR_HR_XYZ_SET_HR_THRESH_HYST1 = 0x40, - _GYR_HR_XYZ_SET_HR_THRESH_HYST_MASK = 3, - _GYR_HR_XYZ_SET_HR_THRESH_HYST_SHIFT = 5 - } GYR_HR_XYZ_SET_BITS_T; - - /** - * REG_GYR_AM_SET bits - */ - typedef enum { - GYR_AM_SET_SLOPE_SAMPLES0 = 0x01, - GYR_AM_SET_SLOPE_SAMPLES1 = 0x02, - _GYR_AM_SET_SLOPE_SAMPLES_MASK = 3, - _GYR_AM_SET_SLOPE_SAMPLES_SHIFT = 0, - - GYR_AM_SET_AWAKE_DUR0 = 0x04, - GYR_AM_SET_AWAKE_DUR1 = 0x08, - _GYR_AM_SET_AWAKE_DUR_MASK = 3, - _GYR_AM_SET_AWAKE_DUR_SHIFT = 2 - - // 0x10-0x80 reserved - } GYR_AM_SET_BITS_T; - - /** - * GYR_AM_SET_SLOPE_SAMPLES values - */ - typedef enum { - SLOPE_SAMPLES_8 = 0, // 8 samples - SLOPE_SAMPLES_16 = 1, - SLOPE_SAMPLES_32 = 2, - SLOPE_SAMPLES_64 = 3 - } SLOPE_SAMPLES_T; - - /** - * BNO055 constructor. + * @library bno055 + * @sensor bno055 + * @comname Intelligent 9-axis Absolute Orientation Sensor + * @type accelerometer compass + * @man adafruit + * @con i2c gpio + * @web https://www.adafruit.com/products/2472 * - * By default, the constructor sets the acceleration units to - * m/s^2, gyro and Euler units to degrees, and temperature to - * celsius. It then enters the NDOF fusion mode. + * @brief API for the BNO055 Absolute Orientation 9DOF Fusion Hub * - * In addition, the internal clock is used so that compatibility - * with other implementations is assured. If you are using a - * device with an external clock, call setClockExternal(true) to - * enable it. + * The BNO055 is a System in Package (SiP), integrating a triaxial + * 14-bit accelerometer, a triaxial 16-bit gyroscope with a range of + * +/- 2000 degrees per second, a triaxial geomagnetic sensor and a + * 32-bit cortex M0+ microcontroller running Bosch Sensortec sensor + * fusion software, in a single package. * - * @param bus I2C bus to use. - * @param address The address for this device. - */ - BNO055(int bus=BNO055_I2C_BUS, uint8_t addr=BNO055_DEFAULT_ADDR); - - /** - * BNO055 Destructor. - */ - ~BNO055(); - - /** - * Update the internal stored values from sensor data. - */ - void update(); - - /** - * Return the chip ID. + * This sensor handles the hard problem of combining various sensor + * information into a reliable measurement of sensor orientation + * (refered to as 'sensor fusion'). The onboard MCU runs this + * software and can provide fusion output in the form of Euler + * Angles, Quaternions, Linear Acceleration, and Gravity Vectors in + * 3 axes. * - * @return The chip ID (BNO055_CHIPID). - */ - uint8_t getChipID(); - - /** - * Return the accelerometer chip ID. + * The focus on this driver has been on supporting the fusion + * components. Less support is available for use of this device as + * a generic accelerometer, gyroscope and magnetometer, however + * enough infrastructure is available to add any missing + * functionality. * - * @return The chip ID. - */ - uint8_t getACCID(); - - /** - * Return the magnetometer chip ID. + * This device requires calibration in order to operate accurately. + * Methods are provided to retrieve calibration data (once + * calibrated) to be stored somewhere else, like in a file. A + * method is provided to load this data as well. Calibration data + * is lost on a power cycle. See one of the examples for a + * description of how to calibrate the device, but in essence: * - * @return The chip ID. - */ - uint8_t getMAGID(); - - /** - * Return the gyroscope chip ID. + * There is a calibration status register available + * (getCalibrationStatus()) that returns the calibration status of + * the accelerometer (ACC), magnetometer (MAG), gyroscope (GYR), and + * overall system (SYS). Each of these values range from 0 + * (uncalibrated) to 3 (fully calibrated). Calibration involves + * certain motions to get all 4 values at 3. The motions are as + * follows (though see the datasheet for more information): * - * @return The chip ID. - */ - uint8_t getGYRID(); - - /** - * Return the fusion firmware revison. + * GYR: Simply let the sensor sit flat for a few seconds. * - * @return The firmware revison. - */ - uint16_t getSWRevID(); - - /** - * Return the bootloader ID. + * ACC: Move the sensor in various positions. Start flat, then + * rotate slowly by 45 degrees, hold for a few seconds, then + * continue rotating another 45 degrees and hold, etc. 6 or more + * movements of this type may be required. You can move through any + * axis you desire, but make sure that the device is lying at least + * once perpendicular to the x, y, and z axis. * - * @return The bootloader ID. - */ - uint8_t getBootLoaderID(); - - /** - * Enable or disables the use of the external clock. The Adafriut - * device does contain an external clock which might be more - * stable. By default, the internal clock is used. + * MAG: Move slowly in a figure 8 pattern in the air, until the + * calibration values reaches 3. * - * @param extClock true to use external clock, false otherwise. - */ - void setClockExternal(bool extClock); - - /** - * Select the temperature source. This can be the accelerometer - * or the gyroscope. By default, the accelerometer temperature is - * used as the source. + * SYS: This will usually reach 3 when the other items have also + * reached 3. If not, continue slowly moving the device though + * various axes until it does. * - * @param src One of the TEMP_SOURCES_T values. + * @snippet bno055.cxx Interesting */ - void setTemperatureSource(TEMP_SOURCES_T src); - /** - * Select the temperature units. This can be the Fahrenheit or - * Celsius. - * - * @param celsius true for Celius, false for Fahrenheit. - */ - void setTemperatureUnits(bool celsius); + class BNO055 { - /** - * Set the operating mode for the device. This places the device - * into a config mode, one of 7 non-fusion modes, or one of 5 - * fusion modes. All stored sensor data is cleared when switching - * modes. The device must be in config mode for most - * configuration operations. See the datasheet for details. - * - * @param mode One of the OPERATION_MODES_T values. - */ - void setOperationMode(OPERATION_MODES_T mode); + public: + /** + * BNO055 constructor. + * + * By default, the constructor sets the acceleration units to + * m/s^2, gyro and Euler units to degrees, and temperature to + * celsius. It then enters the NDOF fusion mode. + * + * In addition, the internal clock is used so that compatibility + * with other implementations is assured. If you are using a + * device with an external clock, call setClockExternal(true) to + * enable it. + * + * @param bus I2C bus to use. + * @param address The address for this device. + * @throws std::runtime_error on initialization failure. + */ + BNO055(int bus=BNO055_DEFAULT_I2C_BUS, + uint8_t addr=BNO055_DEFAULT_ADDR); - /** - * Reboot the sensor. This is equivalent to a power on reset. - * All calibration data will be lost, and the device must be - * recalibrated. - */ - void resetSystem(); + /** + * BNO055 Destructor. + */ + virtual ~BNO055(); - /** - * Read the calibration status registers and return them. The - * values range from 0 (uncalibrated) to 3 (fully calibrated). - * - * @param mag The calibration status of the magnetometer. - * @param acc The calibration status of the accelerometer. - * @param mag The calibration status of the gyroscope. - * @param mag The calibration status of the overall system. - */ - void getCalibrationStatus(int *mag, int *acc, int *gyr, int *sys); + /** + * Update the internal stored values from sensor data. + * + * @throws std::runtime_error on failure. + */ + void update(); - /** - * Read the calibration status registers and return them as an - * integer array. The values range from 0 (uncalibrated) to 3 - * (fully calibrated). - * - * @return An integer array containing the values in the order: - * mag, acc, gyr, and sys. - */ - int *getCalibrationStatus(); + /** + * Return the chip ID. + * + * @return The chip ID (BNO055_CHIPID). + */ + uint8_t getChipID(); - /** - * Read the calibration status registers and return true or false, - * indicating whether all of the calibration parameters are fully - * calibrated. - * - * @return true if all 4 calibration parameters are fully - * calibrated, else false. - */ - bool isFullyCalibrated(); + /** + * Return the accelerometer chip ID. + * + * @return The chip ID. + */ + uint8_t getACCID(); - /** - * Read the calibration data and return it as a string. This data - * can then be saved for later reuse by writeCalibrationData() to - * restore calibration data after a reset. - * - * @return string representing calibration data. - */ - std::string readCalibrationData(); + /** + * Return the magnetometer chip ID. + * + * @return The chip ID. + */ + uint8_t getMAGID(); - /** - * Write previously saved calibration data to the calibration - * registers. - * - * @param string representing calibration data, as returned by - * readCalibrationData(). - */ - void writeCalibrationData(std::string calibData); + /** + * Return the gyroscope chip ID. + * + * @return The chip ID. + */ + uint8_t getGYRID(); - /** - * Return the current measured temperature. Note, this is not - * ambient temperature - this is the temperature of the selected - * source on the chip. update() must have been called prior to - * calling this method. - * - * @param fahrenheit true to return data in Fahrenheit, false for - * Celicus. Celsius is the default. - * @return The temperature in degrees Celsius or Fahrenheit. - */ - float getTemperature(bool fahrenheit=false); + /** + * Return the fusion firmware revison. + * + * @return The firmware revison. + */ + uint16_t getSWRevID(); - /** - * Return current orientation fusion data in the form of Euler - * Angles. By default, the returned values are in degrees. - * update() must have been called prior to calling this method. - * - * @param heading Pointer to a floating point value that will have - * the current heading angle placed into it. - * @param roll Pointer to a floating point value that will have - * the current roll angle placed into it. - * @param pitch Pointer to a floating point value that will have - * the current pitch angle placed into it. - */ - void getEulerAngles(float *heading, float *roll, float *pitch); + /** + * Return the bootloader ID. + * + * @return The bootloader ID. + */ + uint8_t getBootLoaderID(); - /** - * Return current orientation fusion data in the form of Euler - * Angles as a floating point array. By default, the returned - * values are in degrees. update() must have been called prior to - * calling this method. - * - * @return A floating point array containing heading, roll, and - * pitch, in that order. - */ - float *getEulerAngles(); + /** + * Enable or disables the use of the external clock. The Adafruit + * device does contain an external clock which might be more + * stable. By default, the internal clock is used. + * + * @param extClock true to use external clock, false otherwise. + */ + void setClockExternal(bool extClock); - /** - * Return current orientation fusion data in the form of - * Quaternions. update() must have been called prior to calling - * this method. - * - * @param w Pointer to a floating point value that will have - * the current w component placed into it. - * @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 getQuaternions(float *w, float *x, float *y, float *z); + /** + * Select the temperature source. This can be the accelerometer + * or the gyroscope. By default, the accelerometer temperature is + * used as the source. + * + * @param src One of the BNO055_TEMP_SOURCES_T values. + */ + void setTemperatureSource(BNO055_TEMP_SOURCES_T src); - /** - * Return current orientation fusion data in the form of - * Quaternions, as a floating point array. update() must have - * been called prior to calling this method. - * - * @return A floating point array containing w, x, y, and z in - * that order. - */ - float *getQuaternions(); + /** + * Set the operating mode for the device. This places the device + * into a config mode, one of 7 non-fusion modes, or one of 5 + * fusion modes. All stored sensor data is cleared when switching + * modes. The device must be in config mode for most + * configuration operations. See the datasheet for details. + * + * @param mode One of the BNO055_OPERATION_MODES_T values. + */ + void setOperationMode(BNO055_OPERATION_MODES_T mode); - /** - * Return current orientation fusion data in the form of Linear - * Acceleration. By default the returned values are in meters - * per-second squared (m/s^2). 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 getLinearAcceleration(float *x, float *y, float *z); + /** + * Reboot the sensor. This is equivalent to a power on reset. + * All calibration data will be lost, and the device must be + * recalibrated. + */ + void resetSystem(); - /** - * Return current orientation fusion data in the form of Linear - * Acceleration, as a floating point array. update() must have - * been called prior to calling this method. - * - * @return A floating point array containing x, y, and z in - * that order. - */ - float *getLinearAcceleration(); + /** + * Read the calibration status registers and return them. The + * values range from 0 (uncalibrated) to 3 (fully calibrated). + * + * @param mag The calibration status of the magnetometer. + * @param acc The calibration status of the accelerometer. + * @param mag The calibration status of the gyroscope. + * @param mag The calibration status of the overall system. + */ + void getCalibrationStatus(int *mag, int *acc, int *gyr, int *sys); - /** - * Return current orientation fusion data in the form of a Gravity - * Vector per-axis. By default the returned values are in meters - * per-second squared (m/s^2). 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 getGravityVectors(float *x, float *y, float *z); + /** + * Read the calibration status registers and return them as an + * integer vector. The values range from 0 (uncalibrated) to 3 + * (fully calibrated). + * + * @return An integer vector containing the values in the + * order: mag, acc, gyr, and sys. + */ + std::vector getCalibrationStatus(); - /** - * Return current orientation fusion data in the form of a Gravity - * Vector per-axis as a floating point array. update() must have - * been called prior to calling this method. - * - * @return A floating point array containing x, y, and z in - * that order. - */ - float *getGravityVectors(); + /** + * Read the calibration status registers and return true or false, + * indicating whether all of the calibration parameters are fully + * calibrated. + * + * @return True if all 4 calibration parameters are fully + * calibrated, else false. + */ + bool isFullyCalibrated(); - /** - * Return uncompensated accelerometer data (non-fusion). In - * fusion modes, this data will be of little value. By default - * the returned values are in meters per-second squared (m/s^2). - * 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); + /** + * Read the calibration data and return it as a string. This + * data can then be saved for later reuse by + * writeCalibrationData() to restore calibration data after a + * reset. The sensor must be fully calibrated before + * calibration data can be read. + * + * @return A vector of uint8_t's representing the calibration + * data. This vector will always be exactly + * BNO055_CALIBRATION_DATA_SIZE in size. + * @throws std::runtime_error if an error occurs. + */ + std::vector readCalibrationData(); - /** - * Return current uncompensated accelerometer (non-fusion) data in - * the form of a floating point array. By default the returned - * values are in meters per-second squared (m/s^2). 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(); + /** + * Write previously saved calibration data to the calibration + * registers. + * + * @param calibData A vector of uint8_t (bytes) representing + * calibration data as returned by readCalibrationData(). + * It's length must always be exactly BNO055_CALIBRATION_DATA_SIZE. + * @throws std::length_error if the vector size is not equal to + * BNO055_CALIBRATION_DATA_SIZE. + */ + void writeCalibrationData(std::vector calibrationData); - /** - * Return uncompensated magnetometer data (non-fusion). In fusion - * modes, this data will be of little value. The returned values - * are 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 the current measured temperature. Note, this is not + * ambient temperature - this is the temperature of the selected + * source on the chip. update() must have been called prior to + * calling this method. + * + * @param fahrenheit true to return data in Fahrenheit, false for + * Celicus. Celsius is the default. + * @return The temperature in degrees Celsius or Fahrenheit. + */ + float getTemperature(bool fahrenheit=false); - /** - * Return current uncompensated magnetometer (non-fusion) data in - * the form of a floating point array. The returned values are in - * micro-teslas (uT). 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(); + /** + * Return current orientation fusion data in the form of Euler + * Angles. By default, the returned values are in degrees. + * update() must have been called prior to calling this method. + * + * @param heading Pointer to a floating point value that will have + * the current heading angle placed into it. + * @param roll Pointer to a floating point value that will have + * the current roll angle placed into it. + * @param pitch Pointer to a floating point value that will have + * the current pitch angle placed into it. + */ + void getEulerAngles(float *heading, float *roll, float *pitch); - /** - * Return uncompensated gyroscope data (non-fusion). In fusion - * modes, this data will be of little value. By default the - * returned values are in meters per-second squared (m/s^2). - * 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 current orientation fusion data in the form of Euler + * Angles as a floating point vector. By default, the returned + * values are in degrees. update() must have been called prior to + * calling this method. + * + * @return A floating point vector containing heading, roll, and + * pitch, in that order. + */ + std::vector getEulerAngles(); - /** - * Return current uncompensated gyroscope (non-fusion) data in the - * form of a floating point array. By default the returned values - * are in meters per-second squared (m/s^2). 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 current orientation fusion data in the form of + * Quaternions. update() must have been called prior to calling + * this method. + * + * @param w Pointer to a floating point value that will have + * the current w component placed into it. + * @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 getQuaternions(float *w, float *x, float *y, float *z); - /** - * Set the bandwidth, range, and power modes of the accelerometer. - * In fusion modes, these values will be ignored. - * - * @param range One of the ACC_RANGE_T values. - * @param bw One of the ACC_BW_T values. - * @param pwr One of the ACC_PWR_MODE_T values. - */ - void setAccelerationConfig(ACC_RANGE_T range, ACC_BW_T bw, - ACC_PWR_MODE_T pwr); + /** + * Return current orientation fusion data in the form of + * Quaternions, as a floating point vector. update() must have + * been called prior to calling this method. + * + * @return A floating point vector containing w, x, y, and z in + * that order. + */ + std::vector getQuaternions(); - /** - * Set the output data rate, operating mode and power mode of the - * magnetometer. In fusion modes, these values will be ignored. - * - * @param odr One of the MAG_ODR_T values. - * @param opr One of the MAG_OPR_T values. - * @param pwr One of the MAG_POWER_T values. - */ - void setMagnetometerConfig(MAG_ODR_T odr, MAG_OPR_T opr, - MAG_POWER_T pwr); + /** + * Return current orientation fusion data in the form of Linear + * Acceleration. By default the returned values are in meters + * per-second squared (m/s^2). 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 getLinearAcceleration(float *x, float *y, float *z); - /** - * Set the range, bandwidth and power modes of the gyroscope. In - * fusion modes, these values will be ignored. - * - * @param range One of the GYR_RANGE_T values. - * @param bw One of the GYR_BW_T values. - * @param pwr One of the GYR_POWER_MODE_T values. - */ - void setGyroscopeConfig(GYR_RANGE_T range, GYR_BW_T bw, - GYR_POWER_MODE_T pwr); + /** + * Return current orientation fusion data in the form of Linear + * Acceleration, as a floating point vector. update() must have + * been called prior to calling this method. + * + * @return A floating point vector containing x, y, and z in + * that order. + */ + std::vector getLinearAcceleration(); - /** - * Set the unit of measurement for the accelerometer related - * sensor values. The choices are mg (milligrams) or meters - * per-second squared (m/s^2). The default is m/s^2. - * - * @param mg true for mg, false for m/s^2. - */ - void setAccelerometerUnits(bool mg=false); + /** + * Return current orientation fusion data in the form of a Gravity + * Vector per-axis. By default the returned values are in meters + * per-second squared (m/s^2). 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 getGravityVectors(float *x, float *y, float *z); - /** - * Set the unit of measurement for the gyroscope related sensor - * values. The choices are degrees and radians. The default is - * degrees. - * - * @param radians true for radians, false for degrees. - */ - void setGyroscopeUnits(bool radians=false); + /** + * Return current orientation fusion data in the form of a Gravity + * Vector per-axis as a floating point vector. update() must have + * been called prior to calling this method. + * + * @return A floating point vector containing x, y, and z in + * that order. + */ + std::vector getGravityVectors(); - /** - * Set the unit of measurement for the Euler Angle related sensor - * values. The choices are degrees and radians. The default is - * degrees. - * - * @param radians true for radians, false for degrees. - */ - void setEulerUnits(bool radians=false); + /** + * Return uncompensated accelerometer data (non-fusion). In + * fusion modes, this data will be of little value. By default + * the returned values are in meters per-second squared (m/s^2). + * 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); - /** - * Reset all interrupt status bits and interrupt output. - */ - void resetInterruptStatus(); + /** + * Return current uncompensated accelerometer (non-fusion) data in + * the form of a floating point vector. By default the returned + * values are in meters per-second squared (m/s^2). update() must + * have been called prior to calling this method. + * + * @return A floating point vector containing x, y, and z in + * that order. + */ + std::vector getAccelerometer(); - /** - * Return the interrupt status register. This is a bitmask of the - * INT_STA_BITS_T bits. - * - * @return a bitmask of INT_STA_BITS_T bits. - */ - uint8_t getInterruptStatus(); + /** + * Return uncompensated magnetometer data (non-fusion). In fusion + * modes, this data will be of little value. The returned values + * are 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 the interrupt enables register. This is a bitmask of the - * INT_STA_BITS_T bits. - * - * @return a bitmask of INT_STA_BITS_T bits currently set in the - * enable register. - */ - uint8_t getInterruptEnable(); + /** + * Return current uncompensated magnetometer (non-fusion) data in + * the form of a floating point vector. The returned values are in + * micro-teslas (uT). update() must have been called prior to + * calling this method. + * + * @return A floating point vector containing x, y, and z in + * that order. + */ + std::vector getMagnetometer(); - /** - * Set the interrupt enable register. This is composed of a - * bitmask of the INT_STA_BITS_T bits. - * - * @param enables a bitmask of INT_STA_BITS_T bits to enable - */ - void setInterruptEnable(uint8_t enables); + /** + * Return uncompensated gyroscope data (non-fusion). In fusion + * modes, this data will be of little value. By default the + * returned values are in meters per-second squared (m/s^2). + * 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 the interrupt mask register. This is a bitmask of the - * INT_STA_BITS_T bits. The interrupt mask is used to mask off - * enabled interrupts from generating a hardware interrupt. The - * interrupt status register can still be used to detect masked - * interrupts if they are enabled. - * - * @return a bitmask of INT_STA_BITS_T bits currently set in the - * interrupt mask register. - */ - uint8_t getInterruptMask(); + /** + * Return current uncompensated gyroscope (non-fusion) data in the + * form of a floating point vector. By default the returned values + * are in meters per-second squared (m/s^2). update() must have + * been called prior to calling this method. + * + * @return A floating point vector containing x, y, and z in + * that order. + */ + std::vector getGyroscope(); - /** - * Set the interrupt mask register. This is a bitmask of the - * INT_STA_BITS_T bits. The interrupt mask is used to mask off - * enabled interrupts from generating a hardware interrupt. The - * interrupt status register can still be used to detect masked - * interrupts if they are enabled. - * - * @param a bitmask of INT_STA_BITS_T bits to set in the interrupt - * mask register. - */ - void setInterruptMask(uint8_t mask); + /** + * Set the bandwidth, range, and power modes of the accelerometer. + * In fusion modes, these values will be ignored. + * + * @param range One of the BNO055_ACC_RANGE_T values. + * @param bw One of the BNO055_ACC_BW_T values. + * @param pwr One of the BNO055_ACC_PWR_MODE_T values. + */ + void setAccelerationConfig(BNO055_ACC_RANGE_T range, + BNO055_ACC_BW_T bw, + BNO055_ACC_PWR_MODE_T pwr); - /** - * Return the value of the system status register. This method - * can be used to determine the overall status of the device. - * - * @return One of the SYS_STATUS_T values. - */ - SYS_STATUS_T getSystemStatus(); + /** + * Set the output data rate, operating mode and power mode of the + * magnetometer. In fusion modes, these values will be ignored. + * + * @param odr One of the BNO055_MAG_ODR_T values. + * @param opr One of the BNO055_MAG_OPR_T values. + * @param pwr One of the BNO055_MAG_POWER_T values. + */ + void setMagnetometerConfig(BNO055_MAG_ODR_T odr, + BNO055_MAG_OPR_T opr, + BNO055_MAG_POWER_T pwr); - /** - * Return the value of the system error register. This mathod can - * be used to determine a variety of system related error - * conditions. - * - * @return One of the SYS_ERR_T values. - */ - SYS_ERR_T getSystemError(); + /** + * Set the range, bandwidth and power modes of the gyroscope. In + * fusion modes, these values will be ignored. + * + * @param range One of the BNO055_GYR_RANGE_T values. + * @param bw One of the BNO055_GYR_BW_T values. + * @param pwr One of the BNO055_GYR_POWER_MODE_T values. + */ + void setGyroscopeConfig(BNO055_GYR_RANGE_T range, + BNO055_GYR_BW_T bw, + BNO055_GYR_POWER_MODE_T pwr); + + /** + * Set the unit of measurement for the accelerometer related + * sensor values. The choices are mg (milligravities) or meters + * per-second squared (m/s^2). The default is m/s^2. + * + * @param mg true for mg, false for m/s^2. + */ + void setAccelerometerUnits(bool mg=false); + + /** + * Set the unit of measurement for the gyroscope related sensor + * values. The choices are degrees and radians. The default is + * degrees. + * + * @param radians true for radians, false for degrees. + */ + void setGyroscopeUnits(bool radians=false); + + /** + * Set the unit of measurement for the Euler Angle related sensor + * values. The choices are degrees and radians. The default is + * degrees. + * + * @param radians true for radians, false for degrees. + */ + void setEulerUnits(bool radians=false); + + /** + * Reset all interrupt status bits and interrupt output. + */ + void resetInterruptStatus(); + + /** + * Return the interrupt status register. This is a bitmask of the + * BNO055_INT_STA_BITS_T bits. + * + * @return a bitmask of BNO055_INT_STA_BITS_T bits. + */ + uint8_t getInterruptStatus(); + + /** + * Return the interrupt enables register. This is a bitmask of the + * BNO055_INT_STA_BITS_T bits. + * + * @return a bitmask of BNO055_INT_STA_BITS_T bits currently set in the + * enable register. + */ + uint8_t getInterruptEnable(); + + /** + * Set the interrupt enable register. This is composed of a + * bitmask of the BNO055_INT_STA_BITS_T bits. + * + * @param enables a bitmask of BNO055_INT_STA_BITS_T bits to enable + */ + void setInterruptEnable(uint8_t enables); + + /** + * Return the interrupt mask register. This is a bitmask of + * the BNO055_INT_STA_BITS_T bits. The interrupt mask is used + * to mask off enabled interrupts from generating a hardware + * interrupt. The interrupt status register can still be used + * to detect masked interrupts if they are enabled. + * + * @return a bitmask of BNO055_INT_STA_BITS_T bits currently set in the + * interrupt mask register. + */ + uint8_t getInterruptMask(); + + /** + * Set the interrupt mask register. This is a bitmask of the + * BNO055_INT_STA_BITS_T bits. The interrupt mask is used to + * mask off enabled interrupts from generating a hardware + * interrupt. The interrupt status register can still be used + * to detect masked interrupts if they are enabled. + * + * @param a bitmask of BNO055_INT_STA_BITS_T bits to set in + * the interrupt mask register. + */ + void setInterruptMask(uint8_t mask); + + /** + * Return the value of the system status register. This method + * can be used to determine the overall status of the device. + * + * @return One of the BNO055_SYS_STATUS_T values. + */ + BNO055_SYS_STATUS_T getSystemStatus(); + + /** + * Return the value of the system error register. This mathod can + * be used to determine a variety of system related error + * conditions. + * + * @return One of the BNO055_SYS_ERR_T values. + */ + BNO055_SYS_ERR_T getSystemError(); #if defined(SWIGJAVA) || defined(JAVACALLBACK) - void installISR(int gpio, mraa::Edge level, jobject runnable); + void installISR(int gpio, mraa_gpio_edge_t level, jobject runnable) + { + installISR(gpio, level, mraa_java_isr_callback, runnable); + } #else - /** - * install an interrupt handler. - * - * @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(int gpio, mraa::Edge level, - void (*isr)(void *), void *arg); + /** + * install an interrupt handler. + * + * @param gpio gpio pin to use as interrupt pin + * @param level the interrupt trigger level (one of mraa_gpio_edge_t + * values). Make sure that you have configured the interrupt pin + * properly for whatever level you choose. + * @param isr the interrupt handler, accepting a void * argument + * @param arg the argument to pass the the interrupt handler + * @throws std::runtime_error on failure. + */ + void installISR(int gpio, mraa_gpio_edge_t level, + void (*isr)(void *), void *arg); #endif - /** - * uninstall a previously installed interrupt handler - * - */ - void uninstallISR(); + /** + * uninstall a previously installed interrupt handler + * + */ + void uninstallISR(); - protected: - mraa::I2c m_i2c; - mraa::Gpio *m_gpioIntr; - uint8_t m_addr; + protected: + bno055_context m_bno055; - // always stored in C - float m_temperature; + /** + * Set the current internal device register page. This is a low + * level function and should not be used unless you know what you + * are doing. + * + * @param dev The device context. + * @param page The page number to set. This can only be 0 or 1. + * @param force If true, force the device page state to match + * indicated internal page state regardless of current state. + * @throws std::runtime_error on failure. + */ + void setPage(uint8_t page, bool force=false); - // uncompensated data + /** + * Read a register. + * + * @param reg The register to read + * @return The value of the register + */ + uint8_t readReg(uint8_t reg); - // mag data - float m_magX; - float m_magY; - float m_magZ; + /** + * Read contiguous registers into a buffer. + * + * @param buffer The buffer to store the results + * @param len The number of registers to read + * @throws std::runtime_error on failure. + */ + void readRegs(uint8_t reg, uint8_t *buffer, int len); - // acc data - float m_accX; - float m_accY; - float m_accZ; + /** + * Write to a register + * + * @param reg The register to write to + * @param val The value to write + * @throws std::runtime_error on failure. + */ + void writeReg(uint8_t reg, uint8_t val); - // acc units - float m_accUnitScale; + /** + * Write data to contiguous registers + * + * @param reg The starting register to write to + * @param buffer The buffer containing the data to write + * @param len The number of bytes to write + * @throws std::runtime_error on failure. + */ + void writeRegs(uint8_t reg, uint8_t *buffer, int len); - // gyr data - float m_gyrX; - float m_gyrY; - float m_gyrZ; - - // gyr units - float m_gyrUnitScale; - - // eul (euler angle) data - float m_eulHeading; - float m_eulRoll; - float m_eulPitch; - - // eul units - float m_eulUnitScale; - - // qua (quaternion) data - float m_quaW; - float m_quaX; - float m_quaY; - float m_quaZ; - - // lia (linear acceleration) data - float m_liaX; - float m_liaY; - float m_liaZ; - - // grv (gravity vector) data - float m_grvX; - float m_grvY; - float m_grvZ; - - void clearData(); - bool updateFusionData(); - bool updateNonFusionData(); - void setPage(uint8_t page, bool force=false); - - /** - * 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 - */ - void 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 - * @return true if successful, false otherwise - */ - bool writeReg(uint8_t reg, uint8_t val); - - /** - * Write data to contiguous registers - * - * @param reg The starting register to write to - * @param buffer The buffer containing the data to write - * @param len The number of bytes to write - * @return true if successful, false otherwise - */ - bool writeRegs(uint8_t reg, uint8_t *buffer, int len); - - private: - int m_currentPage; - OPERATION_MODES_T m_currentMode; - bool m_tempIsC; - - // Adding a private function definition for java bindings + private: + // Adding a private function definition for java bindings #if defined(SWIGJAVA) || defined(JAVACALLBACK) - void installISR(int gpio, mraa::Edge level, - void (*isr)(void *), void *arg); + void installISR(int gpio, mraa_gpio_edge_t level, + void (*isr)(void *), void *arg); #endif - }; + }; } diff --git a/src/bno055/bno055_regs.h b/src/bno055/bno055_regs.h new file mode 100644 index 00000000..f0648a1c --- /dev/null +++ b/src/bno055/bno055_regs.h @@ -0,0 +1,825 @@ +/* + * Author: Jon Trulson + * Copyright (c) 2016-2017 Intel Corporation. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#pragma once + +#define BNO055_DEFAULT_I2C_BUS 0 +#define BNO055_DEFAULT_ADDR 0x28 + +// The chip ID, for verification in bno055_init(). +#define BNO055_CHIPID 0xa0 + +// number of bytes of stored calibration data +#define BNO055_CALIBRATION_DATA_SIZE (22) + +#ifdef __cplusplus +extern "C" { +#endif + + // NOTE: Reserved registers should not be written into. Reading + // from them will return indeterminate values. + // + // The register map is divided into two pages - page 1 contains + // sensor specific configuration registers, and page 0 contains all + // other configuration data and sensor output registers. + + /** + * BNO055 registers + */ + typedef enum { + // The first register listed here is the page ID register. It + // is the same on both pages, and selects or indicates the + // currently active register page. + + BNO055_REG_PAGE_ID = 0x07, + + // Page 0 + BNO055_REG_CHIP_ID = 0x00, + BNO055_REG_ACC_ID = 0x01, // accel id + BNO055_REG_MAG_ID = 0x02, // mag id + BNO055_REG_GYR_ID = 0x03, // gyro id + BNO055_REG_SW_REV_ID_LSB = 0x04, + BNO055_REG_SW_REV_ID_MSB = 0x05, + BNO055_REG_BL_REV_ID = 0x06, // bootloader rev + + BNO055_REG_ACC_DATA_X_LSB = 0x08, + BNO055_REG_ACC_DATA_X_MSB = 0x09, + BNO055_REG_ACC_DATA_Y_LSB = 0x0a, + BNO055_REG_ACC_DATA_Y_MSB = 0x0b, + BNO055_REG_ACC_DATA_Z_LSB = 0x0c, + BNO055_REG_ACC_DATA_Z_MSB = 0x0d, + + BNO055_REG_MAG_DATA_X_LSB = 0x0e, + BNO055_REG_MAG_DATA_X_MSB = 0x0f, + BNO055_REG_MAG_DATA_Y_LSB = 0x10, + BNO055_REG_MAG_DATA_Y_MSB = 0x11, + BNO055_REG_MAG_DATA_Z_LSB = 0x12, + BNO055_REG_MAG_DATA_Z_MSB = 0x13, + + BNO055_REG_GYR_DATA_X_LSB = 0x14, + BNO055_REG_GYR_DATA_X_MSB = 0x15, + BNO055_REG_GYR_DATA_Y_LSB = 0x16, + BNO055_REG_GYR_DATA_Y_MSB = 0x17, + BNO055_REG_GYR_DATA_Z_LSB = 0x18, + BNO055_REG_GYR_DATA_Z_MSB = 0x19, + + // euler angles + BNO055_REG_EUL_HEADING_LSB = 0x1a, + BNO055_REG_EUL_HEADING_MSB = 0x1b, + BNO055_REG_EUL_ROLL_LSB = 0x1c, + BNO055_REG_EUL_ROLL_MSB = 0x1d, + BNO055_REG_EUL_PITCH_LSB = 0x1e, + BNO055_REG_EUL_PITCH_MSB = 0x1f, + + // Quaternions + BNO055_REG_QUA_DATA_W_LSB = 0x20, + BNO055_REG_QUA_DATA_W_MSB = 0x21, + BNO055_REG_QUA_DATA_X_LSB = 0x22, + BNO055_REG_QUA_DATA_X_MSB = 0x23, + BNO055_REG_QUA_DATA_Y_LSB = 0x24, + BNO055_REG_QUA_DATA_Y_MSB = 0x25, + BNO055_REG_QUA_DATA_Z_LSB = 0x26, + BNO055_REG_QUA_DATA_Z_MSB = 0x27, + + // linear accel data + BNO055_REG_LIA_DATA_X_LSB = 0x28, + BNO055_REG_LIA_DATA_X_MSB = 0x29, + BNO055_REG_LIA_DATA_Y_LSB = 0x2a, + BNO055_REG_LIA_DATA_Y_MSB = 0x2b, + BNO055_REG_LIA_DATA_Z_LSB = 0x2c, + BNO055_REG_LIA_DATA_Z_MSB = 0x2d, + + // gravity vector + BNO055_REG_GRV_DATA_X_LSB = 0x2e, + BNO055_REG_GRV_DATA_X_MSB = 0x2f, + BNO055_REG_GRV_DATA_Y_LSB = 0x30, + BNO055_REG_GRV_DATA_Y_MSB = 0x31, + BNO055_REG_GRV_DATA_Z_LSB = 0x32, + BNO055_REG_GRV_DATA_Z_MSB = 0x33, + + BNO055_REG_TEMPERATURE = 0x34, + + BNO055_REG_CALIB_STAT = 0x35, // calibration status + BNO055_REG_ST_RESULT = 0x36, // selftest result + + BNO055_REG_INT_STA = 0x37, // interrupt status + + BNO055_REG_SYS_CLK_STATUS = 0x38, + + BNO055_REG_SYS_STATUS = 0x39, + BNO055_REG_SYS_ERROR = 0x3a, + + BNO055_REG_UNIT_SEL = 0x3b, + + // 0x3c reserved + + BNO055_REG_OPER_MODE = 0x3d, // operating mode + BNO055_REG_POWER_MODE = 0x3e, + + BNO055_REG_SYS_TRIGGER = 0x3f, + BNO055_REG_TEMP_SOURCE = 0x40, // temperature src + + BNO055_REG_AXIS_MAP_CONFIG = 0x41, + BNO055_REG_AXIS_MAP_SIGN = 0x42, + + // 0x43-0x54 reserved + + // stored calibration data + BNO055_REG_ACC_OFFSET_X_LSB = 0x55, + BNO055_REG_ACC_OFFSET_X_MSB = 0x56, + BNO055_REG_ACC_OFFSET_Y_LSB = 0x57, + BNO055_REG_ACC_OFFSET_Y_MSB = 0x58, + BNO055_REG_ACC_OFFSET_Z_LSB = 0x59, + BNO055_REG_ACC_OFFSET_Z_MSB = 0x5a, + + BNO055_REG_MAG_OFFSET_X_LSB = 0x5b, + BNO055_REG_MAG_OFFSET_X_MSB = 0x5c, + BNO055_REG_MAG_OFFSET_Y_LSB = 0x5d, + BNO055_REG_MAG_OFFSET_Y_MSB = 0x5e, + BNO055_REG_MAG_OFFSET_Z_LSB = 0x5f, + BNO055_REG_MAG_OFFSET_Z_MSB = 0x60, + + BNO055_REG_GYR_OFFSET_X_LSB = 0x61, + BNO055_REG_GYR_OFFSET_X_MSB = 0x62, + BNO055_REG_GYR_OFFSET_Y_LSB = 0x63, + BNO055_REG_GYR_OFFSET_Y_MSB = 0x64, + BNO055_REG_GYR_OFFSET_Z_LSB = 0x65, + BNO055_REG_GYR_OFFSET_Z_MSB = 0x66, + + BNO055_REG_ACC_RADIUS_LSB = 0x67, + BNO055_REG_ACC_RADIUS_MSB = 0x68, + + BNO055_REG_MAG_RADIUS_LSB = 0x69, + BNO055_REG_MAG_RADIUS_MSB = 0x6a, + + // 0x6b-0x7f reserved + // end of page 0 + + // Page 1 + + // 0x00-0x06 reserved + // 0x07 - page id + + BNO055_REG_ACC_CONFIG = 0x08, + BNO055_REG_MAG_CONFIG = 0x09, + BNO055_REG_GYR_CONFIG0 = 0x0a, + BNO055_REG_GYR_CONFIG1 = 0x0b, + BNO055_REG_ACC_SLEEP_CONFIG = 0x0c, + BNO055_REG_GYR_SLEEP_CONFIG = 0x0d, + + // 0x0e reserved + BNO055_REG_INT_MSK = 0x0f, + BNO055_REG_INT_EN = 0x10, + + BNO055_REG_ACC_AM_THRES = 0x11, + BNO055_REG_ACC_INT_SETTINGS = 0x12, + BNO055_REG_ACC_HG_DURATION = 0x13, + BNO055_REG_ACC_HG_THRES = 0x14, + BNO055_REG_ACC_NM_THRES = 0x15, + BNO055_REG_ACC_NM_SET = 0x16, + + BNO055_REG_GYR_INT_SETTING = 0x17, + BNO055_REG_GYR_HR_X_SET = 0x18, + BNO055_REG_GYR_DUR_X = 0x19, + BNO055_REG_GYR_HR_Y_SET = 0x1a, + BNO055_REG_GYR_DUR_Y = 0x1b, + BNO055_REG_GYR_HR_Z_SET = 0x1c, + BNO055_REG_GYR_DUR_Z = 0x1d, + BNO055_REG_GYR_AM_THRES = 0x1e, + BNO055_REG_GYR_AM_SET = 0x1f, + + // 0x20-0x4f reserved + + // 16 byte (0x50-0x5f) unique ID + BNO055_REG_BNO_UNIQUE_ID = 0x50 + + // 0x60-0x7f reserved + } BNO055_REGS_T; + + // Page 0 register enumerants + + /** + * BNO055_REG_CALIB_STAT bits + */ + typedef enum { + BNO055_CALIB_STAT_MAG0 = 0x01, + BNO055_CALIB_STAT_MAG1 = 0x02, + _BNO055_CALIB_STAT_MAG_MASK = 3, + _BNO055_CALIB_STAT_MAG_SHIFT = 0, + + BNO055_CALIB_STAT_ACC0 = 0x04, + BNO055_CALIB_STAT_ACC1 = 0x08, + _BNO055_CALIB_STAT_ACC_MASK = 3, + _BNO055_CALIB_STAT_ACC_SHIFT = 2, + + BNO055_CALIB_STAT_GYR0 = 0x10, + BNO055_CALIB_STAT_GYR1 = 0x20, + _BNO055_CALIB_STAT_GYR_MASK = 3, + _BNO055_CALIB_STAT_GYR_SHIFT = 4, + + BNO055_CALIB_STAT_SYS0 = 0x40, + BNO055_CALIB_STAT_SYS1 = 0x80, + _BNO055_CALIB_STAT_SYS_MASK = 3, + _BNO055_CALIB_STAT_SYS_SHIFT = 6 + } BNO055_CALIB_STAT_BITS_T; + + /** + * BNO055_REG_ST_RESULT bits + */ + typedef enum { + BNO055_ST_RESULT_ACC = 0x01, + BNO055_ST_RESULT_MAG = 0x02, + BNO055_ST_RESULT_GYR = 0x04, + BNO055_ST_RESULT_MCU = 0x08 + // 0x10-0x80 reserved + } BNO055_ST_RESULT_BITS_T; + + /** + * BNO055_REG_INT_STA bits + */ + typedef enum { + // 0x01-0x02 reserved + BNO055_INT_STA_GYRO_AM = 0x04, // gyro any-motion + BNO055_INT_STA_GYR_HIGH_RATE = 0x08, + // 0x010 reserved + BNO055_INT_STA_ACC_HIGH_G = 0x20, + BNO055_INT_STA_ACC_AM = 0x40, // accel any-motion + BNO055_INT_STA_ACC_NM = 0x80 // accel no-motion + } BNO055_INT_STA_BITS_T; + + /** + * BNO055_REG_SYS_CLK_STATUS bits + */ + typedef enum { + BNO055_SYS_CLK_STATUS_ST_MAIN_CLK = 0x01 + // 0x02-0x80 reserved + } BNO055_SYS_CLK_STATUS_BITS_T; + + /** + * BNO055_REG_SYS_STATUS values + */ + typedef enum { + BNO055_SYS_STATUS_IDLE = 0, + BNO055_SYS_STATUS_SYS_ERR = 1, + BNO055_SYS_STATUS_INIT_PERIPHERALS = 2, + BNO055_SYS_STATUS_SYSTEM_INIT = 3, + BNO055_SYS_STATUS_EXECUTING_SELFTEST = 4, + BNO055_SYS_STATUS_FUSION_RUNNING = 5, + BNO055_SYS_STATUS_NO_FUSION_RUNNING = 6 + } BNO055_SYS_STATUS_T; + + /** + * BNO055_REG_SYS_ERR values + */ + typedef enum { + BNO055_SYS_ERR_NOERROR = 0, + BNO055_SYS_ERR_PERIPH_INIT_ERROR = 1, + BNO055_SYS_ERR_SYS_INIT_ERROR = 2, + BNO055_SYS_ERR_SELFTEST_FAIL_ERROR = 3, + BNO055_SYS_ERR_REG_VAL_OUTOFRANGE_ERROR = 4, + BNO055_SYS_ERR_REG_ADDR_OUTOFRANGE_ERROR = 5, + BNO055_SYS_ERR_REG_WRITE_ERROR = 6, + BNO055_SYS_ERR_LP_MODE_NOT_AVAIL_ERROR = 7, + BNO055_SYS_ERR_ACC_PWR_MODE_NOT_AVAIL_ERROR = 8, + BNO055_SYS_ERR_FUSION_CONFIG_ERROR = 9, + BNO055_SYS_ERR_SENSOR_CONFIG_ERROR = 10 + } BNO055_SYS_ERR_T; + + + /** + * BNO055_REG_UNIT_SEL bits + */ + typedef enum { + BNO055_UNIT_SEL_ACC_UNIT = 0x01, // 0=m/s^2, 1=mg + BNO055_UNIT_SEL_GYR_UNIT = 0x02, // 0=dps, 1=rps + BNO055_UNIT_SEL_EUL_UNIT = 0x04, // 0=degrees, 1=radians + // 0x08 reserved + BNO055_UNIT_SEL_TEMP_UNIT = 0x10, // 0=C, 1=F + // 0x20-0x40 reserved + BNO055_UNIT_SEL_ORI_ANDROID_WINDOWS = 0x80 // 0=windows + // orient, + // 1=android + } BNO055_UNIT_SEL_BITS_T; + + /** + * BNO055_REG_OPR_MODE bits + */ + typedef enum { + BNO055_OPR_MODE_OPERATION_MODE0 = 0x01, + BNO055_OPR_MODE_OPERATION_MODE1 = 0x02, + BNO055_OPR_MODE_OPERATION_MODE2 = 0x04, + BNO055_OPR_MODE_OPERATION_MODE3 = 0x08, + _BNO055_OPR_MODE_OPERATION_MODE_MASK = 15, + _BNO055_OPR_MODE_OPERATION_MODE_SHIFT = 0 + // 0x10-0x80 reserved + } BNO055_OPR_MODE_BITS_T; + + /** + * BNO055_OPR_MODE_OPERATION values + */ + typedef enum { + BNO055_OPERATION_MODE_CONFIGMODE = 0, + BNO055_OPERATION_MODE_ACCONLY = 1, + BNO055_OPERATION_MODE_MAGONLY = 2, + BNO055_OPERATION_MODE_GYROONLY = 3, + BNO055_OPERATION_MODE_ACCMAG = 4, + BNO055_OPERATION_MODE_ACCGYRO = 5, + BNO055_OPERATION_MODE_MAGGYRO = 6, + BNO055_OPERATION_MODE_AMG = 7, + // fusion modes + BNO055_OPERATION_MODE_IMU = 8, + BNO055_OPERATION_MODE_COMPASS = 9, + BNO055_OPERATION_MODE_M4G = 10, + BNO055_OPERATION_MODE_NDOF_FMC_OFF = 11, + BNO055_OPERATION_MODE_NDOF = 12 + } BNO055_OPERATION_MODES_T; + + /** + * BNO055_REG_PWR_MODE bits + */ + typedef enum { + BNO055_PWR_MODE_POWER_MODE0 = 0x01, + BNO055_PWR_MODE_POWER_MODE1 = 0x02, + _BNO055_PWR_MODE_POWER_MODE_MASK = 3, + _BNO055_PWR_MODE_POWER_MODE_SHIFT = 0 + // 0x04-0x80 reserved + } BNO055_PWR_MODE_BITS_T; + + /** + * BNO055_POWER_MODE values + */ + typedef enum { + BNO055_POWER_MODE_NORMAL = 0, + BNO055_POWER_MODE_LOW = 1, + BNO055_POWER_MODE_SUSPEND = 2 + } POWER_MODES_T; + + /** + * BNO055_REG_SYS_TRIGGER bits + */ + typedef enum { + BNO055_SYS_TRIGGER_SELF_TEST = 0x01, + // 0x02-0x10 reserved + BNO055_SYS_TRIGGER_RST_SYS = 0x20, + BNO055_SYS_TRIGGER_RST_INT = 0x40, + BNO055_SYS_TRIGGER_CLK_SEL = 0x80 + } BNO055_SYS_TRIGGER_BITS_T; + + /** + * BNO055_REG_TEMP_SOURCE bits + */ + typedef enum { + BNO055_TEMP_SOURCE_TEMP_SOURCE0 = 0x01, + BNO055_TEMP_SOURCE_TEMP_SOURCE1 = 0x02, + _BNO055_TEMP_SOURCE_TEMP_SOURCE_MASK = 3, + _BNO055_TEMP_SOURCE_TEMP_SOURCE_SHIFT = 0 + // 0x04-0x80 reserved + } BNO055_TEMP_SOURCE_BITS_T; + + /** + * BNO055_TEMP_SOURCE values + */ + typedef enum { + BNO055_TEMP_SOURCE_ACC = 0, + BNO055_TEMP_SOURCE_GYR = 1 + } BNO055_TEMP_SOURCES_T; + + /** + * BNO055_REG_AXIS_MAP_CONFIG bits + */ + typedef enum { + BNO055_AXIS_MAP_CONFIG_REMAPPED_X_VAL0 = 0x01, + BNO055_AXIS_MAP_CONFIG_REMAPPED_X_VAL1 = 0x02, + _BNO055_AXIS_MAP_CONFIG_REMAPPED_X_VAL_MASK = 3, + _BNO055_AXIS_MAP_CONFIG_REMAPPED_X_VAL_SHIFT = 0, + + BNO055_AXIS_MAP_CONFIG_REMAPPED_Y_VAL0 = 0x04, + BNO055_AXIS_MAP_CONFIG_REMAPPED_Y_VAL1 = 0x08, + _BNO055_AXIS_MAP_CONFIG_REMAPPED_Y_VAL_MASK = 3, + _BNO055_AXIS_MAP_CONFIG_REMAPPED_Y_VAL_SHIFT = 2, + + BNO055_AXIS_MAP_CONFIG_REMAPPED_Z_VAL0 = 0x10, + BNO055_AXIS_MAP_CONFIG_REMAPPED_Z_VAL1 = 0x20, + _BNO055_AXIS_MAP_CONFIG_REMAPPED_Z_VAL_MASK = 3, + _BNO055_AXIS_MAP_CONFIG_REMAPPED_Z_VAL_SHIFT = 4 + // 0x40-0x80 reserved + } BNO055_AXIS_MAP_CONFIG_BITS_T; + + /** + * REMAPPED_AXIS values, applied to X, Y, and Z axes + * (BNO055_REG_AXIS_MAP_CONFIG) + */ + typedef enum { + BNO055_REMAPPED_AXIS_X = 0, + BNO055_REMAPPED_AXIS_Y = 1, + BNO055_REMAPPED_AXIS_Z = 2 + } BNO055_REMAPPED_AXIS_T; + + /** + * BNO055_REG_AXIS_MAP_SIGN bits + */ + typedef enum { + BNO055_AXIS_MAP_SIGN_REMAPPED_Z_SIGN = 0x01, + BNO055_AXIS_MAP_SIGN_REMAPPED_Y_SIGN = 0x02, + BNO055_AXIS_MAP_SIGN_REMAPPED_X_SIGN = 0x04 + // 0x08-0x80 reserved + } BNO055_AXIS_MAP_SIGN_BITS_T; + + // Page 1 register enumerants + + /** + * BNO055_REG_ACC_CONFIG bits + */ + typedef enum { + BNO055_ACC_CONFIG_ACC_RANGE0 = 0x01, + BNO055_ACC_CONFIG_ACC_RANGE1 = 0x02, + _BNO055_ACC_CONFIG_ACC_RANGE_MASK = 3, + _BNO055_ACC_CONFIG_ACC_RANGE_SHIFT = 0, + + BNO055_ACC_CONFIG_ACC_BW0 = 0x04, + BNO055_ACC_CONFIG_ACC_BW1 = 0x08, + BNO055_ACC_CONFIG_ACC_BW2 = 0x10, + _BNO055_ACC_CONFIG_ACC_BW_MASK = 7, + _BNO055_ACC_CONFIG_ACC_BW_SHIFT = 2, + + BNO055_ACC_CONFIG_ACC_PWR_MODE0 = 0x20, + BNO055_ACC_CONFIG_ACC_PWR_MODE1 = 0x40, + BNO055_ACC_CONFIG_ACC_PWR_MODE2 = 0x80, + _BNO055_ACC_CONFIG_ACC_PWR_MODE_MASK = 7, + _BNO055_ACC_CONFIG_ACC_PWR_MODE_SHIFT = 5 + } BNO055_ACC_CONFIG_BITS_T; + + /** + * BNO055_ACC_CONFIG_ACC_RANGE values + */ + typedef enum { + BNO055_ACC_RANGE_2G = 0, + BNO055_ACC_RANGE_4G = 1, + BNO055_ACC_RANGE_8G = 2, + BNO055_ACC_RANGE_16G = 3 + } BNO055_ACC_RANGE_T; + + /** + * BNO055_ACC_CONFIG_ACC_BW values + */ + typedef enum { + BNO055_ACC_BW_7_81 = 0, // 7.81 Hz + BNO055_ACC_BW_15_53 = 1, + BNO055_ACC_BW_31_25 = 2, + BNO055_ACC_BW_62_5 = 3, + BNO055_ACC_BW_125 = 4, // 125 Hz + BNO055_ACC_BW_250 = 5, + BNO055_ACC_BW_500 = 6, + BNO055_ACC_BW_1000 = 7 + } BNO055_ACC_BW_T; + + /** + * BNO055_ACC_PWR_MODE values + */ + typedef enum { + BNO055_ACC_PWR_MODE_NORMAL = 0, + BNO055_ACC_PWR_MODE_SUSPEND = 1, + BNO055_ACC_PWR_MODE_LOWPOWER1 = 2, + BNO055_ACC_PWR_MODE_STANDBY = 3, + BNO055_ACC_PWR_MODE_LOWPOWER2 = 4, + BNO055_ACC_PWR_MODE_DEEPSUSPEND = 5 + } BNO055_ACC_PWR_MODE_T; + + /** + * BNO055_REG_MAG_CONFIG bits + */ + typedef enum { + BNO055_MAG_CONFIG_MAG_ODR0 = 0x01, + BNO055_MAG_CONFIG_MAG_ODR1 = 0x02, + BNO055_MAG_CONFIG_MAG_ODR2 = 0x04, + _BNO055_MAG_CONFIG_MAG_ODR_MASK = 7, + _BNO055_MAG_CONFIG_MAG_ODR_SHIFT = 0, + + BNO055_MAG_CONFIG_MAG_OPR_MODE0 = 0x08, + BNO055_MAG_CONFIG_MAG_OPR_MODE1 = 0x10, + _BNO055_MAG_CONFIG_MAG_OPR_MODE_MASK = 3, + _BNO055_MAG_CONFIG_MAG_OPR_MODE_SHIFT = 3, + + BNO055_MAG_CONFIG_MAG_POWER_MODE0 = 0x20, + BNO055_MAG_CONFIG_MAG_POWER_MODE1 = 0x40, + _BNO055_MAG_CONFIG_MAG_POWER_MODE_MASK = 3, + _BNO055_MAG_CONFIG_MAG_POWER_MODE_SHIFT = 5 + // 0x80 reserved + } BNO055_MAG_CONFIG_BITS_T; + + /** + * MAG_ODR values + */ + typedef enum { + BNO055_MAG_ODR_2 = 0, // 2Hz + BNO055_MAG_ODR_6 = 1, + BNO055_MAG_ODR_8 = 2, + BNO055_MAG_ODR_10 = 3, + BNO055_MAG_ODR_15 = 4, + BNO055_MAG_ODR_20 = 5, + BNO055_MAG_ODR_25 = 6, + BNO055_MAG_ODR_30 = 7 + } BNO055_MAG_ODR_T; + + /** + * BNO055_MAG_OPR values + */ + typedef enum { + BNO055_MAG_OPR_LOW = 0, // low power + BNO055_MAG_OPR_REGULAR = 1, + BNO055_MAG_OPR_ENHANCED_REGULAR = 2, + BNO055_MAG_OPR_HIGH_ACCURACY = 3 + } BNO055_MAG_OPR_T; + + /** + * BNO055_MAG_POWER values + */ + typedef enum { + BNO055_MAG_POWER_NORMAL = 0, + BNO055_MAG_POWER_SLEEP = 1, + BNO055_MAG_POWER_SUSPEND = 2, + BNO055_MAG_POWER_FORCE_MODE = 3 + } BNO055_MAG_POWER_T; + + /** + * BNO055_REG_GYR_CONFIG0 bits + */ + typedef enum { + BNO055_GYR_CONFIG0_GYR_RANGE0 = 0x01, + BNO055_GYR_CONFIG0_GYR_RANGE1 = 0x02, + BNO055_GYR_CONFIG0_GYR_RANGE2 = 0x04, + _BNO055_GYR_CONFIG0_GYR_RANGE_MASK = 7, + _BNO055_GYR_CONFIG0_GYR_RANGE_SHIFT = 0, + + BNO055_GYR_CONFIG0_GYR_BW0 = 0x08, + BNO055_GYR_CONFIG0_GYR_BW1 = 0x10, + BNO055_GYR_CONFIG0_GYR_BW2 = 0x20, + _BNO055_GYR_CONFIG0_GYR_BW_MASK = 7, + _BNO055_GYR_CONFIG0_GYR_BW_SHIFT = 3 + // 0x40-0x80 reserved + } BNO055_GYR_CONFIG0_BITS_T; + + /** + * BNO055_GYR_RANGE values + */ + typedef enum { + BNO055_GYR_RANGE_2000 = 0, // degrees/sec + BNO055_GYR_RANGE_1000 = 1, + BNO055_GYR_RANGE_500 = 2, + BNO055_GYR_RANGE_250 = 3, + BNO055_GYR_RANGE_125 = 4 + } BNO055_GYR_RANGE_T; + + /** + * BNO055_GYR_BW values + */ + typedef enum { + BNO055_GYR_BW_523 = 0, // Hz + BNO055_GYR_BW_230 = 1, + BNO055_GYR_BW_116 = 2, + BNO055_GYR_BW_47 = 3, + BNO055_GYR_BW_23 = 4, + BNO055_GYR_BW_12 = 5, + BNO055_GYR_BW_64 = 6, + BNO055_GYR_BW_32 = 7 + } BNO055_GYR_BW_T; + + /** + * BNO055_REG_GYR_CONFIG1 bits + */ + typedef enum { + BNO055_GYR_CONFIG1_GYR_POWER_MODE0 = 0x01, + BNO055_GYR_CONFIG1_GYR_POWER_MODE1 = 0x02, + BNO055_GYR_CONFIG1_GYR_POWER_MODE2 = 0x04, + _BNO055_GYR_CONFIG1_GYR_POWER_MODE_MASK = 7, + _BNO055_GYR_CONFIG1_GYR_POWER_MODE_SHIFT = 0 + // 0x08-0x80 reserved + } BNO055_GYR_CONFIG1_BITS_T; + + /** + * BNO055_GYR_POWER_MODE values + */ + typedef enum { + BNO055_GYR_POWER_MODE_NORMAL = 0, + BNO055_GYR_POWER_MODE_FAST_POWERUP = 1, + BNO055_GYR_POWER_MODE_DEEP_SUSPEND = 2, + BNO055_GYR_POWER_MODE_SUSPEND = 3, + BNO055_GYR_POWER_MODE_ADVANCED_POWERSAVE= 4 + } BNO055_GYR_POWER_MODE_T; + + /** + * BNO055_REG_ACC_SLEEP_CONFIG bits + */ + typedef enum { + BNO055_ACC_SLEEP_CONFIG_SLP_MODE = 0x01, // 0=event, + // 1=equidistant + // sample + + BNO055_ACC_SLEEP_CONFIG_ACC_SLP_DUR0 = 0x02, + BNO055_ACC_SLEEP_CONFIG_ACC_SLP_DUR1 = 0x04, + BNO055_ACC_SLEEP_CONFIG_ACC_SLP_DUR2 = 0x08, + BNO055_ACC_SLEEP_CONFIG_ACC_SLP_DUR3 = 0x10, + _BNO055_ACC_SLEEP_CONFIG_ACC_SLP_DUR_MASK = 15, + _BNO055_ACC_SLEEP_CONFIG_ACC_SLP_DUR_SHIFT = 1 + // 0x20-0x80 reserved + } BNO055_ACC_SLEEP_CONFIG_BITS_T; + + /** + * BNO055_ACC_SLP_DUR values + */ + typedef enum { + BNO055_ACC_SLP_DUR_0_5 = 0, // 0.5ms + // same for 1-5 + + BNO055_ACC_SLP_DUR_1 = 6, // 1ms + BNO055_ACC_SLP_DUR_2 = 7, + BNO055_ACC_SLP_DUR_4 = 8, + BNO055_ACC_SLP_DUR_6 = 9, + BNO055_ACC_SLP_DUR_10 = 10, + BNO055_ACC_SLP_DUR_25 = 11, + BNO055_ACC_SLP_DUR_50 = 12, + BNO055_ACC_SLP_DUR_100 = 13, + BNO055_ACC_SLP_DUR_500 = 14 + // 15 = 1ms + } BNO055_ACC_SLP_DUR_T; + + /** + * BNO055_REG_GYR_SLEEP_CONFIG bits + */ + typedef enum { + BNO055_GYR_SLEEP_CONFIG_GYR_SLEEP_DUR0 = 0x01, + BNO055_GYR_SLEEP_CONFIG_GYR_SLEEP_DUR1 = 0x02, + BNO055_GYR_SLEEP_CONFIG_GYR_SLEEP_DUR2 = 0x04, + _BNO055_GYR_SLEEP_CONFIG_GYR_SLEEP_DUR_MASK = 7, + _BNO055_GYR_SLEEP_CONFIG_GYR_SLEEP_DUR_SHIFT = 0, + + BNO055_GYR_SLEEP_CONFIG_GYR_AUTO_SLP_DUR0 = 0x08, + BNO055_GYR_SLEEP_CONFIG_GYR_AUTO_SLP_DUR1 = 0x10, + BNO055_GYR_SLEEP_CONFIG_GYR_AUTO_SLP_DUR2 = 0x20, + _BNO055_GYR_SLEEP_CONFIG_GYR_AUTO_SLP_DUR_MASK = 7, + _BNO055_GYR_SLEEP_CONFIG_GYR_AUTO_SLP_DUR_SHIFT = 3 + // 0x40-0x80 reserved + } BNO055_GYR_SLEEP_CONFIG_BITS_T; + + /** + * BNO055_GYR_SLEEP_DUR values + */ + typedef enum { + BNO055_GYR_SLEEP_DUR_2 = 0, // 2ms + BNO055_GYR_SLEEP_DUR_4 = 1, + BNO055_GYR_SLEEP_DUR_5 = 2, + BNO055_GYR_SLEEP_DUR_8 = 3, + BNO055_GYR_SLEEP_DUR_10 = 4, + BNO055_GYR_SLEEP_DUR_15 = 5, + BNO055_GYR_SLEEP_DUR_18 = 6, + BNO055_GYR_SLEEP_DUR_20 = 7 + } BNO055_GYR_SLEEP_DUR_T; + + /** + * BNO055_GYR_AUTO_SLP_DUR values + */ + typedef enum { + // 0 = illegal + BNO055_GYR_AUTO_SLP_DUR_4 = 1, // ms + BNO055_GYR_AUTO_SLP_DUR_5 = 2, + BNO055_GYR_AUTO_SLP_DUR_8 = 3, + BNO055_GYR_AUTO_SLP_DUR_10 = 4, + BNO055_GYR_AUTO_SLP_DUR_15 = 5, + BNO055_GYR_AUTO_SLP_DUR_20 = 6, + BNO055_GYR_AUTO_SLP_DUR_40 = 7 + } BNO055_GYR_AUTO_SLP_DUR_T; + + /** + * BNO055_REG_INT_MSK and BNO055_REG_INT_EN bits + */ + typedef enum { + // 0x00-0x02 reserved + BNO055_INT_GYRO_AM = 0x04, // gyro any-motion + BNO055_INT_GYRO_HIGH_RATE = 0x08, + // 0x10 reserved + BNO055_INT_ACC_HIGH_G = 0x20, + BNO055_INT_ACC_AM = 0x40, // acc any-motion + BNO055_INT_ACC_NM = 0x80, // acc no-motion + } BNO055_INT_BITS_T; + + /** + * BNO055_REG_ACC_INT_SETTINGS bits + */ + typedef enum { + BNO055_ACC_INT_SETTINGS_AM_DUR0 = 0x01, + BNO055_ACC_INT_SETTINGS_AM_DUR1 = 0x02, + _BNO055_ACC_INT_SETTINGS_AM_DUR_MASK = 3, + _BNO055_ACC_INT_SETTINGS_AM_DUR_SHIFT = 0, + + BNO055_ACC_INT_SETTINGS_AM_NM_X_AXIS = 0x04, + BNO055_ACC_INT_SETTINGS_AM_NM_Y_AXIS = 0x08, + BNO055_ACC_INT_SETTINGS_AM_NM_Z_AXIS = 0x10, + + BNO055_ACC_INT_SETTINGS_HG_X_AXIS = 0x20, + BNO055_ACC_INT_SETTINGS_HG_Y_AXIS = 0x40, + BNO055_ACC_INT_SETTINGS_HG_Z_AXIS = 0x80 + } BNO055_ACC_INT_SETTINGS_BITS_T; + + /** + * BNO055_REG_ACC_NM_SET bits + */ + typedef enum { + BNO055_ACC_NM_SET_SM_NM = 0x01, // 0=slowmotion, + // 1=nomotion + + BNO055_ACC_NM_SET_SM_NM_DUR0 = 0x02, + BNO055_ACC_NM_SET_SM_NM_DUR1 = 0x04, + BNO055_ACC_NM_SET_SM_NM_DUR2 = 0x08, + BNO055_ACC_NM_SET_SM_NM_DUR3 = 0x10, + BNO055_ACC_NM_SET_SM_NM_DUR4 = 0x20, + BNO055_ACC_NM_SET_SM_NM_DUR5 = 0x40, + _BNO055_ACC_NM_SET_SM_NM_DUR_MASK = 63, + _BNO055_ACC_NM_SET_SM_NM_DUR_SHIFT = 1 + // 0x80 reserved + } BNO055_ACC_NM_SET_BITS_T; + + /** + * BNO055_REG_GYR_INT_SETTING bits + */ + typedef enum { + BNO055_GYR_INT_SETTING_AM_X_AXIS = 0x01, + BNO055_GYR_INT_SETTING_AM_Y_AXIS = 0x02, + BNO055_GYR_INT_SETTING_AM_Z_AXIS = 0x04, + + BNO055_GYR_INT_SETTING_HR_X_AXIS = 0x08, + BNO055_GYR_INT_SETTING_HR_Y_AXIS = 0x10, + BNO055_GYR_INT_SETTING_HR_Z_AXIS = 0x20, + + BNO055_GYR_INT_SETTING_AM_FILT = 0x40, + BNO055_GYR_INT_SETTING_HR_FILT = 0x80 + } BNO055_GYR_INT_SETTING_BITS_T; + + /** + * BNO055_REG_GYR_HR_X_SET, BNO055_REG_GYR_HR_Y_SET, and + * BNO055_REG_GYR_HR_Z_SET bits + */ + typedef enum { + BNO055_GYR_HR_XYZ_SET_HR_THRESH0 = 0x01, + BNO055_GYR_HR_XYZ_SET_HR_THRESH1 = 0x02, + BNO055_GYR_HR_XYZ_SET_HR_THRESH2 = 0x04, + BNO055_GYR_HR_XYZ_SET_HR_THRESH3 = 0x08, + BNO055_GYR_HR_XYZ_SET_HR_THRESH4 = 0x10, + _BNO055_GYR_HR_XYZ_SET_HR_THRESH_MASK = 31, + _BNO055_GYR_HR_XYZ_SET_HR_THRESH_SHIFT = 0, + + BNO055_GYR_HR_XYZ_SET_HR_THRESH_HYST0 = 0x20, + BNO055_GYR_HR_XYZ_SET_HR_THRESH_HYST1 = 0x40, + _BNO055_GYR_HR_XYZ_SET_HR_THRESH_HYST_MASK = 3, + _BNO055_GYR_HR_XYZ_SET_HR_THRESH_HYST_SHIFT = 5 + } BNO055_GYR_HR_XYZ_SET_BITS_T; + + /** + * BNO055_REG_GYR_AM_SET bits + */ + typedef enum { + BNO055_GYR_AM_SET_SLOPE_SAMPLES0 = 0x01, + BNO055_GYR_AM_SET_SLOPE_SAMPLES1 = 0x02, + _BNO055_GYR_AM_SET_SLOPE_SAMPLES_MASK = 3, + _BNO055_GYR_AM_SET_SLOPE_SAMPLES_SHIFT = 0, + + BNO055_GYR_AM_SET_AWAKE_DUR0 = 0x04, + BNO055_GYR_AM_SET_AWAKE_DUR1 = 0x08, + _BNO055_GYR_AM_SET_AWAKE_DUR_MASK = 3, + _BNO055_GYR_AM_SET_AWAKE_DUR_SHIFT = 2 + + // 0x10-0x80 reserved + } BNO055_GYR_AM_SET_BITS_T; + + /** + * BNO055_GYR_AM_SET_SLOPE_SAMPLES values + */ + typedef enum { + BNO055_SLOPE_SAMPLES_8 = 0, // 8 samples + BNO055_SLOPE_SAMPLES_16 = 1, + BNO055_SLOPE_SAMPLES_32 = 2, + BNO055_SLOPE_SAMPLES_64 = 3 + } BNO055_SLOPE_SAMPLES_T; + +#ifdef __cplusplus +} +#endif diff --git a/src/bno055/javaupm_bno055.i b/src/bno055/javaupm_bno055.i index 455374a6..65ba3a59 100644 --- a/src/bno055/javaupm_bno055.i +++ b/src/bno055/javaupm_bno055.i @@ -2,69 +2,7 @@ %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 }; -%apply float *INOUT { float *heading, float *roll, float *pitch }; - -%typemap(jni) float* "jfloatArray" -%typemap(jstype) float* "float[]" -%typemap(jtype) float* "float[]" - -%typemap(javaout) float* { - return $jnicall; -} - -%typemap(jni) int* "jintArray" -%typemap(jstype) int* "int[]" -%typemap(jtype) int* "int[]" - -%typemap(javaout) int* { - return $jnicall; -} - - -%typemap(out) float *getAccelerometer { - $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); -} - -%typemap(out) float *getGyroscope { - $result = JCALL1(NewFloatArray, jenv, 3); - JCALL4(SetFloatArrayRegion, jenv, $result, 0, 3, $1); -} - -%typemap(out) float *getEulerAngles { - $result = JCALL1(NewFloatArray, jenv, 3); - JCALL4(SetFloatArrayRegion, jenv, $result, 0, 3, $1); -} - -%typemap(out) float *getQuaternions { - $result = JCALL1(NewFloatArray, jenv, 4); - JCALL4(SetFloatArrayRegion, jenv, $result, 0, 4, $1); -} - -%typemap(out) float *getLinearAcceleration { - $result = JCALL1(NewFloatArray, jenv, 3); - JCALL4(SetFloatArrayRegion, jenv, $result, 0, 3, $1); -} - -%typemap(out) float *getGravityVectors { - $result = JCALL1(NewFloatArray, jenv, 3); - JCALL4(SetFloatArrayRegion, jenv, $result, 0, 3, $1); -} - -%typemap(out) int *getCalibrationStatus { - $result = JCALL1(NewIntArray, jenv, 4); - JCALL4(SetIntArrayRegion, jenv, $result, 0, 4, (const int*)$1); -} +%include "../upm_vectortypes.i" %ignore getCalibrationStatus(int *, int *, int *, int *); %ignore getAccelerometer(float *, float *, float *); @@ -75,12 +13,12 @@ %ignore getLinearAcceleration(float *, float *, float *); %ignore getGravityVectors(float *, float *, float *); +%include "bno055_regs.h" +%include "bno055.hpp" %{ #include "bno055.hpp" %} -%include "bno055.hpp" - %pragma(java) jniclasscode=%{ static { try { diff --git a/src/bno055/jsupm_bno055.i b/src/bno055/jsupm_bno055.i index 7fa679b6..8b863a0d 100644 --- a/src/bno055/jsupm_bno055.i +++ b/src/bno055/jsupm_bno055.i @@ -1,11 +1,16 @@ %module jsupm_bno055 %include "../upm.i" %include "cpointer.i" +%include "../upm_vectortypes.i" -/* Send "int *" and "float *" to JavaScript as intp and floatp */ +/* Send "int *" and "float *" to JS as intp and floatp, though + * using the vector return (upm_vectortypes.i) functions instead of + * the pointer argument functions is preferable. + */ %pointer_functions(int, intp); %pointer_functions(float, floatp); +%include "bno055_regs.h" %include "bno055.hpp" %{ #include "bno055.hpp" diff --git a/src/bno055/pyupm_bno055.i b/src/bno055/pyupm_bno055.i index 23eead26..cabe7ef1 100644 --- a/src/bno055/pyupm_bno055.i +++ b/src/bno055/pyupm_bno055.i @@ -3,19 +3,23 @@ %module pyupm_bno055 %include "../upm.i" %include "cpointer.i" +%include "../upm_vectortypes.i" -%include "stdint.i" - -/* Send "int *" and "float *" to python as intp and floatp */ +/* Send "int *" and "float *" to python as intp and floatp, though + * using the vector return (upm_vectortypes.i) functions instead of + * the pointer argument functions is preferable. + */ %pointer_functions(int, intp); %pointer_functions(float, floatp); + %feature("autodoc", "3"); #ifdef DOXYGEN %include "bno055_doc.i" #endif +%include "bno055_regs.h" %include "bno055.hpp" %{ #include "bno055.hpp"