Showing posts with label arduino. Show all posts
Showing posts with label arduino. Show all posts

Thursday, August 15, 2019

Trackbot (part 3: arduino integration and control code)

So with the microbit sending HIGH to some jumpers, and an arduino setup to control the lego motors, time came to integrate them together.  I brought over four wires from the microbit; forward and reverse for each track.

My plan there was to just connect all four jumpers from the microbit to the analog input pins on the arduino.  This turned out to be trivially easy, in the code i just run analogread() for each pin and if the input is above a threshold, assume it's a signal and do something.

Connecting microbit to Arduino analog input pins.
We're then getting pretty close to having it working.  It took a few iterations in the arduino code before i settled on the following, one for each track:

const int pwmOutput = 255;  
const int moveThreshold = 125; // how much of a signal before we trigger  
// left  
if (analogRead(leftFord) > moveThreshold){  
   moveLeftFord(pwmOutput);  
} else if (analogRead(leftBack) > moveThreshold){  
   moveLeftBack(pwmOutput);  
} else stopLeft();  

This was probably the most time consuming element in the project.  I wanted the vehicle to only move if you were holding the button down, otherwise stop that motor.  I'd already tested and the microbit will happily accept multiple simultaneous commands, so we're all good.

So with the wires etc all bundled on top I drove around a bit and scared the cat :) job done, it's now just a matter of packaging it all up so that it's neat and tidy and kid proof.  I should also add some fun factor in, and with four more potential inputs on the controller i could add some sounds or lights or a gatling gun.. whatever is the most enjoyable.. ;)

Trackbot (part 2: remote control with microbit bluetooth)

Again there was no specific plan here, just worked it out as i went along, meanwhile holding true to these objectives:
  1. Ideally, don't spend any money (use what i have already)
  2. Be able to control forward and reverse for each track.
  3. In case of having to spend money, make any spend as reusable as possible.
  4. Make it fun to use!  Lights!  Buzzers!
A commercial RC control was a non-starter due to rule number 1.  That being said i did find a nice tutorial about how to integrate one with an Arduino.

Next, i did have the two BBC micro-bit microcontrollers, and i knew that they both did bluetooth.  So i had an idea i could build up one as a transmitter/controller and the other as the receiver.  It turns out getting them talking isn't hard (at all) but i didn't want to use block code, nor even that online compiler thing.

So then i did some reading and discovered there are heaps of choices when it comes to where you code your microbit, including the Arduino IDE.  I had a wow moment at that point :) and quickly dipped into the wonderful world of microbit with the arduino ide thanks to Adafruit.  That short tutorial series completely changed my plans, and i learned:
  1. With the right resources we can achieve amazing things!
  2. That i can easily code microbit in the familiar arduino IDE ecosystem.
  3. When doing so i don't need to sacrifice core microbit functionality (like bluetooth or the other sensors etc).
  4. I don't need two microbits at all, because Adafruit has a BRILLIANT iOS app, and i can control the microbit from there!
  5. wow!
So.. that was a bit if a whirlwind, but as a result i then had a microbit with some wires hanging off it, some code largely based off the example, and an app with which i could trigger the microbit, it was perfect for my needs.

Microbit plus jumpers and power cable (to battery terminal).
I was able to then use the remote control app and hit a button, and the microbit would send one of those pins high.  I randomly picked them, but tested each pin in turn until they all worked.  Also soldering to a microbit is annoying.



I know I'm glossing over things a bit, but seriously that tutorial was awesome, go have a look.  So in essence my remote control setup works as follows:
  1. I power up the L298N which provides 5v to the Arduino
  2. The microbit is powered from the 3.3v supply on the arduino
  3. The microbit is paired with my iPhone
  4. I open the app, connect to the microbit and navigate to the Control Pad
  5. Hit one of the 4 numbered buttons, and one of those jumpers goes high.
  6. ..celebrate.  It was almost too easy.
I do note that i lost PWM control here, these are simply on and off signals.  I can deal with that, and can still code in some soft start stuff if i want.
 
Next is then coding the arduino to do sensible things with these inputs..

