HF-Core Platform 0.1.0-dev
Hardware-Agnostic Handler Layer & RTOS Utilities for HardFOC
Loading...
Searching...
No Matches
Pca9685Handler.h
Go to the documentation of this file.
1
86#ifndef COMPONENT_HANDLER_PCA9685_HANDLER_H_
87#define COMPONENT_HANDLER_PCA9685_HANDLER_H_
88
89#include <cstdint>
90#include <memory>
91#include <array>
92#include <cmath>
93#include "base/BaseGpio.h"
94#include "base/BasePwm.h"
95#include "base/BaseI2c.h"
96#include "core/hf-core-drivers/external/hf-pca9685-driver/inc/pca9685.hpp"
97#include "RtosMutex.h"
98
99// Forward declarations
100class Pca9685Handler;
101
107
130class HalI2cPca9685Comm : public pca9685::I2cInterface<HalI2cPca9685Comm> {
131public:
137 explicit HalI2cPca9685Comm(BaseI2c& i2c_device) noexcept;
138
142
154 bool Write(uint8_t addr, uint8_t reg, const uint8_t* data, size_t len) noexcept;
155
167 bool Read(uint8_t addr, uint8_t reg, uint8_t* data, size_t len) noexcept;
168
173 bool EnsureInitialized() noexcept;
174
176
177private:
178 BaseI2c& i2c_device_;
179 mutable RtosMutex i2c_mutex_;
180};
181
183
189
214class Pca9685PwmAdapter : public BasePwm {
215public:
217 static constexpr uint8_t kMaxChannels = 16;
218
220 static constexpr uint8_t kResolutionBits = 12;
221
223 static constexpr uint16_t kMaxRawValue = 4095;
224
226 static constexpr uint32_t kMinFrequencyHz = 24;
227
229 static constexpr uint32_t kMaxFrequencyHz = 1526;
230
235 explicit Pca9685PwmAdapter(Pca9685Handler* parent_handler) noexcept;
236
238 ~Pca9685PwmAdapter() noexcept override = default;
239
242
244 hf_pwm_err_t Initialize() noexcept override;
245
247 hf_pwm_err_t Deinitialize() noexcept override;
248
254 hf_pwm_err_t EnableChannel(hf_channel_id_t channel_id) noexcept override;
255
261 hf_pwm_err_t DisableChannel(hf_channel_id_t channel_id) noexcept override;
262
268 bool IsChannelEnabled(hf_channel_id_t channel_id) const noexcept override;
269
276 hf_pwm_err_t SetDutyCycle(hf_channel_id_t channel_id,
277 float duty_cycle) noexcept override;
278
285 hf_pwm_err_t SetDutyCycleRaw(hf_channel_id_t channel_id,
286 hf_u32_t raw_value) noexcept override;
287
299 hf_pwm_err_t SetFrequency(hf_channel_id_t channel_id,
300 hf_frequency_hz_t frequency_hz) noexcept override;
301
313 hf_pwm_err_t SetPhaseShift(hf_channel_id_t channel_id,
314 float phase_shift_degrees) noexcept override;
315
320 hf_pwm_err_t StartAll() noexcept override;
321
326 hf_pwm_err_t StopAll() noexcept override;
327
332 hf_pwm_err_t UpdateAll() noexcept override;
333
338 hf_pwm_err_t SetComplementaryOutput(hf_channel_id_t primary_channel,
339 hf_channel_id_t complementary_channel,
340 hf_u32_t deadtime_ns) noexcept override;
341
347 float GetDutyCycle(hf_channel_id_t channel_id) const noexcept override;
348
354 hf_frequency_hz_t GetFrequency(hf_channel_id_t channel_id) const noexcept override;
355
357
359 friend class Pca9685Handler;
360
361private:
363
366 std::array<float, kMaxChannels> duty_cache_;
367 std::array<uint16_t, kMaxChannels> on_time_cache_;
368 std::array<bool, kMaxChannels> channel_enabled_;
370
371 hf_frequency_hz_t current_frequency_hz_ = 200;
372
374 bool validateChannel(hf_channel_id_t channel_id) const noexcept {
375 return channel_id < kMaxChannels;
376 }
377};
378
380
386
408class Pca9685GpioPin : public BaseGpio {
409public:
416 Pca9685GpioPin(hf_pin_num_t pin,
417 Pca9685Handler* parent_handler,
418 hf_gpio_active_state_t active_state =
419 hf_gpio_active_state_t::HF_GPIO_ACTIVE_HIGH) noexcept;
420
422 ~Pca9685GpioPin() noexcept override = default;
423
426
428 bool Initialize() noexcept override;
429
431 bool Deinitialize() noexcept override;
432
434 bool IsPinAvailable() const noexcept override;
435
437 hf_u8_t GetMaxPins() const noexcept override { return 16; }
438
440 const char* GetDescription() const noexcept override;
441
443
444protected:
447
452 hf_gpio_err_t SetDirectionImpl(hf_gpio_direction_t direction) noexcept override;
453
455 hf_gpio_err_t GetDirectionImpl(hf_gpio_direction_t& direction) const noexcept override;
456
458 hf_gpio_err_t SetOutputModeImpl(hf_gpio_output_mode_t mode) noexcept override;
459
461 hf_gpio_err_t GetOutputModeImpl(hf_gpio_output_mode_t& mode) const noexcept override;
462
464 hf_gpio_err_t SetPullModeImpl(hf_gpio_pull_mode_t mode) noexcept override;
465
467 hf_gpio_pull_mode_t GetPullModeImpl() const noexcept override;
468
474 hf_gpio_err_t SetPinLevelImpl(hf_gpio_level_t level) noexcept override;
475
479 hf_gpio_err_t GetPinLevelImpl(hf_gpio_level_t& level) noexcept override;
480
482
483 friend class Pca9685Handler;
484
485private:
486 hf_pin_num_t pin_;
488 char description_[32] = {};
489 hf_gpio_level_t cached_level_ =
490 hf_gpio_level_t::HF_GPIO_LEVEL_LOW;
491};
492
494
500
530public:
531 //==========================================================================
534 //==========================================================================
535
537 using Pca9685Driver = pca9685::PCA9685<HalI2cPca9685Comm>;
538
540
541 //==========================================================================
544 //==========================================================================
545
555 explicit Pca9685Handler(BaseI2c& i2c_device) noexcept;
556
558 ~Pca9685Handler() noexcept = default;
559
563 Pca9685Handler& operator=(const Pca9685Handler&) = delete;
564
568 Pca9685Handler& operator=(Pca9685Handler&&) = delete;
569
571
572 //==========================================================================
575 //==========================================================================
576
585 bool EnsureInitialized() noexcept;
586
591 bool EnsureDeinitialized() noexcept;
592
597 bool IsInitialized() const noexcept { return initialized_; }
598
600
601 //==========================================================================
605 //==========================================================================
606
608 static constexpr uint8_t ChannelCount() noexcept { return 16; }
609
614 uint8_t GetI2cAddress() const noexcept;
615
624 std::shared_ptr<BasePwm> GetPwmAdapter() noexcept;
625
638 std::shared_ptr<BaseGpio> CreateGpioPin(
639 hf_pin_num_t channel,
640 hf_gpio_active_state_t active_state =
641 hf_gpio_active_state_t::HF_GPIO_ACTIVE_HIGH,
642 bool allow_existing = true) noexcept;
643
649 std::shared_ptr<BaseGpio> GetGpioPin(hf_pin_num_t channel) noexcept;
650
656 bool IsPinCreated(hf_pin_num_t channel) const noexcept;
657
659
660 //==========================================================================
663 //==========================================================================
664
669 uint16_t GetErrorFlags() const noexcept;
670
675 void ClearErrorFlags(uint16_t mask = 0xFFFF) noexcept;
676
678
679 //==========================================================================
682 //==========================================================================
683
687 void DumpDiagnostics() const noexcept;
688
690
691 //==========================================================================
694 //==========================================================================
695
700 [[nodiscard]] Pca9685Driver* GetDriver() noexcept;
701 [[nodiscard]] const Pca9685Driver* GetDriver() const noexcept;
702
704
706 friend class Pca9685PwmAdapter;
707 friend class Pca9685GpioPin;
708
709private:
710 //==========================================================================
711 // Private Methods
712 //==========================================================================
713
715 bool ensureInitializedLocked() noexcept;
716
718 hf_pwm_err_t initializeInternal() noexcept;
719
721 hf_pwm_err_t deinitializeInternal() noexcept;
722
724 bool validateChannel(uint8_t channel) const noexcept { return channel < 16; }
725
726 // ---- PWM/power/output ops (used internally by Pca9685PwmAdapter & Pca9685GpioPin) ----
727 bool SetFrequency(float freq_hz) noexcept;
728 bool SetDuty(uint8_t channel, float duty) noexcept;
729 bool SetPwm(uint8_t channel, uint16_t on_time, uint16_t off_time) noexcept;
730 bool SetAllPwm(uint16_t on_time, uint16_t off_time) noexcept;
731 bool SetChannelFullOn(uint8_t channel) noexcept;
732 bool SetChannelFullOff(uint8_t channel) noexcept;
733 bool Sleep() noexcept;
734 bool Wake() noexcept;
735 bool SetOutputInvert(bool invert) noexcept;
736 bool SetOutputDriverMode(bool totem_pole) noexcept;
737
738 //==========================================================================
739 // Private Members
740 //==========================================================================
741
744 BaseI2c& i2c_device_;
747 bool initialized_ = false;
748 mutable RtosMutex handler_mutex_;
750
754 std::array<std::shared_ptr<Pca9685GpioPin>, 16> gpio_registry_;
756};
757
759
760#endif // COMPONENT_HANDLER_PCA9685_HANDLER_H_
Concrete I2C communication adapter for PCA9685 using BaseI2c.
Definition Pca9685Handler.h:130
RtosMutex i2c_mutex_
Thread safety for I2C operations.
Definition Pca9685Handler.h:179
bool Read(uint8_t addr, uint8_t reg, uint8_t *data, size_t len) noexcept
Read data from a device register.
Definition Pca9685Handler.cpp:57
BaseI2c & i2c_device_
I2C device interface (not owned).
Definition Pca9685Handler.h:178
bool EnsureInitialized() noexcept
Ensure the I2C bus is initialized and ready.
Definition Pca9685Handler.cpp:68
HalI2cPca9685Comm(BaseI2c &i2c_device) noexcept
Construct the I2C communication adapter.
Definition Pca9685Handler.cpp:32
bool Write(uint8_t addr, uint8_t reg, const uint8_t *data, size_t len) noexcept
Write data to a device register.
Definition Pca9685Handler.cpp:35
BaseGpio adapter for a single PCA9685 channel used as a digital output.
Definition Pca9685Handler.h:408
hf_pin_num_t pin_
Channel number (0-15).
Definition Pca9685Handler.h:486
hf_gpio_err_t SetPinLevelImpl(hf_gpio_level_t level) noexcept override
Write pin level via the PCA9685 driver.
Definition Pca9685Handler.cpp:664
hf_gpio_level_t cached_level_
Cached output level.
Definition Pca9685Handler.h:489
Pca9685Handler * parent_handler_
Owning handler (not owned).
Definition Pca9685Handler.h:487
bool IsPinAvailable() const noexcept override
Check if this channel number is valid (0-15).
Definition Pca9685Handler.cpp:616
Pca9685GpioPin(hf_pin_num_t pin, Pca9685Handler *parent_handler, hf_gpio_active_state_t active_state=hf_gpio_active_state_t::HF_GPIO_ACTIVE_HIGH) noexcept
Construct a PCA9685 GPIO pin wrapper.
Definition Pca9685Handler.cpp:583
hf_gpio_pull_mode_t GetPullModeImpl() const noexcept override
Returns FLOATING (no pull resistors on PCA9685).
Definition Pca9685Handler.cpp:660
char description_[32]
Human-readable description.
Definition Pca9685Handler.h:488
const char * GetDescription() const noexcept override
Returns a description string like "PCA9685_CH_5".
Definition Pca9685Handler.cpp:620
hf_gpio_err_t GetDirectionImpl(hf_gpio_direction_t &direction) const noexcept override
Get direction (always OUTPUT).
Definition Pca9685Handler.cpp:635
bool Initialize() noexcept override
Initialize the GPIO pin (sets channel to full-off by default).
Definition Pca9685Handler.cpp:598
hf_gpio_err_t GetPinLevelImpl(hf_gpio_level_t &level) noexcept override
Read pin level (returns cached state since PCA9685 is output-only).
Definition Pca9685Handler.cpp:682
hf_gpio_err_t GetOutputModeImpl(hf_gpio_output_mode_t &mode) const noexcept override
Get output mode (tracked internally).
Definition Pca9685Handler.cpp:648
hf_gpio_err_t SetDirectionImpl(hf_gpio_direction_t direction) noexcept override
Set pin direction. Only OUTPUT is supported.
Definition Pca9685Handler.cpp:626
~Pca9685GpioPin() noexcept override=default
Default destructor.
hf_gpio_err_t SetPullModeImpl(hf_gpio_pull_mode_t mode) noexcept override
Not supported – returns GPIO_ERR_UNSUPPORTED_OPERATION.
Definition Pca9685Handler.cpp:654
hf_u8_t GetMaxPins() const noexcept override
Returns 16 (total channels on the PCA9685).
Definition Pca9685Handler.h:437
hf_gpio_err_t SetOutputModeImpl(hf_gpio_output_mode_t mode) noexcept override
Set output mode. Only push-pull is natively supported (global setting).
Definition Pca9685Handler.cpp:641
bool Deinitialize() noexcept override
Deinitialize (marks as uninitialized; channel state persists).
Definition Pca9685Handler.cpp:611
Unified, non-templated handler for a single PCA9685 PWM controller.
Definition Pca9685Handler.h:529
bool EnsureInitialized() noexcept
Ensure the handler is initialized (lazy initialization).
Definition Pca9685Handler.cpp:85
bool SetDuty(uint8_t channel, float duty) noexcept
Definition Pca9685Handler.cpp:166
bool initialized_
Initialization state.
Definition Pca9685Handler.h:747
bool SetAllPwm(uint16_t on_time, uint16_t off_time) noexcept
Definition Pca9685Handler.cpp:181
std::unique_ptr< HalI2cPca9685Comm > i2c_adapter_
I2C adapter (created in init).
Definition Pca9685Handler.h:745
std::shared_ptr< BasePwm > GetPwmAdapter() noexcept
Get or create the BasePwm adapter for all 16 channels.
Definition Pca9685Handler.cpp:243
std::shared_ptr< BaseGpio > CreateGpioPin(hf_pin_num_t channel, hf_gpio_active_state_t active_state=hf_gpio_active_state_t::HF_GPIO_ACTIVE_HIGH, bool allow_existing=true) noexcept
Create or retrieve a BaseGpio pin wrapper for a channel.
Definition Pca9685Handler.cpp:256
bool SetChannelFullOff(uint8_t channel) noexcept
Definition Pca9685Handler.cpp:194
bool SetOutputInvert(bool invert) noexcept
Definition Pca9685Handler.cpp:221
std::shared_ptr< Pca9685PwmAdapter > pwm_adapter_
PWM adapter (lazy).
Definition Pca9685Handler.h:753
std::array< std::shared_ptr< Pca9685GpioPin >, 16 > gpio_registry_
GPIO pin registry.
Definition Pca9685Handler.h:754
RtosMutex handler_mutex_
Thread safety for all operations.
Definition Pca9685Handler.h:748
std::shared_ptr< BaseGpio > GetGpioPin(hf_pin_num_t channel) noexcept
Get an existing GPIO pin wrapper by channel number.
Definition Pca9685Handler.cpp:280
Pca9685Handler(BaseI2c &i2c_device) noexcept
Construct a handler for a PCA9685 device.
Definition Pca9685Handler.cpp:76
void ClearErrorFlags(uint16_t mask=0xFFFF) noexcept
Clear driver error flags.
Definition Pca9685Handler.cpp:300
static constexpr uint8_t ChannelCount() noexcept
Total number of PWM channels.
Definition Pca9685Handler.h:608
bool validateChannel(uint8_t channel) const noexcept
Validate channel number (0-15).
Definition Pca9685Handler.h:724
hf_pwm_err_t deinitializeInternal() noexcept
Internal deinitialization.
Definition Pca9685Handler.cpp:138
Pca9685Driver * GetDriver() noexcept
Get the underlying PCA9685 driver for advanced register-level operations.
Definition Pca9685Handler.cpp:369
bool Sleep() noexcept
Definition Pca9685Handler.cpp:205
pca9685::PCA9685< HalI2cPca9685Comm > Pca9685Driver
Typed PCA9685 driver using our I2C adapter.
Definition Pca9685Handler.h:537
bool SetPwm(uint8_t channel, uint16_t on_time, uint16_t off_time) noexcept
Definition Pca9685Handler.cpp:173
bool SetOutputDriverMode(bool totem_pole) noexcept
Definition Pca9685Handler.cpp:227
bool IsPinCreated(hf_pin_num_t channel) const noexcept
Check if a GPIO pin wrapper has been created for a channel.
Definition Pca9685Handler.cpp:286
std::unique_ptr< Pca9685Driver > pca9685_driver_
Typed driver (created in init).
Definition Pca9685Handler.h:746
hf_pwm_err_t initializeInternal() noexcept
Internal initialization (called under mutex).
Definition Pca9685Handler.cpp:106
uint8_t GetI2cAddress() const noexcept
Get the I2C address of the underlying device.
Definition Pca9685Handler.cpp:237
bool ensureInitializedLocked() noexcept
Check init under already-held handler_mutex_.
Definition Pca9685Handler.cpp:101
bool Wake() noexcept
Definition Pca9685Handler.cpp:211
bool EnsureDeinitialized() noexcept
Deinitialize the handler and release resources.
Definition Pca9685Handler.cpp:93
uint16_t GetErrorFlags() const noexcept
Get the driver's error flags.
Definition Pca9685Handler.cpp:296
~Pca9685Handler() noexcept=default
Destructor. Releases driver, adapter, and all wrappers.
bool SetFrequency(float freq_hz) noexcept
Definition Pca9685Handler.cpp:160
bool SetChannelFullOn(uint8_t channel) noexcept
Definition Pca9685Handler.cpp:187
void DumpDiagnostics() const noexcept
Dump comprehensive diagnostics to the system log.
Definition Pca9685Handler.cpp:310
BaseI2c & i2c_device_
I2C device reference (not owned).
Definition Pca9685Handler.h:744
bool IsInitialized() const noexcept
Check if the handler has been initialized.
Definition Pca9685Handler.h:597
BasePwm adapter for all 16 PCA9685 PWM channels.
Definition Pca9685Handler.h:214
hf_pwm_err_t SetComplementaryOutput(hf_channel_id_t primary_channel, hf_channel_id_t complementary_channel, hf_u32_t deadtime_ns) noexcept override
Not supported by PCA9685.
Definition Pca9685Handler.cpp:562
std::array< uint16_t, kMaxChannels > on_time_cache_
Cached on-time values (phase offset).
Definition Pca9685Handler.h:367
hf_pwm_err_t EnableChannel(hf_channel_id_t channel_id) noexcept override
Enable a PWM channel (restore its duty cycle from cache).
Definition Pca9685Handler.cpp:410
hf_pwm_err_t UpdateAll() noexcept override
No-op (PCA9685 updates immediately on register write).
Definition Pca9685Handler.cpp:557
static constexpr uint32_t kMinFrequencyHz
Minimum PWM frequency in Hz.
Definition Pca9685Handler.h:226
hf_pwm_err_t SetDutyCycle(hf_channel_id_t channel_id, float duty_cycle) noexcept override
Set duty cycle for a channel (0.0-1.0).
Definition Pca9685Handler.cpp:449
bool validateChannel(hf_channel_id_t channel_id) const noexcept
Validate channel ID is in range 0-15.
Definition Pca9685Handler.h:374
hf_pwm_err_t Initialize() noexcept override
Initialize the PWM adapter (ensures parent handler is initialized).
Definition Pca9685Handler.cpp:391
static constexpr uint16_t kMaxRawValue
Maximum raw PWM value (2^12 - 1 = 4095).
Definition Pca9685Handler.h:223
bool IsChannelEnabled(hf_channel_id_t channel_id) const noexcept override
Check if a channel is enabled.
Definition Pca9685Handler.cpp:444
std::array< float, kMaxChannels > duty_cache_
Cached duty cycles (0.0-1.0).
Definition Pca9685Handler.h:366
hf_pwm_err_t SetPhaseShift(hf_channel_id_t channel_id, float phase_shift_degrees) noexcept override
Set phase shift for a channel (via PCA9685 on-time offset).
Definition Pca9685Handler.cpp:514
Pca9685Handler * parent_handler_
Owning handler (not owned).
Definition Pca9685Handler.h:362
hf_pwm_err_t StopAll() noexcept override
Put the PCA9685 into sleep mode (stop all outputs).
Definition Pca9685Handler.cpp:550
hf_pwm_err_t SetFrequency(hf_channel_id_t channel_id, hf_frequency_hz_t frequency_hz) noexcept override
Set PWM frequency (global – affects ALL channels).
Definition Pca9685Handler.cpp:498
static constexpr uint32_t kMaxFrequencyHz
Maximum PWM frequency in Hz.
Definition Pca9685Handler.h:229
hf_pwm_err_t StartAll() noexcept override
Wake the PCA9685 from sleep (start all channels).
Definition Pca9685Handler.cpp:543
hf_frequency_hz_t GetFrequency(hf_channel_id_t channel_id) const noexcept override
Get the current PWM frequency (global).
Definition Pca9685Handler.cpp:574
~Pca9685PwmAdapter() noexcept override=default
Default destructor.
static constexpr uint8_t kResolutionBits
PWM resolution in bits.
Definition Pca9685Handler.h:220
hf_pwm_err_t Deinitialize() noexcept override
Deinitialize (marks adapter as uninitialized).
Definition Pca9685Handler.cpp:402
float GetDutyCycle(hf_channel_id_t channel_id) const noexcept override
Get the cached duty cycle for a channel.
Definition Pca9685Handler.cpp:569
hf_pwm_err_t DisableChannel(hf_channel_id_t channel_id) noexcept override
Disable a PWM channel (set to full-off).
Definition Pca9685Handler.cpp:431
std::array< bool, kMaxChannels > channel_enabled_
Channel enable state.
Definition Pca9685Handler.h:368
hf_frequency_hz_t current_frequency_hz_
Current global frequency.
Definition Pca9685Handler.h:371
hf_pwm_err_t SetDutyCycleRaw(hf_channel_id_t channel_id, hf_u32_t raw_value) noexcept override
Set raw PWM tick value for a channel.
Definition Pca9685Handler.cpp:480
static constexpr uint8_t kMaxChannels
Number of PWM channels on the PCA9685.
Definition Pca9685Handler.h:217
Pca9685PwmAdapter(Pca9685Handler *parent_handler) noexcept
Construct the PWM adapter.
Definition Pca9685Handler.cpp:384