LCC Fusion Project 1.0
LCC Automation
Loading...
Searching...
No Matches
IoConfiguredPC Class Reference

#include <IoConfiguredPC.h>

Inheritance diagram for IoConfiguredPC:
Collaboration diagram for IoConfiguredPC:

Public Types

typedef IoCardConfig CardConfig_type
 
typedef IoConfig LineConfig_type
 

Public Member Functions

template<unsigned N>
 IoConfiguredPC (openlcb::Node *pNode, const openlcb::RepeatedGroup< CardConfig_type, N > &configOffset, uint8_t numDevicesPerCard, EventDeviceTypes eventDeviceType, const char *cardDescription) __attribute__((noinline))
 Helper that wires a bank of MCP23017-based I/O cards into the OpenLCB / LCC event system. More...
 
UpdateAction apply_configuration (int fd, bool initial_load, BarrierNotifiable *done) OVERRIDE
 Read CDI, initialize hardware, and (re)register events for every IO card and line. More...
 
void factory_reset (int fd) OVERRIDE
 Reset this node's IO card CDI segment to factory defaults. More...
 
bool ensureUniqueI2cOffset (uint8_t cardIndex, uint8_t bus, uint8_t offset)
 

Public Attributes

union I2cCardHelper::EventUserArgsUnion userArgs
 

Protected Member Functions

void drive_pin (uint8_t card, uint8_t pin, bool set) override
 Consumer hook: parent decodes EventReport and calls this with (card,pin,set).
 
void _do_unregister ()
 Unregisters this event handler from the global registry.
 
void handle_identify_consumer (const openlcb::EventRegistryEntry &registry_entry, openlcb::EventReport *event, BarrierNotifiable *done) OVERRIDE
 Process request to identify produced events.
 
void handle_identify_producer (const openlcb::EventRegistryEntry &registry_entry, openlcb::EventReport *event, BarrierNotifiable *done) OVERRIDE
 Process request to identify produced events.
 
virtual void SendEventIdentified (const openlcb::EventRegistryEntry &registry_entry, openlcb::EventReport *event, BarrierNotifiable *done)
 Sends Producer- or Consumer-Identified for registry_entry. More...
 
void applyI2cInfo (int fd, uint8_t cardIndex, i2cInfoConfig_type cfgI2cInfoRef)
 sets up the MCP card's I2C connection using the user provided (CDI) configuration information (bus and address offset) More...
 
void resetCardInfo (int fd, cardInfoConfig_type cfgI2cInfoRef)
 resets the card configuration information (description field). More...
 
void resetI2cInfo (int fd, i2cInfoConfig_type cfgI2cInfoRef)
 resets the card's I2C configuration information (bus and address fields). More...
 
virtual void drive_pin_ext (uint8_t card, uint8_t pin, bool set, uint8_t intArg)
 
EventUserArgsUnion unpack_user_args (const openlcb::EventRegistryEntry &re) const
 Small helper to unpack our 4-byte user_arg payload from the registry entry.
 
void handle_event_report (const openlcb::EventRegistryEntry &registry_entry, openlcb::EventReport *event, BarrierNotifiable *done) OVERRIDE
 

Private Member Functions

bool _processPinState (int cardIndex, int pinIndex)
 Shadow copy of the event IDs produced by each of the UOD cards. More...
 
void _initI2cCards (bool isProducer)
 Initializes the array of I2C card objects using the configured card type. More...
 

Detailed Description

How IoConfiguredPC acts as Producer <strong>and</strong> Consumer

  • Consumer path (outputs): the parent (I2cCardHelper) decodes incoming Event Reports into (card,pin,set,intArg) and calls drive_pin(...) here. This class writes the MCP pin and, if desired, persists the new state via DefaultDeviceSettings.
  • Producer path (inputs): if this class also inherits I2cPollingHelper.h, it registers with the RefreshLoop. On each poll slice it reads debounced pin state and, if a change is detected, emits one corresponding ON/OFF event via WriteAsync (one‑event‑per‑slice).

CDI fields

  • action per pin: LINPUT (producer) or LOUTPUT (consumer)
  • debounceCount: applied immediately to debouncer at config time
  • onEvent/offEvent: ON/OFF Event IDs for each pin
  • I²C bus/offset per card via i2cInfoConfig

Sequences

