Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Modified Adalight protocol implementation that uses FastLED
- // library (http://fastled.io) for driving WS2811/WS2812 led stripe
- // It uses FastLEDs parallel output feature to drive the LEDs which are arranged in 8 substrips
- // The LED substrip arrangement is as follow:
- // ------strip2: connection right------ ------strip1: connection left------
- // | . |
- // s . s
- // t . t
- // r . r
- // i . i
- // p . p
- // 3 -------------- 8
- // | | | |
- // ............................. | controller | ............................
- // | | | |
- // s -------------- s
- // t . t
- // r . r
- // i . i
- // p . p
- // 4 . 7
- // | . |
- // ------strip5: connection right------ ------strip6: connection left------
- // In order to have correct LED numbering, e.g. counter-clockwise starting at the right upper corner
- // the following considerations have to be taken into account:
- // Strip 1 is connected from the left, it's LEDs have to be accessed reversed: from high to low
- // Strip 2 is connected from the right, it's LEDs have to be accessed normally: from low to high
- // Strip 3 is connected from the bottom, it's LEDs have to be accessed reversed: from high to low
- // Strip 4 is connected from the top, it's LEDs have to be accessed normally: from low to high
- // Strip 5 is connected from the right, it's LEDs have to be accessed reversed: from high to low
- // Strip 6 is connected from the left, it's LEDs have to be accessed normally: from low to high
- // Strip 7 is connected from the top, it's LEDs have to be accessed reversed: from high to low
- // Strip 8 is connected from the bottom, it's LEDs have to be accessed normally: from low to high
- // This configuration was chosen as it simplifies the wiring. Place the teensy 3.2 and the 8 channel
- // 3.3V to 5V level shifter (74HCT245 buffer chip and 8x 100 Ohm resistors) in a box in the center of
- // the TVs back and you cleanly wire your LED strips. Just run thick GND and thick +5V wires ss well as
- // two thin data wires to the 4 centers of the the TVs borders where e.g. LED strip 1 meets LED strip 2.
- // Connect the GND and the +5V wire to both strips, the data wires to their corresponding LED strip.
- // With this arrangement, it is not necessary to wire around the corners.
- // In the ASCI picture, these sets of wires are shown as dots (.....).
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //SETTINGS FOR THE LED STRIPS
- // Define number of LEDS in each of the substrips
- #define LED_STRIP_1_NUM 48
- #define LED_STRIP_2_NUM 47
- #define LED_STRIP_3_NUM 27
- #define LED_STRIP_4_NUM 26
- #define LED_STRIP_5_NUM 47
- #define LED_STRIP_6_NUM 48
- #define LED_STRIP_7_NUM 26
- #define LED_STRIP_8_NUM 27
- // Define the data pin of the substrips (I use the pin layout of the OctoWS2811 libary).
- // You can see pin layout here: https://www.pjrc.com/teensy/td_libs_OctoWS2811.html and
- // here https://www.pjrc.com/teensy/td_libs_OctoWS2811_2.png
- // It is not necessary to connect pin 15 & 16 together. Just leave them free.
- #define LED_STRIP_1_PIN 2
- #define LED_STRIP_2_PIN 14
- #define LED_STRIP_3_PIN 7
- #define LED_STRIP_4_PIN 8
- #define LED_STRIP_5_PIN 6
- #define LED_STRIP_6_PIN 20
- #define LED_STRIP_7_PIN 21
- #define LED_STRIP_8_PIN 5
- // Define the ground pin. You have to connect the ground of your 5V power supply to this pin
- #define GROUND_PIN 10
- // Define the maximal power draw of your LEDs to prevent damage to your power supply. A 30 LED/m strip
- // (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.
- // Choose an appropriate 5V power supply (I took a 15 A one for a 55" TV) and limi the power draw with the
- // following setting. To not overload the power supply it is maby wise to set the limit slighly below it's rated
- // value. The value is set in mA. Here it is set to 10 A.
- #define MAX_CURRENT 10000
- // Define the maximal brightness of your LEDs. The brightness can be reduced from 255 (max) to 0 (min). Due to
- // FastLED's temporal dithering this should not result in a loss of color resolution (very low values might).
- // More information can be found here: https://github.com/FastLED/FastLED/wiki/FastLED-Temporal-Dithering
- #define BRIGHTNESS 255 // maximum brightness
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //SETTINGS FOR THE ADALIGHT PROTOCAL AND THE COMMUNICATION
- // Define the baudrate of the virtual serial port. The same value has to
- // be set on the processing side (.e.g in boblight_config).
- #define SPEED 115200
- // A 'magic word' (along with LED count & checksum) precedes each block
- // of LED data; this assists the microcontroller in syncing up with the
- // host-side software and properly issuing the latch (host I/O is
- // likely buffered, making usleep() unreliable for latch). You may see
- // an initial glitchy frame or two until the two come into alignment.
- // The magic word can be whatever sequence you like, but each character
- // should be unique, and frequent pixel values like 0 and 255 are
- // avoided -- fewer false positives. The host software will need to
- // generate a compatible header: immediately following the magic word
- // are three bytes: a 16-bit count of the number of LEDs (high byte
- // first) followed by a simple checksum value (high byte XOR low byte
- // XOR 0x55). LED data follows, 3 bytes per LED, in order R, G, B,
- // where 0 = off and 255 = max brightness.
- // Set the "magic word" to Ada. This is also the standard of Adalight
- // and other programs (e.g. Prismatik) using the Adalight protocol.
- static const uint8_t magic[] = {
- 'A','d','a'};
- // If no serial data is received for a while, the LEDs are shut off
- // automatically. This avoids the annoying "stuck pixel" look when
- // quitting LED display programs on the host computer. Timeout is
- // set in milli seconds. Thus here we have 150 seconds.
- static const unsigned long serialTimeout = 150000;
- //END OF SETTINGS
- ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
- // Set header and magic word size
- #define MAGICSIZE sizeof(magic)
- #define HEADERSIZE (MAGICSIZE + 3)
- // Set mode of the data processing and header processing
- #define MODE_HEADER 0
- #define MODE_DATA 2
- // Load the FastLED library. You will need FastLED 3.1 or newer for the parallel output to work
- #include "FastLED.h"
- // Calucalte the total number of LEDs
- #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)
- // Generate array of LEDs containing the LEDs of all strips
- CRGBArray<NUM_LEDS> leds;
- // Obtain array of LED raw data
- //LINE WITH THE ERROR. PLEASE HELP TO FIX THIS
- uint8_t * ledsRaw = (uint8_t *)leds;
- // Define the start (STRIP_x_L) and end (STRIP_x_H) index of each LED substrip
- #define STRIP_1_L 0
- #define STRIP_1_H (LED_STRIP_1_NUM - 1)
- #define STRIP_2_L (LED_STRIP_1_NUM)
- #define STRIP_2_H (LED_STRIP_1_NUM + LED_STRIP_2_NUM - 1)
- #define STRIP_3_L (LED_STRIP_1_NUM + LED_STRIP_2_NUM)
- #define STRIP_3_H (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM - 1)
- #define STRIP_4_L (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM)
- #define STRIP_4_H (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM + LED_STRIP_4_NUM - 1)
- #define STRIP_5_L (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM + LED_STRIP_4_NUM)
- #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)
- #define STRIP_6_L (LED_STRIP_1_NUM + LED_STRIP_2_NUM + LED_STRIP_3_NUM + LED_STRIP_4_NUM + LED_STRIP_5_NUM)
- #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)
- #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)
- #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)
- #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)
- #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)
- // Extract the LEDs of the first strip. This strip has to be addressed reverse, thus the index are obtained from high to low.
- CRGBSet STRIP_1(leds(STRIP_1_H,STRIP_1_L));
- // Extract the LEDs of the second strip. This strip has to be addressed normally, thus the index are obtained from low to high.
- CRGBSet STRIP_2(leds(STRIP_2_L,STRIP_2_H));
- // Extract the LEDs of the third strip. This strip has to be addressed reverse, thus the index are obtained from high to low.
- CRGBSet STRIP_3(leds(STRIP_3_H,STRIP_3_L));
- // Extract the LEDs of the fourth strip. This strip has to be addressed normally, thus the index are obtained from low to high.
- CRGBSet STRIP_4(leds(STRIP_4_L,STRIP_4_H));
- // Extract the LEDs of the fifth strip. This strip has to be addressed reverse, thus the index are obtained from high to low.
- CRGBSet STRIP_5(leds(STRIP_5_H,STRIP_5_L));
- // Extract the LEDs of the sixth strip. This strip has to be addressed normally, thus the index are obtained from low to high.
- CRGBSet STRIP_6(leds(STRIP_6_L,STRIP_6_H));
- // Extract the LEDs of the seventh strip. This strip has to be addressed reverse, thus the index are obtained from high to low.
- CRGBSet STRIP_7(leds(STRIP_7_H,STRIP_7_L));
- // Extract the LEDs of the eight strip. This strip has to be addressed normally, thus the index are obtained from low to high.
- CRGBSet STRIP_8(leds(STRIP_8_L,STRIP_8_H));
- void setup()
- {
- // Set ground pin
- pinMode(GROUND_PIN, OUTPUT);
- digitalWrite(GROUND_PIN, LOW);
- // Initialise the 8 LED substrips. My strips had the color order of green-red-blue (GRB). If you have a different color order, you
- // have to adjust all 8 addLeds commands. The type of the used LED strips is WS2812B in this example. Other 3 wire LED strips
- // e.g. NEOPIXEL should work as well. You will just have to adjust the addLeds commadn accordingly.
- FastLED.addLeds<WS2812B, LED_STRIP_1_PIN, GRB>(STRIP_1, LED_STRIP_1_NUM);
- FastLED.addLeds<WS2812B, LED_STRIP_2_PIN, GRB>(STRIP_2, LED_STRIP_2_NUM);
- FastLED.addLeds<WS2812B, LED_STRIP_3_PIN, GRB>(STRIP_3, LED_STRIP_3_NUM);
- FastLED.addLeds<WS2812B, LED_STRIP_4_PIN, GRB>(STRIP_4, LED_STRIP_4_NUM);
- FastLED.addLeds<WS2812B, LED_STRIP_5_PIN, GRB>(STRIP_5, LED_STRIP_5_NUM);
- FastLED.addLeds<WS2812B, LED_STRIP_6_PIN, GRB>(STRIP_6, LED_STRIP_6_NUM);
- FastLED.addLeds<WS2812B, LED_STRIP_7_PIN, GRB>(STRIP_7, LED_STRIP_7_NUM);
- FastLED.addLeds<WS2812B, LED_STRIP_8_PIN, GRB>(STRIP_8, LED_STRIP_8_NUM);
- // Activate the current limit
- FastLED.setMaxPowerInVoltsAndMilliamps(5,MAX_CURRENT);
- //Activate hte brightness limit
- FastLED.setBrightness(BRIGHTNESS);
- // 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, spiFlag;
- int16_t
- bytesBuffered = 0,
- hold = 0,
- c;
- int32_t
- bytesRemaining;
- unsigned long
- startTime,
- lastByteTime,
- lastAckTime,
- t;
- int32_t outPos = 0;
- Serial.begin(SPEED); // Teensy/32u4 disregards baud rate; is OK!
- Serial.print("Ada\n"); // Send ACK string to host
- startTime = micros();
- lastByteTime = lastAckTime = millis();
- // loop() is avoided as even that small bit of function overhead
- // has a measurable impact on this code's overall throughput.
- for(;;) {
- // 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++;
- lastByteTime = lastAckTime = t; // Reset timeout counters
- }
- else {
- // No data received. If this persists, send an ACK packet
- // to host once every second to alert it to our presence.
- if((t - lastAckTime) > 1000) {
- Serial.print("Ada\n"); // Send ACK string to host
- lastAckTime = t; // Reset counter
- }
- // If no data received for an extended time, turn off all LEDs.
- if((t - lastByteTime) > serialTimeout) {
- memset(leds, 0, NUM_LEDS * sizeof(struct CRGB)); //filling Led array by zeroes
- 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<MAGICSIZE) && (buffer[indexOut++] == magic[i++]););
- if(i == MAGICSIZE) {
- // Magic word matches. Now how about the checksum?
- hi = buffer[indexOut++];
- lo = buffer[indexOut++];
- chk = buffer[indexOut++];
- 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);
- 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))
- ledsRaw[outPos++] = buffer[indexOut++]; // Issue next byte
- bytesBuffered--;
- bytesRemaining--;
- }
- // If serial buffer is threatening to underrun, start
- // introducing progressively longer pauses to allow more
- // data to arrive (up to a point).
- }
- else {
- // End of data -- issue latch:
- startTime = micros();
- mode = MODE_HEADER; // Begin next header search
- FastLED.show();
- }
- } // end switch
- } // end for(;;)
- }
- void loop()
- {
- // Not used. See note in setup() function.
- }
Advertisement
Add Comment
Please, Sign In to add comment