home *** CD-ROM | disk | FTP | other *** search
/ Programmer 7500 / MAX_PROGRAMMERS.iso / INFO / TURBOPAS / OASSAM41.ZIP / SAMPLE8.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1988-03-27  |  12.8 KB  |  360 lines

  1. PROGRAM Term_Emulator; {a skeleton of a terminal emulator}
  2. {$R-,S+,I+,D+,T-,F-,V-,B-,N-,L+ }
  3. {$M 16384,0,655360 }
  4.  
  5. uses scl;    {invoke SCL}
  6.  
  7. {--------------------------------------------------------------
  8. The following routines handle the  poll select  protocoll
  9. ---------------------------------------------------------------}
  10. CONST
  11.   Tx_Buffers  = 1;   {nr of xmit buffers; minimum = 1}
  12.   Rx_Buffers  = 1;   {nr of receive buffers; minimum = 1}
  13.   Dc_Addr_1 : Byte = $33;  {first byte of terminal address}
  14.   Dc_Addr_2 : Byte = $31;  {second byte of terminal address}
  15.  
  16. TYPE
  17.   Buffer_Data = ARRAY[1..Dc_Buffer_Size] OF Byte;
  18.   Buffer_Type = RECORD     {description of rx and tx buffers}
  19.                   Len :INTEGER;  {length of data in buffer}
  20.                   Data:Buffer_Data;
  21.                 END;
  22.   Rx_Buffer_Type= ARRAY[0..Rx_Buffers] OF Buffer_Type;
  23.   Tx_Buffer_Type= ARRAY[0..Tx_Buffers] OF Buffer_Type;
  24.  
  25. VAR
  26.   Rx_Buffer_Overflow:BOOLEAN;   {rx data > buffersize}
  27.   Rx_Buffer:Rx_Buffer_Type;
  28.   Tx_Buffer:Tx_Buffer_Type;
  29.   Result_Ok:BOOLEAN;
  30.   Ch_Code:INTEGER;
  31.   State:INTEGER;    {used in poll select state machine}
  32.   Rx_Buff_Wptr,     {rx buffer to be filled next}
  33.   Rx_Buff_Rptr,     {rx buffer to be read next}
  34.   Tx_Buff_Wptr,     {tx buffer to be sent last}
  35.   Tx_Buff_Rptr   : INTEGER;  {tx buffer to be sent first}
  36.   This_Char_Done:BOOLEAN;    {used in poll select state machine}
  37.   Dc_Msg_Header:String;
  38.   Cont_String:String;
  39.   Char_Ind:INTEGER;
  40.   Ok : BOOLEAN;
  41.   Head_Bcc:INTEGER;
  42.  
  43. PROCEDURE Ps_Handler;       {poll select state machine. run as }
  44.   BEGIN;                    {background task}
  45.     IF This_Char_Done THEN  {previous character finished}
  46.       Receive_Char(Ch_Code,Ok); {get next char from dc rx buffer}
  47.       IF Ok THEN                {there was a character}
  48.       BEGIN;
  49.         This_Char_Done:=TRUE;   {preset}
  50.         CASE State OF
  51.         0:IF Ch_Code = Eot THEN State:=1;  {eot received}
  52.         1:IF Ch_Code = Dc_Addr_1 THEN    {first byte of address}
  53.             State:=2                     {wait for second byte}
  54.           ELSE
  55.             State:=0;                   {reset state machine}
  56.         2:IF Ch_Code = Dc_Addr_2 THEN   {second byte of address}
  57.             State:=3                    {wait for cntrl char}
  58.           ELSE State:=0;                {reset state machine}
  59.         3:IF Ch_Code = Pol THEN State:=4 ELSE {poll string}
  60.           IF Ch_Code = Sel THEN State:=7 ELSE {select string}
  61.           IF Ch_Code = Fsl THEN State:=15 ELSE {fast sel}
  62.             State:=0;       {otherwise reset state machine}
  63.         4:IF Ch_Code = Enq THEN   {end of string}
  64.             BEGIN;
  65.               This_Char_Done:=FALSE;  {dont read next char}
  66.               State:=5                {next is state = 5}
  67.             END
  68.           ELSE
  69.             State:=0;                 {reset state machine}
  70.         5:IF Tx_Buffer[Tx_Buff_Rptr].Len = 0 THEN
  71.             BEGIN;                    {no data to send}
  72.               Send_Char(Eot,Ok);      {send eot}
  73.               State:=0;       {..and reset state machine}
  74.             END
  75.           ELSE               {there is data to be sent}
  76.             BEGIN;           {send it with header and bcc}
  77.               Send_Buffer(Tx_Buffer[Tx_Buff_Rptr].Data,
  78.                           1,Tx_Buffer[Tx_Buff_Rptr].Len,Head_Bcc,
  79.                           Dc_Msg_Header,Ok);
  80.               IF Ok THEN     {successfully sent}
  81.                 State:=6     {wait for ack}
  82.               ELSE
  83.                 State:=0;    {otherwise reset state machine}
  84.             END;
  85.         6:BEGIN;
  86.             IF Ch_Code = Ack THEN  {ack received}
  87.               BEGIN;
  88.                 Send_Char(Eot,Ok); {send eot}
  89.                 IF Ok THEN         {successfully sent}
  90.                   BEGIN;    {clear buffer & increase pointer}
  91.                     Tx_Buffer[Tx_Buff_Rptr].Len:=0;
  92.                     Tx_Buff_Rptr:=SUCC(Tx_Buff_Rptr) MOD Tx_Buffers;
  93.                   END;
  94.                 State:=0;      {reset state machine}
  95.               END
  96.             ELSE
  97.             IF Ch_Code = Nak THEN {mainframe didnt receive ok}
  98.               BEGIN;              {resend data}
  99.                 This_Char_Done:=FALSE;
  100.                 State:=5;
  101.               END
  102.             ELSE                  {mainframe did not respond}
  103.               State:=0;           {reset state machine}
  104.           END;
  105.         7: IF Ch_Code = Enq THEN  {end of sel string}
  106.             BEGIN;
  107.               This_Char_Done:=FALSE; {dont receive next char}
  108.               State:=8;              {answer}
  109.             END
  110.           ELSE
  111.             State:=0;                {reset state machine}
  112.        8: IF Rx_Buffer[Rx_Buff_Wptr].Len > 0 THEN
  113.             BEGIN;         {we have no rx buffer available}
  114.               Send_Char(Nak,Ok);     {send nak}
  115.               State:=0;              {reset state machine}
  116.             END
  117.           ELSE        {we can receive data}
  118.             BEGIN;
  119.               Send_Char(Ack,Ok);  {send ack}
  120.               IF Ok THEN State:=9 ELSE   {ack could be sent}
  121.                 State:=0;  {otherwise reset state machine}
  122.             END;
  123.        9: IF Ch_Code = Soh THEN
  124.             State:=10      {SOH received}
  125.           ELSE State:=0;
  126.       10: IF Ch_Code = Dc_Addr_1 THEN  {first byte of address}
  127.             State:=11
  128.           ELSE State:=0;
  129.       11: IF Ch_Code = Dc_Addr_2 THEN
  130.             State:=12  {second byte of address received}
  131.           ELSE State:=0;
  132.       12: BEGIN;
  133.             IF Ch_Code = Stx THEN    {stx received}
  134.               BEGIN;
  135.                 Bcc:=Stx XOr Head_Bcc; {start bcc calculation}
  136.                 Char_Ind:=1;       {init rx buffer}
  137.                 State:=13;         {rx data}
  138.               END
  139.             ELSE
  140.               State:=0;            {reset state machine}
  141.           END;
  142.       13: BEGIN;    {receive data & write into rx buffer}
  143.             IF (Char_Ind < Dc_Buffer_Size) AND (Ch_Code <> Etx) THEN
  144.               BEGIN; {buffer not full and not etx received}
  145.                 Rx_Buffer[Rx_Buff_Wptr].Data[Char_Ind]:=Ch_Code;
  146.                 Bcc:=Bcc XOr Ch_Code; {bcc calculation}
  147.                 Char_Ind:=SUCC(Char_Ind); {increase buffer index}
  148.               END
  149.             ELSE
  150.             IF Ch_Code = Etx THEN  {etx received}
  151.               BEGIN;
  152.                 Bcc:=Bcc XOr Etx;  {get final bcc}
  153.                 Rx_Buffer[Rx_Buff_Wptr].Len:=Char_Ind - 1;
  154.                 State:=14;
  155.               END
  156.             ELSE          {rx buffer overflow}
  157.               BEGIN;
  158.                 State:=0; {reset state machine}
  159.                 Rx_Buffer_Overflow:=TRUE; {set flag}
  160.               END;
  161.           END;
  162.       14: BEGIN;
  163.             IF Ch_Code = Bcc THEN  {received = calculated bcc}
  164.               BEGIN;
  165.                 Send_Char(Ack,Ok); {send an ACK}
  166.                 IF Ok THEN {successfully sent, next rx buffer}
  167.                   Rx_Buff_Wptr:=SUCC(Rx_Buff_Wptr) MOD Rx_Buffers
  168.                 ELSE
  169.                   Rx_Buffer[Rx_Buff_Wptr].Len:=0;{forget rx data}
  170.               END
  171.             ELSE                    {bcc error}
  172.               BEGIN;
  173.                 Rx_Buffer[Rx_Buff_Wptr].Len:=0;{forget rx data}
  174.                 Send_Char(Nak,Ok); {send nak}
  175.               END;
  176.             State:=0;     {reset state machine}
  177.           END;
  178.       15: IF Ch_Code = Soh THEN State:=16 ELSE State:=0; {FSL}
  179.       16: IF Ch_Code = Dc_Addr_1 THEN State:=17 ELSE State:=0;
  180.       17: IF Ch_Code = Dc_Addr_2 THEN State:=18 ELSE State:=0;
  181.       18: BEGIN;
  182.             IF Ch_Code = Stx THEN  {stx received}
  183.               BEGIN;
  184.                 IF Rx_Buffer[Rx_Buff_Wptr].Len > 0 THEN
  185.                   State:=0    {no rx buffer available}
  186.                 ELSE
  187.                   BEGIN;      {start bcc calculation}
  188.                     Bcc:=Stx XOr Head_Bcc;
  189.                     Char_Ind:=1; {init buff index}
  190.                     State:=13;   {wait for rx data}
  191.                   END;
  192.               END
  193.             ELSE
  194.               State:=0;      {reset state machine}
  195.           END;
  196.        ELSE State:=0;  {reset state machine}
  197.       END; {end case}
  198.       IF Ch_Code = Eot THEN State:=1; {preset state machine}
  199.     END;
  200.   END;
  201.  
  202.  
  203. PROCEDURE Clear_Rx_Buffers;  {clear all rx buffers}
  204. VAR
  205.   X:INTEGER;
  206. BEGIN;
  207.   FOR X:=0 TO Rx_Buffers DO
  208.     Rx_Buffer[X].Len:=0;    {set length to 0}
  209.   Rx_Buff_Wptr:=0;          {both pointers to 0}
  210.   Rx_Buff_Rptr:=0;
  211. END;
  212.  
  213. PROCEDURE Clear_Tx_Buffers; {clear all xmit buffers}
  214. VAR
  215.   X:INTEGER;
  216. BEGIN;
  217.   FOR X:=0 TO Tx_Buffers DO
  218.     Tx_Buffer[X].Len:=0;   {set length to 0}
  219.   Tx_Buff_Wptr:=0;         {set both pointers to 0}
  220.   Tx_Buff_Rptr:=0;
  221. END;
  222.  
  223.  
  224. PROCEDURE Init_Ps;         {init poll select system}
  225. VAR
  226.   Stat:INTEGER;
  227. BEGIN;
  228.   Rx_Buffer_Overflow:=FALSE;
  229.   Cont_String:=CHR(Dc_Addr_1) + CHR(Dc_Addr_2)
  230.               + CHR(Pol) + CHR(Enq);  {set up contention string}
  231.   Dc_Msg_Header:=CHR(Soh)+CHR(Dc_Addr_1)+CHR(Dc_Addr_2); {header}
  232.   Head_Bcc:=Dc_Addr_1 XOr Dc_Addr_2;  {calculate bcc for header}
  233.   State:=0;             {reset state machine}
  234.   Clear_Rx_Buffers;     {clear rx buffers}
  235.   Clear_Tx_Buffers;     {clear tx buffers}
  236.   This_Char_Done:=TRUE;
  237.   Open_Dc(Stat);        {open datacom & install ISR}
  238.   Send_String(Cont_String,Result_Ok); {send contention string}
  239. END;
  240.  
  241. FUNCTION Data_Received:BOOLEAN;  {returns true if at least one }
  242. BEGIN;         {of the rx buffers contains data}
  243.   Data_Received:= Rx_Buffer[Rx_Buff_Rptr].Len > 0;
  244. END;
  245.  
  246. FUNCTION Dc_Write_Ok:BOOLEAN;  {returns true if at least one}
  247. BEGIN;            {of the tx buffers is available}
  248.   Dc_Write_Ok:=Tx_Buffer[Tx_Buff_Wptr].Len = 0;
  249. END;
  250.  
  251.  
  252. PROCEDURE  Read_Dc(VAR Data;VAR Len:INTEGER;VAR Ok:BOOLEAN);
  253. BEGIN;  {call this routine to obtain data received from Mainframe}
  254.   IF Data_Received THEN {one of the rx buffers contains data}
  255.     BEGIN;              {return it}
  256.       Len:=Rx_Buffer[Rx_Buff_Rptr].Len;
  257.       Move(Rx_Buffer[Rx_Buff_Rptr].Data,Data,Len);
  258.       Rx_Buffer[Rx_Buff_Rptr].Len:=0; {clear this buffer}
  259.       Rx_Buff_Rptr:=SUCC(Rx_Buff_Rptr) MOD Rx_Buffers; {incr pointer}
  260.       Ok:=TRUE;
  261.     END
  262.   ELSE
  263.     Ok:=FALSE;       {no rx data available}
  264. END;
  265.  
  266. PROCEDURE  Write_Dc(VAR Buff; Len:INTEGER;VAR Ok:BOOLEAN);
  267. BEGIN;  {call this routine to send data to mainframe}
  268.   IF Dc_Write_Ok THEN  {tx buffer available}
  269.     BEGIN;
  270.       Move(Buff,Tx_Buffer[Tx_Buff_Wptr].Data,SIZEOF(Buff));
  271.       Tx_Buffer[Tx_Buff_Wptr].Len:=Len;
  272.       Tx_Buff_Wptr:=SUCC(Tx_Buff_Wptr) MOD Tx_Buffers;
  273.       Ok:=TRUE;
  274.     END
  275.   ELSE
  276.     Ok:=FALSE;        {no tx buffer available}
  277. END;
  278.  
  279. {-----------------------------------------------------------}
  280. {end of poll select routines.}
  281. {-----------------------------------------------------------}
  282. {$F+} {Set Far calls;required for SCL background tasks}
  283.  
  284. PROCEDURE Lp_Background_Task;
  285. VAR
  286.   Mybuffer:ARRAY[0..Dc_Buffer_Size] OF Byte;
  287.   Rx_Len  :INTEGER;
  288.   Ok      :BOOLEAN;
  289.   I       :INTEGER;
  290.   Mystring:String80;
  291. BEGIN;
  292.   Read_Dc(Mybuffer,Rx_Len,Ok);
  293.   IF Ok THEN                     {something has been received}
  294.     BEGIN;
  295.       IF Rx_Len > 78 THEN Rx_Len:=78; {max length = 78 chars}
  296.       FOR I:=0 TO Rx_Len-1 DO         {to display in field}
  297.         Mystring[I+1]:=CHR(Mybuffer[I]);  {convert to string}
  298.       Mystring[0]:=CHR(Rx_Len);
  299.       W_Cont(2,Mystring);         {display in field 2}
  300.     END;
  301. END;
  302.  
  303. PROCEDURE Hp_Background_Task;
  304. BEGIN;
  305.   REPEAT Ps_Handler UNTIL NOT Ok;   {Call poll select handler}
  306. END;
  307.  
  308. {$F-} {Reset Far Calls}
  309.  
  310.  
  311.  
  312. PROCEDURE Write_To_Mainframe(VAR Mystring:String;VAR Ok:BOOLEAN);
  313. VAR
  314.   Mybuffer: ARRAY[0..Dc_Buffer_Size] OF Byte;
  315.   Mylen    : INTEGER;
  316.   I        : INTEGER;
  317. BEGIN;
  318.   Mylen:=LENGTH(Mystring);            {convert string to array}
  319.   FOR I:=0 TO Mylen DO
  320.     Mybuffer[I]:=ORD(Mystring[I+1]);
  321.   Write_Dc(Mybuffer,Mylen,Ok);        {place it into tx buffer}
  322. END;
  323.  
  324. PROCEDURE Do_Dialog;
  325. VAR
  326.   Wrkstr:String80;
  327. BEGIN;
  328.   Select_Format('dialog');
  329.   Display_Format(0,0);
  330.   REPEAT
  331.     Handle_Format;
  332.     IF End_Of_Field THEN
  333.       BEGIN;
  334.         C_Cont(2);                    {clear field 2}
  335.         Wrkstr:=G_Cont(1);
  336.         IF LENGTH(Wrkstr) > 0 THEN
  337.           BEGIN;
  338.             Write_To_Mainframe(Wrkstr,Ok);
  339.             IF NOT Ok THEN
  340.               Glb_Error:=40
  341.             ELSE
  342.               BEGIN;
  343.                 Char_Code:=Code_Noop; {don't terminate format}
  344.                 Goto_Field(1);
  345.               END;
  346.           END;
  347.       END;
  348.   UNTIL Format_Done;                 {in this case f10 pressed}
  349. END;
  350.  
  351. BEGIN; {of main}
  352.   Select_Format_File('sample8');
  353.   LP_background_pointer:=@LP_background_task; {invoke our background tasks}
  354.   HP_background_pointer:=@HP_background_task;
  355.   Init_Ps; {initialize the poll select system; calls also 'Open_DC'}
  356.   Do_Dialog;
  357.   Close_Dc;  {stop datacom subsystem and deinstall ISR}
  358.   Close_Formats;
  359. END.  {of main}
  360.