Skip to content

Commit

Permalink
Updated library, ready for Arduino Shell version 1.6.0.
Browse files Browse the repository at this point in the history
  • Loading branch information
mathertel committed Mar 4, 2015
1 parent cd06cf1 commit 424d8cf
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 22 deletions.
16 changes: 16 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
= DMX Library for Arduino =

This is a library for sending and receiving DMX codes using the Arduino plattform
or a ATmega (ATmega168, ATmega328 or similar) processor with a clock speed of 16 MHz.

For more information about this library please visit us at
http://www.mathertel.de/Arduino/DMXSerial.aspx

== License ==

Copyright (c) 2005-2015 by Matthias Hertel, http://www.mathertel.de/

The detailed Software License Agreement can be found at:
http://www.mathertel.de/License.aspx


9 changes: 9 additions & 0 deletions library.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name=DMXSerial
version=1.2
author=Matthias Hertel
maintainer=Matthias Hertel <www.mathertel.de>
sentence=Enables DMX communication using the built-in serial port. For Arduino boards UNO, Leonardo, Mega.
paragraph=With this library you ...
category=Communication
url=http://www.mathertel.de/Arduino/DMXSerial.aspx
architectures=*
95 changes: 76 additions & 19 deletions DMXSerial.cpp → src/DMXSerial.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// - - - - -
// DMXSerial - A hardware supported interface to DMX.
// DMXSerial - A Arduino library for sending and receiving DMX using the builtin serial hardware port.
// DMXSerial.cpp: Library implementation file
//
// Copyright (c) 2011 by Matthias Hertel, http://www.mathertel.de
Expand Down Expand Up @@ -192,13 +192,22 @@ DMXMode _dmxMode; // Mode of Operation
uint8_t _dmxRecvState; // Current State of receiving DMX Bytes
int _dmxChannel; // the next channel byte to be sent.

volatile int _dmxMaxChannel = 32; // the last channel used for sending (1..32).
volatile unsigned long _gotLastPacket = 0; // the last time (using the millis function) a packet was received.
volatile unsigned int _dmxMaxChannel = 32; // the last channel used for sending (1..32).
volatile unsigned long _dmxLastPacket = 0; // the last time (using the millis function) a packet was received.

bool _dmxUpdated = true; // is set to true when new data arrived.
dmxUpdateFunction _dmxOnUpdateFunc = NULL;

// Array of DMX values (raw).
// Entry 0 will never be used for DMX data but will store the startbyte (0 for DMX mode).
uint8_t _dmxData[DMXSERIAL_MAX+1];

// This pointer will point to the next byte in _dmxData;
uint8_t *_dmxDataPtr;

// This pointer will point to the last byte in _dmxData;
uint8_t *_dmxDataLastPtr;

// Create a single class instance. Multiple class instances (multiple simultaneous DMX ports) are not supported.
DMXSerialClass DMXSerial;

Expand All @@ -224,9 +233,11 @@ void DMXSerialClass::init (int mode)
_dmxMode = DMXNone;
_dmxRecvState= IDLE; // initial state
_dmxChannel = 0;
_gotLastPacket = millis(); // remember current (relative) time in msecs.
_dmxDataPtr = _dmxData;
_dmxLastPacket = millis(); // remember current (relative) time in msecs.

// initialize the DMX buffer
// memset(_dmxData, 0, sizeof(_dmxData));
for (int n = 0; n < DMXSERIAL_MAX+1; n++)
_dmxData[n] = 0;

Expand All @@ -245,7 +256,7 @@ void DMXSerialClass::init (int mode)
// Start sending a BREAK and loop (forever) in UDRE ISR
_DMXSerialBaud(Calcprescale(BREAKSPEED), BREAKFORMAT);
_DMXSerialWriteByte((uint8_t)0);
_dmxChannel = 0;
_dmxMaxChannel = 32; // The default in Controller mode is sending 32 channels.

} else if (_dmxMode == DMXReceiver) {
// Setup external mode signal
Expand All @@ -257,6 +268,9 @@ void DMXSerialClass::init (int mode)
UCSRnB = (1<<RXENn) | (1<<RXCIEn);
_DMXSerialBaud(Calcprescale(DMXSPEED), DMXFORMAT); // Enable serial reception with a 250k rate

_dmxMaxChannel = DMXSERIAL_MAX; // The default in Receiver mode is reading all possible 512 channels.
_dmxDataLastPtr = _dmxData + _dmxMaxChannel;

} else {
// Enable receiver and transmitter and interrupts
// UCSRnB = (1<<RXENn) | (1<<TXENn) | (1<<RXCIEn) | (1<<UDRIEn);
Expand All @@ -272,6 +286,7 @@ void DMXSerialClass::maxChannel(int channel)
if (channel < 1) channel = 1;
if (channel > DMXSERIAL_MAX) channel = DMXSERIAL_MAX;
_dmxMaxChannel = channel;
_dmxDataLastPtr = _dmxData + channel;
} // maxChannel


Expand Down Expand Up @@ -301,20 +316,48 @@ void DMXSerialClass::write(int channel, uint8_t value)
_dmxData[channel] = value;

// Make sure we transmit enough channels for the ones used
if (channel > _dmxMaxChannel)
if (channel > _dmxMaxChannel) {
_dmxMaxChannel = channel;
_dmxDataLastPtr = _dmxData + _dmxMaxChannel;
} // if
} // write()


// Return the DMX buffer of unsave direct but faster access
uint8_t *DMXSerialClass::getBuffer()
{
return(_dmxData);
} // getBuffer()