Startup & config:

  1. apply_configuration(): calls applyI2cInfo per card
  2. packs user_arg and registers ON/OFF events for each pin
  3. for inputs: initializes debouncer and shadows (seed only; no boot event)

Runtime:

  • inputs (producer): _processPinState() → emit ON/OFF → engine resumes on notify()
  • outputs (consumer): parent routes Event Report → drive_pin(card,pin,set) → MCP write

Notes

  • Debounce is evaluated before event emission; only state changes produce events.
  • The polling engine will resume where it left off across slices (card/line cursors).
  • If a card is offline, read_card() returns false and the engine skips it this slice.

Definition at line 113 of file IoConfiguredPC.h.

Member Typedef Documentation

◆ CardConfig_type

typedef IoCardConfig IoConfiguredPC::CardConfig_type

Type for Input/Output card configuration entry

Definition at line 117 of file IoConfiguredPC.h.

◆ LineConfig_type

Type for Input/Output configuration entry

Definition at line 118 of file IoConfiguredPC.h.

Constructor & Destructor Documentation

◆ IoConfiguredPC()

template<unsigned N>
IoConfiguredPC::IoConfiguredPC ( openlcb::Node *  pNode,
const openlcb::RepeatedGroup< CardConfig_type, N > &  configOffset,
uint8_t  numDevicesPerCard,
EventDeviceTypes  eventDeviceType,
const char *  cardDescription 
)
inline

Helper that wires a bank of MCP23017-based I/O cards into the OpenLCB / LCC event system.

Constructs an IoConfiguredPC instance that:

  • Knows how many I/O cards are defined in the CDI.
  • Binds to the CDI repeated group that holds the per-card configuration.
  • Configures the I2C helper for MCP23017-based I/O cards.
  • Allocates debouncers and producer event ID tables for each card/pin.

Typically created once in the sketch (or node wrapper) during startup, then used to apply CDI configuration and register consumer/producer events.

Template Parameters
NNumber of I/O cards in the CDI repeated group.
Parameters
pNodeOpenLCB node object from the stack.
configOffsetCDI configuration offset for the repeated group of I/O cards.
numDevicesPerCardNumber of I/O lines (pins) per card (for example, 16 for a full MCP23017 port).
eventDeviceTypeLogical type of event device (used for logging, diagnostics, and naming).
cardDescriptionHuman-friendly card description for log messages and debug output (e.g. "IO Card").
Usage
// Assume cfg.ioCardsSeg().ioCardConfig() is a repeated group of N cards.
cfg.ioCardsSeg().ioCardConfig(),
16, // 16 I/O lines per MCP23017
EventDeviceTypes::IoCard, // your enum value
"IO Card");
openlcb::Node * node()
node() returns a pointer to the NODE object within memory
Definition: LccNode.h:204
LccNode lccNode(COMM_TYPES::CAN_TWAI|COMM_TYPES::CAN_SLCAN_SERIAL_BRIDGE)
instantiates all consumer and producers

Definition at line 163 of file IoConfiguredPC.h.

Member Function Documentation

◆ _initI2cCards()

void I2cCardHelper::_initI2cCards ( bool  isProducer)
inlineprivateinherited

Initializes the array of I2C card objects using the configured card type.

Allocates and initializes each I2C card in the array to the type specified by the cardType_ member. If isProducer is true, registers each card's polling callback.

Parameters
isProducerTrue if the card is used as a producer and requires polling.

Definition at line 460 of file I2cCardHelper.h.

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

◆ _processPinState()

bool IoConfiguredPC::_processPinState ( int  cardIndex,
int  pinIndex 
)
inlineprivate

Shadow copy of the event IDs produced by each of the UOD cards.

Process one I/O line on a card (debounce + maybe emit one event).

This is called by the polling engine provided by I2cPollingHelper via process_line(cardIndex, lineIndex).

Behavior:

  • Reads the raw GPIO for (card,line) and updates the debouncer.
  • If the debounced state changed since last time:
    • computes the correct ON/OFF event id for this line,
    • emits exactly one Event Report using poll_.helper->WriteAsync(...),
    • returns true so the engine stops this slice (one-event-per-slice rule).
  • If there was no debounced change, returns false and the engine advances to the next line (and eventually the next card).

