Guest User

Pristmatik-Adalight

a guest
Jan 27th, 2017
3,088
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.05 KB | None | 0 0
  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 13 // 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. }
Advertisement
Add Comment
Please, Sign In to add comment