HF-Core Platform 0.1.0-dev
Hardware-Agnostic Handler Layer & RTOS Utilities for HardFOC
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
189 void GpioSet(bno08x::CtrlPin pin, bno08x::GpioSignal signal) noexcept;
190
191private:
192 BaseI2c& i2c_;
193 BaseGpio* reset_gpio_;
194 BaseGpio* int_gpio_;
195};
196
202class HalSpiBno08xComm : public bno08x::CommInterface<HalSpiBno08xComm> {
203public:
211 explicit HalSpiBno08xComm(BaseSpi& spi,
212 BaseGpio* reset_gpio = nullptr,
213 BaseGpio* int_gpio = nullptr,
214 BaseGpio* wake_gpio = nullptr) noexcept
215 : spi_(spi), reset_gpio_(reset_gpio), int_gpio_(int_gpio), wake_gpio_(wake_gpio) {}
216
217 // -- bno08x::CommInterface required methods --
218
220 BNO085Interface GetInterfaceType() noexcept { return BNO085Interface::SPI; }
221
223 bool Open() noexcept;
225 void Close() noexcept;
227 int Write(const uint8_t* data, uint32_t length) noexcept;
229 int Read(uint8_t* data, uint32_t length) noexcept;
231 bool DataAvailable() noexcept;
233 void Delay(uint32_t ms) noexcept;
235 uint32_t GetTimeUs() noexcept;
236
238 void GpioSet(bno08x::CtrlPin pin, bno08x::GpioSignal signal) noexcept;
239
240private:
241 BaseSpi& spi_;
242 BaseGpio* reset_gpio_;
243 BaseGpio* int_gpio_;
244 BaseGpio* wake_gpio_;
245};
246
247// ============================================================================
248// TYPE-ERASED DRIVER INTERFACE (internal)
249// ============================================================================
250
258public:
259 virtual ~IBno08xDriverOps() noexcept = default;
260
261 virtual bool Begin() noexcept = 0;
262 virtual void Update() noexcept = 0;
263 virtual bool EnableSensor(BNO085Sensor sensor, uint32_t interval_ms,
264 float sensitivity) noexcept = 0;
265 virtual bool DisableSensor(BNO085Sensor sensor) noexcept = 0;
266 virtual void SetCallback(SensorCallback cb) noexcept = 0;
267 virtual bool HasNewData(BNO085Sensor sensor) const noexcept = 0;
268 virtual SensorEvent GetLatest(BNO085Sensor sensor) const noexcept = 0;
269 virtual int GetLastError() const noexcept = 0;
270 virtual void HardwareReset(uint32_t lowMs) noexcept = 0;
271 virtual void SetBootPin(bool state) noexcept = 0;
272 virtual void SetWakePin(bool state) noexcept = 0;
273 virtual void SelectInterface(BNO085Interface iface) noexcept = 0;
274 virtual BNO085Interface GetInterfaceType() noexcept = 0;
275};
276
286template <typename CommType>
288public:
292 explicit Bno08xDriverImpl(CommType&& comm) noexcept
293 : comm_(std::move(comm)), driver_(comm_) {}
294
295 bool Begin() noexcept override { return driver_.Begin(); }
296 void Update() noexcept override { driver_.Update(); }
297
298 bool EnableSensor(BNO085Sensor sensor, uint32_t interval_ms,
299 float sensitivity) noexcept override {
300 return driver_.EnableSensor(sensor, interval_ms, sensitivity);
301 }
302
303 bool DisableSensor(BNO085Sensor sensor) noexcept override {
304 return driver_.DisableSensor(sensor);
305 }
306
307 void SetCallback(SensorCallback cb) noexcept override {
308 driver_.SetCallback(std::move(cb));
309 }
310
311 bool HasNewData(BNO085Sensor sensor) const noexcept override {
312 return driver_.HasNewData(sensor);
313 }
314
315 SensorEvent GetLatest(BNO085Sensor sensor) const noexcept override {
316 return driver_.GetLatest(sensor);
317 }
318
319 int GetLastError() const noexcept override {
320 return driver_.GetLastError();
321 }
322
323 void HardwareReset(uint32_t lowMs) noexcept override {
324 driver_.HardwareReset(lowMs);
325 }
326
327 void SetBootPin(bool state) noexcept override {
328 driver_.SetBootPin(state);
329 }
330
331 void SetWakePin(bool state) noexcept override {
332 driver_.SetWakePin(state);
333 }
334
335 void SelectInterface(BNO085Interface iface) noexcept override {
336 driver_.SelectInterface(iface);
337 }
338
339 BNO085Interface GetInterfaceType() noexcept override {
340 return comm_.GetInterfaceType();
341 }
342
343private:
344 CommType comm_;
345 mutable BNO085<CommType> driver_;
346};
347
348// ============================================================================
349// SENSOR DATA STRUCTURES
350// ============================================================================
351
356 float x{0};
357 float y{0};
358 float z{0};
359 uint8_t accuracy{0};
360 uint64_t timestamp_us{0};
361 bool valid{false};
362};
363
368 float w{1};
369 float x{0};
370 float y{0};
371 float z{0};
372 uint8_t accuracy{0};
373 uint64_t timestamp_us{0};
374 bool valid{false};
375};
376
381 float roll{0};
382 float pitch{0};
383 float yaw{0};
384 uint8_t accuracy{0};
385 uint64_t timestamp_us{0};
386 bool valid{false};
387};
388
403
408 bool tap_detected{false};
409 bool double_tap{false};
410 uint8_t tap_direction{0};
411 uint32_t step_count{0};
412 bool step_detected{false};
413 bool shake_detected{false};
414 bool pickup_detected{false};
415 bool significant_motion{false};
416 uint8_t stability_class{0};
417 uint64_t timestamp_us{0};
418 bool valid{false};
419};
420
425 uint8_t accelerometer_accuracy{0};
426 uint8_t gyroscope_accuracy{0};
427 uint8_t magnetometer_accuracy{0};
428 uint8_t rotation_accuracy{0};
429 bool fully_calibrated{false};
430};
431
439 // Sensor enable flags
440 bool enable_accelerometer{true};
441 bool enable_gyroscope{true};
442 bool enable_magnetometer{true};
443 bool enable_rotation_vector{true};
444 bool enable_linear_acceleration{false};
445 bool enable_gravity{false};
446 bool enable_game_rotation{false};
447
448 // Activity detection (interval 0 = on-change)
449 bool enable_tap_detector{false};
450 bool enable_step_counter{false};
451 bool enable_step_detector{false};
452 bool enable_shake_detector{false};
453 bool enable_pickup_detector{false};
454 bool enable_significant_motion{false};
455 bool enable_stability_classifier{false};
456
457 // Sensor intervals (milliseconds, 0 = on-change for event sensors)
458 uint32_t accelerometer_interval_ms{50};
459 uint32_t gyroscope_interval_ms{50};
460 uint32_t magnetometer_interval_ms{100};
461 uint32_t rotation_interval_ms{50};
462 uint32_t linear_accel_interval_ms{50};
463 uint32_t gravity_interval_ms{100};
464 uint32_t game_rotation_interval_ms{50};
465};
466
467// ============================================================================
468// BNO08X HANDLER CLASS
469// ============================================================================
470
485public:
486 // ========================================================================
487 // CONSTRUCTION AND LIFECYCLE
488 // ========================================================================
489
497 explicit Bno08xHandler(BaseI2c& i2c_device,
498 const Bno08xConfig& config = Bno08xConfig{},
499 BaseGpio* reset_gpio = nullptr,
500 BaseGpio* int_gpio = nullptr) noexcept;
501
510 explicit Bno08xHandler(BaseSpi& spi_device,
511 const Bno08xConfig& config = Bno08xConfig{},
512 BaseGpio* reset_gpio = nullptr,
513 BaseGpio* int_gpio = nullptr,
514 BaseGpio* wake_gpio = nullptr) noexcept;
515
516 ~Bno08xHandler() noexcept = default;
517
518 // Non-copyable
519 Bno08xHandler(const Bno08xHandler&) = delete;
520 Bno08xHandler& operator=(const Bno08xHandler&) = delete;
521
522 // Non-movable
524 Bno08xHandler& operator=(Bno08xHandler&&) = delete;
525
526 // ========================================================================
527 // INITIALIZATION AND STATUS
528 // ========================================================================
529
538 Bno08xError Initialize() noexcept;
539
544 bool EnsureInitialized() noexcept;
545
550 Bno08xError Deinitialize() noexcept;
551
556 bool IsInitialized() const noexcept;
557
558 // ========================================================================
559 // SERVICE LOOP
560 // ========================================================================
561
570 Bno08xError Update() noexcept;
571
572 // ========================================================================
573 // CALLBACK MANAGEMENT
574 // ========================================================================
575
584 void SetSensorCallback(SensorCallback callback) noexcept;
585
589 void ClearSensorCallback() noexcept;
590
591 // ========================================================================
592 // UTILITY METHODS
593 // ========================================================================
594
600 static void QuaternionToEuler(const Bno08xQuaternion& quaternion,
601 Bno08xEulerAngles& euler_angles) noexcept;
602
607 BNO085Interface GetInterfaceType() const noexcept;
608
624 IBno08xDriverOps* GetSensor() noexcept;
625
627 const IBno08xDriverOps* GetSensor() const noexcept;
628
633 IBno08xDriverOps* GetDriver() noexcept { return GetSensor(); }
634 const IBno08xDriverOps* GetDriver() const noexcept { return GetSensor(); }
635
640 template <typename Fn>
641 auto visitDriver(Fn&& fn) noexcept -> decltype(fn(std::declval<IBno08xDriverOps&>())) {
642 using ReturnType = decltype(fn(std::declval<IBno08xDriverOps&>()));
643 MutexLockGuard lock(handler_mutex_);
644 if (!lock.IsLocked() || !ensureInitializedLocked() || !driver_ops_) {
645 if constexpr (std::is_void_v<ReturnType>) {
646 return;
647 } else {
648 return ReturnType{};
649 }
650 }
651 return fn(*driver_ops_);
652 }
653
658 Bno08xError GetLastError() const noexcept;
659
664 int GetLastDriverError() const noexcept;
665
670 const char* GetDescription() const noexcept;
671
676 static Bno08xConfig GetDefaultConfig() noexcept { return Bno08xConfig{}; }
677
681 void DumpDiagnostics() const noexcept;
682
683private:
684 // ========================================================================
685 // PRIVATE MEMBERS
686 // ========================================================================
687
688 std::unique_ptr<IBno08xDriverOps> driver_ops_;
689 Bno08xConfig config_;
690 mutable RtosMutex handler_mutex_;
691 bool initialized_{false};
692 mutable Bno08xError last_error_{Bno08xError::SUCCESS};
693 BNO085Interface interface_type_;
694 SensorCallback user_callback_;
695 char description_[64]{};
696
697 // ========================================================================
698 // PRIVATE HELPERS
699 // ========================================================================
700
704 bool ensureInitializedLocked() noexcept;
705
709 bool applyConfigLocked() noexcept;
710
714 static Bno08xError mapDriverError(int sh2_error) noexcept;
715};
716
717// ============================================================================
718// FACTORY METHODS
719// ============================================================================
720
729inline std::unique_ptr<Bno08xHandler> CreateBno08xHandlerI2c(
730 BaseI2c& i2c_device,
731 const Bno08xConfig& config = Bno08xConfig{},
732 BaseGpio* reset_gpio = nullptr,
733 BaseGpio* int_gpio = nullptr) noexcept {
734 return std::make_unique<Bno08xHandler>(i2c_device, config, reset_gpio, int_gpio);
735}
736
746inline std::unique_ptr<Bno08xHandler> CreateBno08xHandlerSpi(
747 BaseSpi& spi_device,
748 const Bno08xConfig& config = Bno08xConfig{},
749 BaseGpio* reset_gpio = nullptr,
750 BaseGpio* int_gpio = nullptr,
751 BaseGpio* wake_gpio = nullptr) noexcept {
752 return std::make_unique<Bno08xHandler>(spi_device, config, reset_gpio, int_gpio, wake_gpio);
753}
754
755#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:729
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:746
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:287
bool HasNewData(BNO085Sensor sensor) const noexcept override
Definition Bno08xHandler.h:311
void SetCallback(SensorCallback cb) noexcept override
Definition Bno08xHandler.h:307
void HardwareReset(uint32_t lowMs) noexcept override
Definition Bno08xHandler.h:323
BNO085< CommType > driver_
BNO085 driver instance (mutable: GetLatest clears internal flag)
Definition Bno08xHandler.h:345
void SetWakePin(bool state) noexcept override
Definition Bno08xHandler.h:331
void Update() noexcept override
Definition Bno08xHandler.h:296
void SetBootPin(bool state) noexcept override
Definition Bno08xHandler.h:327
SensorEvent GetLatest(BNO085Sensor sensor) const noexcept override
Definition Bno08xHandler.h:315
bool EnableSensor(BNO085Sensor sensor, uint32_t interval_ms, float sensitivity) noexcept override
Definition Bno08xHandler.h:298
bool DisableSensor(BNO085Sensor sensor) noexcept override
Definition Bno08xHandler.h:303
Bno08xDriverImpl(CommType &&comm) noexcept
Construct with a pre-built comm adapter (moved in).
Definition Bno08xHandler.h:292
int GetLastError() const noexcept override
Definition Bno08xHandler.h:319
bool Begin() noexcept override
Definition Bno08xHandler.h:295
void SelectInterface(BNO085Interface iface) noexcept override
Definition Bno08xHandler.h:335
CommType comm_
CRTP comm adapter (must outlive driver_)
Definition Bno08xHandler.h:344
BNO085Interface GetInterfaceType() noexcept override
Definition Bno08xHandler.h:339
Unified handler for BNO08x IMU sensor family.
Definition Bno08xHandler.h:484
~Bno08xHandler() noexcept=default
const IBno08xDriverOps * GetDriver() const noexcept
Definition Bno08xHandler.h:634
BNO085Interface interface_type_
I2C or SPI.
Definition Bno08xHandler.h:693
SensorCallback user_callback_
User's sensor callback.
Definition Bno08xHandler.h:694
auto visitDriver(Fn &&fn) noexcept -> decltype(fn(std::declval< IBno08xDriverOps & >()))
Visit the underlying IMU driver under handler mutex protection.
Definition Bno08xHandler.h:641
I2C CRTP communication adapter for BNO08x.
Definition Bno08xHandler.h:155
uint32_t GetTimeUs() noexcept
Definition Bno08xHandler.cpp:109
BaseGpio * int_gpio_
Definition Bno08xHandler.h:194
void GpioSet(bno08x::CtrlPin pin, bno08x::GpioSignal signal) noexcept
Definition Bno08xHandler.cpp:113
BaseI2c & i2c_
Definition Bno08xHandler.h:192
BaseGpio * reset_gpio_
Definition Bno08xHandler.h:193
void Close() noexcept
Definition Bno08xHandler.cpp:60
void Delay(uint32_t ms) noexcept
Definition Bno08xHandler.cpp:105
bool DataAvailable() noexcept
Definition Bno08xHandler.cpp:94
int Read(uint8_t *data, uint32_t length) noexcept
Definition Bno08xHandler.cpp:74
bool Open() noexcept
Definition Bno08xHandler.cpp:37
BNO085Interface GetInterfaceType() noexcept
Definition Bno08xHandler.h:171
int Write(const uint8_t *data, uint32_t length) noexcept
Definition Bno08xHandler.cpp:64
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:202
HalSpiBno08xComm(BaseSpi &spi, BaseGpio *reset_gpio=nullptr, BaseGpio *int_gpio=nullptr, BaseGpio *wake_gpio=nullptr) noexcept
Construct SPI adapter.
Definition Bno08xHandler.h:211
BNO085Interface GetInterfaceType() noexcept
Definition Bno08xHandler.h:220
Internal abstract interface for type-erasing the BNO085<CommType> template.
Definition Bno08xHandler.h:257
virtual ~IBno08xDriverOps() noexcept=default
Activity and gesture detection data.
Definition Bno08xHandler.h:407
Sensor calibration status.
Definition Bno08xHandler.h:424
BNO08x configuration structure.
Definition Bno08xHandler.h:438
Euler angles derived from quaternion.
Definition Bno08xHandler.h:380
Complete IMU sensor data structure.
Definition Bno08xHandler.h:392
Bno08xVector3 gravity
Gravity vector.
Definition Bno08xHandler.h:397
Bno08xVector3 gyroscope
Calibrated angular velocity (rad/s)
Definition Bno08xHandler.h:394
Bno08xVector3 acceleration
Calibrated acceleration (m/s^2)
Definition Bno08xHandler.h:393
Bno08xVector3 magnetometer
Calibrated magnetic field (uT)
Definition Bno08xHandler.h:395
Bno08xQuaternion rotation
Orientation quaternion.
Definition Bno08xHandler.h:398
Bno08xVector3 linear_acceleration
Linear acceleration (no gravity)
Definition Bno08xHandler.h:396
Bno08xEulerAngles euler
Euler angles.
Definition Bno08xHandler.h:399
Enhanced quaternion with timestamp and accuracy.
Definition Bno08xHandler.h:367
Enhanced vector with timestamp and accuracy.
Definition Bno08xHandler.h:355