Subversion Repositories svnkaklik

Rev

Go to most recent revision | Details | Last modification | View Log

Rev Author Line No. Line
507 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
}