home *** CD-ROM | disk | FTP | other *** search
/ Shareware Overload / ShartewareOverload.cdr / progm / pibasy.zip / PIBASYN3.MOD < prev    next >
Text File  |  1987-11-11  |  47KB  |  897 lines

  1. (*----------------------------------------------------------------------*)
  2. (* Async_Find_Delay  --- Finds delay loop value for 1 millesecond delay *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Async_Find_Delay( VAR One_MS_Delay : INTEGER );
  6.  
  7. (*----------------------------------------------------------------------*)
  8. (*                                                                      *)
  9. (*      Procedure: Async_Find_Delay                                     *)
  10. (*                                                                      *)
  11. (*      Purpose:   Finds loop count value to effect 1 ms delay          *)
  12. (*                                                                      *)
  13. (*      Calling Sequence:                                               *)
  14. (*                                                                      *)
  15. (*         Async_Find_Delay( VAR One_MS_Delay : INTEGER );              *)
  16. (*                                                                      *)
  17. (*            One_MS_Delay --- Resulting loop count for 1 ms delay      *)
  18. (*                                                                      *)
  19. (*      Using result:                                                   *)
  20. (*                                                                      *)
  21. (*            Use loop of form:                                         *)
  22. (*                                                                      *)
  23. (*                      MOV    CX,[>One_MS_Delay]                       *)
  24. (*               Delay: LOOP   Delay                                    *)
  25. (*                                                                      *)
  26. (*            to delay for 1 ms.                                        *)
  27. (*                                                                      *)
  28. (*      Remarks:                                                        *)
  29. (*                                                                      *)
  30. (*         This routine watches over the CPU elapsed timer value for    *)
  31. (*         just one timer interval (55 milleseconds).  During that time *)
  32. (*         we run a tight loop and accumulate the ticks.  The result    *)
  33. (*         is the number of ticks required for a 55 ms delay.  The      *)
  34. (*         ticks for a 1 ms delay = ( ticks for 55 ms ) / 55.           *)
  35. (*                                                                      *)
  36. (*         To avoid overflow problems on fast machines, and to ease the *)
  37. (*         worry about storing results at the second timer tick, we     *)
  38. (*         break up the single long tight loop into a series of short   *)
  39. (*         loops inside an outer loop.  We check if the timer has       *)
  40. (*         expired at the end of each inner short loop.  Then the       *)
  41. (*         time for the 55 ms delay is:                                 *)
  42. (*                                                                      *)
  43. (*            Ticks_for_55 := Inner_Ticks * Outer_Ticks;                *)
  44. (*                                                                      *)
  45. (*         and the corresponding 1 ms delay is:                         *)
  46. (*                                                                      *)
  47. (*            Ticks_For_1  := Ticks_For_55 DIV 55;                      *)
  48. (*                                                                      *)
  49. (*         To simplify things, we choose the inner tick value to be     *)
  50. (*         2 x 55 = 110.  Then:                                         *)
  51. (*                                                                      *)
  52. (*            Ticks_For_1  := ( 110 * Outer_Ticks ) / 55;  ==>          *)
  53. (*            Ticks_For_1  := 2 * Outer_Ticks;                          *)
  54. (*                                                                      *)
  55. (*         The CPU timer is located in four bytes at $0000:$46C.        *)
  56. (*         Interrupt $1A also returns these bytes, but using the        *)
  57. (*         interrupt results in an inaccurate loop count value.         *)
  58. (*                                                                      *)
  59. (*         Thanks to Brian Foley and Kim Kokonnen for help with this    *)
  60. (*         problem.                                                     *)
  61. (*                                                                      *)
  62. (*----------------------------------------------------------------------*)
  63.  
  64. (* STRUCTURED *) CONST
  65.    Hi_Timer         : INTEGER = 0  (* Saves high portion of timer        *);
  66.    Lo_Timer         : INTEGER = 0  (* Saves low portion of timer         *);
  67.    OutCount         : INTEGER = 0  (* Accumulates outer loop counts      *);
  68.  
  69. BEGIN (* Async_Find_Delay *)
  70.  
  71. INLINE(
  72.                              {;}
  73.   $31/$C0/                   {          XOR    AX,AX                 ;Clear AX to zero}
  74.   $8E/$C0/                   {          MOV    ES,AX                 ;Allow low-memory access}
  75.                              {;}
  76.   $C7/$06/>OUTCOUNT/$00/$00/ {          MOV    WORD [>OutCount],0    ;Clear outer loop counter}
  77.                              {;}
  78.   $FA/                       {          CLI                          ;No interrupts while reading}
  79.   $26/$8B/$0E/>$46E/         {      ES: MOV    CX,[>$46E]            ;Hi part of CPU timer value}
  80.   $26/$8B/$16/>$46C/         {      ES: MOV    DX,[>$46C]            ;Lo part of CPU timer value}
  81.   $FB/                       {          STI                          ;Interrupts back on}
  82.                              {;}
  83.   $89/$0E/>HI_TIMER/         {          MOV    [>Hi_Timer],CX        ;Save hi part of timer}
  84.   $89/$16/>LO_TIMER/         {          MOV    [>Lo_Timer],DX        ;Save low part of timer}
  85.                              {;}
  86.   $FA/                       {Loop1:    CLI                          ;No interrupts while reading}
  87.                              {;}
  88.   $26/$8B/$0E/>$46E/         {      ES: MOV    CX,[>$46E]            ;Hi part of CPU timer value}
  89.   $26/$8B/$16/>$46C/         {      ES: MOV    DX,[>$46C]            ;Lo part of CPU timer value}
  90.                              {;}
  91.   $FB/                       {          STI                          ;Interrupts back on}
  92.                              {;}
  93.   $89/$C8/                   {          MOV    AX,CX                 ;Save CX and DX for later}
  94.   $89/$D3/                   {          MOV    BX,DX}
  95.                              {;}
  96.   $2B/$06/>HI_TIMER/         {          SUB    AX,[>Hi_Timer]        ;Subtract low order part}
  97.   $1B/$1E/>LO_TIMER/         {          SBB    BX,[>Lo_Timer]        ;Subtract high order part}
  98.                              {;}
  99.   $74/$E6/                   {          JE     Loop1                 ;Continue until non-0 tick difference}
  100.                              {;}
  101.   $89/$0E/>HI_TIMER/         {          MOV    [>Hi_Timer],CX        ;Save hi part}
  102.   $89/$16/>LO_TIMER/         {          MOV    [>Lo_Timer],DX        ;Save low part}
  103.                              {;}
  104.   $B9/$6E/$00/               {Loop2:    MOV    CX,110                ;Run short delay loop.}
  105.   $E2/$FE/                   {Delay:    LOOP   Delay}
  106.                              {;}
  107.   $FA/                       {          CLI                          ;No interrupts while reading}
  108.                              {;}
  109.   $26/$8B/$0E/>$46E/         {      ES: MOV    CX,[>$46E]            ;Hi part of CPU timer value}
  110.   $26/$8B/$16/>$46C/         {      ES: MOV    DX,[>$46C]            ;Lo part of CPU timer value}
  111.                              {;}
  112.   $FB/                       {          STI                          ;Interrupts back on}
  113.                              {;}
  114.   $FF/$06/>OUTCOUNT/         {          INC    WORD [>OutCount]      ;Increment outer loop count}
  115.                              {;}
  116.   $2B/$0E/>HI_TIMER/         {          SUB    CX,[>Hi_Timer]        ;Subtract low order part}
  117.   $1B/$16/>LO_TIMER/         {          SBB    DX,[>Lo_Timer]        ;Subtract high order part}
  118.                              {;}
  119.   $74/$E1/                   {          JE     Loop2                 ;Keep going if next tick not found}
  120.                              {;}
  121.   $A1/>OUTCOUNT/             {          MOV    AX,[>OutCount]        ;Pick up outer loop counter}
  122.   $D1/$E0/                   {          SHL    AX,1                  ;* 2 = ticks for 1 ms delay}
  123.                              {;}
  124.   $C4/$BE/>ONE_MS_DELAY/     {          LES    DI,[BP+>One_MS_Delay] ;Get address of result}
  125.   $26/$89/$05);              {      ES: MOV    [DI],AX               ;Store result}
  126.  
  127. END   (* Async_Find_Delay *);
  128.  
  129. (*----------------------------------------------------------------------*)
  130. (*               Async_Init --- Initialize Asynchronous Variables       *)
  131. (*----------------------------------------------------------------------*)
  132.  
  133. PROCEDURE Async_Init( Async_Buffer_Max  : INTEGER;
  134.                       Async_OBuffer_Max : INTEGER;
  135.                       Async_High_Lev1   : INTEGER;
  136.                       Async_High_Lev2   : INTEGER;
  137.                       Async_Low_Lev     : INTEGER );
  138.  
  139. (*----------------------------------------------------------------------*)
  140. (*                                                                      *)
  141. (*     Procedure:  Async_Init                                           *)
  142. (*                                                                      *)
  143. (*     Purpose:    Initializes variables                                *)
  144. (*                                                                      *)
  145. (*     Calling Sequence:                                                *)
  146. (*                                                                      *)
  147. (*         Async_Init( Async_Buffer_Max  : INTEGER;                     *)
  148. (*                     Async_OBuffer_Max : INTEGER;                     *)
  149. (*                     Async_High_Lev1   : INTEGER;                     *)
  150. (*                     Async_High_Lev2   : INTEGER;                     *)
  151. (*                     Async_Low_Lev     : INTEGER );                   *)
  152. (*                                                                      *)
  153. (*     Calls:  Async_Find_Delay                                         *)
  154. (*             TurnOffTimeSharing                                       *)
  155. (*             TurnOnTimeSharing                                        *)
  156. (*                                                                      *)
  157. (*----------------------------------------------------------------------*)
  158.  
  159. VAR
  160.    I: INTEGER;
  161.  
  162. (*----------------------------------------------------------------------*)
  163.  
  164. BEGIN   (* Async_Init *)
  165.                                    (* No port open yet.                 *)
  166.    Async_Open_Flag        := FALSE;
  167.  
  168.                                    (* No XON/XOFF handling yet.         *)
  169.    Async_XOFF_Sent        := FALSE;
  170.    Async_XOFF_Received    := FALSE;
  171.    Async_XOFF_Rec_Display := FALSE;
  172.    Async_XON_Rec_Display  := FALSE;
  173.    Async_Send_XOFF        := FALSE;
  174.  
  175.                                    (* Set up empty receive buffer       *)
  176.    Async_Buffer_Overflow  := FALSE;
  177.    Async_Buffer_Used      := 0;
  178.    Async_MaxBufferUsed    := 0;
  179.    Async_Buffer_Head      := 0;
  180.    Async_Buffer_Tail      := 0;
  181.                                    (* Set up empty send buffer.         *)
  182.    Async_OBuffer_Overflow := FALSE;
  183.    Async_OBuffer_Used     := 0;
  184.    Async_MaxOBufferUsed   := 0;
  185.    Async_OBuffer_Head     := 0;
  186.    Async_OBuffer_Tail     := 0;
  187.                                    (* Set default wait time for output   *)
  188.                                    (* buffer to drain when it fills up.  *)
  189.    Async_Output_Delay     := 500;
  190.  
  191.                                    (* No modem or line errors yet.       *)
  192.    Async_Line_Status      := 0;
  193.    Async_Modem_Status     := 0;
  194.    Async_Line_Error_Flags := 0;
  195.  
  196.                                    (* Get buffer sizes *)
  197.  
  198.    IF ( Async_Buffer_Max > 0 ) THEN
  199.       Async_Buffer_Size := Async_Buffer_Max  - 1
  200.    ELSE
  201.       Async_Buffer_Size := 4095;
  202.  
  203.    IF ( Async_OBuffer_Max > 0 ) THEN
  204.       Async_OBuffer_Size := Async_OBuffer_Max - 1
  205.    ELSE
  206.       Async_OBuffer_Size := 1131;
  207.  
  208.                                    (* Get receive buffer overflow *)
  209.                                    (* check-points.               *)
  210.    IF ( Async_Low_Lev > 0 ) THEN
  211.       Async_Buffer_Low := Async_Low_Lev
  212.    ELSE
  213.       Async_Buffer_Low := Async_Buffer_Size DIV 4;
  214.  
  215.    IF ( Async_High_Lev1 > 0 ) THEN
  216.       Async_Buffer_High := Async_High_Lev1
  217.    ELSE
  218.       Async_Buffer_High := ( Async_Buffer_Size DIV 4 ) * 3;
  219.  
  220.    IF ( Async_High_Lev2 > 0 ) THEN
  221.       Async_Buffer_High_2 := Async_High_Lev2
  222.    ELSE
  223.       Async_Buffer_High_2 := ( Async_Buffer_Size DIV 10 ) * 9;
  224.  
  225.                                    (* Allocate buffers *)
  226.  
  227.    GETMEM( Async_Buffer_Ptr  , Async_Buffer_Size  + 1 );
  228.    GETMEM( Async_OBuffer_Ptr , Async_OBuffer_Size + 1 );
  229.  
  230.                                    (* No UART addresses defined yet *)
  231.    Async_Uart_IER         := 0;
  232.    Async_Uart_IIR         := 0;
  233.    Async_Uart_MSR         := 0;
  234.    Async_Uart_LSR         := 0;
  235.                                    (* Set default port addresses *)
  236.                                    (* and default IRQ lines      *)
  237.    FOR I := 1 TO MaxComPorts DO
  238.       BEGIN
  239.          Com_Base[I]  := Default_Com_Base [I];
  240.          Com_Irq [I]  := Default_Com_Irq  [I];
  241.       END;
  242.                                    (* Get the delay loop value for 1 ms *)
  243.                                    (* delay loops.                      *)
  244.  
  245. (* ---- You should turn off time sharing if running under a multitasker *)
  246. (* ---- to get an accurate delay loop value.  If MTASK is $DEFINEd,     *)
  247. (* ---- then the calls to the PibMDos routines for interfacing with     *)
  248. (* ---- multitaskers will be generated.                                 *)
  249.  
  250. {$IFDEF MTASK}
  251.    IF TimeSharingActive THEN
  252.       TurnOffTimeSharing;
  253. {$ENDIF}
  254.  
  255.    Async_Find_Delay( Async_OneMSDelay );
  256.  
  257. {$IFDEF MTASK}
  258.    IF TimeSharingActive THEN
  259.       TurnOnTimeSharing;
  260. {$ENDIF}
  261.  
  262. END     (* Async_Init *);
  263.  
  264. (*----------------------------------------------------------------------*)
  265. (*      Async_Carrier_Detect --- Check for modem carrier detect         *)
  266. (*----------------------------------------------------------------------*)
  267.  
  268. FUNCTION Async_Carrier_Detect : BOOLEAN;
  269.  
  270. (*----------------------------------------------------------------------*)
  271. (*                                                                      *)
  272. (*     Function:   Async_Carrier_Detect                                 *)
  273. (*                                                                      *)
  274. (*     Purpose:    Looks for modem carrier detect                       *)
  275. (*                                                                      *)
  276. (*     Calling Sequence:                                                *)
  277. (*                                                                      *)
  278. (*        Flag := Async_Carrier_Detect : BOOLEAN;                       *)
  279. (*                                                                      *)
  280. (*           Flag is set TRUE if carrier detected, else FALSE.          *)
  281. (*                                                                      *)
  282. (*     Calls:  None                                                     *)
  283. (*                                                                      *)
  284. (*----------------------------------------------------------------------*)
  285.  
  286. BEGIN (* Async_Carrier_Detect *)
  287.  
  288.    Async_Carrier_Detect := ODD( Port[ UART_MSR + Async_Base ] SHR 7 ) OR
  289.                            Async_Hard_Wired_On;
  290.  
  291. END   (* Async_Carrier_Detect *);
  292.  
  293. (*----------------------------------------------------------------------*)
  294. (*      Async_Carrier_Drop --- Check for modem carrier drop/timeout     *)
  295. (*----------------------------------------------------------------------*)
  296.  
  297. FUNCTION Async_Carrier_Drop : BOOLEAN;
  298.  
  299. (*----------------------------------------------------------------------*)
  300. (*                                                                      *)
  301. (*     Function:   Async_Carrier_Drop                                   *)
  302. (*                                                                      *)
  303. (*     Purpose:    Looks for modem carrier drop/timeout                 *)
  304. (*                                                                      *)
  305. (*     Calling Sequence:                                                *)
  306. (*                                                                      *)
  307. (*        Flag := Async_Carrier_Drop : BOOLEAN;                         *)
  308. (*                                                                      *)
  309. (*           Flag is set TRUE if carrier dropped, else FALSE.           *)
  310. (*                                                                      *)
  311. (*     Calls:  None                                                     *)
  312. (*                                                                      *)
  313. (*----------------------------------------------------------------------*)
  314.  
  315. BEGIN (* Async_Carrier_Drop *)
  316.  
  317.    Async_Carrier_Drop := NOT ( ODD( Port[ UART_MSR + Async_Base ] SHR 7 ) OR
  318.                                Async_Hard_Wired_On );
  319.  
  320. END   (* Async_Carrier_Drop *);
  321.  
  322. (*----------------------------------------------------------------------*)
  323. (*      Async_Term_Ready --- Set terminal ready status                  *)
  324. (*----------------------------------------------------------------------*)
  325.  
  326. PROCEDURE Async_Term_Ready( Ready_Status : BOOLEAN );
  327.  
  328. (*----------------------------------------------------------------------*)
  329. (*                                                                      *)
  330. (*     Procedure:  Async_Term_Ready                                     *)
  331. (*                                                                      *)
  332. (*     Purpose:    Sets terminal ready status                           *)
  333. (*                                                                      *)
  334. (*     Calling Sequence:                                                *)
  335. (*                                                                      *)
  336. (*        Async_Term_Ready( Ready_Status : BOOLEAN );                   *)
  337. (*                                                                      *)
  338. (*           Ready_Status --- Set TRUE to set terminal ready on,        *)
  339. (*                            Set FALSE to set terminal ready off.      *)
  340. (*                                                                      *)
  341. (*     Calls:  None                                                     *)
  342. (*                                                                      *)
  343. (*----------------------------------------------------------------------*)
  344.  
  345. VAR
  346.    Mcr_Value: BYTE;
  347.  
  348. BEGIN (* Async_Term_Ready *)
  349.  
  350.    Mcr_Value := Port[ UART_MCR + Async_Base ];
  351.  
  352.    IF ODD( Mcr_Value ) THEN Mcr_Value := Mcr_Value - 1;
  353.  
  354.    IF Ready_Status THEN Mcr_Value := Mcr_Value + 1;
  355.  
  356.    Port[ UART_MCR + Async_Base ] := Mcr_Value;
  357.  
  358.    Async_Clear_Errors;
  359.  
  360. END   (* Async_Term_Ready *);
  361.  
  362. (*----------------------------------------------------------------------*)
  363. (*          Async_Buffer_Check --- Check if character in buffer         *)
  364. (*----------------------------------------------------------------------*)
  365.  
  366. FUNCTION Async_Buffer_Check : BOOLEAN;
  367.  
  368. (*----------------------------------------------------------------------*)
  369. (*                                                                      *)
  370. (*     Function:   Async_Buffer_Check                                   *)
  371. (*                                                                      *)
  372. (*     Purpose:    Check if character in buffer                         *)
  373. (*                                                                      *)
  374. (*     Calling Sequence:                                                *)
  375. (*                                                                      *)
  376. (*        Flag := Async_Buffer_Check : BOOLEAN;                         *)
  377. (*                                                                      *)
  378. (*           Flag returned TRUE if character received in buffer,        *)
  379. (*           Flag returned FALSE if no character received.              *)
  380. (*                                                                      *)
  381. (*     Calls:  None                                                     *)
  382. (*                                                                      *)
  383. (*     Remarks:                                                         *)
  384. (*                                                                      *)
  385. (*       This routine only checks if a character has been received      *)
  386. (*       and thus can be read; it does NOT return the character.        *)
  387. (*       Use Async_Receive to read the character.                       *)
  388. (*                                                                      *)
  389. (*----------------------------------------------------------------------*)
  390.  
  391. BEGIN   (* Async_Buffer_Check *)
  392.  
  393.    Async_Buffer_Check := ( Async_Buffer_Head <> Async_Buffer_Tail );
  394.  
  395. END     (* Async_Buffer_Check *);
  396.  
  397. (*----------------------------------------------------------------------*)
  398. (*          Async_Line_Error --- Check if line status error occurred    *)
  399. (*----------------------------------------------------------------------*)
  400.  
  401. FUNCTION Async_Line_Error( VAR Error_Flags: BYTE ) : BOOLEAN;
  402.  
  403. (*----------------------------------------------------------------------*)
  404. (*                                                                      *)
  405. (*     Function:   Async_Line_Error                                     *)
  406. (*                                                                      *)
  407. (*     Purpose:    Check if line status error occurred                  *)
  408. (*                                                                      *)
  409. (*     Calling Sequence:                                                *)
  410. (*                                                                      *)
  411. (*        Flag := Async_Line_Error(VAR Error_Flags: BYTE): BOOLEAN;   *)
  412. (*                                                                      *)
  413. (*           Error_Flags --- Current error flags                        *)
  414. (*                                                                      *)
  415. (*           Flag returned TRUE if line status error occurred,          *)
  416. (*           Flag returned FALSE if no error.                           *)
  417. (*                                                                      *)
  418. (*     Calls:  None                                                     *)
  419. (*                                                                      *)
  420. (*     Remarks:                                                         *)
  421. (*                                                                      *)
  422. (*        The line status error flag is cleared here.                   *)
  423. (*                                                                      *)
  424. (*----------------------------------------------------------------------*)
  425.  
  426. BEGIN   (* Async_Line_Error *)
  427.  
  428.    Async_Line_Error       := ( Async_Line_Error_Flags <> 0 );
  429.    Error_Flags            := Async_Line_Error_Flags;
  430.    Async_Line_Error_Flags := 0;
  431.  
  432. END     (* Async_Line_Error  *);
  433.  
  434. (*----------------------------------------------------------------------*)
  435. (*            Async_Ring_Detect --- Check for phone ringing             *)
  436. (*----------------------------------------------------------------------*)
  437.  
  438. FUNCTION Async_Ring_Detect : BOOLEAN;
  439.  
  440. (*----------------------------------------------------------------------*)
  441. (*                                                                      *)
  442. (*     Function:   Async_Ring_Detect                                    *)
  443. (*                                                                      *)
  444. (*     Purpose:    Looks for phone ringing                              *)
  445. (*                                                                      *)
  446. (*     Calling Sequence:                                                *)
  447. (*                                                                      *)
  448. (*        Flag := Async_Ring_Detect : BOOLEAN;                          *)
  449. (*                                                                      *)
  450. (*           Flag is set TRUE if ringing detected, else FALSE.          *)
  451. (*                                                                      *)
  452. (*     Calls:  None                                                     *)
  453. (*                                                                      *)
  454. (*----------------------------------------------------------------------*)
  455.  
  456. BEGIN (* Async_Ring_Detect *)
  457.  
  458.    Async_Ring_Detect := ODD( Port[ UART_MSR + Async_Base ] SHR 6 );
  459.  
  460. END   (* Async_Ring_Detect *);
  461.  
  462. (*----------------------------------------------------------------------*)
  463. (*          Async_Send_Break --- Send break (attention) signal          *)
  464. (*----------------------------------------------------------------------*)
  465.  
  466. PROCEDURE Async_Send_Break;
  467.  
  468. (*----------------------------------------------------------------------*)
  469. (*                                                                      *)
  470. (*     Procedure:  Async_Send_Break                                     *)
  471. (*                                                                      *)
  472. (*     Purpose:    Sends break signal over communications port          *)
  473. (*                                                                      *)
  474. (*     Calling Sequence:                                                *)
  475. (*                                                                      *)
  476. (*        Async_Send_Break;                                             *)
  477. (*                                                                      *)
  478. (*     Calls:  None                                                     *)
  479. (*                                                                      *)
  480. (*----------------------------------------------------------------------*)
  481.  
  482. VAR
  483.    Old_Lcr   : BYTE;
  484.    Break_Lcr : BYTE;
  485.  
  486. BEGIN (* Async_Send_Break *)
  487.  
  488.    Old_Lcr   := Port[ UART_LCR + Async_Base ];
  489.    Break_Lcr := Old_Lcr;
  490.  
  491.    IF Break_Lcr >  127 THEN Break_Lcr := Break_Lcr - 128;
  492.    IF Break_Lcr <=  63 THEN Break_Lcr := Break_Lcr +  64;
  493.  
  494.    Port[ UART_LCR + Async_Base ] := Break_Lcr;
  495.  
  496.    DELAY( Async_Break_Length * 10 );
  497.  
  498.    Port[ UART_LCR + Async_Base ] := Old_Lcr;
  499.  
  500. END   (* Async_Send_Break *);
  501.  
  502. (*----------------------------------------------------------------------*)
  503. (*     Async_Send_String --- Send string over communications port       *)
  504. (*----------------------------------------------------------------------*)
  505.  
  506. PROCEDURE Async_Send_String( S : AnyStr );
  507.  
  508. (*----------------------------------------------------------------------*)
  509. (*                                                                      *)
  510. (*     Procedure:  Async_Send_String                                    *)
  511. (*                                                                      *)
  512. (*     Purpose:    Sends string out over communications port            *)
  513. (*                                                                      *)
  514. (*     Calling Sequence:                                                *)
  515. (*                                                                      *)
  516. (*        Async_Send_String( S : AnyStr );                              *)
  517. (*                                                                      *)
  518. (*           S --- String to send                                       *)
  519. (*                                                                      *)
  520. (*     Calls:  Async_Send                                               *)
  521. (*                                                                      *)
  522. (*----------------------------------------------------------------------*)
  523.  
  524. VAR
  525.    I : INTEGER;
  526.  
  527. BEGIN  (* Async_Send_String *)
  528.  
  529.   FOR I := 1 TO LENGTH( S ) DO
  530.      Async_Send( S[I] )
  531.  
  532. END    (* Async_Send_String *);
  533.  
  534. (*----------------------------------------------------------------------*)
  535. (*     Async_Send_String_With_Delays --- Send string with timed delays  *)
  536. (*----------------------------------------------------------------------*)
  537.  
  538. PROCEDURE Async_Send_String_With_Delays( S          : AnyStr;
  539.                                          Char_Delay : INTEGER;
  540.                                          EOS_Delay  : INTEGER  );
  541.  
  542. (*----------------------------------------------------------------------*)
  543. (*                                                                      *)
  544. (*     Procedure:  Async_Send_String_With_Delays                        *)
  545. (*                                                                      *)
  546. (*     Purpose:    Sends string out over communications port with       *)
  547. (*                 specified delays for each character and at the       *)
  548. (*                 end of the string.                                   *)
  549. (*                                                                      *)
  550. (*     Calling Sequence:                                                *)
  551. (*                                                                      *)
  552. (*        Async_Send_String_With_Delays( S          : AnyStr ;          *)
  553. (*                                       Char_Delay : INTEGER;          *)
  554. (*                                       EOS_Delay  : INTEGER );        *)
  555. (*                                                                      *)
  556. (*           S          --- String to send                              *)
  557. (*           Char_Delay --- Number of milliseconds to delay after       *)
  558. (*                          sending each character                      *)
  559. (*           EOS_Delay  --- Number of milleseconds to delay after       *)
  560. (*                          sending last character in string            *)
  561. (*                                                                      *)
  562. (*     Calls:  Async_Send                                               *)
  563. (*             Async_Send_String                                        *)
  564. (*             Length                                                   *)
  565. (*             Delay                                                    *)
  566. (*                                                                      *)
  567. (*     Remarks:                                                         *)
  568. (*                                                                      *)
  569. (*        This routine is useful when writing routines to perform       *)
  570. (*        non-protocol uploads.  Many computer systems require delays   *)
  571. (*        between receipt of characters for correct processing.  The    *)
  572. (*        delay for end-of-string usually applies when the string       *)
  573. (*        represents an entire line of a file.                          *)
  574. (*                                                                      *)
  575. (*        If delays are not required, Async_Send_String is faster.      *)
  576. (*        This routine will call Async_Send_String is no character      *)
  577. (*        delay is to be done.                                          *)
  578. (*                                                                      *)
  579. (*----------------------------------------------------------------------*)
  580.  
  581. VAR
  582.    I : INTEGER;
  583.  
  584. BEGIN  (* Async_Send_String_With_Delays *)
  585.  
  586.    IF Char_Delay <= 0 THEN
  587.       Async_Send_String( S )
  588.    ELSE
  589.       FOR I := 1 TO LENGTH( S ) DO
  590.          BEGIN
  591.             Async_Send( S[I] );
  592.             Delay( Char_Delay );
  593.          END;
  594.  
  595.    IF EOS_Delay > 0 THEN Delay( EOS_Delay );
  596.  
  597. END    (* Async_Send_String_With_Delays *);
  598.  
  599. (*----------------------------------------------------------------------*)
  600. (*      Async_Percentage_Used --- Report Percentage Buffer Filled       *)
  601. (*----------------------------------------------------------------------*)
  602.  
  603. FUNCTION Async_Percentage_Used : REAL;
  604.  
  605. (*----------------------------------------------------------------------*)
  606. (*                                                                      *)
  607. (*     Function:   Async_Percent_Used                                   *)
  608. (*                                                                      *)
  609. (*     Purpose:    Reports percentage of com buffer currently filled    *)
  610. (*                                                                      *)
  611. (*     Calling Sequence:                                                *)
  612. (*                                                                      *)
  613. (*        Percentage := Async_Percentage_Used : Real;                   *)
  614. (*                                                                      *)
  615. (*           Percentage gets how much of buffer is filled;              *)
  616. (*           value goes from 0.0 (empty) to 1.0 (totally full).         *)
  617. (*                                                                      *)
  618. (*     Calls:  None                                                     *)
  619. (*                                                                      *)
  620. (*     Remarks:                                                         *)
  621. (*                                                                      *)
  622. (*       This routine is helpful when incorporating handshaking into    *)
  623. (*       a communications program.  For example, assume that the host   *)
  624. (*       computer uses the XON/XOFF (DC1/DC3) protocol.  Then the       *)
  625. (*       PC program should issue an XOFF  to the host when the value    *)
  626. (*       returned by Async_Percentage_Used > .75 or so.  When the       *)
  627. (*       utilization percentage drops below .25 or so, the PC program   *)
  628. (*       should transmit an XON.                                        *)
  629. (*                                                                      *)
  630. (*----------------------------------------------------------------------*)
  631.  
  632. BEGIN (* Async_Percentage_Used *)
  633.  
  634.    Async_Percentage_Used := Async_Buffer_Used / ( Async_Buffer_Size + 1 );
  635.  
  636. END   (* Async_Percentage_Used *);
  637.  
  638. (*----------------------------------------------------------------------*)
  639. (*     Async_Purge_Buffer --- Purge communications input buffer         *)
  640. (*----------------------------------------------------------------------*)
  641.  
  642. PROCEDURE Async_Purge_Buffer;
  643.  
  644. (*----------------------------------------------------------------------*)
  645. (*                                                                      *)
  646. (*     Procedure:  Async_Purge_Buffer                                   *)
  647. (*                                                                      *)
  648. (*     Purpose:    Purges communications input buffer                   *)
  649. (*                                                                      *)
  650. (*     Calling Sequence:                                                *)
  651. (*                                                                      *)
  652. (*        Async_Purge_Buffer;                                           *)
  653. (*                                                                      *)
  654. (*     Calls:  Async_Receive                                            *)
  655. (*                                                                      *)
  656. (*----------------------------------------------------------------------*)
  657.  
  658. VAR
  659.    C: CHAR;
  660.    L: INTEGER;
  661.  
  662. BEGIN  (* Async_Purge_Buffer *)
  663.  
  664.    L     := 10000 DIV Async_Baud_Rate;
  665.  
  666.    IF L <= 0 THEN
  667.       L := 3;
  668.  
  669.    REPEAT
  670.       DELAY( L )
  671.    UNTIL ( NOT Async_Receive( C ) );
  672.  
  673. END    (* Async_Purge_Buffer *);
  674.  
  675. (*----------------------------------------------------------------------*)
  676. (*          Async_Peek --- Peek ahead in communications buffer          *)
  677. (*----------------------------------------------------------------------*)
  678.  
  679. FUNCTION Async_Peek( Nchars : INTEGER ) : CHAR;
  680.  
  681. (*----------------------------------------------------------------------*)
  682. (*                                                                      *)
  683. (*     Function:   Async_Peek                                           *)
  684. (*                                                                      *)
  685. (*     Purpose:    Peeks ahead in comm buffer                           *)
  686. (*                                                                      *)
  687. (*     Calling Sequence:                                                *)
  688. (*                                                                      *)
  689. (*        Ch := Async_Peek( NChars: INTEGER) : CHAR;                    *)
  690. (*                                                                      *)
  691. (*           NChars --- # of characters to peek ahead                   *)
  692. (*           Ch     --- returned (peeked) character                     *)
  693. (*                                                                      *)
  694. (*     Calls:  None                                                     *)
  695. (*                                                                      *)
  696. (*----------------------------------------------------------------------*)
  697.  
  698. VAR
  699.    I: INTEGER;
  700.  
  701. BEGIN (* Async_Peek *)
  702.  
  703.    I := ( Async_Buffer_Tail + NChars ) MOD Async_Buffer_Size;
  704.  
  705.    IF ( I > Async_Buffer_Head ) THEN
  706.       Async_Peek := CHR( 0 )
  707.    ELSE
  708.       Async_Peek := Async_Buffer_Ptr^[ I ];
  709.  
  710. END   (* Async_Peek *);
  711.  
  712. (*----------------------------------------------------------------------*)
  713. (*         Async_Setup_Port --- Setup port address and IRQ line         *)
  714. (*----------------------------------------------------------------------*)
  715.  
  716. PROCEDURE Async_Setup_Port( ComPort       : INTEGER;
  717.                             Base_Address  : INTEGER;
  718.                             IRQ_Line      : INTEGER );
  719.  
  720. (*----------------------------------------------------------------------*)
  721. (*                                                                      *)
  722. (*     Procedure:  Async_Setup_Port                                     *)
  723. (*                                                                      *)
  724. (*     Purpose:    Sets up port address and IRQ line                    *)
  725. (*                                                                      *)
  726. (*     Calling Sequence:                                                *)
  727. (*                                                                      *)
  728. (*        Async_Setup_Port( ComPort       : INTEGER;                    *)
  729. (*                          Base_Address  : INTEGER;                    *)
  730. (*                          IRQ_Line      : INTEGER );                  *)
  731. (*                                                                      *)
  732. (*           ComPort      --- which port (1 though MaxComPorts)         *)
  733. (*           Base_Address --- Base address of port.  If -1, then        *)
  734. (*                            standard default address used.            *)
  735. (*           IRQ_Line     --- IRQ line for interrupts for port.  If -1, *)
  736. (*                            then standard default address used.       *)
  737. (*                                                                      *)
  738. (*     Calls:  None                                                     *)
  739. (*                                                                      *)
  740. (*----------------------------------------------------------------------*)
  741.  
  742. VAR
  743.    Port_Offset : INTEGER;
  744.  
  745. BEGIN  (* Async_Setup_Port *)
  746.  
  747.    IF ( ( ComPort > 0 ) AND ( ComPort <= MaxComPorts ) ) THEN
  748.       BEGIN
  749.          IF ( Base_Address = -1 ) THEN
  750.             Base_Address := Default_Com_Base[ComPort];
  751.          IF ( IRQ_Line = -1 ) THEN
  752.             IRQ_Line := Default_Com_IRQ[ComPort];
  753.          Com_Base [ComPort]   := Base_Address;
  754.          Com_Irq  [ComPort]   := IRQ_Line;
  755.          Port_Offset          := RS232_Base + ( PRED( ComPort ) SHL 1 );
  756.          MemW[$0:Port_Offset] := Base_Address;
  757.       END;
  758.  
  759. END    (* Async_Setup_Port *);
  760.  
  761. (*----------------------------------------------------------------------*)
  762. (*         Async_Release_Buffers --- Release buffers for serial ports   *)
  763. (*----------------------------------------------------------------------*)
  764.  
  765. PROCEDURE Async_Release_Buffers;
  766.  
  767. (*----------------------------------------------------------------------*)
  768. (*                                                                      *)
  769. (*     Procedure:  Async_Release_Buffers;                               *)
  770. (*                                                                      *)
  771. (*     Purpose:    Releases send and receive buffers                    *)
  772. (*                                                                      *)
  773. (*     Calling Sequence:                                                *)
  774. (*                                                                      *)
  775. (*        Async_Release_Buffers;                                        *)
  776. (*                                                                      *)
  777. (*     Calls:  None                                                     *)
  778. (*                                                                      *)
  779. (*----------------------------------------------------------------------*)
  780.  
  781. BEGIN  (* Async_Release_Buffers *)
  782.  
  783.                              (* If port open, close it down first.  *)
  784.    IF Async_Open_Flag THEN
  785.       Async_Close( FALSE );
  786.  
  787.    FREEMEM( Async_Buffer_Ptr  , Async_Buffer_Size  + 1 );
  788.    FREEMEM( Async_OBuffer_Ptr , Async_OBuffer_Size + 1 );
  789.  
  790. END    (* Async_Release_Buffers *);
  791.  
  792. (*----------------------------------------------------------------------*)
  793. (*   Async_Flush_Output_Buffer --- Flush output buffer for serial port  *)
  794. (*----------------------------------------------------------------------*)
  795.  
  796. PROCEDURE Async_Flush_Output_Buffer;
  797.  
  798. (*----------------------------------------------------------------------*)
  799. (*                                                                      *)
  800. (*     Procedure:  Async_Flush_Output_Buffer;                           *)
  801. (*                                                                      *)
  802. (*     Purpose:    Flushes output buffer for serial port.               *)
  803. (*                                                                      *)
  804. (*     Calling Sequence:                                                *)
  805. (*                                                                      *)
  806. (*        Async_Flush_Output_Buffer;                                    *)
  807. (*                                                                      *)
  808. (*     Calls:  None                                                     *)
  809. (*                                                                      *)
  810. (*----------------------------------------------------------------------*)
  811.  
  812. BEGIN  (* Async_Flush_Output_Buffer *)
  813.  
  814.    Async_OBuffer_Head  := Async_OBuffer_Tail;
  815.    Async_OBuffer_Used  := 0;
  816.  
  817. END    (* Async_Flush_Output_Buffer *);
  818.  
  819. (*----------------------------------------------------------------------*)
  820. (*   Async_Drain_Output_Buffer --- Wait for output buffer to drain      *)
  821. (*----------------------------------------------------------------------*)
  822.  
  823. PROCEDURE Async_Drain_Output_Buffer( Max_Wait_Time : INTEGER );
  824.  
  825. (*----------------------------------------------------------------------*)
  826. (*                                                                      *)
  827. (*     Procedure:  Async_Drain_Output_Buffer;                           *)
  828. (*                                                                      *)
  829. (*     Purpose:    Waits for output buffer to drain.                    *)
  830. (*                                                                      *)
  831. (*     Calling Sequence:                                                *)
  832. (*                                                                      *)
  833. (*        Async_Drain_Output_Buffer( Max_Wait_Time : INTEGER );         *)
  834. (*                                                                      *)
  835. (*           Max_Wait_Time --- Maximum # of seconds to wait for         *)
  836. (*                             output buffer to drain.                  *)
  837. (*                                                                      *)
  838. (*     Calls:  TimeOfDay                                                *)
  839. (*             TimeDiff                                                 *)
  840. (*             GiveAwayTime                                             *)
  841. (*                                                                      *)
  842. (*----------------------------------------------------------------------*)
  843.  
  844. VAR
  845.    T1 : LONGINT;
  846.  
  847. BEGIN  (* Async_Drain_Output_Buffer *)
  848.  
  849.    T1 := TimeOfDay;
  850.  
  851.    WHILE( ( Async_OBuffer_Head <> Async_OBuffer_Tail    ) AND
  852.           ( TimeDiff( T1 , TimeOfDay ) <= Max_Wait_Time )     ) DO
  853. {$IFDEF MTASK}
  854.       GiveAwayTime( 1 );
  855. {$ELSE}
  856.       ;
  857. {$ENDIF}
  858.  
  859. END    (* Async_Drain_Output_Buffer *);
  860.  
  861. (*----------------------------------------------------------------------*)
  862. (*   Async_Port_Address_Given --- Check if port address in memory       *)
  863. (*----------------------------------------------------------------------*)
  864.  
  865. FUNCTION Async_Port_Address_Given( Com_Port : INTEGER ) : BOOLEAN;
  866.  
  867. (*----------------------------------------------------------------------*)
  868. (*                                                                      *)
  869. (*     Procedure:  Async_Port_Address_Given;                            *)
  870. (*                                                                      *)
  871. (*     Purpose:    Checks if port address in memory.                    *)
  872. (*                                                                      *)
  873. (*     Calling Sequence:                                                *)
  874. (*                                                                      *)
  875. (*        There := Async_Port_Address_Given( Com_Port : INTEGER ) :     *)
  876. (*                                         BOOLEAN;                     *)
  877. (*                                                                      *)
  878. (*           Com_Port --- Port to check (1 through MaxComPorts)         *)
  879. (*           There    --- TRUE if port address in memory.               *)
  880. (*                                                                      *)
  881. (*----------------------------------------------------------------------*)
  882.  
  883. VAR
  884.    Port_Offset : INTEGER;
  885.  
  886. BEGIN  (* Async_Port_Address_Given *)
  887.  
  888.    IF ( ( Com_Port > 0 ) AND ( Com_Port < MaxComPorts ) ) THEN
  889.       BEGIN
  890.          Port_Offset              := RS232_Base + ( PRED( Com_Port ) SHL 1 );
  891.          Async_Port_Address_Given := ( MemW[$0:Port_Offset] <> 0 );
  892.       END
  893.    ELSE
  894.       Async_Port_Address_Given := FALSE;
  895.  
  896. END    (* Async_Port_Address_Given *);
  897.