Skip to content

Commit 10229e2

Browse files
authored
Merge pull request #14 from kripton/DmxInputAsyncCallback
Dmx input async callback
2 parents 526b73b + dd7a31d commit 10229e2

File tree

3 files changed

+27
-2
lines changed

3 files changed

+27
-2
lines changed

README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,20 @@ Use the `.read(...)` method to read the 3 channels for our RGB fixture into our
9494

9595
The `.read(...)` method blocks until it receives a valid DMX packet. Much like the `DmxOutput`, the zero'th channel in the DMX packet is the start code. Unless you want to mess around with other protocols such as RDM, the start code can safely be ignored.
9696

97+
As an alternative to the blocking `.read(...)` method, you can also start asynchronous buffer updates via the
98+
`.read_async(...)` method. This way, the buffer is automatically updated when DMX data comes in.
99+
Optionally, you can also pass a pointer to a callback-function that will be called everytime a new DMX
100+
frame has been received, processed and has been written to the buffer.
101+
102+
```C++
103+
void dmxDataRecevied() {
104+
// A DMX frame has been received. Toggle some LED
105+
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
106+
}
107+
108+
myDmxInput.read_async(buffer, dmxDataRecevied);
109+
```
110+
97111
## Voltage Transceivers
98112
The Pico itself cannot be directly hooked up to your DMX line, as DMX operates on RS485 logic levels,
99113
which do not match the voltage levels of the GPIO pins on the Pico.

src/DmxInput.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ DmxInput::return_code DmxInput::begin(uint pin, uint start_channel, uint num_cha
8383
_start_channel = start_channel;
8484
_num_channels = num_channels;
8585
_buf = nullptr;
86+
_cb = nullptr;
8687

8788
_dma_chan = dma_claim_unused_channel(true);
8889

@@ -119,13 +120,20 @@ void dmxinput_dma_handler() {
119120
#else
120121
instance->_last_packet_timestamp = to_ms_since_boot(get_absolute_time());
121122
#endif
123+
// Trigger the callback if we have one
124+
if (instance->_cb != nullptr) {
125+
(*(instance->_cb))();
126+
}
122127
}
123128
}
124129
}
125130

126-
void DmxInput::read_async(volatile uint8_t *buffer) {
131+
void DmxInput::read_async(volatile uint8_t *buffer, void (*inputUpdatedCallback)(void)) {
127132

128133
_buf = buffer;
134+
if (inputUpdatedCallback!=nullptr) {
135+
_cb = inputUpdatedCallback;
136+
}
129137

130138
pio_sm_set_enabled(_pio, _sm, false);
131139

src/DmxInput.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class DmxInput
3535
volatile uint _sm;
3636
volatile uint _dma_chan;
3737
volatile unsigned long _last_packet_timestamp=0;
38+
void (*_cb)(void);
3839
/*
3940
All different return codes for the DMX class. Only the SUCCESS
4041
Return code guarantees that the DMX output instance was properly configured
@@ -82,8 +83,10 @@ class DmxInput
8283
/*
8384
Start async read process. This should only be called once.
8485
From then on, the buffer will always contain the latest DMX data.
86+
If you want to be notified whenever a new DMX frame has been received,
87+
provide a callback function that will be called without arguments.
8588
*/
86-
void read_async(volatile uint8_t *buffer);
89+
void read_async(volatile uint8_t *buffer, void (*inputUpdatedCallback)(void) = nullptr);
8790

8891
/*
8992
Get the timestamp (like millis()) from the moment the latest dmx packet was received.

0 commit comments

Comments
 (0)