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 |