-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathusart0.c
120 lines (98 loc) · 2.28 KB
/
usart0.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
/*
serio.c
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include "usart0.h"
#ifndef F_CPU
#define F_CPU 16000000
#endif
#ifndef BAUD_TOL
#define BAUD_TOL 2
#endif
void usart0_init(unsigned long, unsigned char);
void _setbaud(unsigned long);
static inline void _txstart(void);
static inline void _txstop(void);
static inline void _rxstart(void);
static inline void _rxstop(void);
void (*_txcomplete)(char *);
char * buffer;
unsigned char length;
unsigned char position;
void usart0_init(unsigned long baud, unsigned char framedef) {
(void) framedef;
_setbaud(baud);
UCSR0B = 0;
// Set framing, 8N1
UCSR0C = _BV(UCSZ00) | _BV(UCSZ01);
// Enable RX/TX pins
UCSR0B |= _BV(TXEN0) | _BV(RXEN0);
// enable interrupts
_rxstart();
}
void usart0_send(char * b, unsigned long l, void (*cb)(char *)) {
buffer = b;
length = l;
_txcomplete = cb;
position = 0;
_txstart();
}
void _setbaud(unsigned long baud) {
int use2x;
unsigned long div;
div = (((F_CPU) + 8UL * (baud)) / (16UL * (baud)) - 1UL);
if (100 * (F_CPU) > (16 * ((div) + 1)) * (100 * (baud) + (baud) * (BAUD_TOL)))
use2x=1;
else if (100 * (F_CPU) < (16 * ((div) + 1)) * (100 * (baud) - (baud) * (BAUD_TOL)))
use2x = 1;
else
use2x=0;
if (use2x) {
UCSR0A = _BV(U2X2); /* improve baud rate error by using 2x clk */
UBRR0 = (F_CPU / (8UL * baud)) - 1;
}
else
UBRR0 = (F_CPU / (16UL * baud)) - 1;
}
static inline void _txstart() {
UCSR0B |= _BV(UDRIE0); // Turn on UDR empty interrupt
}
static inline void _txstop() {
UCSR0B &= ~(_BV(UDRIE0)); // Turn off UDR empty interrupt
}
static inline void _rxstart() {
UCSR0B |= _BV(RXCIE0); // Turn on RX complete interrupt
}
static inline void _rxstop() {
UCSR0B &= ~(_BV(RXCIE0)); // Turn off RX complete interrupt
}
int usart0_putc(char c, FILE * f) {
(void) f;
while (!(UCSR0A & _BV(UDRE0)));
UDR0 = c;
return 0;
}
int usart0_getc(FILE * f) {
(void) f;
return 0;
}
// USART2 interrupt handlers
ISR(USART0_RX_vect) {
char c = UDR0; // Always read from UDR, otherwise the interrupt will keep firing
(void) c;
// writeb(&_rdbuf, &c, 1);
}
ISR(USART0_TX_vect) {
}
ISR(USART0_UDRE_vect) {
if (buffer && (position < length)) {
UDR0 = buffer[position];
position++;
}
else {
_txstop();
if (_txcomplete) _txcomplete(buffer);
}
}