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.
Diff: main.cpp
- 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;