diff --git a/README.adoc b/README.adoc index f66b14b..2754ae3 100644 --- a/README.adoc +++ b/README.adoc @@ -1,5 +1,7 @@ = DMX Library for Arduino = +Improved to enable the usage of Neopixels and reduce Memory usage. + 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. diff --git a/src/DMXSerial.cpp b/src/DMXSerial.cpp index ee9a8e9..5c92954 100644 --- a/src/DMXSerial.cpp +++ b/src/DMXSerial.cpp @@ -173,9 +173,11 @@ typedef enum { DMXMode _dmxMode; // Mode of Operation int _dmxModePin; // pin used for I/O direction. +int _dmxStartAddress = 1; //first Channel the reciver will listen to. Default is 1. uint8_t _dmxRecvState; // Current State of receiving DMX Bytes int _dmxChannel; // the next channel byte to be sent. +uint16_t _dmxRecvPos; //Next received Channel in one data Frame 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. @@ -373,6 +375,12 @@ void DMXSerialClass::term(void) UCSRnB = 0; } // term() +//sets the first Channel the reciver will listen to +void DMXSerialClass::setStartAddress(int channel){ + if (channel < 1) channel = 1; + if (channel > 512) channel = 512; + _dmxStartAddress = channel; +} // ----- internal functions and interrupt implementations ----- @@ -435,7 +443,9 @@ inline void _DMXSerialWriteByte(uint8_t data) // In DMXController mode this interrupt is disabled and will not occur. // In DMXReceiver mode when a byte was received it is stored to the dmxData buffer. ISR(USARTn_RX_vect) -{ + { + while(UCSRnA & (1 << RXCn)){ //while ther is data in the USART buffer + 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 @@ -450,7 +460,8 @@ ISR(USARTn_RX_vect) // break condition detected. _dmxRecvState = BREAK; _dmxDataPtr = _dmxData; - + _dmxRecvPos = 0; + } else if (DmxState == BREAK) { // first byte after a break was read. if (DmxByte == 0) { @@ -458,6 +469,7 @@ ISR(USARTn_RX_vect) _dmxRecvState = DATA; _dmxLastPacket = millis(); // remember current (relative) time in msecs. _dmxDataPtr++; // start saving data with channel # 1 + _dmxRecvPos ++; } else { // This might be a RDM or customer DMX command -> not implemented so wait for next BREAK ! @@ -465,14 +477,17 @@ ISR(USARTn_RX_vect) } // if } else if (DmxState == DATA) { - // check for new data - if (*_dmxDataPtr != DmxByte) { - _dmxUpdated = true; - // store received data into dmx data buffer. - *_dmxDataPtr = DmxByte; - } // if - _dmxDataPtr++; - + if (_dmxRecvPos >= _dmxStartAddress){ + // check for new data + if (*_dmxDataPtr != DmxByte) { + _dmxUpdated = true; + // store received data into dmx data buffer. + *_dmxDataPtr = DmxByte; + } // if + _dmxDataPtr++; + } + _dmxRecvPos++; + if (_dmxDataPtr > _dmxDataLastPtr) { // all channels received. _dmxRecvState = DONE; @@ -486,14 +501,14 @@ ISR(USARTn_RX_vect) // continue listening without interrupts _DMXSerialInit(Calcprescale(DMXSPEED), (1 << RXENn), DMXFORMAT); //UCSRnB = (1 << RXENn); - - + + } else { // continue on DMXReceiver mode. _dmxRecvState = IDLE; // wait for next break } } // if - +} // while } // ISR(USARTn_RX_vect) diff --git a/src/DMXSerial.h b/src/DMXSerial.h index 6ddebe1..58707c2 100644 --- a/src/DMXSerial.h +++ b/src/DMXSerial.h @@ -28,6 +28,9 @@ // _DMXStartSending and _DMXStartReceiving functions. // 27.08.2017 DMXProbe mode finished. // 29.10.2017 documentation. +// 30.12.2018 included DMX start address on reciving data. +// 30.12.2018 the buffer is now completly read when the RX interrupt occurs. +// This allows the usage of multiple ws8212 LEDs. // - - - - - #ifndef DmxSerial_h @@ -164,7 +167,12 @@ class DMXSerialClass * @brief Terminate the current operation mode. */ void term(); - + + /** + * @brief sets the first channel the reciver is listening and storing to. + */ + void setStartAddress(int channel); + private: // Not used. // all private information is in the global _dmxXXX variables for speed and code size optimization.