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:
1:24f46931d010
Parent:
0:69e5ee3b618d
Child:
2:15134f79b400
--- a/main.cpp	Sun Mar 17 20:13:05 2013 +0000
+++ b/main.cpp	Mon Mar 18 03:49:33 2013 +0000
@@ -4,8 +4,8 @@
 #include "crc16.h"
 
  
-PinDetect  sw2(P0_10); //switch2 debounced input
-PinDetect  sw3(P0_11); //switch3 debounced input
+PinDetect  sw2(P0_11); //switch2 debounced input
+PinDetect  sw3(P0_10); //switch3 debounced input
 TextLCD lcd(P1_15, P1_16, P1_19, P1_20, P1_21, P1_22); // rs, e, d4-d7 led pins:4,6,11-14
 DigitalOut LB(P1_31); //lcd backlight
 DigitalOut LP(P1_29); //lcd power
@@ -13,12 +13,22 @@
 DigitalOut led2(P0_23); //on-board led ds2
 Serial IR(P1_27,P1_26); //IR transmitter and receiver output and input control 
 PwmOut Square_Gen(P1_25);       //square wave generator for IR led
-bool btn1 = false;  //global variable for sw2, since the PinDetect interrupt cannot attach functions that have parameters
-bool btn2 = false;  //global variable for sw3, since the PinDetect interrupt cannot attach functions that have parameters
+Timeout stats;   //used for displaying text for limited periods of time
+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 paramaters
 char c[3];
 unsigned arr = 0;
 
+void minutes()
+{
+    mins ++;
+    timer.reset();
+}
+
 void callback() 
 {
     // Note: you need to actually read from the serial to clear the RX interrupt
@@ -56,25 +66,234 @@
 led2 = !led2;
 }*/
 
-void Btn1Pressed()
+void btn2Pressed()
 {
     led1 = !led1;
-    btn1 = true;
+    btn2 = true;
 }
 
-void Btn2Pressed()
+void btn3Pressed()
 {
     led2 = !led2;
-    btn2 = true;
+    btn3 = true;
     
 }
 
-void finish_disp()
+void finish_disp ()
 {
     done = true;
     return;
 }
 
