root / serial.c @ 20e5429c
History | View | Annotate | Download (1.31 KB)
1 | 20e5429c | Tom Mullins | #include "serial.h" |
---|---|---|---|
2 | #include <avr/io.h> |
||
3 | #include <avr/interrupt.h> |
||
4 | #include <util/atomic.h> |
||
5 | |||
6 | static int rx_start = 0, rx_end = 0; |
||
7 | static char rx_buffer[RX_BUFFER_SIZE]; |
||
8 | |||
9 | ISR(USART1_RX_vect) { |
||
10 | char data = UDR1;
|
||
11 | int new_end = rx_end+1; |
||
12 | if (new_end == RX_BUFFER_SIZE) {
|
||
13 | new_end = 0;
|
||
14 | } |
||
15 | if (new_end == rx_start) {
|
||
16 | // TODO warn of buffer overflow?
|
||
17 | } else {
|
||
18 | rx_buffer[rx_end] = data; |
||
19 | rx_end = new_end; |
||
20 | } |
||
21 | } |
||
22 | |||
23 | void serial_init() {
|
||
24 | // baud = F_CPU / (8 (UBRR + 1))
|
||
25 | uint16_t ubrr = F_CPU / 8 / BAUD_RATE - 1; |
||
26 | UBRR1H = ubrr >> 8;
|
||
27 | UBRR1L = ubrr; |
||
28 | // UMSEL = 0, asynchronous usart
|
||
29 | // UPM = 0, parity check disabled
|
||
30 | // USBS = 0, 1 stop bit
|
||
31 | // UCSZ = 3, 8-bit
|
||
32 | // U2X = 1, use 8 prescale instead of 16 for a more accurate baud rate
|
||
33 | UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1) | _BV(U2X1); |
||
34 | UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); |
||
35 | } |
||
36 | |||
37 | int serial_read() {
|
||
38 | int ret;
|
||
39 | cli(); |
||
40 | if (rx_start == rx_end) {
|
||
41 | ret = -1;
|
||
42 | } else {
|
||
43 | ret = rx_buffer[rx_start]; |
||
44 | rx_start++; |
||
45 | if (rx_start == RX_BUFFER_SIZE)
|
||
46 | rx_start = 0;
|
||
47 | } |
||
48 | sei(); |
||
49 | return ret;
|
||
50 | } |
||
51 | |||
52 | char serial_read_blocking() {
|
||
53 | int c;
|
||
54 | do {
|
||
55 | c = serial_read(); |
||
56 | } while (c < 0); |
||
57 | return c;
|
||
58 | } |
||
59 | |||
60 | void serial_write(char* data, int length) { |
||
61 | int i;
|
||
62 | for (i = 0; i < length; i++) { |
||
63 | while (!(UCSR1A & _BV(UDRE1)));
|
||
64 | UDR1 = data[i]; |
||
65 | } |
||
66 | } |