|
HardFOC Core
API reference
|
Unified, non-templated handler for a single PCA9555 / PCAL9555A device. More...
#include <Pcal95555Handler.h>
Public Types | |
Type Aliases | |
| using | Pcal95555Driver = pcal95555::PCAL95555< HalI2cPcal95555Comm > |
| Typed PCAL95555 driver using our I2C adapter. | |
Public Member Functions | |
Construction and Destruction | |
| Pcal95555Handler (BaseI2c &i2c_device, BaseGpio *interrupt_pin=nullptr) noexcept | |
| Construct a handler for a PCAL95555 device. | |
| ~Pcal95555Handler () noexcept=default | |
| Destructor. Releases driver, adapter, and all pin wrappers. | |
| Pcal95555Handler (const Pcal95555Handler &)=delete | |
| Non-copyable. | |
| Pcal95555Handler & | operator= (const Pcal95555Handler &)=delete |
| Non-copyable. | |
| Pcal95555Handler (Pcal95555Handler &&)=delete | |
| Non-movable. | |
| Pcal95555Handler & | operator= (Pcal95555Handler &&)=delete |
| Non-movable. | |
Initialization and Lifecycle | |
| bool | EnsureInitialized () noexcept |
| Ensure the handler is initialized (lazy initialization). | |
| bool | EnsureDeinitialized () noexcept |
| Deinitialize the handler and release resources. | |
| bool | IsInitialized () const noexcept |
| Check if the handler has been initialized. | |
Basic GPIO Operations | |
Per-pin operations using pin numbers (0-15). | |
| hf_gpio_err_t | SetDirection (uint8_t pin, hf_gpio_direction_t direction) noexcept |
| Set the direction of a single pin. | |
| hf_gpio_err_t | SetOutput (uint8_t pin, bool active) noexcept |
| Write a logical level to an output pin. | |
| hf_gpio_err_t | ReadInput (uint8_t pin, bool &active) noexcept |
| Read the physical level of a pin. | |
| hf_gpio_err_t | Toggle (uint8_t pin) noexcept |
| Toggle the output state of a pin. | |
| hf_gpio_err_t | SetPullMode (uint8_t pin, hf_gpio_pull_mode_t pull_mode) noexcept |
| Set the pull resistor mode for a single pin. | |
| hf_gpio_err_t | GetPullMode (uint8_t pin, hf_gpio_pull_mode_t &pull_mode) noexcept |
| Get the pull resistor mode for a single pin (tracked internally). | |
Batch GPIO Operations | |
Operations on multiple pins using 16-bit masks. | |
| hf_gpio_err_t | SetDirections (uint16_t pin_mask, hf_gpio_direction_t direction) noexcept |
| Set direction for multiple pins at once. | |
| hf_gpio_err_t | SetOutputs (uint16_t pin_mask, bool active) noexcept |
| Write output level for multiple pins at once. | |
| hf_gpio_err_t | SetOutputsVerified (uint16_t pin_mask, bool active) noexcept |
| Write output level for multiple pins in one transaction, then read the latch back and retry (up to 3×) until every selected bit matches. | |
| hf_gpio_err_t | SetPullModes (uint16_t pin_mask, hf_gpio_pull_mode_t pull_mode) noexcept |
| Set pull mode for multiple pins at once. | |
PCAL9555A Advanced Features (Agile I/O) | |
These features require a PCAL9555A chip. They return false on PCA9555. | |
| bool | HasAgileIO () const noexcept |
| Check if the detected chip supports Agile I/O features. | |
| pcal95555::ChipVariant | GetChipVariant () const noexcept |
| Get the detected chip variant. | |
| hf_gpio_err_t | SetPolarityInversion (hf_pin_num_t pin, bool invert) noexcept |
| Set input polarity inversion for a pin. | |
| hf_gpio_err_t | SetMultiplePolarityInversion (uint16_t pin_mask, bool invert) noexcept |
| Batch-set input polarity inversion for a pin mask. | |
| hf_gpio_err_t | SetInterruptMask (hf_pin_num_t pin, bool mask) noexcept |
| Set the per-pin interrupt mask. | |
| hf_gpio_err_t | GetInterruptStatus (hf_pin_num_t pin, bool &status) noexcept |
| Get interrupt status for a single pin. | |
| hf_gpio_err_t | SetDriveStrength (hf_pin_num_t pin, pcal95555::DriveStrength level) noexcept |
| Set output drive strength for a pin. | |
| hf_gpio_err_t | EnableInputLatch (hf_pin_num_t pin, bool enable) noexcept |
| Enable or disable input latch for a pin. | |
| hf_gpio_err_t | SetOutputMode (bool port0_open_drain, bool port1_open_drain) noexcept |
| Configure per-port output mode (push-pull or open-drain). | |
| hf_gpio_err_t | ResetToDefault () noexcept |
| Reset all registers to power-on default state. | |
Error Management | |
| uint16_t | GetErrorFlags () const noexcept |
| Get the driver's error flags. | |
| void | ClearErrorFlags (uint16_t mask=0xFFFF) noexcept |
| Clear driver error flags. | |
Diagnostics | |
| void | DumpDiagnostics () const noexcept |
| Dump comprehensive diagnostics to the system log. | |
Private Member Functions | |
| bool | EnsureInitializedLocked () noexcept |
| Check init state under already-held handler_mutex_. | |
| hf_gpio_err_t | Initialize () noexcept |
| Internal initialization (called by EnsureInitialized under mutex). | |
| hf_gpio_err_t | Deinitialize () noexcept |
| Internal deinitialization. | |
| bool | ValidatePin (uint8_t pin) const noexcept |
| Validate pin number is in range 0-15. | |
| hf_gpio_err_t | RegisterPinInterrupt (hf_pin_num_t pin, hf_gpio_interrupt_trigger_t trigger, InterruptCallback callback, void *user_data) noexcept |
| Register a per-pin interrupt callback (called by Pcal95555GpioPin). | |
| hf_gpio_err_t | UnregisterPinInterrupt (hf_pin_num_t pin) noexcept |
| Unregister a per-pin interrupt callback. | |
| hf_gpio_err_t | ConfigureHardwareInterrupt () noexcept |
| Configure the hardware interrupt pin (falling edge, active-low). | |
| void | ProcessInterrupts () noexcept |
| Process pending interrupts by reading status and dispatching callbacks. | |
Direct Driver Access | |
| Pcal95555Driver * | GetDriver () noexcept |
| Get the underlying PCAL95555 driver for advanced register-level operations. | |
| const Pcal95555Driver * | GetDriver () const noexcept |
Static Private Member Functions | |
| static void | HardwareInterruptCallback (BaseGpio *gpio, hf_gpio_interrupt_trigger_t trigger, void *user_data) noexcept |
| Static ISR callback for the hardware interrupt pin. | |
Private Attributes | |
Core Components | |
| BaseI2c & | i2c_device_ |
| I2C device reference (not owned). | |
| std::unique_ptr< HalI2cPcal95555Comm > | i2c_adapter_ |
| I2C adapter (created in Initialize). | |
| std::unique_ptr< Pcal95555Driver > | pcal95555_driver_ |
| Typed driver (created in Initialize). | |
| bool | initialized_ = false |
| Initialization state. | |
| RtosMutex | handler_mutex_ |
| Thread safety for handler operations. | |
Pin Registry | |
| std::array< Pcal95555GpioPin *, 16 > | pin_registry_ {} |
| Non-owning registry slots. | |
| std::array< std::unique_ptr< Pcal95555GpioPin >, 16 > | owned_pins_ {} |
| Heap pins from CreateGpioPin. | |
Internal Pull Mode Tracking | |
Tracks pull mode per-pin since the driver doesn't provide readback. | |
| std::array< hf_gpio_pull_mode_t, 16 > | pull_mode_cache_ |
Edge Detection State | |
Tracks previous input state for rising/falling edge filtering. | |
| uint16_t | prev_input_state_ = 0 |
| Last-read pin input levels (bitmask). | |
Port shadows (absolute write path) | |
Avoid read-modify-write when register readback is untrustworthy. | |
| uint16_t | output_shadow_ {0xFFFFU} |
| PCA POR default OUTPUT. | |
| uint16_t | config_shadow_ {0xFFFFU} |
| PCA POR default CONFIG (all input) | |
| uint16_t | polarity_shadow_ {0} |
| POLARITY_INV. | |
| bool | port_shadow_valid_ {false} |
Friends | |
| class | Pcal95555GpioPin |
| Allow Pcal95555GpioPin to access private interrupt methods. | |
Interrupt Management | |
| BaseGpio * | interrupt_pin_ |
| Hardware INT pin (optional, not owned). | |
| bool | interrupt_configured_ |
| Whether hardware interrupt is active. | |
| std::atomic< bool > | interrupt_pending_ {false} |
| Deferred interrupt flag (set in ISR, cleared in task context). | |
| bool | HasInterruptSupport () const noexcept |
| Check if hardware interrupt support is available. | |
| bool | IsInterruptConfigured () const noexcept |
| Check if hardware interrupt is configured and enabled. | |
| bool | DrainPendingInterrupts () noexcept |
| Drain any pending interrupt that was deferred from ISR context. | |
| hf_gpio_err_t | GetAllInterruptMasks (uint16_t &mask) noexcept |
| Get the interrupt mask for all 16 pins. | |
| hf_gpio_err_t | GetAllInterruptStatus (uint16_t &status) noexcept |
| Get the interrupt status for all 16 pins. | |
Pin Factory | |
Create and manage BaseGpio-compatible pin wrapper instances. | |
| uint8_t | GetI2cAddress () const noexcept |
| Get the I2C address of the underlying device. | |
| bool | AttachStaticPin (Pcal95555GpioPin &pin) noexcept |
| Register a caller-owned pin wrapper (no heap allocation). | |
| std::shared_ptr< BaseGpio > | CreateGpioPin (hf_pin_num_t pin, hf_gpio_direction_t direction=hf_gpio_direction_t::HF_GPIO_DIRECTION_INPUT, hf_gpio_active_state_t active_state=hf_gpio_active_state_t::HF_GPIO_ACTIVE_HIGH, hf_gpio_output_mode_t output_mode=hf_gpio_output_mode_t::HF_GPIO_OUTPUT_MODE_PUSH_PULL, hf_gpio_pull_mode_t pull_mode=hf_gpio_pull_mode_t::HF_GPIO_PULL_MODE_FLOATING, bool allow_existing=true, bool configure_hardware=true) noexcept |
| Create or retrieve an existing BaseGpio pin wrapper (heap). | |
| std::shared_ptr< BaseGpio > | GetGpioPin (hf_pin_num_t pin) noexcept |
| Get an existing GPIO pin wrapper by number. | |
| Pcal95555GpioPin * | GetGpioPinRaw (hf_pin_num_t pin) noexcept |
| Raw pointer to a registered pin (no shared_ptr control block). | |
| hf_gpio_err_t | ReadAllInputLevels (uint16_t &levels) noexcept |
| Read both INPUT_PORT registers in one dual-port transaction. | |
| hf_gpio_err_t | ProgramPortsAbsolute (uint16_t config, uint16_t output, uint16_t out_check_mask) noexcept |
| Absolute program POL=0, OUTPUT latch, and CONFIG (no RMW). | |
| hf_gpio_err_t | ReadConfigAndOutputPorts (uint16_t &config, uint16_t &output) noexcept |
| Read CONFIG (1=input) and OUTPUT latch port pairs (PCA pin bits). | |
| hf_gpio_err_t | ReadOutputLatchFromWire (uint16_t &output) noexcept |
| Read OUTPUT_PORT_0/1 from the chip (never the CM4 shadow). | |
| hf_gpio_err_t | ReadStandardRegisterBank (uint16_t &input, uint16_t &output, uint16_t &polarity, uint16_t &config) noexcept |
| Read the full standard PCA9555 bank (0x00..0x07) as four 16-bit ports. | |
| hf_gpio_err_t | VerifyOutputPinEffect (uint8_t pin, uint16_t &latch_high, uint16_t &input_high, uint16_t &latch_low, uint16_t &input_low) noexcept |
| Drive one pin and verify OUTPUT latch + INPUT pad follow. | |
| bool | IsPinCreated (hf_pin_num_t pin) const noexcept |
| Check if a pin wrapper has been created. | |
| uint16_t | GetCreatedPinMask () const noexcept |
| Get a bitmask of all created pin numbers. | |
| static constexpr uint8_t | PinCount () noexcept |
| Total number of GPIO pins on the expander. | |
Unified, non-templated handler for a single PCA9555 / PCAL9555A device.
Pcal95555Handler is the primary interface that application and manager code uses to interact with a PCAL95555 GPIO expander. It hides the template complexity of pcal95555::PCAL95555<I2cType> behind a clean public API.
| using Pcal95555Handler::Pcal95555Driver = pcal95555::PCAL95555<HalI2cPcal95555Comm> |
Typed PCAL95555 driver using our I2C adapter.
|
explicitnoexcept |
Construct a handler for a PCAL95555 device.
The I2C adapter and driver are not created until EnsureInitialized() or the first operation that requires them.
| i2c_device | Reference to a BaseI2c device with address pre-configured. Must outlive the handler. |
| interrupt_pin | Optional BaseGpio pin connected to the expander's INT output. Pass nullptr for polling mode (no hardware interrupts). |
|
defaultnoexcept |
Destructor. Releases driver, adapter, and all pin wrappers.
|
delete |
Non-copyable.
|
delete |
Non-movable.
|
noexcept |
Register a caller-owned pin wrapper (no heap allocation).
Prefer for static/.bss pin maps: place Pcal95555GpioPin in fixed storage, batch-program directions, then attach with configure_hardware=false in the pin ctor.
|
noexcept |
Clear driver error flags.
| mask | Bitmask of flags to clear (default: all). |
|
privatenoexcept |
Configure the hardware interrupt pin (falling edge, active-low).
|
noexcept |
Create or retrieve an existing BaseGpio pin wrapper (heap).
Prefer AttachStaticPin when bring-up must avoid heap. This factory remains for tests and ad-hoc tools.
| configure_hardware | If false, Initialize() skips I2C direction/pull (caller must have batched SetDirections). |
|
privatenoexcept |
Internal deinitialization.
|
noexcept |
Drain any pending interrupt that was deferred from ISR context.
This method should be called from task context (e.g., a polling loop or a dedicated worker task). It checks the atomic interrupt_pending_ flag, and if set, performs the I2C reads and user callback dispatch safely.
|
noexcept |
Dump comprehensive diagnostics to the system log.
Logs initialization status, I2C address, chip variant, pin registry, interrupt configuration, and error flags at INFO level.
|
noexcept |
Enable or disable input latch for a pin.
| pin | Pin number (0-15). |
| enable | true to enable input latch, false to disable. |
|
noexcept |
Deinitialize the handler and release resources.
Disables hardware interrupt, clears the pin registry, and releases the driver and I2C adapter.
|
noexcept |
Ensure the handler is initialized (lazy initialization).
On first call, creates the I2C adapter and driver, runs the driver's EnsureInitialized() (which auto-detects chip variant), and optionally configures the hardware interrupt pin.
|
inlineprivatenoexcept |
Check init state under already-held handler_mutex_.
Check initialization under an already-held handler_mutex_.
|
noexcept |
Get the interrupt mask for all 16 pins.
| [out] | mask | 16-bit mask (0=enabled, 1=masked per PCAL9555A convention). |
|
noexcept |
Get the interrupt status for all 16 pins.
Reading the status clears the interrupt condition on the device.
| [out] | status | 16-bit mask (bit N set = pin N has pending interrupt). |
|
noexcept |
Get the detected chip variant.
|
noexcept |
Get a bitmask of all created pin numbers.
|
privatenoexcept |
|
privatenoexcept |
Get the underlying PCAL95555 driver for advanced register-level operations.
|
noexcept |
Get the driver's error flags.
|
noexcept |
Get an existing GPIO pin wrapper by number.
|
noexcept |
Raw pointer to a registered pin (no shared_ptr control block).
|
noexcept |
Get the I2C address of the underlying device.
|
noexcept |
Get interrupt status for a single pin.
| pin | Pin number (0-15). | |
| [out] | status | true if pin has pending interrupt. |
|
noexcept |
Get the pull resistor mode for a single pin (tracked internally).
| pin | Pin number (0-15). | |
| [out] | pull_mode | Current pull mode. |
|
staticprivatenoexcept |
Static ISR callback for the hardware interrupt pin.
| gpio | The GPIO pin that triggered. |
| trigger | Trigger type. |
| user_data | Pointer to Pcal95555Handler instance. |
|
noexcept |
Check if the detected chip supports Agile I/O features.
|
inlinenoexcept |
Check if hardware interrupt support is available.
|
privatenoexcept |
Internal initialization (called by EnsureInitialized under mutex).
|
inlinenoexcept |
Check if the handler has been initialized.
|
inlinenoexcept |
Check if hardware interrupt is configured and enabled.
|
noexcept |
Check if a pin wrapper has been created.
| pin | Pin number (0-15). |
|
delete |
Non-copyable.
|
delete |
Non-movable.
|
inlinestaticconstexprnoexcept |
Total number of GPIO pins on the expander.
|
privatenoexcept |
Process pending interrupts by reading status and dispatching callbacks.
|
noexcept |
Absolute program POL=0, OUTPUT latch, and CONFIG (no RMW).
Seeds the handler port shadow used by SetOutput / SetDirections. Verifies via latch readback when distinct, else INPUT pad follow on driven-high output bits (datasheet: INPUT mirrors pad for outputs).
| config | CONFIG mask (bit=1 → input) |
| output | OUTPUT latch mask |
| out_check_mask | bits of OUTPUT that must match for verify |
|
noexcept |
Read both INPUT_PORT registers in one dual-port transaction.
| [out] | levels | Bit N = physical HIGH on PCA pin N. |
|
noexcept |
Read CONFIG (1=input) and OUTPUT latch port pairs (PCA pin bits).
|
noexcept |
Read the physical level of a pin.
Output pins (CONFIG bit clear) return the OUTPUT latch shadow — Mid I2C0 INPUT_PORT is not used for driven lines. Input pins sample the wire via the driver.
| pin | Pin number (0-15). | |
| [out] | active | true if HIGH, false if LOW. |
|
noexcept |
Read OUTPUT_PORT_0/1 from the chip (never the CM4 shadow).
Use after SetOutput to confirm the chip latch actually updated. Must run before any INPUT_PORT read on this bus.
|
noexcept |
Read the full standard PCA9555 bank (0x00..0x07) as four 16-bit ports.
Per NXP datasheet: INPUT reflects pad levels even when the pin is an output; OUTPUT readback is the latch flip-flop; CONFIG bit=1 means input. Use after a write to confirm the latch took effect.
|
privatenoexcept |
Register a per-pin interrupt callback (called by Pcal95555GpioPin).
| pin | Pin number (0-15). |
| trigger | Trigger type. |
| callback | Callback function. |
| user_data | User data for callback. |
|
noexcept |
Reset all registers to power-on default state.
|
noexcept |
Set the direction of a single pin.
| pin | Pin number (0-15). |
| direction | Input or output. |
|
noexcept |
Set direction for multiple pins at once.
| pin_mask | 16-bit mask (bit N = pin N). |
| direction | Common direction for all selected pins. |
|
noexcept |
Set output drive strength for a pin.
| pin | Pin number (0-15). |
| level | Drive strength (Level0=25%, Level1=50%, Level2=75%, Level3=100%). |
|
noexcept |
Set the per-pin interrupt mask.
| pin | Pin number (0-15). |
| mask | true to mask (disable) interrupt, false to unmask (enable). |
|
noexcept |
Batch-set input polarity inversion for a pin mask.
| pin_mask | Bits set select pins 0..15. |
| invert | true to invert, false for normal (typical clear: mask=0xFFFF). |
|
noexcept |
Write a logical level to an output pin.
| pin | Pin number (0-15). |
| active | true for HIGH, false for LOW. |
|
noexcept |
Configure per-port output mode (push-pull or open-drain).
| port0_open_drain | true for open-drain on port 0 (pins 0-7). |
| port1_open_drain | true for open-drain on port 1 (pins 8-15). |
|
noexcept |
Write output level for multiple pins at once.
| pin_mask | 16-bit mask (bit N = pin N). |
| active | Common level for all selected pins. |
|
noexcept |
Write output level for multiple pins in one transaction, then read the latch back and retry (up to 3×) until every selected bit matches.
The verified single-pin path costs a write + read per pin; parking several control straps one by one (TMC EN + nRST, re-asserted) held the motor thread ~30 ms (desk 2026-10-15). One dual-port write + one read-back covers them all.
|
noexcept |
Set input polarity inversion for a pin.
| pin | Pin number (0-15). |
| invert | true to invert input polarity, false for normal. |
|
noexcept |
Set the pull resistor mode for a single pin.
Maps HardFOC pull modes to PCAL9555A SetPullEnable/SetPullDirection:
| pin | Pin number (0-15). |
| pull_mode | Desired pull mode. |
|
noexcept |
Set pull mode for multiple pins at once.
| pin_mask | 16-bit mask (bit N = pin N). |
| pull_mode | Common pull mode for all selected pins. |
|
noexcept |
Toggle the output state of a pin.
| pin | Pin number (0-15). |
|
privatenoexcept |
Unregister a per-pin interrupt callback.
| pin | Pin number (0-15). |
|
inlineprivatenoexcept |
Validate pin number is in range 0-15.
|
noexcept |
Drive one pin and verify OUTPUT latch + INPUT pad follow.
| pin | PCA pin 0..15 (prefer an unused pad for bench integrity tests). | |
| [out] | latch_high | OUTPUT bank after writing HIGH |
| [out] | input_high | INPUT bank after writing HIGH |
| [out] | latch_low | OUTPUT bank after writing LOW |
| [out] | input_low | INPUT bank after writing LOW |
|
friend |
Allow Pcal95555GpioPin to access private interrupt methods.
|
private |
PCA POR default CONFIG (all input)
|
mutableprivate |
Thread safety for handler operations.
|
private |
I2C adapter (created in Initialize).
|
private |
I2C device reference (not owned).
|
private |
Initialization state.
|
private |
Whether hardware interrupt is active.
|
private |
Deferred interrupt flag (set in ISR, cleared in task context).
|
private |
Hardware INT pin (optional, not owned).
|
private |
PCA POR default OUTPUT.
|
private |
Heap pins from CreateGpioPin.
|
private |
Typed driver (created in Initialize).
|
private |
Non-owning registry slots.
|
private |
POLARITY_INV.
|
private |
|
private |
Last-read pin input levels (bitmask).
|
private |