#define FIRST_PIN 2 #define NPINS 16 #define MIN_SPEED 0.2 #define MAX_SPEED 1.0 #define NVISUALIZATIONS 10 #define NFUNCTIONS 3 int leds[16] = {15, 5, 6, 12, 14, 4, 7, 13, 0, 3, 7, 11, 1, 2, 9, 10}; int grid[4][4] = {{15, 14, 0, 1}, {5, 4, 3, 2}, {6, 7, 8, 9}, {12, 13, 11, 10}}; // Grid arrangement: // [0,0] [1,0] [2,0] [3,0] // [0,1] [1,1] [2,1] [3,1] // [0,2] [1,2] [2,2] [3,2] // [0,3] [1,3] [2,3] [3,3] int blues[3] = {14, 12, 3}; int greens[3] = {6, 4, 10}; int reds[4] = {5, 0, 13, 9}; int yellows[3] = {15, 1, 8}; int whites[3] = {7, 11, 2}; // pointers to the current and last visualizations void (*visualization)() = throb; void (*lastVisualization)() = throb; // array of visualizations void (*visualizations[NVISUALIZATIONS])() = {throb, blinkRandom, wave, waveDiag, waveIn, colorCycle, fireworks, snake, runway, inOut}; // An array of all the functions. int (*allFunctions[NFUNCTIONS])(float x) = {linear, sine, exponential}; // Each pin has a function associated with it. The function determines how the brightness // of the LED changes over time. int (*function[NPINS])(float x); // The x values for the function associated with each LED. The x value is the current position along // the x axis for the function. There are are 256 x values on the x axis. That is, the domain of the // function is [0-255]. float x[NPINS]; // dx describes (for each LED) how the x value changes over time. If dx=1, then x is increased by 1 // for each duty cycle. If dx = -1, it is decreased by 1. If dx=5, then the brightness of the LED will // change faster according to the function because we are moving along the function curve faster. float dx[NPINS]; // y is the current value of the function at x. If the function is 'linear' and x=128, then y=128. // If the function is 'sine' and x=10, then y=0x03. See the sineValues array below that defines // the sine function. int y[NPINS]; // For each LED we can specify whether the x value should "wrap" around when reaching the end. // There are 256 possible values for x [0-255]. If we reach 255 and dx=1, then we can wrap around // back to x=0 if wrapFunction=true. If false, then adding 1 to 255 keeps x=255. boolean wrapFunction[NPINS]; // Definition of sine function. Array lookup executes faster than actually computing the sine. unsigned char sineValues[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08, 0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13,0x15,0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23, 0x25,0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,0x38,0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c, 0x4f,0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,0x67,0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c, 0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae, 0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8, 0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,0xea,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5, 0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7, 0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc, 0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3, 0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83, 0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51, 0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b,0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27, 0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a, 0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00 }; void setup() { randomSeed(analogRead(5)); for(int i=0; i0 will be on. At each step we see if there are any LEDs that need // to be turned off for the remainder of the duty cycle. So if an LED has y=100, we will turn it off at // step 100. That LED will have been on for the first 100 steps of the duty cycle and off for the // remaining 156 steps. So it is dimmer. If an LED has y=255, then it will remain on during the whole // duty cycle and be at full brightness. An LED with a low value y=10 will be very dim because we turn // it off very early in the duty cycle. // This 256 step cycle is executed n times as specified by the input parameter n. void dutyCycle(int n) { for(int i=0;i= 8) && (pin <= 13)) { portBBits = portBBits & (~(1 << (pin-8))); } if ((pin >= 14) && (pin <= 19)) { portCBits = portCBits & (~(1 << (pin-14))); } } } // Use port manipulation to set the values on the LED pins. PORTD = portDBits | (PORTD & 0x03); PORTB = portBBits | (PORTB & 0xC0); PORTC = portCBits | (PORTC & 0xC0); // Perform one duty cycle of 256 steps. // Turn off each pin when it is supposed to be turned off. for(int d=0; d<255; d++){ for(int p=0;p= 8) && (pin <= 13)) { PORTB = PORTB & (~(1 << (pin-8))); } if ((pin >= 14) && (pin <= 19)) { PORTC = PORTC & (~(1 << (pin-14))); } } } } } } void stepXAll() { for(int p=0;p 255) { x[p] = x[p] - 256; } else if (x[p] < 0) { x[p] = x[p] + 256; } } else { if (x[p] > 255) { x[p] = 255; } else if (x[p] < 0) { x[p] = 0; } } } void computePinValueAll() { for(int p=0;p=0;yy--) { x[grid[xx][yy]] = 255; dutyCycle(5); } dutyCycle(10); } } void runwayLeft() { for(int i=0;i<5;i++) { int yy = random(0, 4); for(int xx=3;xx>=0;xx--) { x[grid[xx][yy]] = 255; dutyCycle(5); } dutyCycle(10); } } void runwayRight() { for(int i=0;i<5;i++) { int yy = random(0, 4); for(int xx=0;xx<4;xx++) { x[grid[xx][yy]] = 255; dutyCycle(5); } dutyCycle(10); } } void runwayDownRight() { for(int i=0;i<5;i++) { int xx, yy; switch(random(0, 3)) { case 0: xx = 0; yy = 1; break; case 1: xx = 0; yy = 0; break; case 2: xx = 1; yy = 0; break; } int count = 4-xx-yy; for(int l=0;l 3) || (newX < 0) || (newY > 3) || (newY < 0)) { newX = headX; newY = headY; if (random(0, 2) == 0) { if (random(0, 2) == 0) { newX = headX - 1; } else { newX = headX + 1; } } else { if (random(0, 2) == 0) { newY = headY - 1; } else { newY = headY + 1; } } } lastHeadX = headX; lastHeadY = headY; headX = newX; headY = newY; newX = lastHeadX; // force change newY = lastHeadY; x[grid[headX][headY]] = 255; } } void allUp() { if (lastVisualization == allUp) { return; } for(int p=0; p 0) { done = false; break; } } } } void allOn() { for(int p=0; p