├── Arduino ├── LEDstream │ └── LEDstream.pde ├── LEDstream_CircuitPlayground │ └── LEDstream_CircuitPlayground.ino └── LEDstream_LPD8806 │ └── LEDstream_LPD8806.pde ├── C ├── Makefile └── colorswirl.c ├── COPYING ├── Processing ├── Adalight │ └── Adalight.pde ├── Adalight_CircuitPlayground │ └── Adalight_CircuitPlayground.pde └── Colorswirl │ └── Colorswirl.pde └── README.txt /Arduino/LEDstream/LEDstream.pde: -------------------------------------------------------------------------------- 1 | // Arduino "bridge" code between host computer and WS2801-based digital 2 | // RGB LED pixels (e.g. Adafruit product ID #322). Intended for use 3 | // with USB-native boards such as Teensy or Adafruit 32u4 Breakout; 4 | // works on normal serial Arduinos, but throughput is severely limited. 5 | // LED data is streamed, not buffered, making this suitable for larger 6 | // installations (e.g. video wall, etc.) than could otherwise be held 7 | // in the Arduino's limited RAM. 8 | 9 | // Some effort is put into avoiding buffer underruns (where the output 10 | // side becomes starved of data). The WS2801 latch protocol, being 11 | // delay-based, could be inadvertently triggered if the USB bus or CPU 12 | // is swamped with other tasks. This code buffers incoming serial data 13 | // and introduces intentional pauses if there's a threat of the buffer 14 | // draining prematurely. The cost of this complexity is somewhat 15 | // reduced throughput, the gain is that most visual glitches are 16 | // avoided (though ultimately a function of the load on the USB bus and 17 | // host CPU, and out of our control). 18 | 19 | // LED data and clock lines are connected to the Arduino's SPI output. 20 | // On traditional Arduino boards, SPI data out is digital pin 11 and 21 | // clock is digital pin 13. On both Teensy and the 32u4 Breakout, 22 | // data out is pin B2, clock is B1. LEDs should be externally 23 | // powered -- trying to run any more than just a few off the Arduino's 24 | // 5V line is generally a Bad Idea. LED ground should also be 25 | // connected to Arduino ground. 26 | 27 | // -------------------------------------------------------------------- 28 | // This file is part of Adalight. 29 | 30 | // Adalight is free software: you can redistribute it and/or modify 31 | // it under the terms of the GNU Lesser General Public License as 32 | // published by the Free Software Foundation, either version 3 of 33 | // the License, or (at your option) any later version. 34 | 35 | // Adalight is distributed in the hope that it will be useful, 36 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 37 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 38 | // GNU Lesser General Public License for more details. 39 | 40 | // You should have received a copy of the GNU Lesser General Public 41 | // License along with Adalight. If not, see 42 | // . 43 | // -------------------------------------------------------------------- 44 | 45 | #include 46 | 47 | // LED pin for Adafruit 32u4 Breakout Board: 48 | //#define LED_DDR DDRE 49 | //#define LED_PORT PORTE 50 | //#define LED_PIN _BV(PORTE6) 51 | // LED pin for Teensy: 52 | //#define LED_DDR DDRD 53 | //#define LED_PORT PORTD 54 | //#define LED_PIN _BV(PORTD6) 55 | // LED pin for Arduino: 56 | #define LED_DDR DDRB 57 | #define LED_PORT PORTB 58 | #define LED_PIN _BV(PORTB5) 59 | 60 | // A 'magic word' (along with LED count & checksum) precedes each block 61 | // of LED data; this assists the microcontroller in syncing up with the 62 | // host-side software and properly issuing the latch (host I/O is 63 | // likely buffered, making usleep() unreliable for latch). You may see 64 | // an initial glitchy frame or two until the two come into alignment. 65 | // The magic word can be whatever sequence you like, but each character 66 | // should be unique, and frequent pixel values like 0 and 255 are 67 | // avoided -- fewer false positives. The host software will need to 68 | // generate a compatible header: immediately following the magic word 69 | // are three bytes: a 16-bit count of the number of LEDs (high byte 70 | // first) followed by a simple checksum value (high byte XOR low byte 71 | // XOR 0x55). LED data follows, 3 bytes per LED, in order R, G, B, 72 | // where 0 = off and 255 = max brightness. 73 | 74 | static const uint8_t magic[] = {'A','d','a'}; 75 | #define MAGICSIZE sizeof(magic) 76 | #define HEADERSIZE (MAGICSIZE + 3) 77 | 78 | #define MODE_HEADER 0 79 | #define MODE_HOLD 1 80 | #define MODE_DATA 2 81 | 82 | // If no serial data is received for a while, the LEDs are shut off 83 | // automatically. This avoids the annoying "stuck pixel" look when 84 | // quitting LED display programs on the host computer. 85 | static const unsigned long serialTimeout = 15000; // 15 seconds 86 | 87 | void setup() 88 | { 89 | // Dirty trick: the circular buffer for serial data is 256 bytes, 90 | // and the "in" and "out" indices are unsigned 8-bit types -- this 91 | // much simplifies the cases where in/out need to "wrap around" the 92 | // beginning/end of the buffer. Otherwise there'd be a ton of bit- 93 | // masking and/or conditional code every time one of these indices 94 | // needs to change, slowing things down tremendously. 95 | uint8_t 96 | buffer[256], 97 | indexIn = 0, 98 | indexOut = 0, 99 | mode = MODE_HEADER, 100 | hi, lo, chk, i, spiFlag; 101 | int16_t 102 | bytesBuffered = 0, 103 | hold = 0, 104 | c; 105 | int32_t 106 | bytesRemaining; 107 | unsigned long 108 | startTime, 109 | lastByteTime, 110 | lastAckTime, 111 | t; 112 | 113 | LED_DDR |= LED_PIN; // Enable output for LED 114 | LED_PORT &= ~LED_PIN; // LED off 115 | 116 | Serial.begin(115200); // Teensy/32u4 disregards baud rate; is OK! 117 | 118 | SPI.begin(); 119 | SPI.setBitOrder(MSBFIRST); 120 | SPI.setDataMode(SPI_MODE0); 121 | SPI.setClockDivider(SPI_CLOCK_DIV16); // 1 MHz max, else flicker 122 | 123 | // Issue test pattern to LEDs on startup. This helps verify that 124 | // wiring between the Arduino and LEDs is correct. Not knowing the 125 | // actual number of LEDs connected, this sets all of them (well, up 126 | // to the first 1,000, so as not to be TOO time consuming) to red, 127 | // green, blue, then off. Once you're confident everything is working 128 | // end-to-end, it's OK to comment this out and reprogram the Arduino. 129 | uint8_t testcolor[] = { 0, 0, 0, 255, 0, 0 }; 130 | for(char n=3; n>=0; n--) { 131 | for(c=0; c<1000; c++) { 132 | for(i=0; i<3; i++) { 133 | for(SPDR = testcolor[n + i]; !(SPSR & _BV(SPIF)); ); 134 | } 135 | } 136 | delay(1); // One millisecond pause = latch 137 | } 138 | 139 | Serial.print("Ada\n"); // Send ACK string to host 140 | 141 | startTime = micros(); 142 | lastByteTime = lastAckTime = millis(); 143 | 144 | // loop() is avoided as even that small bit of function overhead 145 | // has a measurable impact on this code's overall throughput. 146 | 147 | for(;;) { 148 | 149 | // Implementation is a simple finite-state machine. 150 | // Regardless of mode, check for serial input each time: 151 | t = millis(); 152 | if((bytesBuffered < 256) && ((c = Serial.read()) >= 0)) { 153 | buffer[indexIn++] = c; 154 | bytesBuffered++; 155 | lastByteTime = lastAckTime = t; // Reset timeout counters 156 | } else { 157 | // No data received. If this persists, send an ACK packet 158 | // to host once every second to alert it to our presence. 159 | if((t - lastAckTime) > 1000) { 160 | Serial.print("Ada\n"); // Send ACK string to host 161 | lastAckTime = t; // Reset counter 162 | } 163 | // If no data received for an extended time, turn off all LEDs. 164 | if((t - lastByteTime) > serialTimeout) { 165 | for(c=0; c<32767; c++) { 166 | for(SPDR=0; !(SPSR & _BV(SPIF)); ); 167 | } 168 | delay(1); // One millisecond pause = latch 169 | lastByteTime = t; // Reset counter 170 | } 171 | } 172 | 173 | switch(mode) { 174 | 175 | case MODE_HEADER: 176 | 177 | // In header-seeking mode. Is there enough data to check? 178 | if(bytesBuffered >= HEADERSIZE) { 179 | // Indeed. Check for a 'magic word' match. 180 | for(i=0; (i 0) and multiply by 3 for R,G,B. 189 | bytesRemaining = 3L * (256L * (long)hi + (long)lo + 1L); 190 | bytesBuffered -= 3; 191 | spiFlag = 0; // No data out yet 192 | mode = MODE_HOLD; // Proceed to latch wait mode 193 | } else { 194 | // Checksum didn't match; search resumes after magic word. 195 | indexOut -= 3; // Rewind 196 | } 197 | } // else no header match. Resume at first mismatched byte. 198 | bytesBuffered -= i; 199 | } 200 | break; 201 | 202 | case MODE_HOLD: 203 | 204 | // Ostensibly "waiting for the latch from the prior frame 205 | // to complete" mode, but may also revert to this mode when 206 | // underrun prevention necessitates a delay. 207 | 208 | if((micros() - startTime) < hold) break; // Still holding; keep buffering 209 | 210 | // Latch/delay complete. Advance to data-issuing mode... 211 | LED_PORT &= ~LED_PIN; // LED off 212 | mode = MODE_DATA; // ...and fall through (no break): 213 | 214 | case MODE_DATA: 215 | 216 | while(spiFlag && !(SPSR & _BV(SPIF))); // Wait for prior byte 217 | if(bytesRemaining > 0) { 218 | if(bytesBuffered > 0) { 219 | SPDR = buffer[indexOut++]; // Issue next byte 220 | bytesBuffered--; 221 | bytesRemaining--; 222 | spiFlag = 1; 223 | } 224 | // If serial buffer is threatening to underrun, start 225 | // introducing progressively longer pauses to allow more 226 | // data to arrive (up to a point). 227 | if((bytesBuffered < 32) && (bytesRemaining > bytesBuffered)) { 228 | startTime = micros(); 229 | hold = 64 + (32 - bytesBuffered) * 4; 230 | mode = MODE_HOLD; 231 | } 232 | } else { 233 | // End of data -- issue latch: 234 | startTime = micros(); 235 | hold = 1000; // Latch duration = 1000 uS 236 | LED_PORT |= LED_PIN; // LED on 237 | mode = MODE_HEADER; // Begin next header search 238 | } 239 | } // end switch 240 | } // end for(;;) 241 | } 242 | 243 | void loop() 244 | { 245 | // Not used. See note in setup() function. 246 | } 247 | -------------------------------------------------------------------------------- /Arduino/LEDstream_CircuitPlayground/LEDstream_CircuitPlayground.ino: -------------------------------------------------------------------------------- 1 | // This is a pared-down version of the LEDstream sketch specifically 2 | // for Circuit Playground. It is NOT a generic solution to NeoPixel 3 | // support with Adalight! The NeoPixel library disables interrupts 4 | // while issuing data...but Serial transfers depend on interrupts. 5 | // This code works (or appears to work, it hasn't been extensively 6 | // battle-tested) only because of the finite number of pixels (10) 7 | // on the Circuit Playground board. With 10 NeoPixels, interrupts are 8 | // off for about 300 microseconds...but if the incoming data rate is 9 | // sufficiently limited (<= 60 FPS or so with the given number of 10 | // pixels), things seem OK, no data is missed. Balancing act! 11 | 12 | // -------------------------------------------------------------------- 13 | // This file is part of Adalight. 14 | 15 | // Adalight is free software: you can redistribute it and/or modify 16 | // it under the terms of the GNU Lesser General Public License as 17 | // published by the Free Software Foundation, either version 3 of 18 | // the License, or (at your option) any later version. 19 | 20 | // Adalight is distributed in the hope that it will be useful, 21 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | // GNU Lesser General Public License for more details. 24 | 25 | // You should have received a copy of the GNU Lesser General Public 26 | // License along with Adalight. If not, see 27 | // . 28 | // -------------------------------------------------------------------- 29 | 30 | #include "Adafruit_CircuitPlayground.h" 31 | 32 | static const uint8_t magic[] = { 'A','d','a' }; 33 | #define MAGICSIZE sizeof(magic) 34 | #define HEADERSIZE (MAGICSIZE + 3) 35 | static uint8_t 36 | buffer[HEADERSIZE], // Serial input buffer 37 | bytesBuffered = 0; // Amount of data in buffer 38 | 39 | static const unsigned long serialTimeout = 15000; // 15 seconds 40 | static unsigned long lastByteTime; 41 | 42 | void setup() { 43 | CircuitPlayground.begin(); 44 | CircuitPlayground.setBrightness(255); // LEDs full blast! 45 | CircuitPlayground.strip.clear(); 46 | CircuitPlayground.strip.show(); 47 | 48 | Serial.begin(38400); 49 | 50 | lastByteTime = millis(); // Initialize timers 51 | } 52 | 53 | // Function is called when no pending serial data is available. 54 | static boolean timeout( 55 | unsigned long t, // Current time, milliseconds 56 | int nLEDs) { // Number of LEDs 57 | 58 | // If no data received for an extended time, turn off all LEDs. 59 | if((t - lastByteTime) > serialTimeout) { 60 | CircuitPlayground.strip.clear(); 61 | CircuitPlayground.strip.show(); 62 | lastByteTime = t; // Reset counter 63 | bytesBuffered = 0; // Clear serial buffer 64 | return true; 65 | } 66 | 67 | return false; // No timeout 68 | } 69 | 70 | void loop() { 71 | uint8_t i, hi, lo, byteNum; 72 | int c; 73 | long nLEDs, pixelNum; 74 | unsigned long t; 75 | 76 | // HEADER-SEEKING BLOCK: locate 'magic word' at start of frame. 77 | 78 | // If any data in serial buffer, shift it down to starting position. 79 | for(i=0; i= 0) { // Data received? 86 | buffer[bytesBuffered++] = c; // Store in buffer 87 | lastByteTime = t; // Reset timeout counter 88 | } else { // No data, check for timeout... 89 | if(timeout(t, 10000) == true) return; // Start over 90 | } 91 | } 92 | 93 | // Have a header's worth of data. Check for 'magic word' match. 94 | for(i=0; i 0) 111 | nLEDs = 256L * (long)hi + (long)lo + 1L; 112 | bytesBuffered = 0; // Clear serial buffer 113 | byteNum = 0; 114 | 115 | // DATA-FORWARDING BLOCK: move bytes from serial input to NeoPixels. 116 | 117 | for(pixelNum = 0; pixelNum < nLEDs; ) { // While more LED data is expected... 118 | t = millis(); 119 | if((c = Serial.read()) >= 0) { // Successful read? 120 | lastByteTime = t; // Reset timeout counters 121 | buffer[byteNum++] = c; // Store in data buffer 122 | if(byteNum == 3) { // Have a full LED's worth? 123 | CircuitPlayground.strip.setPixelColor(pixelNum++, 124 | buffer[0], buffer[1], buffer[2]); 125 | byteNum = 0; 126 | } 127 | } else { // No data, check for timeout... 128 | if(timeout(t, nLEDs) == true) return; // Start over 129 | } 130 | } 131 | 132 | CircuitPlayground.strip.show(); 133 | } 134 | 135 | -------------------------------------------------------------------------------- /Arduino/LEDstream_LPD8806/LEDstream_LPD8806.pde: -------------------------------------------------------------------------------- 1 | // Arduino bridge code between host computer and LPD8806-based digital 2 | // addressable RGB LEDs (e.g. Adafruit product ID #306). LED data is 3 | // streamed, not buffered, making this suitable for larger installations 4 | // (e.g. video wall, etc.) than could otherwise be contained within the 5 | // Arduino's limited RAM. Intended for use with USB-native boards such 6 | // as Teensy or Adafruit 32u4 Breakout; also works on normal serial 7 | // Arduinos (Uno, etc.), but speed will be limited by the serial port. 8 | 9 | // LED data and clock lines are connected to the Arduino's SPI output. 10 | // On traditional Arduino boards (e.g. Uno), SPI data out is digital pin 11 | // 11 and clock is digital pin 13. On both Teensy and the 32u4 Breakout, 12 | // data out is pin B2, clock is B1. On Arduino Mega, 51=data, 52=clock. 13 | // LEDs should be externally powered -- trying to run any more than just 14 | // a few off the Arduino's 5V line is generally a Bad Idea. LED ground 15 | // should also be connected to Arduino ground. 16 | 17 | // Elsewhere, the WS2801 version of this code was specifically designed 18 | // to avoid buffer underrun conditions...the WS2801 pixels automatically 19 | // latch when the data stream stops for 500 microseconds or more, whether 20 | // intentional or not. The LPD8806 pixels are fundamentally different -- 21 | // the latch condition is indicated within the data stream, not by pausing 22 | // the clock -- and buffer underruns are therefore a non-issue. In theory 23 | // it would seem this could allow the code to be much simpler and faster 24 | // (there's no need to sync up with a start-of-frame header), but in 25 | // practice the difference was not as pronounced as expected -- such code 26 | // soon ran up against a USB throughput limit anyway. So, rather than 27 | // break compatibility in the quest for speed that will never materialize, 28 | // this code instead follows the same header format as the WS2801 version. 29 | // This allows the same host-side code (e.g. Adalight, Adavision, etc.) 30 | // to run with either type of LED pixels. Huzzah! 31 | 32 | // -------------------------------------------------------------------- 33 | // This file is part of Adalight. 34 | 35 | // Adalight is free software: you can redistribute it and/or modify 36 | // it under the terms of the GNU Lesser General Public License as 37 | // published by the Free Software Foundation, either version 3 of 38 | // the License, or (at your option) any later version. 39 | 40 | // Adalight is distributed in the hope that it will be useful, 41 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 42 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 43 | // GNU Lesser General Public License for more details. 44 | 45 | // You should have received a copy of the GNU Lesser General Public 46 | // License along with Adalight. If not, see 47 | // . 48 | // -------------------------------------------------------------------- 49 | 50 | #include 51 | 52 | // A 'magic word' precedes each block of LED data; this assists the 53 | // microcontroller in syncing up with the host-side software and latching 54 | // frames at the correct time. You may see an initial glitchy frame or 55 | // two until the two come into alignment. Immediately following the 56 | // magic word are three bytes: a 16-bit count of the number of LEDs (high 57 | // byte first) followed by a simple checksum value (high byte XOR low byte 58 | // XOR 0x55). LED data follows, 3 bytes per LED, in order R, G, B, where 59 | // 0 = off and 255 = max brightness. LPD8806 pixels only have 7-bit 60 | // brightness control, so each value is divided by two; the 8-bit format 61 | // is used to maintain compatibility with the protocol set forth by the 62 | // WS2801 streaming code (those LEDs use 8-bit values). 63 | static const uint8_t magic[] = { 'A','d','a' }; 64 | #define MAGICSIZE sizeof(magic) 65 | #define HEADERSIZE (MAGICSIZE + 3) 66 | static uint8_t 67 | buffer[HEADERSIZE], // Serial input buffer 68 | bytesBuffered = 0; // Amount of data in buffer 69 | 70 | // If no serial data is received for a while, the LEDs are shut off 71 | // automatically. This avoids the annoying "stuck pixel" look when 72 | // quitting LED display programs on the host computer. 73 | static const unsigned long serialTimeout = 15000; // 15 seconds 74 | static unsigned long lastByteTime, lastAckTime; 75 | 76 | void setup() { 77 | byte c; 78 | int i, p; 79 | 80 | Serial.begin(115200); // 32u4 will ignore BPS and run full speed 81 | 82 | // SPI is run at 2 MHz. LPD8806 can run much faster, 83 | // but unshielded wiring is susceptible to interference. 84 | // Feel free to experiment with other divider ratios. 85 | SPI.begin(); 86 | SPI.setBitOrder(MSBFIRST); 87 | SPI.setDataMode(SPI_MODE0); 88 | SPI.setClockDivider(SPI_CLOCK_DIV8); // 2 MHz 89 | 90 | // Issue dummy byte to "prime" the SPI bus. This later simplifies 91 | // the task of doing useful work during SPI transfers. Rather than 92 | // the usual issue-and-wait-loop, code can instead wait-and-issue -- 93 | // with other operations occurring between transfers, the wait is 94 | // then shortened or eliminated. The SPSR register is read-only, 95 | // so this flag can't be forced -- SOMETHING must be issued. 96 | SPDR = 0; 97 | 98 | // Issue initial latch to LEDs. This flushes any undefined data that 99 | // may exist on powerup, and prepares the LEDs to receive the first 100 | // frame of data. Actual number of LEDs isn't known yet (this arrives 101 | // later in frame header packets), so just latch a large number: 102 | latch(10000); 103 | 104 | // Issue test pattern to LEDs on startup. This helps verify that 105 | // wiring between the Arduino and LEDs is correct. Again not knowing 106 | // the actual number of LEDs, this writes data for an arbitrarily 107 | // large number (10K). If wiring is correct, LEDs will all light 108 | // red, green, blue on startup, then off. Once you're confident 109 | // everything is working end-to-end, it's OK to comment this out and 110 | // re-upload the sketch to the Arduino. 111 | const uint8_t testColor[] = { 0x80, 0x80, 0xff, 0x80, 0x80, 0x80 }, 112 | testOffset[] = { 1, 2, 0, 3 }; 113 | for(c=0; c<4; c++) { // for each test sequence color... 114 | for(p=0; p<10000; p++) { // for each pixel... 115 | for(i=0; i<3; i++) { // for each R,G,B... 116 | while(!(SPSR & _BV(SPIF))); // Wait for prior byte out 117 | SPDR = testColor[testOffset[c] + i]; // Issue next byte 118 | } 119 | } 120 | latch(10000); 121 | if(c < 3) delay(250); 122 | } 123 | 124 | Serial.print("Ada\n"); // Send ACK string to host 125 | lastByteTime = lastAckTime = millis(); // Initialize timers 126 | } 127 | 128 | // Program flow is simpler than the WS2801 code. No need for a state 129 | // machine...instead, software just alternates between two conditions: 130 | // a header-seeking mode (looking for the 'magic word' at the start 131 | // of each frame of data), and a data-forwarding mode (moving bytes 132 | // from serial input to SPI output). A proper data stream will 133 | // consist only of alternating valid headers and valid data, so the 134 | // loop() function is simply divided into these two parts, and repeats 135 | // forever. 136 | 137 | // LPD8806 pixels expect colors in G,R,B order vs. WS2801's R,G,B. 138 | // This is used to shuffle things around later. 139 | static const uint8_t byteOrder[] = { 2, 0, 1 }; 140 | 141 | void loop() { 142 | uint8_t i, hi, lo, byteNum; 143 | int c; 144 | long nLEDs, remaining; 145 | unsigned long t; 146 | 147 | // HEADER-SEEKING BLOCK: locate 'magic word' at start of frame. 148 | 149 | // If any data in serial buffer, shift it down to starting position. 150 | for(i=0; i= 0) { // Data received? 157 | buffer[bytesBuffered++] = c; // Store in buffer 158 | lastByteTime = lastAckTime = t; // Reset timeout counters 159 | } else { // No data, check for timeout... 160 | if(timeout(t, 10000) == true) return; // Start over 161 | } 162 | } 163 | 164 | // Have a header's worth of data. Check for 'magic word' match. 165 | for(i=0; i 0) 182 | nLEDs = remaining = 256L * (long)hi + (long)lo + 1L; 183 | bytesBuffered = 0; // Clear serial buffer 184 | byteNum = 0; 185 | 186 | // DATA-FORWARDING BLOCK: move bytes from serial input to SPI output. 187 | 188 | // Unfortunately can't just forward bytes directly. The data order is 189 | // different on LPD8806 (G,R,B), so bytes are buffered in groups of 3 190 | // and issued in the revised order. 191 | 192 | while(remaining > 0) { // While more LED data is expected... 193 | t = millis(); 194 | if((c = Serial.read()) >= 0) { // Successful read? 195 | lastByteTime = lastAckTime = t; // Reset timeout counters 196 | buffer[byteNum++] = c; // Store in data buffer 197 | if(byteNum == 3) { // Have a full LED's worth? 198 | while(byteNum > 0) { // Issue data in LPD8806 order... 199 | i = 0x80 | (buffer[byteOrder[--byteNum]] >> 1); 200 | while(!(SPSR & _BV(SPIF))); // Wait for prior byte out 201 | SPDR = i; // Issue new byte 202 | } 203 | remaining--; 204 | } 205 | } else { // No data, check for timeout... 206 | if(timeout(t, nLEDs) == true) return; // Start over 207 | } 208 | } 209 | 210 | // Normal end of data. Issue latch, return to header-seeking mode. 211 | latch(nLEDs); 212 | } 213 | 214 | static void latch(int n) { // Pass # of LEDs 215 | n = ((n + 63) / 64) * 3; // Convert to latch length (bytes) 216 | while(n--) { // For each latch byte... 217 | while(!(SPSR & _BV(SPIF))); // Wait for prior byte out 218 | SPDR = 0; // Issue next byte 219 | } 220 | } 221 | 222 | // Function is called when no pending serial data is available. 223 | static boolean timeout( 224 | unsigned long t, // Current time, milliseconds 225 | int nLEDs) { // Number of LEDs 226 | 227 | // If condition persists, send an ACK packet to host once every 228 | // second to alert it to our presence. 229 | if((t - lastAckTime) > 1000) { 230 | Serial.print("Ada\n"); // Send ACK string to host 231 | lastAckTime = t; // Reset counter 232 | } 233 | 234 | // If no data received for an extended time, turn off all LEDs. 235 | if((t - lastByteTime) > serialTimeout) { 236 | long bytes = nLEDs * 3L; 237 | latch(nLEDs); // Latch any partial/incomplete data in strand 238 | while(bytes--) { // Issue all new data to turn off strand 239 | while(!(SPSR & _BV(SPIF))); // Wait for prior byte out 240 | SPDR = 0x80; // Issue next byte (0x80 = LED off) 241 | } 242 | latch(nLEDs); // Latch 'all off' data 243 | lastByteTime = t; // Reset counter 244 | bytesBuffered = 0; // Clear serial buffer 245 | return true; 246 | } 247 | 248 | return false; // No timeout 249 | } 250 | 251 | -------------------------------------------------------------------------------- /C/Makefile: -------------------------------------------------------------------------------- 1 | EXECS = colorswirl 2 | 3 | all: $(EXECS) 4 | 5 | colorswirl: colorswirl.c 6 | cc -O2 colorswirl.c -lm -o colorswirl 7 | 8 | clean: 9 | rm -f $(EXECS) *.o 10 | -------------------------------------------------------------------------------- /C/colorswirl.c: -------------------------------------------------------------------------------- 1 | /* 2 | "Colorswirl" LED demo. This is the host PC-side code written in C; 3 | intended for use with a USB-connected Arduino microcontroller running the 4 | accompanying LED streaming code. Requires one strand of Digital RGB LED 5 | Pixels (Adafruit product ID #322, specifically the newer WS2801-based type, 6 | strand of 25) and a 5 Volt power supply (such as Adafruit #276). You may 7 | need to adapt the code and the hardware arrangement for your specific 8 | configuration. 9 | 10 | This is a command-line program. It expects a single parameter, which is 11 | the serial port device name, e.g.: 12 | 13 | ./colorswirl /dev/tty.usbserial-A60049KO 14 | 15 | */ 16 | 17 | // -------------------------------------------------------------------- 18 | // This file is part of Adalight. 19 | 20 | // Adalight is free software: you can redistribute it and/or modify 21 | // it under the terms of the GNU Lesser General Public License as 22 | // published by the Free Software Foundation, either version 3 of 23 | // the License, or (at your option) any later version. 24 | 25 | // Adalight is distributed in the hope that it will be useful, 26 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | // GNU Lesser General Public License for more details. 29 | 30 | // You should have received a copy of the GNU Lesser General Public 31 | // License along with Adalight. If not, see 32 | // . 33 | // -------------------------------------------------------------------- 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #define N_LEDS 25 // Max of 65536 43 | 44 | int main(int argc,char *argv[]) 45 | { 46 | int fd, i, bytesToGo, bytesSent, totalBytesSent = 0, 47 | frame = 0, hue1, hue2, brightness; 48 | unsigned char buffer[6 + (N_LEDS * 3)], // Header + 3 bytes per LED 49 | lo, r, g, b; 50 | double sine1, sine2; 51 | time_t t, start, prev; 52 | struct termios tty; 53 | 54 | if(argc < 2) { 55 | (void)printf("Usage: %s device\n", argv[0]); 56 | return 1; 57 | } 58 | 59 | if((fd = open(argv[1],O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0) { 60 | (void)printf("Can't open device '%s'.\n", argv[1]); 61 | return 1; 62 | } 63 | 64 | // Serial port config swiped from RXTX library (rxtx.qbang.org): 65 | tcgetattr(fd, &tty); 66 | tty.c_iflag = INPCK; 67 | tty.c_lflag = 0; 68 | tty.c_oflag = 0; 69 | tty.c_cflag = CREAD | CS8 | CLOCAL; 70 | tty.c_cc[ VMIN ] = 0; 71 | tty.c_cc[ VTIME ] = 0; 72 | cfsetispeed(&tty, B115200); 73 | cfsetospeed(&tty, B115200); 74 | tcsetattr(fd, TCSANOW, &tty); 75 | 76 | bzero(buffer, sizeof(buffer)); // Clear LED buffer 77 | 78 | // Header only needs to be initialized once, not 79 | // inside rendering loop -- number of LEDs is constant: 80 | buffer[0] = 'A'; // Magic word 81 | buffer[1] = 'd'; 82 | buffer[2] = 'a'; 83 | buffer[3] = (N_LEDS - 1) >> 8; // LED count high byte 84 | buffer[4] = (N_LEDS - 1) & 0xff; // LED count low byte 85 | buffer[5] = buffer[3] ^ buffer[4] ^ 0x55; // Checksum 86 | 87 | sine1 = 0.0; 88 | hue1 = 0; 89 | prev = start = time(NULL); // For bandwidth statistics 90 | 91 | for(;;) { 92 | sine2 = sine1; 93 | hue2 = hue1; 94 | 95 | // Start at position 6, after the LED header/magic word 96 | for(i = 6; i < sizeof(buffer); ) { 97 | // Fixed-point hue-to-RGB conversion. 'hue2' is an 98 | // integer in the range of 0 to 1535, where 0 = red, 99 | // 256 = yellow, 512 = green, etc. The high byte 100 | // (0-5) corresponds to the sextant within the color 101 | // wheel, while the low byte (0-255) is the 102 | // fractional part between primary/secondary colors. 103 | lo = hue2 & 255; 104 | switch((hue2 >> 8) % 6) { 105 | case 0: 106 | r = 255; 107 | g = lo; 108 | b = 0; 109 | break; 110 | case 1: 111 | r = 255 - lo; 112 | g = 255; 113 | b = 0; 114 | break; 115 | case 2: 116 | r = 0; 117 | g = 255; 118 | b = lo; 119 | break; 120 | case 3: 121 | r = 0; 122 | g = 255 - lo; 123 | b = 255; 124 | break; 125 | case 4: 126 | r = lo; 127 | g = 0; 128 | b = 255; 129 | break; 130 | case 5: 131 | r = 255; 132 | g = 0; 133 | b = 255 - lo; 134 | break; 135 | } 136 | 137 | // Resulting hue is multiplied by brightness in the 138 | // range of 0 to 255 (0 = off, 255 = brightest). 139 | // Gamma corrrection (the 'pow' function here) adjusts 140 | // the brightness to be more perceptually linear. 141 | brightness = (int)(pow(0.5+sin(sine2)*0.5,3.0)*255.0); 142 | buffer[i++] = (r * brightness) / 255; 143 | buffer[i++] = (g * brightness) / 255; 144 | buffer[i++] = (b * brightness) / 255; 145 | 146 | // Each pixel is offset in both hue and brightness 147 | hue2 += 40; 148 | sine2 += 0.3; 149 | } 150 | 151 | // Slowly rotate hue and brightness in opposite directions 152 | hue1 = (hue1 + 5) % 1536; 153 | sine1 -= .03; 154 | 155 | // Issue color data to LEDs. Each OS is fussy in different 156 | // ways about serial output. This arrangement of drain-and- 157 | // write-loop seems to be the most relable across platforms: 158 | tcdrain(fd); 159 | for(bytesSent=0, bytesToGo=sizeof(buffer); bytesToGo > 0;) { 160 | if((i=write(fd,&buffer[bytesSent],bytesToGo)) > 0) { 161 | bytesToGo -= i; 162 | bytesSent += i; 163 | } 164 | } 165 | // Keep track of byte and frame counts for statistics 166 | totalBytesSent += sizeof(buffer); 167 | frame++; 168 | 169 | // Update statistics once per second 170 | if((t = time(NULL)) != prev) { 171 | (void)printf( 172 | "Average frames/sec: %d, bytes/sec: %d\n", 173 | (int)((float)frame / (float)(t - start)), 174 | (int)((float)totalBytesSent / (float)(t - start))); 175 | prev = t; 176 | } 177 | } 178 | 179 | close(fd); 180 | return 0; 181 | } 182 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | 2 | GNU GENERAL PUBLIC LICENSE 3 | Version 3, 29 June 2007 4 | 5 | Copyright (C) 2007 Free Software Foundation, Inc. 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The GNU General Public License is a free, copyleft license for 12 | software and other kinds of works. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | the GNU General Public License is intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. We, the Free Software Foundation, use the 19 | GNU General Public License for most of our software; it applies also to 20 | any other work released this way by its authors. You can apply it to 21 | your programs, too. 22 | 23 | When we speak of free software, we are referring to freedom, not 24 | price. Our General Public Licenses are designed to make sure that you 25 | have the freedom to distribute copies of free software (and charge for 26 | them if you wish), that you receive source code or can get it if you 27 | want it, that you can change the software or use pieces of it in new 28 | free programs, and that you know you can do these things. 29 | 30 | To protect your rights, we need to prevent others from denying you 31 | these rights or asking you to surrender the rights. Therefore, you have 32 | certain responsibilities if you distribute copies of the software, or if 33 | you modify it: responsibilities to respect the freedom of others. 34 | 35 | For example, if you distribute copies of such a program, whether 36 | gratis or for a fee, you must pass on to the recipients the same 37 | freedoms that you received. You must make sure that they, too, receive 38 | or can get the source code. And you must show them these terms so they 39 | know their rights. 40 | 41 | Developers that use the GNU GPL protect your rights with two steps: 42 | (1) assert copyright on the software, and (2) offer you this License 43 | giving you legal permission to copy, distribute and/or modify it. 44 | 45 | For the developers' and authors' protection, the GPL clearly explains 46 | that there is no warranty for this free software. For both users' and 47 | authors' sake, the GPL requires that modified versions be marked as 48 | changed, so that their problems will not be attributed erroneously to 49 | authors of previous versions. 50 | 51 | Some devices are designed to deny users access to install or run 52 | modified versions of the software inside them, although the manufacturer 53 | can do so. This is fundamentally incompatible with the aim of 54 | protecting users' freedom to change the software. The systematic 55 | pattern of such abuse occurs in the area of products for individuals to 56 | use, which is precisely where it is most unacceptable. Therefore, we 57 | have designed this version of the GPL to prohibit the practice for those 58 | products. If such problems arise substantially in other domains, we 59 | stand ready to extend this provision to those domains in future versions 60 | of the GPL, as needed to protect the freedom of users. 61 | 62 | Finally, every program is threatened constantly by software patents. 63 | States should not allow patents to restrict development and use of 64 | software on general-purpose computers, but in those that do, we wish to 65 | avoid the special danger that patents applied to a free program could 66 | make it effectively proprietary. To prevent this, the GPL assures that 67 | patents cannot be used to render the program non-free. 68 | 69 | The precise terms and conditions for copying, distribution and 70 | modification follow. 71 | 72 | TERMS AND CONDITIONS 73 | 74 | 0. Definitions. 75 | 76 | "This License" refers to version 3 of the GNU General Public License. 77 | 78 | "Copyright" also means copyright-like laws that apply to other kinds of 79 | works, such as semiconductor masks. 80 | 81 | "The Program" refers to any copyrightable work licensed under this 82 | License. Each licensee is addressed as "you". "Licensees" and 83 | "recipients" may be individuals or organizations. 84 | 85 | To "modify" a work means to copy from or adapt all or part of the work 86 | in a fashion requiring copyright permission, other than the making of an 87 | exact copy. The resulting work is called a "modified version" of the 88 | earlier work or a work "based on" the earlier work. 89 | 90 | A "covered work" means either the unmodified Program or a work based 91 | on the Program. 92 | 93 | To "propagate" a work means to do anything with it that, without 94 | permission, would make you directly or secondarily liable for 95 | infringement under applicable copyright law, except executing it on a 96 | computer or modifying a private copy. Propagation includes copying, 97 | distribution (with or without modification), making available to the 98 | public, and in some countries other activities as well. 99 | 100 | To "convey" a work means any kind of propagation that enables other 101 | parties to make or receive copies. Mere interaction with a user through 102 | a computer network, with no transfer of a copy, is not conveying. 103 | 104 | An interactive user interface displays "Appropriate Legal Notices" 105 | to the extent that it includes a convenient and prominently visible 106 | feature that (1) displays an appropriate copyright notice, and (2) 107 | tells the user that there is no warranty for the work (except to the 108 | extent that warranties are provided), that licensees may convey the 109 | work under this License, and how to view a copy of this License. If 110 | the interface presents a list of user commands or options, such as a 111 | menu, a prominent item in the list meets this criterion. 112 | 113 | 1. Source Code. 114 | 115 | The "source code" for a work means the preferred form of the work 116 | for making modifications to it. "Object code" means any non-source 117 | form of a work. 118 | 119 | A "Standard Interface" means an interface that either is an official 120 | standard defined by a recognized standards body, or, in the case of 121 | interfaces specified for a particular programming language, one that 122 | is widely used among developers working in that language. 123 | 124 | The "System Libraries" of an executable work include anything, other 125 | than the work as a whole, that (a) is included in the normal form of 126 | packaging a Major Component, but which is not part of that Major 127 | Component, and (b) serves only to enable use of the work with that 128 | Major Component, or to implement a Standard Interface for which an 129 | implementation is available to the public in source code form. A 130 | "Major Component", in this context, means a major essential component 131 | (kernel, window system, and so on) of the specific operating system 132 | (if any) on which the executable work runs, or a compiler used to 133 | produce the work, or an object code interpreter used to run it. 134 | 135 | The "Corresponding Source" for a work in object code form means all 136 | the source code needed to generate, install, and (for an executable 137 | work) run the object code and to modify the work, including scripts to 138 | control those activities. However, it does not include the work's 139 | System Libraries, or general-purpose tools or generally available free 140 | programs which are used unmodified in performing those activities but 141 | which are not part of the work. For example, Corresponding Source 142 | includes interface definition files associated with source files for 143 | the work, and the source code for shared libraries and dynamically 144 | linked subprograms that the work is specifically designed to require, 145 | such as by intimate data communication or control flow between those 146 | subprograms and other parts of the work. 147 | 148 | The Corresponding Source need not include anything that users 149 | can regenerate automatically from other parts of the Corresponding 150 | Source. 151 | 152 | The Corresponding Source for a work in source code form is that 153 | same work. 154 | 155 | 2. Basic Permissions. 156 | 157 | All rights granted under this License are granted for the term of 158 | copyright on the Program, and are irrevocable provided the stated 159 | conditions are met. This License explicitly affirms your unlimited 160 | permission to run the unmodified Program. The output from running a 161 | covered work is covered by this License only if the output, given its 162 | content, constitutes a covered work. This License acknowledges your 163 | rights of fair use or other equivalent, as provided by copyright law. 164 | 165 | You may make, run and propagate covered works that you do not 166 | convey, without conditions so long as your license otherwise remains 167 | in force. You may convey covered works to others for the sole purpose 168 | of having them make modifications exclusively for you, or provide you 169 | with facilities for running those works, provided that you comply with 170 | the terms of this License in conveying all material for which you do 171 | not control copyright. Those thus making or running the covered works 172 | for you must do so exclusively on your behalf, under your direction 173 | and control, on terms that prohibit them from making any copies of 174 | your copyrighted material outside their relationship with you. 175 | 176 | Conveying under any other circumstances is permitted solely under 177 | the conditions stated below. Sublicensing is not allowed; section 10 178 | makes it unnecessary. 179 | 180 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 181 | 182 | No covered work shall be deemed part of an effective technological 183 | measure under any applicable law fulfilling obligations under article 184 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 185 | similar laws prohibiting or restricting circumvention of such 186 | measures. 187 | 188 | When you convey a covered work, you waive any legal power to forbid 189 | circumvention of technological measures to the extent such circumvention 190 | is effected by exercising rights under this License with respect to 191 | the covered work, and you disclaim any intention to limit operation or 192 | modification of the work as a means of enforcing, against the work's 193 | users, your or third parties' legal rights to forbid circumvention of 194 | technological measures. 195 | 196 | 4. Conveying Verbatim Copies. 197 | 198 | You may convey verbatim copies of the Program's source code as you 199 | receive it, in any medium, provided that you conspicuously and 200 | appropriately publish on each copy an appropriate copyright notice; 201 | keep intact all notices stating that this License and any 202 | non-permissive terms added in accord with section 7 apply to the code; 203 | keep intact all notices of the absence of any warranty; and give all 204 | recipients a copy of this License along with the Program. 205 | 206 | You may charge any price or no price for each copy that you convey, 207 | and you may offer support or warranty protection for a fee. 208 | 209 | 5. Conveying Modified Source Versions. 210 | 211 | You may convey a work based on the Program, or the modifications to 212 | produce it from the Program, in the form of source code under the 213 | terms of section 4, provided that you also meet all of these conditions: 214 | 215 | a) The work must carry prominent notices stating that you modified 216 | it, and giving a relevant date. 217 | 218 | b) The work must carry prominent notices stating that it is 219 | released under this License and any conditions added under section 220 | 7. This requirement modifies the requirement in section 4 to 221 | "keep intact all notices". 222 | 223 | c) You must license the entire work, as a whole, under this 224 | License to anyone who comes into possession of a copy. This 225 | License will therefore apply, along with any applicable section 7 226 | additional terms, to the whole of the work, and all its parts, 227 | regardless of how they are packaged. This License gives no 228 | permission to license the work in any other way, but it does not 229 | invalidate such permission if you have separately received it. 230 | 231 | d) If the work has interactive user interfaces, each must display 232 | Appropriate Legal Notices; however, if the Program has interactive 233 | interfaces that do not display Appropriate Legal Notices, your 234 | work need not make them do so. 235 | 236 | A compilation of a covered work with other separate and independent 237 | works, which are not by their nature extensions of the covered work, 238 | and which are not combined with it such as to form a larger program, 239 | in or on a volume of a storage or distribution medium, is called an 240 | "aggregate" if the compilation and its resulting copyright are not 241 | used to limit the access or legal rights of the compilation's users 242 | beyond what the individual works permit. Inclusion of a covered work 243 | in an aggregate does not cause this License to apply to the other 244 | parts of the aggregate. 245 | 246 | 6. Conveying Non-Source Forms. 247 | 248 | You may convey a covered work in object code form under the terms 249 | of sections 4 and 5, provided that you also convey the 250 | machine-readable Corresponding Source under the terms of this License, 251 | in one of these ways: 252 | 253 | a) Convey the object code in, or embodied in, a physical product 254 | (including a physical distribution medium), accompanied by the 255 | Corresponding Source fixed on a durable physical medium 256 | customarily used for software interchange. 257 | 258 | b) Convey the object code in, or embodied in, a physical product 259 | (including a physical distribution medium), accompanied by a 260 | written offer, valid for at least three years and valid for as 261 | long as you offer spare parts or customer support for that product 262 | model, to give anyone who possesses the object code either (1) a 263 | copy of the Corresponding Source for all the software in the 264 | product that is covered by this License, on a durable physical 265 | medium customarily used for software interchange, for a price no 266 | more than your reasonable cost of physically performing this 267 | conveying of source, or (2) access to copy the 268 | Corresponding Source from a network server at no charge. 269 | 270 | c) Convey individual copies of the object code with a copy of the 271 | written offer to provide the Corresponding Source. This 272 | alternative is allowed only occasionally and noncommercially, and 273 | only if you received the object code with such an offer, in accord 274 | with subsection 6b. 275 | 276 | d) Convey the object code by offering access from a designated 277 | place (gratis or for a charge), and offer equivalent access to the 278 | Corresponding Source in the same way through the same place at no 279 | further charge. You need not require recipients to copy the 280 | Corresponding Source along with the object code. If the place to 281 | copy the object code is a network server, the Corresponding Source 282 | may be on a different server (operated by you or a third party) 283 | that supports equivalent copying facilities, provided you maintain 284 | clear directions next to the object code saying where to find the 285 | Corresponding Source. Regardless of what server hosts the 286 | Corresponding Source, you remain obligated to ensure that it is 287 | available for as long as needed to satisfy these requirements. 288 | 289 | e) Convey the object code using peer-to-peer transmission, provided 290 | you inform other peers where the object code and Corresponding 291 | Source of the work are being offered to the general public at no 292 | charge under subsection 6d. 293 | 294 | A separable portion of the object code, whose source code is excluded 295 | from the Corresponding Source as a System Library, need not be 296 | included in conveying the object code work. 297 | 298 | A "User Product" is either (1) a "consumer product", which means any 299 | tangible personal property which is normally used for personal, family, 300 | or household purposes, or (2) anything designed or sold for incorporation 301 | into a dwelling. In determining whether a product is a consumer product, 302 | doubtful cases shall be resolved in favor of coverage. For a particular 303 | product received by a particular user, "normally used" refers to a 304 | typical or common use of that class of product, regardless of the status 305 | of the particular user or of the way in which the particular user 306 | actually uses, or expects or is expected to use, the product. A product 307 | is a consumer product regardless of whether the product has substantial 308 | commercial, industrial or non-consumer uses, unless such uses represent 309 | the only significant mode of use of the product. 310 | 311 | "Installation Information" for a User Product means any methods, 312 | procedures, authorization keys, or other information required to install 313 | and execute modified versions of a covered work in that User Product from 314 | a modified version of its Corresponding Source. The information must 315 | suffice to ensure that the continued functioning of the modified object 316 | code is in no case prevented or interfered with solely because 317 | modification has been made. 318 | 319 | If you convey an object code work under this section in, or with, or 320 | specifically for use in, a User Product, and the conveying occurs as 321 | part of a transaction in which the right of possession and use of the 322 | User Product is transferred to the recipient in perpetuity or for a 323 | fixed term (regardless of how the transaction is characterized), the 324 | Corresponding Source conveyed under this section must be accompanied 325 | by the Installation Information. But this requirement does not apply 326 | if neither you nor any third party retains the ability to install 327 | modified object code on the User Product (for example, the work has 328 | been installed in ROM). 329 | 330 | The requirement to provide Installation Information does not include a 331 | requirement to continue to provide support service, warranty, or updates 332 | for a work that has been modified or installed by the recipient, or for 333 | the User Product in which it has been modified or installed. Access to a 334 | network may be denied when the modification itself materially and 335 | adversely affects the operation of the network or violates the rules and 336 | protocols for communication across the network. 337 | 338 | Corresponding Source conveyed, and Installation Information provided, 339 | in accord with this section must be in a format that is publicly 340 | documented (and with an implementation available to the public in 341 | source code form), and must require no special password or key for 342 | unpacking, reading or copying. 343 | 344 | 7. Additional Terms. 345 | 346 | "Additional permissions" are terms that supplement the terms of this 347 | License by making exceptions from one or more of its conditions. 348 | Additional permissions that are applicable to the entire Program shall 349 | be treated as though they were included in this License, to the extent 350 | that they are valid under applicable law. If additional permissions 351 | apply only to part of the Program, that part may be used separately 352 | under those permissions, but the entire Program remains governed by 353 | this License without regard to the additional permissions. 354 | 355 | When you convey a copy of a covered work, you may at your option 356 | remove any additional permissions from that copy, or from any part of 357 | it. (Additional permissions may be written to require their own 358 | removal in certain cases when you modify the work.) You may place 359 | additional permissions on material, added by you to a covered work, 360 | for which you have or can give appropriate copyright permission. 361 | 362 | Notwithstanding any other provision of this License, for material you 363 | add to a covered work, you may (if authorized by the copyright holders of 364 | that material) supplement the terms of this License with terms: 365 | 366 | a) Disclaiming warranty or limiting liability differently from the 367 | terms of sections 15 and 16 of this License; or 368 | 369 | b) Requiring preservation of specified reasonable legal notices or 370 | author attributions in that material or in the Appropriate Legal 371 | Notices displayed by works containing it; or 372 | 373 | c) Prohibiting misrepresentation of the origin of that material, or 374 | requiring that modified versions of such material be marked in 375 | reasonable ways as different from the original version; or 376 | 377 | d) Limiting the use for publicity purposes of names of licensors or 378 | authors of the material; or 379 | 380 | e) Declining to grant rights under trademark law for use of some 381 | trade names, trademarks, or service marks; or 382 | 383 | f) Requiring indemnification of licensors and authors of that 384 | material by anyone who conveys the material (or modified versions of 385 | it) with contractual assumptions of liability to the recipient, for 386 | any liability that these contractual assumptions directly impose on 387 | those licensors and authors. 388 | 389 | All other non-permissive additional terms are considered "further 390 | restrictions" within the meaning of section 10. If the Program as you 391 | received it, or any part of it, contains a notice stating that it is 392 | governed by this License along with a term that is a further 393 | restriction, you may remove that term. If a license document contains 394 | a further restriction but permits relicensing or conveying under this 395 | License, you may add to a covered work material governed by the terms 396 | of that license document, provided that the further restriction does 397 | not survive such relicensing or conveying. 398 | 399 | If you add terms to a covered work in accord with this section, you 400 | must place, in the relevant source files, a statement of the 401 | additional terms that apply to those files, or a notice indicating 402 | where to find the applicable terms. 403 | 404 | Additional terms, permissive or non-permissive, may be stated in the 405 | form of a separately written license, or stated as exceptions; 406 | the above requirements apply either way. 407 | 408 | 8. Termination. 409 | 410 | You may not propagate or modify a covered work except as expressly 411 | provided under this License. Any attempt otherwise to propagate or 412 | modify it is void, and will automatically terminate your rights under 413 | this License (including any patent licenses granted under the third 414 | paragraph of section 11). 415 | 416 | However, if you cease all violation of this License, then your 417 | license from a particular copyright holder is reinstated (a) 418 | provisionally, unless and until the copyright holder explicitly and 419 | finally terminates your license, and (b) permanently, if the copyright 420 | holder fails to notify you of the violation by some reasonable means 421 | prior to 60 days after the cessation. 422 | 423 | Moreover, your license from a particular copyright holder is 424 | reinstated permanently if the copyright holder notifies you of the 425 | violation by some reasonable means, this is the first time you have 426 | received notice of violation of this License (for any work) from that 427 | copyright holder, and you cure the violation prior to 30 days after 428 | your receipt of the notice. 429 | 430 | Termination of your rights under this section does not terminate the 431 | licenses of parties who have received copies or rights from you under 432 | this License. If your rights have been terminated and not permanently 433 | reinstated, you do not qualify to receive new licenses for the same 434 | material under section 10. 435 | 436 | 9. Acceptance Not Required for Having Copies. 437 | 438 | You are not required to accept this License in order to receive or 439 | run a copy of the Program. Ancillary propagation of a covered work 440 | occurring solely as a consequence of using peer-to-peer transmission 441 | to receive a copy likewise does not require acceptance. However, 442 | nothing other than this License grants you permission to propagate or 443 | modify any covered work. These actions infringe copyright if you do 444 | not accept this License. Therefore, by modifying or propagating a 445 | covered work, you indicate your acceptance of this License to do so. 446 | 447 | 10. Automatic Licensing of Downstream Recipients. 448 | 449 | Each time you convey a covered work, the recipient automatically 450 | receives a license from the original licensors, to run, modify and 451 | propagate that work, subject to this License. You are not responsible 452 | for enforcing compliance by third parties with this License. 453 | 454 | An "entity transaction" is a transaction transferring control of an 455 | organization, or substantially all assets of one, or subdividing an 456 | organization, or merging organizations. If propagation of a covered 457 | work results from an entity transaction, each party to that 458 | transaction who receives a copy of the work also receives whatever 459 | licenses to the work the party's predecessor in interest had or could 460 | give under the previous paragraph, plus a right to possession of the 461 | Corresponding Source of the work from the predecessor in interest, if 462 | the predecessor has it or can get it with reasonable efforts. 463 | 464 | You may not impose any further restrictions on the exercise of the 465 | rights granted or affirmed under this License. For example, you may 466 | not impose a license fee, royalty, or other charge for exercise of 467 | rights granted under this License, and you may not initiate litigation 468 | (including a cross-claim or counterclaim in a lawsuit) alleging that 469 | any patent claim is infringed by making, using, selling, offering for 470 | sale, or importing the Program or any portion of it. 471 | 472 | 11. Patents. 473 | 474 | A "contributor" is a copyright holder who authorizes use under this 475 | License of the Program or a work on which the Program is based. The 476 | work thus licensed is called the contributor's "contributor version". 477 | 478 | A contributor's "essential patent claims" are all patent claims 479 | owned or controlled by the contributor, whether already acquired or 480 | hereafter acquired, that would be infringed by some manner, permitted 481 | by this License, of making, using, or selling its contributor version, 482 | but do not include claims that would be infringed only as a 483 | consequence of further modification of the contributor version. For 484 | purposes of this definition, "control" includes the right to grant 485 | patent sublicenses in a manner consistent with the requirements of 486 | this License. 487 | 488 | Each contributor grants you a non-exclusive, worldwide, royalty-free 489 | patent license under the contributor's essential patent claims, to 490 | make, use, sell, offer for sale, import and otherwise run, modify and 491 | propagate the contents of its contributor version. 492 | 493 | In the following three paragraphs, a "patent license" is any express 494 | agreement or commitment, however denominated, not to enforce a patent 495 | (such as an express permission to practice a patent or covenant not to 496 | sue for patent infringement). To "grant" such a patent license to a 497 | party means to make such an agreement or commitment not to enforce a 498 | patent against the party. 499 | 500 | If you convey a covered work, knowingly relying on a patent license, 501 | and the Corresponding Source of the work is not available for anyone 502 | to copy, free of charge and under the terms of this License, through a 503 | publicly available network server or other readily accessible means, 504 | then you must either (1) cause the Corresponding Source to be so 505 | available, or (2) arrange to deprive yourself of the benefit of the 506 | patent license for this particular work, or (3) arrange, in a manner 507 | consistent with the requirements of this License, to extend the patent 508 | license to downstream recipients. "Knowingly relying" means you have 509 | actual knowledge that, but for the patent license, your conveying the 510 | covered work in a country, or your recipient's use of the covered work 511 | in a country, would infringe one or more identifiable patents in that 512 | country that you have reason to believe are valid. 513 | 514 | If, pursuant to or in connection with a single transaction or 515 | arrangement, you convey, or propagate by procuring conveyance of, a 516 | covered work, and grant a patent license to some of the parties 517 | receiving the covered work authorizing them to use, propagate, modify 518 | or convey a specific copy of the covered work, then the patent license 519 | you grant is automatically extended to all recipients of the covered 520 | work and works based on it. 521 | 522 | A patent license is "discriminatory" if it does not include within 523 | the scope of its coverage, prohibits the exercise of, or is 524 | conditioned on the non-exercise of one or more of the rights that are 525 | specifically granted under this License. You may not convey a covered 526 | work if you are a party to an arrangement with a third party that is 527 | in the business of distributing software, under which you make payment 528 | to the third party based on the extent of your activity of conveying 529 | the work, and under which the third party grants, to any of the 530 | parties who would receive the covered work from you, a discriminatory 531 | patent license (a) in connection with copies of the covered work 532 | conveyed by you (or copies made from those copies), or (b) primarily 533 | for and in connection with specific products or compilations that 534 | contain the covered work, unless you entered into that arrangement, 535 | or that patent license was granted, prior to 28 March 2007. 536 | 537 | Nothing in this License shall be construed as excluding or limiting 538 | any implied license or other defenses to infringement that may 539 | otherwise be available to you under applicable patent law. 540 | 541 | 12. No Surrender of Others' Freedom. 542 | 543 | If conditions are imposed on you (whether by court order, agreement or 544 | otherwise) that contradict the conditions of this License, they do not 545 | excuse you from the conditions of this License. If you cannot convey a 546 | covered work so as to satisfy simultaneously your obligations under this 547 | License and any other pertinent obligations, then as a consequence you may 548 | not convey it at all. For example, if you agree to terms that obligate you 549 | to collect a royalty for further conveying from those to whom you convey 550 | the Program, the only way you could satisfy both those terms and this 551 | License would be to refrain entirely from conveying the Program. 552 | 553 | 13. Use with the GNU Affero General Public License. 554 | 555 | Notwithstanding any other provision of this License, you have 556 | permission to link or combine any covered work with a work licensed 557 | under version 3 of the GNU Affero General Public License into a single 558 | combined work, and to convey the resulting work. The terms of this 559 | License will continue to apply to the part which is the covered work, 560 | but the special requirements of the GNU Affero General Public License, 561 | section 13, concerning interaction through a network will apply to the 562 | combination as such. 563 | 564 | 14. Revised Versions of this License. 565 | 566 | The Free Software Foundation may publish revised and/or new versions of 567 | the GNU General Public License from time to time. Such new versions will 568 | be similar in spirit to the present version, but may differ in detail to 569 | address new problems or concerns. 570 | 571 | Each version is given a distinguishing version number. If the 572 | Program specifies that a certain numbered version of the GNU General 573 | Public License "or any later version" applies to it, you have the 574 | option of following the terms and conditions either of that numbered 575 | version or of any later version published by the Free Software 576 | Foundation. If the Program does not specify a version number of the 577 | GNU General Public License, you may choose any version ever published 578 | by the Free Software Foundation. 579 | 580 | If the Program specifies that a proxy can decide which future 581 | versions of the GNU General Public License can be used, that proxy's 582 | public statement of acceptance of a version permanently authorizes you 583 | to choose that version for the Program. 584 | 585 | Later license versions may give you additional or different 586 | permissions. However, no additional obligations are imposed on any 587 | author or copyright holder as a result of your choosing to follow a 588 | later version. 589 | 590 | 15. Disclaimer of Warranty. 591 | 592 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 593 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 594 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 595 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 596 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 597 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 598 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 599 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 600 | 601 | 16. Limitation of Liability. 602 | 603 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 604 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 605 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 606 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 607 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 608 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 609 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 610 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 611 | SUCH DAMAGES. 612 | 613 | 17. Interpretation of Sections 15 and 16. 614 | 615 | If the disclaimer of warranty and limitation of liability provided 616 | above cannot be given local legal effect according to their terms, 617 | reviewing courts shall apply local law that most closely approximates 618 | an absolute waiver of all civil liability in connection with the 619 | Program, unless a warranty or assumption of liability accompanies a 620 | copy of the Program in return for a fee. 621 | 622 | END OF TERMS AND CONDITIONS 623 | 624 | 625 | 626 | LGPL ADDENDUM: 627 | 628 | 629 | 630 | GNU LESSER GENERAL PUBLIC LICENSE 631 | Version 3, 29 June 2007 632 | 633 | Copyright (C) 2007 Free Software Foundation, Inc. 634 | Everyone is permitted to copy and distribute verbatim copies 635 | of this license document, but changing it is not allowed. 636 | 637 | 638 | This version of the GNU Lesser General Public License incorporates 639 | the terms and conditions of version 3 of the GNU General Public 640 | License, supplemented by the additional permissions listed below. 641 | 642 | 0. Additional Definitions. 643 | 644 | As used herein, "this License" refers to version 3 of the GNU Lesser 645 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 646 | General Public License. 647 | 648 | "The Library" refers to a covered work governed by this License, 649 | other than an Application or a Combined Work as defined below. 650 | 651 | An "Application" is any work that makes use of an interface provided 652 | by the Library, but which is not otherwise based on the Library. 653 | Defining a subclass of a class defined by the Library is deemed a mode 654 | of using an interface provided by the Library. 655 | 656 | A "Combined Work" is a work produced by combining or linking an 657 | Application with the Library. The particular version of the Library 658 | with which the Combined Work was made is also called the "Linked 659 | Version". 660 | 661 | The "Minimal Corresponding Source" for a Combined Work means the 662 | Corresponding Source for the Combined Work, excluding any source code 663 | for portions of the Combined Work that, considered in isolation, are 664 | based on the Application, and not on the Linked Version. 665 | 666 | The "Corresponding Application Code" for a Combined Work means the 667 | object code and/or source code for the Application, including any data 668 | and utility programs needed for reproducing the Combined Work from the 669 | Application, but excluding the System Libraries of the Combined Work. 670 | 671 | 1. Exception to Section 3 of the GNU GPL. 672 | 673 | You may convey a covered work under sections 3 and 4 of this License 674 | without being bound by section 3 of the GNU GPL. 675 | 676 | 2. Conveying Modified Versions. 677 | 678 | If you modify a copy of the Library, and, in your modifications, a 679 | facility refers to a function or data to be supplied by an Application 680 | that uses the facility (other than as an argument passed when the 681 | facility is invoked), then you may convey a copy of the modified 682 | version: 683 | 684 | a) under this License, provided that you make a good faith effort to 685 | ensure that, in the event an Application does not supply the 686 | function or data, the facility still operates, and performs 687 | whatever part of its purpose remains meaningful, or 688 | 689 | b) under the GNU GPL, with none of the additional permissions of 690 | this License applicable to that copy. 691 | 692 | 3. Object Code Incorporating Material from Library Header Files. 693 | 694 | The object code form of an Application may incorporate material from 695 | a header file that is part of the Library. You may convey such object 696 | code under terms of your choice, provided that, if the incorporated 697 | material is not limited to numerical parameters, data structure 698 | layouts and accessors, or small macros, inline functions and templates 699 | (ten or fewer lines in length), you do both of the following: 700 | 701 | a) Give prominent notice with each copy of the object code that the 702 | Library is used in it and that the Library and its use are 703 | covered by this License. 704 | 705 | b) Accompany the object code with a copy of the GNU GPL and this license 706 | document. 707 | 708 | 4. Combined Works. 709 | 710 | You may convey a Combined Work under terms of your choice that, 711 | taken together, effectively do not restrict modification of the 712 | portions of the Library contained in the Combined Work and reverse 713 | engineering for debugging such modifications, if you also do each of 714 | the following: 715 | 716 | a) Give prominent notice with each copy of the Combined Work that 717 | the Library is used in it and that the Library and its use are 718 | covered by this License. 719 | 720 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 721 | document. 722 | 723 | c) For a Combined Work that displays copyright notices during 724 | execution, include the copyright notice for the Library among 725 | these notices, as well as a reference directing the user to the 726 | copies of the GNU GPL and this license document. 727 | 728 | d) Do one of the following: 729 | 730 | 0) Convey the Minimal Corresponding Source under the terms of this 731 | License, and the Corresponding Application Code in a form 732 | suitable for, and under terms that permit, the user to 733 | recombine or relink the Application with a modified version of 734 | the Linked Version to produce a modified Combined Work, in the 735 | manner specified by section 6 of the GNU GPL for conveying 736 | Corresponding Source. 737 | 738 | 1) Use a suitable shared library mechanism for linking with the 739 | Library. A suitable mechanism is one that (a) uses at run time 740 | a copy of the Library already present on the user's computer 741 | system, and (b) will operate properly with a modified version 742 | of the Library that is interface-compatible with the Linked 743 | Version. 744 | 745 | e) Provide Installation Information, but only if you would otherwise 746 | be required to provide such information under section 6 of the 747 | GNU GPL, and only to the extent that such information is 748 | necessary to install and execute a modified version of the 749 | Combined Work produced by recombining or relinking the 750 | Application with a modified version of the Linked Version. (If 751 | you use option 4d0, the Installation Information must accompany 752 | the Minimal Corresponding Source and Corresponding Application 753 | Code. If you use option 4d1, you must provide the Installation 754 | Information in the manner specified by section 6 of the GNU GPL 755 | for conveying Corresponding Source.) 756 | 757 | 5. Combined Libraries. 758 | 759 | You may place library facilities that are a work based on the 760 | Library side by side in a single library together with other library 761 | facilities that are not Applications and are not covered by this 762 | License, and convey such a combined library under terms of your 763 | choice, if you do both of the following: 764 | 765 | a) Accompany the combined library with a copy of the same work based 766 | on the Library, uncombined with any other library facilities, 767 | conveyed under the terms of this License. 768 | 769 | b) Give prominent notice with the combined library that part of it 770 | is a work based on the Library, and explaining where to find the 771 | accompanying uncombined form of the same work. 772 | 773 | 6. Revised Versions of the GNU Lesser General Public License. 774 | 775 | The Free Software Foundation may publish revised and/or new versions 776 | of the GNU Lesser General Public License from time to time. Such new 777 | versions will be similar in spirit to the present version, but may 778 | differ in detail to address new problems or concerns. 779 | 780 | Each version is given a distinguishing version number. If the 781 | Library as you received it specifies that a certain numbered version 782 | of the GNU Lesser General Public License "or any later version" 783 | applies to it, you have the option of following the terms and 784 | conditions either of that published version or of any later version 785 | published by the Free Software Foundation. If the Library as you 786 | received it does not specify a version number of the GNU Lesser 787 | General Public License, you may choose any version of the GNU Lesser 788 | General Public License ever published by the Free Software Foundation. 789 | 790 | If the Library as you received it specifies that a proxy can decide 791 | whether future versions of the GNU Lesser General Public License shall 792 | apply, that proxy's public statement of acceptance of any version is 793 | permanent authorization for you to choose that version for the 794 | Library. 795 | -------------------------------------------------------------------------------- /Processing/Adalight/Adalight.pde: -------------------------------------------------------------------------------- 1 | // "Adalight" is a do-it-yourself facsimile of the Philips Ambilight concept 2 | // for desktop computers and home theater PCs. This is the host PC-side code 3 | // written in Processing, intended for use with a USB-connected Arduino 4 | // microcontroller running the accompanying LED streaming code. Requires one 5 | // or more strands of Digital RGB LED Pixels (Adafruit product ID #322, 6 | // specifically the newer WS2801-based type, strand of 25) and a 5 Volt power 7 | // supply (such as Adafruit #276). You may need to adapt the code and the 8 | // hardware arrangement for your specific display configuration. 9 | // Screen capture adapted from code by Cedrik Kiefer (processing.org forum) 10 | 11 | // -------------------------------------------------------------------- 12 | // This file is part of Adalight. 13 | 14 | // Adalight is free software: you can redistribute it and/or modify 15 | // it under the terms of the GNU Lesser General Public License as 16 | // published by the Free Software Foundation, either version 3 of 17 | // the License, or (at your option) any later version. 18 | 19 | // Adalight is distributed in the hope that it will be useful, 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | // GNU Lesser General Public License for more details. 23 | 24 | // You should have received a copy of the GNU Lesser General Public 25 | // License along with Adalight. If not, see 26 | // . 27 | // -------------------------------------------------------------------- 28 | 29 | import java.awt.*; 30 | import java.awt.image.*; 31 | import processing.serial.*; 32 | 33 | // CONFIGURABLE PROGRAM CONSTANTS -------------------------------------------- 34 | 35 | // Minimum LED brightness; some users prefer a small amount of backlighting 36 | // at all times, regardless of screen content. Higher values are brighter, 37 | // or set to 0 to disable this feature. 38 | 39 | static final short minBrightness = 120; 40 | 41 | // LED transition speed; it's sometimes distracting if LEDs instantaneously 42 | // track screen contents (such as during bright flashing sequences), so this 43 | // feature enables a gradual fade to each new LED state. Higher numbers yield 44 | // slower transitions (max of 255), or set to 0 to disable this feature 45 | // (immediate transition of all LEDs). 46 | 47 | static final short fade = 75; 48 | 49 | // Pixel size for the live preview image. 50 | 51 | static final int pixelSize = 20; 52 | 53 | // Depending on many factors, it may be faster either to capture full 54 | // screens and process only the pixels needed, or to capture multiple 55 | // smaller sub-blocks bounding each region to be processed. Try both, 56 | // look at the reported frame rates in the Processing output console, 57 | // and run with whichever works best for you. 58 | 59 | static final boolean useFullScreenCaps = true; 60 | 61 | // Serial device timeout (in milliseconds), for locating Arduino device 62 | // running the corresponding LEDstream code. See notes later in the code... 63 | // in some situations you may want to entirely comment out that block. 64 | 65 | static final int timeout = 5000; // 5 seconds 66 | 67 | // PER-DISPLAY INFORMATION --------------------------------------------------- 68 | 69 | // This array contains details for each display that the software will 70 | // process. If you have screen(s) attached that are not among those being 71 | // "Adalighted," they should not be in this list. Each triplet in this 72 | // array represents one display. The first number is the system screen 73 | // number...typically the "primary" display on most systems is identified 74 | // as screen #1, but since arrays are indexed from zero, use 0 to indicate 75 | // the first screen, 1 to indicate the second screen, and so forth. This 76 | // is the ONLY place system screen numbers are used...ANY subsequent 77 | // references to displays are an index into this list, NOT necessarily the 78 | // same as the system screen number. For example, if you have a three- 79 | // screen setup and are illuminating only the third display, use '2' for 80 | // the screen number here...and then, in subsequent section, '0' will be 81 | // used to refer to the first/only display in this list. 82 | // The second and third numbers of each triplet represent the width and 83 | // height of a grid of LED pixels attached to the perimeter of this display. 84 | // For example, '9,6' = 9 LEDs across, 6 LEDs down. 85 | 86 | static final int displays[][] = new int[][] { 87 | {0,9,6} // Screen 0, 9 LEDs across, 6 LEDs down 88 | //,{1,9,6} // Screen 1, also 9 LEDs across and 6 LEDs down 89 | }; 90 | 91 | // PER-LED INFORMATION ------------------------------------------------------- 92 | 93 | // This array contains the 2D coordinates corresponding to each pixel in the 94 | // LED strand, in the order that they're connected (i.e. the first element 95 | // here belongs to the first LED in the strand, second element is the second 96 | // LED, and so forth). Each triplet in this array consists of a display 97 | // number (an index into the display array above, NOT necessarily the same as 98 | // the system screen number) and an X and Y coordinate specified in the grid 99 | // units given for that display. {0,0,0} is the top-left corner of the first 100 | // display in the array. 101 | // For our example purposes, the coordinate list below forms a ring around 102 | // the perimeter of a single screen, with a one pixel gap at the bottom to 103 | // accommodate a monitor stand. Modify this to match your own setup: 104 | 105 | static final int leds[][] = new int[][] { 106 | {0,3,5}, {0,2,5}, {0,1,5}, {0,0,5}, // Bottom edge, left half 107 | {0,0,4}, {0,0,3}, {0,0,2}, {0,0,1}, // Left edge 108 | {0,0,0}, {0,1,0}, {0,2,0}, {0,3,0}, {0,4,0}, // Top edge 109 | {0,5,0}, {0,6,0}, {0,7,0}, {0,8,0}, // More top edge 110 | {0,8,1}, {0,8,2}, {0,8,3}, {0,8,4}, // Right edge 111 | {0,8,5}, {0,7,5}, {0,6,5}, {0,5,5} // Bottom edge, right half 112 | 113 | /* Hypothetical second display has the same arrangement as the first. 114 | But you might not want both displays completely ringed with LEDs; 115 | the screens might be positioned where they share an edge in common. 116 | ,{1,3,5}, {1,2,5}, {1,1,5}, {1,0,5}, // Bottom edge, left half 117 | {1,0,4}, {1,0,3}, {1,0,2}, {1,0,1}, // Left edge 118 | {1,0,0}, {1,1,0}, {1,2,0}, {1,3,0}, {1,4,0}, // Top edge 119 | {1,5,0}, {1,6,0}, {1,7,0}, {1,8,0}, // More top edge 120 | {1,8,1}, {1,8,2}, {1,8,3}, {1,8,4}, // Right edge 121 | {1,8,5}, {1,7,5}, {1,6,5}, {1,5,5} // Bottom edge, right half 122 | */ 123 | }; 124 | 125 | // GLOBAL VARIABLES ---- You probably won't need to modify any of this ------- 126 | 127 | byte[] serialData = new byte[6 + leds.length * 3]; 128 | short[][] ledColor = new short[leds.length][3], 129 | prevColor = new short[leds.length][3]; 130 | byte[][] gamma = new byte[256][3]; 131 | int nDisplays = displays.length; 132 | Robot[] bot = new Robot[displays.length]; 133 | Rectangle[] dispBounds = new Rectangle[displays.length], 134 | ledBounds; // Alloc'd only if per-LED captures 135 | int[][] pixelOffset = new int[leds.length][256], 136 | screenData; // Alloc'd only if full-screen captures 137 | PImage[] preview = new PImage[displays.length]; 138 | Serial port; 139 | DisposeHandler dh; // For disabling LEDs on exit 140 | 141 | // INITIALIZATION ------------------------------------------------------------ 142 | 143 | void setup() { 144 | GraphicsEnvironment ge; 145 | GraphicsConfiguration[] gc; 146 | GraphicsDevice[] gd; 147 | int d, i, totalWidth, maxHeight, row, col, rowOffset; 148 | int[] x = new int[16], y = new int[16]; 149 | float f, range, step, start; 150 | 151 | dh = new DisposeHandler(this); // Init DisposeHandler ASAP 152 | 153 | // Open serial port. As written here, this assumes the Arduino is the 154 | // first/only serial device on the system. If that's not the case, 155 | // change "Serial.list()[0]" to the name of the port to be used: 156 | port = new Serial(this, Serial.list()[0], 115200); 157 | // Alternately, in certain situations the following line can be used 158 | // to detect the Arduino automatically. But this works ONLY with SOME 159 | // Arduino boards and versions of Processing! This is so convoluted 160 | // to explain, it's easier just to test it yourself and see whether 161 | // it works...if not, leave it commented out and use the prior port- 162 | // opening technique. 163 | // port = openPort(); 164 | // And finally, to test the software alone without an Arduino connected, 165 | // don't open a port...just comment out the serial lines above. 166 | 167 | // Initialize screen capture code for each display's dimensions. 168 | dispBounds = new Rectangle[displays.length]; 169 | if(useFullScreenCaps == true) { 170 | screenData = new int[displays.length][]; 171 | // ledBounds[] not used 172 | } else { 173 | ledBounds = new Rectangle[leds.length]; 174 | // screenData[][] not used 175 | } 176 | ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 177 | gd = ge.getScreenDevices(); 178 | if(nDisplays > gd.length) nDisplays = gd.length; 179 | totalWidth = maxHeight = 0; 180 | for(d=0; d 0) totalWidth++; 195 | if(displays[d][2] > maxHeight) maxHeight = displays[d][2]; 196 | } 197 | 198 | // Precompute locations of every pixel to read when downsampling. 199 | // Saves a bunch of math on each frame, at the expense of a chunk 200 | // of RAM. Number of samples is now fixed at 256; this allows for 201 | // some crazy optimizations in the downsampling code. 202 | for(i=0; i> 8); // LED count high byte 251 | serialData[4] = (byte)((leds.length - 1) & 0xff); // LED count low byte 252 | serialData[5] = (byte)(serialData[3] ^ serialData[4] ^ 0x55); // Checksum 253 | 254 | // Pre-compute gamma correction table for LED brightness levels: 255 | for(i=0; i<256; i++) { 256 | f = pow((float)i / 255.0, 2.8); 257 | gamma[i][0] = (byte)(f * 255.0); 258 | gamma[i][1] = (byte)(f * 240.0); 259 | gamma[i][2] = (byte)(f * 220.0); 260 | } 261 | } 262 | 263 | // Open and return serial connection to Arduino running LEDstream code. This 264 | // attempts to open and read from each serial device on the system, until the 265 | // matching "Ada\n" acknowledgement string is found. Due to the serial 266 | // timeout, if you have multiple serial devices/ports and the Arduino is late 267 | // in the list, this can take seemingly forever...so if you KNOW the Arduino 268 | // will always be on a specific port (e.g. "COM6"), you might want to comment 269 | // out most of this to bypass the checks and instead just open that port 270 | // directly! (Modify last line in this method with the serial port name.) 271 | 272 | Serial openPort() { 273 | String[] ports; 274 | String ack; 275 | int i, start; 276 | Serial s; 277 | 278 | ports = Serial.list(); // List of all serial ports/devices on system. 279 | 280 | for(i=0; i= 4) && 293 | ((ack = s.readString()) != null) && 294 | ack.contains("Ada\n")) { 295 | return s; // Got it! 296 | } 297 | } 298 | // Connection timed out. Close port and move on to the next. 299 | s.stop(); 300 | } 301 | 302 | // Didn't locate a device returning the acknowledgment string. 303 | // Maybe it's out there but running the old LEDstream code, which 304 | // didn't have the ACK. Can't say for sure, so we'll take our 305 | // changes with the first/only serial device out there... 306 | return new Serial(this, ports[0], 115200); 307 | } 308 | 309 | 310 | // PER_FRAME PROCESSING ------------------------------------------------------ 311 | 312 | void draw () { 313 | BufferedImage img; 314 | int d, i, j, o, c, weight, rb, g, sum, deficit, s2; 315 | int[] pxls, offs; 316 | 317 | if(useFullScreenCaps == true ) { 318 | // Capture each screen in the displays array. 319 | for(d=0; d> 24) & 0xff) * weight + 359 | prevColor[i][0] * fade) >> 8); 360 | ledColor[i][1] = (short)(((( g >> 16) & 0xff) * weight + 361 | prevColor[i][1] * fade) >> 8); 362 | ledColor[i][2] = (short)((((rb >> 8) & 0xff) * weight + 363 | prevColor[i][2] * fade) >> 8); 364 | 365 | // Boost pixels that fall below the minimum brightness 366 | sum = ledColor[i][0] + ledColor[i][1] + ledColor[i][2]; 367 | if(sum < minBrightness) { 368 | if(sum == 0) { // To avoid divide-by-zero 369 | deficit = minBrightness / 3; // Spread equally to R,G,B 370 | ledColor[i][0] += deficit; 371 | ledColor[i][1] += deficit; 372 | ledColor[i][2] += deficit; 373 | } else { 374 | deficit = minBrightness - sum; 375 | s2 = sum * 2; 376 | // Spread the "brightness deficit" back into R,G,B in proportion to 377 | // their individual contribition to that deficit. Rather than simply 378 | // boosting all pixels at the low end, this allows deep (but saturated) 379 | // colors to stay saturated...they don't "pink out." 380 | ledColor[i][0] += deficit * (sum - ledColor[i][0]) / s2; 381 | ledColor[i][1] += deficit * (sum - ledColor[i][1]) / s2; 382 | ledColor[i][2] += deficit * (sum - ledColor[i][2]) / s2; 383 | } 384 | } 385 | 386 | // Apply gamma curve and place in serial output buffer 387 | serialData[j++] = gamma[ledColor[i][0]][0]; 388 | serialData[j++] = gamma[ledColor[i][1]][1]; 389 | serialData[j++] = gamma[ledColor[i][2]][2]; 390 | // Update pixels in preview image 391 | preview[d].pixels[leds[i][2] * displays[d][1] + leds[i][1]] = 392 | (ledColor[i][0] << 16) | (ledColor[i][1] << 8) | ledColor[i][2]; 393 | } 394 | 395 | if(port != null) port.write(serialData); // Issue data to Arduino 396 | 397 | // Show live preview image(s) 398 | scale(pixelSize); 399 | for(i=d=0; d. 28 | // -------------------------------------------------------------------- 29 | 30 | import java.awt.*; 31 | import java.awt.image.*; 32 | import processing.serial.*; 33 | 34 | // CONFIGURABLE PROGRAM CONSTANTS -------------------------------------------- 35 | 36 | // This selects from the list of serial devices connected to the system. 37 | // Use print(Serial.list()); to get a list of ports. Then, counting from 0, 38 | // set this value to the index corresponding to the Circuit Playground port: 39 | 40 | static final byte serialPortIndex = 2; 41 | 42 | // For multi-screen systems, set this to the index (counting from 0) of the 43 | // display which will have ambient lighting: 44 | 45 | static final byte screenNumber = 0; 46 | 47 | // Minimum LED brightness; some users prefer a small amount of backlighting 48 | // at all times, regardless of screen content. Higher values are brighter, 49 | // or set to 0 to disable this feature. 50 | 51 | static final short minBrightness = 100; 52 | 53 | // LED transition speed; it's sometimes distracting if LEDs instantaneously 54 | // track screen contents (such as during bright flashing sequences), so this 55 | // feature enables a gradual fade to each new LED state. Higher numbers yield 56 | // slower transitions (max of 255), or set to 0 to disable this feature 57 | // (immediate transition of all LEDs). 58 | 59 | static final short fade = 60; 60 | 61 | // Depending on many factors, it may be faster either to capture full 62 | // screens and process only the pixels needed, or to capture multiple 63 | // smaller sub-blocks bounding each region to be processed. Try both, 64 | // look at the reported frame rates in the Processing output console, 65 | // and run with whichever works best for you. 66 | 67 | static final boolean useFullScreenCaps = true; 68 | 69 | // PER-LED INFORMATION ------------------------------------------------------- 70 | 71 | // The Circuit Playground version of Adalight operates on a fixed 5x5 grid 72 | // encompassing the full display. 10 elements from this grid correspond to 73 | // the 10 NeoPixels on the Circuit Playground board. The following array 74 | // contains the 2D coordinates of each NeoPixel within that 5x5 grid (0,0 is 75 | // top left); board assumed facing away from display, with USB at bottom: 76 | // .4.5. 77 | // 3...6 78 | // 2...7 79 | // 1...8 80 | // .0.9. 81 | 82 | static final int leds[][] = new int[][] { 83 | {1,4}, {0,3}, {0,2}, {0,1}, {1,0}, 84 | {3,0}, {4,1}, {4,2}, {4,3}, {3,4} 85 | }; 86 | 87 | // GLOBAL VARIABLES ---- You probably won't need to modify any of this ------- 88 | 89 | byte serialData[] = new byte[6 + leds.length * 3], 90 | gamma[][] = new byte[256][3]; 91 | short[][] ledColor = new short[leds.length][3], 92 | prevColor = new short[leds.length][3]; 93 | Robot bot; 94 | Rectangle dispBounds, ledBounds[]; 95 | int pixelOffset[][] = new int[leds.length][256], 96 | screenData[]; 97 | PImage preview; 98 | Serial port; 99 | 100 | // INITIALIZATION ------------------------------------------------------------ 101 | 102 | void setup() { 103 | GraphicsEnvironment ge; 104 | GraphicsConfiguration[] gc; 105 | GraphicsDevice[] gd; 106 | int i, row, col; 107 | int[] x = new int[16], y = new int[16]; 108 | float f, range, step, start; 109 | 110 | this.registerMethod("dispose", this); 111 | print(Serial.list()); // Show list of serial devices/ports 112 | // Open serial port. Change serialPortIndex in the globals to 113 | // select a different port: 114 | port = new Serial(this, Serial.list()[serialPortIndex], 38400); 115 | 116 | // Initialize screen capture code for the display's dimensions. 117 | if(useFullScreenCaps == false) ledBounds = new Rectangle[leds.length]; 118 | ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); 119 | gd = ge.getScreenDevices(); 120 | 121 | try { 122 | bot = new Robot(gd[screenNumber]); 123 | } 124 | catch(AWTException e) { 125 | System.out.println("new Robot() failed"); 126 | exit(); 127 | } 128 | gc = gd[screenNumber].getConfigurations(); 129 | dispBounds = gc[0].getBounds(); 130 | dispBounds.x = dispBounds.y = 0; 131 | preview = createImage(5, 5, RGB); 132 | preview.loadPixels(); 133 | 134 | // Precompute locations of every pixel to read when downsampling. 135 | // Saves a bunch of math on each frame, at the expense of a chunk 136 | // of RAM. Number of samples is now fixed at 256; this allows for 137 | // some crazy optimizations in the downsampling code. 138 | for(i=0; i> 8); // LED count high byte 184 | serialData[4] = (byte)((leds.length - 1) & 0xff); // LED count low byte 185 | serialData[5] = (byte)(serialData[3] ^ serialData[4] ^ 0x55); // Checksum 186 | 187 | // Pre-compute gamma correction table for LED brightness levels: 188 | for(i=0; i<256; i++) { 189 | f = pow((float)i / 255.0, 2.8); 190 | gamma[i][0] = (byte)(f * 255.0 + 0.5); 191 | gamma[i][1] = (byte)(f * 240.0 + 0.5); 192 | gamma[i][2] = (byte)(f * 220.0 + 0.5); 193 | } 194 | } 195 | 196 | // PER_FRAME PROCESSING ------------------------------------------------------ 197 | 198 | void draw () { 199 | BufferedImage img; 200 | int i, j, o, c, weight, rb, g, sum, deficit, s2; 201 | int[] pxls, offs; 202 | 203 | if(useFullScreenCaps == true ) { 204 | img = bot.createScreenCapture(dispBounds); 205 | // Get location of source pixel data 206 | screenData = 207 | ((DataBufferInt)img.getRaster().getDataBuffer()).getData(); 208 | } 209 | 210 | weight = 257 - fade; // 'Weighting factor' for new frame vs. old 211 | j = 6; // Serial led data follows header / magic word 212 | 213 | // This computes a single pixel value filtered down from a rectangular 214 | // section of the screen. While it would seem tempting to use the native 215 | // image scaling in Processing/Java, in practice this didn't look very 216 | // good -- either too pixelated or too blurry, no happy medium. So 217 | // instead, a "manual" downsampling is done here. In the interest of 218 | // speed, it doesn't actually sample every pixel within a block, just 219 | // a selection of 256 pixels spaced within the block...the results still 220 | // look reasonably smooth and are handled quickly enough for video. 221 | 222 | for(i=0; i> 24) & 0xff) * weight + 241 | prevColor[i][0] * fade) >> 8); 242 | ledColor[i][1] = (short)(((( g >> 16) & 0xff) * weight + 243 | prevColor[i][1] * fade) >> 8); 244 | ledColor[i][2] = (short)((((rb >> 8) & 0xff) * weight + 245 | prevColor[i][2] * fade) >> 8); 246 | // Boost pixels that fall below the minimum brightness 247 | sum = ledColor[i][0] + ledColor[i][1] + ledColor[i][2]; 248 | if(sum < minBrightness) { 249 | if(sum == 0) { // To avoid divide-by-zero 250 | deficit = minBrightness / 3; // Spread equally to R,G,B 251 | ledColor[i][0] += deficit; 252 | ledColor[i][1] += deficit; 253 | ledColor[i][2] += deficit; 254 | } else { 255 | deficit = minBrightness - sum; 256 | s2 = sum * 2; 257 | // Spread the "brightness deficit" back into R,G,B in proportion to 258 | // their individual contribition to that deficit. Rather than simply 259 | // boosting all pixels at the low end, this allows deep (but saturated) 260 | // colors to stay saturated...they don't "pink out." 261 | ledColor[i][0] += deficit * (sum - ledColor[i][0]) / s2; 262 | ledColor[i][1] += deficit * (sum - ledColor[i][1]) / s2; 263 | ledColor[i][2] += deficit * (sum - ledColor[i][2]) / s2; 264 | } 265 | } 266 | 267 | // Apply gamma curve and place in serial output buffer 268 | serialData[j++] = gamma[ledColor[i][0]][0]; 269 | serialData[j++] = gamma[ledColor[i][1]][1]; 270 | serialData[j++] = gamma[ledColor[i][2]][2]; 271 | // Update pixels in preview image 272 | preview.pixels[leds[i][1] * 5 + leds[i][0]] = 0xFF000000 | 273 | (ledColor[i][0] << 16) | (ledColor[i][1] << 8) | ledColor[i][2]; 274 | } 275 | 276 | if(port != null) port.write(serialData); // Issue data to Arduino 277 | 278 | // Show live preview image 279 | preview.updatePixels(); 280 | scale(40); 281 | image(preview, 0, 0); 282 | 283 | println(frameRate); // How are we doing? 284 | 285 | // Copy LED color data to prior frame array for next pass 286 | arraycopy(ledColor, 0, prevColor, 0, ledColor.length); 287 | } 288 | 289 | // CLEANUP ------------------------------------------------------------------- 290 | 291 | // The DisposeHandler is called on program exit (but before the Serial library 292 | // is shutdown), in order to turn off the LEDs (reportedly more reliable than 293 | // stop()). Seems to work for the window close box and escape key exit, but 294 | // not the 'Quit' menu option. Thanks to phi.lho in the Processing forums. 295 | 296 | void dispose() { 297 | // Fill serialData (after header) with 0's, and issue to Arduino... 298 | java.util.Arrays.fill(serialData, 6, serialData.length, (byte)0); 299 | if(port != null) port.write(serialData); 300 | } -------------------------------------------------------------------------------- /Processing/Colorswirl/Colorswirl.pde: -------------------------------------------------------------------------------- 1 | // "Colorswirl" LED demo. This is the host PC-side code written in 2 | // Processing; intended for use with a USB-connected Arduino microcontroller 3 | // running the accompanying LED streaming code. Requires one strand of 4 | // Digital RGB LED Pixels (Adafruit product ID #322, specifically the newer 5 | // WS2801-based type, strand of 25) and a 5 Volt power supply (such as 6 | // Adafruit #276). You may need to adapt the code and the hardware 7 | // arrangement for your specific configuration. 8 | 9 | // -------------------------------------------------------------------- 10 | // This file is part of Adalight. 11 | 12 | // Adalight is free software: you can redistribute it and/or modify 13 | // it under the terms of the GNU Lesser General Public License as 14 | // published by the Free Software Foundation, either version 3 of 15 | // the License, or (at your option) any later version. 16 | 17 | // Adalight is distributed in the hope that it will be useful, 18 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | // GNU Lesser General Public License for more details. 21 | 22 | // You should have received a copy of the GNU Lesser General Public 23 | // License along with Adalight. If not, see 24 | // . 25 | // -------------------------------------------------------------------- 26 | 27 | import processing.serial.*; 28 | 29 | int N_LEDS = 25; // Max of 65536 30 | 31 | void setup() 32 | { 33 | byte[] buffer = new byte[6 + N_LEDS * 3]; 34 | Serial myPort; 35 | int i, hue1, hue2, bright, lo, r, g, b, t, prev, frame = 0; 36 | long totalBytesSent = 0; 37 | float sine1, sine2; 38 | 39 | noLoop(); 40 | 41 | // Assumes the Arduino is the first/only serial device. If this is not the 42 | // case, change the device index here. println(Serial.list()); can be used 43 | // to get a list of available serial devices. 44 | myPort = new Serial(this, Serial.list()[0], 115200); 45 | 46 | // A special header / magic word is expected by the corresponding LED 47 | // streaming code running on the Arduino. This only needs to be initialized 48 | // once because the number of LEDs remains constant: 49 | buffer[0] = 'A'; // Magic word 50 | buffer[1] = 'd'; 51 | buffer[2] = 'a'; 52 | buffer[3] = byte((N_LEDS - 1) >> 8); // LED count high byte 53 | buffer[4] = byte((N_LEDS - 1) & 0xff); // LED count low byte 54 | buffer[5] = byte(buffer[3] ^ buffer[4] ^ 0x55); // Checksum 55 | 56 | sine1 = 0.0; 57 | hue1 = 0; 58 | prev = second(); // For bandwidth statistics 59 | 60 | for (;;) { 61 | sine2 = sine1; 62 | hue2 = hue1; 63 | 64 | // Start at position 6, after the LED header/magic word 65 | for (i = 6; i < buffer.length; ) { 66 | // Fixed-point hue-to-RGB conversion. 'hue2' is an integer in the 67 | // range of 0 to 1535, where 0 = red, 256 = yellow, 512 = green, etc. 68 | // The high byte (0-5) corresponds to the sextant within the color 69 | // wheel, while the low byte (0-255) is the fractional part between 70 | // the primary/secondary colors. 71 | lo = hue2 & 255; 72 | switch((hue2 >> 8) % 6) { 73 | case 0: 74 | r = 255; 75 | g = lo; 76 | b = 0; 77 | break; 78 | case 1: 79 | r = 255 - lo; 80 | g = 255; 81 | b = 0; 82 | break; 83 | case 2: 84 | r = 0; 85 | g = 255; 86 | b = lo; 87 | break; 88 | case 3: 89 | r = 0; 90 | g = 255 - lo; 91 | b = 255; 92 | break; 93 | case 4: 94 | r = lo; 95 | g = 0; 96 | b = 255; 97 | break; 98 | default: 99 | r = 255; 100 | g = 0; 101 | b = 255 - lo; 102 | break; 103 | } 104 | 105 | // Resulting hue is multiplied by brightness in the range of 0 to 255 106 | // (0 = off, 255 = brightest). Gamma corrrection (the 'pow' function 107 | // here) adjusts the brightness to be more perceptually linear. 108 | bright = int(pow(0.5 + sin(sine2) * 0.5, 2.8) * 255.0); 109 | buffer[i++] = byte((r * bright) / 255); 110 | buffer[i++] = byte((g * bright) / 255); 111 | buffer[i++] = byte((b * bright) / 255); 112 | 113 | // Each pixel is slightly offset in both hue and brightness 114 | hue2 += 40; 115 | sine2 += 0.3; 116 | } 117 | 118 | // Slowly rotate hue and brightness in opposite directions 119 | hue1 = (hue1 + 4) % 1536; 120 | sine1 -= .03; 121 | 122 | // Issue color data to LEDs and keep track of the byte and frame counts 123 | myPort.write(buffer); 124 | totalBytesSent += buffer.length; 125 | frame++; 126 | 127 | // Update statistics once per second 128 | if ((t = second()) != prev) { 129 | print("Average frames/sec: "); 130 | print(int((float)frame / (float)millis() * 1000.0)); 131 | print(", bytes/sec: "); 132 | println(int((float)totalBytesSent / (float)millis() * 1000.0)); 133 | prev = t; 134 | } 135 | } 136 | } 137 | 138 | void draw() 139 | { 140 | } 141 | 142 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | Adalight is free software: you can redistribute it and/or modify 2 | it under the terms of the GNU Lesser General Public License as 3 | published by the Free Software Foundation, either version 3 of 4 | the License, or (at your option) any later version. 5 | 6 | Adalight is distributed in the hope that it will be useful, 7 | but WITHOUT ANY WARRANTY; without even the implied warranty of 8 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 9 | GNU Lesser General Public License for more details. 10 | 11 | You should have received a copy of the GNU Lesser General Public 12 | License along with Adalight. If not, see . 13 | --------------------------------------------------------------------------------