Notes:

  • Do not block; the engine will resume on the next notify() after the write completes.
  • If a card is offline, read_card(cardIndex) should return false so this function is not called for that card during the current slice.

Definition at line 401 of file IoConfiguredPC.h.

Here is the call graph for this function:

◆ apply_configuration()

UpdateAction IoConfiguredPC::apply_configuration ( int  fd,
bool  initial_load,
BarrierNotifiable *  done 
)
inline

Read CDI, initialize hardware, and (re)register events for every IO card and line.

When it runs:

  • Called once after boot with initial_load == true.
  • Called again whenever CDI changes are committed with initial_load == false.

High-level flow: 1) Unregister old events (only on live updates): If !initial_load, call _do_unregister() so we don’t leak duplicate registry entries.

2) Per-card hardware init (I²C): For each card i, call applyI2cInfo(fd, i, cfgCardsRef.i2cInfoConfig()) to:

  • read the CDI bus / address offset,
  • initialize i2cCards[i] with the correct bus/address,
  • ensure the card object is ready for reads/writes at runtime.

3) Per-line configuration and event registration: For each line j on card i:

  • Read CDI fields: action (input vs output), debounceCount, onEvent, offEvent, and optional description.
  • Pack user_arg for the registry entry using the helper’s standard layout: (card=i, pin=j, intArg=0 unless specified elsewhere, isSetEvent bit implied by event, isProducer = (action == input)).
  • Register both events (ON and OFF) with the OpenMRN registry using that user_arg.
  • Role-specific handling:
    • Input (producer):
      • Snapshot the event IDs into producerEventIds_ so the producer path can emit later.
      • Seed the debouncer for (i, j) from the current raw pin value and the configured debounceCount. This is seed only (no Event Report yet); the first debounced change at runtime will produce a single ON/OFF event.
    • Output (consumer):
      • Initialize the MCP pin as an output (no pull-up).
      • The consumer path doesn’t drive the pin here; it will act when an Event Report arrives at runtime (via the parent’s handle_event_report → drive_pin(...) hook).

4) Tell the stack to (re)announce: Return REINIT_NEEDED so OpenMRN will run Identify; this lets peers rediscover the updated set of events after a boot or CDI change.

Notes & guarantees:

  • No Event Reports are sent from inside apply_configuration(...). Producers only emit later, during polling, when the debounced state actually changes. Consumers only act in response to incoming Event Reports.
  • If a card is physically offline, the CDI still applies and events are registered; producer polling will simply skip that card until it becomes reachable.
  • Descriptions stored in CDI are for tools/UI (e.g., JMRI) and do not affect logic.
Parameters
fdFile descriptor used to read CDI entries.
initial_loadtrue on cold boot, false during a live reconfiguration.
doneCompletion notifier (handled via AutoNotify at entry).
Returns
UpdateAction Always REINIT_NEEDED to trigger Identify after registration.

Definition at line 237 of file IoConfiguredPC.h.

Here is the call graph for this function:

◆ applyI2cInfo()

void I2cCardHelper::applyI2cInfo ( int  fd,
uint8_t  cardIndex,
i2cInfoConfig_type  cfgI2cInfoRef 
)
inlineprotectedinherited

sets up the MCP card's I2C connection using the user provided (CDI) configuration information (bus and address offset)

Note
producer/consumers apply_configuration() callback invoke this method to initialize the I2C / MCP connection information for the card
all I2C connected cards have CDI section for user provided bus and address information (which must match the settings of the I2C enabeled card)
HOOK: Typical call site is within your apply_configuration() loop:
  • read bus & offset from CDI
  • initialize the corresponding i2cCards[cardIndex]
Parameters
fdfile handle to access the CDI configuration information (provided by openmrn)
cardIndexspecifies which card the configuration is for. Used to update the i2cCards[] array and initialize the connection
cfgI2cInfoRefoffset into the intenal configuration space for the CDI configuration for the MCP card

Definition at line 295 of file I2cCardHelper.h.

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

◆ drive_pin_ext()

virtual void I2cCardHelper::drive_pin_ext ( uint8_t  card,
uint8_t  pin,
bool  set,
uint8_t  intArg 
)
inlineprotectedvirtualinherited

Extended hook for consumers that also need the CDI intArg (e.g., audio message index). Default forwards to drive_pin(...) so existing consumers remain unchanged.

