6#ifndef BNO085_HEADER_INCLUDED
29template <
typename CommType>
31 halWrapper_.comm = &io_;
32 halWrapper_.hal.open = halOpen;
33 halWrapper_.hal.close = halClose;
34 halWrapper_.hal.read = halRead;
35 halWrapper_.hal.write = halWrite;
36 halWrapper_.hal.getTimeUs = halGetTimeUs;
39template <
typename CommType>
44 last_error_ = SH2_ERR_OP_IN_PROGRESS;
48 last_error_ = SH2_ERR_BAD_PARAM;
55 int status = sh2_open(halWrapper_.asHal(), asyncCallback,
this);
56 if (status != SH2_OK) {
61 status = sh2_reinitialize();
62 if (status != SH2_OK) {
68 status = sh2_setSensorCallback(sensorCallback,
this);
69 if (status != SH2_OK) {
76 new_flag_.fill(
false);
77 last_interval_.fill(0);
78 last_sensitivity_.fill(0);
90template <
typename CommType>
92 float sensitivity)
noexcept {
94 last_error_ = SH2_ERR_OP_IN_PROGRESS;
97 auto id =
static_cast<uint8_t
>(sensor);
98 if (
id >= last_interval_.size())
100 uint32_t interval_us = interval_ms * 1000;
101 if (!configure(sensor, interval_us, sensitivity, 0))
103 last_interval_[id] = interval_us;
104 last_sensitivity_[id] = sensitivity;
109template <
typename CommType>
112 last_error_ = SH2_ERR_OP_IN_PROGRESS;
115 auto id =
static_cast<uint8_t
>(sensor);
116 if (
id >= last_interval_.size())
118 if (!configure(sensor, 0, 0, 0))
120 last_interval_[id] = 0;
121 last_sensitivity_[id] = 0.0f;
122 new_flag_[id] =
false;
127template <
typename CommType>
133template <
typename CommType>
139template <
typename CommType>
143 auto id =
static_cast<uint8_t
>(sensor);
144 if (
id >= new_flag_.size())
146 return new_flag_[id];
152template <
typename CommType>
154 const sh2_SensorValue_t& val)
const noexcept {
157 out.timestamp = val.timestamp;
158 out.detected =
false;
159 const uint8_t accuracy = val.status & 0x03;
163 out.raw.x = val.un.rawAccelerometer.x;
164 out.raw.y = val.un.rawAccelerometer.y;
165 out.raw.z = val.un.rawAccelerometer.z;
166 out.raw.sensorTimeUs = val.un.rawAccelerometer.timestamp;
169 out.vector.x = val.un.accelerometer.x;
170 out.vector.y = val.un.accelerometer.y;
171 out.vector.z = val.un.accelerometer.z;
172 out.vector.accuracy = accuracy;
175 out.vector.x = val.un.linearAcceleration.x;
176 out.vector.y = val.un.linearAcceleration.y;
177 out.vector.z = val.un.linearAcceleration.z;
178 out.vector.accuracy = accuracy;
181 out.vector.x = val.un.gravity.x;
182 out.vector.y = val.un.gravity.y;
183 out.vector.z = val.un.gravity.z;
184 out.vector.accuracy = accuracy;
187 out.raw.x = val.un.rawGyroscope.x;
188 out.raw.y = val.un.rawGyroscope.y;
189 out.raw.z = val.un.rawGyroscope.z;
190 out.raw.temperature = val.un.rawGyroscope.temperature;
191 out.raw.sensorTimeUs = val.un.rawGyroscope.timestamp;
194 out.vector.x = val.un.gyroscope.x;
195 out.vector.y = val.un.gyroscope.y;
196 out.vector.z = val.un.gyroscope.z;
197 out.vector.accuracy = accuracy;
200 out.vector.x = val.un.gyroscopeUncal.x;
201 out.vector.y = val.un.gyroscopeUncal.y;
202 out.vector.z = val.un.gyroscopeUncal.z;
203 out.vector.accuracy = accuracy;
204 out.bias.x = val.un.gyroscopeUncal.biasX;
205 out.bias.y = val.un.gyroscopeUncal.biasY;
206 out.bias.z = val.un.gyroscopeUncal.biasZ;
209 out.raw.x = val.un.rawMagnetometer.x;
210 out.raw.y = val.un.rawMagnetometer.y;
211 out.raw.z = val.un.rawMagnetometer.z;
212 out.raw.sensorTimeUs = val.un.rawMagnetometer.timestamp;
215 out.vector.x = val.un.magneticField.x;
216 out.vector.y = val.un.magneticField.y;
217 out.vector.z = val.un.magneticField.z;
218 out.vector.accuracy = accuracy;
221 out.vector.x = val.un.magneticFieldUncal.x;
222 out.vector.y = val.un.magneticFieldUncal.y;
223 out.vector.z = val.un.magneticFieldUncal.z;
224 out.vector.accuracy = accuracy;
225 out.bias.x = val.un.magneticFieldUncal.biasX;
226 out.bias.y = val.un.magneticFieldUncal.biasY;
227 out.bias.z = val.un.magneticFieldUncal.biasZ;
230 out.rotation.w = val.un.rotationVector.real;
231 out.rotation.x = val.un.rotationVector.i;
232 out.rotation.y = val.un.rotationVector.j;
233 out.rotation.z = val.un.rotationVector.k;
234 out.rotation.accuracy = accuracy;
237 out.rotation.w = val.un.gameRotationVector.real;
238 out.rotation.x = val.un.gameRotationVector.i;
239 out.rotation.y = val.un.gameRotationVector.j;
240 out.rotation.z = val.un.gameRotationVector.k;
241 out.rotation.accuracy = accuracy;
244 out.rotation.w = val.un.geoMagRotationVector.real;
245 out.rotation.x = val.un.geoMagRotationVector.i;
246 out.rotation.y = val.un.geoMagRotationVector.j;
247 out.rotation.z = val.un.geoMagRotationVector.k;
248 out.rotation.accuracy = accuracy;
251 out.rotation.w = val.un.arvrStabilizedRV.real;
252 out.rotation.x = val.un.arvrStabilizedRV.i;
253 out.rotation.y = val.un.arvrStabilizedRV.j;
254 out.rotation.z = val.un.arvrStabilizedRV.k;
255 out.rotation.accuracy = accuracy;
258 out.rotation.w = val.un.arvrStabilizedGRV.real;
259 out.rotation.x = val.un.arvrStabilizedGRV.i;
260 out.rotation.y = val.un.arvrStabilizedGRV.j;
261 out.rotation.z = val.un.arvrStabilizedGRV.k;
262 out.rotation.accuracy = accuracy;
265 out.rotation.w = val.un.gyroIntegratedRV.real;
266 out.rotation.x = val.un.gyroIntegratedRV.i;
267 out.rotation.y = val.un.gyroIntegratedRV.j;
268 out.rotation.z = val.un.gyroIntegratedRV.k;
269 out.rotation.accuracy = accuracy;
270 out.angularVelocity.x = val.un.gyroIntegratedRV.angVelX;
271 out.angularVelocity.y = val.un.gyroIntegratedRV.angVelY;
272 out.angularVelocity.z = val.un.gyroIntegratedRV.angVelZ;
275 out.scalar = val.un.pressure.value;
278 out.scalar = val.un.ambientLight.value;
281 out.scalar = val.un.humidity.value;
284 out.scalar = val.un.proximity.value;
287 out.scalar = val.un.temperature.value;
290 out.latencyUs = val.un.stepDetector.latency;
295 out.latencyUs = val.un.stepCounter.latency;
296 out.stepCount = val.un.stepCounter.steps;
299 out.eventFlags = val.un.sigMotion.motion;
300 out.detected = out.eventFlags != 0;
303 out.classification = val.un.stabilityClassifier.classification;
306 out.eventFlags = val.un.tapDetector.flags;
307 out.tap.doubleTap = (val.un.tapDetector.flags & TAPDET_DOUBLE);
308 if (val.un.tapDetector.flags & TAPDET_X)
309 out.tap.direction = (val.un.tapDetector.flags & TAPDET_X_POS) ? 0 : 1;
310 else if (val.un.tapDetector.flags & TAPDET_Y)
311 out.tap.direction = (val.un.tapDetector.flags & TAPDET_Y_POS) ? 2 : 3;
312 else if (val.un.tapDetector.flags & TAPDET_Z)
313 out.tap.direction = (val.un.tapDetector.flags & TAPDET_Z_POS) ? 4 : 5;
315 out.tap.direction = 0;
316 out.detected = val.un.tapDetector.flags & (TAPDET_X | TAPDET_Y | TAPDET_Z);
319 out.eventFlags = val.un.shakeDetector.shake;
320 out.detected = out.eventFlags != 0;
323 out.eventFlags = val.un.flipDetector.flip;
324 out.detected = out.eventFlags != 0;
327 out.eventFlags = val.un.pickupDetector.pickup;
328 out.detected = out.eventFlags != 0;
331 out.eventFlags = val.un.stabilityDetector.stability;
332 out.detected = out.eventFlags != 0;
335 out.activity.page = val.un.personalActivityClassifier.page;
336 out.activity.lastPage = val.un.personalActivityClassifier.lastPage;
337 out.activity.mostLikelyState = val.un.personalActivityClassifier.mostLikelyState;
338 for (std::size_t i = 0; i < out.activity.confidence.size(); ++i) {
339 out.activity.confidence[i] = val.un.personalActivityClassifier.confidence[i];
341 out.classification = out.activity.mostLikelyState;
344 out.sleepState = val.un.sleepDetector.sleepState;
345 out.detected = out.sleepState != 0;
348 out.eventFlags = val.un.tiltDetector.tilt;
349 out.detected = out.eventFlags != 0;
352 out.eventFlags = val.un.pocketDetector.pocket;
353 out.detected = out.eventFlags != 0;
356 out.eventFlags = val.un.circleDetector.circle;
357 out.detected = out.eventFlags != 0;
360 out.scalar =
static_cast<float>(val.un.heartRateMonitor.heartRate);
363 out.motionIntent =
static_cast<uint8_t
>(val.un.izroRequest.intent);
364 out.motionRequest =
static_cast<uint8_t
>(val.un.izroRequest.request);
367 out.rawOpticalFlow.timestamp = val.un.rawOptFlow.timestamp;
368 out.rawOpticalFlow.dt = val.un.rawOptFlow.dt;
369 out.rawOpticalFlow.dx = val.un.rawOptFlow.dx;
370 out.rawOpticalFlow.dy = val.un.rawOptFlow.dy;
371 out.rawOpticalFlow.iq = val.un.rawOptFlow.iq;
372 out.rawOpticalFlow.resX = val.un.rawOptFlow.resX;
373 out.rawOpticalFlow.resY = val.un.rawOptFlow.resY;
374 out.rawOpticalFlow.shutter = val.un.rawOptFlow.shutter;
375 out.rawOpticalFlow.frameMax = val.un.rawOptFlow.frameMax;
376 out.rawOpticalFlow.frameAvg = val.un.rawOptFlow.frameAvg;
377 out.rawOpticalFlow.frameMin = val.un.rawOptFlow.frameMin;
378 out.rawOpticalFlow.laserOn = val.un.rawOptFlow.laserOn;
381 out.deadReckoningPose.timestamp = val.un.deadReckoningPose.timestamp;
382 out.deadReckoningPose.linearPosition.x = val.un.deadReckoningPose.linPosX;
383 out.deadReckoningPose.linearPosition.y = val.un.deadReckoningPose.linPosY;
384 out.deadReckoningPose.linearPosition.z = val.un.deadReckoningPose.linPosZ;
385 out.deadReckoningPose.rotation.w = val.un.deadReckoningPose.real;
386 out.deadReckoningPose.rotation.x = val.un.deadReckoningPose.i;
387 out.deadReckoningPose.rotation.y = val.un.deadReckoningPose.j;
388 out.deadReckoningPose.rotation.z = val.un.deadReckoningPose.k;
389 out.deadReckoningPose.linearVelocity.x = val.un.deadReckoningPose.linVelX;
390 out.deadReckoningPose.linearVelocity.y = val.un.deadReckoningPose.linVelY;
391 out.deadReckoningPose.linearVelocity.z = val.un.deadReckoningPose.linVelZ;
392 out.deadReckoningPose.angularVelocity.x = val.un.deadReckoningPose.angVelX;
393 out.deadReckoningPose.angularVelocity.y = val.un.deadReckoningPose.angVelY;
394 out.deadReckoningPose.angularVelocity.z = val.un.deadReckoningPose.angVelZ;
397 out.wheelEncoder.timestamp = val.un.wheelEncoder.timestamp;
398 out.wheelEncoder.wheelIndex = val.un.wheelEncoder.wheelIndex;
399 out.wheelEncoder.dataType = val.un.wheelEncoder.dataType;
400 out.wheelEncoder.data = val.un.wheelEncoder.data;
411template <
typename CommType>
417 const auto id =
static_cast<uint8_t
>(sensor);
418 if (
id >= latest_.size())
420 out = toSensorEvent(sensor, latest_[
id]);
421 new_flag_[id] =
false;
426template <
typename CommType>
434template <
typename CommType>
437 last_error_ = SH2_ERR_OP_IN_PROGRESS;
451 new_flag_.fill(
false);
452 last_interval_.fill(0);
453 last_sensitivity_.fill(0.0f);
459template <
typename CommType>
461 auto* t =
reinterpret_cast<CommHal*
>(self);
462 return t->comm->Open() ? SH2_OK : SH2_ERR;
466template <
typename CommType>
468 reinterpret_cast<CommHal*
>(self)->comm->
Close();
472template <
typename CommType>
474 auto* th =
reinterpret_cast<CommHal*
>(self);
475 int ret = th->comm->Read(buf, len);
476 *t = th->comm->GetTimeUs();
481template <
typename CommType>
483 return reinterpret_cast<CommHal*
>(self)->comm->Write(buf, len);
487template <
typename CommType>
489 return reinterpret_cast<CommHal*
>(self)->comm->GetTimeUs();
495template <
typename CommType>
501template <
typename CommType>
512template <
typename CommType>
514 sh2_SensorValue_t value;
515 int decode_status = sh2_decodeSensorEvent(&value, event);
516 if (decode_status != SH2_OK) {
517 last_error_ = decode_status;
520 uint8_t
id = value.sensorId;
521 if (
id >= latest_.size())
524 new_flag_[id] =
true;
526 callback_(toSensorEvent(
static_cast<BNO085Sensor>(
id), value));
536template <
typename CommType>
538 if (event->eventId == SH2_RESET) {
539 for (uint8_t
id = 0;
id < last_interval_.size(); ++id) {
540 if (last_interval_[
id])
541 configure(
static_cast<BNO085Sensor>(
id), last_interval_[
id], last_sensitivity_[
id], 0);
555template <
typename CommType>
557 uint32_t batch_us)
noexcept {
558 sh2_SensorConfig_t cfg{};
559 cfg.reportInterval_us = interval_us;
560 cfg.batchInterval_us = batch_us;
561 cfg.sensorSpecific = 0;
562 const float clamped_sensitivity = std::clamp(sensitivity, 0.0f, 65535.0f);
563 cfg.changeSensitivity =
static_cast<uint16_t
>(clamped_sensitivity + 0.5f);
564 cfg.changeSensitivityEnabled = clamped_sensitivity > 0.0f;
565 int status = sh2_setSensorConfig(
static_cast<sh2_SensorId_t
>(sensor), &cfg);
566 if (status != SH2_OK) {
567 last_error_ = status;
584template <
typename CommType>
587 io_.GpioSetActive(CtrlPin::RSTN);
589 io_.GpioSetInactive(CtrlPin::RSTN);
594template <
typename CommType>
598 io_.GpioSet(CtrlPin::BOOTN, state ? GpioSignal::ACTIVE : GpioSignal::INACTIVE);
602template <
typename CommType>
605 last_error_ = SH2_ERR_BAD_PARAM;
609 last_error_ = SH2_ERR_OP_IN_PROGRESS;
616 last_error_ = SH2_ERR_OP_IN_PROGRESS;
621 HardwareReset(resetLowMs);
626 last_error_ = SH2_OK;
631template <
typename CommType>
634 last_error_ = SH2_ERR_BAD_PARAM;
638 last_error_ = SH2_ERR_OP_IN_PROGRESS;
645 last_error_ = SH2_ERR_OP_IN_PROGRESS;
650 HardwareReset(resetLowMs);
654 last_error_ = SH2_OK;
659template <
typename CommType>
663 io_.GpioSet(CtrlPin::WAKE, state ? GpioSignal::ACTIVE : GpioSignal::INACTIVE);
672template <
typename CommType>
678 io_.GpioSetInactive(CtrlPin::PS1);
679 io_.GpioSetInactive(CtrlPin::PS0);
682 io_.GpioSetActive(CtrlPin::PS1);
683 io_.GpioSetInactive(CtrlPin::PS0);
686 io_.GpioSetInactive(CtrlPin::PS1);
687 io_.GpioSetActive(CtrlPin::PS0);
690 io_.GpioSetActive(CtrlPin::PS1);
691 io_.GpioSetActive(CtrlPin::PS0);
722template <
typename CommType>
727 last_error_ = SH2_ERR_OP_IN_PROGRESS;
731 last_error_ = SH2_ERR_BAD_PARAM;
735 last_error_ = SH2_ERR;
738 last_error_ = SH2_OK;
751template <
typename CommType>
756 while (io_.Read(&c, 1) == 1) {
762template <
typename CommType>
781template <
typename CommType>
783 if (rvc_frame_len_ == RVC_FRAME_LEN_) {
784 std::memmove(rvc_frame_, rvc_frame_ + 1, RVC_FRAME_LEN_ - 1);
785 rvc_frame_[RVC_FRAME_LEN_ - 1] = c;
787 rvc_frame_[rvc_frame_len_++] = c;
790 if (rvc_frame_len_ == RVC_FRAME_LEN_ && rvc_frame_[0] == 0xAA && rvc_frame_[1] == 0xAA) {
792 for (
int i = 2; i < RVC_FRAME_LEN_ - 1; ++i)
793 check += rvc_frame_[i];
795 if (check == rvc_frame_[RVC_FRAME_LEN_ - 1]) {
798 event.index = rvc_frame_[2];
799 event.yaw =
static_cast<int16_t
>((rvc_frame_[4] << 8) | rvc_frame_[3]);
800 event.pitch =
static_cast<int16_t
>((rvc_frame_[6] << 8) | rvc_frame_[5]);
801 event.roll =
static_cast<int16_t
>((rvc_frame_[8] << 8) | rvc_frame_[7]);
802 event.acc_x =
static_cast<int16_t
>((rvc_frame_[10] << 8) | rvc_frame_[9]);
803 event.acc_y =
static_cast<int16_t
>((rvc_frame_[12] << 8) | rvc_frame_[11]);
804 event.acc_z =
static_cast<int16_t
>((rvc_frame_[14] << 8) | rvc_frame_[13]);
805 event.mi = rvc_frame_[15];
806 event.mr = rvc_frame_[16];
810 decodeRvc(&val, &event);
824template <
typename CommType>
826 out->index = in->index;
827 out->yaw_deg = 0.01f * in->yaw;
828 out->pitch_deg = 0.01f * in->pitch;
829 out->roll_deg = 0.01f * in->roll;
830 out->acc_x_g = 0.001f * in->acc_x;
831 out->acc_y_g = 0.001f * in->acc_y;
832 out->acc_z_g = 0.001f * in->acc_z;
835 out->timestamp_uS = in->timestamp_uS;
855static constexpr uint8_t DFU_ACK =
's';
856static constexpr uint32_t DFU_MAX_PACKET_LEN = 64;
857static constexpr uint32_t DFU_MAX_ATTEMPTS = 5;
858static constexpr uint32_t DFU_DELAY_POST_US = 10000;
859static constexpr uint32_t DFU_SEND_TIMEOUT_US = 100000;
862template <
typename CommType>
866 return std::strcmp(part,
"1000-3608") == 0 || std::strcmp(part,
"1000-3676") == 0 ||
867 std::strcmp(part,
"1000-4148") == 0 || std::strcmp(part,
"1000-4563") == 0;
871template <
typename CommType>
873 *buf++ = (value >> 24) & 0xFF;
874 *buf++ = (value >> 16) & 0xFF;
875 *buf++ = (value >> 8) & 0xFF;
876 *buf++ = (value >> 0) & 0xFF;
880template <
typename CommType>
882 uint16_t crc = 0xFFFF;
883 for (
int n = 0; n < len; n++) {
884 uint16_t x =
static_cast<uint16_t
>(packet[n]) << 8;
885 for (
int i = 0; i < 8; i++) {
886 if ((crc ^ x) & 0x8000)
887 crc = (crc << 1) ^ 0x1021;
893 packet[len] = (crc >> 8) & 0xFF;
894 packet[len + 1] = crc & 0xFF;
905template <
typename CommType>
907 unsigned int retries = 0;
910 bool got_ack =
false;
912 sh2_Hal_t* hal = halWrapper_.asHal();
914 while (!got_ack && (retries < DFU_MAX_ATTEMPTS)) {
915 uint32_t now = hal->getTimeUs(hal);
916 uint32_t start = now;
918 while ((status == 0) && ((now - start) < DFU_SEND_TIMEOUT_US)) {
919 status = hal->write(hal, p_data, len);
920 now = hal->getTimeUs(hal);
923 status = SH2_ERR_TIMEOUT;
926 while ((status == 0) && ((now - start) < DFU_SEND_TIMEOUT_US)) {
927 status = hal->read(hal, &ack, 1, &t);
928 now = hal->getTimeUs(hal);
931 status = SH2_ERR_TIMEOUT;
934 if (ack == DFU_ACK) {
939 status = SH2_ERR_HUB;
945 return (status >= 0) ? SH2_OK : status;
949template <
typename CommType>
951 dfuWrite32be(dfu_buff, app_size);
952 dfuAppendCrc(dfu_buff, 4);
953 return dfuSend(dfu_buff, dfu_buff, 6);
957template <
typename CommType>
959 dfu_buff[0] = packet_len;
960 dfuAppendCrc(dfu_buff, 1);
961 return dfuSend(dfu_buff, dfu_buff, 3);
965template <
typename CommType>
967 std::memcpy(dfu_buff, p_data, len);
968 dfuAppendCrc(dfu_buff, len);
969 return dfuSend(dfu_buff, dfu_buff, len + 2);
973template <
typename CommType>
976 return DfuWithOptions(fw, options);
980template <
typename CommType>
983 if (!image.data || image.length == 0) {
984 last_error_ = SH2_ERR_BAD_PARAM;
985 return SH2_ERR_BAD_PARAM;
987 MemoryFirmware memfw(image.data, image.length, image.format ? image.format :
"BNO_V1",
988 image.partNumber ? image.partNumber :
"unknown", image.preferredPacketLen);
989 return DfuWithOptions(memfw.hcbin(), options);
993template <
typename CommType>
999 image.partNumber = partNumber ? partNumber :
"unknown";
1000 return DfuFromMemory(image, options);
1004template <
typename CommType>
1006 uint32_t enterResetLowMs, uint32_t enterSettleMs,
1007 uint32_t exitResetLowMs, uint32_t exitSettleMs)
noexcept {
1008 if (!EnterBootloader(enterResetLowMs, enterSettleMs))
1011 int status = DfuFromMemory(image, options);
1012 const int dfu_status = status;
1013 if (!ExitBootloaderAndReboot(exitResetLowMs, exitSettleMs) && status == SH2_OK) {
1015 status = last_error_;
1018 if (dfu_status != SH2_OK) {
1031template <
typename CommType>
1034 last_error_ = SH2_ERR_BAD_PARAM;
1035 return SH2_ERR_BAD_PARAM;
1038 last_error_ = SH2_ERR_OP_IN_PROGRESS;
1039 return SH2_ERR_OP_IN_PROGRESS;
1046 last_error_ = SH2_ERR_OP_IN_PROGRESS;
1047 return SH2_ERR_OP_IN_PROGRESS;
1050 prepareHalWrapper();
1052 int rc, status = SH2_OK;
1053 uint32_t app_len = 0;
1054 uint8_t packet_len = 0;
1055 uint32_t offset = 0;
1056 const char* meta =
nullptr;
1057 bool fw_opened =
false;
1058 bool hal_opened =
false;
1059 uint8_t dfu_buff[DFU_MAX_PACKET_LEN + 2];
1060 sh2_Hal_t* hal = halWrapper_.asHal();
1069 if (options.requireFormatMatch) {
1070 const char* expected_format = options.requiredFormat ? options.requiredFormat :
"BNO_V1";
1071 meta = fw.getMeta(
"FW-Format");
1072 if (!meta || std::strcmp(meta, expected_format) != 0) {
1073 status = SH2_ERR_BAD_PARAM;
1078 if (options.requirePartNumber) {
1079 meta = fw.getMeta(
"SW-Part-Number");
1081 status = SH2_ERR_BAD_PARAM;
1084 if (options.requiredPartNumber) {
1085 if (std::strcmp(meta, options.requiredPartNumber) != 0) {
1086 status = SH2_ERR_BAD_PARAM;
1089 }
else if (!dfuIsKnownPartNumber(meta)) {
1090 status = SH2_ERR_BAD_PARAM;
1095 app_len = fw.getAppLen();
1096 if (app_len < 1024) {
1097 status = SH2_ERR_BAD_PARAM;
1101 packet_len = fw.getPacketLen();
1102 if (options.packetLenOverride != 0) {
1103 packet_len = options.packetLenOverride;
1105 if (packet_len == 0 || packet_len > DFU_MAX_PACKET_LEN)
1106 packet_len = DFU_MAX_PACKET_LEN;
1108 status = hal->open(hal);
1109 if (status != SH2_OK)
1113 status = dfuSendAppSize(dfu_buff, app_len);
1114 if (status != SH2_OK)
1116 status = dfuSendPktSize(dfu_buff, packet_len);
1117 if (status != SH2_OK)
1120 if (options.progress) {
1125 while (offset < app_len) {
1126 uint32_t to_send = app_len - offset;
1127 if (to_send > packet_len)
1128 to_send = packet_len;
1129 status = fw.getAppData(dfu_buff, offset, to_send);
1130 if (status != SH2_OK) {
1134 status = dfuSendPkt(dfu_buff, dfu_buff, to_send);
1135 if (status != SH2_OK)
1138 if (options.progress) {
1146 if (status == SH2_OK && hal_opened) {
1147 uint32_t now = hal->getTimeUs(hal), start = now;
1148 while ((now - start) < DFU_DELAY_POST_US)
1149 now = hal->getTimeUs(hal);
1156 last_error_ = status;
High-level C++ driver for the BNO08x 9-axis IMU family.
BNO085Interface
Identifies the host interface type that a CommInterface provides.
Definition bno08x_comm_interface.hpp:25
@ UARTRVC
UART in RVC mode (PS1=1, PS0=0). RVC frames only.
@ SPI
SPI bus (PS1=1, PS0=1). Supports SH-2 and DFU.
@ UART
UART in SH-2 mode (PS1=0, PS0=1). Supports SH-2 and DFU.
@ I2C
I2C bus (PS1=0, PS0=0). Supports SH-2 and DFU.
Unified driver for the BNO08x IMU – SH-2 mode, RVC mode, and DFU.
Definition bno08x.hpp:375
int DfuWithOptions(const HcBin_t &fw, const DfuOptions &options) noexcept
Perform DFU with explicit validation and transfer options.
Definition bno08x.ipp:1032
bool DisableSensor(BNO085Sensor sensor) noexcept
Disable reporting for a sensor.
Definition bno08x.ipp:110
bool BeginRvc() noexcept
Initialise RVC mode.
Definition bno08x.ipp:723
void HardwareReset(uint32_t lowMs=2) noexcept
Perform a hardware reset via the RSTN pin.
Definition bno08x.ipp:585
bool HasNewData(BNO085Sensor sensor) const
Check if new data is available for a sensor.
Definition bno08x.ipp:140
SensorEvent GetLatest(BNO085Sensor sensor) noexcept
Retrieve the most recent event for a sensor.
Definition bno08x.ipp:412
bool EnableSensor(BNO085Sensor sensor, uint32_t interval_ms, float sensitivity=0.0f) noexcept
Enable periodic reporting for a sensor.
Definition bno08x.ipp:91
void ServiceRvc() noexcept
Poll for RVC frames and dispatch callbacks.
Definition bno08x.ipp:752
void SetCallback(SensorCallback cb) noexcept
Register a callback for SH-2 sensor events.
Definition bno08x.ipp:128
void CloseRvc() noexcept
Stop RVC processing and close the transport.
Definition bno08x.ipp:763
void SelectInterface(BNO085Interface iface) noexcept
Select the host interface by driving PS0/PS1 pins.
Definition bno08x.ipp:673
void SetWakePin(bool state) noexcept
Drive the WAKE pin (SPI mode only).
Definition bno08x.ipp:660
int DfuFromMemory(const DfuMemoryImage &image, const DfuOptions &options={}) noexcept
Perform DFU from an in-memory firmware image.
Definition bno08x.ipp:981
void Update() noexcept
Pump the SH-2 service loop.
Definition bno08x.ipp:427
int RunDfuFromMemory(const DfuMemoryImage &image, const DfuOptions &options={}, uint32_t enterResetLowMs=10, uint32_t enterSettleMs=50, uint32_t exitResetLowMs=2, uint32_t exitSettleMs=100) noexcept
Full class-aware DFU workflow: enter bootloader -> transfer firmware -> reboot to app.
Definition bno08x.ipp:1005
void Close() noexcept
Close the currently active session and release transport resources.
Definition bno08x.ipp:435
int Dfu(const HcBin_t &fw=firmware) noexcept
Perform a Device Firmware Update (DFU).
Definition bno08x.ipp:974
bool Begin() noexcept
Initialise the sensor in SH-2 mode.
Definition bno08x.ipp:40
bool EnterBootloader(uint32_t resetLowMs=10, uint32_t settleMs=50) noexcept
Enter bootloader mode using BOOTN + reset pin sequence.
Definition bno08x.ipp:603
void SetBootPin(bool state) noexcept
Drive the BOOTN pin to enter/exit DFU bootloader mode.
Definition bno08x.ipp:595
bool ExitBootloaderAndReboot(uint32_t resetLowMs=2, uint32_t settleMs=100) noexcept
Exit bootloader mode and reboot into application firmware.
Definition bno08x.ipp:632
void SetRvcCallback(RvcCallback cb) noexcept
Register a callback for decoded RVC frames.
Definition bno08x.ipp:134
HcBin_t implementation for firmware stored in memory.
Definition MemoryFirmware.hpp:16
std::function< void(const RvcSensorValue &)> RvcCallback
Callback invoked when a decoded RVC frame is available.
Definition bno08x.hpp:273
BNO085Sensor
Identifiers for all SH-2 sensor reports supported by the BNO08x.
Definition bno08x.hpp:44
std::function< void(const SensorEvent &)> SensorCallback
Callback invoked when a new SH-2 sensor event is received.
Definition bno08x.hpp:270
@ HeartRateMonitor
Heart rate data.
@ MagneticFieldUncalibrated
Raw magnetic field (uT)
@ GyroUncalibrated
Raw angular velocity (rad/s)
@ PersonalActivityClassifier
Activity classification (walking, running, etc.)
@ StepDetector
Individual step detected.
@ ShakeDetector
Shake gesture detected.
@ PickupDetector
Pickup gesture detected.
@ ARVRStabilizedRV
AR/VR stabilised rotation vector.
@ CircleDetector
Circular motion detected.
@ IZroMotionRequest
Interactive ZRO motion intent/request.
@ RawOpticalFlow
Raw optical flow report.
@ GeomagneticRotationVector
Orientation using magnetometer for heading.
@ FlipDetector
Flip gesture detected.
@ StepCounter
Cumulative step count.
@ Gravity
Gravity vector (m/s^2)
@ SleepDetector
Sleep state detected.
@ WheelEncoder
Wheel encoder report.
@ RotationVector
Fused absolute orientation quaternion.
@ SignificantMotion
Significant motion detected.
@ AmbientLight
Ambient light level (lux)
@ Magnetometer
Calibrated magnetic field (uT)
@ TiltDetector
Tilt event detected.
@ RawMagnetometer
Raw magnetometer ADC counts.
@ TapDetector
Single or double tap event.
@ Pressure
Barometric pressure (hPa)
@ StabilityClassifier
Device stability state (on table, in hand, etc.)
@ Accelerometer
Calibrated acceleration vector (m/s^2)
@ LinearAcceleration
Acceleration minus gravity (m/s^2)
@ Gyroscope
Calibrated angular velocity (rad/s)
@ StabilityDetector
Stability change detected.
@ GyroIntegratedRV
High-rate gyro-integrated rotation vector.
@ GameRotationVector
Orientation without magnetometer heading.
@ RawAccelerometer
Raw accelerometer ADC counts.
@ ARVRStabilizedGameRV
AR/VR stabilised game rotation vector.
@ Humidity
Relative humidity (%)
@ DeadReckoningPose
Dead reckoning pose estimate.
@ Temperature
Temperature (deg C)
@ RawGyroscope
Raw gyroscope ADC counts.
@ Proximity
Proximity detector (cm)
@ PocketDetector
Device-in-pocket detected.
CtrlPin
Identifies the hardware control pins of the BNO08x.
Definition bno08x_comm_interface.hpp:58
@ BOOTN
Bootloader entry (active-low on the physical pin)
GpioSignal
Abstract signal level for control pins.
Definition bno08x_comm_interface.hpp:74
Firmware image descriptor for class-aware memory DFU.
Definition bno08x.hpp:321
const uint8_t * data
Pointer to firmware bytes.
Definition bno08x.hpp:322
Controls DFU validation and transfer behavior.
Definition bno08x.hpp:308
Progress sample emitted during DFU transfers.
Definition bno08x.hpp:296
Raw RVC frame data in integer fixed-point format.
Definition bno08x.hpp:235
uint64_t timestamp_uS
Timestamp in microseconds (set by the driver)
Definition bno08x.hpp:245
Decoded RVC frame data in floating-point natural units.
Definition bno08x.hpp:254
Container for a single decoded SH-2 sensor report.
Definition bno08x.hpp:201
BNO085Sensor sensor
Which sensor produced this event.
Definition bno08x.hpp:202