HardFOC Vortex V1 HAL
Unified HAL API for the HardFOC Vortex motor-control platform (ESP32-C6, TMC9660)
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes | Static Private Attributes | List of all members
GpioManager Class Reference

Singleton managing GPIO pins across ESP32, PCAL95555 I/O expander, and TMC9660 controllers. More...

#include <GpioManager.h>

Collaboration diagram for GpioManager:
[legend]

Public Member Functions

 GpioManager (const GpioManager &)=delete
 
GpioManager & operator= (const GpioManager &)=delete
 
 GpioManager (GpioManager &&)=delete
 
GpioManager & operator= (GpioManager &&)=delete
 
bool EnsureInitialized () noexcept
 Register all GPIO pins and initialise drivers (idempotent).
 
bool Deinitialize () noexcept
 Reset GPIO manager to uninitialised state.
 
bool IsInitialized () const noexcept
 Check whether the manager is initialised.
 
BaseGpio * Get (std::string_view name) noexcept
 Get the pin object of a named pin.
 
BaseGpio * Get (HfFunctionalGpioPin pin) noexcept
 Get the pin object of a functional pin.
 
bool Contains (std::string_view name) const noexcept
 Check if a named pin exists in the registry.
 
size_t Size () const noexcept
 Number of registered GPIO pins.
 
hf_gpio_err_t DebugReadPcal95555Pin (uint8_t expander_pin_0_to_15, bool &out_level) noexcept
 Read one PCAL95555 expander pin by hardware index (0–15), independent of whether that line is registered in the GPIO table.
 
hf_gpio_err_t DebugReadPcal95555InputSnapshot (uint16_t &out_bits) noexcept
 Read INPUT_PORT_0 and INPUT_PORT_1 in one driver call (bits 0–7 = port0, 8–15 = port1).
 
void RegisterTmc9660BridgePinsIfNeeded () noexcept
 After MotorController::CreateOnboardDevice(), register TMC9660 GPIO17/18 in the table.
 
void UnregisterTmc9660BridgePins () noexcept
 Remove the TMC9660 GPIO17/18 entries (their objects belong to the TMC9660 handler).
 
hf_gpio_err_t Set (std::string_view name, bool value) noexcept
 Drive a GPIO output to its active (true) or inactive (false) state.
 
hf_gpio_err_t SetActive (std::string_view name) noexcept
 Drive a pin to its active state.
 
hf_gpio_err_t SetInactive (std::string_view name) noexcept
 Drive a pin to its inactive state.
 
hf_gpio_err_t Read (std::string_view name, bool &state) noexcept
 Read the logical (active) state of a pin.
 
hf_gpio_err_t Toggle (std::string_view name) noexcept
 Toggle pin output between high and low.
 
hf_gpio_err_t IsActive (std::string_view name, bool &active) noexcept
 Check whether a pin is currently in its active state.
 
hf_gpio_err_t SetDirection (std::string_view name, hf_gpio_direction_t direction) noexcept
 Change pin direction (input / output / open-drain).
 
hf_gpio_err_t SetPullMode (std::string_view name, hf_gpio_pull_mode_t pull_mode) noexcept
 Configure internal pull-up / pull-down resistors.
 
hf_gpio_err_t SetOutputMode (std::string_view name, hf_gpio_output_mode_t mode) noexcept
 Configure output driver mode (push-pull or open-drain).
 
hf_gpio_err_t ConfigureInterrupt (std::string_view name, hf_gpio_interrupt_trigger_t trigger, InterruptCallback callback, void *user_data=nullptr) noexcept
 Configure interrupt on a named GPIO pin.
 
hf_gpio_err_t EnableInterrupt (std::string_view name) noexcept
 Enable a previously configured interrupt on a named pin.
 
hf_gpio_err_t DisableInterrupt (std::string_view name) noexcept
 Disable the interrupt on a named pin.
 
bool SupportsInterrupts (std::string_view name) const noexcept
 Check whether a pin's underlying driver supports interrupts.
 
hf_gpio_err_t GetSystemDiagnostics (GpioSystemDiagnostics &diagnostics) const noexcept
 Populate a diagnostics snapshot.
 
hf_gpio_err_t GetLastError () const noexcept
 Get the most recent error code from any GPIO operation.
 
void DumpStatistics () const noexcept
 Log current GPIO state and statistics to the console.
 

Static Public Member Functions

static GpioManager & GetInstance () noexcept
 Access the singleton instance (Meyers singleton, thread-safe).
 

Private Member Functions

 GpioManager () noexcept=default
 
 ~GpioManager ()=default
 
