Adding ExclusiveConsumer feature to OpenMRN#911
Conversation
Adds a new consumer class where a group of GPIO outputs are mutually exclusive: receiving an event for any output in the group turns that output on and turns off all others. Useful for signal masts, route indicators, or any application where only one output should be active at a time. Includes CDI configuration support (ExclusiveConsumerConfig) with one event per output (rather than an on/off pair), and unit tests covering exclusive switching, identify consumer, and global identify behavior. https://claude.ai/code/session_01178EKqcoikwTtUC9ybWow1
Modifies the nucleo_io application's STM32F303RE Nucleo target to use ConfiguredExclusiveConsumer for Port D and Port E output lines 1-6: - Port D lines 1,2,3: exclusive group 1 (one active at a time) - Port D lines 4,5,6: exclusive group 2 (one active at a time) - Port E lines 1,2,3: exclusive group 1 (one active at a time) - Port E lines 4,5,6: exclusive group 2 (one active at a time) - Port D/E lines 7,8: remain as standard on/off consumers Breaks the main.cxx symlink to the F091RC target to create a target-specific main.cxx. Updates config.hxx CDI layout with ExclusiveGroup3 entries and bumps CANONICAL_VERSION to force EEPROM reset on existing boards. https://claude.ai/code/session_01178EKqcoikwTtUC9ybWow1
Increases exclusive consumer group size from 3 to 4 outputs, which aligns with the shift register divisibility and supports signal mast use cases with a marker light (4 aspects). All 8 lines per port are now covered by two exclusive groups with no remainder: - Port D group 1: lines 1,2,3,4 (mutually exclusive) - Port D group 2: lines 5,6,7,8 (mutually exclusive) - Port E group 1: lines 1,2,3,4 (mutually exclusive) - Port E group 2: lines 5,6,7,8 (mutually exclusive) The ConfiguredExclusiveConsumer class itself already supports any group size (2, 3, 4, etc.) since it is templated on N. https://claude.ai/code/session_01178EKqcoikwTtUC9ybWow1
…0iezv-MH0NT Claude/explain codebase mlk9o584mfw0iezv mh0 nt
…how compile time options are presented. Ready for hardware test and validation.
Finalizing Exclusive Consumer
bakerstu
left a comment
There was a problem hiding this comment.
If you address the comments you can merge.
| // ====================================================================== | ||
|
|
||
| /// Port D lines 1, 2, 3, 4 — exclusive group 1. | ||
| constexpr const Gpio *const kPortDExcl1Gpio[] = { |
There was a problem hiding this comment.
There is a style issue here. constants are supposed to be UNDERSCORE_SEPARATED_ALL_CAPS, no Hungarian style "k" prefix.
The style guide is in the Doxygen. You should be able to have Claude code read and comprehend it. I intend to move the style guide to a Markdown file.
| namespace openlcb | ||
| { | ||
|
|
||
| static const uint64_t kEventBase = 0x05010101FFFF0000ULL; |
| private SimpleEventHandler | ||
| { | ||
| public: | ||
| typedef ExclusiveConsumerConfig config_entry_type; |
There was a problem hiding this comment.
C++ types should use PascalCase.
| /// @param config is the repeated group object from the configuration space | ||
| /// that represents the locations of the events. | ||
| template <unsigned N> | ||
| __attribute__((noinline)) ConfiguredExclusiveConsumer(Node *node, |
There was a problem hiding this comment.
Is the noinline attribute necessary. Normally we let the compiler choose.
| ConfigUpdateService::instance()->register_update_listener(this); | ||
| } | ||
|
|
||
| ~ConfiguredExclusiveConsumer() |
There was a problem hiding this comment.
Missing Doxygen comment blocks here and below.
| } | ||
|
|
||
| UpdateAction apply_configuration(int fd, bool initial_load, | ||
| BarrierNotifiable *done) OVERRIDE |
There was a problem hiding this comment.
The use of "OVERRIDE" here and elsewhere is deprecated. Use "override" (all lowercase) instead.
| /// instances. Can be constant from FLASH space. | ||
| /// @param size is the length of the list of pins array. | ||
| /// @param config is the repeated group object from the configuration space | ||
| /// that represents the locations of the events. |
There was a problem hiding this comment.
Missing brief description and the template argument is undocumented.
| EventRegistry::instance()->unregister_handler(this); | ||
| } | ||
|
|
||
| Node *node_; //< virtual node to export the consumer on |
There was a problem hiding this comment.
There are not proper Doxygen comment blocks. Use ///<.
This is a new consumer class that is aimed at a use case to drive a signal head from a group of outputs on a node. This matches a typical prototype approach of only having a single color or position being lit (turned on) inside a single signal head.
The new class is called ConfiguredExclusiveConsumer, matching the naming scheme of existing producer/consumers. This class enables creating a group of outputs (from 2 to N) that, upon receipt of a matching event ID by the node, will turn on that particular output and turn off all other outputs in the same group.
There is sample usage of this feature in the Nucleo DevKit application (nucleo_io) on Port D and E. I have put various compile time configuration guards in place to match what we have previously done for the Snap Switch and IO expansion features.
I have tested this on DevKit hardware with a F303 Nucleo.