SHARE
TWEET

FastLED ambibox

a guest Feb 7th, 2015 230 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Slightly modified Adalight protocol implementation that uses FastLED
  2. // library (http://fastled.io) for driving WS2811/WS2812 led stripe
  3. // Was tested only with Prismatik software from Lightpack project (version 5.9.1, 5.9.6 and 5.11.1 so far - 5.11.1 has some issues on startup in windows so I'm not using it)
  4.  
  5. #include "FastLED.h"
  6.  
  7. #define NUM_LEDS 100 // Max LED count
  8. //#define LED_PIN 11 // arduino output pin - probably not required for WS2801
  9. //#define GROUND_PIN 10 // probably not required for WS2801
  10. #define BRIGHTNESS 96 // maximum brightness
  11. #define SPEED 115200 // virtual serial port speed, must be the same in boblight_config
  12.  
  13. CRGB leds[NUM_LEDS];
  14. uint8_t * ledsRaw = (uint8_t *)leds;
  15.  
  16. // A 'magic word' (along with LED count & checksum) precedes each block
  17. // of LED data; this assists the microcontroller in syncing up with the
  18. // host-side software and properly issuing the latch (host I/O is
  19. // likely buffered, making usleep() unreliable for latch).  You may see
  20. // an initial glitchy frame or two until the two come into alignment.
  21. // The magic word can be whatever sequence you like, but each character
  22. // should be unique, and frequent pixel values like 0 and 255 are
  23. // avoided -- fewer false positives.  The host software will need to
  24. // generate a compatible header: immediately following the magic word
  25. // are three bytes: a 16-bit count of the number of LEDs (high byte
  26. // first) followed by a simple checksum value (high byte XOR low byte
  27. // XOR 0x55).  LED data follows, 3 bytes per LED, in order R, G, B,
  28. // where 0 = off and 255 = max brightness.
  29.  
  30. static const uint8_t magic[] = {'A','d','a'};
  31. #define MAGICSIZE  sizeof(magic)
  32. #define HEADERSIZE (MAGICSIZE + 3)
  33.  
  34. #define MODE_HEADER 0
  35. #define MODE_DATA   2
  36.  
  37. // If no serial data is received for a while, the LEDs are shut off
  38. // automatically.  This avoids the annoying "stuck pixel" look when
  39. // quitting LED display programs on the host computer.
  40. static const unsigned long serialTimeout = 150000; // 150 seconds
  41.  
  42. void setup()
  43. {
  44.   // pinMode(GROUND_PIN, OUTPUT);
  45.   // digitalWrite(GROUND_PIN, LOW);
  46.   // FastLED.addLeds<WS2811, LED_PIN, BRG>(leds, NUM_LEDS);
  47.   FastLED.addLeds<WS2801, RGB>(leds, NUM_LEDS);
  48.  
  49.   // Dirty trick: the circular buffer for serial data is 256 bytes,
  50.   // and the "in" and "out" indices are unsigned 8-bit types -- this
  51.   // much simplifies the cases where in/out need to "wrap around" the
  52.   // beginning/end of the buffer.  Otherwise there'd be a ton of bit-
  53.   // masking and/or conditional code every time one of these indices
  54.   // needs to change, slowing things down tremendously.
  55.   uint8_t
  56.     buffer[256],
  57.     indexIn       = 0,
  58.     indexOut      = 0,
  59.     mode          = MODE_HEADER,
  60.     hi, lo, chk, i, spiFlag;
  61.   int16_t
  62.     bytesBuffered = 0,
  63.     hold          = 0,
  64.     c;
  65.   int32_t
  66.     bytesRemaining;
  67.   unsigned long
  68.     startTime,
  69.     lastByteTime,
  70.     lastAckTime,
  71.     t;
  72.   int32_t outPos = 0;
  73.  
  74.   Serial.begin(SPEED); // Teensy/32u4 disregards baud rate; is OK!
  75.  
  76.   Serial.print("Ada\n"); // Send ACK string to host
  77.  
  78.   startTime    = micros();
  79.   lastByteTime = lastAckTime = millis();
  80.  
  81.   // loop() is avoided as even that small bit of function overhead
  82.   // has a measurable impact on this code's overall throughput.
  83.  
  84.   for(;;) {
  85.  
  86.     // Implementation is a simple finite-state machine.
  87.     // Regardless of mode, check for serial input each time:
  88.     t = millis();
  89.     if((bytesBuffered < 256) && ((c = Serial.read()) >= 0)) {
  90.       buffer[indexIn++] = c;
  91.       bytesBuffered++;
  92.       lastByteTime = lastAckTime = t; // Reset timeout counters
  93.     } else {
  94.       // No data received.  If this persists, send an ACK packet
  95.       // to host once every second to alert it to our presence.
  96.       if((t - lastAckTime) > 1000) {
  97.         Serial.print("Ada\n"); // Send ACK string to host
  98.         lastAckTime = t; // Reset counter
  99.       }
  100.       // If no data received for an extended time, turn off all LEDs.
  101.       if((t - lastByteTime) > serialTimeout) {
  102.         memset(leds, 0,  NUM_LEDS * sizeof(struct CRGB)); //filling Led array by zeroes
  103.         FastLED.show();
  104.         lastByteTime = t; // Reset counter
  105.       }
  106.     }
  107.  
  108.     switch(mode) {
  109.  
  110.      case MODE_HEADER:
  111.  
  112.       // In header-seeking mode.  Is there enough data to check?
  113.       if(bytesBuffered >= HEADERSIZE) {
  114.         // Indeed.  Check for a 'magic word' match.
  115.         for(i=0; (i<MAGICSIZE) && (buffer[indexOut++] == magic[i++]););
  116.         if(i == MAGICSIZE) {
  117.           // Magic word matches.  Now how about the checksum?
  118.           hi  = buffer[indexOut++];
  119.           lo  = buffer[indexOut++];
  120.           chk = buffer[indexOut++];
  121.           if(chk == (hi ^ lo ^ 0x55)) {
  122.             // Checksum looks valid.  Get 16-bit LED count, add 1
  123.             // (# LEDs is always > 0) and multiply by 3 for R,G,B.
  124.             bytesRemaining = 3L * (256L * (long)hi + (long)lo + 1L);
  125.             bytesBuffered -= 3;
  126.             outPos = 0;
  127.             memset(leds, 0,  NUM_LEDS * sizeof(struct CRGB));
  128.             mode           = MODE_DATA; // Proceed to latch wait mode
  129.           } else {
  130.             // Checksum didn't match; search resumes after magic word.
  131.             indexOut  -= 3; // Rewind
  132.           }
  133.         } // else no header match.  Resume at first mismatched byte.
  134.         bytesBuffered -= i;
  135.       }
  136.       break;
  137.  
  138.      case MODE_DATA:
  139.  
  140.       if(bytesRemaining > 0) {
  141.         if(bytesBuffered > 0) {
  142.           if (outPos < sizeof(leds))
  143.             ledsRaw[outPos++] = buffer[indexOut++];   // Issue next byte
  144.           bytesBuffered--;
  145.           bytesRemaining--;
  146.         }
  147.         // If serial buffer is threatening to underrun, start
  148.         // introducing progressively longer pauses to allow more
  149.         // data to arrive (up to a point).
  150.       } else {
  151.         // End of data -- issue latch:
  152.         startTime  = micros();
  153.         mode       = MODE_HEADER; // Begin next header search
  154.         FastLED.show();
  155.       }
  156.     } // end switch
  157.   } // end for(;;)
  158. }
  159.  
  160. void loop()
  161. {
  162.   // Not used.  See note in setup() function.
  163. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top