HardFOC Core
API reference
Loading...
Searching...
No Matches
Bno08xHandler.h
Go to the documentation of this file.
1
80#ifndef COMPONENT_HANDLER_BNO08X_HANDLER_H_
81#define COMPONENT_HANDLER_BNO08X_HANDLER_H_
82
83#include <cstdint>
84#include <memory>
85#include <array>
86#include <functional>
87#include <type_traits>
88#include <utility>
89#include "core/hf-core-drivers/external/hf-bno08x-driver/inc/bno08x.hpp"
90#include "core/hf-core-drivers/external/hf-bno08x-driver/inc/bno08x_comm_interface.hpp"
91#include "base/BaseI2c.h"
92#include "base/BaseSpi.h"
93#include "base/BaseGpio.h"
94#include "RtosMutex.h"
95
96// ============================================================================
97// BNO08X ERROR CODES
98// ============================================================================
99
120
124constexpr const char* Bno08xErrorToString(Bno08xError error) noexcept {
125 switch (error) {
126 case Bno08xError::SUCCESS: return "Success";
127 case Bno08xError::NOT_INITIALIZED: return "Not initialized";
128 case Bno08xError::INITIALIZATION_FAILED: return "Initialization failed";
129 case Bno08xError::INVALID_PARAMETER: return "Invalid parameter";
130 case Bno08xError::COMMUNICATION_FAILED: return "Communication failed";
131 case Bno08xError::SENSOR_NOT_RESPONDING: return "Sensor not responding";
132 case Bno08xError::CALIBRATION_FAILED: return "Calibration failed";
133 case Bno08xError::FIRMWARE_UPDATE_FAILED: return "Firmware update failed";
134 case Bno08xError::TIMEOUT: return "Timeout";
135 case Bno08xError::MUTEX_LOCK_FAILED: return "Mutex lock failed";
136 case Bno08xError::INVALID_INTERFACE: return "Invalid interface";
137 case Bno08xError::SENSOR_NOT_ENABLED: return "Sensor not enabled";
138 case Bno08xError::DATA_NOT_AVAILABLE: return "Data not available";
139 case Bno08xError::HARDWARE_ERROR: return "Hardware error";
140 case Bno08xError::UNSUPPORTED_OPERATION: return "Unsupported operation";
141 default: return "Unknown error";
142 }
143}
144
145// ============================================================================
146// CRTP COMMUNICATION ADAPTERS
147// ============================================================================
148
155class HalI2cBno08xComm : public bno08x::CommInterface<HalI2cBno08xComm> {
156public:
163 explicit HalI2cBno08xComm(BaseI2c& i2c,
164 BaseGpio* reset_gpio = nullptr,
165 BaseGpio* int_gpio = nullptr) noexcept
166 : i2c_(i2c), reset_gpio_(reset_gpio), int_gpio_(int_gpio) {}
167
168 // -- bno08x::CommInterface required methods --
169
171 BNO085Interface GetInterfaceType() noexcept { return BNO085Interface::I2C; }
172
174 bool Open() noexcept;
176 void Close() noexcept;
178 int Write(const uint8_t* data, uint32_t length) noexcept;
180 int Read(uint8_t* data, uint32_t length) noexcept;
182 bool DataAvailable() noexcept;
184 void Delay(uint32_t ms) noexcept;
186 uint32_t GetTimeUs() noexcept;
187
190 bool GpioSet(bno08x::CtrlPin pin, bno08x::GpioSignal signal) noexcept;
191
192private:
193 BaseI2c& i2c_;
194 BaseGpio* reset_gpio_;
195 BaseGpio* int_gpio_;
196};
197
203class HalSpiBno08xComm : public bno08x::CommInterface<HalSpiBno08xComm> {
204public:
212 explicit HalSpiBno08xComm(BaseSpi& spi,
213 BaseGpio* reset_gpio = nullptr,
214 BaseGpio* int_gpio = nullptr,
215 BaseGpio* wake_gpio = nullptr) noexcept
216 : spi_(spi), reset_gpio_(reset_gpio), int_gpio_(int_gpio), wake_gpio_(wake_gpio) {}
217
218 // -- bno08x::CommInterface required methods --
219
221 BNO085Interface GetInterfaceType() noexcept { return BNO085Interface::SPI; }
222
224 bool Open() noexcept;
226 void Close() noexcept;
228 int Write(const uint8_t* data, uint32_t length) noexcept;
230 int Read(uint8_t* data, uint32_t length) noexcept;
232 bool DataAvailable() noexcept;
234 void Delay(uint32_t ms) noexcept;
236 uint32_t GetTimeUs() noexcept;
237
240 bool GpioSet(bno08x::CtrlPin pin, bno08x::GpioSignal signal) noexcept;
241
242private:
243 BaseSpi& spi_;
244 BaseGpio* reset_gpio_;
245 BaseGpio* int_gpio_;
246 BaseGpio* wake_gpio_;
247};
248
249// ============================================================================
250// TYPE-ERASED DRIVER INTERFACE (internal)
251// ============================================================================
252
260public:
261 virtual ~IBno08xDriverOps() noexcept = default;
262
263 virtual bool Begin() noexcept = 0;
264 virtual void Update() noexcept = 0;
265 virtual bool EnableSensor(BNO085Sensor sensor, uint32_t interval_ms,
266 float sensitivity) noexcept = 0;
267 virtual bool DisableSensor(BNO085Sensor sensor) noexcept = 0;
268 virtual void SetCallback(SensorCallback cb) noexcept = 0;
269 virtual bool HasNewData(BNO085Sensor sensor) const noexcept = 0;
270 virtual SensorEvent GetLatest(BNO085Sensor sensor) const noexcept = 0;
271 virtual int GetLastError() const noexcept = 0;
273 virtual bool HardwareReset(uint32_t lowMs) noexcept = 0;
274 virtual bool SetBootPin(bool state) noexcept = 0;
275 virtual bool SetWakePin(bool state) noexcept = 0;
276 virtual bool SelectInterface(BNO085Interface iface) noexcept = 0;
277 virtual BNO085Interface GetInterfaceType() noexcept = 0;
278};
279
289template <typename CommType>
291public:
295 explicit Bno08xDriverImpl(CommType&& comm) noexcept
296 : comm_(std::move(comm)), driver_(comm_) {}
297
298 bool Begin() noexcept override { return driver_.Begin(); }
299 void Update() noexcept override { driver_.Update(); }
300
301 bool EnableSensor(BNO085Sensor sensor, uint32_t interval_ms,
302 float sensitivity) noexcept override {
303 return driver_.EnableSensor(sensor, interval_ms, sensitivity);
304 }
305
306 bool DisableSensor(BNO085Sensor sensor) noexcept override {
307 return driver_.DisableSensor(sensor);
308 }
309
310 void SetCallback(SensorCallback cb) noexcept override {
311 driver_.SetCallback(std::move(cb));
312 }
313
314 bool HasNewData(BNO085Sensor sensor) const noexcept override {
315 return driver_.HasNewData(sensor);
316 }
317
318 SensorEvent GetLatest(BNO085Sensor sensor) const noexcept override {
319 return driver_.GetLatest(sensor);
320 }
321
322 int GetLastError() const noexcept override {
323 return driver_.GetLastError();
324 }
325
326 bool HardwareReset(uint32_t lowMs) noexcept override {
327 return driver_.HardwareReset(lowMs);
328 }
329
330 bool SetBootPin(bool state) noexcept override {
331 return driver_.SetBootPin(state);
332 }
333
334 bool SetWakePin(bool state) noexcept override {
335 return driver_.SetWakePin(state);
336 }
337
338 bool SelectInterface(BNO085Interface iface) noexcept override {
339 return driver_.SelectInterface(iface);
340 }
341
342 BNO085Interface GetInterfaceType() noexcept override {
343 return comm_.GetInterfaceType();
344 }
345
346private:
347 CommType comm_;
348 mutable BNO085<CommType> driver_;
349};
350
351// ============================================================================
352// SENSOR DATA STRUCTURES
353// ============================================================================
354
359 float x{0};
360 float y{0};
361 float z{0};
362 uint8_t accuracy{0};
363 uint64_t timestamp_us{0};
364 bool valid{false};
365};
366
371 float w{1};
372 float x{0};
373 float y{0};
374 float z{0};
375 uint8_t accuracy{0};
376 uint64_t timestamp_us{0};
377 bool valid{false};
378};
379
384 float roll{0};
385 float pitch{0};
386 float yaw{0};
387 uint8_t accuracy{0};
388 uint64_t timestamp_us{0};
389 bool valid{false};
390};
391
406
411 bool tap_detected{false};
412 bool double_tap{false};
413 uint8_t tap_direction{0};
414 uint32_t step_count{0};
415 bool step_detected{false};
416 bool shake_detected{false};
417 bool pickup_detected{false};
418 bool significant_motion{false};
419 uint8_t stability_class{0};
420 uint64_t timestamp_us{0};
421 bool valid{false};
422};
423
428 uint8_t accelerometer_accuracy{0};
429 uint8_t gyroscope_accuracy{0};
430 uint8_t magnetometer_accuracy{0};
431 uint8_t rotation_accuracy{0};
432 bool fully_calibrated{false};
433};
434
442 // Sensor enable flags
443 bool enable_accelerometer{true};
444 bool enable_gyroscope{true};
445 bool enable_magnetometer{true};
446 bool enable_rotation_vector{true};
447 bool enable_linear_acceleration{false};
448 bool enable_gravity{false};
449 bool enable_game_rotation{false};
450
451 // Activity detection (interval 0 = on-change)
452 bool enable_tap_detector{false};
453 bool enable_step_counter{false};
454 bool enable_step_detector{false};
455 bool enable_shake_detector{false};
456 bool enable_pickup_detector{false};
457 bool enable_significant_motion{false};
458 bool enable_stability_classifier{false};
459
460 // Sensor intervals (milliseconds, 0 = on-change for event sensors)
461 uint32_t accelerometer_interval_ms{50};
462 uint32_t gyroscope_interval_ms{50};
463 uint32_t magnetometer_interval_ms{100};
464 uint32_t rotation_interval_ms{50};
465 uint32_t linear_accel_interval_ms{50};
466 uint32_t gravity_interval_ms{100};
467 uint32_t game_rotation_interval_ms{50};
468};
469
470// ============================================================================
471// BNO08X HANDLER CLASS
472// ============================================================================
473
488public:
489 // ========================================================================
490 // CONSTRUCTION AND LIFECYCLE
491 // ========================================================================
492
500 explicit Bno08xHandler(BaseI2c& i2c_device,
501 const Bno08xConfig& config = Bno08xConfig{},
502 BaseGpio* reset_gpio = nullptr,
503 BaseGpio* int_gpio = nullptr) noexcept;
504
513 explicit Bno08xHandler(BaseSpi& spi_device,
514 const Bno08xConfig& config = Bno08xConfig{},
515 BaseGpio* reset_gpio = nullptr,
516 BaseGpio* int_gpio = nullptr,
517 BaseGpio* wake_gpio = nullptr) noexcept;
518
519 ~Bno08xHandler() noexcept = default;
520
521 // Non-copyable
522 Bno08xHandler(const Bno08xHandler&) = delete;
523 Bno08xHandler& operator=(const Bno08xHandler&) = delete;
524
525 // Non-movable
527 Bno08xHandler& operator=(Bno08xHandler&&) = delete;
528
529 // ========================================================================
530 // INITIALIZATION AND STATUS
531 // ========================================================================
532
541 Bno08xError Initialize() noexcept;
542
547 bool EnsureInitialized() noexcept;
548
553 Bno08xError Deinitialize() noexcept;
554
559 bool IsInitialized() const noexcept;
560
561 // ========================================================================
562 // SERVICE LOOP
563 // ========================================================================
564
573 Bno08xError Update() noexcept;
574
575 // ========================================================================
576 // CALLBACK MANAGEMENT
577 // ========================================================================
578
587 void SetSensorCallback(SensorCallback callback) noexcept;
588
592 void ClearSensorCallback() noexcept;
593
594 // ========================================================================
595 // UTILITY METHODS
596 // ========================================================================
597
603 static void QuaternionToEuler(const Bno08xQuaternion& quaternion,
604 Bno08xEulerAngles& euler_angles) noexcept;
605
610 BNO085Interface GetInterfaceType() const noexcept;
611
627 IBno08xDriverOps* GetSensor() noexcept;
628
630 const IBno08xDriverOps* GetSensor() const noexcept;
631
636 IBno08xDriverOps* GetDriver() noexcept { return GetSensor(); }
637 const IBno08xDriverOps* GetDriver() const noexcept { return GetSensor(); }
638
643 template <typename Fn>
644 auto visitDriver(Fn&& fn) noexcept -> decltype(fn(std::declval<IBno08xDriverOps&>())) {
645 using ReturnType = decltype(fn(std::declval<IBno08xDriverOps&>()));
646 MutexLockGuard lock(handler_mutex_);
647 if (!lock.IsLocked() || !ensureInitializedLocked() || !driver_ops_) {
648 if constexpr (std::is_void_v<ReturnType>) {
649 return;
650 } else {
651 return ReturnType{};
652 }
653 }
654 return fn(*driver_ops_);
655 }
656
661 Bno08xError GetLastError() const noexcept;
662
667 int GetLastDriverError() const noexcept;
668
673 const char* GetDescription() const noexcept;
674
679 static Bno08xConfig GetDefaultConfig() noexcept { return Bno08xConfig{}; }
680
684 void DumpDiagnostics() const noexcept;
685
686private:
687 // ========================================================================
688 // PRIVATE MEMBERS
689 // ========================================================================
690
691 std::unique_ptr<IBno08xDriverOps> driver_ops_;
692 Bno08xConfig config_;
693 mutable RtosMutex handler_mutex_;
694 bool initialized_{false};
695 mutable Bno08xError last_error_{Bno08xError::SUCCESS};
696 BNO085Interface interface_type_;
697 SensorCallback user_callback_;
698 char description_[64]{};
699
700 // ========================================================================
701 // PRIVATE HELPERS
702 // ========================================================================
703
707 bool ensureInitializedLocked() noexcept;
708
712 bool applyConfigLocked() noexcept;
713
717 static Bno08xError mapDriverError(int sh2_error) noexcept;
718};
719
720// ============================================================================
721// FACTORY METHODS
722// ============================================================================
723
732inline std::unique_ptr<Bno08xHandler> CreateBno08xHandlerI2c(
733 BaseI2c& i2c_device,
734 const Bno08xConfig& config = Bno08xConfig{},
735 BaseGpio* reset_gpio = nullptr,
736 BaseGpio* int_gpio = nullptr) noexcept {
737 return std::make_unique<Bno08xHandler>(i2c_device, config, reset_gpio, int_gpio);
738}
739
749inline std::unique_ptr<Bno08xHandler> CreateBno08xHandlerSpi(
750 BaseSpi& spi_device,
751 const Bno08xConfig& config = Bno08xConfig{},
752 BaseGpio* reset_gpio = nullptr,
753 BaseGpio* int_gpio = nullptr,
754 BaseGpio* wake_gpio = nullptr) noexcept {
755 return std::make_unique<Bno08xHandler>(spi_device, config, reset_gpio, int_gpio, wake_gpio);
756}
757
758#endif // COMPONENT_HANDLER_BNO08X_HANDLER_H_
std::unique_ptr< Bno08xHandler > CreateBno08xHandlerI2c(BaseI2c &i2c_device, const Bno08xConfig &config=Bno08xConfig{}, BaseGpio *reset_gpio=nullptr, BaseGpio *int_gpio=nullptr) noexcept
Create BNO08x handler with I2C interface.
Definition Bno08xHandler.h:732
std::unique_ptr< Bno08xHandler > CreateBno08xHandlerSpi(BaseSpi &spi_device, const Bno08xConfig &config=Bno08xConfig{}, BaseGpio *reset_gpio=nullptr, BaseGpio *int_gpio=nullptr, BaseGpio *wake_gpio=nullptr) noexcept
Create BNO08x handler with SPI interface.
Definition Bno08xHandler.h:749
constexpr const char * Bno08xErrorToString(Bno08xError error) noexcept
Convert Bno08xError to string for debugging.
Definition Bno08xHandler.h:124
Bno08xError
BNO08x handler error codes for consistent error reporting.
Definition Bno08xHandler.h:103
@ NOT_INITIALIZED
Handler or sensor not initialized.
@ TIMEOUT
Operation timed out.
@ MUTEX_LOCK_FAILED
Could not acquire handler mutex.
@ INVALID_INTERFACE
Wrong interface type for operation.
@ COMMUNICATION_FAILED
I2C/SPI or SH-2 I/O error.
@ UNSUPPORTED_OPERATION
Feature not supported.
@ HARDWARE_ERROR
GPIO or hardware fault.
@ CALIBRATION_FAILED
Calibration request failed.
@ FIRMWARE_UPDATE_FAILED
DFU transfer failed.
@ SUCCESS
Operation completed successfully.
@ SENSOR_NOT_ENABLED
Sensor not enabled for read.
@ DATA_NOT_AVAILABLE
No new data for requested sensor.
@ SENSOR_NOT_RESPONDING
Hub/sensor did not respond.
@ INITIALIZATION_FAILED
Begin() or config apply failed.
@ INVALID_PARAMETER
Bad argument (e.g. invalid sensor)
Concrete type-erased driver wrapper.
Definition Bno08xHandler.h:290
bool HardwareReset(uint32_t lowMs) noexcept override
Pin calls return false when the port could not drive a pin (GPIO error).
Definition Bno08xHandler.h:326
bool HasNewData(BNO085Sensor sensor) const noexcept override
Definition Bno08xHandler.h:314
void SetCallback(SensorCallback cb) noexcept override
Definition Bno08xHandler.h:310
BNO085< CommType > driver_
BNO085 driver instance (mutable: GetLatest clears internal flag)
Definition Bno08xHandler.h:348
void Update() noexcept override
Definition Bno08xHandler.h:299
SensorEvent GetLatest(BNO085Sensor sensor) const noexcept override
Definition Bno08xHandler.h:318
bool EnableSensor(BNO085Sensor sensor, uint32_t interval_ms, float sensitivity) noexcept override
Definition Bno08xHandler.h:301
bool DisableSensor(BNO085Sensor sensor) noexcept override
Definition Bno08xHandler.h:306
bool SetBootPin(bool state) noexcept override
Definition Bno08xHandler.h:330
Bno08xDriverImpl(CommType &&comm) noexcept
Construct with a pre-built comm adapter (moved in).
Definition Bno08xHandler.h:295
int GetLastError() const noexcept override
Definition Bno08xHandler.h:322
bool SelectInterface(BNO085Interface iface) noexcept override
Definition Bno08xHandler.h:338
bool Begin() noexcept override
Definition Bno08xHandler.h:298
bool SetWakePin(bool state) noexcept override
Definition Bno08xHandler.h:334
CommType comm_
CRTP comm adapter (must outlive driver_)
Definition Bno08xHandler.h:347
BNO085Interface GetInterfaceType() noexcept override
Definition Bno08xHandler.h:342
Unified handler for BNO08x IMU sensor family.
Definition Bno08xHandler.h:487
~Bno08xHandler() noexcept=default
const IBno08xDriverOps * GetDriver() const noexcept
Definition Bno08xHandler.h:637
BNO085Interface interface_type_
I2C or SPI.
Definition Bno08xHandler.h:696
SensorCallback user_callback_
User's sensor callback.
Definition Bno08xHandler.h:697
auto visitDriver(Fn &&fn) noexcept -> decltype(fn(std::declval< IBno08xDriverOps & >()))
Visit the underlying IMU driver under handler mutex protection.
Definition Bno08xHandler.h:644
I2C CRTP communication adapter for BNO08x.
Definition Bno08xHandler.h:155
uint32_t GetTimeUs() noexcept
Definition Bno08xHandler.cpp:141
BaseGpio * int_gpio_
Definition Bno08xHandler.h:195
BaseI2c & i2c_
Definition Bno08xHandler.h:193
BaseGpio * reset_gpio_
Definition Bno08xHandler.h:194
void Close() noexcept
Definition Bno08xHandler.cpp:92
bool GpioSet(bno08x::CtrlPin pin, bno08x::GpioSignal signal) noexcept
Definition Bno08xHandler.cpp:145
void Delay(uint32_t ms) noexcept
Definition Bno08xHandler.cpp:137
bool DataAvailable() noexcept
Definition Bno08xHandler.cpp:126
int Read(uint8_t *data, uint32_t length) noexcept
Definition Bno08xHandler.cpp:106
bool Open() noexcept
Definition Bno08xHandler.cpp:72
BNO085Interface GetInterfaceType() noexcept
Definition Bno08xHandler.h:171
int Write(const uint8_t *data, uint32_t length) noexcept
Definition Bno08xHandler.cpp:96
HalI2cBno08xComm(BaseI2c &i2c, BaseGpio *reset_gpio=nullptr, BaseGpio *int_gpio=nullptr) noexcept
Construct I2C adapter.
Definition Bno08xHandler.h:163
SPI CRTP communication adapter for BNO08x.
Definition Bno08xHandler.h:203
HalSpiBno08xComm(BaseSpi &spi, BaseGpio *reset_gpio=nullptr, BaseGpio *int_gpio=nullptr, BaseGpio *wake_gpio=nullptr) noexcept
Construct SPI adapter.
Definition Bno08xHandler.h:212
BNO085Interface GetInterfaceType() noexcept
Definition Bno08xHandler.h:221
Internal abstract interface for type-erasing the BNO085<CommType> template.
Definition Bno08xHandler.h:259
virtual ~IBno08xDriverOps() noexcept=default
Activity and gesture detection data.
Definition Bno08xHandler.h:410
Sensor calibration status.
Definition Bno08xHandler.h:427
BNO08x configuration structure.
Definition Bno08xHandler.h:441
Euler angles derived from quaternion.
Definition Bno08xHandler.h:383
Complete IMU sensor data structure.
Definition Bno08xHandler.h:395
Bno08xVector3 gravity
Gravity vector.
Definition Bno08xHandler.h:400
Bno08xVector3 gyroscope
Calibrated angular velocity (rad/s)
Definition Bno08xHandler.h:397
Bno08xVector3 acceleration
Calibrated acceleration (m/s^2)
Definition Bno08xHandler.h:396
Bno08xVector3 magnetometer
Calibrated magnetic field (uT)
Definition Bno08xHandler.h:398
Bno08xQuaternion rotation
Orientation quaternion.
Definition Bno08xHandler.h:401
Bno08xVector3 linear_acceleration
Linear acceleration (no gravity)
Definition Bno08xHandler.h:399
Bno08xEulerAngles euler
Euler angles.
Definition Bno08xHandler.h:402
Enhanced quaternion with timestamp and accuracy.
Definition Bno08xHandler.h:370
Enhanced vector with timestamp and accuracy.
Definition Bno08xHandler.h:358