Subversion Repositories Bart

Rev

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