Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
DccAccyConsumer.hxx
Go to the documentation of this file.
1
36#ifndef _OPENLCB_DCCACCYCONSUMER_HXX_
37#define _OPENLCB_DCCACCYCONSUMER_HXX_
38
39#include "dcc/TrackIf.hxx"
42
43namespace openlcb
44{
45
48{
49protected:
54 : node_(node)
55 {
56 EventRegistry::instance()->register_handler(
59 12);
60 EventRegistry::instance()->register_handler(
63 12);
64 memset(lastSetState_, 0, sizeof(lastSetState_));
65 memset(isStateKnown_, 0, sizeof(isStateKnown_));
66 }
67
70 {
71 EventRegistry::instance()->unregister_handler(this);
72 }
73
74 void handle_identify_global(const EventRegistryEntry &registry_entry,
76 {
77 AutoNotify an(done);
78 if (event->dst_node && event->dst_node != node_)
79 {
80 return;
81 }
82 if (registry_entry.event ==
84 {
85 event->event_write_helper<1>()->WriteAsync(node_,
86 Defs::MTI_CONSUMER_IDENTIFIED_RANGE, WriteHelper::global(),
89 4095)),
90 done->new_child());
91 }
92 if (registry_entry.event ==
94 {
95 event->event_write_helper<2>()->WriteAsync(node_,
96 Defs::MTI_CONSUMER_IDENTIFIED_RANGE, WriteHelper::global(),
99 4095)),
100 done->new_child());
101 }
102 }
103
104 void handle_event_report(const EventRegistryEntry &registry_entry,
105 EventReport *event, BarrierNotifiable *done) override
106 {
107 AutoNotify an(done);
108 if (!parse_event(event->event))
109 {
110 return;
111 }
112 uint32_t m = (1U) << eventMask_;
114 if (normalReverse_)
115 {
117 }
118 else
119 {
121 }
122
124 }
125
127 EventReport *event, BarrierNotifiable *done) override
128 {
129 AutoNotify an(done);
130 if (!parse_event(event->event))
131 {
132 return;
133 }
134 uint32_t m = (1U) << eventMask_;
135 EventState s;
136 if (isStateKnown_[eventOfs_] & m)
137 {
138 if (lastSetState_[eventOfs_] & m)
139 {
140 // normal
141 s = EventState::VALID;
142 }
143 else
144 {
145 // reversed
146 s = EventState::INVALID;
147 }
148 if (normalReverse_ != 1)
149 {
150 // query was reversed. invert the event state
151 s = invert_event_state(s);
152 }
153 }
154 else
155 {
156 s = EventState::UNKNOWN;
157 }
159 event->event_write_helper<1>()->WriteAsync(node_, mti,
160 WriteHelper::global(), eventid_to_buffer(event->event),
161 done->new_child());
162 }
163
165 virtual void send_accy_command() = 0;
166
175 bool parse_event(EventId event)
176 {
178 event <
180 {
181 onOff_ = 1;
184 }
185 else if (event >=
187 event <
189 {
190 onOff_ = 0;
193 }
194 else
195 {
196 return false;
197 }
199 eventOfs_ = dccAddress_ >> 6;
200 eventMask_ = (dccAddress_ >> 1) & 31;
201 return true;
202 }
203
205 unsigned onOff_ : 1;
207 unsigned normalReverse_ : 1;
209 unsigned dccAddress_ : 12;
211 unsigned eventOfs_ : 6;
214 unsigned eventMask_ : 5;
215
218 uint32_t lastSetState_[64];
222 uint32_t isStateKnown_[64];
223
226};
227
230{
231public:
238 : DccAccyConsumerBase(node)
239 , track_(track)
240 {
241 }
242
245 {
246 }
247
248private:
250 void send_accy_command() override
251 {
253 mainBufferPool->alloc(&pkt);
254 pkt->data()->add_dcc_basic_accessory(dccAddress_, onOff_);
255 pkt->data()->packet_header.rept_count = 3;
256 track_->send(pkt);
257 }
258
261};
262
267{
268protected:
270 static constexpr unsigned NUM_ADDRESS = 2048;
272 static constexpr unsigned NUM_ASPECT = 256;
274 static constexpr unsigned NUM_EVENT = NUM_ASPECT * NUM_ADDRESS;
275
280 : node_(node)
281 {
282 EventRegistry::instance()->register_handler(
285 11+8 /*number of bits*/);
286 }
287
290 {
291 EventRegistry::instance()->unregister_handler(this);
292 }
293
294 void handle_identify_global(const EventRegistryEntry &registry_entry,
296 {
297 AutoNotify an(done);
298 if (event->dst_node && event->dst_node != node_)
299 {
300 return;
301 }
302 event->event_write_helper<1>()->WriteAsync(node_,
303 Defs::MTI_CONSUMER_IDENTIFIED_RANGE, WriteHelper::global(),
306 done->new_child());
307 }
308
309 void handle_event_report(const EventRegistryEntry &registry_entry,
310 EventReport *event, BarrierNotifiable *done) override
311 {
312 AutoNotify an(done);
313 if (!parse_event(event->event))
314 {
315 return;
316 }
318 }
319
321 EventReport *event, BarrierNotifiable *done) override
322 {
323 AutoNotify an(done);
324 if (!parse_event(event->event))
325 {
326 return;
327 }
328 event->event_write_helper<1>()->WriteAsync(node_,
329 Defs::MTI_CONSUMER_IDENTIFIED_UNKNOWN, WriteHelper::global(),
330 eventid_to_buffer(event->event), done->new_child());
331 }
332
334 virtual void send_accy_command() = 0;
335
344 bool parse_event(EventId event)
345 {
347 event <
349 {
350 aspect_ = event & 0xff;
351 dccAddress_ = (event >> 8) & (NUM_ADDRESS - 1);
352 return true;
353 }
354 else
355 {
356 return false;
357 }
358 }
359
360
362 unsigned dccAddress_ : 11;
364 unsigned aspect_ : 8;
365
368};
369
373{
374public:
382 , track_(track)
383 {
384 }
385
388 {
389 }
390
391private:
393 void send_accy_command() override
394 {
396 mainBufferPool->alloc(&pkt);
397 pkt->data()->add_dcc_ext_accessory(dccAddress_, aspect_);
398 pkt->data()->packet_header.rept_count = 3;
399 track_->send(pkt);
400 }
401
404};
405
406
407} // namespace openlcb
408
409#endif // _OPENLCB_DCCACCYCONSUMER_HXX_
DynamicPool * mainBufferPool
main buffer pool instance
Definition Buffer.cxx:37
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.
Base class for all QMember types that hold data in an expandable format.
Definition Buffer.hxx:195
T * data()
get a pointer to the start of the data.
Definition Buffer.hxx:215
virtual void send(MessageType *message, unsigned priority=UINT_MAX)=0
Entry point to the flow.
void alloc(Buffer< BufferType > **result, Executable *flow=NULL)
Get a free item out of the pool.
Definition Buffer.hxx:292
static EventRegistry * instance()
Definition Singleton.hxx:77
Base (generic protocol) implementation of a DCC accessory consumer.
unsigned onOff_
Parsed event state: 1 = activate (C=1), 2 = deactivate (C=0).
virtual void send_accy_command()=0
Send the actual accessory command.
uint32_t isStateKnown_[64]
each bit determines whether we've sent a command to that accessory address yet or not.
unsigned eventMask_
Parsed event state: bit index (0..31) in the uint32 in the state_ array entry pointed to by eventOfs_...
unsigned eventOfs_
Parsed event state: offset in the state_ array.
DccAccyConsumerBase(Node *node)
Constructs a listener for DCC accessory control.
unsigned dccAddress_
Parsed event state: dcc address (0..4095) without inverting or encoding.
unsigned normalReverse_
Parsed event state: 1 = normal (D0=1), 0 = reversed (D0=0).
void handle_identify_consumer(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on another node sending IdentifyConsumer.
uint32_t lastSetState_[64]
each bit determines what the last command sent to the accessory address was.
bool parse_event(EventId event)
Parses an event into an openlcb accessory offset.
void handle_event_report(const EventRegistryEntry &registry_entry, EventReport *event, BarrierNotifiable *done) override
Called on incoming EventReport messages.
Node * node_
OpenLCB node to export the consumer on.
void handle_identify_global(const EventRegistryEntry &registry_entry, EventReport *event, BarrierNotifiable *done) OVERRIDE
Called on the need of sending out identification messages.
Specialized (DCC protocol) implementation of a DCC accessory consumer.
dcc::TrackIf * track_
Track to send DCC packets to.
DccAccyConsumer(Node *node, dcc::TrackIf *track)
Constructs a listener for DCC accessory control.
void send_accy_command() override
Send the actual accessory command.
Base (generic protocol) implementation of the DCC extended accessory consumer.
static constexpr unsigned NUM_ADDRESS
How may addresses are there for extended accessories.
void handle_event_report(const EventRegistryEntry &registry_entry, EventReport *event, BarrierNotifiable *done) override
Called on incoming EventReport messages.
static constexpr unsigned NUM_ASPECT
How may aspects are supported per accessory.
void handle_identify_global(const EventRegistryEntry &registry_entry, EventReport *event, BarrierNotifiable *done) OVERRIDE
Called on the need of sending out identification messages.
void handle_identify_consumer(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on another node sending IdentifyConsumer.
static constexpr unsigned NUM_EVENT
Total number of events we are listening for.
unsigned aspect_
Parsed event state: the aspect commanded.
Node * node_
OpenLCB node to export the consumer on.
unsigned dccAddress_
Parsed event state: dcc address (0..2047) without inverting or encoding.
DccExtAccyConsumerBase(Node *node)
Constructs a listener for DCC extended accessory control.
virtual void send_accy_command()=0
Send the actual accessory command.
bool parse_event(EventId event)
Parses an event into an openlcb accessory offset.
Specialized (DCC protocol) implementation of a DCC extended accessory consumer.
DccExtAccyConsumer(Node *node, dcc::TrackIf *track)
Constructs a listener for DCC accessory control.
dcc::TrackIf * track_
Track to send DCC packets to.
void send_accy_command() override
Send the actual accessory command.
Structure used in registering event handlers.
Base class for NMRAnet nodes conforming to the asynchronous interface.
Definition Node.hxx:52
SimpleEventHandler ignores all non-essential callbacks.
#define OVERRIDE
Function attribute for virtual functions declaring that this funciton is overriding a funciton that s...
Definition macros.h:180
uint64_t EncodeRange(uint64_t begin, unsigned size)
Creates a single encoded event range from the beginning of the range and the number fo events to cove...
EventState invert_event_state(EventState state)
Returns the inverted event state, switching valid and invalid, but not changing unknown and reserved.
EventState
Allowed states of producers and consumers.
Payload eventid_to_buffer(uint64_t eventid)
Converts an Event ID to a Payload suitable to be sent as an event report.
Definition If.cxx:72
MTI
Known Message type indicators.
@ MTI_CONSUMER_IDENTIFIED_UNKNOWN
consumer broadcast, validity unknown
@ MTI_CONSUMER_IDENTIFIED_VALID
consumer broadcast, valid state
@ MTI_CONSUMER_IDENTIFIED_RANGE
consumer broadcast about a range of consumers
Shared notification structure that is assembled for each incoming event-related message,...
EventId event
The event ID from the incoming message.
static constexpr uint64_t INACTIVATE_BASIC_DCC_ACCESSORY_EVENT_BASE
Base address of DCC accessory decoder well-known event range (inactive)
static constexpr uint64_t EXT_DCC_ACCESSORY_EVENT_BASE
Base address of DCC extended accessory decoder well-known event range.
static constexpr uint64_t ACTIVATE_BASIC_DCC_ACCESSORY_EVENT_BASE
Base address of DCC accessory decoder well-known event range (active)