From e5141bfbea0b24fbaceabf2c9e5eff1b02af4732 Mon Sep 17 00:00:00 2001 From: jprodgers Date: Thu, 28 May 2015 14:45:21 +0200 Subject: [PATCH] Migration and reorganization post google code. I've re-arranged and re-named a number of things in the move over from google code. I've added a few animations and things as well. --- .../LoLShield_Breathe/LoLShield_Breathe.pde | 0 .../LoLShield_CharliHeart.pde | 164 +++--- .../Animations/LoLShield_Demo/LoLDemo.ino | 493 +++++++++++++++++ .../LoLShield_DoubleHelix.ino | 0 .../LoLShield_Life/LoLShield_Life.pde | 0 .../LoLShield_Plasma/LoLShield_Plasma.ino | 0 .../LoLShield_TextScrolling.ino | 39 ++ .../LoLShield_Invader/LoLShield_Invader.pde | 0 .../Games}/LoLShield_Pong/LoLShield_Pong.pde | 0 .../LoLShield_Tetris/LoLShield_Tetris.h | 0 .../LoLShield_Tetris/LoLShield_Tetris.pde | 0 .../LoLShield_BasicTest.pde | 0 .../LoLShield_FadeTest/LoLShield_FadeTest.pde | 0 .../LoLShield_FontTest/LoLShield_FontTest.pde | 0 extras/base12clock/base12clock.pde | 110 ++++ extras/beltbuckle/beltbuckle.ino | 510 ++++++++++++++++++ .../lolcomm}/lolcomm-control/Makefile | 0 .../lolcomm}/lolcomm-control/control.c | 0 {lolcomm => extras/lolcomm}/lolcomm.pde | 0 .../lolcomm}/lolcommand_funcs.h | 0 {lolcomm => extras/lolcomm}/lolcommands.pde | 0 {lolcomm => extras/lolcomm}/lolproto.h | 0 pong1/pong1.pde | 249 --------- 23 files changed, 1234 insertions(+), 331 deletions(-) rename {lib/examples => examples/Animations}/LoLShield_Breathe/LoLShield_Breathe.pde (100%) rename {lib/examples => examples/Animations}/LoLShield_CharliHeart/LoLShield_CharliHeart.pde (94%) create mode 100644 examples/Animations/LoLShield_Demo/LoLDemo.ino rename {lib/examples => examples/Animations}/LoLShield_DoubleHelix/LoLShield_DoubleHelix.ino (100%) rename {lib/examples => examples/Animations}/LoLShield_Life/LoLShield_Life.pde (100%) rename {lib/examples => examples/Animations}/LoLShield_Plasma/LoLShield_Plasma.ino (100%) create mode 100644 examples/Animations/LoLShield_TextScrolling/LoLShield_TextScrolling.ino rename {lib/examples => examples/Games}/LoLShield_Invader/LoLShield_Invader.pde (100%) rename {lib/examples => examples/Games}/LoLShield_Pong/LoLShield_Pong.pde (100%) rename {lib/examples => examples/Games}/LoLShield_Tetris/LoLShield_Tetris.h (100%) rename {lib/examples => examples/Games}/LoLShield_Tetris/LoLShield_Tetris.pde (100%) rename {lib/examples => examples}/LoLShield_BasicTest/LoLShield_BasicTest.pde (100%) rename {lib/examples => examples}/LoLShield_FadeTest/LoLShield_FadeTest.pde (100%) rename {lib/examples => extras}/LoLShield_FontTest/LoLShield_FontTest.pde (100%) create mode 100644 extras/base12clock/base12clock.pde create mode 100644 extras/beltbuckle/beltbuckle.ino rename {lolcomm => extras/lolcomm}/lolcomm-control/Makefile (100%) rename {lolcomm => extras/lolcomm}/lolcomm-control/control.c (100%) rename {lolcomm => extras/lolcomm}/lolcomm.pde (100%) rename {lolcomm => extras/lolcomm}/lolcommand_funcs.h (100%) rename {lolcomm => extras/lolcomm}/lolcommands.pde (100%) rename {lolcomm => extras/lolcomm}/lolproto.h (100%) delete mode 100644 pong1/pong1.pde diff --git a/lib/examples/LoLShield_Breathe/LoLShield_Breathe.pde b/examples/Animations/LoLShield_Breathe/LoLShield_Breathe.pde similarity index 100% rename from lib/examples/LoLShield_Breathe/LoLShield_Breathe.pde rename to examples/Animations/LoLShield_Breathe/LoLShield_Breathe.pde diff --git a/lib/examples/LoLShield_CharliHeart/LoLShield_CharliHeart.pde b/examples/Animations/LoLShield_CharliHeart/LoLShield_CharliHeart.pde similarity index 94% rename from lib/examples/LoLShield_CharliHeart/LoLShield_CharliHeart.pde rename to examples/Animations/LoLShield_CharliHeart/LoLShield_CharliHeart.pde index 0847dfd..5286d0a 100644 --- a/lib/examples/LoLShield_CharliHeart/LoLShield_CharliHeart.pde +++ b/examples/Animations/LoLShield_CharliHeart/LoLShield_CharliHeart.pde @@ -1,82 +1,82 @@ -/* - Example for Charliplexing library - - Alex Wenger http://arduinobuch.wordpress.com/ - - History: - 30/Dez/09 - V0.0 wrote the first version at 26C3/Berlin - -*/ -#include "Charliplexing.h" - -struct point { - uint8_t xp; // Point Position in X direction (multplied by 16) - uint8_t x_speed; // Speed - uint8_t flag; -} points[9]; - -void setup() // run once, when the sketch starts -{ - LedSign::Init(); - - for(uint8_t i = 0; i < 9; i++) - { - points[i].xp = 0; - points[i].x_speed = random(1, 16); - points[i].flag = 1; - } -} - -uint8_t heart_p[] = { - 4,5, - 3,4, - 2,4, - 5,4, - 6,4, - 7,5, - 1,5, - 7,6, - 1,6, - 6,7, - 2,7, - 5,8, - 3,8, - 4,9, -}; - -void heart() -{ - for(uint8_t y = 0; y < 9; y++) - for(uint8_t x = 3; x < 11; x++) - { - LedSign::Set(x,y,0); - } - for(uint8_t i = 0; i < 14; i++) - { - LedSign::Set(heart_p[i*2+1],heart_p[i*2],1); - } -} - -uint8_t heart_flag; - -void loop() // run over and over again -{ - for(uint8_t i = 0; i < 9; i++) - { - points[i].xp += points[i].x_speed; - if (points[i].xp >= 14*16) - { - points[i].x_speed = random(1, 16); - points[i].xp = 0; - points[i].flag ^= 1; - } - LedSign::Set(points[i].xp/16,i,points[i].flag); - } - - heart_flag++; - if (heart_flag < 20) { - heart(); - } - - delay(40); -} +/* + Example for Charliplexing library + + Alex Wenger http://arduinobuch.wordpress.com/ + + History: + 30/Dez/09 - V0.0 wrote the first version at 26C3/Berlin + +*/ +#include "Charliplexing.h" + +struct point { + uint8_t xp; // Point Position in X direction (multplied by 16) + uint8_t x_speed; // Speed + uint8_t flag; +} points[9]; + +void setup() // run once, when the sketch starts +{ + LedSign::Init(); + + for(uint8_t i = 0; i < 9; i++) + { + points[i].xp = 0; + points[i].x_speed = random(1, 16); + points[i].flag = 1; + } +} + +uint8_t heart_p[] = { + 4,5, + 3,4, + 2,4, + 5,4, + 6,4, + 7,5, + 1,5, + 7,6, + 1,6, + 6,7, + 2,7, + 5,8, + 3,8, + 4,9, +}; + +void heart() +{ + for(uint8_t y = 0; y < 9; y++) + for(uint8_t x = 3; x < 11; x++) + { + LedSign::Set(x,y,0); + } + for(uint8_t i = 0; i < 14; i++) + { + LedSign::Set(heart_p[i*2+1],heart_p[i*2],1); + } +} + +uint8_t heart_flag; + +void loop() // run over and over again +{ + for(uint8_t i = 0; i < 9; i++) + { + points[i].xp += points[i].x_speed; + if (points[i].xp >= 14*16) + { + points[i].x_speed = random(1, 16); + points[i].xp = 0; + points[i].flag ^= 1; + } + LedSign::Set(points[i].xp/16,i,points[i].flag); + } + + heart_flag++; + if (heart_flag < 20) { + heart(); + } + + delay(40); +} diff --git a/examples/Animations/LoLShield_Demo/LoLDemo.ino b/examples/Animations/LoLShield_Demo/LoLDemo.ino new file mode 100644 index 0000000..503cc11 --- /dev/null +++ b/examples/Animations/LoLShield_Demo/LoLDemo.ino @@ -0,0 +1,493 @@ +#include "Charliplexing.h" +#include "Myfont.h" +#include "Arduino.h" +#include + +int toggleState; +int EEPROMaddress = 0; +int charLength[]={ + 20, 14, 23, 30}; +unsigned char text0[]="My eyes are up there"; +unsigned char text1[]="Blinky or GTFO"; +unsigned char text2[]="Enjoying the lightshow?"; +unsigned char text3[]="Would you like to play a game?"; + +//Game of Life stuff +#define DELAY 150 //Sets the time each generation is shown +#define RESEEDRATE 5000 //Sets the rate the world is re-seeded +#define SIZEX 14 //Sets the X axis size +#define SIZEY 9 //Sets the Y axis size +byte world[SIZEX][SIZEY][2]; //Creates a double buffer world +long density = 50; //Sets density % during seeding +int geck = 0; //Counter for re-seeding + +//ball stuff +int collision[14][9]; + +void setup(){ + toggleState = EEPROM.read(EEPROMaddress); + upToggleState(); + + if (0==toggleState || 3==toggleState){ + LedSign::Init(GRAYSCALE); + } + else{ + LedSign::Init(); + } + + for (int i = toggleState+1; i > 0; i--){ + LedSign::Set(i-1, 0, 255); + } + delay(1000); + LedSign::Clear(0); + +} + +void loop(){ + /* + 0 *Plasma + 3 *Game of Life + 6 "Would you like to play a game?" + 7 *Double Helix + */ + switch(toggleState){ + case 0: + plasma(); + break; + case 1: + life(); + break; + case 2: + Myfont::Banner(charLength[3],text3); + break; + case 3: + DNA(); + break; + default: + EEPROM.write(EEPROMaddress, 0); + } +} + +//Ups or resets the state counter +void upToggleState(){ + toggleState++; + if (toggleState > 3) toggleState = 0; + EEPROM.write(EEPROMaddress, toggleState); +} + +void plasma(){ + /* + Plasma + written by Zach Archer http://zacharcher.com/ + + NOTES: + - Requires the LoLshield library to run. Get the library here: http://code.google.com/p/lolshield/downloads/ + - How to install the library: http://www.arduino.cc/en/Hacking/Libraries + + This sketch moves two points along Lissajious curves. See: http://en.wikipedia.org/wiki/Lissajous_curve + The distances between each LED and each point are multiplied, + then this value is shaped using a sine function, and this sets the brightness of each LED. + */ + + // Convenient 2D point structure + struct Point { + float x; + float y; + }; + + + + float phase = 0.0; + float phaseIncrement = 0.08; // Controls the speed of the moving points. Higher == faster. I like 0.08 . + float colorStretch = 0.11; // Higher numbers will produce tighter color bands. I like 0.11 . + + + // This function is called every frame. + while(true) { + phase += phaseIncrement; + + // The two points move along Lissajious curves, see: http://en.wikipedia.org/wiki/Lissajous_curve + // We want values that fit the LED grid: x values between 0..13, y values between 0..8 . + // The sin() function returns values in the range of -1.0..1.0, so scale these to our desired ranges. + // The phase value is multiplied by various constants; I chose these semi-randomly, to produce a nice motion. + Point p1 = { + (sin(phase*1.000)+1.0) * 7.5, (sin(phase*1.310)+1.0) * 4.0 }; + Point p2 = { + (sin(phase*1.770)+1.0) * 7.5, (sin(phase*2.865)+1.0) * 4.0 }; + + byte row, col; + + // For each row... + for( row=0; row<9; row++ ) { + float row_f = float(row); // Optimization: Keep a floating point value of the row number, instead of recasting it repeatedly. + + // For each column... + for( col=0; col<14; col++ ) { + float col_f = float(col); // Optimization. + + // Calculate the distance between this LED, and p1. + Point dist1 = { + col_f - p1.x, row_f - p1.y }; // The vector from p1 to this LED. + float distance = sqrt( dist1.x*dist1.x + dist1.y*dist1.y ); + + // Calculate the distance between this LED, and p2. + Point dist2 = { + col_f - p2.x, row_f - p2.y }; // The vector from p2 to this LED. + // Multiply this with the other distance, this will create weird plasma values :) + distance *= sqrt( dist2.x*dist2.x + dist2.y*dist2.y ); + //distance += sqrt( dist2.x*dist2.x + dist2.y*dist2.y ); // Variation: weird linear color bands. Might need to increase colorStretch + + + // Warp the distance with a sin() function. As the distance value increases, the LEDs will get light,dark,light,dark,etc... + // You can use a cos() for slightly different shading, or experiment with other functions. Go crazy! + float color_f = (sin( distance * colorStretch ) + 1.0) * 0.5; // range: 0.0...1.0 + + // Square the color_f value to weight it towards 0. The image will be darker and have higher contrast. + color_f *= color_f; + //color_f *= color_f*color_f*color_f; // Uncomment this line to make it even darker :) + + // Scale the color up to 0..7 . Max brightness is 7. + LedSign::Set( col, row, byte( round(color_f * 7.0) ) ); + } + } + // There's so much math happening, it's already a bit slow ;) No need for extra delays! + //delay( 20 ); + } +} + +void DNA(){ + /* + DoubleHelix + written by Zach Archer http://zacharcher.com/ + + NOTES: + - Requires the LoLshield library to run. Get the library here: http://code.google.com/p/lolshield/downloads/ + - How to install the library: http://www.arduino.cc/en/Hacking/Libraries + + This sketch draws two sine waves with different brightness values. + The phase of the "darker" sine wave will drift a bit. + On every other column, LEDs between the sines will be subtly lit (hopefully resembling DNA nucleobases). + */ + + // You can tweak these values to create a custom DNA molecule :) + float stretch = 0.44; // The width of each sine wave. Smaller values create wider sine waves. I like 0.44 . + + float phaseIncrement = 0.1; // How fast the sines move. I like 0.1 . + + // The phase of the "darker" sine wave will drift (relative to the "lighter" sine wave). + // This makes the DoubleHelix more organic/hypnotic . + float driftIncrement = 0.019; // The speed it drifts back and forth. Larger == faster. I like 0.019 . + float driftForce = 0.4; // The visual amount of drift. I like 0.4 . + + // On every other column, light the LEDs between the sine waves, resembling the nucleotides of a DNA molecule. + // This looks good if we switch between lighting odd columns, then even columns -- the molecule appears to be moving. + float barPhaseIncrement = 0.09; // Bar movement speed. Plz use values between 0..1 . I like 0.09 . + + // Brightness values. Range is 0..7 + byte lightSineBrightness = 7; + byte darkSineBrightness = 3; + byte barBrightness = 1; + + // (End tweak section) + + // These values change every frame: + float phase = 0.0; // This is how "far" we've travelled along the DNA. + float driftPhase = 0.0; + float barPhase = 0.0; + + // This function is called every frame. + while(true) { + phase += phaseIncrement; // Move the sine waves forward. + + // The "darker" sine wave drifts (relative to the "lighter" sine wave). + driftPhase += driftIncrement; + + // Increment the position of the bars. + barPhase += barPhaseIncrement; + if( barPhase > 1.0 ) barPhase -= 1.0; // Wrap this value between 0..1 . + + // We'll hilite either the even columns, or odd columns, depending on the value of barPhase. + boolean drawEvenBars = (barPhase < 0.5); + + byte row, col; + + // For each column of LEDs... + for( col=0; col<14; col++ ) { + + // This is the "raw" value for the lighter sine wave. Range: -1.0...1.0 + float lightSineThisColumn = sin( phase + float(col)*stretch ); + + // Scale the "raw" value and round it off, so the range is 0..8 . This is the LED we're going to light in this column. + int lightSine = int( round( lightSineThisColumn*4.0 ) ) + 4; + + // driftPhase controls the phase drift of the "darker" sine. + // The drift amount is derived from this sin() function, so it will drift back and forth. + // Orbit around 2.1, which is about 1/3 phase offset from the lighter sine wave (2*PI/3). Looks pretty good. + float drift = 2.1 + (driftForce * sin( driftPhase )); + + // This is the LED we're going to light for the "dark" sine wave. + // This is similar to computing the lightSine value, but it's compacted into one line :P + int darkSine = int( round( sin(phase+drift+float(col)*stretch)*4.0 ) ) + 4; + + // For each LED within the column... + for( row=0; row<9; row++ ) { + + // Does this LED belong to our light sine wave? + if( row==lightSine ) { + LedSign::Set( col, row, lightSineBrightness ); // The third argument is the brightness. Max bright == 7. + + // Does this LED belong to our dark sine wave? + } + else if( row==darkSine ) { + LedSign::Set( col, row, darkSineBrightness ); // The third argument is the brightness. + + } + else { + // This LED doesn't belong to either sine wave. So we'll turn it off, unless it belongs to a vertical bar. + int color = 0; // 0 == unlit + + // Alternate even/odd columns: + // If col is an odd number, (col & 0x1) evaluates to true. (Example: 13 == B1101, rightmost bit is 1, so it's odd!) + // The ^ operator is binary XOR. So this statement evaluates true if _one_ condition is met, but _not_ both. + if( (col & 0x1) ^ (drawEvenBars) ) { + + // If lightSine is above this LED, and darkSine is below, then this LED belongs to a vertical bar. + if( lightSine < darkSine ) { + if( lightSine //Imports the library, which needs to be + //Initialized in setup. + + + randomSeed(analogRead(5)); + //Builds the world with an initial seed. + for (int i = 0; i < SIZEX; i++) { + for (int j = 0; j < SIZEY; j++) { + if (random(100) < density) { + world[i][j][0] = 1; + } + else { + world[i][j][0] = 0; + } + world[i][j][1] = 0; + } + } + + + while(true) { + // Birth and death cycle + for (int x = 0; x < SIZEX; x++) { + for (int y = 0; y < SIZEY; y++) { + // Default is for cell to stay the same + world[x][y][1] = world[x][y][0]; + int count = neighbours(x, y); + geck++; + if (count == 3 && world[x][y][0] == 0) { + // A new cell is born + world[x][y][1] = 1; + LedSign::Set(x,y,1); + } + else if ((count < 2 || count > 3) && world[x][y][0] == 1) { + // Cell dies + world[x][y][1] = 0; + LedSign::Set(x,y,0); + } + } + + } + + //Counts and then checks for re-seeding + //Otherwise the display will die out at some point + geck++; + if (geck > RESEEDRATE){ + seedWorld(); + geck = 0; + } + + // Copy next generation into place + for (int x = 0; x < SIZEX; x++) { + for (int y = 0; y < SIZEY; y++) { + world[x][y][0] = world[x][y][1]; + } + } + delay(DELAY); + } + + //Re-seeds based off of RESEEDRATE + + + //Runs the rule checks, including screen wrap + +} +void seedWorld(){ + randomSeed(analogRead(5)); + for (int i = 0; i < SIZEX; i++) { + for (int j = 0; j < SIZEY; j++) { + if (random(100) < density) { + world[i][j][1] = 1; + } + } + } +} +int neighbours(int x, int y) { + return world[(x + 1) % SIZEX][y][0] + + world[x][(y + 1) % SIZEY][0] + + world[(x + SIZEX - 1) % SIZEX][y][0] + + world[x][(y + SIZEY - 1) % SIZEY][0] + + world[(x + 1) % SIZEX][(y + 1) % SIZEY][0] + + world[(x + SIZEX - 1) % SIZEX][(y + 1) % SIZEY][0] + + world[(x + SIZEX - 1) % SIZEX][(y + SIZEY - 1) % SIZEY][0] + + world[(x + 1) % SIZEX][(y + SIZEY - 1) % SIZEY][0]; +} diff --git a/lib/examples/LoLShield_DoubleHelix/LoLShield_DoubleHelix.ino b/examples/Animations/LoLShield_DoubleHelix/LoLShield_DoubleHelix.ino similarity index 100% rename from lib/examples/LoLShield_DoubleHelix/LoLShield_DoubleHelix.ino rename to examples/Animations/LoLShield_DoubleHelix/LoLShield_DoubleHelix.ino diff --git a/lib/examples/LoLShield_Life/LoLShield_Life.pde b/examples/Animations/LoLShield_Life/LoLShield_Life.pde similarity index 100% rename from lib/examples/LoLShield_Life/LoLShield_Life.pde rename to examples/Animations/LoLShield_Life/LoLShield_Life.pde diff --git a/lib/examples/LoLShield_Plasma/LoLShield_Plasma.ino b/examples/Animations/LoLShield_Plasma/LoLShield_Plasma.ino similarity index 100% rename from lib/examples/LoLShield_Plasma/LoLShield_Plasma.ino rename to examples/Animations/LoLShield_Plasma/LoLShield_Plasma.ino diff --git a/examples/Animations/LoLShield_TextScrolling/LoLShield_TextScrolling.ino b/examples/Animations/LoLShield_TextScrolling/LoLShield_TextScrolling.ino new file mode 100644 index 0000000..b2ee632 --- /dev/null +++ b/examples/Animations/LoLShield_TextScrolling/LoLShield_TextScrolling.ino @@ -0,0 +1,39 @@ + +#include "Charliplexing.h" +#include "Myfont.h" + +#include "Arduino.h" + + + int leng=0; //provides the length of the char array + unsigned char test[]="full ASCII charset: $ % & ! [ ] { } \0"; //text has to end with '\0' !!!!!! + +/* ----------------------------------------------------------------- */ +/** MAIN program Setup + */ +void setup() // run once, when the sketch starts +{ + LedSign::Init(); + for(int i=0; ; i++){ //get the length of the text + if(test[i]==0){ + leng=i; + break; + } + + } +} + + +/* ----------------------------------------------------------------- */ +/** MAIN program Loop + */ + +void loop() // run over and over again +{ + + + + Myfont::Banner(leng,test); + + +} diff --git a/lib/examples/LoLShield_Invader/LoLShield_Invader.pde b/examples/Games/LoLShield_Invader/LoLShield_Invader.pde similarity index 100% rename from lib/examples/LoLShield_Invader/LoLShield_Invader.pde rename to examples/Games/LoLShield_Invader/LoLShield_Invader.pde diff --git a/lib/examples/LoLShield_Pong/LoLShield_Pong.pde b/examples/Games/LoLShield_Pong/LoLShield_Pong.pde similarity index 100% rename from lib/examples/LoLShield_Pong/LoLShield_Pong.pde rename to examples/Games/LoLShield_Pong/LoLShield_Pong.pde diff --git a/lib/examples/LoLShield_Tetris/LoLShield_Tetris.h b/examples/Games/LoLShield_Tetris/LoLShield_Tetris.h similarity index 100% rename from lib/examples/LoLShield_Tetris/LoLShield_Tetris.h rename to examples/Games/LoLShield_Tetris/LoLShield_Tetris.h diff --git a/lib/examples/LoLShield_Tetris/LoLShield_Tetris.pde b/examples/Games/LoLShield_Tetris/LoLShield_Tetris.pde similarity index 100% rename from lib/examples/LoLShield_Tetris/LoLShield_Tetris.pde rename to examples/Games/LoLShield_Tetris/LoLShield_Tetris.pde diff --git a/lib/examples/LoLShield_BasicTest/LoLShield_BasicTest.pde b/examples/LoLShield_BasicTest/LoLShield_BasicTest.pde similarity index 100% rename from lib/examples/LoLShield_BasicTest/LoLShield_BasicTest.pde rename to examples/LoLShield_BasicTest/LoLShield_BasicTest.pde diff --git a/lib/examples/LoLShield_FadeTest/LoLShield_FadeTest.pde b/examples/LoLShield_FadeTest/LoLShield_FadeTest.pde similarity index 100% rename from lib/examples/LoLShield_FadeTest/LoLShield_FadeTest.pde rename to examples/LoLShield_FadeTest/LoLShield_FadeTest.pde diff --git a/lib/examples/LoLShield_FontTest/LoLShield_FontTest.pde b/extras/LoLShield_FontTest/LoLShield_FontTest.pde similarity index 100% rename from lib/examples/LoLShield_FontTest/LoLShield_FontTest.pde rename to extras/LoLShield_FontTest/LoLShield_FontTest.pde diff --git a/extras/base12clock/base12clock.pde b/extras/base12clock/base12clock.pde new file mode 100644 index 0000000..a534ab2 --- /dev/null +++ b/extras/base12clock/base12clock.pde @@ -0,0 +1,110 @@ +/* + Base 12 Clock + + Writen for the LoL Shield, designed by Jimmie Rodgers: + http://jimmieprodgers.com/kits/lolshield/ + + This needs the Charliplexing library, which you can get at the + LoL Shield project page: http://code.google.com/p/lolshield/ + + This also uses the Adafruit DS1307 breakout, which you will also + need the library for: + http://www.ladyada.net/learn/breakoutplus/ds1307rtc.html + + Created by Jimmie Rodgers on 2/2/2011. + + This is free software; you can redistribute it and/or + modify it under the terms of the GNU Version 3 General Public + License as published by the Free Software Foundation; + or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +//These libraries need to be included for both the LoL Shield +//and DS1307 breakout. +#include "Charliplexing.h" +#include "WProgram.h" +#include +#include "RTClib.h" +RTC_DS1307 RTC; + +void setup () { + LedSign::Init(); //initializes the LoL Shield frame buffer + pinMode(16, OUTPUT); //16 and 17 power the DS1307 + pinMode(17, OUTPUT); + digitalWrite(16, LOW); //ground for the DS1307 + digitalWrite(17, HIGH);//provides 5v for the DS1307 + Wire.begin(); //starts the I2C serial on pins 18&19 + RTC.begin(); //starts communication with the DS1307 +} + +void loop(){ + DateTime now = RTC.now(); //creates a DateTime object + //I set the time all at once so that it doesn't cause + //strange timing issues + int hour = now.hour(); + int minute = now.minute(); + int second = now.second(); + + //These are used to easily parse the seconds + int fiveCount = second / 5; + int tenCount = second % 10; + + //It only needs to clear on counts of 10, as that + //is the only time the display really changes. + if (tenCount == 0 )LedSign::Clear(); + + //These loops set the seconds on the LoL Shield. + for (int i=0; i < tenCount+1; i++){ + if (i < 5)LedSign::Set(i+1, 8, 1); + else LedSign::Set(i+3, 8, 1); + } + for (int i=0; i < fiveCount+1;i++){ + LedSign::Set(i+1, 7, 1); + } + + //This loop sets the hour. + for (int x=0; x < hour; x++){ + if(x < 12){ + if (x < 6)LedSign::Set(x, 0, 1); + else LedSign::Set(x+1, 0, 1); + } + else{ + if (x < 18)LedSign::Set(x-12, 1, 1); + else LedSign::Set(x-11, 1, 1); + } + } + + //This loop sets the minutes + for (int x=0; x < minute; x++){ + if(x < 12){ + if (x < 6)LedSign::Set(x+1, 2, 1); + else LedSign::Set(x+2, 2, 1); + } + else if (x < 24){ + if (x < 18)LedSign::Set(x-11, 3, 1); + else LedSign::Set(x-10, 3, 1); + } + else if (x < 36){ + if (x < 30)LedSign::Set(x-23, 4, 1); + else LedSign::Set(x-22, 4, 1); + } + else if (x < 48){ + if (x < 42)LedSign::Set(x-35, 5, 1); + else LedSign::Set(x-34, 5, 1); + } + else if (x < 60){ + if (x < 54)LedSign::Set(x-47, 6, 1); + else LedSign::Set(x-46, 6, 1); + } + } + delay(500);//no reason to update much more than this +} diff --git a/extras/beltbuckle/beltbuckle.ino b/extras/beltbuckle/beltbuckle.ino new file mode 100644 index 0000000..f8d79de --- /dev/null +++ b/extras/beltbuckle/beltbuckle.ino @@ -0,0 +1,510 @@ +//This is a series of animations for a belt buckle. You can cycle the animations by cycling the power. + +#include "Charliplexing.h" +#include "Myfont.h" +#include "Arduino.h" +#include + +int toggleState; +int EEPROMaddress = 0; +int charLength[]={ + 20, 14, 23, 30}; +unsigned char text0[]="My eyes are up there"; +unsigned char text1[]="Blinky or GTFO"; +unsigned char text2[]="Enjoying the lightshow?"; +unsigned char text3[]="Would you like to play a game?"; + +//Game of Life stuff +#define DELAY 150 //Sets the time each generation is shown +#define RESEEDRATE 5000 //Sets the rate the world is re-seeded +#define SIZEX 14 //Sets the X axis size +#define SIZEY 9 //Sets the Y axis size +byte world[SIZEX][SIZEY][2]; //Creates a double buffer world +long density = 50; //Sets density % during seeding +int geck = 0; //Counter for re-seeding + +//ball stuff +int collision[14][9]; + +void setup(){ + toggleState = EEPROM.read(EEPROMaddress); + upToggleState(); + + if (1==toggleState || 7==toggleState){ + LedSign::Init(GRAYSCALE); + } + else{ + LedSign::Init(); + } + + for (int i = toggleState+1; i > 0; i--){ + LedSign::Set(i-1, 0, 255); + } + delay(1000); + LedSign::Clear(0); + +} + +void loop(){ + /* + 0 "My eyes are up there" + 1 *Plasma + 2 "Blinky or GTFO" + 3 *Game of Life + 4 "Enjoying the lightshow?" + 5 *Balls + 6 "Would you like to play a game?" + 7 *Double Helix + */ + switch(toggleState){ + case 0: + Myfont::Banner(charLength[0],text0); + break; + case 1: + plasma(); + break; + case 2: + Myfont::Banner(charLength[1],text1); + break; + case 3: + life(); + case 4: + Myfont::Banner(charLength[2],text2); + break; + case 5: + balls(); + break; + case 6: + Myfont::Banner(charLength[3],text3); + break; + case 7: + DNA(); + break; + default: + EEPROM.write(EEPROMaddress, 0); + } +} + +//Ups or resets the state counter +void upToggleState(){ + toggleState++; + if (toggleState > 7) toggleState = 0; + EEPROM.write(EEPROMaddress, toggleState); +} + +void plasma(){ + /* + Plasma + written by Zach Archer http://zacharcher.com/ + + NOTES: + - Requires the LoLshield library to run. Get the library here: http://code.google.com/p/lolshield/downloads/ + - How to install the library: http://www.arduino.cc/en/Hacking/Libraries + + This sketch moves two points along Lissajious curves. See: http://en.wikipedia.org/wiki/Lissajous_curve + The distances between each LED and each point are multiplied, + then this value is shaped using a sine function, and this sets the brightness of each LED. + */ + + // Convenient 2D point structure + struct Point { + float x; + float y; + }; + + + + float phase = 0.0; + float phaseIncrement = 0.08; // Controls the speed of the moving points. Higher == faster. I like 0.08 . + float colorStretch = 0.11; // Higher numbers will produce tighter color bands. I like 0.11 . + + + // This function is called every frame. + while(true) { + phase += phaseIncrement; + + // The two points move along Lissajious curves, see: http://en.wikipedia.org/wiki/Lissajous_curve + // We want values that fit the LED grid: x values between 0..13, y values between 0..8 . + // The sin() function returns values in the range of -1.0..1.0, so scale these to our desired ranges. + // The phase value is multiplied by various constants; I chose these semi-randomly, to produce a nice motion. + Point p1 = { + (sin(phase*1.000)+1.0) * 7.5, (sin(phase*1.310)+1.0) * 4.0 }; + Point p2 = { + (sin(phase*1.770)+1.0) * 7.5, (sin(phase*2.865)+1.0) * 4.0 }; + + byte row, col; + + // For each row... + for( row=0; row<9; row++ ) { + float row_f = float(row); // Optimization: Keep a floating point value of the row number, instead of recasting it repeatedly. + + // For each column... + for( col=0; col<14; col++ ) { + float col_f = float(col); // Optimization. + + // Calculate the distance between this LED, and p1. + Point dist1 = { + col_f - p1.x, row_f - p1.y }; // The vector from p1 to this LED. + float distance = sqrt( dist1.x*dist1.x + dist1.y*dist1.y ); + + // Calculate the distance between this LED, and p2. + Point dist2 = { + col_f - p2.x, row_f - p2.y }; // The vector from p2 to this LED. + // Multiply this with the other distance, this will create weird plasma values :) + distance *= sqrt( dist2.x*dist2.x + dist2.y*dist2.y ); + //distance += sqrt( dist2.x*dist2.x + dist2.y*dist2.y ); // Variation: weird linear color bands. Might need to increase colorStretch + + + // Warp the distance with a sin() function. As the distance value increases, the LEDs will get light,dark,light,dark,etc... + // You can use a cos() for slightly different shading, or experiment with other functions. Go crazy! + float color_f = (sin( distance * colorStretch ) + 1.0) * 0.5; // range: 0.0...1.0 + + // Square the color_f value to weight it towards 0. The image will be darker and have higher contrast. + color_f *= color_f; + //color_f *= color_f*color_f*color_f; // Uncomment this line to make it even darker :) + + // Scale the color up to 0..7 . Max brightness is 7. + LedSign::Set( col, row, byte( round(color_f * 7.0) ) ); + } + } + // There's so much math happening, it's already a bit slow ;) No need for extra delays! + //delay( 20 ); + } +} + +void DNA(){ + /* + DoubleHelix + written by Zach Archer http://zacharcher.com/ + + NOTES: + - Requires the LoLshield library to run. Get the library here: http://code.google.com/p/lolshield/downloads/ + - How to install the library: http://www.arduino.cc/en/Hacking/Libraries + + This sketch draws two sine waves with different brightness values. + The phase of the "darker" sine wave will drift a bit. + On every other column, LEDs between the sines will be subtly lit (hopefully resembling DNA nucleobases). + */ + + // You can tweak these values to create a custom DNA molecule :) + float stretch = 0.44; // The width of each sine wave. Smaller values create wider sine waves. I like 0.44 . + + float phaseIncrement = 0.1; // How fast the sines move. I like 0.1 . + + // The phase of the "darker" sine wave will drift (relative to the "lighter" sine wave). + // This makes the DoubleHelix more organic/hypnotic . + float driftIncrement = 0.019; // The speed it drifts back and forth. Larger == faster. I like 0.019 . + float driftForce = 0.4; // The visual amount of drift. I like 0.4 . + + // On every other column, light the LEDs between the sine waves, resembling the nucleotides of a DNA molecule. + // This looks good if we switch between lighting odd columns, then even columns -- the molecule appears to be moving. + float barPhaseIncrement = 0.09; // Bar movement speed. Plz use values between 0..1 . I like 0.09 . + + // Brightness values. Range is 0..7 + byte lightSineBrightness = 7; + byte darkSineBrightness = 3; + byte barBrightness = 1; + + // (End tweak section) + + // These values change every frame: + float phase = 0.0; // This is how "far" we've travelled along the DNA. + float driftPhase = 0.0; + float barPhase = 0.0; + + // This function is called every frame. + while(true) { + phase += phaseIncrement; // Move the sine waves forward. + + // The "darker" sine wave drifts (relative to the "lighter" sine wave). + driftPhase += driftIncrement; + + // Increment the position of the bars. + barPhase += barPhaseIncrement; + if( barPhase > 1.0 ) barPhase -= 1.0; // Wrap this value between 0..1 . + + // We'll hilite either the even columns, or odd columns, depending on the value of barPhase. + boolean drawEvenBars = (barPhase < 0.5); + + byte row, col; + + // For each column of LEDs... + for( col=0; col<14; col++ ) { + + // This is the "raw" value for the lighter sine wave. Range: -1.0...1.0 + float lightSineThisColumn = sin( phase + float(col)*stretch ); + + // Scale the "raw" value and round it off, so the range is 0..8 . This is the LED we're going to light in this column. + int lightSine = int( round( lightSineThisColumn*4.0 ) ) + 4; + + // driftPhase controls the phase drift of the "darker" sine. + // The drift amount is derived from this sin() function, so it will drift back and forth. + // Orbit around 2.1, which is about 1/3 phase offset from the lighter sine wave (2*PI/3). Looks pretty good. + float drift = 2.1 + (driftForce * sin( driftPhase )); + + // This is the LED we're going to light for the "dark" sine wave. + // This is similar to computing the lightSine value, but it's compacted into one line :P + int darkSine = int( round( sin(phase+drift+float(col)*stretch)*4.0 ) ) + 4; + + // For each LED within the column... + for( row=0; row<9; row++ ) { + + // Does this LED belong to our light sine wave? + if( row==lightSine ) { + LedSign::Set( col, row, lightSineBrightness ); // The third argument is the brightness. Max bright == 7. + + // Does this LED belong to our dark sine wave? + } + else if( row==darkSine ) { + LedSign::Set( col, row, darkSineBrightness ); // The third argument is the brightness. + + } + else { + // This LED doesn't belong to either sine wave. So we'll turn it off, unless it belongs to a vertical bar. + int color = 0; // 0 == unlit + + // Alternate even/odd columns: + // If col is an odd number, (col & 0x1) evaluates to true. (Example: 13 == B1101, rightmost bit is 1, so it's odd!) + // The ^ operator is binary XOR. So this statement evaluates true if _one_ condition is met, but _not_ both. + if( (col & 0x1) ^ (drawEvenBars) ) { + + // If lightSine is above this LED, and darkSine is below, then this LED belongs to a vertical bar. + if( lightSine < darkSine ) { + if( lightSine //Imports the library, which needs to be + //Initialized in setup. + + + randomSeed(analogRead(5)); + //Builds the world with an initial seed. + for (int i = 0; i < SIZEX; i++) { + for (int j = 0; j < SIZEY; j++) { + if (random(100) < density) { + world[i][j][0] = 1; + } + else { + world[i][j][0] = 0; + } + world[i][j][1] = 0; + } + } + + + while(true) { + // Birth and death cycle + for (int x = 0; x < SIZEX; x++) { + for (int y = 0; y < SIZEY; y++) { + // Default is for cell to stay the same + world[x][y][1] = world[x][y][0]; + int count = neighbours(x, y); + geck++; + if (count == 3 && world[x][y][0] == 0) { + // A new cell is born + world[x][y][1] = 1; + LedSign::Set(x,y,1); + } + else if ((count < 2 || count > 3) && world[x][y][0] == 1) { + // Cell dies + world[x][y][1] = 0; + LedSign::Set(x,y,0); + } + } + + } + + //Counts and then checks for re-seeding + //Otherwise the display will die out at some point + geck++; + if (geck > RESEEDRATE){ + seedWorld(); + geck = 0; + } + + // Copy next generation into place + for (int x = 0; x < SIZEX; x++) { + for (int y = 0; y < SIZEY; y++) { + world[x][y][0] = world[x][y][1]; + } + } + delay(DELAY); + } + + //Re-seeds based off of RESEEDRATE + + + //Runs the rule checks, including screen wrap + +} +void seedWorld(){ + randomSeed(analogRead(5)); + for (int i = 0; i < SIZEX; i++) { + for (int j = 0; j < SIZEY; j++) { + if (random(100) < density) { + world[i][j][1] = 1; + } + } + } +} +int neighbours(int x, int y) { + return world[(x + 1) % SIZEX][y][0] + + world[x][(y + 1) % SIZEY][0] + + world[(x + SIZEX - 1) % SIZEX][y][0] + + world[x][(y + SIZEY - 1) % SIZEY][0] + + world[(x + 1) % SIZEX][(y + 1) % SIZEY][0] + + world[(x + SIZEX - 1) % SIZEX][(y + 1) % SIZEY][0] + + world[(x + SIZEX - 1) % SIZEX][(y + SIZEY - 1) % SIZEY][0] + + world[(x + 1) % SIZEX][(y + SIZEY - 1) % SIZEY][0]; +} diff --git a/lolcomm/lolcomm-control/Makefile b/extras/lolcomm/lolcomm-control/Makefile similarity index 100% rename from lolcomm/lolcomm-control/Makefile rename to extras/lolcomm/lolcomm-control/Makefile diff --git a/lolcomm/lolcomm-control/control.c b/extras/lolcomm/lolcomm-control/control.c similarity index 100% rename from lolcomm/lolcomm-control/control.c rename to extras/lolcomm/lolcomm-control/control.c diff --git a/lolcomm/lolcomm.pde b/extras/lolcomm/lolcomm.pde similarity index 100% rename from lolcomm/lolcomm.pde rename to extras/lolcomm/lolcomm.pde diff --git a/lolcomm/lolcommand_funcs.h b/extras/lolcomm/lolcommand_funcs.h similarity index 100% rename from lolcomm/lolcommand_funcs.h rename to extras/lolcomm/lolcommand_funcs.h diff --git a/lolcomm/lolcommands.pde b/extras/lolcomm/lolcommands.pde similarity index 100% rename from lolcomm/lolcommands.pde rename to extras/lolcomm/lolcommands.pde diff --git a/lolcomm/lolproto.h b/extras/lolcomm/lolproto.h similarity index 100% rename from lolcomm/lolproto.h rename to extras/lolcomm/lolproto.h diff --git a/pong1/pong1.pde b/pong1/pong1.pde deleted file mode 100644 index c109077..0000000 --- a/pong1/pong1.pde +++ /dev/null @@ -1,249 +0,0 @@ - -//**************************************************************// -// Name : Pong for Arduino / Charlieplexing // -// Author : Benjamin Sonntag http://benjamin.sonntag.fr/ // -// Date : 28 dec 2009 // -// Version : 0.1 // -// Notes : Uses Charlieplexing techniques to light up // -// : a matrix of 126 LEDs in a 9x14 grid // -// : from Jimmie P Rodgers www.jimmieprodgers.com // -//**************************************************************// - -#include //This is in the Arduino library - -int blinkdelay = 70; //This basically controls brightness. Lower is dimmer -int runspeed = 14; //smaller = faster - -int pin13 =13; -int pin12 =12; -int pin11 =11; -int pin10 =10; -int pin09 =9; -int pin08 =8; -int pin07 =7; -int pin06 =6; -int pin05 =5; -int pin04 =4; -int pin03 =3; -int pin02 =2; - -const int pins[] = { - pin13,pin12,pin11,pin10,pin09,pin08,pin07,pin06,pin05,pin04,pin03,pin02}; - -const int ledMap[126][2] ={ -{pin13, pin05},{pin13, pin06},{pin13, pin07},{pin13, pin08},{pin13, pin09},{pin13, pin10},{pin13, pin11},{pin13, pin12},{pin13, pin04},{pin04, pin13},{pin13, pin03},{pin03, pin13},{pin13, pin02},{pin02, pin13}, -{pin12, pin05},{pin12, pin06},{pin12, pin07},{pin12, pin08},{pin12, pin09},{pin12, pin10},{pin12, pin11},{pin12, pin13},{pin12, pin04},{pin04, pin12},{pin12, pin03},{pin03, pin12},{pin12, pin02},{pin02, pin12}, -{pin11, pin05},{pin11, pin06},{pin11, pin07},{pin11, pin08},{pin11, pin09},{pin11, pin10},{pin11, pin12},{pin11, pin13},{pin11, pin04},{pin04, pin11},{pin11, pin03},{pin03, pin11},{pin11, pin02},{pin02, pin11}, -{pin10, pin05},{pin10, pin06},{pin10, pin07},{pin10, pin08},{pin10, pin09},{pin10, pin11},{pin10, pin12},{pin10, pin13},{pin10, pin04},{pin04, pin10},{pin10, pin03},{pin03, pin10},{pin10, pin02},{pin02, pin10}, -{pin09, pin05},{pin09, pin06},{pin09, pin07},{pin09, pin08},{pin09, pin10},{pin09, pin11},{pin09, pin12},{pin09, pin13},{pin09, pin04},{pin04, pin09},{pin09, pin03},{pin03, pin09},{pin09, pin02},{pin02, pin09}, -{pin08, pin05},{pin08, pin06},{pin08, pin07},{pin08, pin09},{pin08, pin10},{pin08, pin11},{pin08, pin12},{pin08, pin13},{pin08, pin04},{pin04, pin08},{pin08, pin03},{pin03, pin08},{pin08, pin02},{pin02, pin08}, -{pin07, pin05},{pin07, pin06},{pin07, pin08},{pin07, pin09},{pin07, pin10},{pin07, pin11},{pin07, pin12},{pin07, pin13},{pin07, pin04},{pin04, pin07},{pin07, pin03},{pin03, pin07},{pin07, pin02},{pin02, pin07}, -{pin06, pin05},{pin06, pin07},{pin06, pin08},{pin06, pin09},{pin06, pin10},{pin06, pin11},{pin06, pin12},{pin06, pin13},{pin06, pin04},{pin04, pin06},{pin06, pin03},{pin03, pin06},{pin06, pin02},{pin02, pin06}, -{pin05, pin06},{pin05, pin07},{pin05, pin08},{pin05, pin09},{pin05, pin10},{pin05, pin11},{pin05, pin12},{pin05, pin13},{pin05, pin04},{pin04, pin05},{pin05, pin03},{pin03, pin05},{pin05, pin02},{pin02, pin05} -}; - - -uint16_t screens[][9] = { - {0,240,264,516,516,516,516,264,240}, - {6148,4098,12387,8337,8457,8457,8337,12387,4098}, - {0,0,0,0,0,0,0,0,0}, - {0,0,0,0,0,0,0,0,0} -}; - - -// The figures from 0 to 9 encoded in 7 lines of 5 bits : -uint16_t figures[][7] = { -{14,17,17,17,17,17,14}, -{4,6,4,4,4,4,14}, -{14,17,16,14,1,1,31}, -{14,17,16,14,16,17,14}, -{8,12,10,9,31,8,8}, -{31,1,1,15,16,16,15}, -{14,17,1,15,17,17,14}, -{31,16,8,8,4,4,4}, -{14,17,17,14,17,17,14}, -{14,17,17,30,16,16,15}, -}; - - -int x,y,dx,dy; -int sh1y,sh2y,s1,s2; -int activescreen; - -void setup() { - x = 3; - y = 7; - sh1y=3; - sh2y=3; - dx = 1; - dy = 1; - s1 = 0; - s2 = 0; - activescreen = 0; - randomSeed(analogRead(0)); -} - -void loop() { - int ct1,ct2; - - - // The Ball shall bounce on the walls : - if (x==12 || x==1) { - dx=-dx; - if (random(0,6)>4) { - if (random(0,2)==1) { - s1++; if (s1==10) s1=0; - } else { - s2++; if (s2==10) s2=0; - } - drawscores(s1,s2); - } - } - if (y==8 || y==0) dy=-dy; - - - // Clear the non-active screen - for(ct2=0;ct2<9;ct2++) { - screens[1-activescreen][ct2]=0; - } - // Move the BALL : - x=x+dx; - y=y+dy; - - // Draw the ball : - screens[1-activescreen][y]=1<y) { - sh1y--; - } - if (sh1yy) { - sh2y--; - } - if (sh2y7) sh1y=7; - if (sh2y>7) sh2y=7; - if (sh1y<0) sh1y=0; - if (sh2y<0) sh2y=0; - - // swap the screens ;) (sometime we may need this double-buffer algorithm... - // of course, as of today it's a little bit overkill ...) - activescreen=1-activescreen; - for(ct1=0;ct1<20;ct1++) { - DisplayBitMap(); - } - // loop :) -} - - -// Draw the scores in a lovely scrolling :) -// Use the current active screen brutally ... -void drawscores(int s1,int s2) { - int i,j,ps1,ps2,ct2; - - for(ps1=0;ps1<8;ps1++) { - // Clear the active screen - for(ct2=0;ct2<9;ct2++) { - screens[activescreen][ct2]=0; - } - screens[activescreen][4]+=((1<<6) + (1<<7)); // -- in the middle - // Fill it with both scores : - // Left score goes up>down - ps2=8-ps1; - i=ps1; j=6; - while (i>=0 && j>=0) { - screens[activescreen][i]+=figures[s1][j]; - i--; j--; - } - // Right score goes down>up - i=ps2; j=0; - while (i<=8 && j<=6) { - screens[activescreen][i]+=figures[s2][j]<<9; - i++; j++; - } - // Draw it for a little time ... - for(ct2=0;ct2<20;ct2++) { - DisplayBitMap(); - } - } - for(ct2=0;ct2<150;ct2++) { - DisplayBitMap(); - } -} - - - -void turnon(int led) { - int pospin = ledMap[led][0]; - int negpin = ledMap[led][1]; - - pinMode (pospin, OUTPUT); - pinMode (negpin, OUTPUT); - digitalWrite (pospin, HIGH); - digitalWrite (negpin, LOW); -} - -void alloff() { - DDRD = B00000010; - DDRB = B00000000; -} - -void DisplayBitMap() -{ - // boolean run=true; - // byte frame = 0; - byte line = 0; - unsigned long data; - for(line = 0; line < 9; line++) { - data = screens[activescreen][line]; - for (byte led=0; led<14; ++led) { - if (data & (1<