Reimplemented in AudioConfiguredConsumer.

Definition at line 402 of file I2cCardHelper.h.

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

◆ ensureUniqueI2cOffset()

bool I2cCardHelper::ensureUniqueI2cOffset ( uint8_t  cardIndex,
uint8_t  bus,
uint8_t  offset 
)
inlineinherited

Check for duplicate offsets on the same I2C bus. Automatically resets the tracker on the first call per config pass.

Remarks
Call this once per card during your apply_configuration loop, with the CDI values.
Parameters
cardIndexIndex of the card in the config loop.
busI2C bus number (0 or 1).
offsetI2C offset (0–7).
Returns
true if this (bus, offset) was already claimed.

Definition at line 183 of file I2cCardHelper.h.

Here is the caller graph for this function:

◆ factory_reset()

void IoConfiguredPC::factory_reset ( int  fd)
inline

Reset this node's IO card CDI segment to factory defaults.

What this does (by design, CDI only):

  • Iterates every IO card and every line in the CDI and restores the shipped defaults:
    • Calls resetCardInfo(fd, ...) to reset card-level metadata (e.g., enable/name).
    • Calls resetI2cInfo(fd, ...) to reset the I²C bus and address-offset entries.
    • For each line:
      • Resets action (input/output role) and debounceCount to their default values.
      • Clears the description string.
      • Writes default onEvent / offEvent IDs using NEXT_DEFAULT_EVENT(...) so each line has a valid, discoverable pair of event IDs after a reset.

What this does not do:

  • Does not talk to the hardware (no GPIO/I²C traffic).
  • Does not (re)register events with OpenMRN.
  • Does not seed debouncers or change any in-RAM runtime state.

Why this matters:

  • After a factory reset, a subsequent apply_configuration(...) run will re-initialize cards from the clean CDI image and (re)register events in a known-good state.
Parameters
fdFile descriptor used to write the CDI entries.

Definition at line 320 of file IoConfiguredPC.h.

Here is the call graph for this function:

◆ handle_event_report()

void I2cCardHelper::handle_event_report ( const openlcb::EventRegistryEntry &  registry_entry,
openlcb::EventReport *  event,
BarrierNotifiable *  done 
)
inlineprotectedinherited

Default consumer handler: maps an incoming Event Report to (card,pin,set,intArg) and calls drive_pin_ext(...). Producers are ignored.

Definition at line 418 of file I2cCardHelper.h.

Here is the call graph for this function:

◆ resetCardInfo()

void I2cCardHelper::resetCardInfo ( int  fd,
cardInfoConfig_type  cfgI2cInfoRef 
)
inlineprotectedinherited

resets the card configuration information (description field).

Note
invoke from the consumer/producer factory_reset() to reset the card configuration
Parameters
fdfile handle to access the CDI configuration information (provided by openmrn)
cfgI2cInfoRefoffset into the intenal configuration space for the CDI configuration block for the card's info (description, etc)

Definition at line 309 of file I2cCardHelper.h.

Here is the caller graph for this function:

◆ resetI2cInfo()

void I2cCardHelper::resetI2cInfo ( int  fd,
i2cInfoConfig_type  cfgI2cInfoRef 
)
inlineprotectedinherited

resets the card's I2C configuration information (bus and address fields).

Note
invoke from the consumer/producer factory_reset() to reset the card configuration
Parameters
fdfile handle to access the CDI configuration information (provided by openmrn)
cfgI2cInfoRefoffset into the intenal configuration space for the CDI configuration for card's I2C info (bus/offset)

Definition at line 321 of file I2cCardHelper.h.

Here is the caller graph for this function:

◆ SendEventIdentified()

virtual void I2cCardHelper::SendEventIdentified ( const openlcb::EventRegistryEntry &  registry_entry,
openlcb::EventReport *  event,
BarrierNotifiable *  done 
)
inlineprotectedvirtualinherited

Sends Producer- or Consumer-Identified for registry_entry.

Identification type is inferred from the registry entry’s packed user args (see

See also
isProducer). Override to customize the MTI or payload.

Reimplemented in TurnoutConfiguredPC.

Definition at line 273 of file I2cCardHelper.h.

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

Member Data Documentation

◆ userArgs

union I2cCardHelper::EventUserArgsUnion I2cCardHelper::userArgs
inherited

event arguments


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