home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 9 / CDACTUAL9.iso / share / Dos / VARIOS / pascal / COMM.SWG / 0003_Simplified and FAST COMM Routines.pas < prev   
Encoding:
Pascal/Delphi Source File  |  1996-02-21  |  7.8 KB  |  244 lines

  1. {
  2. I am using a PCCOM 4-port serial card and this unit works with a small test
  3. program but when I use it in a larger program (executable approx 48k) I only
  4. get some of the characters from the port.
  5. The serial card is 16450 based with vector at $02BF..
  6. I have done very little interrupt programming so I don't know if that is the
  7. problem.
  8.  
  9. Thanks........
  10. }
  11. unit mycom;
  12.  
  13. interface
  14.  
  15. procedure Async_ISR; interrupt;
  16. procedure XmitChar(Serial_IOPort:byte;C: char);  { Uses variable and constant declarations from}
  17. function  RemoteReadKey(Serial_IOPort:byte): char;  { Uses var and const from above }
  18. function  RemoteKeyPressed(Serial_IOPort:byte):boolean;  { Uses vars and consts from above }
  19. procedure InitPort(Serial_IOPort:byte);
  20. procedure InitInter;
  21. procedure TerminateInter;
  22. function  COM_BufSize (Serial_IOPort:byte):byte;
  23.  
  24. implementation
  25.  
  26.  
  27. USES DOS,crt;
  28.  
  29. var COM_mask:byte;
  30.     COM_Buffer: array [0..3] of array[0 .. 129] of char;  { A buffer for input}
  31.     COM_Temp,  { Varible to hold various modem statuses }
  32.     COM_CommPort: byte;  { Comm Port in use }
  33.     COM_Head : array [0..3] of byte;  { Size of the buffer }
  34.     OldInt0Dh :pointer;
  35.     OldPIC:byte;
  36.  
  37. const COM_IRQ_Number = $07;
  38.       COM_IRQ_Vector = $0F;
  39.  
  40.  
  41. const
  42.   BaseAddr: array[0 .. 3] of word = ($02A0, $02A8, $02B0, $02B8);
  43.   Baud=38400;                     { Speed required }
  44.   Divisor:word = 115200 div Baud; { or 1843200 / (16 * Baud) }
  45.                                   {    ^   UART clock speed  }
  46.  
  47. procedure Async_ISR;
  48.    CONST Buf_Pnt:POINTER=@COM_Buffer;
  49.  
  50.   begin
  51. {  WRITE('*'); }
  52.   asm
  53.   STI { STI - Disable interrupts }
  54.   PUSHA
  55.   PUSH SS
  56.   MOV CL,00           { Com Port Counter 0 - 3 => COM5 - COM8}
  57. @NextVector:
  58.   MOV DX, 02BFh               { WHO WANTED AN INTERRUPT ? }
  59.   MOV BL,01
  60.   SHL BL,CL
  61.   IN AL,DX
  62.   TEST AL,BL
  63.   JNZ @CheckNextVector
  64.   MOV DX, 02A0h               { BASE OF FIRST PORT }
  65.   MOV AL,08
  66.   MUL CL
  67.   ADD DX,AX                  { GOT BASE ADDRESS IN DX }
  68. @GoBackForMore:
  69.   ADD DX,02h
  70.   IN AL,DX                   { CHECK INTERRUPT ID REGISTER }
  71.   SUB DX,02h
  72.   TEST AL,01h                { NO IRQ PENDING }
  73.   JNZ @CheckNextVector
  74.   AND AL,06h
  75.   CMP AL,04h                  { DID WE RECEIVE A CHARACTER }
  76.   JNZ @CheckMore               { NO ? THEN WHAT ELSE }
  77.   IN AL,DX                    { READ INPUT FROM PORT }
  78.   MOV BH,AL                   { PUT DATA IN BH FOR LATER }
  79.   LDS SI,Buf_Pnt
  80.   LES DI,Buf_Pnt
  81.   MOV AL,130            { SIZE OF BUFFER + 2 for size & tail pointer }
  82.   MUL CL
  83.   ADD SI,AX
  84.   ADD DI,AX                    { FOUND BUFFER[COM_PORT] }
  85.   LODSB
  86.   CMP AL,127                  { IF BUFFER FULL IGNORE CHARACTER }
  87.   JA @CheckForAnotherIRQ
  88.   INC AL                      { INC SIZE IF ROOM }
  89.   STOSB                       { WRITE BACK TO SIZE COUNTER }
  90.   LODSB                        { tail pointer }
  91.   MOV BL,AL                    { PUT TAIL POINTER IN BL }
  92.   INC AL
  93.   CMP AL,128
  94.   JB @WriteTail
  95.   MOV AL,0
  96. @WriteTail:
  97.   STOSB
  98.   MOV AL,BH                    { GET BACK DATA FROM BH }
  99.   MOV BH,0
  100.   ADD DI,BX                    { ADD CONTENTS OF TAIL POINTER TO POINTER }
  101.   STOSB                        { WRITE DATA TO BUFFER }
  102.   JMP @CheckForAnotherIRQ
  103. @CheckMore:
  104.   CMP AH,02h                  { THD EMPTY }
  105.   JNZ @CheckMore2
  106.  
  107.   
  108.   { FOR LATER ADDITION OF INTERRUPT SEND ROUTINE }
  109.  
  110.  
  111.   JMP @CheckForAnotherIRQ
  112. @CheckMore2:
  113.   CMP AH,06h                  { ERROR OR BREAK }
  114.   JNZ @CheckForAnotherIRQ
  115.   IN AL,DX                    { READ FROM PORT TO CLEAR OVERRUNS }
  116.   ADD DX,05h
  117.   IN AL,DX                    { READ LINE STATUS REGISTER }
  118.   SUB DX,05h
  119. @CheckForAnotherIRQ:
  120.   JMP @GoBackForMore        { ANOTHER INTERRUPT ON THIS PORT }
  121.  
  122. @CheckNextVector:
  123.   INC CL
  124.   CMP CL,04h
  125.   JNZ @NextVector
  126.   MOV DX,0020h
  127.   MOV AL,20h
  128.   OUT DX,AL    { RESET PIC }
  129.   POP SS
  130.   POPA
  131.   CLI          { CLI - Enable interrupts }
  132.  
  133.   end;
  134. end;
  135.  
  136.  
  137.  
  138. procedure XmitChar(Serial_IOPort:byte;C: char);  { Uses variable and constant declarations from}
  139. begin                         {  the previous example }
  140.   repeat
  141. {  write ('.');}
  142.   until (port[BaseAddr[Serial_IOPort] + $05] and $20 = $20);  { Wait for THR }
  143.  
  144.   port[BaseAddr[Serial_IOPort]] := Ord(C);  { Send character }
  145.  
  146. {  textcolor(red);
  147.   write(ord(c));
  148.   write('.');
  149.   textcolor(lightgray);}
  150. end;
  151.  
  152.  
  153. function RemoteReadKey(Serial_IOPort:byte): char;  { Uses var and const from above }
  154. begin
  155.   if ord(COM_Buffer[Serial_IOPort][0]) > 0 then begin
  156. RemoteReadKey := COM_Buffer[Serial_IOPort][COM_Head[Serial_IOPort]+2];  {Get the character }
  157. inc(COM_Head[Serial_IOPort]);  { Move Head to the nextcharacter }
  158. if COM_Head[Serial_IOPort] > 127 then COM_Head[Serial_IOPort] := 0;  { Wrap Head around if necessary }
  159. dec(COM_Buffer[Serial_IOPort][0]);  {Remove the character }  end
  160.   else RemoteReadKey:=chr(0);
  161. end;
  162.  
  163.  
  164. function RemoteKeyPressed(Serial_IOPort:byte): boolean;  { Uses vars and consts from above }
  165. begin
  166.   RemoteKeyPressed := ord(COM_Buffer[Serial_IOPort][0]) > 0;  { A key was pressed if there is data in}
  167.   end;                             {  the buffer }
  168.  
  169. procedure InitPort(Serial_IOPort:byte);
  170.           var COM_tt:byte;
  171.           begin
  172.           inline($FB); { STI - Disable interrupts }
  173.           Port[BaseAddr[Serial_IOPort]+$03]:=Port[BaseAddr[Serial_IOPort]+$03] or 128;
  174.           { Ready to set Port speed }
  175.           Port[BaseAddr[Serial_IOPort]]:= Lo(Divisor);
  176.           Port[BaseAddr[Serial_IOPort]+$01]:= Hi(Divisor);  { Set Speed to 38400 }
  177.           Port[BaseAddr[Serial_IOPort]+$03]:= $03 or $08 or $00;
  178.                   { end set port speed and set 8  -   O  -   1 }
  179.           Port[BaseAddr[Serial_IOPort]+$01]:= $01;
  180.                    { set Interrupt enable on Rx Data }
  181.           COM_tt:=Port[BaseAddr[Serial_IOPort]];
  182.           COM_tt:=Port[BaseAddr[Serial_IOPort]+1];
  183.           COM_tt:=Port[BaseAddr[Serial_IOPort]+2];
  184.           COM_tt:=Port[BaseAddr[Serial_IOPort]+3];
  185.           COM_tt:=Port[BaseAddr[Serial_IOPort]+4];
  186.           COM_tt:=Port[BaseAddr[Serial_IOPort]+5];
  187.           COM_tt:=Port[BaseAddr[Serial_IOPort]+6];
  188.           Port[BaseAddr[Serial_IOPort]]:=0;
  189.  
  190.   COM_Head[Serial_IOPort]:=0;
  191.   COM_Buffer[Serial_IOPort][1]:=CHR(0);  { tail }
  192.   COM_Buffer[Serial_IOPort][0]:=chr(0);  { size }
  193.  
  194.   inline($FA);  { CLI - Enable interrupts }
  195.           end;
  196.  
  197.  
  198. procedure InitInter;
  199.            begin
  200.            InitPort (0);
  201.            InitPort (1);
  202.            InitPort (2);
  203.            InitPort (3);
  204.                Port[$02BF]:=$ff;
  205.                GetIntVec(COM_IRQ_vector, OldInt0Dh);
  206.                SetIntVec(COM_IRQ_vector, @Async_ISR);
  207.                COM_mask := (1 shl (COM_IRQ_number)) xor $00FF;
  208.                OldPic:=Port[$21];
  209.                Port[$21] := OldPIC and COM_mask;
  210.            end;
  211.  
  212. procedure TerminateInter;
  213.           var Serial_IOPort,com_tt:byte;
  214.           begin
  215. {             COM_mask := 1 shl (COM_IRQ_number);}
  216.              SetIntVec(COM_IRQ_vector, OldInt0Dh);
  217.           for Serial_IOPort := 0 to 3 do begin
  218.                    { set Interrupt enable off }
  219.           COM_tt:=Port[BaseAddr[Serial_IOPort]];
  220.           COM_tt:=Port[BaseAddr[Serial_IOPort]+1];
  221.           COM_tt:=Port[BaseAddr[Serial_IOPort]+2];
  222.           COM_tt:=Port[BaseAddr[Serial_IOPort]+3];
  223.           COM_tt:=Port[BaseAddr[Serial_IOPort]+4];
  224.           COM_tt:=Port[BaseAddr[Serial_IOPort]+5];
  225.           COM_tt:=Port[BaseAddr[Serial_IOPort]+6];
  226.           Port[BaseAddr[Serial_IOPort]]:=0;
  227.           Port[BaseAddr[Serial_IOPort]+$01]:= $00;
  228.              Port[$21] := Port[$21] and OldPIC;
  229.           end;
  230.              END;
  231.  
  232. function COM_BufSize (Serial_IOPort:byte):byte;
  233.          begin
  234.          COM_BufSize:=ord(COM_Buffer[Serial_IOPort][0]);
  235.          end;
  236.  
  237. end.
  238.  
  239.  
  240. Com_Buffer Structure:
  241. Byte 0 -  number of characters in buffer
  242. Byte 1 -  tail ponter in buffer
  243. 2-129  -  128 bytes (the buffer)
  244.