36#ifndef _OPENLCB_MULTICONFIGUREDPC_HXX_
37#define _OPENLCB_MULTICONFIGUREDPC_HXX_
50static const char PC_ACTION_MAP[] =
51 "<relation><property>0</property><value>Output</value></relation>"
52 "<relation><property>1</property><value>Input</value></relation>";
57 Name(
"Description"), Description(
"User name of this line."));
62 Description(
"This event ID will turn the output on / be produced when the "
67 Description(
"This event ID will turn the output off / be produced when the "
73enum class ActionConfig : uint8_t
80 Name(
"Configuration"));
85 Description(
"Used for inputs only. Amount of time to wait for the input to "
87 "producing the event. Unit is 30 msec of time. Usually a value "
88 "of 2-3 works well in a non-noisy environment. In high noise "
89 "(train wheels for example) a setting between 8 -- 15 makes "
90 "for a slower response time but a more stable "
91 "signal.\nFormally, the parameter tells how many times of "
92 "tries, each 30 msec apart, the input must have the same value "
93 "in order for that value to be accepted and the event "
94 "transition produced."),
109 typedef PCConfig config_entry_type;
128 template <
unsigned N>
129 __attribute__((noinline))
140 producedEvents_ =
new EventId[size * 2];
141 std::allocator<debouncer_type> alloc;
142 debouncers_ = alloc.allocate(size_);
143 for (
unsigned i = 0; i < size_; ++i)
145 alloc_traits::construct(alloc, debouncers_ + i, 3);
153 delete[] producedEvents_;
154 std::allocator<debouncer_type> alloc;
155 for (
unsigned i = 0; i < size_; ++i)
157 alloc_traits::destroy(alloc, debouncers_ + i);
159 alloc.deallocate(debouncers_, size_);
172 pollingHelper_ = helper;
181 for (; nextPinToPoll_ < size_; ++nextPinToPoll_)
183 auto i = nextPinToPoll_;
184 if (pins_[i]->direction() == Gpio::Direction::DOUTPUT)
188 if (debouncers_[i].update_state(pins_[i]->is_set()))
192 auto event = producedEvents_[2 * i +
193 (debouncers_[i].current_state() ? 1 : 0)];
194 pollingHelper_->WriteAsync(node_, Defs::MTI_EVENT_REPORT,
199 pollingDone_->notify();
217 for (
unsigned i = 0; i < size_; ++i)
219 const config_entry_type cfg_ref(grp_ref.entry(i));
220 EventId cfg_event_on = cfg_ref.pc().event_on().read(fd);
221 EventId cfg_event_off = cfg_ref.pc().event_off().read(fd);
226 uint8_t action = cfg_ref.action().read(fd);
227 if (action == (uint8_t)PCConfig::ActionConfig::DOUTPUT)
229 pins_[i]->set_direction(Gpio::Direction::DOUTPUT);
230 producedEvents_[i * 2] = 0;
231 producedEvents_[i * 2 + 1] = 0;
235 uint8_t param = cfg_ref.debounce().read(fd);
236 pins_[i]->set_direction(Gpio::Direction::DINPUT);
237 debouncers_[i].reset_options(param);
238 debouncers_[i].initialize(pins_[i]->read());
239 producedEvents_[i * 2] = cfg_event_off;
240 producedEvents_[i * 2 + 1] = cfg_event_on;
249 for (
unsigned i = 0; i < size_; ++i)
251 grp_ref.entry(i).pc().description().write(fd,
"");
260 void factory_reset_names(
int fd,
const char *basename)
263 for (
unsigned i = 0; i < size_; ++i)
268 unsigned_integer_to_buffer(i + 1, buf);
270 grp_ref.entry(i).pc().description().write(fd, v);
282 unsigned pin = registry_entry.
user_arg >> 1;
283 if (pins_[pin]->direction() == Gpio::Direction::DINPUT)
285 SendProducerIdentified(registry_entry, event, done);
289 SendConsumerIdentified(registry_entry, event, done);
301 unsigned pin = registry_entry.
user_arg >> 1;
302 if (pins_[pin]->direction() == Gpio::Direction::DOUTPUT)
304 SendConsumerIdentified(registry_entry, event, done);
316 unsigned pin = registry_entry.
user_arg >> 1;
317 if (pins_[pin]->direction() == Gpio::Direction::DINPUT)
319 SendProducerIdentified(registry_entry, event, done);
332 if (pin->
direction() == Gpio::Direction::DOUTPUT)
334 const bool is_on = (registry_entry.
user_arg & 1);
340 using alloc_traits = std::allocator_traits<std::allocator<debouncer_type>>;
355 unsigned b1 = pins_[registry_entry.
user_arg >> 1]->is_set() ? 1 : 0;
356 unsigned b2 = registry_entry.
user_arg & 1;
361 event->event_write_helper<3>()->WriteAsync(node_, mti,
372 unsigned b1 = pins_[registry_entry.
user_arg >> 1]->is_set() ? 1 : 0;
373 unsigned b2 = registry_entry.
user_arg & 1;
378 event->event_write_helper<4>()->WriteAsync(node_, mti,
385 unsigned nextPinToPoll_;
394 const Gpio *
const *pins_;
401 EventId *producedEvents_;
#define CDI_GROUP(GroupName, ARGS...)
Starts a CDI group.
#define CDI_GROUP_ENTRY(NAME, TYPE, ARGS...)
Adds an entry to a CDI group.
#define CDI_FACTORY_RESET(PATH)
Performs factory reset on a CDI variable.
This class sends a notification in its destructor.
A BarrierNotifiable allows to create a number of child Notifiable and wait for all of them to finish.
BarrierNotifiable * new_child()
Call this for each child task.
Abstract class for components that need to receive configuration from EEPROM.
virtual void factory_reset(int fd)=0
Clears configuration file and resets the configuration settings to factory value.
UpdateAction
Specifies what additional steps are needed to apply the new configuration.
@ REINIT_NEEDED
Need to perform application-level reinitialization.
virtual UpdateAction apply_configuration(int fd, bool initial_load, BarrierNotifiable *done)=0
Notifies the component that there is new configuration available for loading.
virtual void register_update_listener(ConfigUpdateListener *listener)=0
Adds a config update listener to be called upon configuration updates.
virtual void unregister_update_listener(ConfigUpdateListener *listener)=0
Removes a config update listener.
OS-independent abstraction for GPIO.
virtual void write(Value new_state) const =0
Writes a GPIO output pin (set or clear to a specific state).
virtual Direction direction() const =0
Gets the GPIO direction.
An object that can schedule itself on an executor to run.
virtual void notify()=0
Generic callback.
This debouncer will update state if for N consecutive attempts the input value is the same.
static ConfigUpdateService * instance()
Class representing a particular location in the configuration space.
Defines an empty group with no members, but blocking a certain amount of space in the rendered config...
Implementation class for event ID configuration entries.
virtual void handle_identify_global(const EventRegistryEntry ®istry_entry, EventReport *event, BarrierNotifiable *done)=0
Called on the need of sending out identification messages.
virtual void handle_event_report(const EventRegistryEntry ®istry_entry, EventReport *event, BarrierNotifiable *done)=0
Called on incoming EventReport messages.
virtual void handle_identify_consumer(const EventRegistryEntry ®istry_entry, EventReport *event, BarrierNotifiable *done)=0
Called on another node sending IdentifyConsumer.
virtual void handle_identify_producer(const EventRegistryEntry ®istry_entry, EventReport *event, BarrierNotifiable *done)=0
Called on another node sending IdentifyProducer.
Structure used in registering event handlers.
uint32_t user_arg
Opaque user argument.
EventId event
Stores the event ID or beginning of range for which to register the given handler.
Base class for NMRAnet nodes conforming to the asynchronous interface.
Implementation class for numeric configuration entries, templated by the integer type.
Abstract base class for components that need repeated execution (with a specified frequency,...
virtual void poll_33hz(WriteHelper *helper, Notifiable *done)=0
This function will be called approximately 33 times per second by the refresh loop.
Defines a repeated group of a given type and a given number of repeats.
SimpleEventHandler ignores all non-essential callbacks.
Implementation class for string configuration entries.
A statically allocated buffer for sending one message to the OpenLCB bus.
#define OVERRIDE
Function attribute for virtual functions declaring that this funciton is overriding a funciton that s...
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
NumericConfigEntry< uint8_t > Uint8ConfigEntry
Unsigned numeric config entry with 1 byte width.
CDI_GROUP_END()
Signals termination of the group.
Payload eventid_to_buffer(uint64_t eventid)
Converts an Event ID to a Payload suitable to be sent as an event report.
MTI
Known Message type indicators.
@ MTI_PRODUCER_IDENTIFIED_VALID
producer broadcast, valid state
@ MTI_CONSUMER_IDENTIFIED_VALID
consumer broadcast, valid state
Shared notification structure that is assembled for each incoming event-related message,...
EventId event
The event ID from the incoming message.
Node * dst_node
nullptr for global messages; points to the specific virtual node for addressed events identify messag...