home *** CD-ROM | disk | FTP | other *** search
/ POINT Software Programming / PPROG1.ISO / pascal / swag / comm.swg / 0053_SuperFossil.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1994-08-24  |  15.9 KB  |  536 lines

  1.  (* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  *)
  2.  (* ░░██████░░░░░░░░░░░░░░░░░░░░░██████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  *)
  3.  (* ░░█      ░░░░░░░░░░░░░░░░░░░░█      ░░░░░░░░░░·              ·░░░░░  *)
  4.  (* ░░██████ █░░█░████░█▀▀█░█▄██░███░░████░█▀▀▀░░░ By Wayne Boyd  ▒░░░░  *)
  5.  (* ░░░    █ █ ░█ █  █ █▀▀▀ █    █   ░█  █ ▀▀▀█░░░ Fido 1:153/763 ▒░░░░  *)
  6.  (* ░░██████ ████ ████ ████ █ ░░░█ ░░░████ ████ ░░·              ·▒░░░░  *)
  7.  (* ░░░      ░    █    ░    ░ ░░░░ ░░░░    ░    ░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░  *)
  8.  (* ░░░░░░░░░░░░░░█ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  *)
  9.  (* ░░░░░░░░░░░░░░░ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  *)
  10.  (* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  *)
  11.  (* ░░░░░░░░░░░░░░░░░░░░░· A Turbo Pascal Unit for   ·░░░░░░░░░░░░░░░░░  *)
  12.  (* ░░░░░░░░░░░░░░░░░░░░░  modem communications using ▒░░░░░░░░░░░░░░░░  *)
  13.  (* ░░░░░░░░░░░░░░░░░░░░░· a FOSSIL driver.          ·▒░░░░░░░░░░░░░░░░  *)
  14.  (* ░░░░░░░░░░░░░░░░░░░░░░▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒░░░░░░░░░░░░░░░░  *)
  15.  (* ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░  *)
  16.  (* Welcome to my fossil driver world. After struggling for a long       *)
  17.  (* time with various communications drivers I came to realize the       *)
  18.  (* easiest way to go about writing doors and even BBS programs was to   *)
  19.  (* use a FOSSIL driver. FOSSIL stands for Fido Opus Seadog Standard     *)
  20.  (* Interface Layer. It's a TSR program that remains in your computer    *)
  21.  (* memory and helps interface your software with the modem com port.    *)
  22.  (* There's many BBS programs, Fidonet mailer's and On-line BBS games    *)
  23.  (* that only operate with a FOSSIL driver loaded. The programs you      *)
  24.  (* write with this unit will also depend on a FOSSIL driver.            *)
  25.  (* Of course, there is no FOSSIL driver included with this package.     *)
  26.  (* You have to pick one of those up on your own at most major           *)
  27.  (* computer bulletin boards around country. I've tested this unit on    *)
  28.  (* X00, BNU and OPUSCOMM and they work fine. The unit that is           *)
  29.  (* included here is more a less a complete package. You could write a   *)
  30.  (* BBS or a door with it easily. I've written many doors now, and       *)
  31.  (* this is my standard unit. I don't want to claim credit for           *)
  32.  (* everything here. In fact, the function calls used are from the       *)
  33.  (* fossil revision 5 documentation and will work with any proper        *)
  34.  (* FOSSIL driver.                                                       *)
  35.  (*                                                                      *)
  36.  (* = It is important to note that this unit was specifically written to *)
  37.  (* = facilitate writing of BBS doors, but may be modified slightly to   *)
  38.  (* = facilitate the writing of a BBS program itself. The difference is  *)
  39.  (* = that generally when writing a door, if the caller drops carrier    *)
  40.  (* = you would simply want the program to terminate and return to the   *)
  41.  (* = BBS. In the case of a BBS, however, you want the BBS to recycle,   *)
  42.  (* = not to terminate. Also, with some doors, rather than terminate     *)
  43.  (* = immediately, you would want them to save information to file       *)
  44.  (* = first. In such cases you have to modify all of the HALT statements *)
  45.  (* = that are found within this unit to reflect your actual needs.      *)
  46.  (*                                                                      *)
  47.  (* I have provided this unit as a public service for the BBS community, *)
  48.  (* but I do request that if you would like further support for programs *)
  49.  (* that you write with this unit, that you register this unit with me   *)
  50.  (* by sending me a modest donation of $25.00.                           *)
  51.  (*                                                                      *)
  52.  (* I may be contacted by writing:                                       *)
  53.  (*                        ┌───────────────────────┐                     *)
  54.  (*                        │ Wayne Boyd            │                     *)
  55.  (*                        │ c/o Vipramukhya Swami │                     *)
  56.  (*                        │ 5462 SE Marine Drive  │                     *)
  57.  (*                        │ Burnaby, BC, V5J 3G8  │                     *)
  58.  (*                        │ Canada                │                     *)
  59.  (*                        └───────────────────────┘                     *)
  60.  (* My BBS is called Sita and the Ring BBS, and it is Fidonet node       *)
  61.  (* 1:153/763, Transnet node 132:732/4 and ISKCONet 108:410/8. File      *)
  62.  (* requests and netmail is acceptable. You may also log on my board at  *)
  63.  (* 2400 baud or less, and the phone number is (604)431-6260.            *)
  64.  (*                                                                      *)
  65.  
  66. UNIT SuperFos;
  67.  
  68. INTERFACE
  69.  
  70. USES Dos,Crt,ansi;
  71.              { this ANSI module is in ANSI.SWG.  }
  72. CONST
  73.  
  74.   { These are defined global constants that can be passed to SetPort }
  75.  
  76.   Com0 = 0;  { local only mode }
  77.   Com1 = 1;  { for COM1, etc.  }
  78.   Com2 = 2;
  79.   Com3 = 3;
  80.   Com4 = 4;
  81.  
  82. PROCEDURE SetPort(Port : Integer);
  83.  (*   Set's ComPortNum to correct value, used by all procedures. Must be *)
  84.  (*   called first. Use the defined constants to make it easy. For       *)
  85.  (*   example: SetPort(Com1) will assign COM1 as the input/output port.  *)
  86.  (*   In reality, the numeric value of ComPortNum is (Port - 1).         *)
  87.  (*   Calling SetPort with a 0 will cause all functions and              *)
  88.  (*   procedure to function in local mode. You must make one call to     *)
  89.  (*   SetPort at the beginning of your program before using any of the   *)
  90.  (*   procedures or functions in this unit.                              *)
  91.  (*                                                                      *)
  92.  (*   If you use                                                         *)
  93.  (*   SetPort(Com0), all functions and procedures will function in local *)
  94.  (*   mode, since Com0 = 0. This will cause the value of ComPortNum to   *)
  95.  (*   equal -1.                                                          *)
  96.  
  97. PROCEDURE SetBaudRate(A : LongInt);
  98.  {  Set baud rate, 300/600/1200/2400/4800/9600/19200/38400 supported}
  99.  
  100. PROCEDURE TransmitChar(A : Char);
  101.  {  Character is queued for transmission}
  102.  
  103. FUNCTION TxCharNoWait(A : Char) : BOOLEAN;
  104.  {  Try to send char.  Returns true if sent, false if buffer full}
  105.  
  106. FUNCTION ReceiveChar : Char;
  107.  {  Next char in input buffer returned, waits if none avail}
  108.  
  109. FUNCTION SerialStatus : Word;
  110. {  AH bit 6, 1=output buffer empty
  111.    AH bit 5, 1=output buffer not full
  112.    AH bit 1, 1=input buffer overrun
  113.    AH bit 0, 1=characters in input buffer
  114.    AL bit 7, 1=carrier detect
  115.    AL bit 3, 1=always}
  116. FUNCTION KeyPressedPort : Boolean;
  117.   { Similar to KEYPRESSED. Returns TRUE if there is a character waiting in
  118.   the input port. Uses the SerialStatus function above. }
  119.  
  120. FUNCTION OutBufferFull : Boolean;
  121.   { Returns TRUE if the Output Buffer is full. }
  122.  
  123. FUNCTION OutBufferEmpty : Boolean;
  124.   { Returns TRUE if the Output Buffer is empty. }
  125.  
  126. FUNCTION OpenFossil : Boolean;
  127.  {  Open & init fossil. Returns true if a fossil device is loaded }
  128.  
  129. PROCEDURE CloseFossil;
  130.  {  Disengage fossil from com port. DTR not changed}
  131.  
  132. PROCEDURE SetDTR(A : Boolean);
  133.  {  Raise or lower DTR}
  134.  
  135. PROCEDURE FlushOutput;
  136.  {  Wait for all output to complete}
  137.  
  138. PROCEDURE PurgeOutput;
  139.  {  Zero output buffer and return immediately. Chars in buffer lost}
  140.  
  141. PROCEDURE PurgeInput;
  142.  {  Zero input buffer and return immediately.  Chars in buffer lost}
  143.  
  144. FUNCTION CarrierDetect : Boolean;
  145.  {  Returns true if there is carrier detect }
  146.  
  147. FUNCTION SerialInput : Boolean;
  148.  {  Returns true if there is a character ready to be input }
  149.  
  150. PROCEDURE WriteChar(c : Char);
  151.  {  Write char to screen only with ANSI support}
  152.  
  153. PROCEDURE FlowControl(A : Byte);
  154.  {  Enable/Disable com port flow control}
  155.  
  156. PROCEDURE WritePort(s : string);
  157.  {  Write string S to the comport and echo it to the screen. Checks if the
  158.    buffer is full, and if it is, waits until it is available. If Carrier is
  159.    dropped, this procedure will halt the program.}
  160.  
  161. PROCEDURE WritelnPort(s : string);
  162.  { Same as WritePort, but adds a linefeed + CarrierReturn to the end of S }
  163.  
  164. FUNCTION ReadKeyPort : char;
  165.  { Like pascal's Readkey.
  166.   Example:
  167.   var
  168.     ch : char;
  169.   begin
  170.     repeat
  171.       ch := upcase(readkeyport);
  172.     until ch in ['Y','N'];
  173.   end.
  174. }
  175.  
  176. PROCEDURE ReadPort(var C : char);
  177.  { Similar to Pascal's Read(ch : char); This procedure will read the
  178.   comport until a character is received. If no carrier is received it
  179.   will wait and eventually time out. If carrier is dropped it will halt
  180.   the program. The character is echoed to the local screen with ansi
  181.   support.
  182.  
  183.   EXAMPLE
  184.   var
  185.     ch : char;
  186.   begin
  187.     ReadPort(Ch);
  188.   end.
  189. }
  190.  
  191. PROCEDURE ReadlnPort(var S : string);
  192.  { Similar to Pascal's Readln(s : string); This procedure will read the
  193.   comport until a carriage return is received, and assign the value to S.
  194.   Carrier detect monitoring is enabled, and if the carrier is dropped the
  195.   program will halt. Also there is a time out function. The characters
  196.   are echoed to the local screen with ansi support.
  197.  
  198.   Example:
  199.     var
  200.       Rspns : string;
  201.     begin
  202.       ReadlnPort(Rspns);  (* read a string from comport and store in Rspns *)
  203.     end.
  204. }
  205.  
  206. PROCEDURE HangUp;
  207.  {  Hangs up on the caller by lowering DTR until carrier is dropped, and then
  208.    raising DTR again. }
  209.  
  210. VAR
  211.   Reg : Registers;  { Saves on stack usage later }
  212.  
  213.  {-------------------------------------------------------------------------}
  214.  
  215. IMPLEMENTATION
  216.  
  217. Const
  218.   TimeOut = 20000;
  219.  
  220. VAR
  221.   Status : Word;
  222.   bt : byte;
  223.   ComPortNum : Integer;
  224.  
  225. PROCEDURE SetPort(Port : Integer);
  226. BEGIN
  227.   ComPortNum := Port - 1;
  228. END;
  229.  
  230. FUNCTION BitOn(Position, TestByte : Byte) : Boolean;
  231.  {
  232. This function tests to see if a bit in TestByte is turned on (equal to one).
  233. The bit to test is indicated by the parameter Position, which can range from 0
  234. (right-most bit) to 7 (left-most bit). If the bit indicated by Position is
  235. turned on, the BitOn function returns TRUE.
  236. }
  237. BEGIN
  238.   bt := $01;
  239.   bt := bt SHL Position;
  240.   BitOn := (bt AND TestByte) > 0;
  241. END;
  242.  
  243. PROCEDURE SetBaudRate(A : LongInt);
  244. BEGIN
  245.   IF ComPortNum < 0 then exit;
  246.   WITH Reg DO BEGIN
  247.     AH := 0;
  248.     DX := ComPortNum;
  249.     AL := $63;
  250.     IF A=38400 THEN AL:=$23 ELSE
  251.     CASE A OF
  252.       300   : AL := $43;
  253.       600   : AL := $63;
  254.       1200  : AL := $83;
  255.       2400  : AL := $A3;
  256.       4800  : AL := $C3;
  257.       9600  : AL := $E3;
  258.       19200 : AL := $03;
  259.     END;
  260.     Intr($14, Reg);
  261.   END;
  262. END;
  263.  
  264. PROCEDURE TransmitChar(A : Char);
  265. BEGIN
  266.   IF ComPortNum < 0 then exit;
  267.   Reg.AH := 1;
  268.   Reg.DX := ComPortNum;
  269.   Reg.AL := Ord(A);
  270.   Intr($14, Reg);
  271. END;
  272.  
  273. FUNCTION TxCharNoWait(A : Char) : BOOLEAN;
  274. BEGIN
  275.   IF ComPortNum < 0 then exit;
  276.   Reg.AH := $0B;
  277.   Reg.DX := ComPortNum;
  278.   Intr($14,Reg);
  279.   TxCharNoWait := (Reg.AX = 1);
  280. END;
  281.  
  282. FUNCTION ReceiveChar : Char;
  283. BEGIN
  284.   IF ComPortNum < 0 then ReceiveChar := readkey else
  285.   begin
  286.     Reg.AH := 2;
  287.     Reg.DX := ComPortNum;
  288.     Intr($14,Reg);
  289.     ReceiveChar := Chr(Reg.AL);
  290.   end;
  291. END;
  292.  
  293. FUNCTION SerialStatus : Word;
  294. BEGIN
  295.   Reg.AH := 3;
  296.   Reg.DX := ComPortNum;
  297.   Intr($14,Reg);
  298.   SerialStatus := Reg.AX;
  299. END;
  300.  
  301. FUNCTION KeyPressedPort : Boolean;
  302.  {
  303. Similar to KEYPRESSED. Returns TRUE if there is a character waiting in the
  304. input port. Uses the SerialStatus function above.
  305. }
  306. VAR
  307.   Status : Word;
  308.   NextByte : byte;
  309. begin
  310.   IF ComPortNum < 0 then KeyPressedPort := Keypressed else
  311.   begin
  312.     Status := SerialStatus;
  313.     NextByte := hi(Status);
  314.     KeyPressedPort := BitOn(0,NextByte);
  315.   end;
  316. end;
  317.  
  318. FUNCTION OutBufferFull : Boolean;
  319.  { Returns TRUE if the Output Buffer is full. }
  320. begin
  321.   IF ComPortNum < 0 then OutBufferFull := false else
  322.   begin
  323.     Status := SerialStatus;
  324.     bt := hi(Status);
  325.     OutBufferFull := (BitOn(5,bt) = FALSE);
  326.   end;
  327. end;
  328.  
  329. FUNCTION OutBufferEmpty : Boolean;
  330.  { Returns TRUE if the Output Buffer is empty. }
  331. begin
  332.   IF ComPortNum < 0 then OutBufferEmpty := true else
  333.   begin
  334.     Status := SerialStatus;
  335.     bt := hi(Status);
  336.     OutBufferEmpty := BitOn(6,bt);
  337.   end;
  338. end;
  339.  
  340. FUNCTION OpenFossil : boolean;
  341. BEGIN
  342.   if ComPortNum < 0 then OpenFossil := true else
  343.   begin
  344.     Reg.AH := 4;
  345.     Reg.DX := ComPortNum;
  346.     Intr($14,Reg);
  347.     OpenFossil := Reg.AX = $1954;
  348.   end;
  349. END;
  350.  
  351. PROCEDURE CloseFossil;
  352. BEGIN
  353.   IF ComPortNum < 0 then exit;
  354.   Reg.AH := 5;
  355.   Reg.DX := ComPortNum;
  356.   Intr($14,Reg);
  357. END;
  358.  
  359. PROCEDURE SetDTR;
  360. BEGIN
  361.   IF ComPortNum < 0 then exit;
  362.   Reg.AH := 6;
  363.   Reg.DX := ComPortNum;
  364.   Reg.AL := Byte(A);
  365.   Intr($14,Reg);
  366. END;
  367.  
  368. PROCEDURE FlushOutput;
  369. BEGIN
  370.   IF ComPortNum < 0 then exit;
  371.   Reg.AH := 8;
  372.   Reg.DX := ComPortNum;
  373.   Intr($14,Reg);
  374. END;
  375.  
  376. PROCEDURE PurgeOutput;
  377. BEGIN
  378.   IF ComPortNum < 0 then exit;
  379.   Reg.AH := 9;
  380.   Reg.DX := ComPortNum;
  381.   Intr($14,Reg);
  382. END;
  383.  
  384. PROCEDURE PurgeInput;
  385. BEGIN
  386.   IF ComPortNum < 0 then exit;
  387.   Reg.AH := $0A;
  388.   Reg.DX := ComPortNum;
  389.   Intr($14,Reg);
  390. END;
  391.  
  392. FUNCTION CarrierDetect;
  393. BEGIN
  394.   IF ComPortNum < 0 then CarrierDetect := true else
  395.   begin
  396.     Reg.AH := 3;
  397.     Reg.DX := ComPortNum;
  398.     Intr($14,Reg);
  399.     CarrierDetect := (Reg.AL AND $80) > 0;
  400.   end;
  401. END;
  402.  
  403. FUNCTION SerialInput;
  404. BEGIN
  405.   IF ComPortNum < 0 then SerialInput := true else
  406.   begin
  407.     Reg.AH := 3;
  408.     Reg.DX := ComPortNum;
  409.     Intr($14,Reg);
  410.     SerialInput := (Reg.AH And 1) > 0;
  411.   end;
  412. END;
  413.  
  414. PROCEDURE WriteChar(c : char);
  415. BEGIN
  416.   if ComPortNum < 0 then Display_Ansi(c) else
  417.   begin
  418.     Reg.AH := $13;
  419.     Reg.AL := ORD(c);
  420.     Intr($14,Reg);
  421.   end;
  422. END;
  423.  
  424. PROCEDURE FlowControl;
  425. BEGIN
  426.   IF ComPortNum < 0 then exit;
  427.   Reg.AH := $0F;
  428.   Reg.DX := ComPortNum;
  429.   Reg.AL := A;
  430.   Intr($14, Reg);
  431. END;
  432.  
  433. PROCEDURE WritePort(s : string);
  434. VAR
  435.   i : byte;
  436. begin
  437.   for i := 1 to length(s) do
  438.   begin
  439.     if (ComPortNum >= 0) then TransmitChar(s[i]);
  440.     DISPLAY_Ansi(s[i]);
  441.     if not CarrierDetect then halt(1);
  442.   end;
  443. end;
  444.  
  445. PROCEDURE WritelnPort(s : string);
  446. BEGIN
  447.   s := s + #10 + #13;
  448.   WritePort(s);
  449. end;
  450.  
  451. FUNCTION ReadKeyPort : char;
  452. var
  453.   ch : char;
  454.   count : longint;
  455. begin
  456.   count := 0;
  457.   repeat
  458.     if not carrierdetect then exit;
  459.     if ComPortNum < 0 then ch := readkey else
  460.     if KeyPressedPort then ch := ReceiveChar else
  461.      if keypressed then ch := readkey else
  462.       ch := #0;
  463.     if ch = #0 then inc(count);
  464.   until (ch > #0) or (count > timeout);
  465.   ReadKeyPort := ch;
  466. end;
  467.  
  468. PROCEDURE ReadPort(var C : char);
  469. type
  470.   C_Type = char;
  471. var
  472.   CPtr : ^C_Type;
  473.   ch : char;
  474.   count : longint;
  475. begin
  476.   CPtr := @C;
  477.   count := 0;
  478.   repeat
  479.     if not carrierdetect then halt(1);
  480.     if ComPortNum < 0 then ch := readkey else
  481.      if KeyPressedPort then ch := ReceiveChar else
  482.       if keypressed then ch := readkey else
  483.        ch := #0;
  484.     if ch = #0 then inc(count) else
  485.     begin
  486.       if (ComPortNum >= 0) then TransmitChar(ch);
  487.       DISPLAY_Ansi(ch);
  488.     end;
  489.   until (ch > #0) or (count > timeout);
  490.  
  491.   CPtr^ := ch;
  492. end;
  493.  
  494. PROCEDURE ReadlnPort(var S : string);
  495. type
  496.   linestring = string;
  497. var
  498.   SPtr : ^linestring;
  499.   st : string;
  500.   ch : char;
  501. begin
  502.   SPtr := @S;
  503.   st := '';
  504.  
  505.   repeat
  506.     Ch := readkeyport;
  507.     if ch in [#32..#255] then
  508.     begin
  509.       st := st + ch;
  510.       writeport(ch);
  511.     end else
  512.     if (ch = #8) and (st > '') then
  513.     begin
  514.       delete(st,length(st),1);
  515.       writeport(#8+#32+#8);
  516.     end;
  517.   until ch in [#13,#0];   { will equal NULL if ReadPort timed out }
  518.   WritelnPort('');
  519.   SPtr^ := st;
  520. end;
  521.  
  522. PROCEDURE HangUp;
  523. BEGIN
  524.   if ComPortNum < 0 then exit;
  525.   repeat
  526.     SetDtr(TRUE);        { lower DTR to hangup }
  527.   until Not CarrierDetect;
  528.   SetDtr(FALSE);           { raise DTR again     }
  529. END;
  530.  
  531. BEGIN
  532.   Clrscr;
  533.   Write('SuperFos - by Wayne Boyd 1:153/763');
  534.   delay(1000);
  535. END.
  536.