Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 48 additions & 40 deletions DmxReceiver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,25 @@

#include "mk20dx128.h"
#include "DmxReceiver.h"
#include "HardwareSerial.h"

#define DMX_BUFFER_SIZE 513
#include "Arduino.h"

#ifndef UART_C3_FEIE
#define UART_C3_FEIE (uint8_t)0x02 // Framing Error Interrupt Enable
#endif

static volatile uint8_t dmxBuffer1[DMX_BUFFER_SIZE];
static volatile uint8_t dmxBuffer2[DMX_BUFFER_SIZE];
static volatile uint8_t *activeBuffer;
static volatile uint8_t *inactiveBuffer;
static volatile uint16_t dmxBufferIndex;
static volatile unsigned int frameCount=0;
static volatile bool newFrame=false;
HardwareSerial Uart = HardwareSerial();

void DmxReceiver::begin(void)
DmxReceiverClass::DmxReceiverClass() :
Uart(),
m_dmxBuffer1({0}),
m_dmxBuffer2({0}),
m_activeBuffer(m_dmxBuffer1),
m_inactiveBuffer(m_dmxBuffer2),
m_dmxBufferIndex(0),
m_frameCount(0),
m_newFrame(false)
{ }

void DmxReceiverClass::begin(void)
{
// UART Initialization
Uart.begin(250000);
Expand All @@ -58,65 +59,72 @@ void DmxReceiver::begin(void)
UART0_C3 |= UART_C3_FEIE;
NVIC_ENABLE_IRQ(IRQ_UART0_ERROR);

activeBuffer = dmxBuffer1;
inactiveBuffer = dmxBuffer2;
m_activeBuffer = m_dmxBuffer1;
m_inactiveBuffer = m_dmxBuffer2;
}

void DmxReceiver::end(void)
void DmxReceiverClass::end(void)
{
Uart.end();
NVIC_DISABLE_IRQ(IRQ_UART0_ERROR);
}

void DmxReceiver::fill(uint8_t v)
void DmxReceiverClass::fill(uint8_t v)
{
__disable_irq();
dmxBuffer1[0] = 0;
memset((void *)(dmxBuffer1 + 1), v, DMX_BUFFER_SIZE - 1);
dmxBuffer2[0] = 0;
memset((void *)(dmxBuffer2 + 1), v, DMX_BUFFER_SIZE - 1);
m_dmxBuffer1[0] = 0;
memset((void *)(m_dmxBuffer1 + 1), v, DMX_BUFFER_SIZE - 1);
m_dmxBuffer2[0] = 0;
memset((void *)(m_dmxBuffer2 + 1), v, DMX_BUFFER_SIZE - 1);
__enable_irq();
}

void DmxReceiver::clear(void)
void DmxReceiverClass::clear(void)
{
fill(0);
}

unsigned int DmxReceiver::frameCount(void)
unsigned int DmxReceiverClass::frameCount(void)
{
return ::frameCount;
return m_frameCount;
}

uint8_t DmxReceiver::getDimmer(uint16_t d)
uint8_t DmxReceiverClass::getDimmer(uint16_t d)
{
return inactiveBuffer[d];
return m_inactiveBuffer[d];
}

int DmxReceiver::bufferService (void)
volatile uint8_t* DmxReceiverClass::getBuffer()
{
return m_inactiveBuffer;
}

int DmxReceiverClass::bufferService (void)
{
__disable_irq(); //Prevents conflicts with the UART0 error ISR
int available=Uart.available();
int retval=available;
while (available--)
{
activeBuffer[dmxBufferIndex]=Uart.read();
if (dmxBufferIndex<(DMX_BUFFER_SIZE-1)) dmxBufferIndex++;
m_activeBuffer[m_dmxBufferIndex]=Uart.read();
if (m_dmxBufferIndex<(DMX_BUFFER_SIZE-1)) m_dmxBufferIndex++;
}
__enable_irq();
return retval;
}

bool DmxReceiver::newFrame(void)
bool DmxReceiverClass::newFrame(void)
{
if (::newFrame)
if (m_newFrame)
{
::newFrame=false;
m_newFrame=false;
return true;
}
return false;
}

DmxReceiverClass DmxReceiver;

// UART0 will throw a frame error on the DMX break pulse. That's our
// cue to switch buffers and reset the index to zero
void uart0_error_isr(void)
Expand All @@ -130,20 +138,20 @@ void uart0_error_isr(void)

