35#define _DEFAULT_SOURCE
47extern int debug_variables;
48int debug_variables = 0;
52extern const string &GetNameForEvent(uint64_t);
54__attribute__((weak))
const string &GetNameForEvent(uint64_t)
66 uint32_t *backing_store,
unsigned size)
67 : event_base_(event_base)
69 , data_(backing_store)
77BitRangeEventPC::~BitRangeEventPC()
82void BitRangeEventPC::GetBitAndMask(
unsigned bit, uint32_t **data,
88 *data = data_ + (bit >> 5);
89 *mask = 1 << (bit & 31);
97 GetBitAndMask(bit, &ofs, &mask);
100 return (*ofs) & mask;
109 GetBitAndMask(bit, &ofs, &mask);
110 bool old_value = new_value;
113 old_value = (*ofs) & mask;
114 if (old_value != new_value)
119 fprintf(stderr,
"BitRange: OUT bit %x (%s) to %d\n", bit,
120 GetNameForEvent(event_base_ + (bit * 2)).c_str(),
124 LOG(
VERBOSE,
"BitRange: set bit %x to %d", bit, new_value);
134 uint64_t
event = event_base_ + bit * 2;
137 writer->
WriteAsync(node_, Defs::MTI_EVENT_REPORT, WriteHelper::global(),
139#ifndef TARGET_LPC11Cxx
147 while (EventService::instance->event_processing_pending())
157 if (debug_variables > 2)
159 fprintf(stderr,
"BitRange: out bit %x (%s) to %d\n", bit,
160 GetNameForEvent(event_base_ + (bit * 2)).c_str(),
173 if (event->
event < event_base_)
175 uint64_t d = (
event->event - event_base_);
176 bool new_value = !(d & 1);
184 fprintf(stderr,
"BitRange: IN bit %x (%s) to %d\n", bit,
185 GetNameForEvent(event_base_ + (2 * bit)).c_str(), new_value);
188 LOG(
VERBOSE,
"BitRange: evt bit %x to %d", bit, new_value);
191 uint32_t *ofs =
nullptr;
193 GetBitAndMask(bit, &ofs, &mask);
215void BitRangeEventPC::HandleIdentifyBase(
Defs::MTI mti_valid,
219 if (event->
event < event_base_)
221 uint64_t d = (
event->event - event_base_);
222 bool new_value = !(d & 1);
226 uint32_t *ofs =
nullptr;
228 GetBitAndMask(d, &ofs, &mask);
230 bool old_value = *ofs & mask;
231 if (old_value != new_value)
236 event->event_write_helper<1>()->WriteAsync(node_, mti,
243 uint64_t end = begin + size - 1;
245 while ((begin + shift) < end)
270 uint64_t range =
EncodeRange(event_base_, size_ * 2);
271 event->event_write_helper<1>()->WriteAsync(node_,
274 event->event_write_helper<2>()->WriteAsync(node_,
283 uint64_t range =
EncodeRange(event_base_, size_ * 2);
296 uint64_t range =
EncodeRange(event_base_, size_ * 2);
297 event->event_write_helper<1>()->WriteAsync(node_,
304 uint8_t *backing_store,
unsigned size)
305 : event_base_(event_base)
307 , data_(backing_store)
315ByteRangeEventC::~ByteRangeEventC()
331 fprintf(stderr,
"ByteRange: IN byte %" PRIxPTR
" to %d\n", storage - data_,
335 LOG(
VERBOSE,
"ByteRange: evt %x to %d", (
unsigned)(storage - data_), value);
346 if (event < event_base_)
348 event -= event_base_;
349 *value =
event & 0xff;
353 *storage = data_ + event;
367 if (*storage != value)
371 event->event_write_helper<1>()->WriteAsync(node_, mti,
382 uint64_t range =
EncodeRange(event_base_, size_ * 256);
383 event->event_write_helper<1>()->WriteAsync(node_,
392 uint64_t range =
EncodeRange(event_base_, size_ * 256);
398 uint8_t *backing_store,
unsigned size)
418 return event_base_ + (
byte << 8) + data_[
byte];
431 if (*storage != value)
438 event->event_write_helper<1>()->WriteAsync(node_, mti,
450 uint64_t range =
EncodeRange(event_base_, size_ * 256);
451 event->event_write_helper<1>()->WriteAsync(node_,
459 uint64_t range =
EncodeRange(event_base_, size_ * 256);
469 writer->
WriteAsync(node_, Defs::MTI_EVENT_REPORT, WriteHelper::global(),
491 if (event->
event + event->
mask < event_base_)
495 if (event->
event >= event_base_ + size_ * 256)
499 unsigned start_offset = 0;
500 unsigned end_offset = 0;
509 start_offset = storage - data_;
517 end_offset = storage - data_ + 1;
519 unsigned cur = start_offset;
520 if (cur < end_offset)
524 if (cur < end_offset)
528 if (cur < end_offset)
532 if (cur < end_offset)
548 if ((event_on ^ event_off) == 1ULL)
551 uint64_t
id = event_on & (~1ULL);
552 unsigned user_data = 0;
580 event->event_write_helper<1>()->WriteAsync(bit_->
node(), mti,
584 event->event_write_helper<2>()->WriteAsync(bit_->
node(), mti,
594 event->event_write_helper<3>()->WriteAsync(bit_->
node(), mti,
598 event->event_write_helper<4>()->WriteAsync(bit_->
node(), mti,
607 if (value == EventState::VALID) {
609 }
else if (value == EventState::INVALID) {
612 DIE(
"Requested sending event report for a bit event that is in unknown "
645 event->event_write_helper<1>()->WriteAsync(bit_->
node(), mti,
654 if (event->
state == EventState::VALID)
658 else if (event->
state == EventState::INVALID)
683 WriteHelper::global(),
704 WriteHelper::global(),
751 WriteHelper::global(),
772 if (event->
state == EventState::VALID)
776 else if (event->
state == EventState::INVALID)
A BarrierNotifiable allows to create a number of child Notifiable and wait for all of them to finish.
void notify() override
Implementation of the barrier semantics.
void maybe_done()
When there are no more child tasks to add, call maybe_done().
BarrierNotifiable * new_child()
Call this for each child task.
An object that can schedule itself on an executor to run.
static EventRegistry * instance()
void handle_identify_global(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on the need of sending out identification messages.
void handle_event_report(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on incoming EventReport messages.
void handle_identify_consumer(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on another node sending IdentifyConsumer.
void SendQuery(WriteHelper *writer, BarrierNotifiable *done)
Queries producers and acquires the current state of the bit.
void handle_producer_identified(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on another node sending ProducerIdentified for this event.
void SendConsumerIdentified(EventReport *event, BarrierNotifiable *done)
Sends off two packets using event_write_helper{3,4} of ConsumerIdentified for handling a global ident...
void unregister_handler()
Removes this event handler from the global event manager.
void register_handler(uint64_t event_on, uint64_t event_off)
Registers this event handler with the global event manager.
void SendEventReport(WriteHelper *writer, Notifiable *done)
Requests the event associated with the current value of the bit to be produced (unconditionally): sen...
void SendProducerIdentified(EventReport *event, BarrierNotifiable *done)
Sends off two packets using event_write_helper{1,2} of ProducerIdentified for handling a global ident...
void HandlePCIdentify(Defs::MTI mti_valid, EventReport *event, BarrierNotifiable *done)
Checks if the event in the report is something we are interested in, and if so, sends off a {Producer...
@ BOTH_ON_IS_ZERO
This registration is for two events, and the lower numbered is the event on.
@ EVENT_ON
This registration is for a single event_on.
@ EVENT_OFF
This registration is for a single event_off.
@ BOTH_OFF_IS_ZERO
This registration is for two events, and the lower numbered is the event off.
Represents a bit of state using two events.
uint64_t event_on()
returns the event ID for representing the state transition OFF->ON.
virtual void set_state(bool new_value)=0
Updates the hardware for the new event state.
virtual EventState get_requested_state()
Get the requested state.
uint64_t event_off()
returns the event ID for representing the state transition ON->OFF.
virtual Node * node()=0
returns the OpenLCB virtual node from which to send the respective events when the bit changes.
virtual EventState get_current_state()=0
returns the current hardware state: true for ON, false for OFF.
void handle_identify_global(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on the need of sending out identification messages.
void SendQueryConsumer(WriteHelper *writer, BarrierNotifiable *done)
Queries consumer and acquires the current state of the bit.
void handle_identify_producer(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on another node sending IdentifyProducer.
void handle_consumer_identified(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on another node sending ConsumerIdentified for this event.
void SendQuery(WriteHelper *writer, BarrierNotifiable *done)
Queries consumers and acquires the current state of the bit.
void handle_identify_producer(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on another node sending IdentifyProducer.
void handle_identify_global(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on the need of sending out identification messages.
void handle_identify_producer(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on another node sending IdentifyProducer.
void handle_identify_consumer(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on another node sending IdentifyConsumer.
void handle_identify_global(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on the need of sending out identification messages.
BitRangeEventPC(Node *node, uint64_t event_base, uint32_t *backing_store, unsigned size)
Creates a new bit range listener.
bool Get(unsigned bit) const
void SendIdentified(WriteHelper *writer, BarrierNotifiable *done)
Sends out a ProducerRangeIdentified.
void handle_event_report(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on incoming EventReport messages.
void Set(unsigned bit, bool new_value, WriteHelper *writer, BarrierNotifiable *done)
Requests the event associated with the current value of the bit to be produced (unconditionally).
void handle_identify_global(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on the need of sending out identification messages.
Consumer event handler for a sequence of bytes represented by a dense block of consecutive event IDs.
void handle_event_report(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on incoming EventReport messages.
void handle_identify_consumer(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on another node sending IdentifyConsumer.
bool DecodeEventId(uint64_t event_id, uint8_t **data, uint8_t *value)
takes an event ID and checks if we are responsible for it.
void handle_identify_global(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on the need of sending out identification messages.
void SendIdentified(WriteHelper *writer, BarrierNotifiable *done)
Sends out a ConsumerRangeIdentified.
ByteRangeEventC(Node *node, uint64_t event_base, uint8_t *backing_store, unsigned size)
Creates a new byte range listener.
virtual void notify_changed(unsigned offset)
This function is called by the handler when a data value overwrite event arrives.
void handle_identify_consumer(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on another node sending IdentifyConsumer.
void handle_identify_global(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on the need of sending out identification messages.
void Update(unsigned byte, WriteHelper *writer, BarrierNotifiable *done)
Requests the event associated with the current value of a specific byte to be produced (unconditional...
ByteRangeEventP(Node *node, uint64_t event_base, uint8_t *backing_store, unsigned size)
Creates a new byte range producer.
uint64_t CurrentEventId(unsigned byte)
Creates the eventid of the currently valid value of a given byte.
void SendIdentified(WriteHelper *writer, BarrierNotifiable *done)
Sends out a ProducerRangeIdentified.
void handle_identify_producer(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on another node sending IdentifyProducer.
void handle_consumer_identified(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on another node sending ConsumerIdentified for this event.
void handle_event_report(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on incoming EventReport messages.
void handle_consumer_range_identified(const EventRegistryEntry &entry, EventReport *event, BarrierNotifiable *done) override
Called on another node sending ConsumerRangeIdentified.
Structure used in registering event handlers.
static unsigned align_mask(EventId *event, unsigned size)
Computes the alignment mask for registering an event range.
Base class for NMRAnet nodes conforming to the asynchronous interface.
A statically allocated buffer for sending one message to the OpenLCB bus.
void WriteAsync(Node *node, Defs::MTI mti, NodeHandle dst, const payload_type &buffer, Notifiable *done)
Originates an NMRAnet message from a particular node.
#define LOG(level, message...)
Conditionally write a message to the logging output.
static const int VERBOSE
Loglevel that is usually not printed, reporting debugging information.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
#define DIE(MSG)
Unconditionally terminates the current process with a message.
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.
MTI
Known Message type indicators.
@ MTI_PRODUCER_IDENTIFY
query about producers
@ MTI_PRODUCER_IDENTIFIED_RANGE
producer broadcast about a range of producers
@ MTI_PRODUCER_IDENTIFIED_VALID
producer broadcast, valid state
@ MTI_CONSUMER_IDENTIFY
query about consumers
@ 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 mask
Specifies the mask in case the request is for an event range.
EventState state
For producer/consumer identified messages, specifies the state of the producer/consumer as the sender...
NodeHandle src_node
Information about the sender of the incoming event-related OpenLCB 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...
WriteHelper * event_write_helper()
These allow event handlers to produce up to four messages per invocation.
NodeID id
48-bit NMRAnet Node ID