Rev Author Line No. Line
1145 kaklik 1 /*! \file uart.c \brief UART driver with buffer support. */
2 // *****************************************************************************
3 //
4 // File Name : 'uart.c'
5 // Title : UART driver with buffer support
6 // Author : Pascal Stang - Copyright (C) 2000-2002
7 // Created : 11/22/2000
8 // Revised : 06/09/2003
9 // Version : 1.3
10 // Target MCU : ATMEL AVR Series
11 // Editor Tabs : 4
12 //
13 // This code is distributed under the GNU Public License
14 // which can be found at http://www.gnu.org/licenses/gpl.txt
15 //
16 // *****************************************************************************
17  
18 #include <avr/io.h>
19 #include <avr/interrupt.h>
20  
21 #include "buffer.h"
22 #include "uart.h"
23  
24 // UART global variables
25 // flag variables
26 volatile u08 uartReadyTx; ///< uartReadyTx flag
27 volatile u08 uartBufferedTx; ///< uartBufferedTx flag
28 // receive and transmit buffers
29 cBuffer uartRxBuffer; ///< uart receive buffer
30 cBuffer uartTxBuffer; ///< uart transmit buffer
31 unsigned short uartRxOverflow; ///< receive overflow counter
32  
33 #ifndef UART_BUFFERS_EXTERNAL_RAM
34 // using internal ram,
35 // automatically allocate space in ram for each buffer
36 static char uartRxData[UART_RX_BUFFER_SIZE];
37 static char uartTxData[UART_TX_BUFFER_SIZE];
38 #endif
39  
40 typedef void (*voidFuncPtru08)(unsigned char);
41 volatile static voidFuncPtru08 UartRxFunc;
42  
43 // enable and initialize the uart
44 void uartInit(void)
45 {
46 // initialize the buffers
47 uartInitBuffers();
48 // initialize user receive handler
49 UartRxFunc = 0;
50  
51 // enable RxD/TxD and interrupts
52 outb(UCR, BV(RXCIE)|BV(TXCIE)|BV(RXEN)|BV(TXEN));
53  
54 // set default baud rate
55 uartSetBaudRate(UART_DEFAULT_BAUD_RATE);
56 // initialize states
57 uartReadyTx = TRUE;
58 uartBufferedTx = FALSE;
59 // clear overflow count
60 uartRxOverflow = 0;
61 // enable interrupts
62 sei();
63 }
64  
65 // create and initialize the uart transmit and receive buffers
66 void uartInitBuffers(void)
67 {
68 #ifndef UART_BUFFERS_EXTERNAL_RAM
69 // initialize the UART receive buffer
70 bufferInit(&uartRxBuffer, uartRxData, UART_RX_BUFFER_SIZE);
71 // initialize the UART transmit buffer
72 bufferInit(&uartTxBuffer, uartTxData, UART_TX_BUFFER_SIZE);
73 #else
74 // initialize the UART receive buffer
75 bufferInit(&uartRxBuffer, (u08*) UART_RX_BUFFER_ADDR, UART_RX_BUFFER_SIZE);
76 // initialize the UART transmit buffer
77 bufferInit(&uartTxBuffer, (u08*) UART_TX_BUFFER_ADDR, UART_TX_BUFFER_SIZE);
78 #endif
79 }
80  
81 // redirects received data to a user function
82 void uartSetRxHandler(void (*rx_func)(unsigned char c))
83 {
84 // set the receive interrupt to run the supplied user function
85 UartRxFunc = rx_func;
86 }
87  
88 // set the uart baud rate
89 void uartSetBaudRate(u32 baudrate)
90 {
91 // calculate division factor for requested baud rate, and set it
92 u16 bauddiv = ((F_CPU+(baudrate*8L))/(baudrate*16L)-1);
93 outb(UBRRL, bauddiv);
94 #ifdef UBRRH
95 outb(UBRRH, bauddiv>>8);
96 #endif
97 }
98  
99 // returns the receive buffer structure
100 cBuffer* uartGetRxBuffer(void)
101 {
102 // return rx buffer pointer
103 return &uartRxBuffer;
104 }
105  
106 // returns the transmit buffer structure
107 cBuffer* uartGetTxBuffer(void)
108 {
109 // return tx buffer pointer
110 return &uartTxBuffer;
111 }
112  
113 // transmits a byte over the uart
114 void uartSendByte(u08 txData)
115 {
116 // wait for the transmitter to be ready
117 while(!uartReadyTx);
118 // send byte
119 outb(UDR, txData);
120 // set ready state to FALSE
121 uartReadyTx = FALSE;
122 }
123  
124 // gets a single byte from the uart receive buffer (getchar-style)
125 int uartGetByte(void)
126 {
127 u08 c;
128 if(uartReceiveByte(&c))
129 return c;
130 else
131 return -1;
132 }
133  
134 // gets a byte (if available) from the uart receive buffer
135 u08 uartReceiveByte(u08* rxData)
136 {
137 // make sure we have a receive buffer
138 if(uartRxBuffer.size)
139 {
140 // make sure we have data
141 if(uartRxBuffer.datalength)
142 {
143 // get byte from beginning of buffer
144 *rxData = bufferGetFromFront(&uartRxBuffer);
145 return TRUE;
146 }
147 else
148 {
149 // no data
150 return FALSE;
151 }
152 }
153 else
154 {
155 // no buffer
156 return FALSE;
157 }
158 }
159  
160 // flush all data out of the receive buffer
161 void uartFlushReceiveBuffer(void)
162 {
163 // flush all data from receive buffer
164 //bufferFlush(&uartRxBuffer);
165 // same effect as above
166 uartRxBuffer.datalength = 0;
167 }
168  
169 // return true if uart receive buffer is empty
170 u08 uartReceiveBufferIsEmpty(void)
171 {
172 if(uartRxBuffer.datalength == 0)
173 {
174 return TRUE;
175 }
176 else
177 {
178 return FALSE;
179 }
180 }
181  
182 // add byte to end of uart Tx buffer
183 u08 uartAddToTxBuffer(u08 data)
184 {
185 // add data byte to the end of the tx buffer
186 return bufferAddToEnd(&uartTxBuffer, data);
187 }
188  
189 // start transmission of the current uart Tx buffer contents
190 void uartSendTxBuffer(void)
191 {
192 // turn on buffered transmit
193 uartBufferedTx = TRUE;
194 // send the first byte to get things going by interrupts
195 uartSendByte(bufferGetFromFront(&uartTxBuffer));
196 }
197 /*
198 // transmit nBytes from buffer out the uart
199 u08 uartSendBuffer(char *buffer, u16 nBytes)
200 {
201 register u08 first;
202 register u16 i;
203  
204 // check if there's space (and that we have any bytes to send at all)
205 if((uartTxBuffer.datalength + nBytes < uartTxBuffer.size) && nBytes)
206 {
207 // grab first character
208 first = *buffer++;
209 // copy user buffer to uart transmit buffer
210 for(i = 0; i < nBytes-1; i++)
211 {
212 // put data bytes at end of buffer
213 bufferAddToEnd(&uartTxBuffer, *buffer++);
214 }
215  
216 // send the first byte to get things going by interrupts
217 uartBufferedTx = TRUE;
218 uartSendByte(first);
219 // return success
220 return TRUE;
221 }
222 else
223 {
224 // return failure
225 return FALSE;
226 }
227 }
228 */
229 // UART Transmit Complete Interrupt Handler
230 UART_INTERRUPT_HANDLER(SIG_UART_TRANS)
231 {
232 // check if buffered tx is enabled
233 if(uartBufferedTx)
234 {
235 // check if there's data left in the buffer
236 if(uartTxBuffer.datalength)
237 {
238 // send byte from top of buffer
239 outb(UDR, bufferGetFromFront(&uartTxBuffer));
240 }
241 else
242 {
243 // no data left
244 uartBufferedTx = FALSE;
245 // return to ready state
246 uartReadyTx = TRUE;
247 }
248 }
249 else
250 {
251 // we're using single-byte tx mode
252 // indicate transmit complete, back to ready
253 uartReadyTx = TRUE;
254 }
255 }
256  
257 // UART Receive Complete Interrupt Handler
258 UART_INTERRUPT_HANDLER(SIG_UART_RECV)
259 {
260 u08 c;
261  
262 // get received char
263 c = inb(UDR);
264  
265 // if there's a user function to handle this receive event
266 if(UartRxFunc)
267 {
268 // call it and pass the received data
269 UartRxFunc(c);
270 }
271 else
272 {
273 // otherwise do default processing
274 // put received char in buffer
275 // check if there's space
276 if( !bufferAddToEnd(&uartRxBuffer, c) )
277 {
278 // no space in buffer
279 // count overflow
280 uartRxOverflow++;
281 }
282 }
283 }