root / toolbox / serial.c @ a7a56246
History | View | Annotate | Download (1.29 KB)
1 |
#include "serial.h" |
---|---|
2 |
#include <avr/io.h> |
3 |
#include <avr/interrupt.h> |
4 |
|
5 |
static int rx_start = 0, rx_end = 0; |
6 |
static char rx_buffer[RX_BUFFER_SIZE]; |
7 |
|
8 |
ISR(USART1_RX_vect) { |
9 |
char data = UDR1;
|
10 |
int new_end = rx_end+1; |
11 |
if (new_end == RX_BUFFER_SIZE) {
|
12 |
new_end = 0;
|
13 |
} |
14 |
if (new_end == rx_start) {
|
15 |
// TODO warn of buffer overflow?
|
16 |
} else {
|
17 |
rx_buffer[rx_end] = data; |
18 |
rx_end = new_end; |
19 |
} |
20 |
} |
21 |
|
22 |
void serial_init() {
|
23 |
// baud = F_CPU / (8 (UBRR + 1))
|
24 |
uint16_t ubrr = F_CPU / 8 / BAUD_RATE - 1; |
25 |
UBRR1H = ubrr >> 8;
|
26 |
UBRR1L = ubrr; |
27 |
// UMSEL = 0, asynchronous usart
|
28 |
// UPM = 0, parity check disabled
|
29 |
// USBS = 0, 1 stop bit
|
30 |
// UCSZ = 3, 8-bit
|
31 |
// U2X = 1, use 8 prescale instead of 16 for a more accurate baud rate
|
32 |
UCSR1A = _BV(U2X1); |
33 |
UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1); |
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 |
} |