Fully featured I2C and SPI driver for CEVA (Hilcrest)'s BNO080 and FSM300 Inertial Measurement Units.

Dependents:   BNO080-Examples BNO080-Examples

BNO080 Driver

by Jamie Smith / USC Rocket Propulsion Lab

After lots of development, we are proud to present our driver for the Hilcrest BNO080 IMU! This driver is inspired by SparkFun and Nathan Seidle's Arduino driver for this chip, but has been substantially rewritten and adapted.

It supports the main features of the chip, such as reading rotation and acceleration data, as well as some of its more esoteric functionality, such as counting steps and detecting whether the device is being hand-held.

Features

  • Support for 15 different data reports from the IMU, from acceleration to rotation to tap detection
  • Support for reading of sensor data, and automatic checking of update rate against allowed values in metadata
  • BNO_DEBUG switch enabling verbose, detailed output about communications with the chip for ease of debugging
  • Ability to tare sensor rotation and set mounting orientation
  • Can operate in several execution modes: polling I2C, polling SPI, and threaded SPI (which handles timing-critical functions in a dedicated thread, and automatically activates when the IMU has data available)
    • Also has experimental support for using asynchronous SPI transactions, allowing other threads to execute while communication with the BNO is occurring. Note that this functionality requires a patch to Mbed OS source code due to Mbed bug #13941
  • Calibration function
  • Reasonable code size for what you get: the library uses about 4K of flash and one instance of the object uses about 1700 bytes of RAM.

Documentation

Full Doxygen documentation is available online here

Example Code

Here's a simple example:

BNO080 Rotation Vector and Acceleration

#include <mbed.h>
#include <BNO080.h>

int main()
{
	Serial pc(USBTX, USBRX);

	// Create IMU, passing in output stream, pins, I2C address, and I2C frequency
	// These pin assignments are specific to my dev setup -- you'll need to change them
	BNO080I2C imu(&pc, p28, p27, p16, p30, 0x4a, 100000); 

	pc.baud(115200);
	pc.printf("============================================================\n");

	// Tell the IMU to report rotation every 100ms and acceleration every 200ms
	imu.enableReport(BNO080::ROTATION, 100);
	imu.enableReport(BNO080::TOTAL_ACCELERATION, 200);

	while (true)
	{
		wait(.001f);
		
		// poll the IMU for new data -- this returns true if any packets were received
		if(imu.updateData())
		{
			// now check for the specific type of data that was received (can be multiple at once)
			if (imu.hasNewData(BNO080::ROTATION))
			{
				// convert quaternion to Euler degrees and print
				pc.printf("IMU Rotation Euler: ");
				TVector3 eulerRadians = imu.rotationVector.euler();
				TVector3 eulerDegrees = eulerRadians * (180.0 / M_PI);
				eulerDegrees.print(pc, true);
				pc.printf("\n");
			}
			if (imu.hasNewData(BNO080::TOTAL_ACCELERATION))
			{
				// print the acceleration vector using its builtin print() method
				pc.printf("IMU Total Acceleration: ");
				imu.totalAcceleration.print(pc, true);
				pc.printf("\n");
			}
		}
	}

}


If you want more, a comprehensive, ready-to-run set of examples is available on my BNO080-Examples repository.

Credits

This driver makes use of a lightweight, public-domain library for vectors and quaternions available here.

Changelog

Version 2.1 (Nov 24 2020)

  • Added BNO080Async, which provides a threaded implementation of the SPI driver. This should help get the best performance and remove annoying timing requirements on the code calling the driver
  • Added experimental USE_ASYNC_SPI option
  • Fixed bug in v2.0 causing calibrations to fail

Version 2.0 (Nov 18 2020)

  • Added SPI support
  • Refactored buffer system so that SPI could be implemented as a subclass. Unfortunately this does substantially increase the memory usage of the driver, but I believe that the benefits are worth it.

