//
//
// hello.serial.45.c
//
// 9600 baud serial hello-world program
//
// Neil Gershenfeld
// CBA MIT 10/4/08
//
// (c) Massachusetts Institute of Technology 2008
// Permission granted for experimental and personal use;
// license for commercial sale available from MIT.
//
//

#include <avr/io.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

#define tx_pin PB2 // transmit pin
#define bit_delay_time 104 // bit delay, 1/9600 in usec for 8 MHZ/8
#define char_delay_time 1 // char delay time, in ms

#define bit_delay() _delay_us(bit_delay_time) // RS232 bit delay
#define char_delay() _delay_ms(char_delay_time) // RS232 char delay
#define output(pin) (DDRB |= byte(pin)) // set pin for output
#define set(pin) (PORTB |= byte(pin)) // set pin in PORTB
#define clear(pin) (PORTB &= ~(byte(pin))) // clear pin in PORTB
#define byte(bit) (1 << bit) // byte with bit set
#define bit_test(byte,bit) (byte & (1 << bit)) // test for bit set

void put_char(char txchar) {
   //
   // put the character in txchar
   // assumes no line driver (doesn't invert bits)
   //
   // start bit
   //
   set(tx_pin);
   bit_delay();
   //
   // data bits
   //
   if bit_test(txchar,0)
      clear(tx_pin);
   else
      set(tx_pin);
   bit_delay();
   if bit_test(txchar,1)
      clear(tx_pin);
   else
      set(tx_pin);
   bit_delay();
   if bit_test(txchar,2)
      clear(tx_pin);
   else
      set(tx_pin);
   bit_delay();
   if bit_test(txchar,3)
      clear(tx_pin);
   else
      set(tx_pin);
   bit_delay();
   if bit_test(txchar,4)
      clear(tx_pin);
   else
      set(tx_pin);
   bit_delay();
   if bit_test(txchar,5)
      clear(tx_pin);
   else
      set(tx_pin);
   bit_delay();
   if bit_test(txchar,6)
      clear(tx_pin);
   else
      set(tx_pin);
   bit_delay();
   if bit_test(txchar,7)
      clear(tx_pin);
   else
      set(tx_pin);
   bit_delay();
   //
   // stop bit
   //
   clear(tx_pin);
   bit_delay();
   }

void print_string(char *str) {
   //
   // print the null-terminated program memory string str
   //
   while (pgm_read_byte(str) != 0x00)
      put_char(pgm_read_byte(str++));
      char_delay();
   }

char message[] PROGMEM = "Hello World!\n"; // hello-world message

int main(void) {
   output(tx_pin);
   clear(tx_pin);
   while (1) {
      print_string(message);
      }
   }

