diff --git a/Arduino/LEDstream_FastLED/LEDstream_FastLED.ino b/Arduino/LEDstream_FastLED/LEDstream_FastLED.ino index 324f0b6..8a3b850 100644 --- a/Arduino/LEDstream_FastLED/LEDstream_FastLED.ino +++ b/Arduino/LEDstream_FastLED/LEDstream_FastLED.ino @@ -4,7 +4,7 @@ * library (http://fastled.io) for driving led strips. * * http://github.com/dmadison/Adalight-FastLED - * Last Updated: 2017-03-27 + * Last Updated: 2017-04-08 */ // --- General Settings @@ -52,10 +52,14 @@ uint8_t * ledsRaw = (uint8_t *)leds; static const uint8_t magic[] = { 'A','d','a'}; #define MAGICSIZE sizeof(magic) -#define HEADERSIZE (MAGICSIZE + 3) + +// Check values are header byte # - 1, as they are indexed from 0 +#define HICHECK (MAGICSIZE) +#define LOCHECK (MAGICSIZE + 1) +#define CHECKSUM (MAGICSIZE + 2) #define MODE_HEADER 0 -#define MODE_DATA 2 +#define MODE_DATA 1 void setup(){ #ifdef GROUND_PIN @@ -76,26 +80,16 @@ void setup(){ } void adalight(){ - // Dirty trick: the circular buffer for serial data is 256 bytes, - // and the "in" and "out" indices are unsigned 8-bit types -- this - // much simplifies the cases where in/out need to "wrap around" the - // beginning/end of the buffer. Otherwise there'd be a ton of bit- - // masking and/or conditional code every time one of these indices - // needs to change, slowing things down tremendously. - uint8_t - buffer[256], - indexIn = 0, - indexOut = 0, - mode = MODE_HEADER, - hi, lo, chk, i; + mode = MODE_HEADER, + headPos, + hi, lo, chk; int16_t c; uint16_t - bytesBuffered = 0; - uint32_t - bytesRemaining, outPos; + uint32_t + bytesRemaining; unsigned long lastByteTime, lastAckTime, @@ -113,11 +107,69 @@ void adalight(){ // Implementation is a simple finite-state machine. // Regardless of mode, check for serial input each time: t = millis(); - if((bytesBuffered < 256) && ((c = Serial.read()) >= 0)) { - buffer[indexIn++] = c; - bytesBuffered++; + + if((c = Serial.read()) >= 0){ lastByteTime = lastAckTime = t; // Reset timeout counters - } + + switch(mode) { + + case MODE_HEADER: + + if(headPos < MAGICSIZE){ + if(c == magic[headPos]) headPos++; + else headPos = 0; + } + else{ + switch(headPos){ + case HICHECK: + hi = c; + headPos++; + break; + case LOCHECK: + lo = c; + headPos++; + break; + case CHECKSUM: + chk = c; + if(chk == (hi ^ lo ^ 0x55)) { + // Checksum looks valid. Get 16-bit LED count, add 1 + // (# LEDs is always > 0) and multiply by 3 for R,G,B. + bytesRemaining = 3L * (256L * (long)hi + (long)lo + 1L); + outPos = 0; + memset(leds, 0, Num_Leds * sizeof(struct CRGB)); + mode = MODE_DATA; // Proceed to latch wait mode + } + headPos = 0; // Reset header position regardless of checksum result + break; + } + } + break; + + case MODE_DATA: + + if(bytesRemaining > 0) { + if (outPos < sizeof(leds)){ + #ifdef CALIBRATE + if(outPos < 3) + ledsRaw[outPos++] = c; + else{ + ledsRaw[outPos] = ledsRaw[outPos%3]; // Sets RGB data to first LED color + outPos++; + } + #else + ledsRaw[outPos++] = c; // Issue next byte + #endif + } + bytesRemaining--; + } + if(bytesRemaining == 0) { + // End of data -- issue latch: + mode = MODE_HEADER; // Begin next header search + FastLED.show(); + } + break; + } // end switch + } // end serial if else { // No data received. If this persists, send an ACK packet // to host once every second to alert it to our presence. @@ -131,66 +183,7 @@ void adalight(){ FastLED.show(); lastByteTime = t; // Reset counter } - } - - switch(mode) { - - case MODE_HEADER: - - // In header-seeking mode. Is there enough data to check? - if(bytesBuffered >= HEADERSIZE) { - // Indeed. Check for a 'magic word' match. - for(i=0; (i 0) and multiply by 3 for R,G,B. - bytesRemaining = 3L * (256L * (long)hi + (long)lo + 1L); - bytesBuffered -= 3; - outPos = 0; - memset(leds, 0, Num_Leds * sizeof(struct CRGB)); - mode = MODE_DATA; // Proceed to latch wait mode - } - else { - // Checksum didn't match; search resumes after magic word. - indexOut -= 3; // Rewind - } - } // else no header match. Resume at first mismatched byte. - bytesBuffered -= i; - } - break; - - case MODE_DATA: - - if(bytesRemaining > 0) { - if(bytesBuffered > 0) { - if (outPos < sizeof(leds)){ - #ifdef CALIBRATE - if(outPos < 3) - ledsRaw[outPos++] = buffer[indexOut]; - else{ - ledsRaw[outPos] = ledsRaw[outPos%3]; // Sets RGB data to first LED color - outPos++; - } - #else - ledsRaw[outPos++] = buffer[indexOut]; // Issue next byte - #endif - } - indexOut++; - bytesBuffered--; - bytesRemaining--; - } - } - else { - // End of data -- issue latch: - mode = MODE_HEADER; // Begin next header search - FastLED.show(); - } - } // end switch + } // end else } // end for(;;) }