+/*Error Routine.
+    Displays "ERROR" on LCD screen and flashes leds
+    when called for an indefinite period of time
+*/
+void error_custom ()
+{
+    lcd.cls();
+    lcd.printf("ERROR");
+    led1 = 0;
+    led2 = 1;
+    while(1)
+    {
+      led1 = !led1;
+      led2 = !led2;
+      wait(0.5);
+    } 
+}
+/*Alphanumeric selector
+    Used with char_sel function in order to select a number 0-9 or letters A-Z through user input.
+    Returns a char.
+*/
+char alpha_num_sel (bool number)
+{
+    char n0 = '0';
+    char n_tmp = '0';
+    unsigned incr = 0;   //used to increment characters between 0-9 or A-Z 
+    unsigned mod;
+    if (number)
+    {
+        lcd.cls();
+        lcd.printf("Pick\nNumber:%c",n_tmp);
+        n0 = '0';
+        n_tmp = n0;
+        mod = 10;
+    }
+    else
+    {
+        lcd.cls();
+        n0 = 'A';
+        n_tmp = n0;
+        lcd.printf("Pick\nLetter:%c",n_tmp);
+        mod = 26;
+    }
+    while(1)
+    {
+        while(!btn2 && !btn3)   //waits until button input received
+        {
+            wait(0.05);
+        }
+        if(btn3)
+        {
+            btn3 = false;
+            btn2 = false;       //if both butons pressed, it just selects the current character
+            return (n_tmp);
+        }
+        else if(btn2)
+        {
+            btn2 = false;
+            incr ++;
+            incr = incr % mod; //ensures that numbers stay within the 0-9 range
+            n_tmp = n0 + incr;    //increment current number selected
+            lcd.cls();
+            if(number)
+            {
+                lcd.printf("Pick\nNumber:%c",n_tmp);    //displays current number
+            }
+            else
+            {
+                lcd.printf("Pick\nLetter:%c",n_tmp);     //displays current letter
+            }
+        }
+        else
+        {
+            error_custom();
+        }
+    
+    }
+}
+/*Character Selection
+    Used with setup() function in order to pick a character A-Z and number 0-9
+    for use as part of user id and/or team. Passed a 0 if selecting team letter (A-Z),
+    otherwise will select player id letter
+*/
+char char_sel (bool player)
+{
+    if (player)
+    {
+        lcd.cls();
+        lcd.printf("A-Z? or\n0-9?");
+        while(!btn2 && !btn3)   //waits until button input received
+        {
+            wait(0.05);
+        }
+        if(btn2)    //if select button pressed, goes through numerical selection
+        {
+            btn2 = false;
+            btn3 = false;   //if both buttons pressed at the same time, it just does numerical selection
+            
+            return(alpha_num_sel(1));
+        }
+        else if(btn3)
+        {
+            btn3 = false;   //pressing the option button in this case is the same as selecting a team
+        }
+        else
+        {
+            error_custom(); //if you somehow make it here without pressing buttons, it will throw an error
+        }    
+    }
+return(alpha_num_sel(0)); //returns capital alpha character for id or team by calling selection function
+}
+        
+    
+/*Setup Routine.
+    Sets the user id for use in-game.
+    Function must be passed an array of characters of size 15
+    in order to work correctly.
+*/
+void setup (char* ID_array)
+{
+    unsigned size = 1;
+    
+    lcd.cls();
+    lcd.printf("ID Size?\n%u",size);
+    while(1)
+    {
+        while(!btn2 && !btn3)   //waits until button input received
+        {
+            wait(0.05);     //ensures buttons cannot be pressed extremely fast
+        }
+        if(btn2 && btn3)    //routine to set size of player id in bytes
+        {
+            btn2 = false;   //handling for simultaneous button pressing
+            btn3 = false;   
+            size++;
+            if (size > 12) 
+            {
+                size = 1;    //ensures size cannot be greater than 12 or less than 1
+            }
+            break;          //sets size to whatever current size is +1 and moves on
+        }
+        else if(btn2)   //increases size or loops back to 1, displays current size
+        {
+            btn2 = false;
+            size++;
+            if (size > 12) 
+            {
+                size = 1;   //ensures size cannot be greater than 12 or less than 1
+            }
+            lcd.cls();
+            lcd.printf("ID Size?\n%u",size);    //displays current size
+        }
+        else if(btn3)
+        {
+            btn3 = false;   //selects current size
+            break;
+        }
+        else
+        {
+            error_custom();    //error called if unexpected output
+        }
+    }
+        
+    for (unsigned j = 0; j < size; j ++)    //sets player id
+    {
+        ID_array[j] = char_sel(1);
+    }
+    for (unsigned j = size; j < 12; j ++)
+    {
+        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
+    }
+    if(btn3)
+    {
+        btn3 = false;
+        btn2 = false;   //you're on a team if you press both buttons
+        ID_array[12] = char_sel(0);   //sets team letter
+    }
+    else if (btn2)
+    {
+        btn2 = false;
+        ID_array[12] = '0';    //sets team to 'zero', indicating no team
+    }
+    else
+    {
+        error_custom(); //throws an error if you somehow get here)
+    }
+    lcd.cls();
+    lcd.printf("Your ID\n is:");
+    wait(1.5);
+    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
+        }
+    }
+    crc16_attach(ID_array,13);   //attaches crc bits to last two bits of 15 character array
+    wait(5);
+    return;
+}
+
 int main() 
 {
     IR.attach(&callback);   //attaches interrupt for serial buffer
@@ -89,53 +308,90 @@
     sw3.setSampleFrequency();
     sw2.setAssertValue(0);  //set buttons to be logic high when voltage is low.
     sw3.setAssertValue(0);
-    sw2.attach_asserted( &Btn1Pressed ); //attach button interrupts
-    sw3.attach_asserted( &Btn2Pressed );
+    sw2.attach_asserted( &btn2Pressed ); //attach button interrupts
+    sw3.attach_asserted( &btn3Pressed );
+    clock_tick.attach(&minutes, 60);  //ticker interrupts every 60 seconds to add 1 minute and reset timer
+    timer.reset();  //ensure timer starts at 0
+    timer.start();  //start reset timer
+    unsigned secs;
     
     led1 = 1;
-    char id = 'j';
-    Timeout stats;
-    //stats.attach(&finish_disp, 5);
-    //bool done = false;
-    unsigned time;
-    unsigned time_compare = 0;
-    Timer timer;
-    
-    timer.reset();  //ensure timer starts at 0
-    timer.start();  //start reset timer   
+    char id[15]; //id array, capable of storing user ids up to 12 bytes with 1 byte for team and 2 bytes for CRC.
+    lcd.cls();      //ensure lcd starts with clear screen
+    lcd.printf("Choose \nYour ID.");
+    while(btn2 == false && btn3 == false)
+    {
+        wait(0.2);      //wait to start setup until select button is pressed
+    }
+    btn2 = false;       //reset button values
+    btn3 = false;
+    setup(id);      //setup player id and team, passing function the id array
     while(1) 
         {
-            time = timer.read();
+            secs = timer.read();
             lcd.cls();
-            lcd.printf("%d", time);
+            lcd.printf("Mins:%u\nSecs:%u", mins,secs);
+            wait(1);
             //lcd.cls();
             //lcd.printf("43%c%c%c!",c[0],c[1],c[2]);
             //IR.printf("%c%c%c",id);
-            if (btn1 == true)
+            
+            if (btn3 == true)
+            {
+                btn3 = false;
+                lcd.cls();
+                if (crc16_match(id,2))
+                {   
+                    lcd.printf("true");
+                }
+                else
+                {
+                    lcd.printf("false");
+                }
+                wait(5);
+            }
+            
+            //crc16 matching test - works!
+            /*if (btn3 == true)
             {
-                btn1 = false;
+                btn3 = false;
+                lcd.cls();
+                if (crc16_match(id,2))
+                {   
+                    lcd.printf("true");
+                }
+                else
+                {
+                    lcd.printf("false");
+                }
+                wait(5);
+            }*/
+            
+            //statistics display test - works!
+            /*
+            if (btn2 == true)
+            {
+                btn2 = false;
                 done = false;
                 wait(0.05);
                 stats.attach(&finish_disp, 5);
+                lcd.cls();
+                lcd.printf("ID:%c%c%c%c", id[0],id[1],id[2],id[3]);
                 while(!done)
                 {
-                    time = timer.read();
-                    lcd.cls();
-                    lcd.printf("New:%d", time);
-                    if(btn1 == true)
+                    if(btn2 == true)
                     {
-                        btn1 = false;
+                        btn2 = false;
                         stats.detach();
                         lcd.cls();
                         break;
                     }
-                    wait(0.5);
+                    wait(0.2);
                 }
-            }
+            }*/
                     
             //IR.printf("%c",id);
             
-            wait(1);
             
         }
 }