Mbed based laser tag system using IR LEDs and receivers

Dependencies:   mbed fwdcrc16library PinDetect TextLCD

This project was the result of an embedded systems design course held in 2013.

Revision:
4:7294c20b1025
Parent:
3:752f5f63f783
Child:
5:6e6ab7e5074e
--- a/main.cpp	Mon Mar 18 07:36:18 2013 +0000
+++ b/main.cpp	Fri Mar 22 17:59:26 2013 +0000
@@ -18,28 +18,26 @@
 Timeout flash;  //used to flash leds and backlight when shooting or tagging
 Timer timer;    //used as seconds for reset timer       
 Ticker clock_tick;    //used with timer for minutes of reset timer
+
 unsigned mins = 0;   //global variable for minutes in game, since ticker interrupt cannot attach functions that have parameters
 bool btn2 = false;  //global variable for sw2, since the PinDetect interrupt cannot attach functions that have parameters
 bool btn3 = false;  //global variable for sw3, since the PinDetect interrupt cannot attach functions that have parameters
 bool done = false;   //global variable for timeout, since TimeOut interrupt cannot attach functions that have parameters
 bool taggable = false;  //global variable for whether serial received input will be used or not
+volatile bool tagged = false;     //global variable for whether tag is complete
 char id_rx[15];         //global variable for received ID. Required to use serial interrupt correctly
 unsigned id_pos = 0;    //global variable for recieved ID array location. Also required for serial interrupt.
 
+/*Minute Interrupt
+    Intended to be called every minute to increment the minute counter.
+    Also resets the seconds timer as it reaches 60 seconds (assuming it is called at timer.start();)
+*/
 void minutes()
 {
     mins ++;
     timer.reset();
 }
 
-void shot_check()
-{
-    id_pos = 0;     //resets current id
-    //sets 15th byte of array to NULL
-    id_rx[14] = NULL;   //if this byte is changed from NULL, it will signify that the player has been successfully tagged
-    LB = 0; //ensure backlight is back off if it was turned on earlier
-}
-
 /* Flashing interrupt
     Intended to be used with a timeout object to flash lights when shot or shooting
 */
@@ -50,6 +48,25 @@
     led2 = !led2;
 }
 
+/*Shot Check/Reset Interrupt
+    Intended to be called after a short period of time to start array over from the start
+    Should keep data from being received over an excessive amount of time and thus is one
+    method of ensuring player is actually tagged
+*/
+void shot_check()
+{
+    id_pos = 0;     //resets current id
+    //sets 15th byte of array to NULL
+    //id_rx[14] = NULL;   //if this byte is changed from NULL, it will signify that the player has been successfully tagged
+    //LB = 0; //ensure backlight is back off if it was turned on earlier
+}
+
+/*Serial Callback interrupt
+    Receives IR information using IR receiver
+    If taggable = false, received data is thrown away.
+    Otherwise, up to 15 characters are collected in a time period of 0.5 seconds
+    If less than 15 characters received in 0.5 seconds, function array returns to first bit
+*/
 void callback() 
 {
     // Note: you need to actually read from the serial buffer to clear the RX interrupt
@@ -60,28 +77,33 @@
     }
     
     id_rx[id_pos] = IR.getc();  //place received character into array
-    if (id_pos == 0)    //starts a timer for the time in which receiver must receive a full id
+    /*if (id_pos == 0)    //starts a timer for the time in which receiver must receive a full id
     {
         shot_time.attach(&shot_check, 0.5);
-    }
-    else if(id_pos >= 14)   
+    }*/
+    if(id_pos >= 14)   
     {
         id_pos = 0; //ensures no array overflows
         shot_time.detach(); //ensures no further action upon array until next time tagged
+        tagged = true;
+        return;
     }
-    led1 = !led1;   //flashes lights when IR is received
-    led2 = !led1;
-    LB = !LB;       //flashes LCD backlight when IR received
     id_pos ++;  //increment to next array position for id
     return;    
 }
 
+/*Button 2 Interrupt
+    Sets button variable to true for use in code when button is pressed
+*/
 void btn2Pressed()
 {
     led1 = !led1;
     btn2 = true;
 }
 
