HardFOC Core
API reference
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"
99
100// Forward declarations
101class Pca9685Handler;
102
108
131class HalI2cPca9685Comm : public pca9685::I2cInterface<HalI2cPca9685Comm> {
132public:
138 explicit HalI2cPca9685Comm(BaseI2c& i2c_device) noexcept;
139
143
155 bool Write(uint8_t addr, uint8_t reg, const uint8_t* data, size_t len) noexcept;
156
168 bool Read(uint8_t addr, uint8_t reg, uint8_t* data, size_t len) noexcept;
169
174 bool EnsureInitialized() noexcept;
175
183 void DelayUs(uint32_t us) noexcept;
184
186
187private:
188 BaseI2c& i2c_device_;
189 mutable RtosMutex i2c_mutex_;
190};
191
193
199
224class Pca9685PwmAdapter : public BasePwm {
225public:
227 static constexpr uint8_t kMaxChannels = 16;
228
230 static constexpr uint8_t kResolutionBits = 12;
231
233 static constexpr uint16_t kMaxRawValue = 4095;
234
236 static constexpr uint32_t kMinFrequencyHz = 24;
237
239 static constexpr uint32_t kMaxFrequencyHz = 1526;
240
245 explicit Pca9685PwmAdapter(Pca9685Handler* parent_handler) noexcept;
246
248 ~Pca9685PwmAdapter() noexcept override = default;
249
252
254 hf_pwm_err_t Initialize() noexcept override;
255
257 hf_pwm_err_t Deinitialize() noexcept override;
258
264 hf_pwm_err_t EnableChannel(hf_channel_id_t channel_id) noexcept override;
265
271 hf_pwm_err_t DisableChannel(hf_channel_id_t channel_id) noexcept override;
272
278 bool IsChannelEnabled(hf_channel_id_t channel_id) const noexcept override;
279
286 hf_pwm_err_t SetDutyCycle(hf_channel_id_t channel_id,
287 float duty_cycle) noexcept override;
288
295 hf_pwm_err_t SetDutyCycleRaw(hf_channel_id_t channel_id,
296 hf_u32_t raw_value) noexcept override;
297
309 hf_pwm_err_t SetFrequency(hf_channel_id_t channel_id,
310 hf_frequency_hz_t frequency_hz) noexcept override;
311
323 hf_pwm_err_t SetPhaseShift(hf_channel_id_t channel_id,
324 float phase_shift_degrees) noexcept override;
325
330 hf_pwm_err_t StartAll() noexcept override;
331
336 hf_pwm_err_t StopAll() noexcept override;
337
342 hf_pwm_err_t UpdateAll() noexcept override;
343
348 hf_pwm_err_t SetComplementaryOutput(hf_channel_id_t primary_channel,
349 hf_channel_id_t complementary_channel,
350 hf_u32_t deadtime_ns) noexcept override;
351
357 float GetDutyCycle(hf_channel_id_t channel_id) const noexcept override;
358
364 hf_frequency_hz_t GetFrequency(hf_channel_id_t channel_id) const noexcept override;
365
367
369 friend class Pca9685Handler;
370
371private:
373
376 std::array<float, kMaxChannels> duty_cache_;
377 std::array<uint16_t, kMaxChannels> on_time_cache_;
378 std::array<bool, kMaxChannels> channel_enabled_;
380
381 hf_frequency_hz_t current_frequency_hz_ = 200;
382
384 bool validateChannel(hf_channel_id_t channel_id) const noexcept {
385 return channel_id < kMaxChannels;
386 }
387};
388
390
396
418class Pca9685GpioPin : public BaseGpio {
419public:
426 Pca9685GpioPin(hf_pin_num_t pin,
427 Pca9685Handler* parent_handler,
428 hf_gpio_active_state_t active_state =
429 hf_gpio_active_state_t::HF_GPIO_ACTIVE_HIGH) noexcept;
430
432 ~Pca9685GpioPin() noexcept override = default;
433
436
438 bool Initialize() noexcept override;
439
441 bool Deinitialize() noexcept override;
442
444 bool IsPinAvailable() const noexcept override;
445
447 hf_u8_t GetMaxPins() const noexcept override { return 16; }
448
450 const char* GetDescription() const noexcept override;
451
453
454protected:
457
462 hf_gpio_err_t SetDirectionImpl(hf_gpio_direction_t direction) noexcept override;
463
465 hf_gpio_err_t GetDirectionImpl(hf_gpio_direction_t& direction) const noexcept override;
466
468 hf_gpio_err_t SetOutputModeImpl(hf_gpio_output_mode_t mode) noexcept override;
469
471 hf_gpio_err_t GetOutputModeImpl(hf_gpio_output_mode_t& mode) const noexcept override;
472
474 hf_gpio_err_t SetPullModeImpl(hf_gpio_pull_mode_t mode) noexcept override;
475
477 hf_gpio_pull_mode_t GetPullModeImpl() const noexcept override;
478
484 hf_gpio_err_t SetPinLevelImpl(hf_gpio_level_t level) noexcept override;
485
489 hf_gpio_err_t GetPinLevelImpl(hf_gpio_level_t& level) noexcept override;
490
492
493 friend class Pca9685Handler;
494
495private:
496 hf_pin_num_t pin_;
498 char description_[32] = {};
499 hf_gpio_level_t cached_level_ =
500 hf_gpio_level_t::HF_GPIO_LEVEL_LOW;
501};
502
504
510
540public:
541 //==========================================================================
544 //==========================================================================
545
547 using Pca9685Driver = pca9685::PCA9685<HalI2cPca9685Comm>;
548
550
551 //==========================================================================
554 //==========================================================================
555
565 explicit Pca9685Handler(BaseI2c& i2c_device) noexcept;
566
568 ~Pca9685Handler() noexcept = default;
569
573 Pca9685Handler& operator=(const Pca9685Handler&) = delete;
574
578 Pca9685Handler& operator=(Pca9685Handler&&) = delete;
579
581
582 //==========================================================================
585 //==========================================================================
586
595 bool EnsureInitialized() noexcept;
596
601 bool EnsureDeinitialized() noexcept;
602
607 bool IsInitialized() const noexcept { return initialized_; }
608
610
611 //==========================================================================
615 //==========================================================================
616
618 static constexpr uint8_t ChannelCount() noexcept { return 16; }
619
624 uint8_t GetI2cAddress() const noexcept;
625
634 std::shared_ptr<BasePwm> GetPwmAdapter() noexcept;
635
648 std::shared_ptr<BaseGpio> CreateGpioPin(
649 hf_pin_num_t channel,
650 hf_gpio_active_state_t active_state =
651 hf_gpio_active_state_t::HF_GPIO_ACTIVE_HIGH,
652 bool allow_existing = true) noexcept;
653
659 std::shared_ptr<BaseGpio> GetGpioPin(hf_pin_num_t channel) noexcept;
660
666 bool IsPinCreated(hf_pin_num_t channel) const noexcept;
667
669
670 //==========================================================================
673 //==========================================================================
674
679 uint16_t GetErrorFlags() const noexcept;
680
685 void ClearErrorFlags(uint16_t mask = 0xFFFF) noexcept;
686
688
689 //==========================================================================
692 //==========================================================================
693
697 void DumpDiagnostics() const noexcept;
698
700
701 //==========================================================================
704 //==========================================================================
705
710 [[nodiscard]] Pca9685Driver* GetDriver() noexcept;
711 [[nodiscard]] const Pca9685Driver* GetDriver() const noexcept;
712
714
716 friend class Pca9685PwmAdapter;
717 friend class Pca9685GpioPin;
718
719private:
720 //==========================================================================
721 // Private Methods
722 //==========================================================================
723
725 bool ensureInitializedLocked() noexcept;
726
728 hf_pwm_err_t initializeInternal() noexcept;
729
731 hf_pwm_err_t deinitializeInternal() noexcept;
732
734 bool validateChannel(uint8_t channel) const noexcept { return channel < 16; }
735
736 // ---- PWM/power/output ops (used internally by Pca9685PwmAdapter & Pca9685GpioPin) ----
737 bool SetFrequency(float freq_hz) noexcept;
738 bool SetDuty(uint8_t channel, float duty) noexcept;
739 bool SetPwm(uint8_t channel, uint16_t on_time, uint16_t off_time) noexcept;
740 bool SetAllPwm(uint16_t on_time, uint16_t off_time) noexcept;
741 bool SetChannelFullOn(uint8_t channel) noexcept;
742 bool SetChannelFullOff(uint8_t channel) noexcept;
743 bool Sleep() noexcept;
744 bool Wake() noexcept;
745 bool SetOutputInvert(bool invert) noexcept;
746 bool SetOutputDriverMode(bool totem_pole) noexcept;
747
748 //==========================================================================
749 // Private Members
750 //==========================================================================
751
754 BaseI2c& i2c_device_;
757 bool initialized_ = false;
758 mutable RtosMutex handler_mutex_;
760
764 std::array<std::shared_ptr<Pca9685GpioPin>, 16> gpio_registry_;
766};
767
769
770#endif // COMPONENT_HANDLER_PCA9685_HANDLER_H_
Shared utility functions for handler CRTP communication adapters.
Concrete I2C communication adapter for PCA9685 using BaseI2c.
Definition Pca9685Handler.h:131
RtosMutex i2c_mutex_
Thread safety for I2C operations.
Definition Pca9685Handler.h:189
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:188
bool EnsureInitialized() noexcept
Ensure the I2C bus is initialized and ready.
Definition Pca9685Handler.cpp:68
void DelayUs(uint32_t us) noexcept
Optional driver hook: wait at least us microseconds.
Definition Pca9685Handler.cpp:72
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:418
hf_pin_num_t pin_
Channel number (0-15).
Definition Pca9685Handler.h:496
hf_gpio_err_t SetPinLevelImpl(hf_gpio_level_t level) noexcept override
Write pin level via the PCA9685 driver.
Definition Pca9685Handler.cpp:670
hf_gpio_level_t cached_level_
Cached output level.
Definition Pca9685Handler.h:499
Pca9685Handler * parent_handler_
Owning handler (not owned).
Definition Pca9685Handler.h:497
bool IsPinAvailable() const noexcept override
Check if this channel number is valid (0-15).
Definition Pca9685Handler.cpp:622
hf_gpio_pull_mode_t GetPullModeImpl() const noexcept override
Returns FLOATING (no pull resistors on PCA9685).
Definition Pca9685Handler.cpp:666
char description_[32]
Human-readable description.
Definition Pca9685Handler.h:498
const char * GetDescription() const noexcept override
Returns a description string like "PCA9685_CH_5".
Definition Pca9685Handler.cpp:626
hf_gpio_err_t GetDirectionImpl(hf_gpio_direction_t &direction) const noexcept override
Get direction (always OUTPUT).
Definition Pca9685Handler.cpp:641
bool Initialize() noexcept override
Initialize the GPIO pin (sets channel to full-off by default).
Definition Pca9685Handler.cpp:604
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:688
hf_gpio_err_t GetOutputModeImpl(hf_gpio_output_mode_t &mode) const noexcept override
Get output mode (tracked internally).
Definition Pca9685Handler.cpp:654
hf_gpio_err_t SetDirectionImpl(hf_gpio_direction_t direction) noexcept override
Set pin direction. Only OUTPUT is supported.
Definition Pca9685Handler.cpp:632
~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:660
hf_u8_t GetMaxPins() const noexcept override
Returns 16 (total channels on the PCA9685).
Definition Pca9685Handler.h:447
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:647
bool Deinitialize() noexcept override
Deinitialize (marks as uninitialized; channel state persists).
Definition Pca9685Handler.cpp:617
Unified, non-templated handler for a single PCA9685 PWM controller.
Definition Pca9685Handler.h:539
bool EnsureInitialized() noexcept
Ensure the handler is initialized (lazy initialization).
Definition Pca9685Handler.cpp:89
bool SetDuty(uint8_t channel, float duty) noexcept
Definition Pca9685Handler.cpp:170
bool initialized_
Initialization state.
Definition Pca9685Handler.h:757
bool SetAllPwm(uint16_t on_time, uint16_t off_time) noexcept
Definition Pca9685Handler.cpp:185
std::unique_ptr< HalI2cPca9685Comm > i2c_adapter_
I2C adapter (created in init).
Definition Pca9685Handler.h:755
std::shared_ptr< BasePwm > GetPwmAdapter() noexcept
Get or create the BasePwm adapter for all 16 channels.
Definition Pca9685Handler.cpp:247
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:260
bool SetChannelFullOff(uint8_t channel) noexcept
Definition Pca9685Handler.cpp:198
bool SetOutputInvert(bool invert) noexcept
Definition Pca9685Handler.cpp:225
std::shared_ptr< Pca9685PwmAdapter > pwm_adapter_
PWM adapter (lazy).
Definition Pca9685Handler.h:763
std::array< std::shared_ptr< Pca9685GpioPin >, 16 > gpio_registry_
GPIO pin registry.
Definition Pca9685Handler.h:764
RtosMutex handler_mutex_
Thread safety for all operations.
Definition Pca9685Handler.h:758
std::shared_ptr< BaseGpio > GetGpioPin(hf_pin_num_t channel) noexcept
Get an existing GPIO pin wrapper by channel number.
Definition Pca9685Handler.cpp:284
void ClearErrorFlags(uint16_t mask=0xFFFF) noexcept
Clear driver error flags.
Definition Pca9685Handler.cpp:304
static constexpr uint8_t ChannelCount() noexcept
Total number of PWM channels.
Definition Pca9685Handler.h:618
bool validateChannel(uint8_t channel) const noexcept
Validate channel number (0-15).
Definition Pca9685Handler.h:734
hf_pwm_err_t deinitializeInternal() noexcept
Internal deinitialization.
Definition Pca9685Handler.cpp:142
Pca9685Driver * GetDriver() noexcept
Get the underlying PCA9685 driver for advanced register-level operations.
Definition Pca9685Handler.cpp:373
bool Sleep() noexcept
Definition Pca9685Handler.cpp:209
pca9685::PCA9685< HalI2cPca9685Comm > Pca9685Driver
Typed PCA9685 driver using our I2C adapter.
Definition Pca9685Handler.h:547
bool SetPwm(uint8_t channel, uint16_t on_time, uint16_t off_time) noexcept
Definition Pca9685Handler.cpp:177
bool SetOutputDriverMode(bool totem_pole) noexcept
Definition Pca9685Handler.cpp:231
bool IsPinCreated(hf_pin_num_t channel) const noexcept
Check if a GPIO pin wrapper has been created for a channel.
Definition Pca9685Handler.cpp:290
std::unique_ptr< Pca9685Driver > pca9685_driver_
Typed driver (created in init).
Definition Pca9685Handler.h:756
hf_pwm_err_t initializeInternal() noexcept
Internal initialization (called under mutex).
Definition Pca9685Handler.cpp:110
uint8_t GetI2cAddress() const noexcept
Get the I2C address of the underlying device.
Definition Pca9685Handler.cpp:241
bool ensureInitializedLocked() noexcept
Check init under already-held handler_mutex_.
Definition Pca9685Handler.cpp:105
bool Wake() noexcept
Definition Pca9685Handler.cpp:215
bool EnsureDeinitialized() noexcept
Deinitialize the handler and release resources.
Definition Pca9685Handler.cpp:97
uint16_t GetErrorFlags() const noexcept
Get the driver's error flags.
Definition Pca9685Handler.cpp:300
~Pca9685Handler() noexcept=default
Destructor. Releases driver, adapter, and all wrappers.
bool SetFrequency(float freq_hz) noexcept
Definition Pca9685Handler.cpp:164
bool SetChannelFullOn(uint8_t channel) noexcept
Definition Pca9685Handler.cpp:191
void DumpDiagnostics() const noexcept
Dump comprehensive diagnostics to the system log.
Definition Pca9685Handler.cpp:314
BaseI2c & i2c_device_
I2C device reference (not owned).
Definition Pca9685Handler.h:754
bool IsInitialized() const noexcept
Check if the handler has been initialized.
Definition Pca9685Handler.h:607
BasePwm adapter for all 16 PCA9685 PWM channels.
Definition Pca9685Handler.h:224
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:568
std::array< uint16_t, kMaxChannels > on_time_cache_
Cached on-time values (phase offset).
Definition Pca9685Handler.h:377
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:414
hf_pwm_err_t UpdateAll() noexcept override
No-op (PCA9685 updates immediately on register write).
Definition Pca9685Handler.cpp:563
static constexpr uint32_t kMinFrequencyHz
Minimum PWM frequency in Hz.
Definition Pca9685Handler.h:236
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:453
bool validateChannel(hf_channel_id_t channel_id) const noexcept
Validate channel ID is in range 0-15.
Definition Pca9685Handler.h:384
hf_pwm_err_t Initialize() noexcept override
Initialize the PWM adapter (ensures parent handler is initialized).
Definition Pca9685Handler.cpp:395
static constexpr uint16_t kMaxRawValue
Maximum raw PWM value (2^12 - 1 = 4095).
Definition Pca9685Handler.h:233
bool IsChannelEnabled(hf_channel_id_t channel_id) const noexcept override
Check if a channel is enabled.
Definition Pca9685Handler.cpp:448
std::array< float, kMaxChannels > duty_cache_
Cached duty cycles (0.0-1.0).
Definition Pca9685Handler.h:376
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:520
Pca9685Handler * parent_handler_
Owning handler (not owned).
Definition Pca9685Handler.h:372
hf_pwm_err_t StopAll() noexcept override
Put the PCA9685 into sleep mode (stop all outputs).
Definition Pca9685Handler.cpp:556
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:504
static constexpr uint32_t kMaxFrequencyHz
Maximum PWM frequency in Hz.
Definition Pca9685Handler.h:239
hf_pwm_err_t StartAll() noexcept override
Wake the PCA9685 from sleep (start all channels).
Definition Pca9685Handler.cpp:549
hf_frequency_hz_t GetFrequency(hf_channel_id_t channel_id) const noexcept override
Get the current PWM frequency (global).
Definition Pca9685Handler.cpp:580
~Pca9685PwmAdapter() noexcept override=default
Default destructor.
static constexpr uint8_t kResolutionBits
PWM resolution in bits.
Definition Pca9685Handler.h:230
hf_pwm_err_t Deinitialize() noexcept override
Deinitialize (marks adapter as uninitialized).
Definition Pca9685Handler.cpp:406
float GetDutyCycle(hf_channel_id_t channel_id) const noexcept override
Get the cached duty cycle for a channel.
Definition Pca9685Handler.cpp:575
hf_pwm_err_t DisableChannel(hf_channel_id_t channel_id) noexcept override
Disable a PWM channel (set to full-off).
Definition Pca9685Handler.cpp:435
std::array< bool, kMaxChannels > channel_enabled_
Channel enable state.
Definition Pca9685Handler.h:378
hf_frequency_hz_t current_frequency_hz_
Current global frequency.
Definition Pca9685Handler.h:381
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:486
static constexpr uint8_t kMaxChannels
Number of PWM channels on the PCA9685.
Definition Pca9685Handler.h:227