author | Tero Marttila <terom@paivola.fi> |
Sat, 07 Jun 2014 16:22:56 +0300 | |
changeset 95 | 478b9d0485aa |
parent 69 | ef9fe98ebf72 |
permissions | -rw-r--r-- |
53
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
1 |
/** Serial modes */ |
52
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
2 |
static enum { |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
3 |
SERIAL_MODE_ASYNC = 0b00, |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
4 |
} serial_mode = SERIAL_MODE_ASYNC; |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
5 |
|
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
6 |
static enum { |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
7 |
SERIAL_BAUD_9600 = 103, |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
8 |
} serial_baud = SERIAL_BAUD_9600; |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
9 |
|
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
10 |
static enum { |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
11 |
SERIAL_PARITY_N = 0b00, |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
12 |
} serial_parity = SERIAL_PARITY_N; |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
13 |
|
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
14 |
static enum { |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
15 |
SERIAL_STOPBITS_1 = 0b0, |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
16 |
} serial_stopbits = SERIAL_STOPBITS_1; |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
17 |
|
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
18 |
static enum { |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
19 |
SERIAL_CHARS_8 = 0b011, |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
20 |
} serial_chars = SERIAL_CHARS_8; |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
21 |
|
53
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
22 |
/** Serial state */ |
69 | 23 |
#define SERIAL_BUF 64 |
24 |
||
25 |
struct serial { |
|
26 |
char buf[SERIAL_BUF]; |
|
27 |
byte in, out; |
|
28 |
} serial_rx; |
|
29 |
||
53
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
30 |
char serial_tx = 0; |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
31 |
|
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
32 |
void serial_enable (char rx, char tx); |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
33 |
|
52
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
34 |
/* |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
35 |
* Setup the UART for serial mode. |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
36 |
*/ |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
37 |
void serial_init () |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
38 |
{ |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
39 |
UCSR0A = ( |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
40 |
// Double the USART Transmission Speed |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
41 |
(0b0 << U2X0) // single speed |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
42 |
|
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
43 |
// Multi-processor Communication Mode |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
44 |
| (0b0 << MPCM0) // off |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
45 |
); |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
46 |
UCSR0B = ( |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
47 |
// Character Size |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
48 |
((serial_chars >> 2) << UCSZ02) // standard character sizes |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
49 |
); |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
50 |
UCSR0C = ( |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
51 |
// USART Mode Select |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
52 |
(serial_mode << UMSEL00) // async |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
53 |
|
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
54 |
// Parity Mode |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
55 |
| (serial_parity << UPM00) |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
56 |
|
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
57 |
// Stop Bit Select |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
58 |
| (serial_stopbits << USBS0) |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
59 |
|
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
60 |
// Character Size |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
61 |
| ((serial_chars & 0b11) << UCSZ00) |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
62 |
|
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
63 |
// Clock Polarity |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
64 |
| (0b0 << UCPOL0) |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
65 |
); |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
66 |
UBRR0 = serial_baud; |
53
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
67 |
|
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
68 |
// active RX, idle TX |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
69 |
serial_enable(1, 0); |
52
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
70 |
} |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
71 |
|
53
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
72 |
void serial_enable (char rx, char tx) |
52
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
73 |
{ |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
74 |
UCSR0B = ( |
53
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
75 |
// RX Complete Interrupt Enable |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
76 |
(!!rx << RXCIE0) |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
77 |
|
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
78 |
// USART Data Register Empty Interrupt Enable |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
79 |
| (!!tx << UDRIE0) |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
80 |
|
52
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
81 |
// Receiver Enable |
53
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
82 |
| (0b1 << RXEN0) // enabled |
52
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
83 |
|
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
84 |
// Transmitter Enable |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
85 |
| (0b1 << TXEN0) // enabled |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
86 |
|
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
87 |
// Character Size |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
88 |
| ((serial_chars >> 2) << UCSZ02) // standard character sizes |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
89 |
); |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
90 |
} |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
91 |
|
53
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
92 |
/* |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
93 |
* Read incoming into buffer. |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
94 |
*/ |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
95 |
ISR(USART_RX_vect) |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
96 |
{ |
69 | 97 |
serial_rx.buf[serial_rx.in++] = UDR0; |
98 |
||
99 |
if (serial_rx.in >= SERIAL_BUF) |
|
100 |
serial_rx.in = 0; |
|
53
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
101 |
} |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
102 |
|
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
103 |
/* |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
104 |
* Write outgoing buffer. |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
105 |
*/ |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
106 |
ISR(USART_UDRE_vect) |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
107 |
{ |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
108 |
UDR0 = serial_tx; |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
109 |
|
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
110 |
// tx buffer consumed |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
111 |
serial_tx = 0; |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
112 |
|
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
113 |
// idle tx |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
114 |
serial_enable(1, 0); |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
115 |
} |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
116 |
|
52
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
117 |
char serial_read () |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
118 |
{ |
69 | 119 |
if (serial_rx.out == serial_rx.in) |
120 |
return 0; |
|
52
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
121 |
|
69 | 122 |
char rx = serial_rx.buf[serial_rx.out++]; |
123 |
||
124 |
if (serial_rx.out >= SERIAL_BUF) |
|
125 |
serial_rx.out = 0; |
|
53
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
126 |
|
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
127 |
return rx; |
52
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
128 |
} |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
129 |
|
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
130 |
void serial_write (char c) |
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
131 |
{ |
53
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
132 |
// XXX: atomic? |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
133 |
if (tbi(&UCSR0A, UDRE0)) { |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
134 |
// direct |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
135 |
UDR0 = c; |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
136 |
} else { |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
137 |
// buffered |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
138 |
serial_tx = c; |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
139 |
serial_enable(1, 1); |
dfe67409fbcd
hello: interruptable timer sleep, with buffered serial IO
Tero Marttila <terom@paivola.fi>
parents:
52
diff
changeset
|
140 |
} |
52
237d1f5c1c32
hello: split out timer; add serial
Tero Marttila <terom@paivola.fi>
parents:
diff
changeset
|
141 |
} |