/* Daniel Warren Heidi Ng ECE 476 Final Project Remote Controlled Outlet Strip RECEIVER END (c) Spring 2004 */ #include #include #include // reload times for the software timers #define t0_on 100 #define t0_off 900 #define t1 500 // error correction bytes #define start_tag 0b10010100 #define stop_tag 0b01001011 // max number of blink states and speed states #define speed_max 6 #define blink_max 6 unsigned int time0; // for heartbeat LED unsigned int time1; // for receive LED unsigned int time2; // for light state transition unsigned int t2_reload; // reload value for t2 // ms delay between blink state changes unsigned int blink_speeds[6] = {125, 250, 500, 1000, 2000, 5000}; unsigned char blink_mode, speed; //keeps track of current blink and speed mode unsigned char blink_state; // each blink state machine uses this as its state variable unsigned char active, output; // which outlets are active, and which should be on // outlet states for a scrolling marquee unsigned char marquee[8] = {0b11111111, 0b11101110, 0b11001100, 0b10001000, 0b00000000, 0b00010001, 0b00110011, 0b01110111}; unsigned char uart_status, incoming, data; // for verifying data from the receiver unsigned char receive_status; // indicates what bytes have been received unsigned char got_data; // flag that data was received void initialize(void); // set everything up void decode(void); // figure which button was pressed void blink(void); // blinking state machine //----------------------------------------------------------------------------------- // ticks every ms interrupt [TIM0_COMP] void timer0_ms(void) { // Decrement the time to check state, if not already zero if (time0>0) --time0; if (time1>0) --time1; if (time2>0) --time2; } //----------------------------------------------------------------------------------- interrupt [USART_RXC] void uart_receive(void) { // read status bits and data byte from UART uart_status = UCSRA; incoming = UDR; // check for frame and parity errors if((uart_status & 0x10) == 0x10 || (uart_status & 0x04) == 0x04) { receive_status = 0; // data error - start over } else { if(receive_status == 0 && incoming == start_tag) { receive_status = 1; // now have start tag } else if(receive_status == 1) { data = incoming; receive_status = 2; // now have start and data } else if(receive_status == 2 && incoming == stop_tag) { receive_status = 0; // now have start, data, stop PORTD.7 = 0; // turn on receive LED time1 = t1; got_data = 1; } else { receive_status = 0; // something missing - restart } } } //----------------------------------------------------------------------------------- void main(void) { // sets everything up initialize(); while(1) { // heartbeat on for 100ms, off for 900ms if(time0==0) { if(PORTD.6 == 0) // LED was on { PORTD.6 = 1; time0 = t0_off; } else { PORTD.6 = 0; time0 = t0_on; } } if(time1 == 0) PORTD.7 = 1; // stop indicating data received // update blink state if(time2 == 0) { time2 = t2_reload; blink(); } // decode data byte received if(got_data == 1) { got_data = 0; decode(); } } } //----------------------------------------------------------------------------------- // incoming data packet - active low // 7 6 5 4 3 2 1 0 // +-----------------------------------------------------------------+ // | all | speed | toggle | toggle | all | mode | toggle | toggle | // | off | | second | fourth | on | | first | third | // +-----------------------------------------------------------------+ // void decode(void) { switch(data) { case 0b11111101: // 1st active = active ^ 0b00010001; time2=0; break; case 0b11011111: // 2nd active = active ^ 0b00100010; time2=0; break; case 0b11111110: // 3rd active = active ^ 0b01000100; time2=0; break; case 0b11101111: // 4th active = active ^ 0b10001000; time2=0; break; case 0b01111111: // all off active = 0x00; time2=0; break; case 0b11110111: // all on active = 0xff; time2=0; break; case 0b11111011: // mode blink_mode++; if(blink_mode >= blink_max) blink_mode = 0; blink_state = 0; time2=0; break; case 0b10111111: // speed speed++; if(speed >= speed_max) speed = 0; t2_reload=blink_speeds[speed]; time2=0; break; default: // not a valid piece of data -- another error correction step PORTD.7 = 1; // turn off receive LED time1 = 0; break; } } //----------------------------------------------------------------------------------- void blink(void) { switch(blink_mode) { case 0: // not blinking output = active; break; case 1: // blink all/off switch(blink_state) { case 0: // all off blink_state = 1; output = 0x00; break; case 1: // some on blink_state = 0; output = active; break; } break; case 2: // blink all/on switch(blink_state) { case 0: // all on blink_state = 1; output = 0xff; break; case 1: // some on blink_state = 0; output = active; break; } break; case 3: // blink active / non-active switch(blink_state) { case 0: // active on blink_state = 1; output = active; break; case 1: // non-active on blink_state = 0; output = ~active; break; } break; case 4: //scroll whichever are on blink_state++; if (blink_state >= 4) blink_state = 0; output = active << blink_state; output = (output & 0xf0) | ((output >> 4) & 0x0f); break; case 5: // scroll all without wraparound blink_state++; if (blink_state >= 8) blink_state = 0; output = marquee[blink_state]; break; } PORTC = output; } //----------------------------------------------------------------------------------- void initialize(void) { DDRD = 0xf0; //bottom nibble input for receive, top nibble output for heartbeat LEDs PORTD = 0xf0; //LEDs off DDRC = 0xff; //output for status LEDs and relays PORTC = 0xff; //lights and relays start on //timer0 ticks every 1ms OCR0 = 124; TCCR0 = 0b00001011; //prescale 64 TIMSK = 0x02; //enable output compare match //set USART UCSRB = 0x90; //receiver on, receive interrupt enabled UCSRC = 0b10111110; //8bit, odd parity enable, 2 stop bits // UBRRL = 207; //2400 baud -> (8MHz/(16*2400))- 1 UBRRL = 0xa0; //1200 baud -> UBRR = 416 UBRRH = 0x01; #asm ("sei"); receive_status = 0; got_data = 0; blink_mode = 0; blink_state = 0; speed = 2; t2_reload = blink_speeds[speed]; time0 = t0_off; time1 = 0; time2 = t2_reload; active=0xff; output=0xff; }