Subversion Repositories Bart

Rev

Blame | Last modification | View Log | RSS feed

  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
  837.