bool Initialize () noexcept
 
void ReleaseLocked () noexcept
 Drop every entry and destroy the pin objects and the expander handler. Caller holds mutex_.
 
size_t FindByName (std::string_view name) const noexcept
 Find entry index by string name. Returns kInvalidIndex if not found.
 
bool EnsurePcal95555Handler () noexcept
 Lazy-init the PCAL95555 handler (needs I²C from CommChannelsManager).
 

Private Attributes

std::array< GpioEntry, kMaxEntries > entries_ {}
 
size_t registered_count_ {0}
 
uint64_t init_time_ms_ {0}
 
uint32_t total_ops_ {0}
 
uint32_t successful_ops_ {0}
 
uint32_t failed_ops_ {0}
 
hf_gpio_err_t last_error_ {hf_gpio_err_t::GPIO_SUCCESS}
 
std::atomic< bool > initialized_ {false}
 
RtosMutex mutex_
 
std::optional< Pcal95555Handler > pcal95555_handler_
 In place; emplaced at init.
 
std::array< std::optional< Pcal95555GpioPin >, 16 > pcal_pins_ {}
 
BaseGpio * pcal_host_int_gpio_ {nullptr}
 ESP32 GPIO for PCAL95555 /INT (COMM_I2C_PCAL95555_INT); not in the GPIO registry table.
 

Static Private Attributes

static constexpr size_t kMaxEntries
 
static constexpr size_t kInvalidIndex = SIZE_MAX
 

Detailed Description

Singleton managing GPIO pins across ESP32, PCAL95555 I/O expander, and TMC9660 controllers.

Registers all GPIO, USER, ADC, and SPI category pins from the X-MACRO pin config. Handles three chip types:

Constructor & Destructor Documentation

◆ GpioManager() [1/3]

GpioManager::GpioManager ( const GpioManager &  )
delete

◆ GpioManager() [2/3]

GpioManager::GpioManager ( GpioManager &&  )
delete

◆ GpioManager() [3/3]

GpioManager::GpioManager ( )
privatedefaultnoexcept

◆ ~GpioManager()

GpioManager::~GpioManager ( )
privatedefault

Member Function Documentation

◆ ConfigureInterrupt()

hf_gpio_err_t GpioManager::ConfigureInterrupt ( std::string_view  name,
hf_gpio_interrupt_trigger_t  trigger,
InterruptCallback  callback,
void *  user_data = nullptr 
)
noexcept

Configure interrupt on a named GPIO pin.

Parameters
namePin name from pincfg.
triggerInterrupt trigger edge/level.
callbackFunction called on interrupt (keep minimal — ISR context).
user_dataOptional user pointer passed to callback.
Returns
GPIO_SUCCESS on success.

◆ Contains()

bool GpioManager::Contains ( std::string_view  name) const
noexcept

Check if a named pin exists in the registry.

◆ DebugReadPcal95555InputSnapshot()

hf_gpio_err_t GpioManager::DebugReadPcal95555InputSnapshot ( uint16_t &  out_bits)
noexcept

Read INPUT_PORT_0 and INPUT_PORT_1 in one driver call (bits 0–7 = port0, 8–15 = port1).

For bench / bring-up. Lines tied to GND read as 0 (inactive) with typical strapping; compare against your schematic for A0–A2 and routed nets.

◆ DebugReadPcal95555Pin()

hf_gpio_err_t GpioManager::DebugReadPcal95555Pin ( uint8_t  expander_pin_0_to_15,
bool &  out_level 
)
noexcept

Read one PCAL95555 expander pin by hardware index (0–15), independent of whether that line is registered in the GPIO table.

For bench / bring-up only. Uses the shared Pcal95555Handler after I²C init. out_level follows the same convention as Pcal95555Handler::ReadInput.

◆ Deinitialize()

bool GpioManager::Deinitialize ( )
noexcept

Reset GPIO manager to uninitialised state.

Returns
true on success.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ DisableInterrupt()

hf_gpio_err_t GpioManager::DisableInterrupt ( std::string_view  name)
noexcept

Disable the interrupt on a named pin.

Parameters
namePin name from pincfg.
Returns
GPIO_SUCCESS on success.

◆ DumpStatistics()

void GpioManager::DumpStatistics ( ) const
noexcept

Log current GPIO state and statistics to the console.

Here is the caller graph for this function:

◆ EnableInterrupt()

hf_gpio_err_t GpioManager::EnableInterrupt ( std::string_view  name)
noexcept

Enable a previously configured interrupt on a named pin.

