home *** CD-ROM | disk | FTP | other *** search
/ Fifty: Elektronik / FIFTY Elektronik (PS_Computer_Vertrieb).iso / ps8 / fty1017 / gepackt.exe / DISK2 / PLOTSRC.EXE / SERINOUT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1993-11-10  |  8.0 KB  |  281 lines

  1. {$R-,I-,S-}
  2. unit SERINOUT;
  3.  
  4. interface
  5.  
  6. uses Time,Dos;
  7.  
  8. Const SerTimeOut :Longint =5; { in 0.5 sec Intervallen}
  9.       DSR_Handshake:Boolean=true;
  10.       CTS_Handshake:Boolean=false;
  11.       XonXoff      :Boolean=false;
  12.       X_on =$11;
  13.       X_off=$13;
  14.  
  15.  
  16.  
  17. type
  18.       ParityType=(Nopar,Oddpar,EvenPar);
  19.  
  20. procedure SetSeriell(S_port:Word;
  21.                      BaudRate,StopBits,DataBits:Byte;Parity: Paritytype);
  22.                     {Baudrate 96 =9600}
  23.  
  24. FUNCTION BusyRead (VAR ch : CHAR ): BOOLEAN;
  25.  
  26. Function InSerPort(Var Error:Byte):Byte;
  27.  
  28. procedure OutSerPort(C:Byte;Var Error :Byte);
  29.  
  30.  
  31. implementation
  32.  
  33. Const TX_buffer =0;
  34.       RX_buffer =0;
  35.       Div_latch_L =0;
  36.       Int_Enable=1;
  37.       Div_latch_H =1;
  38.       Int_Ident =2;
  39.       Line_Ctrl =3;
  40.       Modem_Ctrl=4;
  41.       Line_Stat=5;
  42.       Modem_Stat=6;
  43.       RTS_DTR_On       = $03;
  44.       InitModemCtrl    = $08;           { set Out2, reset RTS DTR      }
  45.       EnableComInt     = $01;           { enable error and receive CHR }
  46.       DisableComInt    = $00;           { disable interrupt 8250       }
  47.  
  48.       baseIO    :Word=$3F8; { Com1}
  49.       ActualPort:Word=0;
  50.       Wait_Xon  :Boolean=false;
  51.  
  52. VAR   StoreOldComInt : Pointer;
  53.       ExitSave       : POINTER;       { Store old exitproc }
  54. { ComBuffer declarations: }
  55.  
  56. CONST
  57.     ComBufferSize    = $100;          { 256 Byte default buffer }
  58.     ComBufferEnd     = $0FF;          { ComBufferSize - 1 }
  59.     ComBufferFull    : BOOLEAN = FALSE; { set to TRUE if buffer full }
  60.     ComInIndx        : INTEGER = 0;   { input index to comm buffer }
  61.     ComOutIndx       : INTEGER = 0;   { output index to comm buffer }
  62.  
  63. VAR ComBuffer      : ARRAY [0..ComBufferEnd] OF BYTE;
  64.  
  65. CONST
  66.     RS232installed   : BOOLEAN = FALSE;  { TRUE if interrupthandler active }
  67.     ComUtilByte      : BYTE    = $00;    { intermediate buffer variable }
  68.     ComAuxInIndx     : INTEGER = 0;      { utlity variable for INT handler }
  69.  
  70. {  8259 interrupt  controller  }
  71. CONST
  72.     i8259ContrWord1  = $21;        { Control Word 1 }
  73.     i8259ContrWord2  = $20;        { Control Word 2 }
  74.     i8259EOFintrupt  = $20;        { signal END of interrupt }
  75.  
  76.     Rs232cDevNr : BYTE = $04;      { Interrupt Mask Bit Nr for COM1 }
  77.  
  78. VAR i8259Status     : BYTE;        { store device status }
  79.  
  80. {  8250 communication controller  }
  81. CONST
  82.     CommInt     : Byte =$0C;        { Comm INT for COM1, use 0B for COM2 }
  83.     { registers 8250 if COM1 used.  Use 3F0 for COM1 and 2F0 for COM2 }
  84.  
  85.  
  86. Var   OutTimeoutCnt :Longint;
  87.       InTimeOutCnt  :Longint;
  88.       IoBaseTab     :Array[1..4] of word absolute $0:$400;
  89.  
  90.  
  91. Procedure Ints_Freigabe;
  92. inline($FB);                             { sti }
  93.  
  94. Procedure Ints_Sperre;
  95. inline($FA);                             { Cli }
  96.  
  97. {$F+}
  98. PROCEDURE ComIntHandler;              { never call this procedure }
  99.                                       { it is an interrupt handler }
  100. INTERRUPT;
  101. BEGIN
  102.    Ints_Freigabe;
  103.    ComUtilByte := PORT[BaseIo{+Rx_buffer}];
  104.    If ComUtilByte=X_on then Wait_xon:=false;
  105.    If ComUtilByte=X_off then Wait_xon:=true;
  106.    ComAuxInIndx := (ComInIndx+1) MOD ComBufferSize;
  107.    IF ComAuxInIndx<>ComOutIndx THEN BEGIN
  108.       ComBuffer[ComInIndx] := ComUtilByte;
  109.       ComInIndx := ComAuxInIndx;
  110.    END
  111.    ELSE ComBufferFull := TRUE;
  112.    PORT[i8259ContrWord2] := i8259EOFintrupt;
  113.    Ints_Sperre;
  114. END; { ComIntHandler }
  115.  
  116. PROCEDURE DeInstallComInt;
  117. BEGIN
  118.    IF NOT RS232installed THEN EXIT;
  119.  
  120.    PORT[BaseIo+int_Enable]    :=  DisableComInt;   { disable  interrupt in 8250 }
  121.    PORT[BaseIo+Modem_Ctrl]   :=  00;
  122.  
  123.    i8259Status := PORT[i8259ContrWord1];      { disable interrupt in 8259 }
  124.    PORT[i8259ContrWord1] := (i8259Status or ($01 shl Rs232cDevNr));
  125.    SetIntVec(CommInt,StoreOldComInt); { restore old intvector }
  126.    RS232installed := FALSE;
  127.    ExitProc := ExitSave;
  128. END; { DeInstallComInt }
  129. {$F-}
  130.  
  131.  
  132. FUNCTION BusyRead (VAR ch : CHAR ): BOOLEAN;
  133.  
  134. BEGIN
  135.    IF ComInIndx<>ComOutIndx THEN BEGIN
  136.       ch := CHR(ComBuffer[ComOutIndx]);
  137.       ComOutIndx := (ComOutIndx + 1) MOD ComBufferSize;
  138.       BusyRead := TRUE;
  139.    END
  140.    ELSE BEGIN
  141.       ch := #0;
  142.       BusyRead := FALSE;
  143.    END;
  144. END; { BusyRead }
  145.  
  146.  
  147. procedure SetSeriell(S_port :word;
  148.                      BaudRate,StopBits,DataBits:Byte;Parity: Paritytype);
  149. var Divisor  :Word;
  150.     Control  :Byte;
  151.  begin
  152.    S_port:=Succ(Pred(S_port) and 3);
  153.    If (ActualPort<>S_port) then DeinstallComInt;
  154.    ActualPort:=S_port;
  155.    If IobaseTab[1]=0 then IobaseTab[1]:=$3F8;
  156.    If IobaseTab[2]=0 then IobaseTab[2]:=$2F8;
  157.    If IobaseTab[3]=0 then IobaseTab[3]:=$3E8;
  158.    If IobaseTab[4]=0 then IobaseTab[4]:=$2E8;
  159.    baseIo:=IobaseTab[S_port];
  160.  
  161.    { Get Port Address of Port 1 through 4 }
  162.  
  163.    Wait_Xon:=false;
  164.    If Not Odd(S_port) then
  165.      begin
  166.        Rs232cDevNr := $03;      { Interrupt Mask Bit Nr for COM2/4 }
  167.        CommInt     := $0B;      { Comm INT for COM2              }
  168.       end
  169.      else
  170.       begin
  171.        Rs232cDevNr := $04;      { Interrupt Mask Bit Nr for COM1/3 }
  172.        CommInt     := $0C;      { Comm INT for COM1              }
  173.       end;
  174.    PORT [BaseIo+Int_Enable] :=  DisableComInt;
  175.    PORT [BaseIo+Modem_Ctrl] :=  InitModemCtrl;
  176.    IF Not Rs232installed THEN             { you have to deinstall it first! }
  177.    begin
  178.      GetIntVec(CommInt,StoreOldComInt);
  179.      SetIntVec(CommInt,@ComIntHandler);      {Set own intvector }
  180.      IF ((PORT[BaseIo+Line_Stat] and $01) = $01)   { clear the controler }
  181.         THEN ComUtilByte := PORT[BaseIo{+ Rx_buffer}];
  182.      i8259Status := PORT[i8259ContrWord1];      { enable device interrupt }
  183.      PORT[i8259ContrWord1] := (i8259Status AND (NOT($01 shl Rs232cDevNr)));
  184.      RS232installed := TRUE;
  185.      ExitSave := ExitProc;
  186.      ExitProc := @DeInstallComInt;
  187.    end;
  188.    case BaudRate of
  189.      3: Divisor:=$180;
  190.      6: Divisor:=$C0;
  191.      12:Divisor:=$60;
  192.      24:Divisor:=$30;
  193.      48:Divisor:=$18;
  194.      192:Divisor:=$06;
  195.      else Divisor:=$0C;
  196.    end;
  197.    Stopbits:=(Stopbits shr 1) and 1;
  198.    Databits:=3 xor (Databits and 1);
  199.    Control:=(StopBits Shl 2)+DataBits;
  200.    case Parity of
  201.      oddpar: Control:=Control+8;
  202.      evenpar: Control:=Control+24;
  203.    end;
  204.    Ints_Sperre;
  205.       ComBufferFull := FALSE;                { reset ComBuffer  }
  206.       ComInIndx := 0;
  207.       ComOutIndx := 0;
  208.       Port[BaseIo+Line_Ctrl]:=$80;
  209.       Port[BaseIo { +Div_latch_L } ]:=Lo(Divisor);
  210.       Port[BaseIo+Div_latch_H]:=Hi(Divisor);
  211.       Port[BaseIo+Line_ctrl]:=Control;
  212.       Port[BaseIo+Modem_ctrl]:=InitmodemCtrl+RTS_DTR_on;
  213.       PORT[BaseIo+int_Enable]    :=  EnableComInt;    { enable ComInt in 8250 }
  214.    Ints_Freigabe;
  215. end;
  216.  
  217. Function InSerPort(Var Error:Byte):Byte;
  218. var T :LongInt;
  219.     NoTout :Boolean;
  220.     ModemCt,LineSt :Word;
  221.     N      :Word;
  222.     Ch     :Char;
  223.  
  224. begin
  225.   InSerPort:=0;
  226.   LineSt:=BaseIo+Line_Stat;
  227.   ModemCt:=BaseIo+Modem_Ctrl;
  228.   T:=Time_Ms;
  229.   N:=0;
  230.   NoTout:=true;
  231.   Ints_Sperre;
  232.   Port[ModemCt]:=RTS_DTR_on+InitModemCtrl;         {Setze DTR,RTS auf High}
  233.                                           { empfangsbereit }
  234.   While NoTout and Not(BusyRead(Ch)) Do
  235.   { Warte bis Zeichen da }
  236.   begin
  237.    Inc(N,1);
  238.    If (N and $3FF)=0 then
  239.          NoTout:=Time_Ms-T<SerTimeout*500;
  240.   end;
  241.   IF NoTout Then
  242.     begin
  243.       InserPort:=Ord(Ch);
  244.       Error:=Port[LineSt] and $1E;
  245.     end
  246.   else Error:=$80;
  247.   Port[ModemCt]:=InitModemCtrl;  {Setze DTR,RTS auf Low}
  248. end;
  249.  
  250. procedure OutSerPort(C:Byte;Var Error :Byte);
  251. var T :LongInt;
  252.     NoTout :Boolean;
  253.     NoXonOff:Boolean;
  254.     N,
  255.     LineSt,
  256.     ModemSt :Word;
  257.  
  258. begin
  259.   LineSt:=BaseIo+Line_Stat;
  260.   ModemSt:=BaseIo+Modem_Stat;
  261.   N:=0;NoTout:=true;
  262.   T:=Time_Ms;
  263.   Error:=0;
  264.   While ((DSR_Handshake and ((Port[ModemSt] and $20)=0)) or
  265.         ( CTS_Handshake and ((Port[ModemSt] and $10)=0)) or
  266.         ( XonXoff   and  Wait_xon ) or
  267.         ((Port[LineSt] and $60)<>$60))    { Transmitter empty}
  268.         and NoTout Do
  269.   begin
  270.    Inc(N,1);
  271.    If (N and $3FF)=0 then
  272.          NoTout:=Time_Ms-T<SerTimeout*500;
  273.   end;
  274.   IF NoTout Then
  275.       Port[BaseIo { +Tx_Buffer} ]:=C
  276.   else Error:=$80;
  277. end;
  278.  
  279.  
  280. end.
  281.