Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | mjames | 1 | /* |
2 | * $Header: c:/cvsroot/bart/rt_serial.c,v 1.5 2004/03/10 20:13:46 mjames Exp $ |
||
3 | |||
4 | RCS Log file |
||
5 | |||
6 | $Log: rt_serial.c,v $ |
||
7 | Revision 1.5 2004/03/10 20:13:46 mjames |
||
8 | Correcting hard flow |
||
9 | |||
10 | Revision 1.4 2004/03/09 00:45:20 mjames |
||
11 | Corrected mistakes, made task numbers visible |
||
12 | |||
13 | Revision 1.3 2004/03/06 12:17:48 mjames |
||
14 | Moved headers around, made it clearer that there are no configurable |
||
15 | parts to the OS unless it is rebuilt |
||
16 | |||
17 | Revision 1.2 2004/03/04 21:52:59 mjames |
||
18 | Made the files work with a demo project |
||
19 | |||
20 | Revision 1.1.1.1 2004/03/03 22:54:33 mjames |
||
21 | no message |
||
22 | |||
23 | |||
24 | */ |
||
25 | |||
26 | |||
27 | |||
28 | /******************* |
||
29 | * INCLUDE FILES * |
||
30 | ********************/ |
||
31 | #include "mcs51reg.h" |
||
32 | |||
33 | #include "rt_int.h" |
||
34 | #include "rt_ext.h" |
||
35 | |||
36 | |||
37 | #define SIO1_RATIO (PRESCALE/SIO1_BAUD) |
||
38 | #define SIO1_BAUDCODE (255-SIO1_RATIO) |
||
39 | |||
40 | |||
41 | /** compute baud timing for T2, an independent UART */ |
||
42 | #define SIO2_RATIO (PRESCALE2/SIO2_BAUD) |
||
43 | |||
44 | /** after 1->0 transition on T2EX then wait 1/2bit, check = 0 |
||
45 | then wait 1 bit , shift in bit 0 and so on.... */ |
||
46 | #define SIO2_BAUDCODE_START (65535-(SIO2_RATIO/2)) |
||
47 | #define SIO2_BAUDCODE_BIT (65535-(SIO2_RATIO)) |
||
48 | |||
49 | |||
50 | |||
51 | |||
52 | #if SIO2_BAUDCODE_START <=0 |
||
53 | #error SIO2 baudcode out of range |
||
54 | #endif |
||
55 | |||
56 | |||
57 | |||
58 | |||
59 | /* phone buffer size */ |
||
60 | #define SIO1_TX_FIFOBITS 7 /* Phone Tx may have quite a few chars in the buffer */ |
||
61 | #define SIO1_RX_FIFOBITS 5 /* Expect to buffer fewer chars incoming */ |
||
62 | #define SIO2_RX_FIFOBITS 6 /* Second recieve buffer */ |
||
63 | #define SIO2_TX_FIFOBITS 5 /* Second transmit buffer */ |
||
64 | |||
65 | |||
66 | #if SIO1_TX_FIFOBITS > 7 |
||
67 | #error Max value of SIO1_TX_FIFOBITS is 7 |
||
68 | #endif |
||
69 | |||
70 | |||
71 | #if SIO1_RX_FIFOBITS > 7 |
||
72 | #error Max value of SIO1_RX_FIFOBITS is 7 |
||
73 | #endif |
||
74 | |||
75 | |||
76 | |||
77 | /********************************************************************************/ |
||
78 | /* Setup fifo for Phone Writing */ |
||
79 | /********************************************************************************/ |
||
80 | #define SIO1_TX_FIFOSIZE (1<<SIO1_TX_FIFOBITS) |
||
81 | |||
82 | /* determine the byte count limit : 1<<8 == 0 in byte arithmetic :-) */ |
||
83 | #if SIO1_TX_FIFOBITS == 8 |
||
84 | #define SIO1_TX_FIFOFULL (SIO1_TX_FIFOSIZE-1) |
||
85 | #else |
||
86 | #define SIO1_TX_FIFOFULL SIO1_TX_FIFOSIZE |
||
87 | #endif |
||
88 | |||
89 | #define SIO1_TX_FIFOMASK (SIO1_TX_FIFOSIZE-1) |
||
90 | #define SIO1_TX_FIFO_LWM (SIO1_TX_FIFOSIZE/2) |
||
91 | |||
92 | /********************************************************************************/ |
||
93 | /* Setup fifo for Phone Reading */ |
||
94 | /********************************************************************************/ |
||
95 | #define SIO1_RX_FIFOSIZE (1<<SIO1_RX_FIFOBITS) |
||
96 | /* determine the byte count limit : 1<<8 == 0 in byte arithmetic :-) */ |
||
97 | #if SIO1_RX_FIFOBITS == 8 |
||
98 | #define SIO1_RX_FIFOFULL (SIO1_RX_FIFOSIZE-1) |
||
99 | #else |
||
100 | #define SIO1_RX_FIFOFULL SIO1_RX_FIFOSIZE |
||
101 | #endif |
||
102 | |||
103 | #define SIO1_RX_FIFOMASK (SIO1_RX_FIFOSIZE-1) |
||
104 | #define SIO1_RX_FIFO_LWM (SIO1_RX_FIFOSIZE/4) /* Low Water Mark for Xon/Xoff flow control */ |
||
105 | #define SIO1_RX_FIFO_HWM (SIO1_RX_FIFOSIZE/2) /* High Water Mark for Xon/Xoff flow control */ |
||
106 | |||
107 | |||
108 | /********************************************************************************/ |
||
109 | /* Setup fifo for SIO2 reading */ |
||
110 | /********************************************************************************/ |
||
111 | |||
112 | #define SIO2_RX_FIFOSIZE (1<<SIO2_RX_FIFOBITS) |
||
113 | /* determine the byte count limit : 1<<8 == 0 in byte arithmetic :-) */ |
||
114 | #if SIO2_RX_FIFOBITS == 8 |
||
115 | #define SIO2_RX_FIFOFULL (SIO2_RX_FIFOSIZE-1) |
||
116 | #else |
||
117 | #define SIO2_RX_FIFOFULL SIO2_RX_FIFOSIZE |
||
118 | #endif |
||
119 | |||
120 | #define SIO2_RX_FIFOMASK (SIO2_RX_FIFOSIZE-1) |
||
121 | #define SIO2_RX_FIFO_LWM (SIO2_RX_FIFOSIZE/4) /* Low Water Mark for Xon/Xoff flow control */ |
||
122 | #define SIO2_RX_FIFO_HWM (SIO2_RX_FIFOSIZE/2) /* High Water Mark for Xon/Xoff flow control */ |
||
123 | |||
124 | |||
125 | |||
126 | /******************* |
||
127 | * LOCAL TYPEDEFS * |
||
128 | ********************/ |
||
129 | |||
130 | /* this code is for the main uart of the 8051 */ |
||
131 | |||
132 | static volatile char SIO1_TXFIFO[SIO1_TX_FIFOSIZE]; /* Data FIFO for transmit data */ |
||
133 | static volatile char SIO1_RXFIFO[SIO1_RX_FIFOSIZE]; /* Data FIFO for receive data */ |
||
134 | |||
135 | #if defined SIO2_TX_EN |
||
136 | static volatile char SIO2_TXFIFO2[SIO2_TX_FIFOSIZE]; /* Data FIFO for transmit2 data */ |
||
137 | #endif |
||
138 | static volatile char SIO2_RXFIFO[SIO2_RX_FIFOSIZE]; /* Data FIFO for receive 2 data */ |
||
139 | |||
140 | |||
141 | static volatile unsigned char SIO1_TxPtr; /**< next byte in FIFO to be transmitted */ |
||
142 | volatile unsigned char SIO1_TxCount; /**< num of un-transmitted byted in FIFO */ |
||
143 | volatile Bool SIO1_TxBusy; /**< TRUE when UART is transmitting */ |
||
144 | static volatile Byte SIO1_RxPtr; /**< next byte to fetch from Rx buffer */ |
||
145 | static volatile Byte SIO1_RxCount; /**< num of un-readin bytes in FIFO */ |
||
146 | |||
147 | |||
148 | #if defined SOFT_FLOW |
||
149 | static volatile Bool SIO1_TxOn; /**< true if we think we are able to transmit, i.e. |
||
150 | * we haven't (yet) recieved an XOFF from host */ |
||
151 | |||
152 | static volatile Bool SIO1_RxOn; /**< true if we think we are ready to receive, i.e. * |
||
153 | * we haven't tried to stop the host with an XOFF */ |
||
154 | static Byte SIO1_FlowChar; /* if this is non-zero, then send this char in place */ |
||
155 | /* of the byte queued in the FIFO (used for XON/XOFF) */ |
||
156 | #endif |
||
157 | |||
158 | /* this is storage for the second virtual uart */ |
||
159 | static volatile Byte SIO2_RxPtr; /* next byte to fetch from Rx buffer */ |
||
160 | volatile Byte SIO2_RxCount; /* num of un-readin bytes in FIFO */ |
||
161 | |||
162 | #if defined SIO2_TX_EN |
||
163 | static volatile Byte SIO2_TxPtr; /* next byte to send from Tx buffer */ |
||
164 | static volatile Byte SIO2_TxCount; /* num of un-sent bytes in FIFO |
||
165 | (non zero, transmitter enabled) */ |
||
166 | #endif |
||
167 | |||
168 | /* these counters are shared between transmit and recieve on the SIO2 */ |
||
169 | static volatile Byte SIO2_Byte; |
||
170 | volatile Byte SIO2_BitCnt; |
||
171 | |||
172 | static volatile Bool SIO_put_semaphore; |
||
173 | |||
174 | |||
175 | /******************************************************************************** |
||
176 | * Name : rt_serial_init |
||
177 | * This function sets up all of the timers for the serial ports |
||
178 | * |
||
179 | *******************************************************************************/ |
||
180 | void rt_serial_init (void) |
||
181 | { |
||
182 | |||
183 | SIO1_TxPtr = 0; |
||
184 | SIO1_RxPtr = 0; |
||
185 | SIO1_TxCount = 0; |
||
186 | SIO1_RxCount = 0; |
||
187 | SIO1_TxBusy = FALSE; |
||
188 | SIO1_TxPtr = 0; |
||
189 | |||
190 | SIO2_RxPtr = 0; |
||
191 | SIO2_RxCount = 0; |
||
192 | #if defined SIO2_TX_EN |
||
193 | SIO2_TxPtr = 0; |
||
194 | SIO2_TxCount = 0; |
||
195 | #endif |
||
196 | |||
197 | #if defined SOFT_FLOW |
||
198 | SIO1_FlowChar = 0; |
||
199 | SIO1_TxOn = TRUE; |
||
200 | SIO1_RxOn = TRUE; |
||
201 | #endif |
||
202 | |||
203 | #if defined HARD_FLOW |
||
204 | SIO1_CTS = FALSE; /* assert CTS */ |
||
205 | #endif |
||
206 | |||
207 | SIO_put_semaphore = TRUE; |
||
208 | |||
209 | TR1 = FALSE; |
||
210 | SCON= 0x50; /* select mode 1 (8bit variable baudrate) */ |
||
211 | |||
212 | TH1 = SIO1_BAUDCODE; /* set timer 1 for SIO1 baud */ |
||
213 | TL1 = SIO1_BAUDCODE; /* set timer 1*/ |
||
214 | TR1 = TRUE; /* set timer 1 running */ |
||
215 | |||
216 | /* initialise T2EX to generate a falling edge interrupt and |
||
217 | use timer 2 as an SIO baud rate timer for the second soft UART */ |
||
218 | |||
219 | T2CON = 0; /* 16 bit auto reload */ |
||
220 | |||
221 | EXEN2 = TRUE; /* allow for falling edge IRQ */ |
||
222 | |||
223 | ET2 = TRUE; /*TURNED OFF to allow further debug allow for T2 interrupt */ |
||
224 | |||
225 | TR2 = TRUE; /* only edges now */ |
||
226 | |||
227 | |||
228 | PT2 = TRUE; /* up priority */ |
||
229 | IPH |=PT2H; |
||
230 | |||
231 | |||
232 | |||
233 | RCAP2H = SIO2_BAUDCODE_START / 256; /* setup for 4800 baud */ |
||
234 | RCAP2L = SIO2_BAUDCODE_START & 255; /* start bit */ |
||
235 | |||
236 | |||
237 | REN = TRUE; // Receive characters. |
||
238 | /* PS = TRUE; */ // Low priority. |
||
239 | ES = TRUE; |
||
240 | |||
241 | #if defined HARD_FLOW && defined SIMULATOR_BUILD |
||
242 | SIO1_RTS = FALSE; /* enable output by forcing ready status*/ |
||
243 | #endif |
||
244 | |||
245 | } |
||
246 | |||
247 | |||
248 | /******************************************************************************** |
||
249 | * Name : SIOInterrupt |
||
250 | * This function handles the RI and TI Interrupts from the SIO on the 8051 |
||
251 | * |
||
252 | *******************************************************************************/ |
||
253 | void SIOInterrupt(void) interrupt SIO_INTVEC using SIO_INTERRUPT_BANK |
||
254 | |||
255 | { |
||
256 | /* |
||
257 | * do |
||
258 | * { |
||
259 | */ |
||
260 | if(RI) /* receive handler */ |
||
261 | { |
||
262 | Byte Chr; |
||
263 | |||
264 | |||
265 | RI = 0; |
||
266 | Chr = SBUF; |
||
267 | #if defined SOFT_FLOW |
||
268 | if (Chr == XON) |
||
269 | { |
||
270 | SIO1_TxOn = TRUE; |
||
271 | if (!SIO1_TxBusy) |
||
272 | { |
||
273 | TI=1; |
||
274 | } |
||
275 | } |
||
276 | else if (Chr == XOFF) |
||
277 | { |
||
278 | SIO1_TxOn = FALSE; |
||
279 | } |
||
280 | else /* char was not an xon/xoff */ |
||
281 | #endif |
||
282 | { |
||
283 | |||
284 | #if defined SOFT_FLOW |
||
285 | if ((SIO1_RxCount >= (Byte) SIO1_RX_FIFO_HWM) && SIO1_RxOn) |
||
286 | { |
||
287 | SIO1_RxOn = FALSE; |
||
288 | |||
289 | SIO1_FlowChar = XOFF; /* buffer is filling, try and shutup host */ |
||
290 | |||
291 | if (!SIO1_TxBusy) TI = 1; /* force the XOFF to be sent */ |
||
292 | } |
||
293 | #endif |
||
294 | |||
295 | #if defined HARD_FLOW |
||
296 | if (SIO1_RxCount >= SIO1_RX_FIFOFULL-1) |
||
297 | { |
||
298 | SIO1_CTS = TRUE; |
||
299 | } |
||
300 | #endif |
||
301 | |||
302 | if(SIO1_RxCount != SIO1_RX_FIFOFULL) /* is there room left in the Rx FIFO ? */ |
||
303 | { |
||
304 | Byte TempPtr = (SIO1_RxPtr+SIO1_RxCount) & SIO1_RX_FIFOMASK; |
||
305 | SIO1_RXFIFO[TempPtr] = Chr; |
||
306 | SIO1_RxCount++; |
||
307 | } |
||
308 | } |
||
309 | #if defined SIO1_TASK |
||
310 | INT_SIGNAL(SIO1_TASK,SERIAL_SIG); |
||
311 | #endif |
||
312 | } |
||
313 | |||
314 | if(TI) /* handle transmit interrupt */ |
||
315 | { |
||
316 | TI = 0; |
||
317 | |||
318 | #if defined SOFT_FLOW |
||
319 | if(SIO1_FlowChar) |
||
320 | { |
||
321 | SBUF = SIO1_FlowChar; /* a flow control char to be sent pre-empts the */ |
||
322 | SIO1_TxBusy = TRUE; /* normal fifo content transmission */ |
||
323 | SIO1_FlowChar = 0; |
||
324 | } |
||
325 | else |
||
326 | #endif |
||
327 | { |
||
328 | #if defined SOFT_FLOW |
||
329 | if(SIO1_TxOn && SIO1_TxCount) |
||
330 | #else |
||
331 | #if defined HARD_FLOW |
||
332 | if(!SIO1_RTS && SIO1_TxCount) |
||
333 | #else |
||
334 | |||
335 | if(SIO1_TxCount) |
||
336 | #endif |
||
337 | #endif |
||
338 | |||
339 | { register char c; |
||
340 | SIO1_TxCount--; |
||
341 | c = SIO1_TXFIFO[SIO1_TxPtr++]; /* send next char if there is one, and */ |
||
342 | SIO1_TxPtr &= SIO1_TX_FIFOMASK; |
||
343 | SIO1_TxBusy = TRUE; /* flow has not been stopped */ |
||
344 | SBUF = c; |
||
345 | } |
||
346 | else |
||
347 | { |
||
348 | SIO1_TxBusy = FALSE; |
||
349 | } |
||
350 | } |
||
351 | |||
352 | } |
||
353 | |||
354 | |||
355 | } |
||
356 | |||
357 | /******************************************************************************** |
||
358 | ** Name : T2Interrupt |
||
359 | * Timer 2 uses its T2EX pin as a falling edge IRQ pin for incoming data |
||
360 | ** It also can transmit data in a half-duplex mode |
||
361 | *******************************************************************************/ |
||
362 | void T2Interrupt(void) interrupt T2_INTVEC using T2_INTERRUPT_BANK |
||
363 | { |
||
364 | /* Falling edge interrupt */ |
||
365 | |||
366 | if (EXF2) |
||
367 | { |
||
368 | |||
369 | EXF2 = FALSE; |
||
370 | TF2 = FALSE; |
||
371 | |||
372 | EXEN2 = FALSE; /* turn off the ext2 IRQ */ |
||
373 | |||
374 | // TH2 = SIO2_BAUDCODE_START / 256; /* setup for 4800 baud */ |
||
375 | // TL2 = SIO2_BAUDCODE_START & 255; /* start bit */ |
||
376 | RCAP2H = SIO2_BAUDCODE_BIT / 256; |
||
377 | RCAP2L = SIO2_BAUDCODE_BIT & 255; /* set timer 2 for 4800 baud */ |
||
378 | |||
379 | SIO2_BitCnt = 0; /* count up incl start bit to 8 */ |
||
380 | #if defined SIO2_TX_EN |
||
381 | Rx_Run2 = TRUE; |
||
382 | #endif |
||
383 | } |
||
384 | |||
385 | |||
386 | /* timeout ? */ |
||
387 | if (TF2) |
||
388 | { |
||
389 | |||
390 | TF2 = FALSE; |
||
391 | |||
392 | #if defined SIO2_TX_EN |
||
393 | /* TRANSMIT USAGE OF T2 */ |
||
394 | /* interrupt with no reciever running now must be transmit */ |
||
395 | if(!SIO2_Rx_Run) |
||
396 | { |
||
397 | if(SIO2_BitCnt == 0) |
||
398 | { |
||
399 | /* load next Tx byte */ |
||
400 | if(SIO2_TxCount) |
||
401 | { |
||
402 | SIO2_Byte = SIO2_FIFO[SIO2_TxPtr]; /* send next char if there is one, and */ |
||
403 | SIO2_TxPtr2++; |
||
404 | TxPtr2 &= TX2_FIFOMASK; |
||
405 | TxCount2--; |
||
406 | } |
||
407 | } |
||
408 | else if (SIO2_BitCnt == 8) |
||
409 | { |
||
410 | SIO2_OUTPIN = TRUE; |
||
411 | SIO2_BitCnt++; |
||
412 | } |
||
413 | else if (SIO2_BitCnt == 9) |
||
414 | { /* finished stop bit : any more bytes to send ? */ |
||
415 | if (TxCount2) |
||
416 | { /* If so preserve the preload values and continue with the start bit */ |
||
417 | Ch2BitCnt = 0; |
||
418 | SIO2_OUTPIN = FALSE: |
||
419 | } |
||
420 | else |
||
421 | { /* reenable reciever */ |
||
422 | Rx_Run2 = TRUE; |
||
423 | } |
||
424 | } |
||
425 | else |
||
426 | { |
||
427 | SIO2_OUTPIN = SIO2_Byte & 1; |
||
428 | SIO2_Byte >>= 1; |
||
429 | SIO2_BitCnt++; |
||
430 | } |
||
431 | |||
432 | |||
433 | } |
||
434 | /* END OF TRANSMIT USAGE */ |
||
435 | |||
436 | else |
||
437 | { |
||
438 | #endif |
||
439 | |||
440 | if(!EXEN2) |
||
441 | { |
||
442 | |||
443 | if(SIO2_BitCnt == 0) |
||
444 | { |
||
445 | if( SIO2_RXD != 0) |
||
446 | { |
||
447 | /* Start bit preload is due to EX2 falling, check */ |
||
448 | RCAP2H = SIO2_BAUDCODE_START / 256; /* setup for 4800 baud */ |
||
449 | RCAP2L = SIO2_BAUDCODE_START & 255; /* start bit */ |
||
450 | EXF2 = FALSE; |
||
451 | EXEN2 = TRUE; |
||
452 | TR2 = TRUE; /* Keep running counter */ |
||
453 | #if defined SIO2_TX_EN |
||
454 | SIO2_Rx_Run = FALSE; /* not recieving at present */ |
||
455 | #endif |
||
456 | } |
||
457 | else |
||
458 | { |
||
459 | SIO2_BitCnt++; |
||
460 | } |
||
461 | } |
||
462 | else |
||
463 | { |
||
464 | SIO2_Byte = (SIO2_Byte >> 1) | (SIO2_RXD << 7); |
||
465 | |||
466 | if (SIO2_BitCnt==8 ) |
||
467 | { |
||
468 | if(SIO2_RxCount != SIO2_RX_FIFOFULL) /* is there room left in the Rx FIFO ? */ |
||
469 | { |
||
470 | Byte TempPtr = (SIO2_RxPtr+SIO2_RxCount) & SIO2_RX_FIFOMASK; |
||
471 | SIO2_RXFIFO[TempPtr] = SIO2_Byte; |
||
472 | SIO2_RxCount++; |
||
473 | } |
||
474 | #if defined SIO2_TASK |
||
475 | INT_SIGNAL(SIO2_TASK,SERIAL_SIG); |
||
476 | #endif |
||
477 | } |
||
478 | |||
479 | if(SIO2_BitCnt <8 ) |
||
480 | { |
||
481 | SIO2_BitCnt++; |
||
482 | } |
||
483 | else /* stop bit */ |
||
484 | { |
||
485 | #if defined SIO2_TX_EN |
||
486 | SIO2_Rx_Run = FALSE; /* not recieving at present */ |
||
487 | /* go straight to start Tx if anything to send now */ |
||
488 | if(SIO2_TxCount) |
||
489 | { |
||
490 | EXEN2 = FALSE; /* turn off the ext2 IRQ */ |
||
491 | SIO2_BitCnt = 0; /* count up incl start bit to 8 */ |
||
492 | SIO2_TXD = FALSE; |
||
493 | } |
||
494 | else |
||
495 | #endif |
||
496 | { |
||
497 | RCAP2H = SIO2_BAUDCODE_START / 256; /* setup for 4800 baud */ |
||
498 | RCAP2L = SIO2_BAUDCODE_START & 255; /* start bit */ |
||
499 | EXF2 = FALSE; |
||
500 | EXEN2 = TRUE; |
||
501 | TR2 = TRUE; /* Keep running counter */ |
||
502 | } |
||
503 | } |
||
504 | } |
||
505 | } |
||
506 | } |
||
507 | } |
||
508 | |||
509 | |||
510 | |||
511 | |||
512 | /******************************************************************************** |
||
513 | * |
||
514 | * Description |
||
515 | * This is the putchar routine that tries to fill the SIO transmit FIFO. |
||
516 | * If the FIFO is full it waits for a FIFO becoming less than full signal |
||
517 | * it then places a char in the buffer and uses the set TI flag trick |
||
518 | * to force a transmit interrupt. |
||
519 | * |
||
520 | **************************************************************************/ |
||
521 | |||
522 | #pragma save |
||
523 | #pragma noinduction |
||
524 | |||
525 | void putchar(char c) |
||
526 | { |
||
527 | USE_CRITICAL; |
||
528 | BEGIN_CRITICAL; |
||
529 | |||
530 | while(SIO1_TxCount == SIO1_TX_FIFOFULL) |
||
531 | { |
||
532 | /* STORE_A16 = 0; */ |
||
533 | END_CRITICAL; |
||
534 | RESCHEDULE; |
||
535 | /* STORE_A16 = 1; */ |
||
536 | BEGIN_CRITICAL; |
||
537 | |||
538 | } |
||
539 | |||
540 | SIO1_TXFIFO[(SIO1_TxPtr+SIO1_TxCount) & SIO1_TX_FIFOMASK] = c; /* place character into buffer */ |
||
541 | SIO1_TxCount++; |
||
542 | END_CRITICAL; |
||
543 | |||
544 | if (!SIO1_TxBusy) |
||
545 | { |
||
546 | TI=1; |
||
547 | } |
||
548 | |||
549 | #if defined USE_CRLF_MAP |
||
550 | if (c==LF) /* handle LF -> LF,CR mapping */ |
||
551 | { |
||
552 | c = CR; |
||
553 | while(SIO1_TxCount == SIO1_TX_FIFOFULL) |
||
554 | { |
||
555 | RESCHEDULE; /* wait for space in the FIFO */ |
||
556 | } |
||
557 | |||
558 | BEGIN_CRITICAL; |
||
559 | SIO1_TXFIFO[(SIO1_TxPtr+SIO1_TxCount) & SIO1_TX_FIFOMASK] = c; /* place character into buffer */ |
||
560 | SIO1_TxCount++; |
||
561 | END_CRITICAL; |
||
562 | |||
563 | if (!SIO1_TxBusy) |
||
564 | { |
||
565 | TI=1; |
||
566 | } |
||
567 | } |
||
568 | #endif |
||
569 | } |
||
570 | #pragma restore |
||
571 | |||
572 | /********************************************************************************** |
||
573 | |||
574 | Transmit character on SIO2. If there is nothing being recieved then we take |
||
575 | over the T2 interrupt immediately. If there is something being recieved then |
||
576 | wait until this character has been recieved, and on final Rx T2 IRQ switch to |
||
577 | transmit T2 IRQ and send a start bit. |
||
578 | |||
579 | ***********************************************************************************/ |
||
580 | #if defined SIO2_TX_EN |
||
581 | void SIO2_putchar(char c) |
||
582 | { |
||
583 | USE_CRITICAL; |
||
584 | |||
585 | while(SIO2_TxCount == SIO2_TX_FIFOFULL) |
||
586 | { |
||
587 | RESCHEDULE; /* wait for space in the FIFO */ |
||
588 | } |
||
589 | |||
590 | BEGIN_CRITICAL; |
||
591 | SIO2_TxFIFO[(SIO2_TxPtr+SIO2_TxCount) & SIO2_TX_FIFOMASK] = c; /* place character into buffer */ |
||
592 | SIO2_TxCount2++; |
||
593 | |||
594 | /* if the reciever is not running any more, start the transmitter interrupts */ |
||
595 | if (!SIO2_Rx_Run) |
||
596 | { |
||
597 | EXEN2 = FALSE; /* turn off the ext2 IRQ */ |
||
598 | |||
599 | TF2 = FALSE; |
||
600 | TR2 = FALSE; |
||
601 | T2H = SIO2_BAUDCODE_BIT >> 8 ; |
||
602 | T2L = SIO2_BAUDCODE_BIT & 255; |
||
603 | RCAP2H = SIO2_BAUDCODE_BIT >> 8; |
||
604 | RCAP2L = SIO2_BAUDCODE_BIT & 255; /* set timer 2 for 4800 baud */ |
||
605 | TR2 =TRUE; |
||
606 | SIO2_BitCnt = 0; /* count up incl start bit to 8 */ |
||
607 | SIO2_TXD = FALSE; |
||
608 | } |
||
609 | END_CRITICAL; |
||
610 | |||
611 | } |
||
612 | #endif |
||
613 | |||
614 | /** This is the getchar routine that tries to empty the receive FIFO for SIO1 |
||
615 | * If the FIFO is empty then it will wait until there is a character in the buffer |
||
616 | * it then removes a character from the buffer. |
||
617 | * if the buffer empties below the FIFO_LWM and the RxOn flag is clear, |
||
618 | * force the transmitter to send an XON. |
||
619 | */ |
||
620 | char getchar(void) |
||
621 | { |
||
622 | Byte Chr; |
||
623 | USE_CRITICAL; |
||
624 | while (!SIO1_RxCount) |
||
625 | { |
||
626 | RESCHEDULE; |
||
627 | } |
||
628 | |||
629 | BEGIN_CRITICAL; |
||
630 | |||
631 | Chr = SIO1_RXFIFO[SIO1_RxPtr]; /* get next char out of RxFIFO */ |
||
632 | SIO1_RxPtr++; |
||
633 | SIO1_RxPtr &= SIO1_RX_FIFOMASK; |
||
634 | SIO1_RxCount--; |
||
635 | SIO1_RxCount &= SIO1_RX_FIFOMASK; |
||
636 | |||
637 | #if defined SOFT_FLOW |
||
638 | if((SIO1_RxCount <= (Byte) SIO1_RX_FIFO_LWM) && !SIO1_RxOn) /* is reception is off, and is FIFO */ |
||
639 | { /* empty enough to allow a restart ?? */ |
||
640 | SIO1_RxOn = TRUE; |
||
641 | SIO1_FlowChar = XON; |
||
642 | if (!SIO1_TxBusy) TI = 1; /* force the XON char to be sent */ |
||
643 | } |
||
644 | #endif |
||
645 | |||
646 | #if defined HARD_FLOW |
||
647 | if(SIO1_RxCount <= (Byte) SIO1_RX_FIFO_LWM) /* when space in FIFO restart */ |
||
648 | { |
||
649 | SIO1_CTS = FALSE; |
||
650 | } |
||
651 | #endif |
||
652 | |||
653 | END_CRITICAL; |
||
654 | |||
655 | return Chr; |
||
656 | } |
||
657 | |||
658 | /** This is the getchar routine that tries to empty the receive FIFO for SIO2 |
||
659 | * If the FIFO is empty then it will wait until there is a character in the buffer |
||
660 | * it then removes a character from the buffer. |
||
661 | */ |
||
662 | char SIO2_getchar(void) |
||
663 | { |
||
664 | USE_CRITICAL; |
||
665 | Byte Chr; |
||
666 | |||
667 | while (!SIO2_RxCount) |
||
668 | { |
||
669 | RESCHEDULE; |
||
670 | } |
||
671 | |||
672 | BEGIN_CRITICAL; |
||
673 | |||
674 | Chr = SIO2_RXFIFO[SIO2_RxPtr]; /* get next char out of RxFIFO */ |
||
675 | SIO2_RxPtr++; |
||
676 | SIO2_RxPtr &= SIO2_RX_FIFOMASK; |
||
677 | SIO2_RxCount--; |
||
678 | SIO2_RxCount &= SIO2_RX_FIFOMASK; |
||
679 | |||
680 | END_CRITICAL; |
||
681 | |||
682 | return Chr; |
||
683 | } |
||
684 | |||
685 | |||
686 | /******************************************************************************** |
||
687 | * Name : SIO_pollchar |
||
688 | * |
||
689 | * Module : SIO |
||
690 | * |
||
691 | * Returns : the number of characters in the SIO recieve buffer |
||
692 | * |
||
693 | *******************************************************************************/ |
||
694 | char SIO1_pollchar(void) |
||
695 | { |
||
696 | return SIO1_RxCount; |
||
697 | } |
||
698 | |||
699 | |||
700 | char SIO2_pollchar(void) |
||
701 | { |
||
702 | return SIO2_RxCount; |
||
703 | } |
||
704 | |||
705 | |||
706 | void SIO1_flush(void) |
||
707 | { |
||
708 | USE_CRITICAL; |
||
709 | BEGIN_CRITICAL; |
||
710 | SIO1_RxPtr = 0; |
||
711 | SIO1_RxCount = 0; |
||
712 | END_CRITICAL; |
||
713 | } |
||
714 | |||
715 | |||
716 | void SIO2_flush(void) |
||
717 | { |
||
718 | USE_CRITICAL; |
||
719 | BEGIN_CRITICAL; |
||
720 | SIO2_RxPtr = 0; |
||
721 | SIO2_RxCount = 0; |
||
722 | END_CRITICAL; |
||
723 | } |
||
724 | |||
725 | |||
726 | /********************************************************************************/ |
||
727 | /** this drives the SIO1_TXD line to level for a number of ticks (USE 2 OR MORE ticks) |
||
728 | * timed by the T0 interrupt |
||
729 | * This function needs to be bracketed by a claim on the SIO semaphore. */ |
||
730 | /********************************************************************************/ |
||
731 | |||
732 | void SIO1_break(char level,unsigned char ticks) |
||
733 | { |
||
734 | /* wait forTx buffer to clear */ |
||
735 | while(SIO1_TxCount) |
||
736 | { |
||
737 | RESCHEDULE; |
||
738 | }; |
||
739 | |||
740 | SIO1_TXD = level; |
||
741 | sleep(ticks); |
||
742 | SIO1_TXD = 1; |
||
743 | } |
||
744 | |||
745 | |||
746 | |||
747 | /********************************************************************************/ |
||
748 | #pragma save |
||
749 | #pragma noinduction |
||
750 | |||
751 | /** This function sends a string from xdata removing the inefficiency of |
||
752 | * generic pointers */ |
||
753 | void SendStringCode(code char * s) |
||
754 | { |
||
755 | char c; |
||
756 | if (!s) return; |
||
757 | |||
758 | while(*s) |
||
759 | { |
||
760 | c= *s++; |
||
761 | putchar(c); |
||
762 | } |
||
763 | } |
||
764 | /** This function sends a string from xdata removing the inefficiency of |
||
765 | * generic pointers */ |
||
766 | void SendStringXdata(xdata char * s) |
||
767 | { |
||
768 | char c; |
||
769 | if (!s) return; |
||
770 | |||
771 | while(*s) |
||
772 | { |
||
773 | c= *s++; |
||
774 | putchar(c); |
||
775 | } |
||
776 | } |
||
777 | |||
778 | |||
779 | #pragma restore |
||
780 | |||
781 | |||
782 | void SendHex(unsigned char x) |
||
783 | { |
||
784 | unsigned char p; |
||
785 | p = x / 16; |
||
786 | putchar(p>15?'-':p>9?p+'A'-10:p+'0'); |
||
787 | p = x & 15; |
||
788 | putchar(p>15?'-':p>9?p+'A'-10:p+'0'); |
||
789 | } |
||
790 | |||
791 | |||
792 | |||
793 | |||
794 | #pragma save |
||
795 | #pragma noinduction |
||
796 | |||
797 | /** This is the semaphore used throughout for claiming the serial port. It also |
||
798 | has a busy wait if there are no ready to run tasks */ |
||
799 | void SIOTakeSemaphore(void) |
||
800 | { |
||
801 | USE_CRITICAL; |
||
802 | while(1){ |
||
803 | BEGIN_CRITICAL; |
||
804 | if(SIO_put_semaphore) |
||
805 | { |
||
806 | SIO_put_semaphore = FALSE; |
||
807 | END_CRITICAL; |
||
808 | return; |
||
809 | |||
810 | } |
||
811 | else |
||
812 | { |
||
813 | END_CRITICAL; |
||
814 | RESCHEDULE; |
||
815 | } |
||
816 | } |
||
817 | } |
||
818 | |||
819 | void SIOPutSemaphore(void) |
||
820 | { |
||
821 | SIO_put_semaphore = TRUE; |
||
822 | } |
||
823 | |||
824 | char SIOSetSemaphore(Bool value) |
||
825 | { |
||
826 | USE_CRITICAL; |
||
827 | char rc; |
||
828 | BEGIN_CRITICAL; |
||
829 | rc= SIO_put_semaphore; |
||
830 | SIO_put_semaphore = value; |
||
831 | END_CRITICAL; |
||
832 | return rc; |
||
833 | } |
||
834 | |||
835 | |||
836 | #pragma restore |