Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
DccAccyProducer.hxx
Go to the documentation of this file.
1
37#ifndef _OPENLCB_DCCACCYPRODUCER_HXX_
38#define _OPENLCB_DCCACCYPRODUCER_HXX_
39
40#include <vector>
41
43#include "openlcb/NonAuthoritativeEventProducer.hxx"
46
47namespace openlcb
48{
52{
54 enum Query
55 {
57 };
58
60 enum Set
61 {
63 };
64};
65
70{
73 {
76 };
77
81 const uint16_t address)
82 {
84 address_ = address;
85 }
86
90 void reset(const DccAccyProducerCommands::Set &, const uint16_t address,
91 bool value)
92 {
93 cmd_ = CMD_SET;
94 address_ = address;
95 value_ = value;
96 }
97
99 uint16_t address_;
100 bool value_;
101};
102
106class DccAccyProducer : public CallableFlow<DccAccyProducerInput>
107{
108public:
110 enum Route
111 {
112 NORMAL = false,
113 REVERSE = true,
114 };
115
117 static constexpr uint16_t MAX_ADDRESS = 2044;
118
129 std::function<void(unsigned, bool)> dcc_state_callback = nullptr)
130 : CallableFlow<DccAccyProducerInput>(node->iface())
131 , dccStateCallback_(dcc_state_callback)
132 , writer_()
133 , bn_()
134 {
135 once_.once();
137 if (instances_->empty())
138 {
139 uint32_t max_address = MAX_ADDRESS;
140 eventProducer_.emplace(
141 node,
143 max_address, state_callback);
144 }
145 instances_->push_back(this);
146 }
147
150 {
152 for (unsigned i = 0; i < instances_->size(); ++i)
153 {
154 if (instances_->at(i) == this)
155 {
156 instances_->erase(instances_->begin() + i);
157 break;
158 }
159 }
160 if (instances_->empty())
161 {
162 eventProducer_.reset();
163 }
164 }
165
166private:
167 using Command = DccAccyProducerInput::Command;
168
171 static void once_routine()
172 {
173 instances_.emplace();
174 }
175
181 Action entry() override
182 {
183 HASSERT(input()->address_ > 0 && input()->address_ <= MAX_ADDRESS);
184 switch (input()->cmd_)
185 {
186 case Command::CMD_QUERY:
188 case Command::CMD_SET:
189 return call_immediately(STATE(set));
190 default:
191 return return_with_error(Defs::ERROR_INVALID_ARGS);
192 }
193 }
194
201 {
202 eventProducer_->send_query_consumer(input()->address_ - 1, &writer_,
203 bn_.reset(this));
204 return wait_and_return_ok();
205 }
206
213 {
214 eventProducer_->set(input()->address_ - 1, input()->value_, &writer_,
215 bn_.reset(this));
216 return wait_and_return_ok();
217 }
218
223 {
224 return message()->data();
225 }
226
233 static void state_callback(unsigned bit, bool value)
234 {
237 for (unsigned i = 0; i < instances_->size(); ++i)
238 {
239 if (instances_->at(i)->dccStateCallback_)
240 {
241 instances_->at(i)->dccStateCallback_(bit + 1, value);
242 }
243 }
244 }
245
249
253
256
259
262 std::function<void(unsigned, bool)> dccStateCallback_;
263
266
268};
269
270} // namespace openlcb
271
272#endif // _OPENLCB_DCCACCYPRODUCER_HXX_
#define STATE(_fn)
Turns a function name into an argument to be supplied to functions expecting a state.
Definition StateFlow.hxx:61
See OSMutexLock in os/OS.hxx.
Definition Atomic.hxx:153
Lightweight locking class for protecting small critical sections.
Definition Atomic.hxx:130
A BarrierNotifiable allows to create a number of child Notifiable and wait for all of them to finish.
BarrierNotifiable * reset(Notifiable *done)
Resets the barrier. Returns &*this. Asserts that is_done().
Action wait_and_return_ok()
Waits to be notified before moving onto the next state for termination.
Action return_with_error(int error)
Terminates the flow and returns the request buffer to the caller with an specific error code.
This class provides support for one time initialization.
Definition OS.hxx:206
int once(void)
call one time intialization routine
Definition OS.hxx:220
Return type for a state flow callback.
Action call_immediately(Callback c)
Imediately call the next state upon return.
DCC accessory address event producer for the Well-Known DCC Accessory range.
Action entry() override
Entry point to sub-flow that dispatches the next state based on the incoming command.
Route
DCC accessory activation values.
DccAccyProducer(Node *node, std::function< void(unsigned, bool)> dcc_state_callback=nullptr)
Constructor.
~DccAccyProducer()
Destructor. Remove "this" instance from instances_ vector.
static OSThreadOnce once_
one time execution helper
static uninitialized< BitRangeNonAuthoritativeEventP > eventProducer_
Singleton instance of a BitRangeNonAuthoritativeEventP for the DCC accessory address Well-Known Event...
static uninitialized< std::vector< DccAccyProducer * > > instances_
Vector of all the subscribers to the DCC accessory address Well-Known Event ID Range.
static void once_routine()
Called once.
static void state_callback(unsigned bit, bool value)
Callback called when there is a notification of event (DCC accessory address) state.
std::function< void(unsigned, bool)> dccStateCallback_
Callback method that will be invoked when a consumer identified message is received with a known stat...
BarrierNotifiable bn_
notfiable for unblocking the next state
Action query()
Query the last known state of the accessory address.
WriteHelper writer_
statically allocated buffer
Action set()
Set the state of the accessory address.
DccAccyProducerInput * input()
Helper method for accessing the subflow input data.
static Atomic instancesLock_
This lock protects the instances_ vector;.
static constexpr uint16_t MAX_ADDRESS
highest possible DCC address supported
Base class for NMRAnet nodes conforming to the asynchronous interface.
Definition Node.hxx:52
A statically allocated buffer for sending one message to the OpenLCB bus.
Template class that allows allocating storage for an object but not calling its constructor.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Removes default copy-constructor and assignment added by C++.
Definition macros.h:171
All callable flow request objects have to derive from this struct.
C++ Namespace for collecting all commands that can be sent to the DccAccyProducer flow.
Request structure used to send requests to the DccAccyProducer class.
void reset(const DccAccyProducerCommands::Set &, const uint16_t address, bool value)
Reset method for CMD_SET.
bool value_
DCC accessory address value.
Command cmd_
subflow command
void reset(const DccAccyProducerCommands::Query &, const uint16_t address)
Reset method for CMD_QUERY.
Command
Possible subflow commands.
uint16_t address_
DCC accessory address.
static constexpr uint64_t ACTIVATE_BASIC_DCC_ACCESSORY_EVENT_BASE
Base address of DCC accessory decoder well-known event range (active)