uart0.c 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /*---------------------------------------------------------*/
  2. /* UART functions for ATmega164A/PA/324A/PA/644A/PA/1284/P */
  3. /*---------------------------------------------------------*/
  4. #include <avr/interrupt.h>
  5. #include "uart0.h"
  6. #define UART0_BAUD 9600
  7. #define USE_TXINT 0
  8. #define SZ_FIFO 512
  9. #if SZ_FIFO >= 256
  10. typedef uint16_t idx_t;
  11. #else
  12. typedef uint8_t idx_t;
  13. #endif
  14. typedef struct {
  15. idx_t wi, ri, ct;
  16. uint8_t buff[SZ_FIFO];
  17. } FIFO;
  18. static
  19. volatile FIFO RxFifo;
  20. #if USE_TXINT
  21. static
  22. volatile FIFO TxFifo;
  23. #endif
  24. /* Initialize UART */
  25. void uart0_init (void)
  26. {
  27. UCSR0B = 0;
  28. PORTD |= _BV(PD1); DDRD |= _BV(PD1); /* Set TXD as output */
  29. DDRD &= ~_BV(PD0); PORTD &= ~_BV(PD0); /* Set RXD as input */
  30. RxFifo.ct = 0; RxFifo.ri = 0; RxFifo.wi = 0;
  31. #if USE_TXINT
  32. TxFifo.ct = 0; TxFifo.ri = 0; TxFifo.wi = 0;
  33. #endif
  34. UBRR0L = F_CPU / UART0_BAUD / 16 - 1;
  35. UCSR0B = _BV(RXEN0) | _BV(RXCIE0) | _BV(TXEN0);
  36. }
  37. /* Deinitialize UART */
  38. void uart0_deinit (void)
  39. {
  40. UCSR0B = 0;
  41. }
  42. /* Get a received character */
  43. uint8_t uart0_test (void)
  44. {
  45. return RxFifo.ct;
  46. }
  47. uint8_t uart0_get (void)
  48. {
  49. uint8_t d;
  50. idx_t i;
  51. do {
  52. cli(); i = RxFifo.ct; sei();
  53. } while (i == 0) ;
  54. i = RxFifo.ri;
  55. d = RxFifo.buff[i];
  56. cli();
  57. RxFifo.ct--;
  58. sei();
  59. RxFifo.ri = (i + 1) % sizeof RxFifo.buff;
  60. return d;
  61. }
  62. /* Put a character to transmit */
  63. void uart0_put (uint8_t d)
  64. {
  65. #if USE_TXINT
  66. idx_t i;
  67. do {
  68. cli(); i = TxFifo.ct; sei();
  69. } while (i >= sizeof TxFifo.buff);
  70. i = TxFifo.wi;
  71. TxFifo.buff[i] = d;
  72. TxFifo.wi = (i + 1) % sizeof TxFifo.buff;
  73. cli();
  74. TxFifo.ct++;
  75. UCSR0B = _BV(RXEN0)|_BV(RXCIE0)|_BV(TXEN0)|_BV(UDRIE0);
  76. sei();
  77. #else
  78. loop_until_bit_is_set(UCSR0A, UDRE0);
  79. UDR0 = d;
  80. #endif
  81. }
  82. /* USART0 RXC interrupt */
  83. ISR(USART0_RX_vect)
  84. {
  85. uint8_t d;
  86. idx_t i;
  87. d = UDR0;
  88. i = RxFifo.ct;
  89. if (i < sizeof RxFifo.buff) {
  90. RxFifo.ct = ++i;
  91. i = RxFifo.wi;
  92. RxFifo.buff[i] = d;
  93. RxFifo.wi = (i + 1) % sizeof RxFifo.buff;
  94. }
  95. }
  96. #if USE_TXINT
  97. ISR(USART0_UDRE_vect)
  98. {
  99. idx_t n, i;
  100. n = TxFifo.ct;
  101. if (n) {
  102. TxFifo.ct = --n;
  103. i = TxFifo.ri;
  104. UDR0 = TxFifo.buff[i];
  105. TxFifo.ri = (i + 1) % sizeof TxFifo.buff;
  106. }
  107. if (n == 0)
  108. UCSR0B = _BV(RXEN0)|_BV(RXCIE0)|_BV(TXEN0);
  109. }
  110. #endif