Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1734 | - | 1 | /************************************************************************* |
2 | Title: Interrupt UART library with receive/transmit circular buffers |
||
3 | Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury |
||
4 | File: $Id: uart.c,v 1.6.2.2 2009/11/29 08:56:12 Peter Exp $ |
||
5 | Software: AVR-GCC 4.1, AVR Libc 1.4.6 or higher |
||
6 | Hardware: any AVR with built-in UART, |
||
7 | License: GNU General Public License |
||
8 | |||
9 | DESCRIPTION: |
||
10 | An interrupt is generated when the UART has finished transmitting or |
||
11 | receiving a byte. The interrupt handling routines use circular buffers |
||
12 | for buffering received and transmitted data. |
||
13 | |||
14 | The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE variables define |
||
15 | the buffer size in bytes. Note that these variables must be a |
||
16 | power of 2. |
||
17 | |||
18 | USAGE: |
||
19 | Refere to the header file uart.h for a description of the routines. |
||
20 | See also example test_uart.c. |
||
21 | |||
22 | NOTES: |
||
23 | Based on Atmel Application Note AVR306 |
||
24 | |||
25 | LICENSE: |
||
26 | Copyright (C) 2006 Peter Fleury |
||
27 | |||
28 | This program is free software; you can redistribute it and/or modify |
||
29 | it under the terms of the GNU General Public License as published by |
||
30 | the Free Software Foundation; either version 2 of the License, or |
||
31 | any later version. |
||
32 | |||
33 | This program is distributed in the hope that it will be useful, |
||
34 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
35 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
36 | GNU General Public License for more details. |
||
37 | |||
38 | *************************************************************************/ |
||
39 | |||
40 | #include <avr/io.h> |
||
41 | #include <avr/interrupt.h> |
||
42 | #include <avr/pgmspace.h> |
||
43 | #include <string.h> |
||
44 | #include <stdbool.h> |
||
45 | #include "uart1.h" |
||
46 | #include "main.h" |
||
47 | #include "bluetooth.h" |
||
48 | #include "tracking.h" |
||
49 | // |
||
50 | // constants and macros |
||
51 | // |
||
52 | #if defined HWVERSION1_3W || defined HWVERSION3_9 |
||
53 | |||
54 | // size of RX/TX buffers |
||
55 | #define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1) |
||
56 | #define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1) |
||
57 | |||
58 | #if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK ) |
||
59 | #error RX buffer size is not a power of 2 |
||
60 | #endif |
||
61 | |||
62 | #if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK ) |
||
63 | #error TX buffer size is not a power of 2 |
||
64 | #endif |
||
65 | |||
66 | |||
67 | // ATmega with two USART |
||
68 | |||
69 | #define ATMEGA_USART1 |
||
70 | |||
71 | #define UART1_STATUS UCSR1A |
||
72 | #define UART1_CONTROL UCSR1B |
||
73 | #define UART1_DATA UDR1 |
||
74 | #define UART1_UDRIE UDRIE1 |
||
75 | |||
76 | |||
77 | |||
78 | // |
||
79 | // module global variables |
||
80 | // |
||
81 | |||
82 | uint8_t receiveNMEA = false; |
||
83 | |||
84 | |||
85 | #if defined( ATMEGA_USART1 ) |
||
86 | static volatile unsigned char UART1_TxBuf[UART_TX_BUFFER_SIZE]; |
||
87 | static volatile unsigned char UART1_RxBuf[UART_RX_BUFFER_SIZE]; |
||
88 | static volatile unsigned char UART1_TxHead; |
||
89 | static volatile unsigned char UART1_TxTail; |
||
90 | static volatile unsigned char UART1_RxHead; |
||
91 | static volatile unsigned char UART1_RxTail; |
||
92 | static volatile unsigned char UART1_LastRxError; |
||
93 | #endif |
||
94 | |||
95 | |||
96 | |||
97 | |||
98 | // |
||
99 | // these functions are only for ATmegas with two USART |
||
100 | // |
||
101 | |||
102 | |||
103 | #if defined( ATMEGA_USART1 ) |
||
104 | |||
105 | //-------------------------------------------------------------- |
||
106 | // Function: UART1 Receive Complete interrupt |
||
107 | // Purpose: called when the UART1 has received a character |
||
108 | //-------------------------------------------------------------- |
||
109 | ISR(USART1_RX_vect) |
||
110 | { |
||
111 | unsigned char tmphead; |
||
112 | unsigned char data; |
||
113 | unsigned char usr; |
||
114 | unsigned char lastRxError; |
||
115 | |||
116 | |||
117 | // read UART status register and UART data register |
||
118 | usr = UART1_STATUS; |
||
119 | data = UART1_DATA; |
||
120 | |||
121 | lastRxError = (usr & (_BV(FE1)|_BV(DOR1)) ); |
||
122 | |||
123 | // calculate buffer index |
||
124 | tmphead = ( UART1_RxHead + 1) & UART_RX_BUFFER_MASK; |
||
125 | |||
126 | if ( tmphead == UART1_RxTail ) |
||
127 | { |
||
128 | // error: receive buffer overflow |
||
129 | lastRxError = UART_BUFFER_OVERFLOW >> 8; |
||
130 | } |
||
131 | else |
||
132 | { |
||
133 | // store new index |
||
134 | UART1_RxHead = tmphead; |
||
135 | // store received data in buffer |
||
136 | UART1_RxBuf[tmphead] = data; |
||
137 | } |
||
138 | UART1_LastRxError = lastRxError; |
||
139 | |||
140 | #if defined HWVERSION3_9 |
||
141 | |||
142 | if (receiveNMEA==true) |
||
143 | { |
||
144 | if (bt_receiveNMEA()) Tracking_NMEA(); |
||
145 | |||
146 | } |
||
147 | #endif |
||
148 | } |
||
149 | |||
150 | |||
151 | //-------------------------------------------------------------- |
||
152 | // Function: UART1 Data Register Empty interrupt |
||
153 | // Purpose: called when the UART1 is ready to transmit the next byte |
||
154 | //-------------------------------------------------------------- |
||
155 | ISR(USART1_UDRE_vect) |
||
156 | { |
||
157 | unsigned char tmptail; |
||
158 | |||
159 | |||
160 | if ( UART1_TxHead != UART1_TxTail) |
||
161 | { |
||
162 | // calculate and store new buffer index |
||
163 | tmptail = (UART1_TxTail + 1) & UART_TX_BUFFER_MASK; |
||
164 | UART1_TxTail = tmptail; |
||
165 | // get one byte from buffer and write it to UART |
||
166 | UART1_DATA = UART1_TxBuf[tmptail]; // start transmission |
||
167 | } |
||
168 | else |
||
169 | { |
||
170 | // tx buffer empty, disable UDRE interrupt |
||
171 | UART1_CONTROL &= ~_BV(UART1_UDRIE); |
||
172 | } |
||
173 | } |
||
174 | |||
175 | |||
176 | //-------------------------------------------------------------- |
||
177 | // Function: uart1_init() |
||
178 | // Purpose: initialize UART1 and set baudrate |
||
179 | // Input: baudrate using macro UART_BAUD_SELECT() |
||
180 | // Returns: none |
||
181 | //-------------------------------------------------------------- |
||
182 | void uart1_init(unsigned int baudrate) |
||
183 | { |
||
184 | UART1_TxHead = 0; |
||
185 | UART1_TxTail = 0; |
||
186 | UART1_RxHead = 0; |
||
187 | UART1_RxTail = 0; |
||
188 | |||
189 | |||
190 | // Set baud rate |
||
191 | if ( baudrate & 0x8000 ) |
||
192 | { |
||
193 | UART1_STATUS = (1<<U2X1); //Enable 2x speed |
||
194 | baudrate &= ~0x8000; |
||
195 | } |
||
196 | UBRR1H = (unsigned char)(baudrate>>8); |
||
197 | UBRR1L = (unsigned char) baudrate; |
||
198 | |||
199 | // Enable USART receiver and transmitter and receive complete interrupt |
||
200 | UART1_CONTROL = _BV(RXCIE1)|(1<<RXEN1)|(1<<TXEN1); |
||
201 | |||
202 | // Set frame format: asynchronous, 8data, no parity, 1stop bit |
||
203 | #ifdef URSEL1 |
||
204 | UCSR1C = (1<<URSEL1)|(3<<UCSZ10); |
||
205 | #else |
||
206 | UCSR1C = (3<<UCSZ10); |
||
207 | |||
208 | |||
209 | #endif |
||
210 | } |
||
211 | |||
212 | |||
213 | //-------------------------------------------------------------- |
||
214 | // Function: uart1_getc() |
||
215 | // Purpose: return byte from ringbuffer |
||
216 | // Returns: lower byte: received byte from ringbuffer |
||
217 | // higher byte: last receive error |
||
218 | //-------------------------------------------------------------- |
||
219 | unsigned int uart1_getc(void) |
||
220 | { |
||
221 | unsigned char tmptail; |
||
222 | unsigned char data; |
||
223 | |||
224 | |||
225 | if ( UART1_RxHead == UART1_RxTail ) |
||
226 | { |
||
227 | return UART_NO_DATA; // no data available |
||
228 | } |
||
229 | |||
230 | // calculate /store buffer index |
||
231 | tmptail = (UART1_RxTail + 1) & UART_RX_BUFFER_MASK; |
||
232 | UART1_RxTail = tmptail; |
||
233 | |||
234 | // get data from receive buffer |
||
235 | data = UART1_RxBuf[tmptail]; |
||
236 | |||
237 | return (UART1_LastRxError << 8) + data; |
||
238 | |||
239 | } |
||
240 | |||
241 | |||
242 | //-------------------------------------------------------------- |
||
243 | // Function: uart1_putc() |
||
244 | // Purpose: write byte to ringbuffer for transmitting via UART |
||
245 | // Input: byte to be transmitted |
||
246 | // Returns: 1 on succes, 0 if remote not ready |
||
247 | //-------------------------------------------------------------- |
||
248 | int uart1_putc(unsigned char data) |
||
249 | { |
||
250 | unsigned char tmphead; |
||
251 | |||
252 | |||
253 | tmphead = (UART1_TxHead + 1) & UART_TX_BUFFER_MASK; |
||
254 | |||
255 | while ( tmphead == UART1_TxTail ) |
||
256 | {;} // wait for free space in buffer |
||
257 | |||
258 | UART1_TxBuf[tmphead] = data; |
||
259 | UART1_TxHead = tmphead; |
||
260 | |||
261 | // enable UDRE interrupt |
||
262 | UART1_CONTROL |= _BV(UART1_UDRIE); |
||
263 | return (UART1_LastRxError << 8) + data; |
||
264 | } |
||
265 | |||
266 | |||
267 | //-------------------------------------------------------------- |
||
268 | // Function: uart1_puts() |
||
269 | // Purpose: transmit string to UART1 |
||
270 | // Input: string to be transmitted |
||
271 | // Returns: none |
||
272 | //-------------------------------------------------------------- |
||
273 | void uart1_puts(const char *s ) |
||
274 | { |
||
275 | while (*s) |
||
276 | uart1_putc(*s++); |
||
277 | } |
||
278 | |||
279 | |||
280 | //-------------------------------------------------------------- |
||
281 | // Function: uart1_puts_p() |
||
282 | // Purpose: transmit string from program memory to UART1 |
||
283 | // Input: program memory string to be transmitted |
||
284 | // Returns: none |
||
285 | //-------------------------------------------------------------- |
||
286 | void uart1_puts_p(const char *progmem_s ) |
||
287 | { |
||
288 | register char c; |
||
289 | while ( (c = pgm_read_byte(progmem_s++)) ) |
||
290 | uart1_putc(c); |
||
291 | } |
||
292 | |||
293 | |||
294 | //-------------------------------------------------------------- |
||
295 | // Function: uart1_available() |
||
296 | // Purpose: Determine the number of bytes waiting in the receive buffer |
||
297 | // Input: None |
||
298 | // Returns: Integer number of bytes in the receive buffer |
||
299 | //-------------------------------------------------------------- |
||
300 | int uart1_available(void) |
||
301 | { |
||
302 | return (UART_RX_BUFFER_MASK + UART1_RxHead - UART1_RxTail) % UART_RX_BUFFER_MASK; |
||
303 | } |
||
304 | |||
305 | |||
306 | |||
307 | //-------------------------------------------------------------- |
||
308 | // Function: uart1_flush() |
||
309 | // Purpose: Flush bytes waiting the receive buffer. Acutally ignores them. |
||
310 | // Input: None |
||
311 | // Returns: None |
||
312 | //-------------------------------------------------------------- |
||
313 | void uart1_flush(void) |
||
314 | { |
||
315 | UART1_RxHead = UART1_RxTail; |
||
316 | } |
||
317 | |||
318 | |||
319 | |||
320 | |||
321 | |||
322 | |||
323 | |||
324 | |||
325 | |||
326 | #endif |
||
327 | #endif |
||
328 |