Version 1.3 (Jul 21 2020)

  • Fix deprecation warnings and compile errors in Mbed 6
  • Fix compile errors in Arm Compiler (why doesn't it have M_PI????)

Version 1.2 (Jan 30 2020)

  • Removed accidental IRQ change
  • Fixed hard iron offset reading incorrectly due to missing cast

Version 1.1 (Jun 14 2019)

  • Added support for changing permanent orientation
  • Add FRS writing functions
  • Removed some errant printfs

Version 1.0 (Dec 29 2018)

  • Initial Mbed OS release
Committer:
Jamie Smith
Date:
Tue Nov 24 15:06:05 2020 -0800
Revision:
9:430f5302f9e1
Implement BNO080Async

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jamie Smith 9:430f5302f9e1 1 //
Jamie Smith 9:430f5302f9e1 2 // Created by jamie on 11/18/2020.
Jamie Smith 9:430f5302f9e1 3 //
Jamie Smith 9:430f5302f9e1 4
Jamie Smith 9:430f5302f9e1 5 #include "BNO080Async.h"
Jamie Smith 9:430f5302f9e1 6
Jamie Smith 9:430f5302f9e1 7 #include <cinttypes>
Jamie Smith 9:430f5302f9e1 8
Jamie Smith 9:430f5302f9e1 9 #define BNO_ASYNC_DEBUG 0
Jamie Smith 9:430f5302f9e1 10
Jamie Smith 9:430f5302f9e1 11 // event flags constants for signalling the thread
Jamie Smith 9:430f5302f9e1 12 #define EF_INTERRUPT 0b1
Jamie Smith 9:430f5302f9e1 13 #define EF_SHUTDOWN 0b10
Jamie Smith 9:430f5302f9e1 14 #define EF_RESTART 0b100
Jamie Smith 9:430f5302f9e1 15
Jamie Smith 9:430f5302f9e1 16 void BNO080Async::threadMain()
Jamie Smith 9:430f5302f9e1 17 {
Jamie Smith 9:430f5302f9e1 18 while(commLoop())
Jamie Smith 9:430f5302f9e1 19 {
Jamie Smith 9:430f5302f9e1 20 // loop forever
Jamie Smith 9:430f5302f9e1 21 }
Jamie Smith 9:430f5302f9e1 22 }
Jamie Smith 9:430f5302f9e1 23
Jamie Smith 9:430f5302f9e1 24 bool BNO080Async::commLoop()
Jamie Smith 9:430f5302f9e1 25 {
Jamie Smith 9:430f5302f9e1 26 _rst = 0; // Reset BNO080
Jamie Smith 9:430f5302f9e1 27 ThisThread::sleep_for(1ms); // Min length not specified in datasheet?
Jamie Smith 9:430f5302f9e1 28 _rst = 1; // Bring out of reset
Jamie Smith 9:430f5302f9e1 29
Jamie Smith 9:430f5302f9e1 30 // wait for a falling edge (NOT just a low) on the INT pin to denote startup
Jamie Smith 9:430f5302f9e1 31 {
Jamie Smith 9:430f5302f9e1 32 EventFlags edgeWaitFlags;
Jamie Smith 9:430f5302f9e1 33 _int.fall(callback([&](){edgeWaitFlags.set(1);}));
Jamie Smith 9:430f5302f9e1 34
Jamie Smith 9:430f5302f9e1 35 // have the RTOS wait until an edge is detected or the timeout is hit
Jamie Smith 9:430f5302f9e1 36 uint32_t edgeWaitEvent = edgeWaitFlags.wait_any(1, (BNO080_RESET_TIMEOUT).count());
Jamie Smith 9:430f5302f9e1 37
Jamie Smith 9:430f5302f9e1 38 if(!edgeWaitEvent)
Jamie Smith 9:430f5302f9e1 39 {
Jamie Smith 9:430f5302f9e1 40 _debugPort->printf("Error: BNO080 reset timed out, chip not detected.\n");
Jamie Smith 9:430f5302f9e1 41 }
Jamie Smith 9:430f5302f9e1 42 }
Jamie Smith 9:430f5302f9e1 43
Jamie Smith 9:430f5302f9e1 44 #if BNO_ASYNC_DEBUG
Jamie Smith 9:430f5302f9e1 45 _debugPort->printf("BNO080 detected!\r\n");
Jamie Smith 9:430f5302f9e1 46 #endif
Jamie Smith 9:430f5302f9e1 47
Jamie Smith 9:430f5302f9e1 48 wakeupFlags.set(EF_INTERRUPT);
Jamie Smith 9:430f5302f9e1 49
Jamie Smith 9:430f5302f9e1 50 // configure interrupt to send the event flag
Jamie Smith 9:430f5302f9e1 51 _int.fall(callback([&]()
Jamie Smith 9:430f5302f9e1 52 {
Jamie Smith 9:430f5302f9e1 53 if(!inTXRX)
Jamie Smith 9:430f5302f9e1 54 {
Jamie Smith 9:430f5302f9e1 55 wakeupFlags.set(EF_INTERRUPT);
Jamie Smith 9:430f5302f9e1 56 }
Jamie Smith 9:430f5302f9e1 57 }));
Jamie Smith 9:430f5302f9e1 58
Jamie Smith 9:430f5302f9e1 59 while(true)
Jamie Smith 9:430f5302f9e1 60 {
Jamie Smith 9:430f5302f9e1 61 uint32_t wakeupEvent = wakeupFlags.wait_any(EF_INTERRUPT | EF_SHUTDOWN | EF_RESTART);
Jamie Smith 9:430f5302f9e1 62
Jamie Smith 9:430f5302f9e1 63 if(wakeupEvent & EF_SHUTDOWN)
Jamie Smith 9:430f5302f9e1 64 {
Jamie Smith 9:430f5302f9e1 65 // shutdown thread permanently
Jamie Smith 9:430f5302f9e1 66 return false;
Jamie Smith 9:430f5302f9e1 67 }
Jamie Smith 9:430f5302f9e1 68 else if(wakeupEvent & EF_RESTART)
Jamie Smith 9:430f5302f9e1 69 {
Jamie Smith 9:430f5302f9e1 70 // restart thread
Jamie Smith 9:430f5302f9e1 71 return true;
Jamie Smith 9:430f5302f9e1 72 }
Jamie Smith 9:430f5302f9e1 73
Jamie Smith 9:430f5302f9e1 74 // lock the mutex to handle remaining cases
Jamie Smith 9:430f5302f9e1 75 bnoDataMutex.lock();
Jamie Smith 9:430f5302f9e1 76
Jamie Smith 9:430f5302f9e1 77 if(wakeupEvent & EF_INTERRUPT)
Jamie Smith 9:430f5302f9e1 78 {
Jamie Smith 9:430f5302f9e1 79 while(_int == 0)
Jamie Smith 9:430f5302f9e1 80 {
Jamie Smith 9:430f5302f9e1 81 inTXRX = true;
Jamie Smith 9:430f5302f9e1 82
Jamie Smith 9:430f5302f9e1 83 // send data if there is data to send. This may also receive a packet.
Jamie Smith 9:430f5302f9e1 84 if (dataToSend)
Jamie Smith 9:430f5302f9e1 85 {
Jamie Smith 9:430f5302f9e1 86 BNO080SPI::sendPacket(txPacketChannelNumber, txPacketDataLength);
Jamie Smith 9:430f5302f9e1 87 dataToSend = false;
Jamie Smith 9:430f5302f9e1 88 }
Jamie Smith 9:430f5302f9e1 89 else
Jamie Smith 9:430f5302f9e1 90 {
Jamie Smith 9:430f5302f9e1 91 BNO080SPI::receivePacket();
Jamie Smith 9:430f5302f9e1 92 }
Jamie Smith 9:430f5302f9e1 93
Jamie Smith 9:430f5302f9e1 94 inTXRX = false;
Jamie Smith 9:430f5302f9e1 95
Jamie Smith 9:430f5302f9e1 96 // clear the wake flag if it was set
Jamie Smith 9:430f5302f9e1 97 _wakePin = 1;
Jamie Smith 9:430f5302f9e1 98
Jamie Smith 9:430f5302f9e1 99 // If the IMU wants to send us an interrupt immediately after a transaction,
Jamie Smith 9:430f5302f9e1 100 // it will be missed due to the inTXRX block. So, we need to keep checking _int
Jamie Smith 9:430f5302f9e1 101 // in a loop.
Jamie Smith 9:430f5302f9e1 102
Jamie Smith 9:430f5302f9e1 103 // update received flag
Jamie Smith 9:430f5302f9e1 104 dataReceived = true;
Jamie Smith 9:430f5302f9e1 105
Jamie Smith 9:430f5302f9e1 106 // check if this packet is being waited on.
Jamie Smith 9:430f5302f9e1 107 if (waitingForPacket)
Jamie Smith 9:430f5302f9e1 108 {
Jamie Smith 9:430f5302f9e1 109 if (waitingForReportID == rxShtpData[0] && waitingForChannel == rxShtpHeader[2])
Jamie Smith 9:430f5302f9e1 110 {
Jamie Smith 9:430f5302f9e1 111 // unblock main thread so it can process this packet
Jamie Smith 9:430f5302f9e1 112 waitingPacketArrived = true;
Jamie Smith 9:430f5302f9e1 113 waitingPacketArrivedCV.notify_all();
Jamie Smith 9:430f5302f9e1 114
Jamie Smith 9:430f5302f9e1 115 // unlock mutex and wait until the main thread says it's OK to receive another packet
Jamie Smith 9:430f5302f9e1 116 clearToRxNextPacket = false;
Jamie Smith 9:430f5302f9e1 117 waitingPacketProcessedCV.wait([&]() { return clearToRxNextPacket; });
Jamie Smith 9:430f5302f9e1 118 }
Jamie Smith 9:430f5302f9e1 119 }
Jamie Smith 9:430f5302f9e1 120 else
Jamie Smith 9:430f5302f9e1 121 {
Jamie Smith 9:430f5302f9e1 122 processPacket();
Jamie Smith 9:430f5302f9e1 123 }
Jamie Smith 9:430f5302f9e1 124
Jamie Smith 9:430f5302f9e1 125 // clear the interrupt flag if it has been set because we're about to check _int anyway.
Jamie Smith 9:430f5302f9e1 126 // Prevents spurious wakeups.
Jamie Smith 9:430f5302f9e1 127 wakeupFlags.clear(EF_INTERRUPT);
Jamie Smith 9:430f5302f9e1 128
Jamie Smith 9:430f5302f9e1 129 }
Jamie Smith 9:430f5302f9e1 130
Jamie Smith 9:430f5302f9e1 131 }
Jamie Smith 9:430f5302f9e1 132
Jamie Smith 9:430f5302f9e1 133 // unlock data mutex before waiting for flags
Jamie Smith 9:430f5302f9e1 134 bnoDataMutex.unlock();
Jamie Smith 9:430f5302f9e1 135 }
Jamie Smith 9:430f5302f9e1 136 }
Jamie Smith 9:430f5302f9e1 137
Jamie Smith 9:430f5302f9e1 138 bool BNO080Async::sendPacket(uint8_t channelNumber, uint8_t dataLength)
Jamie Smith 9:430f5302f9e1 139 {
Jamie Smith 9:430f5302f9e1 140 // first make sure mutex is locked
Jamie Smith 9:430f5302f9e1 141 if(bnoDataMutex.get_owner() != ThisThread::get_id())
Jamie Smith 9:430f5302f9e1 142 {
Jamie Smith 9:430f5302f9e1 143 _debugPort->printf("IMU communication function called without bnoDataMutex locked!\n");
Jamie Smith 9:430f5302f9e1 144 return false;
Jamie Smith 9:430f5302f9e1 145 }
Jamie Smith 9:430f5302f9e1 146
Jamie Smith 9:430f5302f9e1 147 // now set class variables
Jamie Smith 9:430f5302f9e1 148 txPacketChannelNumber = channelNumber;
Jamie Smith 9:430f5302f9e1 149 txPacketDataLength = dataLength;
Jamie Smith 9:430f5302f9e1 150 dataToSend = true;
Jamie Smith 9:430f5302f9e1 151
Jamie Smith 9:430f5302f9e1 152 // signal thread to wake up by sending _wake signal (which will cause the IMU to interrupt us once ready)
Jamie Smith 9:430f5302f9e1 153 _wakePin = 0;
Jamie Smith 9:430f5302f9e1 154
Jamie Smith 9:430f5302f9e1 155 return true;
Jamie Smith 9:430f5302f9e1 156 }
Jamie Smith 9:430f5302f9e1 157
Jamie Smith 9:430f5302f9e1 158 void BNO080Async::clearSendBuffer()
Jamie Smith 9:430f5302f9e1 159 {
Jamie Smith 9:430f5302f9e1 160 // first make sure mutex is locked
Jamie Smith 9:430f5302f9e1 161 if(bnoDataMutex.get_owner() != ThisThread::get_id())
Jamie Smith 9:430f5302f9e1 162 {
Jamie Smith 9:430f5302f9e1 163 _debugPort->printf("IMU communication function called without bnoDataMutex locked!\n");
Jamie Smith 9:430f5302f9e1 164 return;
Jamie Smith 9:430f5302f9e1 165 }
Jamie Smith 9:430f5302f9e1 166
Jamie Smith 9:430f5302f9e1 167 // Check if we are trying to send a packet while another packet is still queued.
Jamie Smith 9:430f5302f9e1 168 // Since we don't have an actual queue, just wait until the other packet is sent.
Jamie Smith 9:430f5302f9e1 169 while(dataToSend)
Jamie Smith 9:430f5302f9e1 170 {
Jamie Smith 9:430f5302f9e1 171 dataSentCV.wait();
Jamie Smith 9:430f5302f9e1 172 }
Jamie Smith 9:430f5302f9e1 173
Jamie Smith 9:430f5302f9e1 174 // now actually erase the buffer
Jamie Smith 9:430f5302f9e1 175 BNO080Base::clearSendBuffer();
Jamie Smith 9:430f5302f9e1 176 }
Jamie Smith 9:430f5302f9e1 177
Jamie Smith 9:430f5302f9e1 178 bool BNO080Async::waitForPacket(int channel, uint8_t reportID, std::chrono::milliseconds timeout)
Jamie Smith 9:430f5302f9e1 179 {
Jamie Smith 9:430f5302f9e1 180 // first make sure mutex is locked
Jamie Smith 9:430f5302f9e1 181 if(bnoDataMutex.get_owner() != ThisThread::get_id())
Jamie Smith 9:430f5302f9e1 182 {
Jamie Smith 9:430f5302f9e1 183 _debugPort->printf("IMU communication function called without bnoDataMutex locked!\n");
Jamie Smith 9:430f5302f9e1 184 return false;
Jamie Smith 9:430f5302f9e1 185 }
Jamie Smith 9:430f5302f9e1 186
Jamie Smith 9:430f5302f9e1 187 // send information to thread
Jamie Smith 9:430f5302f9e1 188 waitingForPacket = true;
Jamie Smith 9:430f5302f9e1 189 waitingForChannel = channel;
Jamie Smith 9:430f5302f9e1 190 waitingForReportID = reportID;
Jamie Smith 9:430f5302f9e1 191 waitingPacketArrived = false;
Jamie Smith 9:430f5302f9e1 192
Jamie Smith 9:430f5302f9e1 193 // now unlock mutex and allow thread to run and receive packets
Jamie Smith 9:430f5302f9e1 194 waitingPacketArrivedCV.wait_for(timeout, [&]() {return waitingPacketArrived;});
Jamie Smith 9:430f5302f9e1 195
Jamie Smith 9:430f5302f9e1 196 if(!waitingPacketArrived)
Jamie Smith 9:430f5302f9e1 197 {
Jamie Smith 9:430f5302f9e1 198 _debugPort->printf("Packet wait timeout.\n");
Jamie Smith 9:430f5302f9e1 199 return false;
Jamie Smith 9:430f5302f9e1 200 }
Jamie Smith 9:430f5302f9e1 201
Jamie Smith 9:430f5302f9e1 202 // packet we are waiting for is now in the buffer.
Jamie Smith 9:430f5302f9e1 203 waitingForPacket = false;
Jamie Smith 9:430f5302f9e1 204
Jamie Smith 9:430f5302f9e1 205 // Now we can unblock the comms thread and allow it to run.
Jamie Smith 9:430f5302f9e1 206 // BUT, it can't actually start until bnoDataMutex is released.
Jamie Smith 9:430f5302f9e1 207 // This means that the packet data is guaranteed to stay in the buffer until that mutex is released
Jamie Smith 9:430f5302f9e1 208 // which will happen either when the main thread is done with the IMU, or on the next sendPacket() or
Jamie Smith 9:430f5302f9e1 209 // waitForPacket() call.
Jamie Smith 9:430f5302f9e1 210 clearToRxNextPacket = true;
Jamie Smith 9:430f5302f9e1 211 waitingPacketProcessedCV.notify_all();
Jamie Smith 9:430f5302f9e1 212
Jamie Smith 9:430f5302f9e1 213 return true;
Jamie Smith 9:430f5302f9e1 214 }
Jamie Smith 9:430f5302f9e1 215
Jamie Smith 9:430f5302f9e1 216 BNO080Async::BNO080Async(Stream *debugPort, PinName rstPin, PinName intPin, PinName wakePin, PinName misoPin,
Jamie Smith 9:430f5302f9e1 217 PinName mosiPin, PinName sclkPin, PinName csPin, int spiSpeed, osPriority_t threadPriority):
Jamie Smith 9:430f5302f9e1 218 BNO080SPI(debugPort, rstPin, intPin, wakePin, misoPin, mosiPin, sclkPin, csPin, spiSpeed),
Jamie Smith 9:430f5302f9e1 219 commThread(threadPriority),
Jamie Smith 9:430f5302f9e1 220 dataSentCV(bnoDataMutex),
Jamie Smith 9:430f5302f9e1 221 waitingPacketArrivedCV(bnoDataMutex),
Jamie Smith 9:430f5302f9e1 222 waitingPacketProcessedCV(bnoDataMutex)
Jamie Smith 9:430f5302f9e1 223 {
Jamie Smith 9:430f5302f9e1 224
Jamie Smith 9:430f5302f9e1 225 }
Jamie Smith 9:430f5302f9e1 226
Jamie Smith 9:430f5302f9e1 227
Jamie Smith 9:430f5302f9e1 228 bool BNO080Async::begin()
Jamie Smith 9:430f5302f9e1 229 {
Jamie Smith 9:430f5302f9e1 230 // shut down thread if it's running
Jamie Smith 9:430f5302f9e1 231 if(commThread.get_state() == Thread::Deleted)
Jamie Smith 9:430f5302f9e1 232 {
Jamie Smith 9:430f5302f9e1 233 // start thread for the first time
Jamie Smith 9:430f5302f9e1 234 commThread.start(callback(this, &BNO080Async::threadMain));
Jamie Smith 9:430f5302f9e1 235 }
Jamie Smith 9:430f5302f9e1 236 else
Jamie Smith 9:430f5302f9e1 237 {
Jamie Smith 9:430f5302f9e1 238 // restart thread
Jamie Smith 9:430f5302f9e1 239 wakeupFlags.set(EF_RESTART);
Jamie Smith 9:430f5302f9e1 240 }
Jamie Smith 9:430f5302f9e1 241
Jamie Smith 9:430f5302f9e1 242
Jamie Smith 9:430f5302f9e1 243 {
Jamie Smith 9:430f5302f9e1 244 ScopedLock<Mutex> lock(bnoDataMutex);
Jamie Smith 9:430f5302f9e1 245
Jamie Smith 9:430f5302f9e1 246 // once the thread starts it, the BNO will send an Unsolicited Initialize response (SH-2 section 6.4.5.2), and an Executable Reset command
Jamie Smith 9:430f5302f9e1 247 if(!waitForPacket(CHANNEL_EXECUTABLE, EXECUTABLE_REPORTID_RESET, 1s))
Jamie Smith 9:430f5302f9e1 248 {
Jamie Smith 9:430f5302f9e1 249 _debugPort->printf("No initialization report from BNO080.\n");
Jamie Smith 9:430f5302f9e1 250 return false;
Jamie Smith 9:430f5302f9e1 251 }
Jamie Smith 9:430f5302f9e1 252 else
Jamie Smith 9:430f5302f9e1 253 {
Jamie Smith 9:430f5302f9e1 254 #if BNO_DEBUG
Jamie Smith 9:430f5302f9e1 255 _debugPort->printf("BNO080 reports initialization successful!\n");
Jamie Smith 9:430f5302f9e1 256 #endif
Jamie Smith 9:430f5302f9e1 257 }
Jamie Smith 9:430f5302f9e1 258
Jamie Smith 9:430f5302f9e1 259 // Finally, we want to interrogate the device about its model and version.
Jamie Smith 9:430f5302f9e1 260 clearSendBuffer();
Jamie Smith 9:430f5302f9e1 261 txShtpData[0] = SHTP_REPORT_PRODUCT_ID_REQUEST; //Request the product ID and reset info
Jamie Smith 9:430f5302f9e1 262 txShtpData[1] = 0; //Reserved
Jamie Smith 9:430f5302f9e1 263 sendPacket(CHANNEL_CONTROL, 2);
Jamie Smith 9:430f5302f9e1 264
Jamie Smith 9:430f5302f9e1 265 waitForPacket(CHANNEL_CONTROL, SHTP_REPORT_PRODUCT_ID_RESPONSE);
Jamie Smith 9:430f5302f9e1 266
Jamie Smith 9:430f5302f9e1 267 if (rxShtpData[0] == SHTP_REPORT_PRODUCT_ID_RESPONSE)
Jamie Smith 9:430f5302f9e1 268 {
Jamie Smith 9:430f5302f9e1 269 majorSoftwareVersion = rxShtpData[2];
Jamie Smith 9:430f5302f9e1 270 minorSoftwareVersion = rxShtpData[3];
Jamie Smith 9:430f5302f9e1 271 patchSoftwareVersion = (rxShtpData[13] << 8) | rxShtpData[12];
Jamie Smith 9:430f5302f9e1 272 partNumber = (rxShtpData[7] << 24) | (rxShtpData[6] << 16) | (rxShtpData[5] << 8) | rxShtpData[4];
Jamie Smith 9:430f5302f9e1 273 buildNumber = (rxShtpData[11] << 24) | (rxShtpData[10] << 16) | (rxShtpData[9] << 8) | rxShtpData[8];
Jamie Smith 9:430f5302f9e1 274
Jamie Smith 9:430f5302f9e1 275 #if BNO_DEBUG
Jamie Smith 9:430f5302f9e1 276 _debugPort->printf("BNO080 reports as SW version %hhu.%hhu.%hu, build %lu, part no. %lu\n",
Jamie Smith 9:430f5302f9e1 277 majorSoftwareVersion, minorSoftwareVersion, patchSoftwareVersion,
Jamie Smith 9:430f5302f9e1 278 buildNumber, partNumber);
Jamie Smith 9:430f5302f9e1 279 #endif
Jamie Smith 9:430f5302f9e1 280
Jamie Smith 9:430f5302f9e1 281 }
Jamie Smith 9:430f5302f9e1 282 else
Jamie Smith 9:430f5302f9e1 283 {
Jamie Smith 9:430f5302f9e1 284 _debugPort->printf("Bad response from product ID command.\n");
Jamie Smith 9:430f5302f9e1 285 return false;
Jamie Smith 9:430f5302f9e1 286 }
Jamie Smith 9:430f5302f9e1 287 }
Jamie Smith 9:430f5302f9e1 288
Jamie Smith 9:430f5302f9e1 289
Jamie Smith 9:430f5302f9e1 290 // successful init
Jamie Smith 9:430f5302f9e1 291 return true;
Jamie Smith 9:430f5302f9e1 292 }
Jamie Smith 9:430f5302f9e1 293
Jamie Smith 9:430f5302f9e1 294 bool BNO080Async::updateData()
Jamie Smith 9:430f5302f9e1 295 {
Jamie Smith 9:430f5302f9e1 296 bool newData = dataReceived;
Jamie Smith 9:430f5302f9e1 297 dataReceived = false;
Jamie Smith 9:430f5302f9e1 298 return newData;
Jamie Smith 9:430f5302f9e1 299 }
Jamie Smith 9:430f5302f9e1 300
Jamie Smith 9:430f5302f9e1 301
Jamie Smith 9:430f5302f9e1 302
Jamie Smith 9:430f5302f9e1 303
Jamie Smith 9:430f5302f9e1 304
Jamie Smith 9:430f5302f9e1 305