+/*Button 3 Interrupt
+    Sets button variable to true for use in code when button is pressed
+*/
 void btn3Pressed()
 {
     led2 = !led2;
@@ -223,6 +245,7 @@
     
     lcd.cls();
     lcd.printf("ID Size?\n%u",size);
+    
     while(1)
     {
         while(!btn2 && !btn3)   //waits until button input received
@@ -270,8 +293,10 @@
     {
         ID_array[j] = ' ';      //fill unused characters with spaces
     }
+    
     lcd.cls();
     lcd.printf("On team?\n Y or N");
+    
     while(!btn2 && !btn3)   //waits until button input received
     {
         wait(0.05);     //ensures buttons cannot be pressed extremely fast
@@ -291,16 +316,17 @@
     {
         error_custom(); //throws an error if you somehow get here)
     }
+    
     lcd.cls();
     lcd.printf("Your ID\n is:");
-    wait(1.5);
+    wait(1);
     lcd.cls();
     for(unsigned j = 0; j <= 12; j++)  //prints out player id and team
     {
         lcd.printf("%c",ID_array[j]);
         if (j == 7)
         {
-            lcd.printf("\n"); //puts in a new line if id is longer than eight characters
+            lcd.printf("\n"); //puts in a new line after eight characters
         }
     }
     crc16_attach(ID_array,13);   //attaches crc bits to last two bits of 15 character array
@@ -315,36 +341,48 @@
 */
 bool check_id(char* player_array)
 {
-    if (id_rx[12] == player_array[12] && id_rx[12] >= 'A' || id_rx[13] == player_array[13] && id_rx[14] == player_array[14])
+    if (id_rx[12] == player_array[12] && id_rx[12] >= 'A')
     {
         return false;   //if ids are on the same team or are the same person, they cannot be hit by each other/themselves
     }
-    
+    else if(id_rx[13] == player_array[13] && id_rx[14] == player_array[14])
+    {
+        return false;
+    }
     return (crc16_match(id_rx, 13));  //compares the crc tag in received id to a calculated one. Returns false if different.
 }
 
+/*Respawn Display
+    Displays appropriate information for who player was hit by while they are "respawning"
+    Returns nothing
+*/
 void respawn()
 {
     lcd.cls();
     lcd.printf("Hit by:");
-    wait(1.5);
+    wait(1);
     lcd.cls();
     for(unsigned j = 0; j <= 12; j++)  //prints out id and team of person who tagged player
     {
         lcd.printf("%c",id_rx[j]);
         if (j == 7)
         {
-            lcd.printf("\n"); //puts in a new line if id is longer than eight characters
+            lcd.printf("\n"); //puts in a new line after eight characters
         }
     }
-    wait(3.5);
+    wait(4);
 }
-
+/*Firing function
+  Sends ID information through IR
+  Parameters: player_id
+  player_id = 15 character array that contains player id and crc hash
+  returns nothing 
+*/
 void fire(char* player_id)
 {
-    for (unsigned i = 0; i < 15; i += 3)
+    for (unsigned i = 0; i < 15; i ++)
     {
-        IR.printf("%c%c%c%",player_id[i],player_id[i+1],player_id[i+2]);
+        IR.putc(player_id[i]);
     }
 }   
 
@@ -387,7 +425,7 @@
     stats.attach(&finish_disp, 5);
     while(!done)
     {
-        if(btn3 == true || id_rx[14])
+        if(btn3 == true || tagged)
         {
             stats.detach(); //exit if something interrupts stats
             lcd.cls();
@@ -408,11 +446,10 @@
 
 int main() 
 {
-    id_rx[14] = NULL;       //makes use of last letter of received id for a flag deciding if player is shot
-    IR.attach(&callback);   //attaches interrupt for serial buffer
-    IR.baud(1200);          //sets baud rate of serial output and input
     Square_Gen.period_us(26);       //produces a 38kHz square wave to ensure proper IR communication...
     Square_Gen.pulsewidth_us(13);   //...this signal is sent to one of the IR diode terminals through a transistor
+    IR.baud(1200);          //sets baud rate of serial output and input
+    IR.attach(&callback);   //attaches interrupt for serial buffer  
     LB = 1; //turn on lcd backlight
     LP = 1; //turn on lcd power
     sw2.mode(PullUp);   //set buttons to a default high voltage for logic low
@@ -440,33 +477,37 @@
     btn2 = false;       //reset button values
     btn3 = false;
     setup(id);      //setup player id and team, passing function the id array
-    lcd.cls();
+    /*lcd.cls();
     lcd.printf("Starting\nin 3 sec");
-    wait(3);
+    wait(3);*/
     taggable = true;
-    LB = 0; //turn off lcd screen and backlight to save power during game
+    LB = 0; //turn off lcd screen, backlight, and leds to save power during game
     LP = 0;
+    led1 = 0;
+    led2 = 0;
     while(1) 
     {
-        if(id_rx[14])
+        if(tagged)
         {
-            taggable = false;    //don't allow new tags while the current one is checked
             flash.attach(&flasher,0.5);
-            LB = 1; //turn on backlight and leds
+            tagged = false;
+            //LB = 1; //turn on backlight and leds for flash
             led1 = 1;
             led2 = 1;
             if (check_id(id))
             {
+                taggable = false;    //don't allow new tags if respawning
                 flash.detach(); //if tag is valid, no need to flash
                 tag_count ++;
                 LP = 1; //turn LCD power and backlight on 
                 LB = 1;
                 respawn();  //prints appropriate respawn info
-                LB = 0; //turn LCD backlight and power back off
-                LP = 0; 
+                taggable = true;
+                led2 = 0;
             }
-            id_rx[14] = NULL;   //ensure this if statement does not immediately reactivate
-            taggable = true;
+            LB = 0; //turn LCD backlight and power back off
+            LP = 0;
+            led1 = 0; 
         }
         if(btn3)    //fires IR led if btn3 is pressed
         {
@@ -479,8 +520,9 @@
             flash.attach(flasher,0.5); //flashes backlight and leds when firing
             fire(id);   //fires player id using IR diode
         }
-        if (btn2 == true)   //displays statistics if btn2 is pressed
+        if (btn2)   //displays statistics if btn2 is pressed
         {
+            flash.detach();
             btn2 = false;
             LP = 1; //turn on display
             LB = 1;