?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 6

Line No. Rev Author Line
1 6 kaklik /*! \file uartsw2.c \brief Interrupt-driven Software UART Driver. */
2 //*****************************************************************************
3 //
4 // File Name : 'uartsw2.c'
5 // Title : Interrupt-driven Software UART Driver
6 // Author : Pascal Stang - Copyright (C) 2002-2004
7 // Created : 7/20/2002
8 // Revised : 4/27/2004
9 // Version : 0.6
10 // Target MCU : Atmel AVR Series (intended for the ATmega16 and ATmega32)
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 "global.h"
22 #include "timer128.h"
23 #include "uartsw128.h"
24  
25 // Program ROM constants
26  
27 // Global variables
28  
29 // uartsw transmit status and data variables
30 static volatile u08 UartswTxBusy;
31 static volatile u08 UartswTxData;
32 static volatile u08 UartswTxBitNum;
33  
34 // baud rate common to transmit and receive
35 static volatile u08 UartswBaudRateDiv;
36  
37 // uartsw receive status and data variables
38 static volatile u08 UartswRxBusy;
39 static volatile u08 UartswRxData;
40 static volatile u08 UartswRxBitNum;
41 // receive buffer
42 static cBuffer uartswRxBuffer; ///< uartsw receive buffer
43 // automatically allocate space in ram for each buffer
44 static char uartswRxData[UARTSW_RX_BUFFER_SIZE];
45  
46 // functions
47  
48 //! enable and initialize the software uart
49 void uartswInit(void)
50 {
51 // initialize the buffers
52 uartswInitBuffers();
53 // initialize the ports
54 sbi(UARTSW_TX_DDR, UARTSW_TX_PIN);
55 cbi(UARTSW_RX_DDR, UARTSW_RX_PIN);
56 cbi(UARTSW_RX_PORT, UARTSW_RX_PIN);
57 // initialize baud rate
58 uartswSetBaudRate(9600);
59  
60 // setup the transmitter
61 UartswTxBusy = FALSE;
62 // disable OC2 interrupt
63 cbi(TIMSK, OCIE2);
64 // attach TxBit service routine to OC2
65 timerAttach(TIMER2OUTCOMPARE_INT, uartswTxBitService);
66  
67 // setup the receiver
68 UartswRxBusy = FALSE;
69 // disable OC0 interrupt
70 cbi(TIMSK, OCIE0);
71 // attach RxBit service routine to OC0
72 timerAttach(TIMER0OUTCOMPARE_INT, uartswRxBitService);
73 // INT2 trigger on rising edge
74 sbi(EICRA, ISC20);
75 // enable INT2 interrupt
76 sbi(EIMSK, INT2);
77  
78 // turn on interrupts
79 sei();
80 }
81  
82 //! create and initialize the uart buffers
83 void uartswInitBuffers(void)
84 {
85 // initialize the UART receive buffer
86 bufferInit(&uartswRxBuffer, uartswRxData, UARTSW_RX_BUFFER_SIZE);
87 }
88  
89 //! turns off software UART
90 void uartswOff(void)
91 {
92 // disable interrupts
93 cbi(TIMSK, OCIE2);
94 cbi(TIMSK, OCIE0);
95 cbi(EIMSK, INT2);
96 // detach the service routines
97 timerDetach(TIMER2OUTCOMPARE_INT);
98 timerDetach(TIMER0OUTCOMPARE_INT);
99 }
100  
101 void uartswSetBaudRate(u32 baudrate)
102 {
103 u16 div;
104  
105 // set timer prescaler
106 if( baudrate > (F_CPU/64L*256L) )
107 //CHANGE THE ABOVE LINE IF CLOCK FREQ OF AVRLINX BOARD DIFFERS
108 //FROM AVRSAT
109 {
110 // if the requested baud rate is high,
111 // set timer prescalers to div-by-64
112 timer2SetPrescaler(TIMERRTC_CLK_DIV64);
113 timer0SetPrescaler(TIMER_CLK_DIV64);
114 div = 64;
115 }
116 else
117 {
118 // if the requested baud rate is low,
119 // set timer prescalers to div-by-256
120 timer2SetPrescaler(TIMERRTC_CLK_DIV256);
121 timer0SetPrescaler(TIMER_CLK_DIV256);
122 div = 256;
123 }
124  
125 // calculate division factor for requested baud rate, and set it
126 //UartswBaudRateDiv = (u08)(((F_CPU/64L)+(baudrate/2L))/(baudrate*1L));
127 //UartswBaudRateDiv = (u08)(((F_CPU/256L)+(baudrate/2L))/(baudrate*1L));
128 UartswBaudRateDiv = (u08)(((F_CPU/div)+(baudrate/2L))/(baudrate*1L));
129 }
130  
131 //! returns the receive buffer structure
132 cBuffer* uartswGetRxBuffer(void)
133 {
134 // return rx buffer pointer
135 return &uartswRxBuffer;
136 }
137  
138 void uartswSendByte(u08 data)
139 {
140 // wait until uart is ready
141 while(UartswTxBusy);
142 // set busy flag
143 UartswTxBusy = TRUE;
144 // save data
145 UartswTxData = data;
146 // set number of bits (+1 for stop bit)
147 UartswTxBitNum = 9;
148  
149 // set the start bit
150 cbi(UARTSW_TX_PORT, UARTSW_TX_PIN);//changed to cbi -JGM
151 // schedule the next bit
152 outb(OCR2, inb(TCNT2) + UartswBaudRateDiv);
153 // enable OC2 interrupt
154 sbi(TIMSK, OCIE2);
155 }
156  
157 //! gets a byte (if available) from the uart receive buffer
158 u08 uartswReceiveByte(u08* rxData)
159 {
160 // make sure we have a receive buffer
161 if(uartswRxBuffer.size)
162 {
163 // make sure we have data
164 if(uartswRxBuffer.datalength)
165 {
166 // get byte from beginning of buffer
167 *rxData = bufferGetFromFront(&uartswRxBuffer);
168 return TRUE;
169 }
170 else
171 {
172 // no data
173 return FALSE;
174 }
175 }
176 else
177 {
178 // no buffer
179 return FALSE;
180 }
181 }
182  
183 void uartswTxBitService(void)
184 {
185 if(UartswTxBitNum)
186 {
187 // there are bits still waiting to be transmitted
188 if(UartswTxBitNum > 1)
189 {
190 // transmit data bits (inverted, LSB first)
191 if( !(UartswTxData & 0x01) )
192 cbi(UARTSW_TX_PORT, UARTSW_TX_PIN);//changed to cbi -JGM
193 else
194 sbi(UARTSW_TX_PORT, UARTSW_TX_PIN);//changed to sbi -JGM
195 // shift bits down
196 UartswTxData = UartswTxData>>1;
197 }
198 else
199 {
200 // transmit stop bit
201 sbi(UARTSW_TX_PORT, UARTSW_TX_PIN);//changed to sbi -JGM
202 }
203 // schedule the next bit
204 outb(OCR2, inb(OCR2) + UartswBaudRateDiv); //WHAT IS INB?
205 // count down
206 UartswTxBitNum--;
207 }
208 else
209 {
210 // transmission is done
211 // clear busy flag
212 UartswTxBusy = FALSE;
213 // disable OC2 interrupt
214 cbi(TIMSK, OCIE2);
215 }
216 }
217  
218 void uartswRxBitService(void)
219 {
220 // this function runs on either:
221 // - a rising edge interrupt
222 // - Timer 0 output compare
223 if(!UartswRxBusy)
224 {
225 // UART was not previously busy,
226 // this must be is a start bit
227  
228 // disable INT2 interrupt
229 cbi(EIMSK, INT2);
230 // schedule data bit sampling 1.5 bit periods from now
231 outb(OCR0, inb(TCNT0) + UartswBaudRateDiv + UartswBaudRateDiv/2);
232 // clear OC0 interrupt flag
233 sbi(TIFR, OCF0);
234 // enable OC0 interrupt
235 sbi(TIMSK, OCIE0);
236 // set busy flag
237 UartswRxBusy = TRUE;
238 // reset bit counter
239 UartswRxBitNum = 0;
240 // reset data
241 UartswRxData = 0;
242 }
243 else
244 {
245 // start bit has already been received
246 // we're in the data bits
247  
248 // shift data byte to make room for new bit
249 UartswRxData = UartswRxData>>1;
250  
251 // sample the data line
252 if((inb(UARTSW_RX_PORTIN) & (1<<UARTSW_RX_PIN)) ) //Removed ! condition -JGM
253 {
254 // serial line is low
255 // record '1' bit (data inverted)
256 UartswRxData |= 0x80;
257 }
258  
259 // increment bit counter
260 UartswRxBitNum++;
261 // schedule next bit sample
262 outb(OCR0, inb(OCR0) + UartswBaudRateDiv);
263  
264 // check if we have a full byte
265 if(UartswRxBitNum >= 8)
266 {
267 // save data in receive buffer
268 bufferAddToEnd(&uartswRxBuffer, UartswRxData);
269 // disable OC0 interrupt
270 cbi(TIMSK, OCIE0);
271 // clear INT2 interrupt flag
272 sbi(EIFR, INTF2);
273 // enable INT interrupt
274 sbi(EIMSK, INT2);
275 // clear busy flag
276 UartswRxBusy = FALSE;
277 }
278 }
279 }
280  
281 SIGNAL(SIG_INTERRUPT2)
282 {
283 // run RxBit service routine
284 uartswRxBitService();
285 }
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3