Guest User

adalight fastled (parallel output)

a guest
Mar 15th, 2016
180
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 16.13 KB | None | 0 0
  1. // Modified Adalight protocol implementation that uses FastLED
  2. // library (http://fastled.io) for driving WS2811/WS2812 led stripe
  3. // It uses FastLEDs parallel output feature to drive the LEDs which are arranged in 8 substrips
  4.  
  5. // The LED substrip arrangement is as follow:
  6.  
  7.  
  8. //     ------strip2: connection right------        ------strip1: connection left------
  9. //     |                                       .                                     |
  10. //     s                                       .                                     s
  11. //     t                                       .                                     t
  12. //     r                                       .                                     r
  13. //     i                                       .                                     i                                                      
  14. //     p                                       .                                     p
  15. //     3                                --------------                               8
  16. //     |                                |            |                               |
  17. //        ............................. | controller | ............................    
  18. //     |                                |            |                               |
  19. //     s                                --------------                               s
  20. //     t                                       .                                     t
  21. //     r                                       .                                     r
  22. //     i                                       .                                     i                                                      
  23. //     p                                       .                                     p
  24. //     4                                       .                                     7
  25. //     |                                       .                                     |                                                      
  26. //     ------strip5: connection right------        ------strip6: connection left------
  27.  
  28.  
  29. // In order to have correct LED numbering, e.g. counter-clockwise starting at the right upper corner
  30. // the following considerations have to be taken into account:
  31.  
  32. // Strip 1 is connected from the left, it's LEDs have to be accessed reversed: from high to low
  33. // Strip 2 is connected from the right, it's LEDs have to be accessed normally: from low to high
  34. // Strip 3 is connected from the bottom, it's LEDs have to be accessed reversed: from high to low
  35. // Strip 4 is connected from the top, it's LEDs have to be accessed normally: from low to high
  36. // Strip 5 is connected from the right, it's LEDs have to be accessed reversed: from high to low
  37. // Strip 6 is connected from the left, it's LEDs have to be accessed normally: from low to high
  38. // Strip 7 is connected from the top, it's LEDs have to be accessed reversed: from high to low
  39. // Strip 8 is connected from the bottom, it's LEDs have to be accessed normally: from low to high
  40.  
  41. // This configuration was chosen as it simplifies the wiring. Place the teensy 3.2 and the 8 channel
  42. // 3.3V to 5V level shifter (74HCT245 buffer chip and 8x 100 Ohm resistors) in a box in the center of
  43. // the TVs back and you cleanly wire your LED strips. Just run thick GND and thick +5V wires ss well as
  44. // two thin data wires to the 4 centers of the the TVs borders where e.g. LED strip 1 meets LED strip 2.
  45. // Connect the GND and the +5V wire to both strips, the data wires to their corresponding LED strip.
  46. // With this arrangement, it is not necessary to wire around the corners.
  47. // In the ASCI picture, these sets of wires are shown as dots (.....).
  48.  
  49. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  50. //SETTINGS FOR THE LED STRIPS
  51.  
  52. // Define number of LEDS in each of the substrips
  53. #define LED_STRIP_1_NUM 48
  54. #define LED_STRIP_2_NUM 47
  55. #define LED_STRIP_3_NUM 27
  56. #define LED_STRIP_4_NUM 26
  57. #define LED_STRIP_5_NUM 47
  58. #define LED_STRIP_6_NUM 48
  59. #define LED_STRIP_7_NUM 26
  60. #define LED_STRIP_8_NUM 27
  61.  
  62. // Define the data pin of the substrips (I use the pin layout of the OctoWS2811 libary).
  63. // You can see pin layout here: https://www.pjrc.com/teensy/td_libs_OctoWS2811.html and
  64. // here https://www.pjrc.com/teensy/td_libs_OctoWS2811_2.png
  65. // It is not necessary to connect pin 15 & 16 together. Just leave them free.
  66. #define LED_STRIP_1_PIN 2
  67. #define LED_STRIP_2_PIN 14
  68. #define LED_STRIP_3_PIN 7
  69. #define LED_STRIP_4_PIN 8
  70. #define LED_STRIP_5_PIN 6
  71. #define LED_STRIP_6_PIN 20
  72. #define LED_STRIP_7_PIN 21
  73. #define LED_STRIP_8_PIN 5
  74.  
  75. // Define the ground pin. You have to connect the ground of your 5V power supply to this pin
  76. #define GROUND_PIN 10
  77.  
  78. // Define the maximal power draw of your LEDs to prevent damage to your power supply. A 30 LED/m strip
  79. // (WS2812b) needs roughly 9 W/m and 60 LED/m strip 18 W/m. With 5V these are 1.8 A/m and 3.6 A/m, respectivly.
  80. // Choose an appropriate 5V power supply (I took a 15 A one for a 55" TV) and limi the power draw with the
  81. // following setting. To not overload the power supply it is maby wise to set the limit slighly below it's rated
  82. // value. The value is set in mA. Here it is set to 10 A.
  83. #define MAX_CURRENT 10000
  84.  
  85. // Define the maximal brightness of your LEDs. The brightness can be reduced from 255 (max) to 0 (min). Due to
  86. // FastLED's temporal dithering this should not result in a loss of color resolution (very low values might).
  87. // More information can be found here: https://github.com/FastLED/FastLED/wiki/FastLED-Temporal-Dithering
  88. #define BRIGHTNESS 255 // maximum brightness
  89.  
  90.  
  91. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  92. //SETTINGS FOR THE ADALIGHT PROTOCAL AND THE COMMUNICATION
  93.  
  94. // Define the baudrate of the virtual serial port. The same value has to
  95. // be set on the processing side (.e.g in boblight_config).
  96. #define SPEED 115200
  97.  
  98. // A 'magic word' (along with LED count & checksum) precedes each block
  99. // of LED data; this assists the microcontroller in syncing up with the
  100. // host-side software and properly issuing the latch (host I/O is
  101. // likely buffered, making usleep() unreliable for latch).  You may see
  102. // an initial glitchy frame or two until the two come into alignment.
  103. // The magic word can be whatever sequence you like, but each character
  104. // should be unique, and frequent pixel values like 0 and 255 are
  105. // avoided -- fewer false positives.  The host software will need to
  106. // generate a compatible header: immediately following the magic word
  107. // are three bytes: a 16-bit count of the number of LEDs (high byte
  108. // first) followed by a simple checksum value (high byte XOR low byte
  109. // XOR 0x55).  LED data follows, 3 bytes per LED, in order R, G, B,
  110. // where 0 = off and 255 = max brightness.
  111.  
  112. // Set the "magic word" to Ada. This is also the standard of Adalight
  113. // and other programs (e.g. Prismatik) using the Adalight protocol.
  114. static const uint8_t magic[] = {
  115.   'A','d','a'};
  116.  
  117. // If no serial data is received for a while, the LEDs are shut off
  118. // automatically.  This avoids the annoying "stuck pixel" look when
  119. // quitting LED display programs on the host computer. Timeout is
  120. // set in milli seconds. Thus here we have 150 seconds.
  121. static const unsigned long serialTimeout = 150000;
  122.  
  123.  
  124. //END OF SETTINGS
  125. ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  126.  
  127. // Set header and magic word size
  128. #define MAGICSIZE  sizeof(magic)
  129. #define HEADERSIZE (MAGICSIZE + 3)
  130.  
  131. // Set mode of the data processing and header processing
  132. #define MODE_HEADER 0
  133. #define MODE_DATA   2
  134.  
  135. // Load the FastLED library. You will need FastLED 3.1 or newer for the parallel output to work
  136. #include "FastLED.h"
  137.  
  138. // Calucalte the total number of LEDs
  139. #define NUM_LEDS (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM + LED_STRIP_4_NUM + LED_STRIP_5_NUM + LED_STRIP_6_NUM + LED_STRIP_7_NUM + LED_STRIP_8_NUM)
  140.  
  141. // Generate array of LEDs containing the LEDs of all strips
  142. CRGBArray<NUM_LEDS> leds;
  143.  
  144. // Obtain array of LED raw data
  145. //LINE WITH THE ERROR. PLEASE HELP TO FIX THIS
  146. uint8_t * ledsRaw = (uint8_t *)leds;
  147.  
  148. // Define the start (STRIP_x_L) and end (STRIP_x_H) index of each LED substrip
  149. #define STRIP_1_L 0
  150. #define STRIP_1_H (LED_STRIP_1_NUM - 1)
  151. #define STRIP_2_L (LED_STRIP_1_NUM)
  152. #define STRIP_2_H (LED_STRIP_1_NUM + LED_STRIP_2_NUM - 1)
  153. #define STRIP_3_L (LED_STRIP_1_NUM + LED_STRIP_2_NUM)
  154. #define STRIP_3_H (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM - 1)
  155. #define STRIP_4_L (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM)
  156. #define STRIP_4_H (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM + LED_STRIP_4_NUM - 1)
  157. #define STRIP_5_L (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM + LED_STRIP_4_NUM)
  158. #define STRIP_5_H (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM + LED_STRIP_4_NUM + LED_STRIP_5_NUM - 1)
  159. #define STRIP_6_L (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM + LED_STRIP_4_NUM + LED_STRIP_5_NUM)
  160. #define STRIP_6_H (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM + LED_STRIP_4_NUM + LED_STRIP_5_NUM + LED_STRIP_6_NUM - 1)
  161. #define STRIP_7_L (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM + LED_STRIP_4_NUM + LED_STRIP_5_NUM + LED_STRIP_6_NUM)
  162. #define STRIP_7_H (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM + LED_STRIP_4_NUM + LED_STRIP_5_NUM + LED_STRIP_6_NUM + LED_STRIP_7_NUM - 1)
  163. #define STRIP_8_L (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM + LED_STRIP_4_NUM + LED_STRIP_5_NUM + LED_STRIP_6_NUM + LED_STRIP_7_NUM)
  164. #define STRIP_8_H (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM + LED_STRIP_4_NUM + LED_STRIP_5_NUM + LED_STRIP_6_NUM + LED_STRIP_7_NUM + LED_STRIP_8_NUM - 1)
  165.  
  166. // Extract the LEDs of the first strip. This strip has to be addressed reverse, thus the index are obtained from high to low.
  167. CRGBSet STRIP_1(leds(STRIP_1_H,STRIP_1_L));
  168. // Extract the LEDs of the second strip. This strip has to be addressed normally, thus the index are obtained from low to high.
  169. CRGBSet STRIP_2(leds(STRIP_2_L,STRIP_2_H));
  170. // Extract the LEDs of the third strip. This strip has to be addressed reverse, thus the index are obtained from high to low.
  171. CRGBSet STRIP_3(leds(STRIP_3_H,STRIP_3_L));
  172. // Extract the LEDs of the fourth strip. This strip has to be addressed normally, thus the index are obtained from low to high.
  173. CRGBSet STRIP_4(leds(STRIP_4_L,STRIP_4_H));
  174. // Extract the LEDs of the fifth strip. This strip has to be addressed reverse, thus the index are obtained from high to low.
  175. CRGBSet STRIP_5(leds(STRIP_5_H,STRIP_5_L));
  176. // Extract the LEDs of the sixth strip. This strip has to be addressed normally, thus the index are obtained from low to high.
  177. CRGBSet STRIP_6(leds(STRIP_6_L,STRIP_6_H));
  178. // Extract the LEDs of the seventh strip. This strip has to be addressed reverse, thus the index are obtained from high to low.
  179. CRGBSet STRIP_7(leds(STRIP_7_H,STRIP_7_L));
  180. // Extract the LEDs of the eight strip. This strip has to be addressed normally, thus the index are obtained from low to high.
  181. CRGBSet STRIP_8(leds(STRIP_8_L,STRIP_8_H));
  182.  
  183.  
  184. void setup()
  185. {
  186.   // Set ground pin
  187.   pinMode(GROUND_PIN, OUTPUT);
  188.   digitalWrite(GROUND_PIN, LOW);
  189.  
  190.   // Initialise the 8 LED substrips. My strips had the color order of green-red-blue (GRB). If you have a different color order, you
  191.   // have to adjust all 8 addLeds commands. The type of the used LED strips is WS2812B in this example. Other 3 wire LED strips
  192.   // e.g. NEOPIXEL should work as well. You will just have to adjust the addLeds commadn accordingly.
  193.   FastLED.addLeds<WS2812B, LED_STRIP_1_PIN, GRB>(STRIP_1, LED_STRIP_1_NUM);
  194.   FastLED.addLeds<WS2812B, LED_STRIP_2_PIN, GRB>(STRIP_2, LED_STRIP_2_NUM);
  195.   FastLED.addLeds<WS2812B, LED_STRIP_3_PIN, GRB>(STRIP_3, LED_STRIP_3_NUM);
  196.   FastLED.addLeds<WS2812B, LED_STRIP_4_PIN, GRB>(STRIP_4, LED_STRIP_4_NUM);
  197.   FastLED.addLeds<WS2812B, LED_STRIP_5_PIN, GRB>(STRIP_5, LED_STRIP_5_NUM);
  198.   FastLED.addLeds<WS2812B, LED_STRIP_6_PIN, GRB>(STRIP_6, LED_STRIP_6_NUM);
  199.   FastLED.addLeds<WS2812B, LED_STRIP_7_PIN, GRB>(STRIP_7, LED_STRIP_7_NUM);
  200.   FastLED.addLeds<WS2812B, LED_STRIP_8_PIN, GRB>(STRIP_8, LED_STRIP_8_NUM);
  201.  
  202.   // Activate the current limit
  203.   FastLED.setMaxPowerInVoltsAndMilliamps(5,MAX_CURRENT);
  204.  
  205.   //Activate hte brightness limit
  206.   FastLED.setBrightness(BRIGHTNESS);
  207.  
  208.   // Dirty trick: the circular buffer for serial data is 256 bytes,
  209.   // and the "in" and "out" indices are unsigned 8-bit types -- this
  210.   // much simplifies the cases where in/out need to "wrap around" the
  211.   // beginning/end of the buffer.  Otherwise there'd be a ton of bit-
  212.   // masking and/or conditional code every time one of these indices
  213.   // needs to change, slowing things down tremendously.
  214.   uint8_t
  215.     buffer[256],
  216.   indexIn       = 0,
  217.   indexOut      = 0,
  218.   mode          = MODE_HEADER,
  219.   hi, lo, chk, i, spiFlag;
  220.   int16_t
  221.     bytesBuffered = 0,
  222.   hold          = 0,
  223.   c;
  224.   int32_t
  225.     bytesRemaining;
  226.   unsigned long
  227.     startTime,
  228.   lastByteTime,
  229.   lastAckTime,
  230.   t;
  231.   int32_t outPos = 0;
  232.  
  233.   Serial.begin(SPEED); // Teensy/32u4 disregards baud rate; is OK!
  234.  
  235.   Serial.print("Ada\n"); // Send ACK string to host
  236.  
  237.     startTime    = micros();
  238.   lastByteTime = lastAckTime = millis();
  239.  
  240.   // loop() is avoided as even that small bit of function overhead
  241.   // has a measurable impact on this code's overall throughput.
  242.  
  243.   for(;;) {
  244.  
  245.     // Implementation is a simple finite-state machine.
  246.     // Regardless of mode, check for serial input each time:
  247.     t = millis();
  248.     if((bytesBuffered < 256) && ((c = Serial.read()) >= 0)) {
  249.       buffer[indexIn++] = c;
  250.       bytesBuffered++;
  251.       lastByteTime = lastAckTime = t; // Reset timeout counters
  252.     }
  253.     else {
  254.       // No data received.  If this persists, send an ACK packet
  255.       // to host once every second to alert it to our presence.
  256.       if((t - lastAckTime) > 1000) {
  257.         Serial.print("Ada\n"); // Send ACK string to host
  258.         lastAckTime = t; // Reset counter
  259.       }
  260.       // If no data received for an extended time, turn off all LEDs.
  261.       if((t - lastByteTime) > serialTimeout) {
  262.         memset(leds, 0,  NUM_LEDS * sizeof(struct CRGB)); //filling Led array by zeroes
  263.         FastLED.show();
  264.         lastByteTime = t; // Reset counter
  265.       }
  266.     }
  267.  
  268.     switch(mode) {
  269.  
  270.     case MODE_HEADER:
  271.  
  272.       // In header-seeking mode.  Is there enough data to check?
  273.       if(bytesBuffered >= HEADERSIZE) {
  274.         // Indeed.  Check for a 'magic word' match.
  275.         for(i=0; (i<MAGICSIZE) && (buffer[indexOut++] == magic[i++]););
  276.         if(i == MAGICSIZE) {
  277.           // Magic word matches.  Now how about the checksum?
  278.           hi  = buffer[indexOut++];
  279.           lo  = buffer[indexOut++];
  280.           chk = buffer[indexOut++];
  281.           if(chk == (hi ^ lo ^ 0x55)) {
  282.             // Checksum looks valid.  Get 16-bit LED count, add 1
  283.             // (# LEDs is always > 0) and multiply by 3 for R,G,B.
  284.             bytesRemaining = 3L * (256L * (long)hi + (long)lo + 1L);
  285.             bytesBuffered -= 3;
  286.             outPos = 0;
  287.             memset(leds, 0,  NUM_LEDS * sizeof(struct CRGB));
  288.             mode           = MODE_DATA; // Proceed to latch wait mode
  289.           }
  290.           else {
  291.             // Checksum didn't match; search resumes after magic word.
  292.             indexOut  -= 3; // Rewind
  293.           }
  294.         } // else no header match.  Resume at first mismatched byte.
  295.         bytesBuffered -= i;
  296.       }
  297.       break;
  298.  
  299.     case MODE_DATA:
  300.  
  301.       if(bytesRemaining > 0) {
  302.         if(bytesBuffered > 0) {
  303.           if (outPos < sizeof(leds))
  304.             ledsRaw[outPos++] = buffer[indexOut++];   // Issue next byte
  305.           bytesBuffered--;
  306.           bytesRemaining--;
  307.         }
  308.         // If serial buffer is threatening to underrun, start
  309.         // introducing progressively longer pauses to allow more
  310.         // data to arrive (up to a point).
  311.       }
  312.       else {
  313.         // End of data -- issue latch:
  314.         startTime  = micros();
  315.         mode       = MODE_HEADER; // Begin next header search
  316.         FastLED.show();
  317.       }
  318.     } // end switch
  319.   } // end for(;;)
  320. }
  321.  
  322. void loop()
  323. {
  324.   // Not used.  See note in setup() function.
  325. }
Advertisement
Add Comment
Please, Sign In to add comment