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 <jtrulson@ics.com>
This commit is contained in:
Jon Trulson 2017-03-07 12:43:44 -07:00
parent 2bdde21a2f
commit d4b536b593
16 changed files with 3382 additions and 2155 deletions

View File

@ -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

View File

@ -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

View File

@ -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)

119
examples/c/bno055.c Normal file
View File

@ -0,0 +1,119 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* 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 <unistd.h>
#include <stdbool.h>
#include <stdio.h>
#include <upm_utilities.h>
#include <signal.h>
#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;
}

View File

@ -1,6 +1,8 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* 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);

View File

@ -1,6 +1,8 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* 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("");
};

View File

@ -1,6 +1,8 @@
#!/usr/bin/python
# Author: Jon Trulson <jtrulson@ics.com>
# 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()

View File

@ -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)

910
src/bno055/bno055.c Normal file
View File

@ -0,0 +1,910 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* 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 <string.h>
#include <assert.h>
#include <upm_utilities.h>
#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; i<len; i++)
buf[i+1] = buffer[i];
if (mraa_i2c_write(dev->i2c, 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;
}
}

View File

@ -1,6 +1,8 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* 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 <unistd.h>
#include <iostream>
#include <stdexcept>
#include <string>
#include <string.h>
#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<len; i++)
buf[i+1] = buffer[i];
mraa::Result rv;
if ((rv = m_i2c.write(buf, len+1)) != mraa::SUCCESS)
{
throw std::runtime_error(std::string(__FUNCTION__)
+ ": I2c.write() failed");
}
return true;
if (bno055_write_regs(m_bno055, reg, buffer, len))
throw std::runtime_error(string(__FUNCTION__)
+ ": bno055_write_regs() failed");
}
uint8_t BNO055::getChipID()
{
setPage(0);
return readReg(REG_CHIP_ID);
return bno055_get_chip_id(m_bno055);
}
uint8_t BNO055::getACCID()
{
setPage(0);
return readReg(REG_ACC_ID);
return bno055_get_acc_id(m_bno055);
}
uint8_t BNO055::getMAGID()
{
setPage(0);
return readReg(REG_MAG_ID);
return bno055_get_mag_id(m_bno055);
}
uint8_t BNO055::getGYRID()
{
setPage(0);
return readReg(REG_GYR_ID);
return bno055_get_gyr_id(m_bno055);
}
uint16_t BNO055::getSWRevID()
{
setPage(0);
uint16_t vers = uint16_t( readReg(REG_SW_REV_ID_LSB) |
(readReg(REG_SW_REV_ID_MSB) << 8) );
return vers;
return bno055_get_sw_revision(m_bno055);
}
uint8_t BNO055::getBootLoaderID()
{
setPage(0);
return readReg(REG_BL_REV_ID);
return bno055_get_bootloader_id(m_bno055);
}
void BNO055::setPage(uint8_t page, bool force)
{
// page can only be 0 or 1
if (!(page == 0 || page == 1))
throw std::out_of_range(string(__FUNCTION__) +
": page can only be 0 or 1");
if (force || page != m_currentPage)
writeReg(REG_PAGE_ID, page);
m_currentPage = page;
if (bno055_set_page(m_bno055, page, force))
throw std::runtime_error(string(__FUNCTION__)
+ ": bno055_set_page() failed");
}
void BNO055::setClockExternal(bool extClock)
{
setPage(0);
// first we need to be in config mode
OPERATION_MODES_T currentMode = m_currentMode;
setOperationMode(OPERATION_MODE_CONFIGMODE);
uint8_t reg = readReg(REG_SYS_TRIGGER);
if (extClock)
reg |= SYS_TRIGGER_CLK_SEL;
else
reg &= ~SYS_TRIGGER_CLK_SEL;
writeReg(REG_SYS_TRIGGER, reg);
// now reset our operating mode
setOperationMode(currentMode);
bno055_set_clock_external(m_bno055, extClock);
}
void BNO055::setTemperatureSource(TEMP_SOURCES_T src)
void BNO055::setTemperatureSource(BNO055_TEMP_SOURCES_T src)
{
setPage(0);
writeReg(REG_TEMP_SOURCE, src);
}
void BNO055::setTemperatureUnits(bool celsius)
{
setPage(0);
uint8_t reg = readReg(REG_UNIT_SEL);
if (celsius)
reg &= ~UNIT_SEL_TEMP_UNIT;
else
reg |= UNIT_SEL_TEMP_UNIT;
writeReg(REG_UNIT_SEL, reg);
m_tempIsC = celsius;
bno055_set_temperature_source(m_bno055, src);
}
void BNO055::setAccelerometerUnits(bool mg)
{
setPage(0);
uint8_t reg = readReg(REG_UNIT_SEL);
if (mg)
{
reg |= UNIT_SEL_ACC_UNIT;
m_accUnitScale = 1.0;
}
else
{
reg &= ~UNIT_SEL_ACC_UNIT;
m_accUnitScale = 100.0;
}
writeReg(REG_UNIT_SEL, reg);
bno055_set_accelerometer_units(m_bno055, mg);
}
void BNO055::setGyroscopeUnits(bool radians)
{
setPage(0);
uint8_t reg = readReg(REG_UNIT_SEL);
if (radians)
{
reg |= UNIT_SEL_GYR_UNIT;
m_gyrUnitScale = 900.0;
}
else
{
reg &= ~UNIT_SEL_GYR_UNIT;
m_gyrUnitScale = 16.0;
}
writeReg(REG_UNIT_SEL, reg);
bno055_set_gyroscope_units(m_bno055, radians);
}
void BNO055::setEulerUnits(bool radians)
{
setPage(0);
uint8_t reg = readReg(REG_UNIT_SEL);
if (radians)
{
reg |= UNIT_SEL_EUL_UNIT;
m_eulUnitScale = 900.0;
}
else
{
reg &= ~UNIT_SEL_EUL_UNIT;
m_eulUnitScale = 16.0;
}
writeReg(REG_UNIT_SEL, reg);
bno055_set_euler_units(m_bno055, radians);
}
void BNO055::setOperationMode(OPERATION_MODES_T mode)
void BNO055::setOperationMode(BNO055_OPERATION_MODES_T mode)
{
setPage(0);
// we clear all of our loaded data on mode changes
clearData();
uint8_t reg = readReg(REG_OPER_MODE);
reg &= ~(_OPR_MODE_OPERATION_MODE_MASK << _OPR_MODE_OPERATION_MODE_SHIFT);
reg |= (mode << _OPR_MODE_OPERATION_MODE_SHIFT);
writeReg(REG_OPER_MODE, reg);
m_currentMode = mode;
usleep(30);
bno055_set_operation_mode(m_bno055, mode);
}
void BNO055::getCalibrationStatus(int *mag, int *acc, int *gyr, int *sys)
{
setPage(0);
uint8_t reg = readReg(REG_CALIB_STAT);
if (mag)
*mag = (reg >> _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<int> 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<int>(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<BNO055::SYS_STATUS_T>(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<BNO055::SYS_ERR_T>(readReg(REG_SYS_ERROR));
return bno055_get_system_error(m_bno055);
}
string BNO055::readCalibrationData()
std::vector<uint8_t> 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<uint8_t>(calibrationData,
calibrationData+BNO055_CALIBRATION_DATA_SIZE);
}
void BNO055::writeCalibrationData(string calibData)
void BNO055::writeCalibrationData(vector<uint8_t> calibrationData)
{
if (static_cast<int>(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<float> 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<float>(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<float> 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<float>(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<float> 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<float>(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<float> 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<float>(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<float> 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<float>(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<float> 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<float>(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<float> 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<float>(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);
}

676
src/bno055/bno055.h Normal file
View File

@ -0,0 +1,676 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* 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 <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <upm.h>
#include <mraa/i2c.h>
#include <mraa/gpio.h>
#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

File diff suppressed because it is too large Load Diff

825
src/bno055/bno055_regs.h Normal file
View File

@ -0,0 +1,825 @@
/*
* Author: Jon Trulson <jtrulson@ics.com>
* 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

View File

@ -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 {

View File

@ -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"

View File

@ -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"