#include /* for cheap Chinese 64 dots LED-Projector Board has unmarked chip in socket - pin layout fits to ATTiny 2313 an 4313 the LEDS are connected to 8 pcs 74HC595 --u-- RST 1 20 VCC NC (0) 2 19 (16) IN SCK NC (1) 3 18 (15) IN MISO XTAL 4 17 (14) IN MOSI XTAL 5 16 (13) IN OUT (4) 6 15 (12) IN OUT (5) 7 14 (11) IN OUT (6) 8 13 (10) IN NC (7) 9 12 (9) MIC GND 10 11 (8) IN ----- () = Arduino Pins RST = Reset - 10K to GND, 10uF to VCC XTAL = 16 MHz Crystal IN = switches MIC = Input from microphone amplifier (LM358) */ /* x XXXXXXX XX XXX XX XXXXXXXXXXX X XXXXXXX X X X X X XX XX */ #define LATCHPIN 5 #define DATAPIN 4 #define CLOCKPIN 6 byte ledsData[8]; byte currentled = 0; int stepcount = 0; // low level functions void clear() { for (int i=0; i < 8; i++) { // low is led on ledsData[i] = 255; } } void writebuffer(byte ledNr) { byte chipNr = ledNr / 8; byte pinNr = ledNr % 8; if(chipNr < 8) { bitWrite(ledsData[chipNr], pinNr, LOW); } } void writexy(byte x, byte y) { byte lednr = x*8 + y; writebuffer(lednr); } byte rowmask[8] = {5,3,1,0,2,4,6,7}; void pushout() { digitalWrite(LATCHPIN, LOW); for(int i = 8-1; i>=0; i--) { byte row = rowmask[i]; shiftOut(DATAPIN, CLOCKPIN, MSBFIRST, ledsData[row]); } digitalWrite(LATCHPIN, HIGH); } // space invader //byte invaderA0[11] = {112,24,125,182,188,60,188,182,125,24,112}; //byte invaderA1[11] = {14,24,189,118,60,60,60,118,189,24,14}; static byte invader_A0[8] = {152,92,182,95,95,182,92,152}; static byte invader_A1[8] = {88,188,22,63,63,22,188,88}; bool invader_read(int x, int y, bool invader_state) { if (invader_state) { return bitRead(invader_A0[x],y); } else { return bitRead(invader_A1[x],y); } } void invader_draw(int xposition, int yposition, bool invaderstate) { for (int x=0; x<8; x++) { int screenx = x+xposition; if (screenx >=0 && screenx < 8) { for (int y=0; y<8; y++) { int screeny = y+yposition; if (screeny >=0 && screeny < 8) { if ( invader_read(x,y,invaderstate) ) { writexy(screenx,screeny); } } } } } } byte invader_currentcol=1; bool invader_direction = true; int invader_start = -12; int invader_end = 8; int invader_position = invader_start; bool invader_state = true; int invader_statecount = 0; void invader_setup() { invader_state = true; stepcount = 0; invader_statecount = 0; } void invader_step() { invader_draw(0,0, invader_state); pushout(); invader_state = !invader_state; stepcount++; invader_statecount++; if (invader_statecount >=4) { invader_position++; if (invader_position >=invader_end) { invader_position = invader_start; } invader_statecount = 0; } delay(600); } // Game of life byte gol_last[8]; byte gol_next[8]; byte gol_last2[8]; byte gol_last3[8]; byte gol_last4[8]; long gol_stepcount; int gol_deadcount = 0; void gol_setup() { gol_deadcount = 0; for (int x=0; x<8; x++) { gol_last[x] = 0; for (int y=0; y<8; y++) { if (random(4)<1) { bitWrite(gol_last[x], y, HIGH); } } } } static byte gol_glider[8] = {4,5,6,0,0,0,0,0}; void gol_setup_glider() { gol_deadcount = 0; for (int i=0; i<8; i++) { gol_last[i] = gol_glider[i]; } } static byte gol_spaceship[8] = {12,28,26,14,4,0,0,0}; void gol_setup_spaceship() { gol_deadcount = 0; for (int i=0; i<8; i++) { gol_last[i] = gol_spaceship[i]; } } void setup() { pinMode(LATCHPIN, OUTPUT); pinMode(DATAPIN, OUTPUT); pinMode(CLOCKPIN, OUTPUT); gol_setup(); clear(); pushout(); } void gol_clearnext() { for (int i=0; i<8; i++) { gol_next[i] = 0; } } bool gol_getstate(int x, int y) { // warp around if (x<0) { x=7; } if (x>7) { x=0; } if (y<0) { y=7; } if (y>7) { y=0; } return bitRead(gol_last[x],y); } byte gol_countNeighbours(int x, int y) { byte count = 0; for (int xoff=-1; xoff <= 1; xoff++) { for (int yoff=-1; yoff <= 1; yoff++) { if ( !(xoff==0 && yoff==0) ) { if (gol_getstate(x+xoff, y+yoff) ) { count++; } } } } return count; } void gol_setnext(int x, int y) { bitWrite( gol_next[x], y, HIGH); } void gol_writeLEDS() { for(int x=0; x<8; x++) { for (int y=0; y<8; y++) { if (bitRead(gol_next[x],y)) { writexy(x, y); } } } } int gol_pixelcount; int gol_diffrences; int gol_diffrences2; int gol_diffrences3; int gol_diffrences4; void gol_step() { gol_clearnext(); gol_pixelcount = 0; for (int x=0; x<8; x++) { for (int y=0; y<8; y++) { bool myself = gol_getstate(x,y); byte neighbours = gol_countNeighbours(x,y); if ( neighbours==3) { gol_setnext(x,y); gol_pixelcount++; } if ( neighbours==2 && myself) { gol_setnext(x,y); gol_pixelcount++; } } } gol_writeLEDS(); pushout(); gol_diffrences = 0; gol_diffrences2 = 0; gol_diffrences3 = 0; gol_diffrences4 = 0; for (int i=0; i<8; i++) { if (gol_last4[i] != gol_next[i]) { gol_diffrences4++; } gol_last4[i] = gol_last3[i]; if (gol_last3[i] != gol_next[i]) { gol_diffrences3++; } gol_last3[i] = gol_last2[i]; if (gol_last2[i] != gol_next[i]) { gol_diffrences2++; } gol_last2[i] = gol_last[i]; if (gol_last[i] != gol_next[i]) { gol_diffrences++; } gol_last[i] = gol_next[i]; } if (gol_diffrences == 0 || gol_diffrences2==0 || gol_diffrences3 == 0 || gol_diffrences4 == 0 || gol_pixelcount == 0) { //went static gol_deadcount++; } gol_stepcount++; delay(200); } // pattern 1 int pattern_state = 0; bool pattern_direction = true; void pattern1_setup() { stepcount = 0; pattern_state = 0; pattern_direction = true; } void pattern1_step() { // x-line for(byte i=0; i<8; i++) { writexy(i,pattern_state); } // y line for(byte i=0; i<8; i++) { writexy(pattern_state,i); } if(pattern_direction) { pattern_state++; } else { pattern_state--; } if (pattern_state >=8) { pattern_state = 6; pattern_direction = false; } if (pattern_state <0) { pattern_state=1; pattern_direction = true; } pushout(); stepcount++; delay(120); } // pattern 2 void pattern2_setup() { stepcount = 0; pattern_state = 0; pattern_direction = true; } void pattern2_step() { for (int i=pattern_state; i < 8-pattern_state; i++) { writexy(pattern_state,i); writexy(i,pattern_state); writexy(7-pattern_state,i); writexy(i,7-pattern_state); } pattern_state++; if(pattern_state>=4) { pattern_state= 0; } pushout(); stepcount++; delay(800); } // main loop int mode = 0; #define NRMODES 6 void switchmode( ){ mode = random(NRMODES); switch(mode) { case 0: //game of life gol_stepcount = 0; gol_setup(); break; case 1: // gol glider; gol_stepcount = 0; gol_setup_glider(); break; case 2: // gol spaceship gol_stepcount = 0; gol_setup_spaceship(); break; case 3: // spaceinvader stepcount = 0; invader_setup(); break; case 4: stepcount = 0; pattern1_setup(); break; case 5: stepcount = 0; pattern2_setup(); break; } } void loop() { clear(); // check for end switch(mode) { case 0: // game of life case 1: case 2: if (gol_stepcount >150) { switchmode(); } if (gol_deadcount > 12) { switchmode(); } break; case 3: // spaceinvader if (stepcount > 50) { switchmode(); } break; case 4: if (stepcount > 100) { switchmode(); } break; case 5: if (stepcount > 40) { switchmode(); } break; } switch(mode) { case 0: // game of life case 1: case 2: gol_step(); break; case 3: // spaceinvader invader_step(); break; case 4: pattern1_step(); break; case 5: pattern2_step(); break; } }