#include #include /* Commands: 0x0D mute 0x2A 0x2B "Full" 0x2C PC 0x2D side-by-side? 0x2F "i" 0x38 AV */ #define UART_BIT_TIME 104 #define UART_HALF_BIT_TIME 52 #define IR_PORT P1OUT const uint8_t IR_BIT = 0x40; const uint8_t RX_BIT = 0x04; uint8_t rxbyte; uint16_t rxbuf; // byte currently being received uint8_t rxbit; // current bit uint8_t rxdone; // done receiving byte uint8_t state = 0; uint8_t buf[20]; uint8_t start = 0; void delay_ms(uint16_t ms) { while (ms--) __delay_cycles(1000); } void wait_for_button() { while (!(P1IN & 0x08)) ; delay_ms(20); while (P1IN & 0x08) ; delay_ms(20); } void philips_rc5_send(uint16_t data) { const uint16_t bit_cycles = 889 - 6; // Configure timer P1SEL |= IR_BIT; P1SEL2 |= IR_BIT; P1IFG &= ~IR_BIT; // Configure timer (36kHz, count up) TACTL = TASSEL1 | TACLR; TACCTL0 = 0; TACCTL2 = 0; TACCR0 = 27; // MHZ / 36000 - 1; // ~36kHz (round(1000000/36000) - 1) TACCR2 = 0; __delay_cycles(bit_cycles * 2); // Start timer TACTL |= MC_1; // Send bits uint8_t bit = 14; while (bit--) { if (data & (1 << 13)) { TACCTL2 = 0; __delay_cycles(bit_cycles); TACCTL2 = OUTMOD_4; __delay_cycles(bit_cycles); } else { TACCTL2 = OUTMOD_4; __delay_cycles(bit_cycles); TACCTL2 = 0; __delay_cycles(bit_cycles); } data <<= 1; } P1OUT &= ~IR_BIT; TACCTL2 = 0; } int16_t inc; uint16_t bittime; uint8_t fail; int main() { bittime = UART_BIT_TIME; // Disable watchdog WDTCTL = WDTPW | WDTHOLD; // 1MHz internal timer BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; // Configure output port (timer output, minus SEL so interrupts work) P1SEL = 0; P1SEL2 = 0; P1OUT &= ~IR_BIT; P1DIR |= IR_BIT; // Configure RX port (software UART) P1IES |= RX_BIT; P1IFG &= ~RX_BIT; P1IE |= RX_BIT; P1DIR |= 0x01; P1OUT &= ~0x01; __bis_status_register(GIE); while (1) { // Wait for interrupt inc++; // ...in low power mode if (rxdone) { rxdone = 0; if (state == 0) { if (rxbyte == 0xFF) state++; } else if (state == 1) { buf[0] = rxbyte; state++; } else { buf[1] = rxbyte; __disable_interrupt(); philips_rc5_send((((uint16_t)buf[0]) << 8) | buf[1]); __enable_interrupt(); state = 0; delay_ms(100); P1OUT |= 0x01; delay_ms(100); P1OUT &= ~0x01; } } if (fail) P1OUT |= 0x01; if (!rxdone) __bis_status_register(CPUOFF | GIE); } return 0; } void __attribute__((interrupt (PORT1_VECTOR))) p1_isr() { // Disable port interrupt P1IE &= ~RX_BIT; P1IFG &= ~RX_BIT; // Clear buffers rxbuf = 0; rxbit = 9; // Enable timer, start at half bit time TACTL = TASSEL_2 | MC_2; TACCR0 = TAR + UART_HALF_BIT_TIME; TACCTL0 = OUTMOD1 | CCIE; } void __attribute__((interrupt (TIMER0_A0_VECTOR))) ta0_isr() { TACCR0 += UART_BIT_TIME; if (rxbit == 0) { TACTL = TASSEL_2; TACCTL0 &= ~CCIE; P1IFG &= ~RX_BIT; P1IE |= RX_BIT; // start bit = 0, stop bit = 1 if ((rxbuf & 0x201) == 0x200) { rxbyte = (rxbuf >> 1) & 0xFF; rxdone = 1; } __bic_status_register_on_exit(CPUOFF); } else { if (P1IN & RX_BIT) rxbuf |= 0x400; rxbuf >>= 1; rxbit--; } }