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.

Committer:
Mike951
Date:
Fri Mar 22 17:59:26 2013 +0000
Revision:
4:7294c20b1025
Parent:
3:752f5f63f783
Child:
5:6e6ab7e5074e
Final revision;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Mike951 0:69e5ee3b618d 1 #include "mbed.h"
Mike951 0:69e5ee3b618d 2 #include "TextLCD.h"
Mike951 0:69e5ee3b618d 3 #include "PinDetect.h"
Mike951 0:69e5ee3b618d 4 #include "crc16.h"
Mike951 0:69e5ee3b618d 5
Mike951 0:69e5ee3b618d 6
Mike951 1:24f46931d010 7 PinDetect sw2(P0_11); //switch2 debounced input
Mike951 1:24f46931d010 8 PinDetect sw3(P0_10); //switch3 debounced input
Mike951 0:69e5ee3b618d 9 TextLCD lcd(P1_15, P1_16, P1_19, P1_20, P1_21, P1_22); // rs, e, d4-d7 led pins:4,6,11-14
Mike951 0:69e5ee3b618d 10 DigitalOut LB(P1_31); //lcd backlight
Mike951 0:69e5ee3b618d 11 DigitalOut LP(P1_29); //lcd power
Mike951 0:69e5ee3b618d 12 DigitalOut led1(P0_22); //on-board led ds1
Mike951 0:69e5ee3b618d 13 DigitalOut led2(P0_23); //on-board led ds2
Mike951 2:15134f79b400 14 Serial IR(P1_27,P1_26); //IR transmitter and receiver output and input control P1_27 controls IR diode, P1_26 controls IR reciever
Mike951 0:69e5ee3b618d 15 PwmOut Square_Gen(P1_25); //square wave generator for IR led
Mike951 1:24f46931d010 16 Timeout stats; //used for displaying text for limited periods of time
Mike951 2:15134f79b400 17 Timeout shot_time; //used to ensure shots take place in a brief period of time
Mike951 2:15134f79b400 18 Timeout flash; //used to flash leds and backlight when shooting or tagging
Mike951 2:15134f79b400 19 Timer timer; //used as seconds for reset timer
Mike951 1:24f46931d010 20 Ticker clock_tick; //used with timer for minutes of reset timer
Mike951 4:7294c20b1025 21
Mike951 1:24f46931d010 22 unsigned mins = 0; //global variable for minutes in game, since ticker interrupt cannot attach functions that have parameters
Mike951 1:24f46931d010 23 bool btn2 = false; //global variable for sw2, since the PinDetect interrupt cannot attach functions that have parameters
Mike951 1:24f46931d010 24 bool btn3 = false; //global variable for sw3, since the PinDetect interrupt cannot attach functions that have parameters
Mike951 2:15134f79b400 25 bool done = false; //global variable for timeout, since TimeOut interrupt cannot attach functions that have parameters
Mike951 2:15134f79b400 26 bool taggable = false; //global variable for whether serial received input will be used or not
Mike951 4:7294c20b1025 27 volatile bool tagged = false; //global variable for whether tag is complete
Mike951 2:15134f79b400 28 char id_rx[15]; //global variable for received ID. Required to use serial interrupt correctly
Mike951 2:15134f79b400 29 unsigned id_pos = 0; //global variable for recieved ID array location. Also required for serial interrupt.
Mike951 0:69e5ee3b618d 30
Mike951 4:7294c20b1025 31 /*Minute Interrupt
Mike951 4:7294c20b1025 32 Intended to be called every minute to increment the minute counter.
Mike951 4:7294c20b1025 33 Also resets the seconds timer as it reaches 60 seconds (assuming it is called at timer.start();)
Mike951 4:7294c20b1025 34 */
Mike951 1:24f46931d010 35 void minutes()
Mike951 1:24f46931d010 36 {
Mike951 1:24f46931d010 37 mins ++;
Mike951 1:24f46931d010 38 timer.reset();
Mike951 1:24f46931d010 39 }
Mike951 1:24f46931d010 40
Mike951 2:15134f79b400 41 /* Flashing interrupt
Mike951 2:15134f79b400 42 Intended to be used with a timeout object to flash lights when shot or shooting
Mike951 2:15134f79b400 43 */
Mike951 2:15134f79b400 44 void flasher()
Mike951 2:15134f79b400 45 {
Mike951 2:15134f79b400 46 LB = 0;
Mike951 2:15134f79b400 47 led1 = !led1;
Mike951 2:15134f79b400 48 led2 = !led2;
Mike951 2:15134f79b400 49 }
Mike951 2:15134f79b400 50
Mike951 4:7294c20b1025 51 /*Shot Check/Reset Interrupt
Mike951 4:7294c20b1025 52 Intended to be called after a short period of time to start array over from the start
Mike951 4:7294c20b1025 53 Should keep data from being received over an excessive amount of time and thus is one
Mike951 4:7294c20b1025 54 method of ensuring player is actually tagged
Mike951 4:7294c20b1025 55 */
Mike951 4:7294c20b1025 56 void shot_check()
Mike951 4:7294c20b1025 57 {
Mike951 4:7294c20b1025 58 id_pos = 0; //resets current id
Mike951 4:7294c20b1025 59 //sets 15th byte of array to NULL
Mike951 4:7294c20b1025 60 //id_rx[14] = NULL; //if this byte is changed from NULL, it will signify that the player has been successfully tagged
Mike951 4:7294c20b1025 61 //LB = 0; //ensure backlight is back off if it was turned on earlier
Mike951 4:7294c20b1025 62 }
Mike951 4:7294c20b1025 63
Mike951 4:7294c20b1025 64 /*Serial Callback interrupt
Mike951 4:7294c20b1025 65 Receives IR information using IR receiver
Mike951 4:7294c20b1025 66 If taggable = false, received data is thrown away.
Mike951 4:7294c20b1025 67 Otherwise, up to 15 characters are collected in a time period of 0.5 seconds
Mike951 4:7294c20b1025 68 If less than 15 characters received in 0.5 seconds, function array returns to first bit
Mike951 4:7294c20b1025 69 */
Mike951 0:69e5ee3b618d 70 void callback()
Mike951 0:69e5ee3b618d 71 {
Mike951 2:15134f79b400 72 // Note: you need to actually read from the serial buffer to clear the RX interrupt
Mike951 2:15134f79b400 73 if (!taggable)
Mike951 2:15134f79b400 74 {
Mike951 2:15134f79b400 75 IR.getc(); //ensures no extra buffering left over when player is not taggable
Mike951 2:15134f79b400 76 return;
Mike951 2:15134f79b400 77 }
Mike951 2:15134f79b400 78
Mike951 2:15134f79b400 79 id_rx[id_pos] = IR.getc(); //place received character into array
Mike951 4:7294c20b1025 80 /*if (id_pos == 0) //starts a timer for the time in which receiver must receive a full id
Mike951 0:69e5ee3b618d 81 {
Mike951 2:15134f79b400 82 shot_time.attach(&shot_check, 0.5);
Mike951 4:7294c20b1025 83 }*/
Mike951 4:7294c20b1025 84 if(id_pos >= 14)
Mike951 0:69e5ee3b618d 85 {
Mike951 2:15134f79b400 86 id_pos = 0; //ensures no array overflows
Mike951 2:15134f79b400 87 shot_time.detach(); //ensures no further action upon array until next time tagged
Mike951 4:7294c20b1025 88 tagged = true;
Mike951 4:7294c20b1025 89 return;
Mike951 0:69e5ee3b618d 90 }
Mike951 2:15134f79b400 91 id_pos ++; //increment to next array position for id
Mike951 2:15134f79b400 92 return;
Mike951 0:69e5ee3b618d 93 }
Mike951 0:69e5ee3b618d 94
Mike951 4:7294c20b1025 95 /*Button 2 Interrupt
Mike951 4:7294c20b1025 96 Sets button variable to true for use in code when button is pressed
Mike951 4:7294c20b1025 97 */
Mike951 1:24f46931d010 98 void btn2Pressed()
Mike951 0:69e5ee3b618d 99 {
Mike951 0:69e5ee3b618d 100 led1 = !led1;
Mike951 1:24f46931d010 101 btn2 = true;
Mike951 0:69e5ee3b618d 102 }
Mike951 0:69e5ee3b618d 103
Mike951 4:7294c20b1025 104 /*Button 3 Interrupt
Mike951 4:7294c20b1025 105 Sets button variable to true for use in code when button is pressed
Mike951 4:7294c20b1025 106 */
Mike951 1:24f46931d010 107 void btn3Pressed()
Mike951 0:69e5ee3b618d 108 {
Mike951 0:69e5ee3b618d 109 led2 = !led2;
Mike951 1:24f46931d010 110 btn3 = true;
Mike951 0:69e5ee3b618d 111
Mike951 0:69e5ee3b618d 112 }
Mike951 0:69e5ee3b618d 113
Mike951 1:24f46931d010 114 void finish_disp ()
Mike951 0:69e5ee3b618d 115 {
Mike951 0:69e5ee3b618d 116 done = true;
Mike951 0:69e5ee3b618d 117 return;
Mike951 0:69e5ee3b618d 118 }
Mike951 0:69e5ee3b618d 119
Mike951 1:24f46931d010 120 /*Error Routine.
Mike951 1:24f46931d010 121 Displays "ERROR" on LCD screen and flashes leds
Mike951 1:24f46931d010 122 when called for an indefinite period of time
Mike951 1:24f46931d010 123 */
Mike951 1:24f46931d010 124 void error_custom ()
Mike951 1:24f46931d010 125 {
Mike951 1:24f46931d010 126 lcd.cls();
Mike951 1:24f46931d010 127 lcd.printf("ERROR");
Mike951 1:24f46931d010 128 led1 = 0;
Mike951 1:24f46931d010 129 led2 = 1;
Mike951 1:24f46931d010 130 while(1)
Mike951 1:24f46931d010 131 {
Mike951 1:24f46931d010 132 led1 = !led1;
Mike951 1:24f46931d010 133 led2 = !led2;
Mike951 1:24f46931d010 134 wait(0.5);
Mike951 1:24f46931d010 135 }
Mike951 1:24f46931d010 136 }
Mike951 1:24f46931d010 137 /*Alphanumeric selector
Mike951 1:24f46931d010 138 Used with char_sel function in order to select a number 0-9 or letters A-Z through user input.
Mike951 1:24f46931d010 139 Returns a char.
Mike951 1:24f46931d010 140 */
Mike951 1:24f46931d010 141 char alpha_num_sel (bool number)
Mike951 1:24f46931d010 142 {
Mike951 1:24f46931d010 143 char n0 = '0';
Mike951 1:24f46931d010 144 char n_tmp = '0';
Mike951 1:24f46931d010 145 unsigned incr = 0; //used to increment characters between 0-9 or A-Z
Mike951 1:24f46931d010 146 unsigned mod;
Mike951 1:24f46931d010 147 if (number)
Mike951 1:24f46931d010 148 {
Mike951 1:24f46931d010 149 lcd.cls();
Mike951 1:24f46931d010 150 lcd.printf("Pick\nNumber:%c",n_tmp);
Mike951 1:24f46931d010 151 n0 = '0';
Mike951 1:24f46931d010 152 n_tmp = n0;
Mike951 2:15134f79b400 153 mod = 11; //modulus for character range
Mike951 1:24f46931d010 154 }
Mike951 1:24f46931d010 155 else
Mike951 1:24f46931d010 156 {
Mike951 1:24f46931d010 157 lcd.cls();
Mike951 1:24f46931d010 158 n0 = 'A';
Mike951 1:24f46931d010 159 n_tmp = n0;
Mike951 1:24f46931d010 160 lcd.printf("Pick\nLetter:%c",n_tmp);
Mike951 1:24f46931d010 161 mod = 26;
Mike951 1:24f46931d010 162 }
Mike951 1:24f46931d010 163 while(1)
Mike951 1:24f46931d010 164 {
Mike951 1:24f46931d010 165 while(!btn2 && !btn3) //waits until button input received
Mike951 1:24f46931d010 166 {
Mike951 1:24f46931d010 167 wait(0.05);
Mike951 1:24f46931d010 168 }
Mike951 1:24f46931d010 169 if(btn3)
Mike951 1:24f46931d010 170 {
Mike951 1:24f46931d010 171 btn3 = false;
Mike951 1:24f46931d010 172 btn2 = false; //if both butons pressed, it just selects the current character
Mike951 1:24f46931d010 173 return (n_tmp);
Mike951 1:24f46931d010 174 }
Mike951 1:24f46931d010 175 else if(btn2)
Mike951 1:24f46931d010 176 {
Mike951 1:24f46931d010 177 btn2 = false;
Mike951 1:24f46931d010 178 incr ++;
Mike951 2:15134f79b400 179 incr = incr % mod; //ensures that numbers stay within the 0-9/A-Z range
Mike951 2:15134f79b400 180 n_tmp = n0 + incr; //increment current character selected
Mike951 2:15134f79b400 181 if (incr == 10 && number) //feature addition to allow for space entry
Mike951 2:15134f79b400 182 {
Mike951 2:15134f79b400 183 n_tmp = ' ';
Mike951 2:15134f79b400 184 }
Mike951 1:24f46931d010 185 lcd.cls();
Mike951 1:24f46931d010 186 if(number)
Mike951 1:24f46931d010 187 {
Mike951 1:24f46931d010 188 lcd.printf("Pick\nNumber:%c",n_tmp); //displays current number
Mike951 1:24f46931d010 189 }
Mike951 1:24f46931d010 190 else
Mike951 1:24f46931d010 191 {
Mike951 1:24f46931d010 192 lcd.printf("Pick\nLetter:%c",n_tmp); //displays current letter
Mike951 1:24f46931d010 193 }
Mike951 1:24f46931d010 194 }
Mike951 1:24f46931d010 195 else
Mike951 1:24f46931d010 196 {
Mike951 1:24f46931d010 197 error_custom();
Mike951 1:24f46931d010 198 }
Mike951 1:24f46931d010 199
Mike951 1:24f46931d010 200 }
Mike951 1:24f46931d010 201 }
Mike951 1:24f46931d010 202 /*Character Selection
Mike951 1:24f46931d010 203 Used with setup() function in order to pick a character A-Z and number 0-9
Mike951 1:24f46931d010 204 for use as part of user id and/or team. Passed a 0 if selecting team letter (A-Z),
Mike951 1:24f46931d010 205 otherwise will select player id letter
Mike951 1:24f46931d010 206 */
Mike951 1:24f46931d010 207 char char_sel (bool player)
Mike951 1:24f46931d010 208 {
Mike951 1:24f46931d010 209 if (player)
Mike951 1:24f46931d010 210 {
Mike951 1:24f46931d010 211 lcd.cls();
Mike951 1:24f46931d010 212 lcd.printf("A-Z? or\n0-9?");
Mike951 1:24f46931d010 213 while(!btn2 && !btn3) //waits until button input received
Mike951 1:24f46931d010 214 {
Mike951 1:24f46931d010 215 wait(0.05);
Mike951 1:24f46931d010 216 }
Mike951 1:24f46931d010 217 if(btn2) //if select button pressed, goes through numerical selection
Mike951 1:24f46931d010 218 {
Mike951 1:24f46931d010 219 btn2 = false;
Mike951 1:24f46931d010 220 btn3 = false; //if both buttons pressed at the same time, it just does numerical selection
Mike951 1:24f46931d010 221
Mike951 1:24f46931d010 222 return(alpha_num_sel(1));
Mike951 1:24f46931d010 223 }
Mike951 1:24f46931d010 224 else if(btn3)
Mike951 1:24f46931d010 225 {
Mike951 1:24f46931d010 226 btn3 = false; //pressing the option button in this case is the same as selecting a team
Mike951 1:24f46931d010 227 }
Mike951 1:24f46931d010 228 else
Mike951 1:24f46931d010 229 {
Mike951 1:24f46931d010 230 error_custom(); //if you somehow make it here without pressing buttons, it will throw an error
Mike951 1:24f46931d010 231 }
Mike951 1:24f46931d010 232 }
Mike951 1:24f46931d010 233 return(alpha_num_sel(0)); //returns capital alpha character for id or team by calling selection function
Mike951 1:24f46931d010 234 }
Mike951 1:24f46931d010 235
Mike951 1:24f46931d010 236
Mike951 1:24f46931d010 237 /*Setup Routine.
Mike951 1:24f46931d010 238 Sets the user id for use in-game.
Mike951 1:24f46931d010 239 Function must be passed an array of characters of size 15
Mike951 1:24f46931d010 240 in order to work correctly.
Mike951 1:24f46931d010 241 */
Mike951 1:24f46931d010 242 void setup (char* ID_array)
Mike951 1:24f46931d010 243 {
Mike951 1:24f46931d010 244 unsigned size = 1;
Mike951 1:24f46931d010 245
Mike951 1:24f46931d010 246 lcd.cls();
Mike951 1:24f46931d010 247 lcd.printf("ID Size?\n%u",size);
Mike951 4:7294c20b1025 248
Mike951 1:24f46931d010 249 while(1)
Mike951 1:24f46931d010 250 {
Mike951 1:24f46931d010 251 while(!btn2 && !btn3) //waits until button input received
Mike951 1:24f46931d010 252 {
Mike951 1:24f46931d010 253 wait(0.05); //ensures buttons cannot be pressed extremely fast
Mike951 1:24f46931d010 254 }
Mike951 1:24f46931d010 255 if(btn2 && btn3) //routine to set size of player id in bytes
Mike951 1:24f46931d010 256 {
Mike951 1:24f46931d010 257 btn2 = false; //handling for simultaneous button pressing
Mike951 1:24f46931d010 258 btn3 = false;
Mike951 1:24f46931d010 259 size++;
Mike951 1:24f46931d010 260 if (size > 12)
Mike951 1:24f46931d010 261 {
Mike951 1:24f46931d010 262 size = 1; //ensures size cannot be greater than 12 or less than 1
Mike951 1:24f46931d010 263 }
Mike951 1:24f46931d010 264 break; //sets size to whatever current size is +1 and moves on
Mike951 1:24f46931d010 265 }
Mike951 1:24f46931d010 266 else if(btn2) //increases size or loops back to 1, displays current size
Mike951 1:24f46931d010 267 {
Mike951 1:24f46931d010 268 btn2 = false;
Mike951 1:24f46931d010 269 size++;
Mike951 1:24f46931d010 270 if (size > 12)
Mike951 1:24f46931d010 271 {
Mike951 1:24f46931d010 272 size = 1; //ensures size cannot be greater than 12 or less than 1
Mike951 1:24f46931d010 273 }
Mike951 1:24f46931d010 274 lcd.cls();
Mike951 1:24f46931d010 275 lcd.printf("ID Size?\n%u",size); //displays current size
Mike951 1:24f46931d010 276 }
Mike951 1:24f46931d010 277 else if(btn3)
Mike951 1:24f46931d010 278 {
Mike951 1:24f46931d010 279 btn3 = false; //selects current size
Mike951 1:24f46931d010 280 break;
Mike951 1:24f46931d010 281 }
Mike951 1:24f46931d010 282 else
Mike951 1:24f46931d010 283 {
Mike951 1:24f46931d010 284 error_custom(); //error called if unexpected output
Mike951 1:24f46931d010 285 }
Mike951 1:24f46931d010 286 }
Mike951 1:24f46931d010 287
Mike951 1:24f46931d010 288 for (unsigned j = 0; j < size; j ++) //sets player id
Mike951 1:24f46931d010 289 {
Mike951 1:24f46931d010 290 ID_array[j] = char_sel(1);
Mike951 1:24f46931d010 291 }
Mike951 1:24f46931d010 292 for (unsigned j = size; j < 12; j ++)
Mike951 1:24f46931d010 293 {
Mike951 1:24f46931d010 294 ID_array[j] = ' '; //fill unused characters with spaces
Mike951 1:24f46931d010 295 }
Mike951 4:7294c20b1025 296
Mike951 1:24f46931d010 297 lcd.cls();
Mike951 1:24f46931d010 298 lcd.printf("On team?\n Y or N");
Mike951 4:7294c20b1025 299
Mike951 1:24f46931d010 300 while(!btn2 && !btn3) //waits until button input received
Mike951 1:24f46931d010 301 {
Mike951 1:24f46931d010 302 wait(0.05); //ensures buttons cannot be pressed extremely fast
Mike951 1:24f46931d010 303 }
Mike951 1:24f46931d010 304 if(btn3)
Mike951 1:24f46931d010 305 {
Mike951 1:24f46931d010 306 btn3 = false;
Mike951 1:24f46931d010 307 btn2 = false; //you're on a team if you press both buttons
Mike951 1:24f46931d010 308 ID_array[12] = char_sel(0); //sets team letter
Mike951 1:24f46931d010 309 }
Mike951 1:24f46931d010 310 else if (btn2)
Mike951 1:24f46931d010 311 {
Mike951 1:24f46931d010 312 btn2 = false;
Mike951 1:24f46931d010 313 ID_array[12] = '0'; //sets team to 'zero', indicating no team
Mike951 1:24f46931d010 314 }
Mike951 1:24f46931d010 315 else
Mike951 1:24f46931d010 316 {
Mike951 1:24f46931d010 317 error_custom(); //throws an error if you somehow get here)
Mike951 1:24f46931d010 318 }
Mike951 4:7294c20b1025 319
Mike951 1:24f46931d010 320 lcd.cls();
Mike951 1:24f46931d010 321 lcd.printf("Your ID\n is:");
Mike951 4:7294c20b1025 322 wait(1);
Mike951 1:24f46931d010 323 lcd.cls();
Mike951 1:24f46931d010 324 for(unsigned j = 0; j <= 12; j++) //prints out player id and team
Mike951 1:24f46931d010 325 {
Mike951 1:24f46931d010 326 lcd.printf("%c",ID_array[j]);
Mike951 1:24f46931d010 327 if (j == 7)
Mike951 1:24f46931d010 328 {
Mike951 4:7294c20b1025 329 lcd.printf("\n"); //puts in a new line after eight characters
Mike951 1:24f46931d010 330 }
Mike951 1:24f46931d010 331 }
Mike951 1:24f46931d010 332 crc16_attach(ID_array,13); //attaches crc bits to last two bits of 15 character array
Mike951 3:752f5f63f783 333 wait(3);
Mike951 1:24f46931d010 334 return;
Mike951 1:24f46931d010 335 }
Mike951 1:24f46931d010 336
Mike951 2:15134f79b400 337 /*ID Checking Routine
Mike951 2:15134f79b400 338 Checks received IDs to see if it is a valid shot
Mike951 2:15134f79b400 339 player_array is the 15 character id array of the player that constains a 16-bit crc in the last two bytes
Mike951 2:15134f79b400 340 Returns a boolean true if shot is valid, otherwise false
Mike951 2:15134f79b400 341 */
Mike951 2:15134f79b400 342 bool check_id(char* player_array)
Mike951 2:15134f79b400 343 {
Mike951 4:7294c20b1025 344 if (id_rx[12] == player_array[12] && id_rx[12] >= 'A')
Mike951 2:15134f79b400 345 {
Mike951 2:15134f79b400 346 return false; //if ids are on the same team or are the same person, they cannot be hit by each other/themselves
Mike951 2:15134f79b400 347 }
Mike951 4:7294c20b1025 348 else if(id_rx[13] == player_array[13] && id_rx[14] == player_array[14])
Mike951 4:7294c20b1025 349 {
Mike951 4:7294c20b1025 350 return false;
Mike951 4:7294c20b1025 351 }
Mike951 2:15134f79b400 352 return (crc16_match(id_rx, 13)); //compares the crc tag in received id to a calculated one. Returns false if different.
Mike951 2:15134f79b400 353 }
Mike951 2:15134f79b400 354
Mike951 4:7294c20b1025 355 /*Respawn Display
Mike951 4:7294c20b1025 356 Displays appropriate information for who player was hit by while they are "respawning"
Mike951 4:7294c20b1025 357 Returns nothing
Mike951 4:7294c20b1025 358 */
Mike951 2:15134f79b400 359 void respawn()
Mike951 2:15134f79b400 360 {
Mike951 2:15134f79b400 361 lcd.cls();
Mike951 2:15134f79b400 362 lcd.printf("Hit by:");
Mike951 4:7294c20b1025 363 wait(1);
Mike951 2:15134f79b400 364 lcd.cls();
Mike951 2:15134f79b400 365 for(unsigned j = 0; j <= 12; j++) //prints out id and team of person who tagged player
Mike951 2:15134f79b400 366 {
Mike951 2:15134f79b400 367 lcd.printf("%c",id_rx[j]);
Mike951 2:15134f79b400 368 if (j == 7)
Mike951 2:15134f79b400 369 {
Mike951 4:7294c20b1025 370 lcd.printf("\n"); //puts in a new line after eight characters
Mike951 2:15134f79b400 371 }
Mike951 2:15134f79b400 372 }
Mike951 4:7294c20b1025 373 wait(4);
Mike951 2:15134f79b400 374 }
Mike951 4:7294c20b1025 375 /*Firing function
Mike951 4:7294c20b1025 376 Sends ID information through IR
Mike951 4:7294c20b1025 377 Parameters: player_id
Mike951 4:7294c20b1025 378 player_id = 15 character array that contains player id and crc hash
Mike951 4:7294c20b1025 379 returns nothing
Mike951 4:7294c20b1025 380 */
Mike951 2:15134f79b400 381 void fire(char* player_id)
Mike951 2:15134f79b400 382 {
Mike951 4:7294c20b1025 383 for (unsigned i = 0; i < 15; i ++)
Mike951 3:752f5f63f783 384 {
Mike951 4:7294c20b1025 385 IR.putc(player_id[i]);
Mike951 3:752f5f63f783 386 }
Mike951 3:752f5f63f783 387 }
Mike951 3:752f5f63f783 388
Mike951 3:752f5f63f783 389 /*Statistics Display Function
Mike951 3:752f5f63f783 390 Displays game statistics without interrupting gameplay significantly
Mike951 3:752f5f63f783 391 Requires LCD to be on.
Mike951 3:752f5f63f783 392 Function will end if fire button is pressed or 5 seconds have passed
Mike951 3:752f5f63f783 393 without the statistics button (btn2) being pressed again.
Mike951 3:752f5f63f783 394 Maximum amount of time possible in this function is 15 seconds,
Mike951 3:752f5f63f783 395 5 seconds for each of the 3 statistics displays
Mike951 3:752f5f63f783 396 Parameters: tag_count = number of times player has been tagged
Mike951 3:752f5f63f783 397 shots = number of times player has shot
Mike951 3:752f5f63f783 398 mode = level of statistics looking at: tag count(0), shots(1), or time since reset(2)
Mike951 3:752f5f63f783 399 Returns nothing
Mike951 3:752f5f63f783 400 */
Mike951 3:752f5f63f783 401 void statistics(const unsigned &tag_count, const unsigned &shots, short mode)
Mike951 3:752f5f63f783 402 {
Mike951 3:752f5f63f783 403 done = false; //Used to timeout on statistics display
Mike951 3:752f5f63f783 404 lcd.cls();
Mike951 3:752f5f63f783 405 if(mode == 0)
Mike951 3:752f5f63f783 406 {
Mike951 3:752f5f63f783 407 lcd.printf("Tagged:\n%u",tag_count);
Mike951 3:752f5f63f783 408 }
Mike951 3:752f5f63f783 409 else if(mode == 1)
Mike951 3:752f5f63f783 410 {
Mike951 3:752f5f63f783 411 lcd.printf("# Shots:\n%u",shots); //shot count
Mike951 3:752f5f63f783 412 }
Mike951 3:752f5f63f783 413 else if(mode == 2)
Mike951 3:752f5f63f783 414 {
Mike951 3:752f5f63f783 415 unsigned secs = 0; //used to readout numer of seconds on timer
Mike951 3:752f5f63f783 416 secs = timer.read();
Mike951 3:752f5f63f783 417 lcd.printf("Mins:%u\nSecs:%u", mins,secs);
Mike951 3:752f5f63f783 418 }
Mike951 3:752f5f63f783 419 else
Mike951 3:752f5f63f783 420 {
Mike951 3:752f5f63f783 421 led1 = 1;
Mike951 3:752f5f63f783 422 led2 = 1;
Mike951 3:752f5f63f783 423 return; //if no valid mode, the function will end. Used to end recursion
Mike951 3:752f5f63f783 424 }
Mike951 3:752f5f63f783 425 stats.attach(&finish_disp, 5);
Mike951 3:752f5f63f783 426 while(!done)
Mike951 3:752f5f63f783 427 {
Mike951 4:7294c20b1025 428 if(btn3 == true || tagged)
Mike951 3:752f5f63f783 429 {
Mike951 3:752f5f63f783 430 stats.detach(); //exit if something interrupts stats
Mike951 3:752f5f63f783 431 lcd.cls();
Mike951 3:752f5f63f783 432 return;
Mike951 3:752f5f63f783 433 }
Mike951 3:752f5f63f783 434 else if(btn2 == true)
Mike951 3:752f5f63f783 435 {
Mike951 3:752f5f63f783 436 btn2 = false;
Mike951 3:752f5f63f783 437 stats.detach(); //keeps statistics display from timing out for another 5 seconds
Mike951 3:752f5f63f783 438 mode ++;
Mike951 3:752f5f63f783 439 statistics(tag_count,shots,mode); //recursive function call of statistics
Mike951 3:752f5f63f783 440 return; //jumps out of function whenever other forms return
Mike951 3:752f5f63f783 441 }
Mike951 3:752f5f63f783 442 wait(0.05); //function will get stuck without short wait
Mike951 3:752f5f63f783 443 }
Mike951 3:752f5f63f783 444 return;
Mike951 3:752f5f63f783 445 }
Mike951 2:15134f79b400 446
Mike951 0:69e5ee3b618d 447 int main()
Mike951 0:69e5ee3b618d 448 {
Mike951 0:69e5ee3b618d 449 Square_Gen.period_us(26); //produces a 38kHz square wave to ensure proper IR communication...
Mike951 0:69e5ee3b618d 450 Square_Gen.pulsewidth_us(13); //...this signal is sent to one of the IR diode terminals through a transistor
Mike951 4:7294c20b1025 451 IR.baud(1200); //sets baud rate of serial output and input
Mike951 4:7294c20b1025 452 IR.attach(&callback); //attaches interrupt for serial buffer
Mike951 0:69e5ee3b618d 453 LB = 1; //turn on lcd backlight
Mike951 0:69e5ee3b618d 454 LP = 1; //turn on lcd power
Mike951 0:69e5ee3b618d 455 sw2.mode(PullUp); //set buttons to a default high voltage for logic low
Mike951 0:69e5ee3b618d 456 sw3.mode(PullUp);
Mike951 0:69e5ee3b618d 457 sw2.setSampleFrequency(); //set buttons to default sample frequency for debouncing
Mike951 0:69e5ee3b618d 458 sw3.setSampleFrequency();
Mike951 0:69e5ee3b618d 459 sw2.setAssertValue(0); //set buttons to be logic high when voltage is low.
Mike951 0:69e5ee3b618d 460 sw3.setAssertValue(0);
Mike951 1:24f46931d010 461 sw2.attach_asserted( &btn2Pressed ); //attach button interrupts
Mike951 1:24f46931d010 462 sw3.attach_asserted( &btn3Pressed );
Mike951 1:24f46931d010 463 clock_tick.attach(&minutes, 60); //ticker interrupts every 60 seconds to add 1 minute and reset timer
Mike951 1:24f46931d010 464 timer.reset(); //ensure timer starts at 0
Mike951 1:24f46931d010 465 timer.start(); //start reset timer
Mike951 0:69e5ee3b618d 466
Mike951 0:69e5ee3b618d 467 led1 = 1;
Mike951 1:24f46931d010 468 char id[15]; //id array, capable of storing user ids up to 12 bytes with 1 byte for team and 2 bytes for CRC.
Mike951 2:15134f79b400 469 unsigned tag_count = 0; //number of times player has been tagged in a game
Mike951 2:15134f79b400 470 unsigned shots = 0; //number of shots fired in a game.
Mike951 1:24f46931d010 471 lcd.cls(); //ensure lcd starts with clear screen
Mike951 1:24f46931d010 472 lcd.printf("Choose \nYour ID.");
Mike951 1:24f46931d010 473 while(btn2 == false && btn3 == false)
Mike951 1:24f46931d010 474 {
Mike951 2:15134f79b400 475 wait(0.2); //wait to start setup until either button is pressed
Mike951 1:24f46931d010 476 }
Mike951 1:24f46931d010 477 btn2 = false; //reset button values
Mike951 1:24f46931d010 478 btn3 = false;
Mike951 1:24f46931d010 479 setup(id); //setup player id and team, passing function the id array
Mike951 4:7294c20b1025 480 /*lcd.cls();
Mike951 2:15134f79b400 481 lcd.printf("Starting\nin 3 sec");
Mike951 4:7294c20b1025 482 wait(3);*/
Mike951 2:15134f79b400 483 taggable = true;
Mike951 4:7294c20b1025 484 LB = 0; //turn off lcd screen, backlight, and leds to save power during game
Mike951 3:752f5f63f783 485 LP = 0;
Mike951 4:7294c20b1025 486 led1 = 0;
Mike951 4:7294c20b1025 487 led2 = 0;
Mike951 0:69e5ee3b618d 488 while(1)
Mike951 3:752f5f63f783 489 {
Mike951 4:7294c20b1025 490 if(tagged)
Mike951 0:69e5ee3b618d 491 {
Mike951 3:752f5f63f783 492 flash.attach(&flasher,0.5);
Mike951 4:7294c20b1025 493 tagged = false;
Mike951 4:7294c20b1025 494 //LB = 1; //turn on backlight and leds for flash
Mike951 3:752f5f63f783 495 led1 = 1;
Mike951 3:752f5f63f783 496 led2 = 1;
Mike951 3:752f5f63f783 497 if (check_id(id))
Mike951 2:15134f79b400 498 {
Mike951 4:7294c20b1025 499 taggable = false; //don't allow new tags if respawning
Mike951 3:752f5f63f783 500 flash.detach(); //if tag is valid, no need to flash
Mike951 3:752f5f63f783 501 tag_count ++;
Mike951 3:752f5f63f783 502 LP = 1; //turn LCD power and backlight on
Mike951 2:15134f79b400 503 LB = 1;
Mike951 3:752f5f63f783 504 respawn(); //prints appropriate respawn info
Mike951 4:7294c20b1025 505 taggable = true;
Mike951 4:7294c20b1025 506 led2 = 0;
Mike951 2:15134f79b400 507 }
Mike951 4:7294c20b1025 508 LB = 0; //turn LCD backlight and power back off
Mike951 4:7294c20b1025 509 LP = 0;
Mike951 4:7294c20b1025 510 led1 = 0;
Mike951 0:69e5ee3b618d 511 }
Mike951 3:752f5f63f783 512 if(btn3) //fires IR led if btn3 is pressed
Mike951 3:752f5f63f783 513 {
Mike951 3:752f5f63f783 514 btn3 = false;
Mike951 3:752f5f63f783 515 flash.detach(); //lights will not flash if you fire really fast
Mike951 3:752f5f63f783 516 shots ++; //increment number of times ir has been shot by player
Mike951 3:752f5f63f783 517 LB = 1;
Mike951 3:752f5f63f783 518 led1 = 1;
Mike951 3:752f5f63f783 519 led2 = 1;
Mike951 3:752f5f63f783 520 flash.attach(flasher,0.5); //flashes backlight and leds when firing
Mike951 3:752f5f63f783 521 fire(id); //fires player id using IR diode
Mike951 3:752f5f63f783 522 }
Mike951 4:7294c20b1025 523 if (btn2) //displays statistics if btn2 is pressed
Mike951 3:752f5f63f783 524 {
Mike951 4:7294c20b1025 525 flash.detach();
Mike951 3:752f5f63f783 526 btn2 = false;
Mike951 3:752f5f63f783 527 LP = 1; //turn on display
Mike951 3:752f5f63f783 528 LB = 1;
Mike951 3:752f5f63f783 529 statistics(tag_count,shots,0);
Mike951 3:752f5f63f783 530 LP = 0;
Mike951 3:752f5f63f783 531 LB = 0;
Mike951 3:752f5f63f783 532 }
Mike951 3:752f5f63f783 533 wait(0.01);
Mike951 3:752f5f63f783 534 }
Mike951 0:69e5ee3b618d 535 }