// Calculate how long no data packet was received
unsigned long DMXSerialClass::noDataSince()
{
unsigned long now = millis();
return(now - _gotLastPacket);
return(now - _dmxLastPacket);
} // noDataSince()


// Terminale operation
// save function for the onUpdate callback
void DMXSerialClass::attachOnUpdate(dmxUpdateFunction newFunction)
{
_dmxOnUpdateFunc = newFunction;
} // attachOnUpdate



bool DMXSerialClass::dataUpdated()
{
return(_dmxUpdated);
}

void DMXSerialClass::resetUpdated()
{
_dmxUpdated = false;
}


// Terminate operation
void DMXSerialClass::term(void)
{
// Disable all USART Features, including Interrupts
Expand Down Expand Up @@ -352,8 +395,8 @@ void _DMXSerialWriteByte(uint8_t data)
// In DMXReceiver mode when a byte was received it is stored to the dmxData buffer.
ISR(USARTn_RX_vect)
{
uint8_t USARTstate = UCSRnA; //get state before data!
uint8_t DmxByte = UDRn; //get data
uint8_t USARTstate = UCSRnA; // get state before data!
uint8_t DmxByte = UDRn; // get data
uint8_t DmxState = _dmxRecvState; //just load once from SRAM to increase speed

#ifdef SCOPEDEBUG
Expand All @@ -362,29 +405,43 @@ ISR(USARTn_RX_vect)

if (USARTstate & (1<<FEn)) { //check for break
_dmxRecvState = BREAK; // break condition detected.
_dmxChannel = 0; // The next data byte is the start byte

// _dmxChannel = 0; // The next data byte is the start byte
_dmxDataPtr = _dmxData;

} else if (DmxState == BREAK) {
if (DmxByte == 0) {
// normal DMX start code (0) detected
#ifdef SCOPEDEBUG
digitalWrite(DmxTriggerPin, LOW);
digitalWrite(DmxTriggerPin, HIGH);
#endif
_dmxRecvState = DATA; // normal DMX start code detected
_dmxChannel = 1; // start with channel # 1
_gotLastPacket = millis(); // remember current (relative) time in msecs.
_dmxRecvState = DATA;
_dmxLastPacket = millis(); // remember current (relative) time in msecs.
// _dmxChannel++; // start with channel # 1
_dmxDataPtr++;

} else {
// This might be a RDM command -> not implemented so wait for next BREAK !
// This might be a RDM or customer DMX command -> not implemented so wait for next BREAK !
_dmxRecvState = IDLE;
} // if

} else if (DmxState == DATA) {
_dmxData[_dmxChannel] = DmxByte; // store received data into dmx data buffer.
_dmxChannel++;
if (_dmxChannel > DMXSERIAL_MAX) { // all channels done.
// check for new data
if (*_dmxDataPtr != DmxByte) {
_dmxUpdated = true;
// store data
*_dmxDataPtr = DmxByte; //_dmxData[_dmxChannel] = DmxByte; store received data into dmx data buffer.
} // if

if (_dmxDataPtr == _dmxDataLastPtr) { // all channels received.
_dmxRecvState = IDLE; // wait for next break

if ((_dmxUpdated) && (_dmxOnUpdateFunc))
_dmxOnUpdateFunc();
_dmxUpdated = false;
} // if
// _dmxChannel++;
_dmxDataPtr++;

} // if

Expand Down
31 changes: 28 additions & 3 deletions DMXSerial.h → src/DMXSerial.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
// - - - - -
// DMXSerial - A hardware supported interface to DMX.
// DMXSerial - A Arduino library for sending and receiving DMX using the builtin serial hardware port.
// DMXSerial.h: Library header file
//
// Copyright (c) 2011 by Matthias Hertel, http://www.mathertel.de
// Copyright (c) 2011-2014 by Matthias Hertel, http://www.mathertel.de
// This work is licensed under a BSD style license. See http://www.mathertel.de/License.aspx
//
// Documentation and samples are available at http://www.mathertel.de/Arduino
// 25.07.2011 creation of the DMXSerial library.
// 01.12.2011 include file changed to work with the Arduino 1.0 environment
// 10.05.2012 added method noDataSince to check how long no packet was received
// 12.07.2014 added update flag
// Until here the maxChannel feature only was used in DMXController mode.
// Now it enables triggering the onUpdate function in DMX receiver mode.
//
// See the WebSite for more information.
//
// - - - - -

#ifndef DmxSerial_h
Expand All @@ -35,6 +41,10 @@ typedef enum {

// ----- Library Class -----

extern "C" {
typedef void (*dmxUpdateFunction)(void);
}

class DMXSerialClass
{
public:
Expand All @@ -50,14 +60,29 @@ class DMXSerialClass
// Write a new value of a channel.
void write (int channel, uint8_t value);

// Calculate how long no data backet was received
uint8_t *getBuffer();

// Calculate how long no data packet was received
unsigned long noDataSince();

// attach function that will be called when new data was received.
void attachOnUpdate(dmxUpdateFunction newFunction);

// Calculate how long no data backet was received
bool dataUpdated();
void resetUpdated();

// Terminate operation.
void term (void);

private:
// Not used.
// all private information is in the global _dmxXXX variables for speed and code size optimization.
// See DMXSerial.cpp.
};

// Use the DMXSerial library through the DMXSerial object.
// There is only one DMX port supported and DMXSerial is a static object.
extern DMXSerialClass DMXSerial;

#endif

0 comments on commit 424d8cf

Please sign in to comment.