// Ensure we've processed all the data that may still be sitting
// in software buffers.
DmxReceiver::bufferService();
DmxReceiver.bufferService();

// Update frame count and swap buffers
::frameCount++;
dmxBufferIndex = 0;
if (activeBuffer == dmxBuffer1)
DmxReceiver.m_frameCount++;
DmxReceiver.m_dmxBufferIndex = 0;
if (DmxReceiver.m_activeBuffer == DmxReceiver.m_dmxBuffer1)
{
activeBuffer = dmxBuffer2;
inactiveBuffer = dmxBuffer1;
DmxReceiver.m_activeBuffer = DmxReceiver.m_dmxBuffer2;
DmxReceiver.m_inactiveBuffer = DmxReceiver.m_dmxBuffer1;
}
else
{
activeBuffer = dmxBuffer1;
inactiveBuffer = dmxBuffer2;
DmxReceiver.m_activeBuffer = DmxReceiver.m_dmxBuffer1;
DmxReceiver.m_inactiveBuffer = DmxReceiver.m_dmxBuffer2;
}
::newFrame=true;
DmxReceiver.m_newFrame = true;
}
42 changes: 33 additions & 9 deletions DmxReceiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,35 +24,59 @@
#ifndef DMXRECEIVER_H
#define DMXRECEIVER_H

#include "HardwareSerial.h"
#include <inttypes.h>

class DmxReceiver
class DmxReceiverClass
{
public:
DmxReceiverClass();

/* Initialize UART0 for DMX */
static void begin(void);
void begin(void);

/* Deinitialize */
static void end(void);
void end(void);

/* Clear all stored DMX values to zero */
static void clear(void);
void clear(void);

/* Fill DMX data with specified value */
static void fill(uint8_t v);
void fill(uint8_t v);

/* Call this every 2ms or faster */
static int bufferService(void);
int bufferService(void);

/* Return the value at DMX address d */
static uint8_t getDimmer(uint16_t d);
uint8_t getDimmer(uint16_t d);

volatile uint8_t* getBuffer();

/* Return the number of frame that have been received */
static unsigned int frameCount(void);
unsigned int frameCount(void);

/* Returns true if a new frame has been received since the
last call to this function. */
static bool newFrame(void);
bool newFrame(void);

private:

enum {
DMX_BUFFER_SIZE = 513
};

HardwareSerial Uart;
volatile uint8_t m_dmxBuffer1[DMX_BUFFER_SIZE];
volatile uint8_t m_dmxBuffer2[DMX_BUFFER_SIZE];
volatile uint8_t *m_activeBuffer;
volatile uint8_t *m_inactiveBuffer;
volatile uint16_t m_dmxBufferIndex;
volatile unsigned int m_frameCount;
volatile bool m_newFrame;

friend void uart0_error_isr(void);
};

extern DmxReceiverClass DmxReceiver;

#endif
11 changes: 5 additions & 6 deletions examples/DmxTest/DmxTest.ino
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,19 @@

#include <DmxReceiver.h>

DmxReceiver dmx;
IntervalTimer dmxTimer;

void dmxTimerISR(void)
{
dmx.bufferService();
DmxReceiver.bufferService();
}

void setup() {
/* USB serial */
Serial.begin(115200);

/* DMX */
dmx.begin();
DmxReceiver.begin();

/* Use a timer to service DMX buffers every 1ms */
dmxTimer.begin(dmxTimerISR, 1000);
Expand All @@ -55,7 +54,7 @@ elapsedMillis elapsed;
void loop()
{
/* Toggle LED on every new frame */
if (dmx.newFrame())
if (DmxReceiver.newFrame())
{
led = !led;
digitalWrite(LED_BUILTIN, led);
Expand All @@ -64,11 +63,11 @@ void loop()
/* Dump DMX data every second */
if (elapsed > 1000) {
elapsed -= 1000;
Serial.printf("DMX frameCount=%d", dmx.frameCount());
Serial.printf("DMX frameCount=%d", DmxReceiver.frameCount());

/* Display all nonzero DMX values */
for (int i = 0; i < 512; i++) {
uint8_t v = dmx.getDimmer(i);
uint8_t v = DmxReceiver.getDimmer(i);
if (v)
Serial.printf(" %d:%d", i, v);
}
Expand Down