Parameters
namePin name from pincfg.
Returns
GPIO_SUCCESS on success.

◆ EnsureInitialized()

bool GpioManager::EnsureInitialized ( )
noexcept

Register all GPIO pins and initialise drivers (idempotent).

Returns
true on success or if already initialised.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ EnsurePcal95555Handler()

bool GpioManager::EnsurePcal95555Handler ( )
privatenoexcept

Lazy-init the PCAL95555 handler (needs I²C from CommChannelsManager).

Here is the call graph for this function:
Here is the caller graph for this function:

◆ FindByName()

size_t GpioManager::FindByName ( std::string_view  name) const
privatenoexcept

Find entry index by string name. Returns kInvalidIndex if not found.

◆ Get() [1/2]

BaseGpio * GpioManager::Get ( HfFunctionalGpioPin  pin)
noexcept

Get the pin object of a functional pin.

Returns
Non-owning pointer, valid until Deinitialize() (TMC9660 pins: until MotorController::Deinitialize()); nullptr if not registered.

◆ Get() [2/2]

BaseGpio * GpioManager::Get ( std::string_view  name)
noexcept

Get the pin object of a named pin.

Returns
Non-owning pointer, valid until Deinitialize(); nullptr if not found.
Note
A name lookup walks the pin table; bind once at init, not per cycle.
Here is the caller graph for this function:

◆ GetInstance()

GpioManager & GpioManager::GetInstance ( )
staticnoexcept

Access the singleton instance (Meyers singleton, thread-safe).

Returns
Reference to the sole GpioManager instance.
Here is the caller graph for this function:

◆ GetLastError()

hf_gpio_err_t GpioManager::GetLastError ( ) const
inlinenoexcept

Get the most recent error code from any GPIO operation.

Returns
Last hf_gpio_err_t set by any API call

◆ GetSystemDiagnostics()

hf_gpio_err_t GpioManager::GetSystemDiagnostics ( GpioSystemDiagnostics &  diagnostics) const
noexcept

Populate a diagnostics snapshot.

Parameters
[out]diagnosticsStruct filled with current counters and state.
Returns
GPIO_SUCCESS on success.

◆ Initialize()

bool GpioManager::Initialize ( )
privatenoexcept
Here is the call graph for this function:
Here is the caller graph for this function:

◆ IsActive()

hf_gpio_err_t GpioManager::IsActive ( std::string_view  name,
bool &  active 
)
noexcept

Check whether a pin is currently in its active state.

Parameters
namePin name from pincfg.
[out]activetrue if pin is active.
Returns
GPIO_SUCCESS on success.

◆ IsInitialized()

bool GpioManager::IsInitialized ( ) const
inlinenoexcept

Check whether the manager is initialised.

Returns
true if ready.
Here is the caller graph for this function:

◆ operator=() [1/2]

GpioManager & GpioManager::operator= ( const GpioManager &  )
delete

◆ operator=() [2/2]

GpioManager & GpioManager::operator= ( GpioManager &&  )
delete

◆ Read()

hf_gpio_err_t GpioManager::Read ( std::string_view  name,
bool &  state 
)
noexcept

Read the logical (active) state of a pin.

The result honours the pin's polarity from the pin map: for an active-low pin (PIN_LOGIC_INVERTED), a low electrical level reads as true. It is the same as IsActive(). It is not the electrical level.

Parameters
namePin name from pincfg.
[out]statetrue = active, false = inactive.
Returns
GPIO_SUCCESS on success.

◆ RegisterTmc9660BridgePinsIfNeeded()

void GpioManager::RegisterTmc9660BridgePinsIfNeeded ( )
noexcept

After MotorController::CreateOnboardDevice(), register TMC9660 GPIO17/18 in the table.

Vortex initializes GPIO before motors, so Tmc9660Handler does not exist during the first EnsureInitialized() scan. Call this from Vortex::InitializeMotors() once the onboard handler exists; idempotent if pins are already registered.

Those pins are the same physical lines as PCAL_TMC_GPIO17_EXP_IN / PCAL_TMC_GPIO18_EXP_IN (expander inputs P1–P2): use the PCAL aliases for passive read without TMCL; use TMC_GPIO17 / TMC_GPIO18 for driver-backed direction and output updates over SPI/UART.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ ReleaseLocked()

void GpioManager::ReleaseLocked ( )
privatenoexcept

Drop every entry and destroy the pin objects and the expander handler. Caller holds mutex_.

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Set()

hf_gpio_err_t GpioManager::Set ( std::string_view  name,
bool  value 
)
noexcept

Drive a GPIO output to its active (true) or inactive (false) state.

