/* Daniel Warren Heidi Ng ECE 476 Final Project Remote Controlled Outlet Strip TRANSMITTER END (c) Spring 2004 */ #include #include #include // reload times for the software timers #define t0 30 #define t1 500 #define t2 5000 // error correction bytes #define start_tag 0b10010100 #define stop_tag 0b01001011 unsigned int time0; // for debouncing the buttons unsigned int time1; // for heartbeat and battery check unsigned int time2; // sleep timer unsigned int Ain; // analog input to check battery voltage unsigned char buttons, bstate; // for debouncing unsigned char data; // data byte to transmit unsigned char num_buttons; // number of buttons pushed unsigned char i; // loop variable // input if only one button pushed at a time unsigned char one_push[8]= {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; void initialize(void); // set everything up void debounce(void); // debounce buttons void transmit(void); // transmit data void power_down(void); // go to sleep //----------------------------------------------------------------------- // ticks every ms interrupt [TIM0_COMP] void timer0_ms(void) { // Decrement the event timers, if not already zero if (time0>0) --time0; if (time1>0) --time1; if (time2>0) --time2; } //----------------------------------------------------------------------- //transmit the data byte void transmit(void) { // check that only one button was pressed num_buttons = 0; for(i=0;i<8;i++) if(data == one_push[i]) num_buttons++; // if only one button pushed, transmit the data if(num_buttons == 1) { // synchronize the receiver putchar(0xaa); putchar(0xaa); putchar(0xaa); putchar(0xaa); putchar(0xaa); putchar(0xaa); putchar(0xaa); putchar(0xaa); putchar(0xf0); putchar(0x0f); // once synchronized, send the data packet putchar(start_tag); putchar(data); putchar(stop_tag); } } //----------------------------------------------------------------------- // disables peripherals, puts the MCU to sleep, then re-enables everything when it wakes up void power_down(void) { ADCSRA.7 = 0; // disable ADC PORTD |= 0b11100000; // LEDs off UCSRB = 0; // disable transmitter PORTD.1 = 0; // transmitter output off // enable external interrupt to wake from sleep MCUCSR = 0b01000000; //ISC2 rising edge for nand gate from buttons GIFR = 0b00100000; //clear flag for INTF2 GICR = 0b00100000; //enable EXT INT2 #asm("sleep"); // power down GICR = 0; // disable INT2 - not needed now data = PINC; // read button state // make sure the same button isn't transmitted twice // preload debouncing state machine bstate = 2; buttons = data; // reset timers time0 = t0; time1 = t1; time2 = t2; UCSRB = 0x08; // transmit enable ADCSRA.7 = 1; // enable ADC // wake up takes long enough that the data shouldn't be bouncing // so transmit it once the MCU wakes up transmit(); } //----------------------------------------------------------------------- interrupt [EXT_INT2] void nand_buttons(void) { // wake up, nothing in the interrupt } //----------------------------------------------------------------------- // PORTC connections // 7 6 5 4 3 2 1 0 // +-----------------------------------------------------------------+ // | all | speed | toggle | toggle | all | mode | toggle | toggle | // | off | | second | fourth | on | | first | third | // +-----------------------------------------------------------------+ // void debounce(void) { // debounce buttons switch (bstate) { case 0: // unpressed if (PINC != 0xff) // something pressed { bstate = 1; // go to possible pressed state buttons = PINC; // save state of buttons } // else // do nothing break; case 1: // possible press if (buttons == PINC) // actual press { bstate = 2; // go to actual press state data = PINC; // read the buttons into the data byte transmit(); // and transmit the data time2 = t2; // reset sleep timer } else // still bouncing { bstate = 0; //back to no push state } break; case 2: // pressed if (buttons == PINC); // buttons haven't changed else bstate = 3; // go to possible release state break; case 3: // possible release if (buttons == PINC) bstate = 2; // buttons back to previous value -- bouncing -- go to pressed state else // buttons actually changed - go to release state { bstate = 0; } break; } } //----------------------------------------------------------------------- void main(void) { // sets everything up initialize(); // main loop -- polls buttons every 30ms while(1) { // every 30ms, check for button push if(time0 == 0) { time0 = t0; // reset timer debounce(); } // every 0.5 sec if(time1==0) { time1 = t1; PORTD.6 = ~PORTD.6; //heartbeat LED // Ain = voltage*1024/2.63 // read full 10 bits of ADC Ain = ADCL; Ain = ((int)ADCH << 8) | Ain; if(Ain < 749 ) // less than 7.75V (1.92293V), turn on red LED { PORTD.7 = 0; //red PORTD.5 = 1; //yellow } else if(Ain < 773) // between 8.00V (1.98496V) and 7.75V, turn on yellow LED { PORTD.7 = 1; PORTD.5 = 0; } ADCSRA.6 = 1; // start ADC conversion for next time } // if no buttons pushed in 5 seconds, go to sleep if(time2==0) { power_down(); } } } //----------------------------------------------------------------------- void initialize(void) { DDRB = 0x00; // input for external interrupt2 (pin3) DDRC = 0x00; // input from buttons PORTC = 0xff; // pull-up resistors DDRD = 0xff; // output for heartbeat LEDs and transmitter PORTD = 0xf0; // LEDs off // timer0 ticks every 1ms OCR0 = 124; TCCR0 = 0b00001011; // prescale 64 TIMSK = 0x02; // enable output compare match //for external interrpt 2 GICR = 0; // disable EXT INT2 MCUCSR = 0b01000000; // ISC2 rising edge for nand gate from buttons GIFR = 0b00100000; // clear flag for INTF2 GICR = 0b00100000; // enable EXT INT2 //set up ADC ADMUX = 0b11000000; // internal Aref, right adj, channel 0 ADCSRA = 0b11000110; // ADC enable, 8MHz/64 prescaler = 125kHz MCUCR = 0b01100000; // enable sleep mode, power down mode //set USART UCSRB = 0x08; // transmit enable 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"); // initialize timers time0 = t0; time1 = t1; time2 = t2; // intialize debouncing state machine bstate = 0; buttons = 0xff; // no data to send just yet data = 0; }