Trackbot (part 1: assembing parts, hatching a plan)

I had some parts laying around and I figured i could probably turn all this into something fun for me to make, and fun for my boy to play with. 
  1. The tracks etc from the Lego Technic excavator (42006)
  2. A couple of Lego Technic motors and some cogs to gear them down a bit
  3. A few Lego power cables including a couple of the ones for lights (8870)
  4. An arduino Uno clone (Freetronics eleven)
  5. Two BBC microbit microcontrollers
  6. An L298N motor driver board (these things are neat!)
  7. A 6s NiMh battery pack (9.6v) with Tamiya RC connector
  8. A potentiometer, various jumper wires, a random DC motor etc 
  9. And Ben's oscilloscope which needs using before i have to give it back.

I didn't have a perfectly crafted plan, but it was something like this:
  1. Remember how to drive a DC motor using the L298N with PWM
  2. Work out how the wiring works for Lego motors and how to connect them to the L298N without cutting their cables (because they're expensive).
  3. Work out how to control an arduino remotely.
  4. Shove it all on the tracks and make an remote controlled .. thing.
After sorting out power to the Arduino (using the 5v output from the L298N), the first thing was to hook up the random dc motor to the driver board (tutorial elsewhere) and use the potentiometer to control the PWM input.  Next was to hook in the Lego motors, which required understanding how they were cabled:

Cut these *before* you find out how much they cost.
To connect the Lego motor to the L298N i created some cables as above by cutting the 8870 cables and soldering jumpers into c1 and c2 (you don't need GND or 9v).  The standard motors can now plug into the Lego end and c1 and c2 go to the screw terminals on the L298N. 

Quite nerdy spaghetti.

The code* worked ok, so I then moved on to the tracks themselves. I already had this layout from when I'd been mucking around with the tracks as a Lego project.  There's one engine per track, and for forward travel obviously they'll be rotating in opposite directions.  I just needed to install the battery somewhere and luckily it just fit right in there..
The tracks; one motor for each track and battery pack


And again from awhile ago, I'd gear the motors down so they can run at full speed and provide slow powerful motive force, all the torque etc:

Two stage reduction gears.
Finally i kinda just stuck it all together and it worked, but there was zero consideration given to the packaging, so I couldn't actually drive it anywhere, and there was no control beyond the potentiometer (driving both tracks, one way only).

So next was do work out how to do the remote control, and that was a bit more interesting..

Sunday, August 05, 2012

Interfacing Atari 2600 Joystick to Arduino

Cleaning up the study the other day i found an old joystick from an Atari 2600.  So like everything else, I tried to connect it to my Arduino :)

The Arduino "button" example uses pull-down resistors, but after awhile i realized that approach wasn't going to work. This joystick switches to ground, meaning that any voltage going to say the Fire button will "dissapear" when the button is pressed. Same for each of the directions too, because this is a "digital" joystick, they're all just buttons inside the joystick.

So the answer is to measure what's going *into* the joystick, not what's coming out. For each of the joystick pins we send 5v into the joystick, and monitor that voltage. If there's 5v going in, then nothing has happened. But if that suddenly drops to near nothing, then a button has been pressed.

Figure 1: Current limiting resistors.

/*
 Interfacing Atari Joystick to Arduino:
 
 Returns output of Atari 2600 9 pin joystick to Arduino serial console.
 
       +---------> Right
       | +-------> Left
       | | +-----> Down
       | | | +---> Up 
       | | | | 
   _____________
 5 \ x o o o o / 1
    \ x o x o / 
   9 `~~~~~~~' 6
        |   |
        |   +----> Button
        +--------> Ground
 
 pinout via http://www.epanorama.net/documents/joystick/ataristick.html
 
 The circuit:
 * 5v through 10k resistor to each of the 5 joystick output pins
 * Arduino ground to Joystick ground
 * 5 data wires from joystick inputs to the arduino pins in the format:
    5V -> 10K resistor > Data to Arduino > Joystick Input
    
 created 2012 by Julius Roberts http://hooliowobbits.blogspot.com.au/
 
 This example code is in the public domain.
 */

// constants won't change. They're used here to set pin numbers:
const int FireButtonPin = 2;     
const int JoystickUpPin = 3;
const int JoystickDownPin = 4;
const int JoystickLeftPin = 5;
const int JoystickRightPin = 6;

void setup() {
  // initialize the Joystick pins as inputs:
  pinMode(FireButtonPin, INPUT);     
  pinMode(JoystickUpPin, INPUT);
  pinMode(JoystickDownPin, INPUT);
  pinMode(JoystickLeftPin, INPUT);
  pinMode(JoystickRightPin, INPUT);

  Serial.begin(9600);
}

void loop(){
  // read the state of the pushbutton value.  Because we're using a
  // pullup resistor, the value for each of the variables will normally 
  // be 1, and 0 when pressed.  This is the opposite of normal 
  // programming logic where 1 = true.  So we invert the variable using
  //  the map function  
  int FireButtonState = digitalRead(FireButtonPin); 
  FireButtonState = map(FireButtonState,0,1,1,0); 
  int JoystickUpState = digitalRead(JoystickUpPin); 
  JoystickUpState = map(JoystickUpState,0,1,1,0);
  int JoystickDownState = digitalRead(JoystickDownPin); 
  JoystickDownState = map(JoystickDownState,0,1,1,0);
  int JoystickLeftState = digitalRead(JoystickLeftPin); 
  JoystickLeftState = map(JoystickLeftState,0,1,1,0);
  int JoystickRightState = digitalRead(JoystickRightPin);  
  JoystickRightState = map(JoystickRightState,0,1,1,0);

  // output the setting to the serial console
  Serial.print("Fire: "); Serial.print(FireButtonState);
  Serial.print(" Up: "); Serial.print(JoystickUpState);
  Serial.print(" Down: "); Serial.print(JoystickDownState);
  Serial.print(" Left: "); Serial.print(JoystickLeftState);
  Serial.print(" Right: "); Serial.println(JoystickRightState);
}

Friday, August 03, 2012

Managing many LEDs on Arduino

Arguably the most simple Arduino project of all is the "blink" sketch which comes pre-installed the Arduino software (examples > basics > blink).  Some Arduino boards even have a surface mount LED already connected to pin 13 so you can do this sketch without any additional hardware.

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.
 
  This example code is in the public domain.
 */
 
// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

And once you get that far, it's not much more difficult to blink multiple lights in some sequence, using a separate arduino pin for each LED you wish to light, and some logic defining which to blink when, or which delay etc.  The "problem" is that as you add more LEDs to such a project each LED requires a dedicated pin. 10 LEDs = 10 pins, 15 LEDs = 15 pins etc, so that approach reasonably scales up to about 16 pins, give or take.  After that you need a smarter way to address the LEDs.  One way is to buy a fancy LED array or the alternative is to make your own.  I chose the latter of course :)

The video below to shows how to wire a circuit in order to allow your Arduino to drive more LEDs than you have pins, and also how to use a technique called multiplexing to avoid some of the compromises in not actually having one pin per LED.  I use this method to wire the circuit board in TINY (TINY Is Not space invaYders) which features a 5x5 array of 25 LEDs using "only" 10 pins.


TINY (This Is Not space invaYders)

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);
      }
    }
}


Tuesday, July 31, 2012

Posting code to your blogger blog

http://oneqonea.blogspot.com.au/2012/04/how-do-i-add-syntax-highlighting-to-my.html

^^ worked for me, had it up and running in a couple of mins
/*
  This Is Not space invaYders
  This example code is in the public domain, etc, have fun :)
 */
 
// 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;
etc.. Cool eh? :) to make some code look all neat like that you just have to use HTML view within the blogger interface, and put it between the pre tags as follows:
The "brushes" allow you to define the type of code and therefore which syntax gets highlighted etc.  In this case I've used the cpp brush but there are heaps of others documented at the authors website here. 

In some cases when the pre method doesn't work (such as when it gets confused over the less than character <) you can instead escape your code with the following. Note also this code also features the argument to have your code auto-hidden; great for long posts: