Skip to content

Commit f5c08f5

Browse files
authored
Merge pull request #7 from PharosMarcusB/dmx_rx
Improve DMX RX
2 parents debaa4c + f28b327 commit f5c08f5

File tree

1 file changed

+105
-42
lines changed

1 file changed

+105
-42
lines changed

lib-dmx/src/gd32/dmx.cpp

Lines changed: 105 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@
5151

5252
#include "debug.h"
5353

54+
constexpr auto dmxSlotsCompleteFlag = 0x8000U;
55+
constexpr auto rdmSlotsCompleteFlag = 0x4000U;
56+
5457
extern struct HwTimersSeconds g_Seconds;
5558

5659
namespace dmx {
@@ -91,16 +94,20 @@ struct RxDmxData {
9194
uint32_t nSlotsInPacket;
9295
};
9396

97+
enum class ActiveBuffer { A, B };
98+
9499
struct RxData {
95100
struct {
96-
volatile RxDmxData current;
101+
volatile RxDmxData bufferA;
102+
volatile RxDmxData bufferB;
103+
ActiveBuffer active { ActiveBuffer::A }; // Active write buffer
97104
RxDmxData previous;
98105
} Dmx ALIGNED;
99106
struct {
100107
volatile uint8_t data[sizeof(struct TRdmMessage)] ALIGNED;
101108
volatile uint32_t nIndex;
102109
} Rdm ALIGNED;
103-
volatile TxRxState State;
110+
volatile TxRxState State { TxRxState::IDLE };
104111
} ALIGNED;
105112

106113
struct DirGpio {
@@ -158,29 +165,62 @@ static RxData sv_RxBuffer[dmx::config::max::PORTS] ALIGNED;
158165
static TxData s_TxBuffer[dmx::config::max::PORTS] ALIGNED SECTION_DMA_BUFFER;
159166
static DmxTransmit s_nDmxTransmit;
160167

168+
// The active DMX data buffer for writes
169+
volatile RxDmxData& getWriteDmxDataBuffer(const uint32_t nPortIndex) {
170+
if (sv_RxBuffer[nPortIndex].Dmx.active == ActiveBuffer::A) {
171+
return sv_RxBuffer[nPortIndex].Dmx.bufferA;
172+
}
173+
return sv_RxBuffer[nPortIndex].Dmx.bufferB;
174+
}
175+
176+
// The non-active DMX data buffer for reads
177+
volatile RxDmxData& getReadDmxDataBuffer(const uint32_t nPortIndex) {
178+
if (sv_RxBuffer[nPortIndex].Dmx.active == ActiveBuffer::A) {
179+
return sv_RxBuffer[nPortIndex].Dmx.bufferB;
180+
}
181+
return sv_RxBuffer[nPortIndex].Dmx.bufferA;
182+
}
183+
184+
// Swap the active buffer for writing
185+
void swapActiveDmxDataBuffer(const uint32_t nPortIndex) {
186+
if (sv_RxBuffer[nPortIndex].Dmx.active == ActiveBuffer::A) {
187+
sv_RxBuffer[nPortIndex].Dmx.active = ActiveBuffer::B;
188+
}
189+
else
190+
{
191+
sv_RxBuffer[nPortIndex].Dmx.active = ActiveBuffer::A;
192+
}
193+
}
194+
161195
template<uint32_t uart, uint32_t nPortIndex>
162196
void irq_handler_dmx_rdm_input() {
197+
auto& dmxDataBuffer = getWriteDmxDataBuffer(nPortIndex);
163198
const auto isFlagIdleFrame = (USART_REG_VAL(uart, USART_FLAG_IDLE) & BIT(USART_BIT_POS(USART_FLAG_IDLE))) == BIT(USART_BIT_POS(USART_FLAG_IDLE));
164199
/*
165200
* Software can clear this bit by reading the USART_STAT and USART_DATA registers one by one.
166201
*/
167202
if (isFlagIdleFrame) {
168203
static_cast<void>(GET_BITS(USART_RDATA(uart), 0U, 8U));
169-
170-
if (sv_RxBuffer[nPortIndex].State == TxRxState::DMXDATA) {
171-
sv_RxBuffer[nPortIndex].State = TxRxState::IDLE;
172-
sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket |= 0x8000;
173-
174-
return;
175-
}
176-
177-
if (sv_RxBuffer[0].State == TxRxState::RDMDISC) {
178-
sv_RxBuffer[nPortIndex].State = TxRxState::IDLE;
179-
sv_RxBuffer[nPortIndex].Rdm.nIndex |= 0x4000;
180-
181-
return;
204+
switch (sv_RxBuffer[nPortIndex].State)
205+
{
206+
case TxRxState::BREAK: break;
207+
case TxRxState::DMXDATA:
208+
{
209+
dmxDataBuffer.nSlotsInPacket |= dmxSlotsCompleteFlag;
210+
break;
211+
}
212+
case TxRxState::RDMDISC:
213+
{
214+
sv_RxBuffer[nPortIndex].State = TxRxState::IDLE;
215+
sv_RxBuffer[nPortIndex].Rdm.nIndex |= rdmSlotsCompleteFlag;
216+
break;
217+
}
218+
default:
219+
{
220+
sv_RxBuffer[nPortIndex].State = TxRxState::IDLE;
221+
break;
222+
}
182223
}
183-
184224
return;
185225
}
186226

@@ -191,15 +231,41 @@ void irq_handler_dmx_rdm_input() {
191231
if (isFlagFrameError) {
192232
static_cast<void>(GET_BITS(USART_RDATA(uart), 0U, 8U));
193233

194-
if (sv_RxBuffer[nPortIndex].State == TxRxState::IDLE) {
195-
sv_RxBuffer[nPortIndex].State = TxRxState::BREAK;
234+
switch (sv_RxBuffer[nPortIndex].State)
235+
{
236+
case TxRxState::RDMDISC:
237+
case TxRxState::IDLE:
238+
{
239+
break;
240+
}
241+
case TxRxState::DMXDATA:
242+
{
243+
if (!(dmxDataBuffer.nSlotsInPacket & dmxSlotsCompleteFlag)) {
244+
return;
245+
}
246+
break;
247+
}
248+
case TxRxState::RDMDATA:
249+
{
250+
if (!(sv_RxBuffer[nPortIndex].Rdm.nIndex & rdmSlotsCompleteFlag)) {
251+
return;
252+
}
253+
break;
254+
}
255+
default:
256+
{
257+
sv_RxBuffer[nPortIndex].State = TxRxState::IDLE;
258+
return;
259+
}
196260
}
197261

262+
sv_RxBuffer[nPortIndex].State = TxRxState::BREAK;
263+
swapActiveDmxDataBuffer(nPortIndex);
264+
198265
return;
199266
}
200267

201268
const auto data = static_cast<uint8_t>(GET_BITS(USART_RDATA(uart), 0U, 8U));
202-
203269
switch (sv_RxBuffer[nPortIndex].State) {
204270
case TxRxState::IDLE:
205271
sv_RxBuffer[nPortIndex].State = TxRxState::RDMDISC;
@@ -209,8 +275,8 @@ void irq_handler_dmx_rdm_input() {
209275
case TxRxState::BREAK:
210276
switch (data) {
211277
case START_CODE:
212-
sv_RxBuffer[nPortIndex].Dmx.current.data[0] = START_CODE;
213-
sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket = 1;
278+
dmxDataBuffer.data[0] = START_CODE;
279+
dmxDataBuffer.nSlotsInPacket = 1;
214280
sv_nRxDmxPackets[nPortIndex].nCount++;
215281
sv_RxBuffer[nPortIndex].State = TxRxState::DMXDATA;
216282
break;
@@ -220,21 +286,18 @@ void irq_handler_dmx_rdm_input() {
220286
sv_RxBuffer[nPortIndex].State = TxRxState::RDMDATA;
221287
break;
222288
default:
223-
sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket = 0;
289+
dmxDataBuffer.nSlotsInPacket = 0;
224290
sv_RxBuffer[nPortIndex].Rdm.nIndex = 0;
225291
sv_RxBuffer[nPortIndex].State = TxRxState::IDLE;
226292
break;
227293
}
228294
break;
229295
case TxRxState::DMXDATA: {
230-
auto nIndex = sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket;
231-
sv_RxBuffer[nPortIndex].Dmx.current.data[nIndex] = data;
232-
nIndex++;
233-
sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket = nIndex;
296+
dmxDataBuffer.nSlotsInPacket &= ~dmxSlotsCompleteFlag;
297+
dmxDataBuffer.data[dmxDataBuffer.nSlotsInPacket++] = data;
234298

235-
if (nIndex > dmx::max::CHANNELS) {
236-
nIndex |= 0x8000;
237-
sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket = nIndex;
299+
if (dmxDataBuffer.nSlotsInPacket > dmx::max::CHANNELS) {
300+
dmxDataBuffer.nSlotsInPacket |= dmxSlotsCompleteFlag;
238301
sv_RxBuffer[nPortIndex].State = TxRxState::IDLE;
239302
break;
240303
}
@@ -266,7 +329,7 @@ void irq_handler_dmx_rdm_input() {
266329
case TxRxState::CHECKSUML: {
267330
auto nIndex = sv_RxBuffer[nPortIndex].Rdm.nIndex;
268331
sv_RxBuffer[nPortIndex].Rdm.data[nIndex] = data;
269-
nIndex |= 0x4000;
332+
nIndex |= rdmSlotsCompleteFlag;
270333
sv_RxBuffer[nPortIndex].Rdm.nIndex = nIndex;
271334
sv_RxBuffer[nPortIndex].State = TxRxState::IDLE;
272335
gsv_RdmDataReceiveEnd = DWT->CYCCNT;
@@ -283,7 +346,7 @@ void irq_handler_dmx_rdm_input() {
283346
}
284347
break;
285348
default:
286-
sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket = 0;
349+
dmxDataBuffer.nSlotsInPacket = 0;
287350
sv_RxBuffer[nPortIndex].Rdm.nIndex = 0;
288351
sv_RxBuffer[nPortIndex].State = TxRxState::IDLE;
289352
break;
@@ -1960,11 +2023,12 @@ const uint8_t *Dmx::GetDmxChanged(const uint32_t nPortIndex) {
19602023
return nullptr;
19612024
}
19622025

1963-
const auto * __restrict__ pSrc32 = reinterpret_cast<const volatile uint32_t *>(sv_RxBuffer[nPortIndex].Dmx.current.data);
2026+
auto& dmxDataBuffer = getReadDmxDataBuffer(nPortIndex);
2027+
const auto * __restrict__ pSrc32 = reinterpret_cast<const volatile uint32_t *>(dmxDataBuffer.data);
19642028
auto * __restrict__ pDst32 = reinterpret_cast<uint32_t *>(sv_RxBuffer[nPortIndex].Dmx.previous.data);
19652029

1966-
if (sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket != sv_RxBuffer[nPortIndex].Dmx.previous.nSlotsInPacket) {
1967-
sv_RxBuffer[nPortIndex].Dmx.previous.nSlotsInPacket = sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket;
2030+
if (dmxDataBuffer.nSlotsInPacket != sv_RxBuffer[nPortIndex].Dmx.previous.nSlotsInPacket) {
2031+
sv_RxBuffer[nPortIndex].Dmx.previous.nSlotsInPacket = dmxDataBuffer.nSlotsInPacket;
19682032

19692033
for (size_t i = 0; i < buffer::SIZE / 4; ++i) {
19702034
pDst32[i] = pSrc32[i];
@@ -1994,24 +2058,23 @@ const uint8_t *Dmx::GetDmxChanged(const uint32_t nPortIndex) {
19942058
const uint8_t *Dmx::GetDmxAvailable([[maybe_unused]] const uint32_t nPortIndex) {
19952059
assert(nPortIndex < dmx::config::max::PORTS);
19962060
#if !defined(CONFIG_DMX_TRANSMIT_ONLY)
1997-
auto nSlotsInPacket = sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket;
19982061

1999-
if ((nSlotsInPacket & 0x8000) != 0x8000) {
2062+
auto& dmxDataBuffer = getReadDmxDataBuffer(nPortIndex);
2063+
if (!(dmxDataBuffer.nSlotsInPacket & dmxSlotsCompleteFlag)) {
20002064
return nullptr;
20012065
}
20022066

2003-
nSlotsInPacket &= ~0x8000;
2004-
nSlotsInPacket--; // Remove SC from length
2005-
sv_RxBuffer[nPortIndex].Dmx.current.nSlotsInPacket = nSlotsInPacket;
2067+
dmxDataBuffer.nSlotsInPacket &= ~dmxSlotsCompleteFlag;
2068+
dmxDataBuffer.nSlotsInPacket--; // Remove SC from length
20062069

2007-
return const_cast<const uint8_t *>(sv_RxBuffer[nPortIndex].Dmx.current.data);
2070+
return const_cast<const uint8_t *>(dmxDataBuffer.data);
20082071
#else
20092072
return nullptr;
20102073
#endif
20112074
}
20122075

20132076
const uint8_t *Dmx::GetDmxCurrentData(const uint32_t nPortIndex) {
2014-
return const_cast<const uint8_t *>(sv_RxBuffer[nPortIndex].Dmx.current.data);
2077+
return const_cast<const uint8_t *>(getReadDmxDataBuffer(nPortIndex).data);
20152078
}
20162079

20172080
uint32_t Dmx::GetDmxUpdatesPerSecond([[maybe_unused]] uint32_t nPortIndex) {
@@ -2247,7 +2310,7 @@ void Dmx::RdmSendDiscoveryRespondMessage(uint32_t nPortIndex, const uint8_t *pRd
22472310
const uint8_t *Dmx::RdmReceive(const uint32_t nPortIndex) {
22482311
assert(nPortIndex < dmx::config::max::PORTS);
22492312

2250-
if ((sv_RxBuffer[nPortIndex].Rdm.nIndex & 0x4000) != 0x4000) {
2313+
if (!(sv_RxBuffer[nPortIndex].Rdm.nIndex & rdmSlotsCompleteFlag)) {
22512314
return nullptr;
22522315
}
22532316

0 commit comments

Comments
 (0)