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

  1. (*----------------------------------------------------------------------*)
  2. (*          Async_Send --- Send character over communications port      *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Async_Send( C : Char );
  6.  
  7. (*----------------------------------------------------------------------*)
  8. (*                                                                      *)
  9. (*     Procedure:  Async_Send                                           *)
  10. (*                                                                      *)
  11. (*     Purpose:    Sends character out over communications port         *)
  12. (*                                                                      *)
  13. (*     Calling Sequence:                                                *)
  14. (*                                                                      *)
  15. (*        Async_Send( C : Char );                                       *)
  16. (*                                                                      *)
  17. (*           C --- Character to send                                    *)
  18. (*                                                                      *)
  19. (*     Calls:  None                                                     *)
  20. (*                                                                      *)
  21. (*----------------------------------------------------------------------*)
  22.  
  23. BEGIN   (* Async_Send *)
  24.  
  25. INLINE(
  26.   $8B/$1E/>ASYNC_OBUFFER_HEAD/         {         MOV     BX,[>Async_OBuffer_Head]   ;Get output queue head pointer}
  27.   $C4/$3E/>ASYNC_OBUFFER_PTR/          {         LES     DI,[>Async_OBuffer_Ptr]    ;Pick up output buffer address}
  28.   $01/$DF/                             {         ADD     DI,BX                      ;Position to current character}
  29.                                        {;}
  30.   $89/$DA/                             {         MOV     DX,BX                      ;Save previous head pointer}
  31.   $43/                                 {         INC     BX                         ;Increment head pointer}
  32.   $3B/$1E/>ASYNC_OBUFFER_SIZE/         {         CMP     BX,[>Async_OBuffer_Size]   ;See if past end of buffer}
  33.   $7E/$02/                             {         JLE     Send1                      ;Skip if not}
  34.   $31/$DB/                             {         XOR     BX,BX                      ;Wrap to start of buffer}
  35.                                        {;}
  36.   $3B/$1E/>ASYNC_OBUFFER_TAIL/         {Send1:   CMP     BX,[>Async_OBuffer_Tail]   ;See if head collided with tail}
  37.   $75/$1C/                             {         JNE     Send4                      ;No -- buffer didn't fill up}
  38.                                        {;}
  39.   $8B/$0E/>ASYNC_OUTPUT_DELAY/         {         MOV     CX,[>Async_Output_Delay]   ;Run delay loop and see if buffer drains}
  40.                                        {;}
  41.   $51/                                 {Send2:   PUSH    CX                         ;Save milleseconds to go}
  42.   $8B/$0E/>ASYNC_ONEMSDELAY/           {         MOV     CX,[>Async_OneMSDelay]     ;Get delay loop value for 1 ms}
  43.                                        {;}
  44.   $E2/$FE/                             {Send3:   LOOP    Send3                      ;Tight loop for 1 ms delay}
  45.                                        {;}
  46.   $59/                                 {         POP     CX                         ;Get back millesecond count}
  47.                                        {;}
  48.   $3B/$1E/>ASYNC_OBUFFER_TAIL/         {         CMP     BX,[>Async_OBuffer_Tail]   ;See if buffer drained yet}
  49.   $75/$0A/                             {         JNE     Send4                      ;Yes -- OK, stop delay loop.}
  50.                                        {;}
  51.   $E2/$F0/                             {         LOOP    Send2                      ;Decrement millesecond count and loop}
  52.                                        {;}
  53.   $C6/$06/>ASYNC_OBUFFER_OVERFLOW/$01/ {         MOV     BYTE [>Async_OBuffer_Overflow],1 ;Indicate output buffer overflow}
  54.   $E9/$1A/$00/                         {         JMP     Send5                      ;Skip updating head pointers}
  55.                                        {;}
  56.   $89/$1E/>ASYNC_OBUFFER_HEAD/         {Send4:   MOV     [>Async_OBuffer_Head],BX   ;Save updated head pointer}
  57.   $8A/$46/<C/                          {         MOV     AL,[BP+<C]                 ;Pick up character to send}
  58.   $26/$88/$05/                         {     ES: MOV     [DI],AL                    ;Place character in output buffer}
  59.                                        {;}
  60.   $A1/>ASYNC_OBUFFER_USED/             {         MOV     AX,[>Async_OBuffer_Used]   ;Get buffer use count}
  61.   $40/                                 {         INC     AX                         ;Increment buffer use count}
  62.   $A3/>ASYNC_OBUFFER_USED/             {         MOV     [>Async_OBuffer_Used],AX   ;Save new count}
  63.   $3B/$06/>ASYNC_MAXOBUFFERUSED/       {         CMP     AX,[>Async_MaxOBufferUsed] ;See if larger than ever before}
  64.   $7E/$03/                             {         JLE     Send5                      ;Skip if not}
  65.   $A3/>ASYNC_MAXOBUFFERUSED/           {         MOV     [>Async_MaxOBufferUsed],AX ;Save new maximum usage}
  66.                                        {;}
  67.   $8B/$16/>ASYNC_UART_IER/             {Send5:   MOV     DX,[>Async_Uart_IER]       ;Get interrupt enable register}
  68.   $EC/                                 {         IN      AL,DX                      ;Check contents of IER}
  69.   $A8/$02/                             {         TEST    AL,2                       ;See if write interrupt enabled}
  70.   $75/$03/                             {         JNZ     Send6                      ;Skip if so}
  71.   $0C/$02/                             {         OR      AL,2                       ;Else enable write interrupts ...}
  72.   $EE);                                {         OUT     DX,AL                      ;... by rewriting IER contents}
  73.                                        {;}
  74.                                        {Send6:}
  75.  
  76. END    (* Async_Send *);
  77.  
  78. (*----------------------------------------------------------------------*)
  79. (*          Async_Receive --- Return character from buffer              *)
  80. (*----------------------------------------------------------------------*)
  81.  
  82. FUNCTION Async_Receive( VAR C : Char ) : BOOLEAN;
  83.  
  84. (*----------------------------------------------------------------------*)
  85. (*                                                                      *)
  86. (*     Function:   Async_Receive                                        *)
  87. (*                                                                      *)
  88. (*     Purpose:    Retrieve character (if any) from buffer              *)
  89. (*                                                                      *)
  90. (*     Calling Sequence:                                                *)
  91. (*                                                                      *)
  92. (*        Flag := Async_Receive( VAR C: Char ) : BOOLEAN;               *)
  93. (*                                                                      *)
  94. (*           C --- character (if any) retrieved from buffer;            *)
  95. (*                 set to CHR(0) if no character available.             *)
  96. (*                                                                      *)
  97. (*           Flag returned TRUE if character retrieved from buffer,     *)
  98. (*           Flag returned FALSE if no character retrieved.             *)
  99. (*                                                                      *)
  100. (*     Calls:  None                                                     *)
  101. (*                                                                      *)
  102. (*----------------------------------------------------------------------*)
  103.  
  104. BEGIN   (* Async_Receive *)
  105.  
  106. INLINE(
  107.                                   {;}
  108.                                   {;  Check if any characters in input comm buffer}
  109.                                   {;}
  110.   $A1/>ASYNC_BUFFER_TAIL/         {         MOV   AX,[>Async_Buffer_Tail]}
  111.   $3B/$06/>ASYNC_BUFFER_HEAD/     {         CMP   AX,[>Async_Buffer_Head]}
  112.   $75/$0B/                        {         JNE   Rec1}
  113.                                   {;}
  114.                                   {;  Buffer is empty -- return NUL character}
  115.                                   {;}
  116.   $C4/$7E/<C/                     {         LES   DI,[BP+<C]                   ;Get character address}
  117.   $31/$C0/                        {         XOR   AX,AX                        ;Clear out unused bits}
  118.   $26/$88/$05/                    {     ES: MOV   [DI],AL                      ;NUL character}
  119.   $E9/$3F/$00/                    {         JMP   Return}
  120.                                   {;}
  121.                                   {;  Buffer not empty -- pick up next character.}
  122.                                   {;}
  123.   $C4/$3E/>ASYNC_BUFFER_PTR/      {Rec1:    LES   DI,[>Async_Buffer_Ptr]       ;Pick up buffer address}
  124.   $01/$C7/                        {         ADD   DI,AX                        ;Add character offset}
  125.   $26/$8A/$1D/                    {     ES: MOV   BL,[DI]                      ;Get character from buffer}
  126.   $C4/$7E/<C/                     {         LES   DI,[BP+<C]                   ;Get result address}
  127.   $26/$88/$1D/                    {     ES: MOV   [DI],BL                      ;Store character from buffer}
  128.   $40/                            {         INC   AX                           ;Increment tail pointer}
  129.   $3B/$06/>ASYNC_BUFFER_SIZE/     {         CMP   AX,[>Async_Buffer_Size]      ;Past end of buffer?}
  130.   $7E/$02/                        {         JLE   Rec2                         ;No -- skip wrapping}
  131.   $31/$C0/                        {         XOR   AX,AX                        ;Yes -- point to start of buffer}
  132.   $A3/>ASYNC_BUFFER_TAIL/         {Rec2:    MOV   [>Async_Buffer_Tail],AX      ;Update tail pointer}
  133.   $FF/$0E/>ASYNC_BUFFER_USED/     {         DEC   Word [>Async_Buffer_Used]    ;Update buffer use count}
  134.                                   {;}
  135.                                   {; If XOFF previously sent because buffer was too full, and}
  136.                                   {; now buffer is reasonably empty, send XON to get things rolling again.}
  137.                                   {;}
  138.   $F6/$06/>ASYNC_XOFF_SENT/$01/   {         TEST  BYTE [<Async_XOff_Sent],1    ;Check if Xoff sent}
  139.   $74/$16/                        {         JZ    Rec3                         ;No -- skip.}
  140.                                   {;}
  141.   $A1/>ASYNC_BUFFER_USED/         {         MOV   AX,[>Async_Buffer_Used]      ;Pick up amount of buffer used}
  142.   $3B/$06/>ASYNC_BUFFER_LOW/      {         CMP   AX,[>Async_Buffer_Low]       ;Check if low enough}
  143.   $7F/$0D/                        {         JG    Rec3                         ;Still too full, skip}
  144.                                   {;}
  145.   $B8/>XON/                       {         MOV   AX,>XON                      ;Else push XON onto stack}
  146.   $50/                            {         PUSH  AX}
  147.   $FF/$1E/>ASYNC_SEND_ADDR/       {         CALL  FAR [>Async_Send_Addr]       ;Call output routine}
  148.                                   {;}
  149.   $C6/$06/>ASYNC_XOFF_SENT/$00/   {         MOV   BYTE [>Async_XOff_Sent],0    ;Clear Xoff flag}
  150.                                   {;}
  151.                                   {;  Indicate character found}
  152.                                   {;}
  153.   $B8/$01/$00/                    {Rec3:    MOV    AX,1}
  154.                                   {;}
  155.   $80/$26/>ASYNC_LINE_STATUS/$FD/ {Return:  AND    Byte [>Async_Line_Status],$FD ;Remove overflow flag}
  156.   $09/$C0/                        {         OR     AX,AX                       ;Set zero flag to indicate return status}
  157.   $89/$EC/                        {         MOV    SP,BP}
  158.   $5D/                            {         POP    BP}
  159.   $CA/$04/$00);                   {         RETF   4}
  160.  
  161. END   (* Async_Receive *);
  162.  
  163. (*----------------------------------------------------------------------*)
  164. (*   Async_Receive_With_TimeOut --- Return char. from buffer with delay *)
  165. (*----------------------------------------------------------------------*)
  166.  
  167. PROCEDURE Async_Receive_With_Timeout( Secs : INTEGER; VAR C : INTEGER );
  168.  
  169. (*----------------------------------------------------------------------*)
  170. (*                                                                      *)
  171. (*     Procedure:  Async_Receive_With_Timeout                           *)
  172. (*                                                                      *)
  173. (*     Purpose:    Retrieve character as integer from buffer,           *)
  174. (*                 or return TimeOut if specified delay period          *)
  175. (*                 expires.                                             *)
  176. (*                                                                      *)
  177. (*     Calling Sequence:                                                *)
  178. (*                                                                      *)
  179. (*        Async_Receive_With_Timeout( Secs: INTEGER; VAR C: INTEGER );  *)
  180. (*                                                                      *)
  181. (*           Secs ---  Timeout period in seconds                        *)
  182. (*                     NOTE:  Cannot be longer than 32 seconds!         *)
  183. (*           C     --- ORD(character) (if any) retrieved from buffer;   *)
  184. (*                     set to TimeOut if no character found before      *)
  185. (*                     delay period expires.                            *)
  186. (*                                                                      *)
  187. (*     Calls:  Async_Receive                                            *)
  188. (*                                                                      *)
  189. (*     WATCH OUT!  THIS ROUTINE RETURNS AN INTEGER, NOT A CHARACTER!!!  *)
  190. (*                                                                      *)
  191. (*----------------------------------------------------------------------*)
  192.  
  193. BEGIN (* Async_Receive_With_Timeout *)
  194.  
  195. INLINE(
  196.                                   {;}
  197.                                   {;  Check if a character in input comm buffer}
  198.                                   {;}
  199.   $A1/>ASYNC_BUFFER_TAIL/         {         MOV   AX,[>Async_Buffer_Tail]}
  200.   $3B/$06/>ASYNC_BUFFER_HEAD/     {         CMP   AX,[>Async_Buffer_Head]}
  201.   $75/$29/                        {         JNE   Rec1}
  202.                                   {;}
  203.                                   {;  Buffer empty -- begin wait loop.}
  204.                                   {;}
  205.   $8B/$46/<SECS/                  {         MOV   AX,[BP+<Secs]                 ;Get seconds to wait}
  206.   $B9/$0A/$00/                    {         MOV   CX,10                         ;Shift count = 2 ** 10 = 1024}
  207.   $D3/$E0/                        {         SHL   AX,CL                         ;Seconds * 1024 = milleseconds}
  208.   $89/$C1/                        {         MOV   CX,AX                         ;Move to looping register}
  209.                                   {;}
  210.                                   {;  Delay for 1 ms.}
  211.                                   {;}
  212.   $51/                            {Delay:   PUSH  CX                            ;Save milleseconds to go}
  213.   $8B/$0E/>ASYNC_ONEMSDELAY/      {         MOV   CX,[>Async_OneMSDelay]        ;Get delay loop value for 1 ms}
  214.   $E2/$FE/                        {Delay1:  LOOP  Delay1                        ;Tight loop for 1 ms delay}
  215.                                   {;}
  216.                                   {;  Check if any character yet.}
  217.                                   {;}
  218.   $59/                            {         POP   CX                            ;Get back millesecond count}
  219.                                   {;}
  220.   $A1/>ASYNC_BUFFER_TAIL/         {         MOV   AX,[>Async_Buffer_Tail]}
  221.   $3B/$06/>ASYNC_BUFFER_HEAD/     {         CMP   AX,[>Async_Buffer_Head]}
  222.   $75/$0E/                        {         JNE   Rec1}
  223.                                   {;}
  224.                                   {;  Buffer still empty -- decrement elapsed time}
  225.                                   {;}
  226.   $E2/$ED/                        {         LOOP  Delay                         ;Decrement millesecond count and loop}
  227.                                   {;}
  228.                                   {;  Dropped through -- no character arrived in specified interval.}
  229.                                   {;  Return TimeOut as result.}
  230.                                   {;}
  231.   $BB/>TIMEOUT/                   {         MOV   BX,>TimeOut                   ;Pick up timeout value}
  232.   $C4/$7E/<C/                     {         LES   DI,[BP+<C]                    ;Get result character address}
  233.   $26/$89/$1D/                    {    ES:  MOV   [DI],BX                       ;Store timeout value}
  234.   $E9/$3E/$00/                    {         JMP   Return                        ;Return to caller}
  235.                                   {;}
  236.                                   {;  Buffer not empty -- pick up next character.}
  237.                                   {;}
  238.   $C4/$3E/>ASYNC_BUFFER_PTR/      {Rec1:    LES   DI,[>Async_Buffer_Ptr]        ;Pick up buffer address}
  239.   $01/$C7/                        {         ADD   DI,AX                         ;Add character offset}
  240.   $26/$8A/$1D/                    {     ES: MOV   BL,[DI]                       ;Get character from buffer}
  241.                                   {;}
  242.   $30/$FF/                        {         XOR   BH,BH                         ;Clear high-order bits}
  243.   $C4/$7E/<C/                     {         LES   DI,[BP+<C]                    ;Get result address}
  244.   $26/$89/$1D/                    {     ES: MOV   [DI],BX                       ;Store character from buffer}
  245.                                   {;}
  246.   $40/                            {         INC   AX                            ;Increment tail pointer}
  247.   $3B/$06/>ASYNC_BUFFER_SIZE/     {         CMP   AX,[>Async_Buffer_Size]       ;Past end of buffer?}
  248.   $7E/$02/                        {         JLE   Rec2                          ;No -- skip wrapping}
  249.   $31/$C0/                        {         XOR   AX,AX                         ;Yes -- point to start of buffer}
  250.   $A3/>ASYNC_BUFFER_TAIL/         {Rec2:    MOV   [>Async_Buffer_Tail],AX       ;Update tail pointer}
  251.   $FF/$0E/>ASYNC_BUFFER_USED/     {         DEC   Word [>Async_Buffer_Used]     ;Update buffer usage count}
  252.                                   {;}
  253.                                   {; If XOFF previously sent because buffer was too full, and}
  254.                                   {; now buffer is reasonably empty, send XON to get things rolling again.}
  255.                                   {;}
  256.   $F6/$06/>ASYNC_XOFF_SENT/$01/   {         TEST  BYTE [<Async_XOff_Sent],1     ;Check if Xoff sent}
  257.   $74/$16/                        {         JZ    Return                        ;No -- skip.}
  258.                                   {;}
  259.   $A1/>ASYNC_BUFFER_USED/         {         MOV   AX,[>Async_Buffer_Used]       ;Pick up amount of buffer used}
  260.   $3B/$06/>ASYNC_BUFFER_LOW/      {         CMP   AX,[>Async_Buffer_Low]        ;Check if low enough}
  261.   $7F/$0D/                        {         JG    Return                        ;Still too full, skip}
  262.                                   {;}
  263.   $B8/>XON/                       {         MOV   AX,>XON                       ;Push XON onto stack}
  264.   $50/                            {         PUSH  AX}
  265.   $FF/$1E/>ASYNC_SEND_ADDR/       {         CALL  FAR [>Async_Send_Addr]        ;Call output routine}
  266.                                   {;}
  267.   $C6/$06/>ASYNC_XOFF_SENT/$00/   {         MOV   BYTE [>Async_XOff_Sent],0     ;Clear Xoff flag}
  268.                                   {;}
  269.   $80/$26/>ASYNC_LINE_STATUS/$FD);{Return:  AND   Byte [>Async_Line_Status],$FD ;Remove overflow flag}
  270.  
  271. END   (* Async_Receive_With_Timeout *);
  272.  
  273. (*----------------------------------------------------------------------*)
  274. (*        Async_Stuff --- Stuff character into receive buffer           *)
  275. (*----------------------------------------------------------------------*)
  276.  
  277. PROCEDURE Async_Stuff( Ch: CHAR );
  278.  
  279. (*----------------------------------------------------------------------*)
  280. (*                                                                      *)
  281. (*     Procedure:  Async_Stuff                                          *)
  282. (*                                                                      *)
  283. (*     Purpose:    Stuffs a character into receive buffer               *)
  284. (*                                                                      *)
  285. (*     Calling Sequence:                                                *)
  286. (*                                                                      *)
  287. (*        Async_Stuff( Ch : Char );                                     *)
  288. (*                                                                      *)
  289. (*           Ch --- Character to stuff                                  *)
  290. (*                                                                      *)
  291. (*     Calls:  None                                                     *)
  292. (*                                                                      *)
  293. (*----------------------------------------------------------------------*)
  294.  
  295. VAR
  296.    New_Head : INTEGER;
  297.  
  298. BEGIN (* Async_Stuff *)
  299.  
  300.    Async_Buffer_Ptr^[Async_Buffer_Head] := Ch;
  301.    New_Head                             := SUCC( Async_Buffer_Head ) MOD
  302.                                            SUCC( Async_Buffer_Size );
  303.  
  304.    IF ( New_Head = Async_Buffer_Tail ) THEN
  305.       Async_Buffer_Overflow := TRUE
  306.    ELSE
  307.       BEGIN
  308.          Async_Buffer_Head := New_Head;
  309.          Async_Buffer_Used := SUCC( Async_Buffer_Used );
  310.          IF ( Async_Buffer_Used > Async_MaxBufferUsed ) THEN
  311.             Async_MaxBufferUsed := Async_Buffer_Used
  312.       END;
  313.  
  314. END   (* Async_Stuff *);
  315.