Logical, like Read(): for an active-low pin, true drives the line low.

Parameters
namePin name from pincfg.
valuetrue = active, false = inactive.
Returns
GPIO_SUCCESS on success.

◆ SetActive()

hf_gpio_err_t GpioManager::SetActive ( std::string_view  name)
noexcept

Drive a pin to its active state.

Parameters
namePin name from pincfg.
Returns
GPIO_SUCCESS on success.

◆ SetDirection()

hf_gpio_err_t GpioManager::SetDirection ( std::string_view  name,
hf_gpio_direction_t  direction 
)
noexcept

Change pin direction (input / output / open-drain).

Parameters
namePin name from pincfg.
directionDesired direction.
Returns
GPIO_SUCCESS on success.

◆ SetInactive()

hf_gpio_err_t GpioManager::SetInactive ( std::string_view  name)
noexcept

Drive a pin to its inactive state.

Parameters
namePin name from pincfg.
Returns
GPIO_SUCCESS on success.

◆ SetOutputMode()

hf_gpio_err_t GpioManager::SetOutputMode ( std::string_view  name,
hf_gpio_output_mode_t  mode 
)
noexcept

Configure output driver mode (push-pull or open-drain).

Parameters
namePin name from pincfg.
modeDesired output mode.
Returns
GPIO_SUCCESS on success.

◆ SetPullMode()

hf_gpio_err_t GpioManager::SetPullMode ( std::string_view  name,
hf_gpio_pull_mode_t  pull_mode 
)
noexcept

Configure internal pull-up / pull-down resistors.

Parameters
namePin name from pincfg.
pull_modeDesired pull mode.
Returns
GPIO_SUCCESS on success.

◆ Size()

size_t GpioManager::Size ( ) const
noexcept

Number of registered GPIO pins.

◆ SupportsInterrupts()

bool GpioManager::SupportsInterrupts ( std::string_view  name) const
noexcept

Check whether a pin's underlying driver supports interrupts.

Parameters
namePin name from pincfg.
Returns
true if interrupts are supported.

◆ Toggle()

hf_gpio_err_t GpioManager::Toggle ( std::string_view  name)
noexcept

Toggle pin output between high and low.

Parameters
namePin name from pincfg.
Returns
GPIO_SUCCESS on success.

◆ UnregisterTmc9660BridgePins()

void GpioManager::UnregisterTmc9660BridgePins ( )
noexcept

Remove the TMC9660 GPIO17/18 entries (their objects belong to the TMC9660 handler).

Called by MotorController::Deinitialize() before it destroys the onboard handler, so Get(TMC_GPIO17/18) returns nullptr instead of a dangling pointer.

Here is the caller graph for this function:

Member Data Documentation

◆ entries_

std::array<GpioEntry, kMaxEntries> GpioManager::entries_ {}
private

◆ failed_ops_

uint32_t GpioManager::failed_ops_ {0}
private

◆ init_time_ms_

uint64_t GpioManager::init_time_ms_ {0}
private

◆ initialized_

std::atomic<bool> GpioManager::initialized_ {false}
private

◆ kInvalidIndex

constexpr size_t GpioManager::kInvalidIndex = SIZE_MAX
staticconstexprprivate

◆ kMaxEntries

constexpr size_t GpioManager::kMaxEntries
staticconstexprprivate
Initial value:
=
static_cast<size_t>(HfFunctionalGpioPin::HF_FUNCTIONAL_GPIO_COUNT)

◆ last_error_

hf_gpio_err_t GpioManager::last_error_ {hf_gpio_err_t::GPIO_SUCCESS}
private

◆ mutex_

RtosMutex GpioManager::mutex_
mutableprivate

◆ pcal95555_handler_

std::optional<Pcal95555Handler> GpioManager::pcal95555_handler_
private

In place; emplaced at init.

◆ pcal_host_int_gpio_

BaseGpio* GpioManager::pcal_host_int_gpio_ {nullptr}
private

ESP32 GPIO for PCAL95555 /INT (COMM_I2C_PCAL95555_INT); not in the GPIO registry table.

Owned by the board binding

◆ pcal_pins_

std::array<std::optional<Pcal95555GpioPin>, 16> GpioManager::pcal_pins_ {}
private

Expander pin objects (static)

◆ registered_count_

size_t GpioManager::registered_count_ {0}
private

◆ successful_ops_

uint32_t GpioManager::successful_ops_ {0}
private

◆ total_ops_

uint32_t GpioManager::total_ops_ {0}
private

The documentation for this class was generated from the following files: