Or "Yet Another Arduino Blinken Light Thing" :)
So we were chatting on the TASLUG (Tasmanian Linux Users Group) mailing list talking about a new hackerspace development and whatnot when one of the fellows said he hoped that it didn't become a club of Arduino fanboys. I said what's up with Arduino, it's awesome, and he said there's far too much boring blinkenlights and not enough actual cool stuff. It was a bit tongue in cheek, but regardless, my nerd pride was offended and I managed to interpret it as a challenge :) A month or so later and I had created TINY:
I'm pretty sure nerd etiquette precludes me from proclaiming success, but it did have an awesome time doing it. I am curious though, what do you think? ;)
/* Space Invaders Turns on an LED on for one second, then off for one second, repeatedly. This example code is in the public domain. */ // pin assignments int annodes0 = 2;int annodes1 = 3;int annodes2 = 4;int annodes3 = 5;int annodes4 = 6; //pin 7 is spare int cathodes0 = 8;int cathodes1 = 9;int cathodes2 = 10;int cathodes3 = 11;int cathodes4 = 12; int IndicatorLED = 13; int InputPot = A0; int C_ButtonPin = 18; //ie analog4, in use as a digital pin int C_SpeakerPin = 19; //ie analog5, in use as a digital pin int mycursor=2; // set initial position of the cursor //int difficulty = 1; // where 1 is easy and 3 is hard. // the setup routine runs once when you press reset: void setup() { // initialize the pins pinMode(annodes0, OUTPUT); pinMode(annodes1, OUTPUT); pinMode(annodes2, OUTPUT); pinMode(annodes3, OUTPUT); pinMode(annodes4, OUTPUT); pinMode(cathodes0, OUTPUT); pinMode(cathodes1, OUTPUT); pinMode(cathodes2, OUTPUT); pinMode(cathodes3, OUTPUT); pinMode(cathodes4, OUTPUT); pinMode(IndicatorLED, OUTPUT); pinMode(C_ButtonPin, INPUT); pinMode(InputPot, INPUT); Serial.begin(9600); } void loop() { //basicMultiplexing(); //SoundEffectGenViaPot(); //MakeASmiley(); //lightled(6,2000); delay(2000); //int buttonState = digitalRead(C_ButtonPin); if (buttonState == HIGH) { sound(7); } int difficulty = introSequence(); delay(200); SnotVaders(difficulty); delay(200); MakeASmiley(); delay(1000); } int introSequence(){ int difficultyX = SimpleVelocityLoop(); //int difficulty = map(difficultyX, 0, 1023, 3, 1); int difficulty = 0; if (difficultyX < 315) { difficulty = 3; } else if (difficultyX > 648 ) { difficulty = 1; } else { difficulty = 2; } Serial.print("difficultyX = "); Serial.println(difficultyX); Serial.print("difficulty = "); Serial.println(difficulty); delay(200); int mydelay=10; for (int i = 1; i <= 25; i++) { sound(1); lightled(i,mydelay); delay(mydelay); lightled(25-i,mydelay); delay(mydelay); } sound(7); delay(400); return difficulty; } void SnotVaders(int difficulty){ // (number of displaycycles per tick will be determined by gameroundtickspeed[v_round]. // the number of rounds is determined by the length of gameroundtickspeed[]. // we determine the ticks per round based on the difficulty :) int gameroundtickspeed[]= {0,0,0,0,0,0,0,0,0}; switch (difficulty){ case 1: // easy { int gameroundtickspeedX[]= {28,22,23,20,21,17,17,17,17}; for (int z = 0; z < 9; z++) { gameroundtickspeed[z]=gameroundtickspeedX[z];} break; } case 2: // medium { int gameroundtickspeedX[]= {20,20,20,19,18,14,14,14,11}; for (int z = 0; z < 9; z++) { gameroundtickspeed[z]=gameroundtickspeedX[z];} break; } case 3: // hard { int gameroundtickspeedX[]= {7,7,7,7,7,7,7,7,7}; for (int z = 0; z < 9; z++) { gameroundtickspeed[z]=gameroundtickspeedX[z];} break; } } int rounds = sizeof(gameroundtickspeed)/sizeof(int); int shipLocation=1; int notdead=1; int idealFlikerRate=24; int buttonStateToggle = 1; int baddieDetails[] = {0,0,0,0,0}; // play successive rounds, each terminating when either all baddies or the player dies for (int round = 1; round <= rounds; round++){ // output the round to the serial console for debug //Serial.print(" round = "); Serial.println(round); // baddies move closer to the player each round. // and they will do that faster depending on the round number. // if they hit the player, then the player dies, game over etc. // we define baddie starting location based on the round. // note that locations < 1 is "no location" and wont be displayed at all. // i was unable to have the switch populate baddieDetails[] directly, so that's why // we have this odd baddieDetails[z]=locations[z] arrangement. switch (round) { case 1: { int locations[]= {15, -1, -1, -1, -1}; for (int z = 0; z <= 5; z++) { baddieDetails[z]=locations[z];} } break; case 2: { int locations[]= {5, 25, -1, -1, -1}; for (int z = 0; z <= 5; z++) { baddieDetails[z]=locations[z];} } break; case 3: { int locations[]= {5, 14, 25, -1, -1}; for (int z = 0; z <= 5; z++) { baddieDetails[z]=locations[z];} } break; case 4: { int locations[]= {4, 15, 24, -1, -1}; for (int z = 0; z <= 5; z++) { baddieDetails[z]=locations[z];} } break; case 5: { int locations[]= {4, 10, 15, 20, 24}; for (int z = 0; z <= 5; z++) { baddieDetails[z]=locations[z];} } break; case 6: { int locations[]= {3, 9, 15, 19, 23}; for (int z = 0; z <= 5; z++) { baddieDetails[z]=locations[z];} } break; case 7: { int locations[]= {4, 8, 15, 18, 24}; for (int z = 0; z <= 5; z++) { baddieDetails[z]=locations[z];} } break; case 8: { int locations[]= {3, 8, 15, 18, 23}; for (int z = 0; z <= 5; z++) { baddieDetails[z]=locations[z];} } break; } int baddieDetailsarraylen = sizeof(baddieDetails)/sizeof(int); while(notdead) { // grunt noise sound(1); // update the display X times to do the flicker thing for (int displaycycle = 1; displaycycle <= gameroundtickspeed[round-1]; displaycycle++) { // we plot LEDs once per displaycycle. we do that repeatedly to give us a picture. // (number of displaycycles per tick will be determined by gameroundtickspeed[v_round] // each plotXX() function will illuminate and also extinguish it's own LEDs // we want this to minimise the number of simultaneously lit leds; ie flicker.) // first plot the baddies based on baddieDetails[] and check to see if they're all dead notdead = PlotBaddiesAndDetectAllDead(baddieDetails, baddieDetailsarraylen, idealFlikerRate); if (notdead == 0) { break; } //terminate processing the while loop // check to see if any of the baddies have hit the ground, if so terminate the game. int Zinstruction[] = {1, 6, 11, 16, 21}; for(int z = 0; z < baddieDetailsarraylen; z++) { for(int q = 0; q < 5; q++){ if (baddieDetails[z] == Zinstruction[q]){ // then a baddie has hit the ground, play wah wah wahhh and end sound(5); delay (500); software_Reset(); } } } // check to see if the player is shooting and if so, plot the laser and return the path it took. // the toggle stuff is to make sure they're not just holding the fire button int buttonState = digitalRead(C_ButtonPin); if (buttonState == HIGH) { if (buttonStateToggle) { PlotShootAndDetectHit(baddieDetails, baddieDetailsarraylen, shipLocation); buttonStateToggle = 0; } } else { buttonStateToggle = 1; } // move ship and return our current location shipLocation=PlotAndControlShipV2(idealFlikerRate); //ie; PlotAndControlShip(delay) // output debug stuff //Serial.print(" dc = "); Serial.print(displaycycle); //Serial.print(" rounds = "); Serial.print(rounds); //Serial.print(" round = "); Serial.println(round); //Serial.print(" shipLocation = "); Serial.println(shipLocation); } // end of displaycycle // make the baddies move closer to the player for(int z = 0; z < baddieDetailsarraylen; z++) { baddieDetails[z]--; Serial.print(" baddieDetails["); Serial.print(z); Serial.print("] "); Serial.println( baddieDetails[z]); } //} } // end of roundlengthcounter, ie end of round delay(500); sound(4); delay(1000); //delay between rounds notdead = 1; } // end of round, ie end of the game. sound(6); // play endgame music } void software_Reset() { // Restarts program from beginning but does not reset the peripherals and registers // taken from http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1246541553 asm volatile (" jmp 0"); } void MakeASmiley(){ int instructions[]= {9, 19, 2, 6, 11, 16, 22}; //int instructions[]= {10, 20, 14, 22, 21, 16, 11, 6, 1, 2}; //froggy int instructionsArraylen = sizeof(instructions)/sizeof(int); for (int i = 0; i < instructionsArraylen; i++){ lightled(instructions[i],350); } delay(200); for (int flickercounter = 0; flickercounter < 1008 ; flickercounter ++) { // iterate through the array, starting at element 0 for (int i = 0; i < instructionsArraylen; i++){ lightled(instructions[i],1); //delay(100); } } delay(1000); } int PlotBaddiesAndDetectAllDead(int baddieDetails[], int baddieDetailsarraylen, int mydelay){ int deadBaddieCounter=0; // note the last element in the array is arraylen -1. int lastarrayelement = baddieDetailsarraylen - 1; // iterate through the array, starting at element 1, not 0. and while we're at it // we'll calculate the score too int score = 0; for (int i = 0; i < baddieDetailsarraylen; i++){ // blink the leds according to the baddieDetails if (baddieDetails[i] < 0){ // this is a dead baddie, so don't plot it. instead count it. deadBaddieCounter++; if (deadBaddieCounter == baddieDetailsarraylen) { // all baddies are dead score = score + baddieDetails[i]; score = score * -1; score = 5 - score; Serial.print(" score = "); Serial.println( score); return 0; } } else { lightled(baddieDetails[i],mydelay); } } } void PlotShootAndDetectHit(int baddieDetails[], int baddieDetailsarraylen, int shipLocation){ //note this assumes that the ship won't leave the planet surface and that the //planet surface is defined explicityly as 1, 6, 11, 16, 21. if that changes //then this will look odd. int shootdelay = 12; // to start with, simply play the shoot noise sound(2); //shoot // then take the ship location, and for each one, calculate the laser trajectory // each led upon that trajectory is called laserLocation. when we have that laserLocation // also iterate through the baddieDetails array to see if that laserLocation coincides with // where a baddie is, if so, play the explode noise. switch(shipLocation){ // this will send the laser towards the baddies :) case 1: for(int laserLocation=2; laserLocation <=5; laserLocation++){ // plot the laser trajectory lightled(laserLocation,shootdelay); // plot the led(note singular) corresponding to the laserLocation for (int blc = 0; blc < baddieDetailsarraylen; blc ++){ if (laserLocation == baddieDetails[blc]) { // if the laser is where a baddie is sound(3); // they hit the target!! so play the explode noise baddieDetails[blc]=-1; // set that baddie to dead; ie don't display it } } } break; case 6: for(int laserLocation=7; laserLocation <=10; laserLocation++){ lightled(laserLocation,shootdelay); // plot the led(note singular) corresponding to the laserLocation for (int blc = 0; blc < baddieDetailsarraylen; blc ++){ if (laserLocation == baddieDetails[blc]) { // if the laser is where a baddie is sound(3); // they hit the target!! so play the explode noise baddieDetails[blc]=-1; // set that baddie to dead; ie don't display it } } } break; case 11: for(int laserLocation=12; laserLocation <=15; laserLocation++){ lightled(laserLocation,shootdelay); // plot the led(note singular) corresponding to the laserLocation for (int blc = 0; blc < baddieDetailsarraylen; blc ++){ if (laserLocation == baddieDetails[blc]) { // if the laser is where a baddie is sound(3); // they hit the target!! so play the explode noise baddieDetails[blc]=-1; // set that baddie to dead; ie don't display it } } } break; case 16: for(int laserLocation=17; laserLocation <=20; laserLocation++){ lightled(laserLocation,shootdelay); // plot the led(note singular) corresponding to the laserLocation for (int blc = 0; blc < baddieDetailsarraylen; blc ++){ if (laserLocation == baddieDetails[blc]) { // if the laser is where a baddie is sound(3); // they hit the target!! so play the explode noise baddieDetails[blc]=-1; // set that baddie to dead; ie don't display it } } } break; case 21: for(int laserLocation=22; laserLocation <=25; laserLocation++){ lightled(laserLocation,shootdelay); // plot the led(note singular) corresponding to the laserLocation for (int blc = 0; blc < baddieDetailsarraylen; blc ++){ if (laserLocation == baddieDetails[blc]) { // if the laser is where a baddie is sound(3); // they hit the target!! so play the explode noise baddieDetails[blc]=-1; // set that baddie to dead; ie don't display it } } } break; } } int PlotAndControlShipV2(int mydelay){ // planet surface int instruction[] = {1, 6, 11, 16, 21}; // mycursor is a globally declared variable which stores where in the *instruction array* the ship // is currently residing. it should not be confused with shipLocation which stores the LEDid of the // ship location. ie shipLocation = instruction[mycursor] int rawLocation = analogRead(InputPot); int location = map(rawLocation, 0, 1025, 0, 5); //Serial.print("rawLocation = "); Serial.print(rawLocation); Serial.print(" location = "); Serial.println(location); lightled(instruction[location],mydelay); return instruction[location]; } void sound(int soundeffect) { switch( soundeffect ) { case 1: {//grunt tone(C_SpeakerPin, 17, 250); } break; case 2: {//shoot for (int z = 0; z < 1; z++){ tone(C_SpeakerPin, 600, 80); delay(40); tone(C_SpeakerPin, 100, 40); delay(10); } } break; case 3: {//explode //basically random-ish noise descending in frequency int freqbase=480; // where to start for(int i=0; i < 15; i++){ // how many individual noises in the effect freqbase = freqbase - 20; // how much lower should each noise go? int frequency = random(freqbase-30,freqbase); //what exact freqency to plot int mydelay = random(30,150); // how long should each noise go for tone(C_SpeakerPin, frequency, mydelay); Serial.print("frequency = "); Serial.print(frequency); Serial.print(" mydelay = "); Serial.println(mydelay); } } break; case 4: {// end round tone(C_SpeakerPin, 300, 300);delay(150); tone(C_SpeakerPin, 600, 100);delay(300); tone(C_SpeakerPin, 300, 300);delay(150); tone(C_SpeakerPin, 600, 800);delay(300); } break; case 5: {//you loose for (int z = 0; z < 1; z++){ tone(C_SpeakerPin, 300, 80); delay(800); tone(C_SpeakerPin, 275, 80); delay(800); tone(C_SpeakerPin, 260, 80); delay(800); for (int i = 0; i < 30; i++) { tone(C_SpeakerPin, 245, 15); delay(15); tone(C_SpeakerPin, 255, 15); delay(15); } tone(C_SpeakerPin, 100, 40); delay(10); } } break; case 6: {//you win! // the song to play at the truimphant conclusion :) char *song = "20thCenFoxShort:d=16,o=5,b=140:b,8p,b,b,2b,p,c6,32p,b,32p,c6,32p,b,32p,c6,32p,b,8p,b,b,b,32p,b,32p,b,32p,b,32p,b,32p,b,32p,b,32p,g#,32p,a,32p,b,8p,b,b,2b,4p"; play_rtttl(song); } break; case 7: {// game start //basically random-ish noise ascending in frequency int freqbase=180; // where to start for(int i=0; i < 30; i++){ // how many individual noises in the effect freqbase = freqbase + 15; // how much lower should each noise go? int frequency = random(freqbase-30,freqbase); //what exact freqency to plot int mydelay = random(30,150); // how long should each noise go for tone(C_SpeakerPin, frequency, mydelay); Serial.print("frequency = "); Serial.print(frequency); Serial.print(" mydelay = "); Serial.println(mydelay); } tone(C_SpeakerPin, 100, 15); delay(250); for (int i = 0; i < 2; i++) { for (int i = 0; i < 4; i++) { tone(C_SpeakerPin, 690, 100); delay(20); tone(C_SpeakerPin, 640, 100); delay(20); } tone(C_SpeakerPin, 100, 15); delay(100); } } break; } } void lightled(int LEDid, int ondelay) { //Serial.print(" led = "); Serial.print(LEDid); Serial.print(" ondelay = "); Serial.println(ondelay); switch (LEDid) { case 0: //all off digitalWrite(cathodes0, LOW); digitalWrite(annodes0, LOW); digitalWrite(cathodes1, LOW); digitalWrite(annodes1, LOW); digitalWrite(cathodes2, LOW); digitalWrite(annodes2, LOW); digitalWrite(cathodes3, LOW); digitalWrite(annodes3, LOW); digitalWrite(cathodes4, LOW); digitalWrite(annodes4, LOW); break; case 1: //c0a0 digitalWrite(cathodes0, HIGH); digitalWrite(annodes0, HIGH); break; case 2: //c0a1 digitalWrite(cathodes0, HIGH); digitalWrite(annodes1, HIGH); break; case 3: //c0a2 digitalWrite(cathodes0, HIGH); digitalWrite(annodes2, HIGH); break; case 4: //c0a3 digitalWrite(cathodes0, HIGH); digitalWrite(annodes3, HIGH); break; case 5: //c0a4 digitalWrite(cathodes0, HIGH); digitalWrite(annodes4, HIGH); break; case 6: //c1a0 digitalWrite(cathodes1, HIGH); digitalWrite(annodes0, HIGH); break; case 7: //c1a1 digitalWrite(cathodes1, HIGH); digitalWrite(annodes1, HIGH); break; case 8: //c1a2 digitalWrite(cathodes1, HIGH); digitalWrite(annodes2, HIGH); break; case 9: //c1a3 digitalWrite(cathodes1, HIGH); digitalWrite(annodes3, HIGH); break; case 10: //c1a4 digitalWrite(cathodes1, HIGH); digitalWrite(annodes4, HIGH); break; case 11: //c2a0 digitalWrite(cathodes2, HIGH); digitalWrite(annodes0, HIGH); break; case 12: //c2a1 digitalWrite(cathodes2, HIGH); digitalWrite(annodes1, HIGH); break; case 13: //c2a2 digitalWrite(cathodes2, HIGH); digitalWrite(annodes2, HIGH); break; case 14: //c2a3 digitalWrite(cathodes2, HIGH); digitalWrite(annodes3, HIGH); break; case 15: //c2a4 digitalWrite(cathodes2, HIGH); digitalWrite(annodes4, HIGH); break; case 16: //c3a0 digitalWrite(cathodes3, HIGH); digitalWrite(annodes0, HIGH); break; case 17: //c3a1 digitalWrite(cathodes3, HIGH); digitalWrite(annodes1, HIGH); break; case 18: //c3a2 digitalWrite(cathodes3, HIGH); digitalWrite(annodes2, HIGH); break; case 19: //c3a3 digitalWrite(cathodes3, HIGH); digitalWrite(annodes3, HIGH); break; case 20: //c3a4 digitalWrite(cathodes3, HIGH); digitalWrite(annodes4, HIGH); break; case 21: //c4a0 digitalWrite(cathodes4, HIGH); digitalWrite(annodes0, HIGH); break; case 22: //c4a1 digitalWrite(cathodes4, HIGH); digitalWrite(annodes1, HIGH); break; case 23: //c4a2 digitalWrite(cathodes4, HIGH); digitalWrite(annodes2, HIGH); break; case 24: //c4a3 digitalWrite(cathodes4, HIGH); digitalWrite(annodes3, HIGH); break; case 25: //c4a3 digitalWrite(cathodes4, HIGH); digitalWrite(annodes4, HIGH); break; case 88: //do nothing. break; case 100: //all on digitalWrite(cathodes0, HIGH); digitalWrite(annodes0, HIGH); digitalWrite(cathodes1, HIGH); digitalWrite(annodes1, HIGH); digitalWrite(cathodes2, HIGH); digitalWrite(annodes2, HIGH); digitalWrite(cathodes3, HIGH); digitalWrite(annodes3, HIGH); digitalWrite(cathodes4, HIGH); digitalWrite(annodes4, HIGH); break; default: // if nothing else matches, do the default //Serial.print("ERROR LEDid = "); Serial.println(LEDid); alloff(); allon(); delay(1500); break; } //delay a sec before resuming delay(ondelay); alloff(); } void alloff(){ // turn everything off for contrast digitalWrite(cathodes0, LOW); digitalWrite(cathodes1, LOW); digitalWrite(cathodes2, LOW); digitalWrite(cathodes3, LOW); digitalWrite(cathodes4, LOW); digitalWrite(annodes0, LOW); digitalWrite(annodes1, LOW); digitalWrite(annodes2, LOW); digitalWrite(annodes3, LOW); digitalWrite(annodes4, LOW); digitalWrite(IndicatorLED, LOW); } void allon(){ // turn everything off for contrast digitalWrite(cathodes0, HIGH); digitalWrite(cathodes1, HIGH); digitalWrite(cathodes2, HIGH); digitalWrite(cathodes3, HIGH); digitalWrite(cathodes4, HIGH); digitalWrite(annodes0, HIGH); digitalWrite(annodes1, HIGH); digitalWrite(annodes2, HIGH); digitalWrite(annodes3, HIGH); digitalWrite(annodes4, HIGH); digitalWrite(IndicatorLED, HIGH); } void SoundEffectGenViaPot(){ //generate sounds using input pot int buttonState = digitalRead(C_ButtonPin); int frequencyX = analogRead(InputPot); int frequency = map(frequencyX, 0, 1023, 1, 6000); if (buttonState == HIGH) { //tone(C_SpeakerPin, frequency, 200); tone(C_SpeakerPin, frequency, 40); //delay(10); tone(C_SpeakerPin, frequency-200, 40); //delay(10); tone(C_SpeakerPin, frequency, 40); //delay(10); //tone(C_SpeakerPin, 100, 40); delay(5); } Serial.print("frequency = "); Serial.println(frequency); } void basicMultiplexing(){ // for our matrix 24 is a good delay, but more leds means more flicker. simple. int ondelayX = analogRead(InputPot); int ondelay = map(ondelayX, 0, 1023, 0, 100); for (int i = 1; i <= 25; i++){lightled(i,ondelay);} Serial.print("ondelay = "); Serial.println(ondelay); } int PlotAndControlShipVelocity(int mydelay){ // planet surface int instruction[] = {1, 6, 11, 16, 21}; // mycursor is a globally declared variable which stores where in the *instruction array* the ship // is currently residing. it should not be confused with shipLocation which stores the LEDid of the // ship location. ie shipLocation = instruction[mycursor] // note the last element in the array is arraylen -1 !!!! int arraylen = sizeof(instruction)/sizeof(int); int lastarrayelement = arraylen - 1; // determine the position of the pot and assign a velocity to it int velocityX= analogRead(InputPot); int velocity = map(velocityX, 0, 1023, -150, 150); // set the cursor to increment or decrement depending on the velocity, note the deadzone if (velocity > 15) { mycursor++;} if (velocity < -15) {mycursor--;} // what do we do when they reach the edge of the play area? to wrap or not to wrap? // wrap: // if (mycursor < 0) { mycursor = lastarrayelement; } if (mycursor > lastarrayelement) { mycursor = 0; } // not wrap: if (mycursor < 0) { mycursor = 0; } if (mycursor > lastarrayelement) { mycursor = lastarrayelement; } //Serial.print("mycursor = "); Serial.print(mycursor); Serial.print(" mydelay = "); Serial.print(mydelay); Serial.print(" velocity = "); Serial.print(velocity); // blink the leds according to the instructions lightled(instruction[mycursor],mydelay); //ie shipLocation = instruction[mycursor] return instruction[mycursor]; } int SimpleVelocityLoop(){ // define the instructions for the array and the delay for led illumination //int instruction[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,0,100,0,100}; //test //int instruction[] = {1, 6, 11, 16, 21, 22, 23, 24, 25, 20, 15, 10, 5, 4, 3, 2, 7, 12, 17, 18, 19, 14, 9, 8, 13, 7}; // spiral and exit int instruction[] = {1, 6, 11, 16, 21, 22, 23, 24, 25, 20, 15, 10, 5, 4, 3, 2}; // outside loop //int instruction[] = {1, 6, 7, 11, 16, 12, 21, 22, 17, 23, 24, 18, 25, 20, 19, 15, 10, 14, 5, 4, 9, 3, 2, 8}; // 2 square loop // and then simply iterate through the instruction array int i; int arraylen = sizeof(instruction)/sizeof(int); int mydelayX = 0; int buttonState = 0; while(buttonState != HIGH){ for (i = 0; i < arraylen; i = i + 1) { buttonState = digitalRead(C_ButtonPin); if (buttonState) { break; } // delay is used for setting both the ON and OFF durations mydelayX= analogRead(InputPot); int mydelay = map(mydelayX, 0, 1023, 4, 200); // blink the leds according to the instructions // sound(1); lightled(instruction[i],mydelay); // turn everything off and wait a sec (before re-reading the instructinos and starting again etc) alloff(); delay(mydelay/2); //Serial.print("mydelayX = "); Serial.print(mydelayX); } } return mydelayX; } void play_rtttl(char *p) { // this function based on the LCA 2012 leo stick tunes collaborative effort at https://gist.github.com/1800871 //char *song = "Muppets:d=4,o=5,b=250:c6,c6,a,b,8a,b,g,p,c6,c6,a,8b,8a,8p,g.,p,e,e,g,f,8e,f,8c6,8c,8d,e,8e,8e,8p,8e,g,2p,c6,c6,a,b,8a,b,g,p,c6,c6,a,8b,a,g.,p,e,e,g,f,8e,f,8c6,8c,8d,e,8e,d,8d,c"; //char *song = "Looney:d=4,o=5,b=140:32p,c6,8f6,8e6,8d6,8c6,a.,8c6,8f6,8e6,8d6,8d#6,e.6,8e6,8e6,8c6,8d6,8c6,8e6,8c6,8d6,8a,8c6,8g,8a#,8a,8f"; //char *song = "20thCenFox:d=16,o=5,b=140:b,8p,b,b,2b,p,c6,32p,b,32p,c6,32p,b,32p,c6,32p,b,8p,b,b,b,32p,b,32p,b,32p,b,32p,b,32p,b,32p,b,32p,g#,32p,a,32p,b,8p,b,b,2b,4p,8e,8g#,8b,1c#6,8f#,8a,8c#6,1e6,8a,8c#6,8e6,1e6,8b,8g#,8a,2b"; //char *song = "Canon:d=4,o=5,b=80:8d,8f#,8a,8d6,8c#,8e,8a,8c#6,8d,8f#,8b,8d6,8a,8c#,8f#,8a,8b,8d,8g,8b,8a,8d,8f#,8a,8b,8f#,8g,8b,8c#,8e,8a,8c#6,f#6,8f#,8a,e6,8e,8a,d6,8f#,8a,c#6,8c#,8e,b,8d,8g,a,8f#,8d,b,8d,8g,c#.6"; //char *song = "StarWars:d=4,o=5,b=45:32p,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#.6,32f#,32f#,32f#,8b.,8f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32c#6,8b.6,16f#.6,32e6,32d#6,32e6,8c#6"; //char *song = "Gadget:d=16,o=5,b=50:32d#,32f,32f#,32g#,a#,f#,a,f,g#,f#,32d#,32f,32f#,32g#,a#,d#6,4d6,32d#,32f,32f#,32g#,a#,f#,a,f,g#,f#,8d#"; //char *song = "Smurfs:d=32,o=5,b=200:4c#6,16p,4f#6,p,16c#6,p,8d#6,p,8b,p,4g#,16p,4c#6,p,16a#,p,8f#,p,8a#,p,4g#,4p,g#,p,a#,p,b,p,c6,p,4c#6,16p,4f#6,p,16c#6,p,8d#6,p,8b,p,4g#,16p,4c#6,p,16a#,p,8b,p,8f,p,4f#"; //char *song = "LeisureSuit:d=16,o=6,b=56:f.5,f#.5,g.5,g#5,32a#5,f5,g#.5,a#.5,32f5,g#5,32a#5,g#5,8c#.,a#5,32c#,a5,a#.5,c#.,32a5,a#5,32c#,d#,8e,c#.,f.,f.,f.,f.,f,32e,d#,8d,a#.5,e,32f,e,32f,c#,d#.,c#"; #define isdigit(n) (n >= '0' && n <= '9') #define NOTE_B0 31 #define NOTE_C1 33 #define NOTE_CS1 35 #define NOTE_D1 37 #define NOTE_DS1 39 #define NOTE_E1 41 #define NOTE_F1 44 #define NOTE_FS1 46 #define NOTE_G1 49 #define NOTE_GS1 52 #define NOTE_A1 55 #define NOTE_AS1 58 #define NOTE_B1 62 #define NOTE_C2 65 #define NOTE_CS2 69 #define NOTE_D2 73 #define NOTE_DS2 78 #define NOTE_E2 82 #define NOTE_F2 87 #define NOTE_FS2 93 #define NOTE_G2 98 #define NOTE_GS2 104 #define NOTE_A2 110 #define NOTE_AS2 117 #define NOTE_B2 123 #define NOTE_C3 131 #define NOTE_CS3 139 #define NOTE_D3 147 #define NOTE_DS3 156 #define NOTE_E3 165 #define NOTE_F3 175 #define NOTE_FS3 185 #define NOTE_G3 196 #define NOTE_GS3 208 #define NOTE_A3 220 #define NOTE_AS3 233 #define NOTE_B3 247 #define NOTE_C4 262 #define NOTE_CS4 277 #define NOTE_D4 294 #define NOTE_DS4 311 #define NOTE_E4 330 #define NOTE_F4 349 #define NOTE_FS4 370 #define NOTE_G4 392 #define NOTE_GS4 415 #define NOTE_A4 440 #define NOTE_AS4 466 #define NOTE_B4 494 #define NOTE_C5 523 #define NOTE_CS5 554 #define NOTE_D5 587 #define NOTE_DS5 622 #define NOTE_E5 659 #define NOTE_F5 698 #define NOTE_FS5 740 #define NOTE_G5 784 #define NOTE_GS5 831 #define NOTE_A5 880 #define NOTE_AS5 932 #define NOTE_B5 988 #define NOTE_C6 1047 #define NOTE_CS6 1109 #define NOTE_D6 1175 #define NOTE_DS6 1245 #define NOTE_E6 1319 #define NOTE_F6 1397 #define NOTE_FS6 1480 #define NOTE_G6 1568 #define NOTE_GS6 1661 #define NOTE_A6 1760 #define NOTE_AS6 1865 #define NOTE_B6 1976 #define NOTE_C7 2093 #define NOTE_CS7 2217 #define NOTE_D7 2349 #define NOTE_DS7 2489 #define NOTE_E7 2637 #define NOTE_F7 2794 #define NOTE_FS7 2960 #define NOTE_G7 3136 #define NOTE_GS7 3322 #define NOTE_A7 3520 #define NOTE_AS7 3729 #define NOTE_B7 3951 #define NOTE_C8 4186 #define NOTE_CS8 4435 #define NOTE_D8 4699 #define NOTE_DS8 4978 #define OCTAVE_OFFSET 0 int notes[] = { 0, NOTE_C4, NOTE_CS4, NOTE_D4, NOTE_DS4, NOTE_E4, NOTE_F4, NOTE_FS4, NOTE_G4, NOTE_GS4, NOTE_A4, NOTE_AS4, NOTE_B4, NOTE_C5, NOTE_CS5, NOTE_D5, NOTE_DS5, NOTE_E5, NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, NOTE_A5, NOTE_AS5, NOTE_B5, NOTE_C6, NOTE_CS6, NOTE_D6, NOTE_DS6, NOTE_E6, NOTE_F6, NOTE_FS6, NOTE_G6, NOTE_GS6, NOTE_A6, NOTE_AS6, NOTE_B6, NOTE_C7, NOTE_CS7, NOTE_D7, NOTE_DS7, NOTE_E7, NOTE_F7, NOTE_FS7, NOTE_G7, NOTE_GS7, NOTE_A7, NOTE_AS7, NOTE_B7 }; // Absolutely no error checking in here byte default_dur = 4; byte default_oct = 6; int bpm = 63; int num; long wholenote; long duration; byte note; byte scale; // format: d=N,o=N,b=NNN: // find the start (skip name, etc) while(*p != ':') p++; // ignore name p++; // skip ':' // get default duration if(*p == 'd'){ p++; p++; // skip "d=" num = 0; while(isdigit(*p)){ num = (num * 10) + (*p++ - '0'); } if(num > 0) default_dur = num; p++; // skip comma } // get default octave if(*p == 'o'){ p++; p++; // skip "o=" num = *p++ - '0'; if(num >= 3 && num <=7) default_oct = num; p++; // skip comma } // get BPM if(*p == 'b'){ p++; p++; // skip "b=" num = 0; while(isdigit(*p)){ num = (num * 10) + (*p++ - '0'); } bpm = num; p++; // skip colon } // BPM usually expresses the number of quarter notes per minute wholenote = (60 * 1000L / bpm) * 4; // this is the time for whole note (in milliseconds) // now begin note loop while(*p){ // first, get note duration, if available num = 0; while(isdigit(*p)){ num = (num * 10) + (*p++ - '0'); } if(num) duration = wholenote / num; else duration = wholenote / default_dur; // we will need to check if we are a dotted note after // now get the note note = 0; switch(*p) { case 'c': note = 1; break; case 'd': note = 3; break; case 'e': note = 5; break; case 'f': note = 6; break; case 'g': note = 8; break; case 'a': note = 10; break; case 'b': note = 12; break; case 'p': default: note = 0; } p++; // now, get optional '#' sharp if(*p == '#'){ note++; p++; } // now, get optional '.' dotted note if(*p == '.'){ duration += duration/2; p++; } // now, get scale if(isdigit(*p)){ scale = *p - '0'; p++; } else{ scale = default_oct; } scale += OCTAVE_OFFSET; if(*p == ',') p++; // skip comma for next note (or we may be at the end) // now play the note if(note){ digitalWrite(C_SpeakerPin, HIGH); int danFreq; float danDur; danFreq = notes[(scale - 4) * 12 + note]; danDur = 1000000 / danFreq; unsigned long start = millis(); while (millis() - start <= duration) { digitalWrite(C_SpeakerPin, HIGH); delayMicroseconds(danDur); digitalWrite(C_SpeakerPin, LOW); delayMicroseconds(danDur); } digitalWrite(C_SpeakerPin, LOW); } else{ delay(duration); } } }
10 comments:
Thanks for posting this, TINY is a great project and much more than Yet Another Arduino Blinken Light Thing. This will be my next Arduino project, I hope to have it done by the end of the year. The kids should think it is fun.
very nice! good job.
good job! very nice.
very nice! good job.
Mate, that is definitely the coolest blinkin' thing I have seen done with an Arduino. Well done!
Mate, that is definitely the coolest blinkin' thing I have seen done with an Arduino. Well done!
I think it's awesome. Challenge was offered, you accepted, and delivered. Greets from Adelaide Hills
That is so cool....I want an arduino...
So cool... :)
Thanks everyone for your appreciation and encouragement, it means alot :)
Post a Comment