Subversion Repositories HomeAutomation

Rev

Rev 73 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /**
  2.  * @file    uart.c
  3.  *          Routines for interrupt based USART communication on the ATmega8.
  4.  * @author  Jimmy Myhrman
  5.  * @date    2005-08-20
  6.  */
  7.  
  8. /* -----------------------------------------------------------------------------
  9.  * Includes
  10.  * ---------------------------------------------------------------------------*/
  11. #include "uart.h"
  12.  
  13. /* -----------------------------------------------------------------------------
  14.  * Defines
  15.  * ---------------------------------------------------------------------------*/
  16. #define TX_BUFSIZE  256         /* must be power of 2 */
  17. #define RX_BUFSIZE  2           /* must be power of 2 */
  18.  
  19. #define TX_MASK     (TX_BUFSIZE-1)
  20. #define RX_MASK     (RX_BUFSIZE-1)
  21.  
  22. #define RX_BUFLEN   (rx_tail - rx_head)
  23. #define TX_BUFLEN   (tx_tail - tx_head)
  24.  
  25. /* -----------------------------------------------------------------------------
  26.  * Variables
  27.  * ---------------------------------------------------------------------------*/
  28. volatile unsigned char tx_buf[TX_BUFSIZE];
  29. volatile unsigned char rx_buf[RX_BUFSIZE];
  30.  
  31. volatile uint8_t tx_head;
  32. volatile uint8_t tx_tail;
  33.  
  34. volatile uint8_t rx_head;
  35. volatile uint8_t rx_tail;
  36.  
  37. /* -----------------------------------------------------------------------------
  38.  * Functions
  39.  * ---------------------------------------------------------------------------*/
  40.  
  41. void uartInit(unsigned char baudrate) {
  42.     UBRRH = (unsigned char) (baudrate>>8);
  43.     UBRRL = (unsigned char) baudrate;
  44.     /* 8 Databits, receive and transmit enabled, receive complete interrupt enabled */
  45.     UCSRB = (1<<RXCIE)|(1<<TXEN)|(1<<RXEN);
  46. }
  47.  
  48. int uartPutChar(char c) {
  49.     // Fills the transmit buffer, if it is full wait
  50.     //TODO: if interrupts are currently disabled (which is the case when this
  51.     //function is called from within an interrupt routine), skip the while-loop
  52.     //below. otherwise, use it
  53.     //while ((TX_BUFSIZE - TX_BUFLEN) <= 2) {
  54.         //if uartPutchar is called while global ints are disabled, we are
  55.         //stuck here!
  56.     //}
  57.     if ((TX_BUFSIZE - TX_BUFLEN) <= 2) {
  58.         return(1);
  59.     }
  60.     // Add data to the transmit buffer, move the tail and enable TXCIE
  61.     // while tx_tail will count from 0 to 255... AND'ing it with 31 will
  62.     //continually wrap the index 0 to 31
  63.     tx_buf[tx_tail & TX_MASK] = c;
  64.     tx_tail++;
  65.     // enable data register empty interrupt
  66.     UCSRB |= (1<<UDRIE);
  67.     return(0);
  68. }
  69.  
  70.  
  71. int uartGetChar (void) {
  72.     unsigned char c;
  73.     // this will sit here and wait for SIG_UART0_RECV to get a character and
  74.     //place it into rx0_buff
  75.     while (RX_BUFLEN == 0) {
  76.     }
  77.     // rx_head will count from 0 to 255... AND'ing it with 31 will continually
  78.     //wrap the index 0 to 31
  79.     c = rx_buf[rx_head & RX_MASK];
  80.     rx_head++;
  81.     return(c);
  82. }
  83.  
  84.  
  85. // USART receive complete interrupt
  86. SIGNAL(SIG_UART_RECV) {
  87.     char c;
  88.     // Get the received character
  89.     c = UDR;
  90.     // Echo the character back
  91.     uartPutChar(c);
  92.     // place the received character into the receive buffer and move the tail
  93.     // rx_tail will count from 0 to 255... AND'ing it with 31 will continually
  94.     //wrap the index 0 to 31
  95.     rx_buf[rx_tail & RX_MASK] = c;
  96.     rx_tail++;
  97. }
  98.  
  99.  
  100. // USART0 data register empty interrupt... another char can be transmitted if (tx0_head != tx0_tail)
  101. SIGNAL(SIG_UART_DATA) {
  102.     // tx_head will count from 0 to 255... AND'ing it with 31 will continually
  103.     //wrap the index 0 to 31
  104.     if (tx_head != tx_tail) {
  105.         UDR = tx_buf[tx_head & TX_MASK];
  106.         tx_head++;
  107.     }
  108.     else {
  109.         // "~" is a one's compliment so UCSR0B = (UCSR0B AND 11011111) which disables udr empty interrupt
  110.         UCSRB &= ~(1<<UDRIE);
  111.     }
  112. }
  113.  
  114.  
  115. //string must be null-terminated
  116. void uartPutString(char* str) {
  117.     while (*str != 0) {
  118.         uartPutChar(*str);
  119.         str++;
  120.     }
  121. }
  122.  
  123.  
  124. void uartPutUInt8(uint8_t number, uint8_t base) {
  125.     uint8_t a;
  126.     if ((a = number/base) != 0) {
  127.         uartPutUInt8(a, base);
  128.     }
  129.     uartPutChar("0123456789ABCDEF"[(uint8_t)(number%base)]);
  130. }
  131.  
  132.  
  133. void uartPutUInt16(uint16_t number, uint8_t base) {
  134.     uint16_t a;
  135.     if ((a = number/base) != 0) {
  136.         uartPutUInt16(a, base);
  137.     }
  138.     uartPutChar("0123456789ABCDEF"[(uint8_t)(number%base)]);
  139. }
  140.  
  141.  
  142. void uartNewLine(void) {
  143.     uartPutString("\n\r");
  144. }
  145.