//Laser Simon Board //Cathy Chen -cc464 //4/28/2008 //Ported to GCC by Adam Shapiro, 5/6/08. #include #include #include #include #include "radio.h" #include "simon.h" #include "messages.h" #include "radio_addr.h" //Signals to be used in game unsigned char fired = 0; unsigned char current_player = RADIO_ADDR_CONTROL_A; unsigned char pattern[10] = {0}; unsigned char target = 0; unsigned char next =0; unsigned char current_level = 11; unsigned char counter = 0; unsigned char rotate_enabled = 0; unsigned char show_pattern_enable = 0; unsigned char winner = 0; unsigned char rotate = 0; unsigned int playerA_score = 0; unsigned int playerB_score = 0; unsigned int led_rate=500; unsigned int led_timer=0; unsigned int simon_led = 0; void message_decode(void); void initialize(void); void hit_detection(void); void show_pattern(void); void rotate_leds(void); void set_pattern(void); void scan_photosensors(void); #include "radio_def.h" int main(void) { initialize(); set_pattern(); while(1) { radio_exec(); message_decode(); hit_detection(); if(rotate_enabled)rotate_leds(); if(show_pattern_enable) show_pattern(); if(led_timer == 0) { PORTD^=_BV(PD4); led_timer = led_rate; } } return 0; } void initialize(void) { //PortB as outputs DDRB=0xFF; PORTB=0xFF; //PortD.4 as output DDRD|=_BV(PD4); PORTD|=_BV(PD4); //Set Analog Input ADMUX = 0x20; ADCSRA = 0xE0; radio_init(); TIMSK1 = 0x02;//Enable output compare interrupt. TCCR1B = 0x0A;//Enable reset on compare match, 1:8 clock. OCR1AH = 1; OCR1AL = 244;//Set register sei(); } //Takes message and extracts information void message_decode(void) { unsigned char data[10]; unsigned char length; unsigned char ret; unsigned char src; ret=radio_receive(&src,&length,data); if (ret==RET_RX_PACKET_REC) { switch(data[0]) { case LB_MSG_FIRE: if (src == current_player)fired = 1; break; case LB_MSG_RESET: current_player = RADIO_ADDR_CONTROL_A; target = 0; next =0; current_level = 1; counter = 0; rotate_enabled = 0; winner = 0; rotate = 0; fired = 0; data[0] = LB_MSG_LEVEL; data[1] = current_level; radio_send(RADIO_ADDR_CONTROL_A, 1, 2, data); radio_send(RADIO_ADDR_CONTROL_B, 1, 2, data); data[0] = LB_MSG_PLAYER; data[1] = current_player; radio_send(RADIO_ADDR_CONTROL_A, 1, 2, data); radio_send(RADIO_ADDR_CONTROL_B, 1, 2, data); set_pattern(); show_pattern_enable = 1; break; } } } //Hit Calculation void hit_detection(void) { if(!fired||current_level>MAX_LEVELS) return; fired = 0; if(ADCH > 1) // PHOTODIODE NUMBER //when correct player hits, go onto next thing in pattern, send hit report, give points { unsigned char data[2] = {LB_MSG_HIT_REPORT, LB_DATA_HIT}; radio_send(current_player, 0, 2, data); // repeat, message length, payload if (current_player == RADIO_ADDR_CONTROL_A)playerA_score = playerA_score + current_level; else playerB_score = playerB_score + current_level; } else { unsigned char data[2] = {LB_MSG_HIT_REPORT, LB_DATA_MISS}; radio_send(current_player, 0, 2, data); // repeat, message length, payload } next++; scan_photosensors(); //FIXME move this until after setting the target? if (next == current_level)// end of current player's turn { unsigned char data[2] = {LB_MSG_PLAYER}; if(current_player == RADIO_ADDR_CONTROL_A) { current_player = RADIO_ADDR_CONTROL_B; show_pattern_enable = 1; counter = 0; } else { current_player =RADIO_ADDR_CONTROL_A; current_level++; data[0] = LB_MSG_LEVEL; data[1] = current_level; if(current_level<=MAX_LEVELS) { radio_send(RADIO_ADDR_CONTROL_A, 1, 2, data); radio_send(RADIO_ADDR_CONTROL_B, 1, 2, data); } counter = 0; set_pattern(); } if(current_level MAX_LEVELS)// end of game { unsigned char data[2]={LB_MSG_GAME_OVER,RADIO_ADDR_NULL}; if( playerA_score > playerB_score) { data[1] = RADIO_ADDR_CONTROL_A; winner = PLAYER_A; } if (playerB_score > playerA_score) { data[1] = RADIO_ADDR_CONTROL_B; winner = PLAYER_B; } else { winner = TIE; } radio_send(RADIO_ADDR_CONTROL_A, 1, 2, data); radio_send(RADIO_ADDR_CONTROL_B, 1, 2, data); rotate_enabled = 1; rotate = 0; counter = 0; } } void show_pattern(void)//blink leds in next pattern { if (simon_led != 0 ) return; simon_led = 700; if (counter < current_level) { if(pattern[counter]== PHOTO0)LED_PORT|=_BV(LED0); else LED_PORT&=~_BV(LED0); if(pattern[counter]== PHOTO1)LED_PORT|=_BV(LED1); else LED_PORT&=~_BV(LED1); if(pattern[counter]== PHOTO2)LED_PORT|=_BV(LED2); else LED_PORT&=~_BV(LED2); if(pattern[counter]== PHOTO3)LED_PORT|=_BV(LED3); else LED_PORT&=~_BV(LED3); if(pattern[counter]== PHOTO4)LED_PORT|=_BV(LED4); else LED_PORT&=~_BV(LED4); counter++; } else { PORTB&=~(_BV(LED0)|_BV(LED1)|_BV(LED2)|_BV(LED3)|_BV(LED4)); show_pattern_enable = 0; } } void rotate_leds(void) { if(simon_led != 0) return; simon_led = 500; if(rotate < ROTATE_TIMES) { if(counter == 0)LED_PORT|=_BV(LED0); else LED_PORT&=~_BV(LED0); if(counter == 1)LED_PORT|=_BV(LED1); else LED_PORT&=~_BV(LED1); if(counter == 2)LED_PORT|=_BV(LED2); else LED_PORT&=~_BV(LED2); if(counter == 3)LED_PORT|=_BV(LED3); else LED_PORT&=~_BV(LED3); if(counter == 4) { LED_PORT|=_BV(LED4); counter = 0; rotate++; } else { LED_PORT&=~_BV(LED4); counter++; } } else { if(winner == PLAYER_A) { PORTB=(PORTB&0xE0)|0x18; } if (winner == PLAYER_B) { PORTB=(PORTB&0xE0)|0x06; } else { PORTB=(PORTB&0xE0)|0x1F; } rotate_enabled = 0; } } void set_pattern(void) { unsigned char i; for(i=0; i< current_level; i++) pattern[i]=rand()%5; } void scan_photosensors(void) { if (target == PHOTO0)ADMUX = ADCPORT0; if (target == PHOTO1)ADMUX = ADCPORT1; if (target == PHOTO2)ADMUX = ADCPORT2; if (target == PHOTO3)ADMUX = ADCPORT3; if (target == PHOTO4)ADMUX = ADCPORT4; } ISR(TIMER1_COMPA_vect) { if(radio_tx_timer!=RADIO_TIMER_OFF&&radio_tx_timer>0)radio_tx_timer--; if(radio_rx_timer!=RADIO_TIMER_OFF&&radio_rx_timer>0)radio_rx_timer--; if(led_timer>0)led_timer--; if(simon_led >0) simon_led--; }