//**************************************************************// // Name : Pong for Arduino / Charlieplexing // // Authors : Benjamin Sonntag http://benjamin.sonntag.fr/ // // : Aurélien Couderc // // 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 /* ---------------------------------------------------------------------------*/ /** The 2 screens we use for double-buffering */ uint16_t screens[][9] = { {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,olds1,olds2; int activescreen; /* ---------------------------------------------------------------------------*/ /* Arduino setup func */ void setup() { x = 3; y = 7; sh1y=3; sh2y=3; dx = 1; dy = 1; s1 = 0; s2 = 0; olds1 = 0; olds2 = 0; activescreen = 0; randomSeed(analogRead(0)); drawscores(); } /* ---------------------------------------------------------------------------*/ /* Arduino main loop */ void loop() { int ct1,ct2,randommove; // The Ball shall bounce on the walls : if (x==12 || x==1) { dx=-dx; // Collision detection if (x==1) { // check the first ship (left side) if (sh1y!=y && sh1y+1!=y) { olds1=s1; olds2=s2; s2++; drawscores(); } } else { // check the second ship (right side) if (sh2y!=y && sh2y+1!=y) { olds1=s1; olds2=s2; s1++; drawscores(); } } } 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 (sh1y0) { // the ball goes away from me, let's move randomly randommove=random(0,3); if (randommove==0) { sh1y--; } if (randommove==1) { sh1y++; } } else { if (sh1y>y && (random(0,12)<10 || x<3)) { sh1y--; } if (sh1yy) { sh1y++; } if (sh1y7) 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; // Display the bitmap some times for(ct1=0;ct1<20;ct1++) { DisplayBitMap(); } // loop :) } /* ---------------------------------------------------------------------------*/ /** Draw the scores in a lovely scrolling :) * Use the current active screen brutally... */ void drawscores() { int i,j,ps1,ps2,ct2; for(ps1=0;ps1<=9;ps1++) { // Clear the active screen for(ct2=0;ct2<9;ct2++) { screens[activescreen][ct2]=0; } screens[activescreen][4]+=((1<<6) + (1<<7)); // dash between the scores // Fill it with both scores : // Left score if (s1==olds1) { stackfigure(s1,0); } else { stackfigureanim(olds1,s1,0,ps1); } // Right (human) score if (s2==olds2) { stackfigure(s2,9); } else { stackfigureanim(olds2,s2,9,ps1); } // Draw it for a little time ... for(ct2=0;ct2<15;ct2++) { DisplayBitMap(); } } for(ct2=0;ct2<150;ct2++) { DisplayBitMap(); } for(ct2=0;ct2<9;ct2++) { screens[1-activescreen][ct2]=0; } if (s1==9 || s2==9) { for(ps1=0;ps1<3;ps1++) { activescreen=1-activescreen; for(ct2=0;ct2<30;ct2++) { DisplayBitMap(); } activescreen=1-activescreen; for(ct2=0;ct2<60;ct2++) { DisplayBitMap(); } } for(ct2=0;ct2<150;ct2++) { DisplayBitMap(); } olds1=0; olds2=0; s1=0; s2=0; drawscores(); } } /* ---------------------------------------------------------------------------*/ /** Stacks a figure over the current active buffer. * « Stacks » means that the buffer is not added, it's just added * (OR-ed) to the buffer. * number : the number to be displayed. * shift : the index of the column to shift the number to. */ void stackfigure(int number, int shift) { int ct; for(ct=0;ct<7;ct++) { screens[activescreen][ct+1]|=figures[number][ct]<=0 && ygrid>=0) { screens[activescreen][ygrid]|=figures[numdown][yfig]<