// // // hello.echo.44.c // // 115200 baud serial echo hello-world program // // Neil Gershenfeld // CBA MIT 9/12/09 // // (c) Massachusetts Institute of Technology 2009 // Permission granted for experimental and personal use; // license for commercial sale available from MIT. // // #include #include #include #define tx_pin PA6 // transmit pin #define rx_pin PA7 // receive pin #define led_pin PB2 // LED pin #define bit_delay_time 8.7 // bit delay, 1/115200 in usec at 20 MHZ #define led_delay_time 10 // LED delay time, in ms #define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay #define half_bit_delay() _delay_us(bit_delay_time/2) // RS232 half bit delay #define output_A(pin) (DDRA |= byte(pin)) // set PORTA pin for output #define output_B(pin) (DDRB |= byte(pin)) // set PORTB pin for output #define set_A(pin) (PORTA |= byte(pin)) // set pin in PORTA #define clear_A(pin) (PORTA &= ~(byte(pin))) // clear pin in PORTA #define set_B(pin) (PORTB |= byte(pin)) // set pin in PORTB #define clear_B(pin) (PORTB &= ~(byte(pin))) // clear pin in PORTB #define pin_test_A(bit) (PINA & (1 << bit)) // test for pin in PORTA #define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set #define byte(bit) (1 << bit) // byte with bit set char get_char() { // // read and return a character // assumes no line driver (doesn't invert bits) // unsigned char rxbyte = 0; while (! pin_test_A(rx_pin)) // // wait for start bit // ; // // delay to middle of first data bit // half_bit_delay(); bit_delay(); // // unrolled loop to read data bits // if pin_test_A(rx_pin) rxbyte |= (0 << 0); else rxbyte |= (1 << 0); bit_delay(); if pin_test_A(rx_pin) rxbyte |= (0 << 1); else rxbyte |= (1 << 1); bit_delay(); if pin_test_A(rx_pin) rxbyte |= (0 << 2); else rxbyte |= (1 << 2); bit_delay(); if pin_test_A(rx_pin) rxbyte |= (0 << 3); else rxbyte |= (1 << 3); bit_delay(); if pin_test_A(rx_pin) rxbyte |= (0 << 4); else rxbyte |= (1 << 4); bit_delay(); if pin_test_A(rx_pin) rxbyte |= (0 << 5); else rxbyte |= (1 << 5); bit_delay(); if pin_test_A(rx_pin) rxbyte |= (0 << 6); else rxbyte |= (1 << 6); bit_delay(); if pin_test_A(rx_pin) rxbyte |= (0 << 7); else rxbyte |= (1 << 7); return rxbyte; } void put_char(char txchar) { // // print the character in txchar // assumes no line driver (doesn't invert bits) // // start bit // set_A(tx_pin); bit_delay(); // // unrolled loop to write data bits // if bit_test(txchar,0) clear_A(tx_pin); else set_A(tx_pin); bit_delay(); if bit_test(txchar,1) clear_A(tx_pin); else set_A(tx_pin); bit_delay(); if bit_test(txchar,2) clear_A(tx_pin); else set_A(tx_pin); bit_delay(); if bit_test(txchar,3) clear_A(tx_pin); else set_A(tx_pin); bit_delay(); if bit_test(txchar,4) clear_A(tx_pin); else set_A(tx_pin); bit_delay(); if bit_test(txchar,5) clear_A(tx_pin); else set_A(tx_pin); bit_delay(); if bit_test(txchar,6) clear_A(tx_pin); else set_A(tx_pin); bit_delay(); if bit_test(txchar,7) clear_A(tx_pin); else set_A(tx_pin); bit_delay(); // // stop bit // clear_A(tx_pin); bit_delay(); } void print_string(char *str) { // // print the null-terminated program memory string str // char chr; chr = pgm_read_byte(str++); while (chr != 0x00) { put_char(chr); chr = pgm_read_byte(str++); } } void blink() { // // blink the LED // set_B(led_pin); _delay_ms(led_delay_time); clear_B(led_pin); } char message[] PROGMEM = "received character: "; int main(void) { unsigned char rxbyte; // // set clock divider to /1 // CLKPR = (1 << CLKPCE); CLKPR = (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0); // // initialize output pins // output_A(tx_pin); output_B(led_pin); clear_A(tx_pin); // // main loop // while (1) { rxbyte = get_char(); print_string(message); put_char(rxbyte); put_char('\n'); blink(); } }