1 /* interrupt-driven UART routines */
6 #include <avr/interrupt.h>
10 static volatile uint8_t uart_txbuf[UART_TXBUFSIZE];
11 static volatile uint8_t uart_tx_rp = 0;
12 static volatile uint8_t uart_tx_wp = 0;
13 static volatile uint8_t uart_rxbuf[UART_RXBUFSIZE];
14 static volatile uint8_t uart_rx_rp = 0;
15 static volatile uint8_t uart_rx_wp = 0;
17 /* global, external accessable variables */
18 volatile uint8_t uart_break = 0; /* 0: no break detected */
19 volatile uint8_t uart_echo = 0; /* 0: disabled, otherwise enabled */
23 UBRR0 = ((F_CPU + BAUDRATE * 8) / (BAUDRATE * 16) - 1);
24 UCSR0B = (1<<RXCIE0) | (1<<RXEN0) | (1<<TXEN0);
25 UCSR0C = (1<<UCSZ01) | (1<<UCSZ00);
28 uint8_t uart_rx_state(void)
30 /* number of bytes in Rx buffer */
31 return((uint8_t)(uart_rx_wp - uart_rx_rp) % UART_RXBUFSIZE);
34 uint8_t uart_tx_state(void)
36 /* number of bytes in Tx buffer */
37 return((uint8_t)(uart_tx_wp - uart_tx_rp) & UART_TXBUFSIZE);
40 int uart_putc(char c, FILE *stream)
42 if(c == '\n') uart_putc('\r', stream);
44 uint8_t tmp = (uart_tx_wp + 1) % UART_TXBUFSIZE;
46 /* buffer full -> block */
47 while(tmp == uart_tx_rp);
50 uart_txbuf[uart_tx_wp] = c;
53 /* enable UDRE interrupt */
54 UCSR0B |= (1<<UDRIE0);
63 if(uart_tx_rp != uart_tx_wp) {
65 tmp = (uart_tx_rp + 1) % UART_TXBUFSIZE;
66 UDR0 = uart_txbuf[uart_tx_rp];
69 /* buffer empty -> disable interrupt */
70 UCSR0B &= ~(1<<UDRIE0);
74 int uart_getc(FILE *stream)
76 uint8_t tmp = (uart_rx_rp + 1) % UART_RXBUFSIZE;
78 /* empty buffer -> block */
79 while(uart_rx_rp == uart_rx_wp);
83 unsigned char c = uart_rxbuf[uart_rx_rp];
87 if(c == '\r') uart_putc('\n', stream);
95 uint8_t tmp = (uart_rx_wp + 1) % UART_RXBUFSIZE;
96 uint8_t ferr = UCSR0A & (1<<FE0);
100 if(ferr && (data == 0)) {
105 /* enqueue if space in buffer */
106 if(uart_rx_rp != tmp) {
108 uart_rxbuf[uart_rx_wp] = data;
112 FILE uart_out = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);
113 FILE uart_in = FDEV_SETUP_STREAM(NULL, uart_getc, _FDEV_SETUP_READ);