-
Notifications
You must be signed in to change notification settings - Fork 0
/
uart.c
130 lines (94 loc) · 1.81 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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*------------------------------------------------*/
/* UART functions */
#include <avr/io.h>
#include <avr/interrupt.h>
#include "uart.h"
#define SYSCLK 8000000
#define BAUD 57600
typedef struct _fifo {
uint8_t idx_w;
uint8_t idx_r;
uint8_t count;
uint8_t buff[64];
} FIFO;
static volatile
FIFO txfifo, rxfifo;
/* Initialize UART */
void uart_init()
{
rxfifo.idx_r = 0;
rxfifo.idx_w = 0;
rxfifo.count = 0;
txfifo.idx_r = 0;
txfifo.idx_w = 0;
txfifo.count = 0;
UCSR0A = _BV(U2X0);
UCSR0B = _BV(RXEN0)|_BV(RXCIE0)|_BV(TXEN0);
UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
UBRR0L = (uint8_t)( (SYSCLK + BAUD * 4L) / (BAUD * 8L) - 1 );
}
/* Get a received character */
uint8_t uart_test ()
{
return rxfifo.count;
}
uint8_t uart_get ()
{
uint8_t d, i;
i = rxfifo.idx_r;
while(rxfifo.count == 0);
d = rxfifo.buff[i++];
cli();
rxfifo.count--;
sei();
if(i >= sizeof(rxfifo.buff))
i = 0;
rxfifo.idx_r = i;
return d;
}
/* Put a character to transmit */
void uart_put (uint8_t d)
{
uint8_t i;
i = txfifo.idx_w;
while(txfifo.count >= sizeof(txfifo.buff));
txfifo.buff[i++] = d;
cli();
txfifo.count++;
UCSR0B = _BV(RXEN0)|_BV(RXCIE0)|_BV(TXEN0)|_BV(UDRIE0);
sei();
if(i >= sizeof(txfifo.buff))
i = 0;
txfifo.idx_w = i;
}
/* UART RXC interrupt */
SIGNAL(USART_RX_vect)
{
uint8_t d, n, i;
d = UDR0;
n = rxfifo.count;
if(n < sizeof(rxfifo.buff)) {
rxfifo.count = ++n;
i = rxfifo.idx_w;
rxfifo.buff[i++] = d;
if(i >= sizeof(rxfifo.buff))
i = 0;
rxfifo.idx_w = i;
}
}
/* UART UDRE interrupt */
SIGNAL(USART_UDRE_vect)
{
uint8_t n, i;
n = txfifo.count;
if(n) {
txfifo.count = --n;
i = txfifo.idx_r;
UDR0 = txfifo.buff[i++];
if(i >= sizeof(txfifo.buff))
i = 0;
txfifo.idx_r = i;
}
if(n == 0)
UCSR0B = _BV(RXEN0)|_BV(RXCIE0)|_BV(TXEN0);
}