start the wrapper burrito

Committer:
MultipleMonomials
Date:
Sun Dec 23 05:23:21 2018 +0000
Revision:
0:f677e13975d0
Child:
1:aac28ffd63ed
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MultipleMonomials 0:f677e13975d0 1 //
MultipleMonomials 0:f677e13975d0 2 // USC RPL BNO080 driver.
MultipleMonomials 0:f677e13975d0 3 //
MultipleMonomials 0:f677e13975d0 4
MultipleMonomials 0:f677e13975d0 5 /*
MultipleMonomials 0:f677e13975d0 6 * Overview of BNO080 Communications
MultipleMonomials 0:f677e13975d0 7 * ===============================================
MultipleMonomials 0:f677e13975d0 8 *
MultipleMonomials 0:f677e13975d0 9 * Hilcrest has developed a protocol called SHTP (Sensor Hub Transport Protocol) for binary communications with
MultipleMonomials 0:f677e13975d0 10 * the BNO080 and the other IMUs it sells. Over this protocol, SH-2 (Sensor Hub 2) messages are sent to configure
MultipleMonomials 0:f677e13975d0 11 * the chip and read data back.
MultipleMonomials 0:f677e13975d0 12 *
MultipleMonomials 0:f677e13975d0 13 * SHTP messages are divided at two hierarchical levels: first the channel, then the report ID. Each category
MultipleMonomials 0:f677e13975d0 14 * of messages (system commands, sensor data reports, etc.) has its own channel, and the individual messages
MultipleMonomials 0:f677e13975d0 15 * in each channel are identified by their report id, which is the first byte of the message payload (note that the
MultipleMonomials 0:f677e13975d0 16 * datasheets don't *always* call the first byte the report ID, but that byte does identify the report, so I'm going
MultipleMonomials 0:f677e13975d0 17 * with it).
MultipleMonomials 0:f677e13975d0 18 *
MultipleMonomials 0:f677e13975d0 19 * ===============================================
MultipleMonomials 0:f677e13975d0 20 *
MultipleMonomials 0:f677e13975d0 21 * Information about the BNO080 is split into three datasheets. Here's the download links and what they cover:
MultipleMonomials 0:f677e13975d0 22 *
MultipleMonomials 0:f677e13975d0 23 * - the BNO080 datasheet: http://www.hillcrestlabs.com/download/5a05f340566d07c196001ec1
MultipleMonomials 0:f677e13975d0 24 * -- Chip pinouts
MultipleMonomials 0:f677e13975d0 25 * -- Example circuits
MultipleMonomials 0:f677e13975d0 26 * -- Physical specifications
MultipleMonomials 0:f677e13975d0 27 * -- Supported reports and configuration settings (at a high level)
MultipleMonomials 0:f677e13975d0 28 * -- List of packets on the SHTP executable channel
MultipleMonomials 0:f677e13975d0 29 *
MultipleMonomials 0:f677e13975d0 30 * - the SHTP protocol: http://www.hillcrestlabs.com/download/59de8f99cd829e94dc0029d7
MultipleMonomials 0:f677e13975d0 31 * -- SHTP transmit and receive protcols (for SPI, I2C, and UART)
MultipleMonomials 0:f677e13975d0 32 * -- SHTP binary format
MultipleMonomials 0:f677e13975d0 33 * -- packet types on the SHTP command channel
MultipleMonomials 0:f677e13975d0 34 *
MultipleMonomials 0:f677e13975d0 35 * - the SH-2 reference: http://www.hillcrestlabs.com/download/59de8f398934bf6faa00293f
MultipleMonomials 0:f677e13975d0 36 * -- list of packets and their formats for all channels other than command and executable
MultipleMonomials 0:f677e13975d0 37 * -- list of FRS (Flash Record System) entries and their formats
MultipleMonomials 0:f677e13975d0 38 *
MultipleMonomials 0:f677e13975d0 39 * ===============================================
MultipleMonomials 0:f677e13975d0 40 *
MultipleMonomials 0:f677e13975d0 41 * Overview of SHTP channels:
MultipleMonomials 0:f677e13975d0 42 *
MultipleMonomials 0:f677e13975d0 43 * 0 -> Command
MultipleMonomials 0:f677e13975d0 44 * -- Used for protocol-global packets, currently only the advertisement packet (which lists all the channels) and error reports
MultipleMonomials 0:f677e13975d0 45 *
MultipleMonomials 0:f677e13975d0 46 * 1 -> Executable
MultipleMonomials 0:f677e13975d0 47 * -- Used for things that control the software on the chip: commands to reset and sleep
MultipleMonomials 0:f677e13975d0 48 * -- Also used by the chip to report when it's done booting up
MultipleMonomials 0:f677e13975d0 49 *
MultipleMonomials 0:f677e13975d0 50 * 2 -> Control
MultipleMonomials 0:f677e13975d0 51 * -- Used to send configuration commands to the IMU and for it to send back responses.
MultipleMonomials 0:f677e13975d0 52 * -- Common report IDs: Command Request (0xF2), Set Feature (0xFD)
MultipleMonomials 0:f677e13975d0 53 *
MultipleMonomials 0:f677e13975d0 54 * 3 -> Sensor Reports
MultipleMonomials 0:f677e13975d0 55 * -- Used for sensors to send back data reports.
MultipleMonomials 0:f677e13975d0 56 * -- AFAIK the only report ID on this channel will be 0xFB (Report Base Timestamp); sensor data is send in a series of structures
MultipleMonomials 0:f677e13975d0 57 * following an 0xFB
MultipleMonomials 0:f677e13975d0 58 *
MultipleMonomials 0:f677e13975d0 59 * 4 -> Wake Sensor Reports
MultipleMonomials 0:f677e13975d0 60 * -- same as above, but for sensors configured to wake the device
MultipleMonomials 0:f677e13975d0 61 *
MultipleMonomials 0:f677e13975d0 62 * 5 -> Gyro Rotation Vector
MultipleMonomials 0:f677e13975d0 63 * -- a dedicated channel for the Gyro Rotation Vector sensor report
MultipleMonomials 0:f677e13975d0 64 * -- Why does this get its own channel? I don't know!!!
MultipleMonomials 0:f677e13975d0 65 */
MultipleMonomials 0:f677e13975d0 66
MultipleMonomials 0:f677e13975d0 67 #include "BNO080.h"
MultipleMonomials 0:f677e13975d0 68 #include "BNO080Constants.h"
MultipleMonomials 0:f677e13975d0 69
MultipleMonomials 0:f677e13975d0 70 /// Set to 1 to enable debug printouts. Should be very useful if the chip is giving you trouble.
MultipleMonomials 0:f677e13975d0 71 /// When debugging, it is recommended to use the highest possible serial baudrate so as not to interrupt the timing of operations.
MultipleMonomials 0:f677e13975d0 72 #define BNO_DEBUG 1
MultipleMonomials 0:f677e13975d0 73
MultipleMonomials 0:f677e13975d0 74 BNO080::BNO080(Serial *debugPort, PinName user_SDApin, PinName user_SCLpin, PinName user_INTPin, PinName user_RSTPin,
MultipleMonomials 0:f677e13975d0 75 uint8_t i2cAddress, int i2cPortSpeed) :
MultipleMonomials 0:f677e13975d0 76 _debugPort(debugPort),
MultipleMonomials 0:f677e13975d0 77 _i2cPort(user_SDApin, user_SCLpin),
MultipleMonomials 0:f677e13975d0 78 _i2cAddress(i2cAddress),
MultipleMonomials 0:f677e13975d0 79 _int(user_INTPin),
MultipleMonomials 0:f677e13975d0 80 _rst(user_RSTPin, 1),
MultipleMonomials 0:f677e13975d0 81 _scope(p21, 1)
MultipleMonomials 0:f677e13975d0 82 {
MultipleMonomials 0:f677e13975d0 83 //Get user settings
MultipleMonomials 0:f677e13975d0 84 _i2cPortSpeed = i2cPortSpeed;
MultipleMonomials 0:f677e13975d0 85 if(_i2cPortSpeed > 4000000)
MultipleMonomials 0:f677e13975d0 86 {
MultipleMonomials 0:f677e13975d0 87 _i2cPortSpeed = 4000000; //BNO080 max is 400Khz
MultipleMonomials 0:f677e13975d0 88 }
MultipleMonomials 0:f677e13975d0 89 _i2cPort.frequency(_i2cPortSpeed);
MultipleMonomials 0:f677e13975d0 90
MultipleMonomials 0:f677e13975d0 91 }
MultipleMonomials 0:f677e13975d0 92
MultipleMonomials 0:f677e13975d0 93 bool BNO080::begin()
MultipleMonomials 0:f677e13975d0 94 {
MultipleMonomials 0:f677e13975d0 95 //Configure the BNO080 for SPI communication
MultipleMonomials 0:f677e13975d0 96
MultipleMonomials 0:f677e13975d0 97 _rst = 0; // Reset BNO080
MultipleMonomials 0:f677e13975d0 98 wait(.002f); // Min length not specified in datasheet?
MultipleMonomials 0:f677e13975d0 99 _rst = 1; // Bring out of reset
MultipleMonomials 0:f677e13975d0 100
MultipleMonomials 0:f677e13975d0 101 // wait for a falling edge (NOT just a low) on the INT pin to denote startup
MultipleMonomials 0:f677e13975d0 102 Timer timeoutTimer;
MultipleMonomials 0:f677e13975d0 103
MultipleMonomials 0:f677e13975d0 104 bool highDetected = false;
MultipleMonomials 0:f677e13975d0 105 bool lowDetected = false;
MultipleMonomials 0:f677e13975d0 106
MultipleMonomials 0:f677e13975d0 107 while(true)
MultipleMonomials 0:f677e13975d0 108 {
MultipleMonomials 0:f677e13975d0 109 if(timeoutTimer.read() > BNO080_RESET_TIMEOUT)
MultipleMonomials 0:f677e13975d0 110 {
MultipleMonomials 0:f677e13975d0 111 _debugPort->printf("Error: BNO080 reset timed out, chip not detected.\n");
MultipleMonomials 0:f677e13975d0 112 return false;
MultipleMonomials 0:f677e13975d0 113 }
MultipleMonomials 0:f677e13975d0 114
MultipleMonomials 0:f677e13975d0 115 // simple edge detector
MultipleMonomials 0:f677e13975d0 116 if(!highDetected)
MultipleMonomials 0:f677e13975d0 117 {
MultipleMonomials 0:f677e13975d0 118 if(_int == 1)
MultipleMonomials 0:f677e13975d0 119 {
MultipleMonomials 0:f677e13975d0 120 highDetected = true;
MultipleMonomials 0:f677e13975d0 121 }
MultipleMonomials 0:f677e13975d0 122 }
MultipleMonomials 0:f677e13975d0 123 else if(!lowDetected)
MultipleMonomials 0:f677e13975d0 124 {
MultipleMonomials 0:f677e13975d0 125 if(_int == 0)
MultipleMonomials 0:f677e13975d0 126 {
MultipleMonomials 0:f677e13975d0 127 lowDetected = true;
MultipleMonomials 0:f677e13975d0 128 }
MultipleMonomials 0:f677e13975d0 129 }
MultipleMonomials 0:f677e13975d0 130 else
MultipleMonomials 0:f677e13975d0 131 {
MultipleMonomials 0:f677e13975d0 132 // high and low detected
MultipleMonomials 0:f677e13975d0 133 break;
MultipleMonomials 0:f677e13975d0 134 }
MultipleMonomials 0:f677e13975d0 135 }
MultipleMonomials 0:f677e13975d0 136
MultipleMonomials 0:f677e13975d0 137 _debugPort->printf("BNO080 detected!\n");
MultipleMonomials 0:f677e13975d0 138
MultipleMonomials 0:f677e13975d0 139 // At system startup, the hub must send its full advertisement message (see SHTP 5.2 and 5.3) to the
MultipleMonomials 0:f677e13975d0 140 // host. It must not send any other data until this step is complete.
MultipleMonomials 0:f677e13975d0 141 // We don't actually care what's in it, we're just using it as a signal to indicate that the reset is complete.
MultipleMonomials 0:f677e13975d0 142 receivePacket();
MultipleMonomials 0:f677e13975d0 143
MultipleMonomials 0:f677e13975d0 144 // now, after startup, the BNO will send an Unsolicited Initialize response (SH-2 section 6.4.5.2), and an Executable Reset command
MultipleMonomials 0:f677e13975d0 145 waitForPacket(CHANNEL_EXECUTABLE, EXECUTABLE_REPORTID_RESET);
MultipleMonomials 0:f677e13975d0 146
MultipleMonomials 0:f677e13975d0 147 // Next, officially tell it to initialize, and wait for a successful Initialize Response
MultipleMonomials 0:f677e13975d0 148 zeroBuffer();
MultipleMonomials 0:f677e13975d0 149 shtpData[3] = 0;
MultipleMonomials 0:f677e13975d0 150 _scope = 0;
MultipleMonomials 0:f677e13975d0 151 sendCommand(COMMAND_INITIALIZE);
MultipleMonomials 0:f677e13975d0 152
MultipleMonomials 0:f677e13975d0 153
MultipleMonomials 0:f677e13975d0 154 if(!waitForPacket(CHANNEL_CONTROL, SHTP_REPORT_COMMAND_RESPONSE) || shtpData[2] != COMMAND_INITIALIZE || shtpData[5] != 0)
MultipleMonomials 0:f677e13975d0 155 {
MultipleMonomials 0:f677e13975d0 156 _debugPort->printf("BNO080 reports initialization failed.\n");
MultipleMonomials 0:f677e13975d0 157 __enable_irq();
MultipleMonomials 0:f677e13975d0 158 return false;
MultipleMonomials 0:f677e13975d0 159 }
MultipleMonomials 0:f677e13975d0 160 else
MultipleMonomials 0:f677e13975d0 161 {
MultipleMonomials 0:f677e13975d0 162 #if BNO_DEBUG
MultipleMonomials 0:f677e13975d0 163 _debugPort->printf("BNO080 reports initialization successful!\n");
MultipleMonomials 0:f677e13975d0 164 #endif
MultipleMonomials 0:f677e13975d0 165 }
MultipleMonomials 0:f677e13975d0 166
MultipleMonomials 0:f677e13975d0 167
MultipleMonomials 0:f677e13975d0 168 // Finally, we want to interrogate the device about its model and version.
MultipleMonomials 0:f677e13975d0 169 zeroBuffer();
MultipleMonomials 0:f677e13975d0 170 shtpData[0] = SHTP_REPORT_PRODUCT_ID_REQUEST; //Request the product ID and reset info
MultipleMonomials 0:f677e13975d0 171 shtpData[1] = 0; //Reserved
MultipleMonomials 0:f677e13975d0 172 sendPacket(CHANNEL_CONTROL, 2);
MultipleMonomials 0:f677e13975d0 173
MultipleMonomials 0:f677e13975d0 174 waitForPacket(CHANNEL_CONTROL, SHTP_REPORT_PRODUCT_ID_RESPONSE, 5);
MultipleMonomials 0:f677e13975d0 175
MultipleMonomials 0:f677e13975d0 176 if (shtpData[0] == SHTP_REPORT_PRODUCT_ID_RESPONSE)
MultipleMonomials 0:f677e13975d0 177 {
MultipleMonomials 0:f677e13975d0 178 majorSoftwareVersion = shtpData[2];
MultipleMonomials 0:f677e13975d0 179 minorSoftwareVersion = shtpData[3];
MultipleMonomials 0:f677e13975d0 180 patchSoftwareVersion = (shtpData[13] << 8) | shtpData[12];
MultipleMonomials 0:f677e13975d0 181 partNumber = (shtpData[7] << 24) | (shtpData[6] << 16) | (shtpData[5] << 8) | shtpData[4];
MultipleMonomials 0:f677e13975d0 182 buildNumber = (shtpData[11] << 24) | (shtpData[10] << 16) | (shtpData[9] << 8) | shtpData[8];
MultipleMonomials 0:f677e13975d0 183
MultipleMonomials 0:f677e13975d0 184 #if BNO_DEBUG
MultipleMonomials 0:f677e13975d0 185 _debugPort->printf("BNO080 reports as SW version %hhu.%hhu.%hu, build %lu, part no. %lu\n",
MultipleMonomials 0:f677e13975d0 186 majorSoftwareVersion, minorSoftwareVersion, patchSoftwareVersion,
MultipleMonomials 0:f677e13975d0 187 buildNumber, partNumber);
MultipleMonomials 0:f677e13975d0 188 #endif
MultipleMonomials 0:f677e13975d0 189
MultipleMonomials 0:f677e13975d0 190 }
MultipleMonomials 0:f677e13975d0 191 else
MultipleMonomials 0:f677e13975d0 192 {
MultipleMonomials 0:f677e13975d0 193 _debugPort->printf("Bad response from product ID command.\n");
MultipleMonomials 0:f677e13975d0 194 return false;
MultipleMonomials 0:f677e13975d0 195 }
MultipleMonomials 0:f677e13975d0 196
MultipleMonomials 0:f677e13975d0 197 // successful init
MultipleMonomials 0:f677e13975d0 198 return true;
MultipleMonomials 0:f677e13975d0 199
MultipleMonomials 0:f677e13975d0 200 }
MultipleMonomials 0:f677e13975d0 201
MultipleMonomials 0:f677e13975d0 202 void BNO080::tare(bool zOnly)
MultipleMonomials 0:f677e13975d0 203 {
MultipleMonomials 0:f677e13975d0 204 zeroBuffer();
MultipleMonomials 0:f677e13975d0 205
MultipleMonomials 0:f677e13975d0 206 // from SH-2 section 6.4.4.1
MultipleMonomials 0:f677e13975d0 207 shtpData[3] = 0; // perform tare now
MultipleMonomials 0:f677e13975d0 208
MultipleMonomials 0:f677e13975d0 209 if(zOnly)
MultipleMonomials 0:f677e13975d0 210 {
MultipleMonomials 0:f677e13975d0 211 shtpData[4] = 0b100; // tare Z axis
MultipleMonomials 0:f677e13975d0 212 }
MultipleMonomials 0:f677e13975d0 213 else
MultipleMonomials 0:f677e13975d0 214 {
MultipleMonomials 0:f677e13975d0 215 shtpData[4] = 0b111; // tare X, Y, and Z axes
MultipleMonomials 0:f677e13975d0 216 }
MultipleMonomials 0:f677e13975d0 217
MultipleMonomials 0:f677e13975d0 218 shtpData[5] = 0; // reorient all motion outputs
MultipleMonomials 0:f677e13975d0 219
MultipleMonomials 0:f677e13975d0 220 sendCommand(COMMAND_TARE);
MultipleMonomials 0:f677e13975d0 221 }
MultipleMonomials 0:f677e13975d0 222
MultipleMonomials 0:f677e13975d0 223 bool BNO080::updateData()
MultipleMonomials 0:f677e13975d0 224 {
MultipleMonomials 0:f677e13975d0 225 if(_int.read() != 0)
MultipleMonomials 0:f677e13975d0 226 {
MultipleMonomials 0:f677e13975d0 227 // no waiting packets
MultipleMonomials 0:f677e13975d0 228 return false;
MultipleMonomials 0:f677e13975d0 229 }
MultipleMonomials 0:f677e13975d0 230
MultipleMonomials 0:f677e13975d0 231 while(_int.read() == 0)
MultipleMonomials 0:f677e13975d0 232 {
MultipleMonomials 0:f677e13975d0 233 if(!receivePacket())
MultipleMonomials 0:f677e13975d0 234 {
MultipleMonomials 0:f677e13975d0 235 // comms error
MultipleMonomials 0:f677e13975d0 236 return false;
MultipleMonomials 0:f677e13975d0 237 }
MultipleMonomials 0:f677e13975d0 238
MultipleMonomials 0:f677e13975d0 239 processPacket();
MultipleMonomials 0:f677e13975d0 240 }
MultipleMonomials 0:f677e13975d0 241
MultipleMonomials 0:f677e13975d0 242 // packets were received, so data may have changed
MultipleMonomials 0:f677e13975d0 243 return true;
MultipleMonomials 0:f677e13975d0 244 }
MultipleMonomials 0:f677e13975d0 245
MultipleMonomials 0:f677e13975d0 246 uint8_t BNO080::getReportStatus(Report report)
MultipleMonomials 0:f677e13975d0 247 {
MultipleMonomials 0:f677e13975d0 248 uint8_t reportNum = static_cast<uint8_t>(report);
MultipleMonomials 0:f677e13975d0 249 if(reportNum > STATUS_ARRAY_LEN)
MultipleMonomials 0:f677e13975d0 250 {
MultipleMonomials 0:f677e13975d0 251 return 0;
MultipleMonomials 0:f677e13975d0 252 }
MultipleMonomials 0:f677e13975d0 253
MultipleMonomials 0:f677e13975d0 254 return reportStatus[reportNum];
MultipleMonomials 0:f677e13975d0 255 }
MultipleMonomials 0:f677e13975d0 256
MultipleMonomials 0:f677e13975d0 257 //Sends the packet to enable the rotation vector
MultipleMonomials 0:f677e13975d0 258 void BNO080::enableReport(Report report, uint16_t timeBetweenReports)
MultipleMonomials 0:f677e13975d0 259 {
MultipleMonomials 0:f677e13975d0 260 setFeatureCommand(static_cast<uint8_t>(report), timeBetweenReports);
MultipleMonomials 0:f677e13975d0 261
MultipleMonomials 0:f677e13975d0 262 // note: we don't wait for ACKs on these packets because they can take quite a while, like half a second, to come in
MultipleMonomials 0:f677e13975d0 263 }
MultipleMonomials 0:f677e13975d0 264
MultipleMonomials 0:f677e13975d0 265
MultipleMonomials 0:f677e13975d0 266 void BNO080::processPacket()
MultipleMonomials 0:f677e13975d0 267 {
MultipleMonomials 0:f677e13975d0 268 if(shtpHeader[2] == CHANNEL_CONTROL)
MultipleMonomials 0:f677e13975d0 269 {
MultipleMonomials 0:f677e13975d0 270 // currently no command reports are read
MultipleMonomials 0:f677e13975d0 271 }
MultipleMonomials 0:f677e13975d0 272 else if(shtpHeader[2] == CHANNEL_EXECUTABLE)
MultipleMonomials 0:f677e13975d0 273 {
MultipleMonomials 0:f677e13975d0 274 // currently no executable reports are read
MultipleMonomials 0:f677e13975d0 275 }
MultipleMonomials 0:f677e13975d0 276 else if(shtpHeader[2] == CHANNEL_COMMAND)
MultipleMonomials 0:f677e13975d0 277 {
MultipleMonomials 0:f677e13975d0 278
MultipleMonomials 0:f677e13975d0 279 }
MultipleMonomials 0:f677e13975d0 280 else if(shtpHeader[2] == CHANNEL_REPORTS || shtpHeader[2] == CHANNEL_WAKE_REPORTS)
MultipleMonomials 0:f677e13975d0 281 {
MultipleMonomials 0:f677e13975d0 282 if(shtpData[0] == SHTP_REPORT_BASE_TIMESTAMP)
MultipleMonomials 0:f677e13975d0 283 {
MultipleMonomials 0:f677e13975d0 284 // sensor data packet
MultipleMonomials 0:f677e13975d0 285 parseSensorDataPacket();
MultipleMonomials 0:f677e13975d0 286 }
MultipleMonomials 0:f677e13975d0 287 }
MultipleMonomials 0:f677e13975d0 288 }
MultipleMonomials 0:f677e13975d0 289
MultipleMonomials 0:f677e13975d0 290 // sizes of various sensor data packet elements
MultipleMonomials 0:f677e13975d0 291 #define SIZEOF_BASE_TIMESTAMP 5
MultipleMonomials 0:f677e13975d0 292 #define SIZEOF_TIMESTAMP_REBASE 5
MultipleMonomials 0:f677e13975d0 293 #define SIZEOF_ACCELEROMETER 10
MultipleMonomials 0:f677e13975d0 294 #define SIZEOF_LINEAR_ACCELERATION 10
MultipleMonomials 0:f677e13975d0 295 #define SIZEOF_GYROSCOPE_CALIBRATED 10
MultipleMonomials 0:f677e13975d0 296 #define SIZEOF_MAGNETIC_FIELD_CALIBRATED 10
MultipleMonomials 0:f677e13975d0 297 #define SIZEOF_ROTATION_VECTOR 14
MultipleMonomials 0:f677e13975d0 298 #define SIZEOF_GAME_ROTATION_VECTOR 12
MultipleMonomials 0:f677e13975d0 299 #define SIZEOF_GEOMAGNETIC_ROTATION_VECTOR 14
MultipleMonomials 0:f677e13975d0 300 #define SIZEOF_TAP_DETECTOR 5
MultipleMonomials 0:f677e13975d0 301
MultipleMonomials 0:f677e13975d0 302
MultipleMonomials 0:f677e13975d0 303 void BNO080::parseSensorDataPacket()
MultipleMonomials 0:f677e13975d0 304 {
MultipleMonomials 0:f677e13975d0 305 size_t currReportOffset = 0;
MultipleMonomials 0:f677e13975d0 306
MultipleMonomials 0:f677e13975d0 307 // every sensor data report first contains a timestamp offset to show how long it has been between when
MultipleMonomials 0:f677e13975d0 308 // the host interrupt was sent and when the packet was transmitted.
MultipleMonomials 0:f677e13975d0 309 // We don't use interrupts and don't care about times, so we can throw this out.
MultipleMonomials 0:f677e13975d0 310 currReportOffset += SIZEOF_BASE_TIMESTAMP;
MultipleMonomials 0:f677e13975d0 311
MultipleMonomials 0:f677e13975d0 312 while(currReportOffset < packetLength)
MultipleMonomials 0:f677e13975d0 313 {
MultipleMonomials 0:f677e13975d0 314 // lots of sensor reports use 3 16-bit numbers stored in bytes 4 through 9
MultipleMonomials 0:f677e13975d0 315 // we can save some time by parsing those out here.
MultipleMonomials 0:f677e13975d0 316 uint16_t data1 = (uint16_t)shtpData[currReportOffset + 5] << 8 | shtpData[currReportOffset + 4];
MultipleMonomials 0:f677e13975d0 317 uint16_t data2 = (uint16_t)shtpData[currReportOffset + 7] << 8 | shtpData[currReportOffset + 6];
MultipleMonomials 0:f677e13975d0 318 uint16_t data3 = (uint16_t)shtpData[currReportOffset + 9] << 8 | shtpData[currReportOffset + 8];
MultipleMonomials 0:f677e13975d0 319
MultipleMonomials 0:f677e13975d0 320 uint8_t reportNum = shtpData[currReportOffset];
MultipleMonomials 0:f677e13975d0 321
MultipleMonomials 0:f677e13975d0 322 if(reportNum != SENSOR_REPORTID_TIMESTAMP_REBASE)
MultipleMonomials 0:f677e13975d0 323 {
MultipleMonomials 0:f677e13975d0 324 // set status from byte 2
MultipleMonomials 0:f677e13975d0 325 reportStatus[reportNum] = static_cast<uint8_t>(shtpData[currReportOffset + 2] & 0b11);
MultipleMonomials 0:f677e13975d0 326 }
MultipleMonomials 0:f677e13975d0 327
MultipleMonomials 0:f677e13975d0 328 switch(shtpData[currReportOffset])
MultipleMonomials 0:f677e13975d0 329 {
MultipleMonomials 0:f677e13975d0 330 case SENSOR_REPORTID_TIMESTAMP_REBASE:
MultipleMonomials 0:f677e13975d0 331 currReportOffset += SIZEOF_TIMESTAMP_REBASE;
MultipleMonomials 0:f677e13975d0 332 break;
MultipleMonomials 0:f677e13975d0 333
MultipleMonomials 0:f677e13975d0 334 case SENSOR_REPORTID_ACCELEROMETER:
MultipleMonomials 0:f677e13975d0 335
MultipleMonomials 0:f677e13975d0 336 totalAcceleration = TVector3(
MultipleMonomials 0:f677e13975d0 337 qToFloat(data1, ACCELEROMETER_Q_POINT),
MultipleMonomials 0:f677e13975d0 338 qToFloat(data2, ACCELEROMETER_Q_POINT),
MultipleMonomials 0:f677e13975d0 339 qToFloat(data3, ACCELEROMETER_Q_POINT));
MultipleMonomials 0:f677e13975d0 340
MultipleMonomials 0:f677e13975d0 341 currReportOffset += SIZEOF_ACCELEROMETER;
MultipleMonomials 0:f677e13975d0 342 break;
MultipleMonomials 0:f677e13975d0 343
MultipleMonomials 0:f677e13975d0 344 case SENSOR_REPORTID_LINEAR_ACCELERATION:
MultipleMonomials 0:f677e13975d0 345
MultipleMonomials 0:f677e13975d0 346 linearAcceleration = TVector3(
MultipleMonomials 0:f677e13975d0 347 qToFloat(data1, ACCELEROMETER_Q_POINT),
MultipleMonomials 0:f677e13975d0 348 qToFloat(data2, ACCELEROMETER_Q_POINT),
MultipleMonomials 0:f677e13975d0 349 qToFloat(data3, ACCELEROMETER_Q_POINT));
MultipleMonomials 0:f677e13975d0 350
MultipleMonomials 0:f677e13975d0 351 currReportOffset += SIZEOF_LINEAR_ACCELERATION;
MultipleMonomials 0:f677e13975d0 352 break;
MultipleMonomials 0:f677e13975d0 353
MultipleMonomials 0:f677e13975d0 354 case SENSOR_REPORTID_GRAVITY:
MultipleMonomials 0:f677e13975d0 355
MultipleMonomials 0:f677e13975d0 356 gravityAcceleration = TVector3(
MultipleMonomials 0:f677e13975d0 357 qToFloat(data1, ACCELEROMETER_Q_POINT),
MultipleMonomials 0:f677e13975d0 358 qToFloat(data2, ACCELEROMETER_Q_POINT),
MultipleMonomials 0:f677e13975d0 359 qToFloat(data3, ACCELEROMETER_Q_POINT));
MultipleMonomials 0:f677e13975d0 360
MultipleMonomials 0:f677e13975d0 361 currReportOffset += SIZEOF_LINEAR_ACCELERATION;
MultipleMonomials 0:f677e13975d0 362 break;
MultipleMonomials 0:f677e13975d0 363
MultipleMonomials 0:f677e13975d0 364 case SENSOR_REPORTID_GYROSCOPE_CALIBRATED:
MultipleMonomials 0:f677e13975d0 365
MultipleMonomials 0:f677e13975d0 366 gyroRotation = TVector3(
MultipleMonomials 0:f677e13975d0 367 qToFloat(data1, GYRO_Q_POINT),
MultipleMonomials 0:f677e13975d0 368 qToFloat(data2, GYRO_Q_POINT),
MultipleMonomials 0:f677e13975d0 369 qToFloat(data3, GYRO_Q_POINT));
MultipleMonomials 0:f677e13975d0 370
MultipleMonomials 0:f677e13975d0 371 currReportOffset += SIZEOF_GYROSCOPE_CALIBRATED;
MultipleMonomials 0:f677e13975d0 372 break;
MultipleMonomials 0:f677e13975d0 373
MultipleMonomials 0:f677e13975d0 374 case SENSOR_REPORTID_MAGNETIC_FIELD_CALIBRATED:
MultipleMonomials 0:f677e13975d0 375
MultipleMonomials 0:f677e13975d0 376 magField = TVector3(
MultipleMonomials 0:f677e13975d0 377 qToFloat(data1, MAGNETOMETER_Q_POINT),
MultipleMonomials 0:f677e13975d0 378 qToFloat(data2, MAGNETOMETER_Q_POINT),
MultipleMonomials 0:f677e13975d0 379 qToFloat(data3, MAGNETOMETER_Q_POINT));
MultipleMonomials 0:f677e13975d0 380
MultipleMonomials 0:f677e13975d0 381 currReportOffset += SIZEOF_MAGNETIC_FIELD_CALIBRATED;
MultipleMonomials 0:f677e13975d0 382 break;
MultipleMonomials 0:f677e13975d0 383
MultipleMonomials 0:f677e13975d0 384 case SENSOR_REPORTID_ROTATION_VECTOR:
MultipleMonomials 0:f677e13975d0 385 {
MultipleMonomials 0:f677e13975d0 386 uint16_t realPartQ = (uint16_t) shtpData[currReportOffset + 11] << 8 | shtpData[currReportOffset + 10];
MultipleMonomials 0:f677e13975d0 387 uint16_t accuracyQ = (uint16_t) shtpData[currReportOffset + 13] << 8 | shtpData[currReportOffset + 12];
MultipleMonomials 0:f677e13975d0 388
MultipleMonomials 0:f677e13975d0 389 rotationVector = TVector4(
MultipleMonomials 0:f677e13975d0 390 qToFloat(data1, ROTATION_Q_POINT),
MultipleMonomials 0:f677e13975d0 391 qToFloat(data2, ROTATION_Q_POINT),
MultipleMonomials 0:f677e13975d0 392 qToFloat(data3, ROTATION_Q_POINT),
MultipleMonomials 0:f677e13975d0 393 qToFloat(realPartQ, ROTATION_Q_POINT));
MultipleMonomials 0:f677e13975d0 394
MultipleMonomials 0:f677e13975d0 395 rotationAccuracy = qToFloat(accuracyQ, ROTATION_ACCURACY_Q_POINT);
MultipleMonomials 0:f677e13975d0 396
MultipleMonomials 0:f677e13975d0 397 currReportOffset += SIZEOF_ROTATION_VECTOR;
MultipleMonomials 0:f677e13975d0 398 }
MultipleMonomials 0:f677e13975d0 399 break;
MultipleMonomials 0:f677e13975d0 400
MultipleMonomials 0:f677e13975d0 401 case SENSOR_REPORTID_GAME_ROTATION_VECTOR:
MultipleMonomials 0:f677e13975d0 402 {
MultipleMonomials 0:f677e13975d0 403 uint16_t realPartQ = (uint16_t) shtpData[currReportOffset + 11] << 8 | shtpData[currReportOffset + 10];
MultipleMonomials 0:f677e13975d0 404
MultipleMonomials 0:f677e13975d0 405 gameRotationVector = TVector4(
MultipleMonomials 0:f677e13975d0 406 qToFloat(data1, ROTATION_Q_POINT),
MultipleMonomials 0:f677e13975d0 407 qToFloat(data2, ROTATION_Q_POINT),
MultipleMonomials 0:f677e13975d0 408 qToFloat(data3, ROTATION_Q_POINT),
MultipleMonomials 0:f677e13975d0 409 qToFloat(realPartQ, ROTATION_Q_POINT));
MultipleMonomials 0:f677e13975d0 410
MultipleMonomials 0:f677e13975d0 411 currReportOffset += SIZEOF_GAME_ROTATION_VECTOR;
MultipleMonomials 0:f677e13975d0 412 }
MultipleMonomials 0:f677e13975d0 413 break;
MultipleMonomials 0:f677e13975d0 414
MultipleMonomials 0:f677e13975d0 415 case SENSOR_REPORTID_GEOMAGNETIC_ROTATION_VECTOR:
MultipleMonomials 0:f677e13975d0 416 {
MultipleMonomials 0:f677e13975d0 417 uint16_t realPartQ = (uint16_t) shtpData[currReportOffset + 11] << 8 | shtpData[currReportOffset + 10];
MultipleMonomials 0:f677e13975d0 418 uint16_t accuracyQ = (uint16_t) shtpData[currReportOffset + 13] << 8 | shtpData[currReportOffset + 12];
MultipleMonomials 0:f677e13975d0 419
MultipleMonomials 0:f677e13975d0 420 geomagneticRotationVector = TVector4(
MultipleMonomials 0:f677e13975d0 421 qToFloat(data1, ROTATION_Q_POINT),
MultipleMonomials 0:f677e13975d0 422 qToFloat(data2, ROTATION_Q_POINT),
MultipleMonomials 0:f677e13975d0 423 qToFloat(data3, ROTATION_Q_POINT),
MultipleMonomials 0:f677e13975d0 424 qToFloat(realPartQ, ROTATION_Q_POINT));
MultipleMonomials 0:f677e13975d0 425
MultipleMonomials 0:f677e13975d0 426 geomagneticRotationAccuracy = qToFloat(accuracyQ, ROTATION_ACCURACY_Q_POINT);
MultipleMonomials 0:f677e13975d0 427
MultipleMonomials 0:f677e13975d0 428 currReportOffset += SIZEOF_GEOMAGNETIC_ROTATION_VECTOR;
MultipleMonomials 0:f677e13975d0 429 }
MultipleMonomials 0:f677e13975d0 430 break;
MultipleMonomials 0:f677e13975d0 431
MultipleMonomials 0:f677e13975d0 432 case SENSOR_REPORTID_TAP_DETECTOR:
MultipleMonomials 0:f677e13975d0 433
MultipleMonomials 0:f677e13975d0 434 // since we got the report, a tap was detected
MultipleMonomials 0:f677e13975d0 435 tapDetected = true;
MultipleMonomials 0:f677e13975d0 436
MultipleMonomials 0:f677e13975d0 437 doubleTap = (shtpData[currReportOffset + 4] & (1 << 6)) != 0;
MultipleMonomials 0:f677e13975d0 438
MultipleMonomials 0:f677e13975d0 439 currReportOffset += SIZEOF_TAP_DETECTOR;
MultipleMonomials 0:f677e13975d0 440 break;
MultipleMonomials 0:f677e13975d0 441
MultipleMonomials 0:f677e13975d0 442 default:
MultipleMonomials 0:f677e13975d0 443 _debugPort->printf("Error: unrecognized report ID in sensor report: %hhx. Byte %u, length %hu\n", shtpData[currReportOffset], currReportOffset, packetLength);
MultipleMonomials 0:f677e13975d0 444 return;
MultipleMonomials 0:f677e13975d0 445 }
MultipleMonomials 0:f677e13975d0 446 }
MultipleMonomials 0:f677e13975d0 447
MultipleMonomials 0:f677e13975d0 448 }
MultipleMonomials 0:f677e13975d0 449
MultipleMonomials 0:f677e13975d0 450 bool BNO080::waitForPacket(int channel, uint8_t reportID, float timeout)
MultipleMonomials 0:f677e13975d0 451 {
MultipleMonomials 0:f677e13975d0 452 Timer timeoutTimer;
MultipleMonomials 0:f677e13975d0 453 timeoutTimer.start();
MultipleMonomials 0:f677e13975d0 454
MultipleMonomials 0:f677e13975d0 455 while(timeoutTimer.read() <= timeout)
MultipleMonomials 0:f677e13975d0 456 {
MultipleMonomials 0:f677e13975d0 457 if(_int.read() == 0)
MultipleMonomials 0:f677e13975d0 458 {
MultipleMonomials 0:f677e13975d0 459 if(!receivePacket(timeout))
MultipleMonomials 0:f677e13975d0 460 {
MultipleMonomials 0:f677e13975d0 461 return false;
MultipleMonomials 0:f677e13975d0 462 }
MultipleMonomials 0:f677e13975d0 463
MultipleMonomials 0:f677e13975d0 464 if(channel == shtpHeader[2] && reportID == shtpData[0])
MultipleMonomials 0:f677e13975d0 465 {
MultipleMonomials 0:f677e13975d0 466 // found correct packet!
MultipleMonomials 0:f677e13975d0 467 return true;
MultipleMonomials 0:f677e13975d0 468 }
MultipleMonomials 0:f677e13975d0 469 else
MultipleMonomials 0:f677e13975d0 470 {
MultipleMonomials 0:f677e13975d0 471 // other data packet, send to proper channels
MultipleMonomials 0:f677e13975d0 472 processPacket();
MultipleMonomials 0:f677e13975d0 473 }
MultipleMonomials 0:f677e13975d0 474 }
MultipleMonomials 0:f677e13975d0 475 }
MultipleMonomials 0:f677e13975d0 476
MultipleMonomials 0:f677e13975d0 477 _debugPort->printf("Packet wait timeout.\n");
MultipleMonomials 0:f677e13975d0 478 return false;
MultipleMonomials 0:f677e13975d0 479 }
MultipleMonomials 0:f677e13975d0 480
MultipleMonomials 0:f677e13975d0 481 //Given a register value and a Q point, convert to float
MultipleMonomials 0:f677e13975d0 482 //See https://en.wikipedia.org/wiki/Q_(number_format)
MultipleMonomials 0:f677e13975d0 483 float BNO080::qToFloat(int16_t fixedPointValue, uint8_t qPoint)
MultipleMonomials 0:f677e13975d0 484 {
MultipleMonomials 0:f677e13975d0 485 float qFloat = fixedPointValue;
MultipleMonomials 0:f677e13975d0 486 qFloat *= pow(2, qPoint * -1);
MultipleMonomials 0:f677e13975d0 487 return (qFloat);
MultipleMonomials 0:f677e13975d0 488 }
MultipleMonomials 0:f677e13975d0 489
MultipleMonomials 0:f677e13975d0 490 //Given a floating point value and a Q point, convert to Q
MultipleMonomials 0:f677e13975d0 491 //See https://en.wikipedia.org/wiki/Q_(number_format)
MultipleMonomials 0:f677e13975d0 492 int16_t BNO080::floatToQ(float qFloat, uint8_t qPoint)
MultipleMonomials 0:f677e13975d0 493 {
MultipleMonomials 0:f677e13975d0 494 int16_t qVal = static_cast<int16_t>(qFloat * pow(2, qPoint));
MultipleMonomials 0:f677e13975d0 495 return qVal;
MultipleMonomials 0:f677e13975d0 496 }
MultipleMonomials 0:f677e13975d0 497
MultipleMonomials 0:f677e13975d0 498 //Tell the sensor to do a command
MultipleMonomials 0:f677e13975d0 499 //See 6.3.8 page 41, Command request
MultipleMonomials 0:f677e13975d0 500 //The caller is expected to set P0 through P8 prior to calling
MultipleMonomials 0:f677e13975d0 501 void BNO080::sendCommand(uint8_t command)
MultipleMonomials 0:f677e13975d0 502 {
MultipleMonomials 0:f677e13975d0 503 shtpData[0] = SHTP_REPORT_COMMAND_REQUEST; //Command Request
MultipleMonomials 0:f677e13975d0 504 shtpData[1] = commandSequenceNumber++; //Increments automatically each function call
MultipleMonomials 0:f677e13975d0 505 shtpData[2] = command; //Command
MultipleMonomials 0:f677e13975d0 506
MultipleMonomials 0:f677e13975d0 507 //Caller must set these
MultipleMonomials 0:f677e13975d0 508 /*shtpData[3] = 0; //P0
MultipleMonomials 0:f677e13975d0 509 shtpData[4] = 0; //P1
MultipleMonomials 0:f677e13975d0 510 shtpData[5] = 0; //P2
MultipleMonomials 0:f677e13975d0 511 shtpData[6] = 0;
MultipleMonomials 0:f677e13975d0 512 shtpData[7] = 0;
MultipleMonomials 0:f677e13975d0 513 shtpData[8] = 0;
MultipleMonomials 0:f677e13975d0 514 shtpData[9] = 0;
MultipleMonomials 0:f677e13975d0 515 shtpData[10] = 0;
MultipleMonomials 0:f677e13975d0 516 shtpData[11] = 0;*/
MultipleMonomials 0:f677e13975d0 517
MultipleMonomials 0:f677e13975d0 518 //Transmit packet on channel 2, 12 bytes
MultipleMonomials 0:f677e13975d0 519 sendPacket(CHANNEL_CONTROL, 12);
MultipleMonomials 0:f677e13975d0 520 }
MultipleMonomials 0:f677e13975d0 521
MultipleMonomials 0:f677e13975d0 522 //Given a sensor's report ID, this tells the BNO080 to begin reporting the values
MultipleMonomials 0:f677e13975d0 523 //Also sets the specific config word. Useful for personal activity classifier
MultipleMonomials 0:f677e13975d0 524 void BNO080::setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports, uint32_t specificConfig)
MultipleMonomials 0:f677e13975d0 525 {
MultipleMonomials 0:f677e13975d0 526 uint32_t microsBetweenReports = static_cast<uint32_t>(timeBetweenReports * 1000);
MultipleMonomials 0:f677e13975d0 527
MultipleMonomials 0:f677e13975d0 528 const uint32_t batchMicros = 0;
MultipleMonomials 0:f677e13975d0 529
MultipleMonomials 0:f677e13975d0 530 shtpData[0] = SHTP_REPORT_SET_FEATURE_COMMAND; //Set feature command. Reference page 55
MultipleMonomials 0:f677e13975d0 531 shtpData[1] = reportID; //Feature Report ID. 0x01 = Accelerometer, 0x05 = Rotation vector
MultipleMonomials 0:f677e13975d0 532 shtpData[2] = 0; //Feature flags
MultipleMonomials 0:f677e13975d0 533 shtpData[3] = 0; //Change sensitivity (LSB)
MultipleMonomials 0:f677e13975d0 534 shtpData[4] = 0; //Change sensitivity (MSB)
MultipleMonomials 0:f677e13975d0 535 shtpData[5] = (microsBetweenReports >> 0) & 0xFF; //Report interval (LSB) in microseconds. 0x7A120 = 500ms
MultipleMonomials 0:f677e13975d0 536 shtpData[6] = (microsBetweenReports >> 8) & 0xFF; //Report interval
MultipleMonomials 0:f677e13975d0 537 shtpData[7] = (microsBetweenReports >> 16) & 0xFF; //Report interval
MultipleMonomials 0:f677e13975d0 538 shtpData[8] = (microsBetweenReports >> 24) & 0xFF; //Report interval (MSB)
MultipleMonomials 0:f677e13975d0 539 shtpData[9] = (batchMicros >> 0) & 0xFF; //Batch Interval (LSB)
MultipleMonomials 0:f677e13975d0 540 shtpData[10] = (batchMicros >> 8) & 0xFF; //Batch Interval
MultipleMonomials 0:f677e13975d0 541 shtpData[11] = (batchMicros >> 16) & 0xFF;//Batch Interval
MultipleMonomials 0:f677e13975d0 542 shtpData[12] = (batchMicros >> 24) & 0xFF;//Batch Interval (MSB)
MultipleMonomials 0:f677e13975d0 543 shtpData[13] = (specificConfig >> 0) & 0xFF; //Sensor-specific config (LSB)
MultipleMonomials 0:f677e13975d0 544 shtpData[14] = (specificConfig >> 8) & 0xFF; //Sensor-specific config
MultipleMonomials 0:f677e13975d0 545 shtpData[15] = (specificConfig >> 16) & 0xFF; //Sensor-specific config
MultipleMonomials 0:f677e13975d0 546 shtpData[16] = (specificConfig >> 24) & 0xFF; //Sensor-specific config (MSB)
MultipleMonomials 0:f677e13975d0 547
MultipleMonomials 0:f677e13975d0 548 //Transmit packet on channel 2, 17 bytes
MultipleMonomials 0:f677e13975d0 549 sendPacket(CHANNEL_CONTROL, 17);
MultipleMonomials 0:f677e13975d0 550 }
MultipleMonomials 0:f677e13975d0 551
MultipleMonomials 0:f677e13975d0 552
MultipleMonomials 0:f677e13975d0 553 //Given the data packet, send the header then the data
MultipleMonomials 0:f677e13975d0 554 //Returns false if sensor does not ACK
MultipleMonomials 0:f677e13975d0 555 bool BNO080::sendPacket(uint8_t channelNumber, uint8_t dataLength)
MultipleMonomials 0:f677e13975d0 556 {
MultipleMonomials 0:f677e13975d0 557 // start the transaction and contact the IMU
MultipleMonomials 0:f677e13975d0 558 _i2cPort.start();
MultipleMonomials 0:f677e13975d0 559
MultipleMonomials 0:f677e13975d0 560 // to indicate an i2c read, shift the 7 bit address up 1 bit and keep bit 0 as a 0
MultipleMonomials 0:f677e13975d0 561 int writeResult = _i2cPort.write(_i2cAddress << 1);
MultipleMonomials 0:f677e13975d0 562
MultipleMonomials 0:f677e13975d0 563 if(writeResult != 1)
MultipleMonomials 0:f677e13975d0 564 {
MultipleMonomials 0:f677e13975d0 565 _debugPort->printf("BNO I2C write failed!\n");
MultipleMonomials 0:f677e13975d0 566 _scope = 0;
MultipleMonomials 0:f677e13975d0 567 _i2cPort.stop();
MultipleMonomials 0:f677e13975d0 568 return false;
MultipleMonomials 0:f677e13975d0 569 }
MultipleMonomials 0:f677e13975d0 570
MultipleMonomials 0:f677e13975d0 571
MultipleMonomials 0:f677e13975d0 572 uint16_t totalLength = dataLength + 4; //Add four bytes for the header
MultipleMonomials 0:f677e13975d0 573 packetLength = dataLength;
MultipleMonomials 0:f677e13975d0 574
MultipleMonomials 0:f677e13975d0 575 #if BNO_DEBUG
MultipleMonomials 0:f677e13975d0 576 shtpHeader[0] = totalLength & 0xFF;
MultipleMonomials 0:f677e13975d0 577 shtpHeader[1] = totalLength >> 8;
MultipleMonomials 0:f677e13975d0 578 shtpHeader[2] = channelNumber;
MultipleMonomials 0:f677e13975d0 579 shtpHeader[3] = sequenceNumber[channelNumber];
MultipleMonomials 0:f677e13975d0 580
MultipleMonomials 0:f677e13975d0 581 _debugPort->printf("Transmitting packet: ----------------\n");
MultipleMonomials 0:f677e13975d0 582 printPacket();
MultipleMonomials 0:f677e13975d0 583 #endif
MultipleMonomials 0:f677e13975d0 584
MultipleMonomials 0:f677e13975d0 585 //Send the 4 byte packet header
MultipleMonomials 0:f677e13975d0 586 _i2cPort.write(totalLength & 0xFF); //Packet length LSB
MultipleMonomials 0:f677e13975d0 587 _i2cPort.write(totalLength >> 8); //Packet length MSB
MultipleMonomials 0:f677e13975d0 588 _i2cPort.write(channelNumber); //Channel number
MultipleMonomials 0:f677e13975d0 589 _i2cPort.write(sequenceNumber[channelNumber]++); //Send the sequence number, increments with each packet sent, different counter for each channel
MultipleMonomials 0:f677e13975d0 590
MultipleMonomials 0:f677e13975d0 591 //Send the user's data packet
MultipleMonomials 0:f677e13975d0 592 for (uint8_t i = 0 ; i < dataLength ; i++)
MultipleMonomials 0:f677e13975d0 593 {
MultipleMonomials 0:f677e13975d0 594 _i2cPort.write(shtpData[i]);
MultipleMonomials 0:f677e13975d0 595 }
MultipleMonomials 0:f677e13975d0 596 _i2cPort.stop();
MultipleMonomials 0:f677e13975d0 597
MultipleMonomials 0:f677e13975d0 598 return (true);
MultipleMonomials 0:f677e13975d0 599 }
MultipleMonomials 0:f677e13975d0 600
MultipleMonomials 0:f677e13975d0 601 //Check to see if there is any new data available
MultipleMonomials 0:f677e13975d0 602 //Read the contents of the incoming packet into the shtpData array
MultipleMonomials 0:f677e13975d0 603 bool BNO080::receivePacket(float timeout)
MultipleMonomials 0:f677e13975d0 604 {
MultipleMonomials 0:f677e13975d0 605 Timer waitStartTime;
MultipleMonomials 0:f677e13975d0 606 waitStartTime.start();
MultipleMonomials 0:f677e13975d0 607
MultipleMonomials 0:f677e13975d0 608 while(_int.read() != 0)
MultipleMonomials 0:f677e13975d0 609 {
MultipleMonomials 0:f677e13975d0 610 if(waitStartTime.read() > timeout)
MultipleMonomials 0:f677e13975d0 611 {
MultipleMonomials 0:f677e13975d0 612 _debugPort->printf("BNO I2C wait timeout\n");
MultipleMonomials 0:f677e13975d0 613 return false;
MultipleMonomials 0:f677e13975d0 614 }
MultipleMonomials 0:f677e13975d0 615
MultipleMonomials 0:f677e13975d0 616 }
MultipleMonomials 0:f677e13975d0 617
MultipleMonomials 0:f677e13975d0 618 // start the transaction and contact the IMU
MultipleMonomials 0:f677e13975d0 619 _i2cPort.start();
MultipleMonomials 0:f677e13975d0 620
MultipleMonomials 0:f677e13975d0 621 // to indicate an i2c read, shift the 7 bit address up 1 bit and set bit 0 to a 1
MultipleMonomials 0:f677e13975d0 622 int writeResult = _i2cPort.write((_i2cAddress << 1) | 0x1);
MultipleMonomials 0:f677e13975d0 623
MultipleMonomials 0:f677e13975d0 624 if(writeResult != 1)
MultipleMonomials 0:f677e13975d0 625 {
MultipleMonomials 0:f677e13975d0 626 _debugPort->printf("BNO I2C read failed!\n");
MultipleMonomials 0:f677e13975d0 627 return false;
MultipleMonomials 0:f677e13975d0 628 }
MultipleMonomials 0:f677e13975d0 629
MultipleMonomials 0:f677e13975d0 630 //Get the first four bytes, aka the packet header
MultipleMonomials 0:f677e13975d0 631 uint8_t packetLSB = static_cast<uint8_t>(_i2cPort.read(true));
MultipleMonomials 0:f677e13975d0 632 uint8_t packetMSB = static_cast<uint8_t>(_i2cPort.read(true));
MultipleMonomials 0:f677e13975d0 633 uint8_t channelNumber = static_cast<uint8_t>(_i2cPort.read(true));
MultipleMonomials 0:f677e13975d0 634 uint8_t sequenceNum = static_cast<uint8_t>(_i2cPort.read(true)); //Not sure if we need to store this or not
MultipleMonomials 0:f677e13975d0 635
MultipleMonomials 0:f677e13975d0 636 //Store the header info
MultipleMonomials 0:f677e13975d0 637 shtpHeader[0] = packetLSB;
MultipleMonomials 0:f677e13975d0 638 shtpHeader[1] = packetMSB;
MultipleMonomials 0:f677e13975d0 639 shtpHeader[2] = channelNumber;
MultipleMonomials 0:f677e13975d0 640 shtpHeader[3] = sequenceNum;
MultipleMonomials 0:f677e13975d0 641
MultipleMonomials 0:f677e13975d0 642 if(shtpHeader[0] == 0xFF && shtpHeader[1] == 0xFF)
MultipleMonomials 0:f677e13975d0 643 {
MultipleMonomials 0:f677e13975d0 644 // invalid according to BNO080 datasheet section 1.4.1
MultipleMonomials 0:f677e13975d0 645
MultipleMonomials 0:f677e13975d0 646 #if BNO_DEBUG
MultipleMonomials 0:f677e13975d0 647 _debugPort->printf("Recieved 0xFFFF packet length, protocol error!\n");
MultipleMonomials 0:f677e13975d0 648 #endif
MultipleMonomials 0:f677e13975d0 649 return false;
MultipleMonomials 0:f677e13975d0 650 }
MultipleMonomials 0:f677e13975d0 651
MultipleMonomials 0:f677e13975d0 652 //Calculate the number of data bytes in this packet
MultipleMonomials 0:f677e13975d0 653 packetLength = (static_cast<uint16_t>(packetMSB) << 8 | packetLSB);
MultipleMonomials 0:f677e13975d0 654
MultipleMonomials 0:f677e13975d0 655 // Clear the MSbit.
MultipleMonomials 0:f677e13975d0 656 // This bit indicates if this package is a continuation of the last. TBH, I don't really know what this means (it's not really explained in the datasheet)
MultipleMonomials 0:f677e13975d0 657 // but we don't actually care about any of the advertisement packets
MultipleMonomials 0:f677e13975d0 658 // that use this, so we can just cut off the rest of the packet by releasing chip select.
MultipleMonomials 0:f677e13975d0 659 packetLength &= ~(1 << 15);
MultipleMonomials 0:f677e13975d0 660
MultipleMonomials 0:f677e13975d0 661 if (packetLength == 0)
MultipleMonomials 0:f677e13975d0 662 {
MultipleMonomials 0:f677e13975d0 663 // Packet is empty
MultipleMonomials 0:f677e13975d0 664 return (false); //All done
MultipleMonomials 0:f677e13975d0 665 }
MultipleMonomials 0:f677e13975d0 666
MultipleMonomials 0:f677e13975d0 667 packetLength -= 4; //Remove the header bytes from the data count
MultipleMonomials 0:f677e13975d0 668
MultipleMonomials 0:f677e13975d0 669 //Read incoming data into the shtpData array
MultipleMonomials 0:f677e13975d0 670 for (uint16_t dataSpot = 0 ; dataSpot < packetLength ; dataSpot++)
MultipleMonomials 0:f677e13975d0 671 {
MultipleMonomials 0:f677e13975d0 672 bool sendACK = dataSpot < packetLength - 1;
MultipleMonomials 0:f677e13975d0 673
MultipleMonomials 0:f677e13975d0 674 // per the datasheet, 0xFF is used as filler for the receiver to transmit back
MultipleMonomials 0:f677e13975d0 675 uint8_t incoming = static_cast<uint8_t>(_i2cPort.read(sendACK));
MultipleMonomials 0:f677e13975d0 676 if (dataSpot < STORED_PACKET_SIZE) //BNO080 can respond with upto 270 bytes, avoid overflow
MultipleMonomials 0:f677e13975d0 677 shtpData[dataSpot] = incoming; //Store data into the shtpData array
MultipleMonomials 0:f677e13975d0 678 }
MultipleMonomials 0:f677e13975d0 679
MultipleMonomials 0:f677e13975d0 680 _i2cPort.stop();
MultipleMonomials 0:f677e13975d0 681
MultipleMonomials 0:f677e13975d0 682 #if BNO_DEBUG
MultipleMonomials 0:f677e13975d0 683 _debugPort->printf("Recieved packet: ----------------\n");
MultipleMonomials 0:f677e13975d0 684 printPacket(); // note: add 4 for the header length
MultipleMonomials 0:f677e13975d0 685 #endif
MultipleMonomials 0:f677e13975d0 686
MultipleMonomials 0:f677e13975d0 687 return (true); //We're done!
MultipleMonomials 0:f677e13975d0 688 }
MultipleMonomials 0:f677e13975d0 689
MultipleMonomials 0:f677e13975d0 690 //Pretty prints the contents of the current shtp header and data packets
MultipleMonomials 0:f677e13975d0 691 void BNO080::printPacket()
MultipleMonomials 0:f677e13975d0 692 {
MultipleMonomials 0:f677e13975d0 693 #if BNO_DEBUG
MultipleMonomials 0:f677e13975d0 694 //Print the four byte header
MultipleMonomials 0:f677e13975d0 695 _debugPort->printf("Header:");
MultipleMonomials 0:f677e13975d0 696 for (uint8_t x = 0 ; x < 4 ; x++)
MultipleMonomials 0:f677e13975d0 697 {
MultipleMonomials 0:f677e13975d0 698 _debugPort->printf(" ");
MultipleMonomials 0:f677e13975d0 699 if (shtpHeader[x] < 0x10) _debugPort->printf("0");
MultipleMonomials 0:f677e13975d0 700 _debugPort->printf("%hhx", shtpHeader[x]);
MultipleMonomials 0:f677e13975d0 701 }
MultipleMonomials 0:f677e13975d0 702
MultipleMonomials 0:f677e13975d0 703 uint16_t printLength = packetLength;
MultipleMonomials 0:f677e13975d0 704 if (printLength > 40) printLength = 40; //Artificial limit. We don't want the phone book.
MultipleMonomials 0:f677e13975d0 705
MultipleMonomials 0:f677e13975d0 706 _debugPort->printf(" Body:");
MultipleMonomials 0:f677e13975d0 707 for (uint16_t x = 0 ; x < printLength ; x++)
MultipleMonomials 0:f677e13975d0 708 {
MultipleMonomials 0:f677e13975d0 709 _debugPort->printf(" ");
MultipleMonomials 0:f677e13975d0 710 if (shtpData[x] < 0x10) _debugPort->printf("0");
MultipleMonomials 0:f677e13975d0 711 _debugPort->printf("%hhx", shtpData[x]);
MultipleMonomials 0:f677e13975d0 712 }
MultipleMonomials 0:f677e13975d0 713
MultipleMonomials 0:f677e13975d0 714 _debugPort->printf(", Length:");
MultipleMonomials 0:f677e13975d0 715 _debugPort->printf("%hhu", packetLength + SHTP_HEADER_SIZE);
MultipleMonomials 0:f677e13975d0 716
MultipleMonomials 0:f677e13975d0 717 if(shtpHeader[1] >> 7)
MultipleMonomials 0:f677e13975d0 718 {
MultipleMonomials 0:f677e13975d0 719 _debugPort->printf("[C]");
MultipleMonomials 0:f677e13975d0 720 }
MultipleMonomials 0:f677e13975d0 721
MultipleMonomials 0:f677e13975d0 722 _debugPort->printf(", SeqNum: %hhu", shtpHeader[3]);
MultipleMonomials 0:f677e13975d0 723
MultipleMonomials 0:f677e13975d0 724 _debugPort->printf(", Channel:");
MultipleMonomials 0:f677e13975d0 725 if (shtpHeader[2] == 0) _debugPort->printf("Command");
MultipleMonomials 0:f677e13975d0 726 else if (shtpHeader[2] == 1) _debugPort->printf("Executable");
MultipleMonomials 0:f677e13975d0 727 else if (shtpHeader[2] == 2) _debugPort->printf("Control");
MultipleMonomials 0:f677e13975d0 728 else if (shtpHeader[2] == 3) _debugPort->printf("Sensor-report");
MultipleMonomials 0:f677e13975d0 729 else if (shtpHeader[2] == 4) _debugPort->printf("Wake-report");
MultipleMonomials 0:f677e13975d0 730 else if (shtpHeader[2] == 5) _debugPort->printf("Gyro-vector");
MultipleMonomials 0:f677e13975d0 731 else _debugPort->printf("%hhu", shtpHeader[2]);
MultipleMonomials 0:f677e13975d0 732
MultipleMonomials 0:f677e13975d0 733 _debugPort->printf("\n");
MultipleMonomials 0:f677e13975d0 734 #endif
MultipleMonomials 0:f677e13975d0 735 }
MultipleMonomials 0:f677e13975d0 736
MultipleMonomials 0:f677e13975d0 737
MultipleMonomials 0:f677e13975d0 738 void BNO080::zeroBuffer()
MultipleMonomials 0:f677e13975d0 739 {
MultipleMonomials 0:f677e13975d0 740 memset(shtpHeader, 0, SHTP_HEADER_SIZE);
MultipleMonomials 0:f677e13975d0 741 memset(shtpData, 0, STORED_PACKET_SIZE);
MultipleMonomials 0:f677e13975d0 742 packetLength = 0;
MultipleMonomials 0:f677e13975d0 743 }