-
Notifications
You must be signed in to change notification settings - Fork 0
/
uart.c
93 lines (72 loc) · 2.23 KB
/
uart.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include <avr/interrupt.h>
#include <string.h>
#include "uart.h"
#include "radio.h"
#include "config.h"
#include "system.h"
volatile uart_t uart;
void uart_init()
{
// TODO: What does this?
UCSRC = _BV(URSEL) | _BV(UCSZ1) | _BV(UCSZ0);
// TODO: Not really needed, we know memory is zero on startup
//memset(&uart, '\0', sizeof(uart_t));
/* baudrate set to 1200 */
UBRRH = 0x0;
UBRRL = 0xbf;
/* enable the transceiver and receiver in the uart module */
/* enable Receive Complete and Transceive Complete Interrupt */
UCSRB = _BV(TXEN) | _BV(RXEN) | _BV(RXCIE) | _BV(TXCIE);
/* the radio is connected to us */
radio_init();
}
bool_t uart_putc(uint8_t byte)
{
/* is there any space in the buffer? */
if((uart.tx.write_pos + 1) % UART_FIFO_SIZE == uart.tx.read_pos)
return FALSE;
uart.tx.data[uart.tx.write_pos] = byte;
uart.tx.write_pos = (uart.tx.write_pos + 1) % UART_FIFO_SIZE;
radio_on();
/* ask the uart to notify us when we can put data into it */
UCSRB |= _BV(UDRIE);
return TRUE;
}
uint8_t uart_getc(void)
{
uint8_t data;
/* is the buffer empty */
if(uart.rx.write_pos == uart.rx.read_pos)
{
panic("uart: rx empty");
}
data = uart.rx.data[uart.rx.read_pos];
uart.rx.read_pos = (uart.rx.read_pos + 1) % UART_FIFO_SIZE;
return data;
}
/* Interrupt Service Routines */
ISR(USART_UDRE_vect)
{
/* is this the last byte? */
if((uart.tx.read_pos + 1) % UART_FIFO_SIZE == uart.tx.write_pos)
UCSRB &= ~_BV(UDRIE);
/* put the byte into Uart Data Register */
UDR = uart.tx.data[uart.tx.read_pos];
uart.tx.read_pos = (uart.tx.read_pos + 1) % UART_FIFO_SIZE;
}
ISR(USART_TXC_vect)
{
/* turn of the radio if the buffer is empty */
if(uart.tx.read_pos == uart.tx.write_pos)
radio_off();
}
ISR(USART_RXC_vect)
{
/* throw away the oldest byte if if the fifo is full */
if((uart.rx.write_pos + 1) % UART_FIFO_SIZE == uart.rx.read_pos)
uart.rx.read_pos = (uart.rx.read_pos + 1) % UART_FIFO_SIZE;
uart.rx.data[uart.rx.write_pos] = UDR;
if(uart.rx.data[uart.rx.write_pos] == PROTOCOL_STOPCHAR)
uart.stopchars++;
uart.rx.write_pos = (uart.rx.write_pos + 1) % UART_FIFO_SIZE;
}