

union REGS in_registers,out_registers;


/*-------------- The routines that work with the fossil ------------------*/ 

void fossil_clear_regs()    /* This (utility) routine is used by the rest.*/
{
in_registers.h.al = 0;  /* Do them first by byte.      */
in_registers.h.ah = 0;
in_registers.h.bl = 0;
in_registers.h.bh = 0;
in_registers.h.cl = 0;
in_registers.h.ch = 0;
in_registers.h.dl = 0;
in_registers.h.dh = 0;
in_registers.x.ax = 0;  /* Do these just to make sure! */
in_registers.x.bx = 0;
in_registers.x.cx = 0;
in_registers.x.dx = 0;
in_registers.x.si = 0;
in_registers.x.di = 0;
in_registers.x.cflag = 0;
in_registers.x.flags = 0;
}

void fossil_set_parameters(int port,int baud,int bits,char parity,int stopbits)
{
int code=0;
fossil_clear_regs();
switch (baud)
  {
  case  0 : break;
  case 100 : code += 000 + 00 + 00; break;
  case 150 : code += 000 + 00 + 32; break;
  case 300 : code += 000 + 64 + 00; break;
  case 600 : code += 000 + 64 + 32; break;
  case 1200: code += 128 + 00 + 00; break;
  case 2400: code += 128 + 00 + 32; break;
  case 4800: code += 128 + 64 + 00; break;
  case 9600: code += 128 + 64 + 32; break;
  }
switch (bits)
  {
  case 5: code += 0 + 0; break;
  case 6: code += 0 + 1; break;
  case 7: code += 2 + 0; break;
  case 8: code += 2 + 1; break;
  }
switch (parity)
  {
  case 'N': code += 00 + 0; break;
  case 'O': code += 00 + 8; break;
  case 'E': code += 16 + 8; break;
  }
switch (stopbits)
  {
  case 1: code += 0; break;
  case 2: code += 4; break;
  }
in_registers.h.ah = 0;
in_registers.h.al = code;
in_registers.x.dx = port - 1;
int86(0x14,&in_registers,&out_registers);
}

int fossil_init(int port)  /* Returns zero if successful. */
{
fossil_clear_regs();
in_registers.h.ah = 4;
in_registers.x.dx = port - 1;
int86(0x14,&in_registers,&out_registers);
if (out_registers.x.ax != 0x1954)  /* Failed to get fossil? */
  return(1);                       /*  Return non-zero!     */
return(0);
}

void fossil_set_dtr(unsigned char comport, int dtr_state)  /* State is 0 for low, 1 for high. */
{
fossil_clear_regs();
in_registers.h.ah = 6;
in_registers.x.dx = comport - 1;
if (dtr_state)
  in_registers.h.al = 1;
 else
  in_registers.h.al = 0;
int86(0x14,&in_registers,&out_registers);
}

void fossil_set_handshaking(unsigned char comport, unsigned char handshake_mask)
{
fossil_clear_regs();                /* Mask of 2 for hardware handshaking.   */
in_registers.h.ah = 15;             /* Mask of 0 for no handshaking.         */
in_registers.x.dx = comport - 1;    /* Mask of 9 for bidirectional XON/XOFF. */
in_registers.h.al = handshake_mask;
int86(0x14,&in_registers,&out_registers);
}

int fossil_cd(int port)
{
fossil_clear_regs();
in_registers.h.ah = 3;
in_registers.x.dx = port - 1;
int86(0x14,&in_registers,&out_registers);
if ((out_registers.h.al & 128) == 128)
  return(1);
return(0);             /* Return a zero if there's no carrier detect. */
}

int fossil_available(int port)
{
fossil_clear_regs();
in_registers.h.ah = 3;
in_registers.x.dx = port - 1;
int86(0x14,&in_registers,&out_registers);
return(out_registers.h.ah & 1);             /* Anything there? */
}

unsigned char fossil_receive(int port)
{
fossil_clear_regs();
in_registers.h.ah = 2;
in_registers.x.dx = port - 1;
int86(0x14,&in_registers,&out_registers);
return(out_registers.h.al);
}

int fossil_ok_to_send(int port)   /* Returns non-zero if ok to send. */
{
fossil_clear_regs();
in_registers.h.ah = 3;
in_registers.x.dx = port - 1;
int86(0x14,&in_registers,&out_registers);
if ((out_registers.h.ah & 32) == 32)
  return(1);
return(0);
}

void fossil_send(int port, char the_character)
{
fossil_clear_regs();
in_registers.h.ah = 1;
in_registers.x.dx = port - 1;
in_registers.h.al = the_character;
int86(0x14,&in_registers,&out_registers);
}

void fossil_close(int port, int drop_dtr_flag)
{
fossil_clear_regs();
if (drop_dtr_flag)               /* Drop DTR if drop_dtr_flag is non-zero. */
  fossil_set_dtr(port,0);
in_registers.h.ah = 5;
in_registers.x.dx = port - 1;
int86(0x14,&in_registers,&out_registers);
}


/*------------------------- Interface routines ---------------------------*/
int initSerial(int port)
{
return(fossil_init((unsigned char)port));
}

void deinitSerial(int port,int dtr_state_to_leave)
{
int drop_dtr_flag=0;
if (!dtr_state_to_leave)
  drop_dtr_flag = 1;
fossil_close(port,drop_dtr_flag);
}

void port_set_handshaking(int port,int handshaking_type)  /* Pass 0 for XON/XOFF and 1 for hardware. */
{
if (!handshaking_type)
  fossil_set_handshaking(port,9);
 else
  fossil_set_handshaking(port,2);
}

int port_cd(int port)
{
return(fossil_cd(port));
}

int port_in(int port)      /* Returns -1 if nothing ready, or the character. */
{
if (!fossil_available(port))
  return(-1);
return(fossil_receive(port));
}

int port_out(int port,char char_to_send)
{
fossil_send(port,char_to_send);
return(0);   /* This routine should return a success code. */
}



/*

int fossil_parameters (ComPort: Byte; Baud: Integer; DataBits: Byte; Parity: Char; StopBit: Byte);
Var
 Code: Integer;
Begin
  Code:=0;
  Fos_Clear_Regs;
    Case Baud of
      0 : Exit;
    100 : code:=code+000+00+00;
    150 : code:=code+000+00+32;
    300 : code:=code+000+64+00;
    600 : code:=code+000+64+32;
    1200: code:=code+128+00+00;
    2400: code:=code+128+00+32;
    4800: code:=code+128+64+00;
    9600: code:=code+128+64+32;
  end;
  Case DataBits of
    5: code:=code+0+0;
    6: code:=code+0+1;
    7: code:=code+2+0;
    8: code:=code+2+1;
  end;
  Case Parity of
    'N','n': code:=code+00+0;
    'O','o': code:=code+00+8;
    'E','e': code:=code+16+8;
  end;
  Case StopBit of
    1: code := code + 0;
    2: code := code + 4;
  end;
  With Regs do
  begin
    AH := 0;
    AL := Code;
    DX := (ComPort-1);
    Intr ($14, Regs);
  end;
end;

Procedure Fos_Flow  (Comport: Byte; State: Boolean);
Begin
  Fos_Clear_Regs;
    With Regs do
    Begin
    AH := 15;
    DX := ComPort-1;
    Case State of
      TRUE:  AL := 255;
      FALSE: AL := 0;
    end;
    Intr ($14, Regs);
  end;
end;

Procedure Fos_Kill_Out (Comport: Byte);
Begin
  Fos_Clear_Regs;
    With Regs do
    begin
    AH := 9;
    DX := ComPort-1;
    Intr ($14, Regs);
  end;
end;

Procedure Fos_Kill_In  (Comport: Byte);
Begin
  Fos_Clear_Regs;
  With Regs do
  begin
    AH := 10;
    DX := ComPort-1;
    Intr ($14, Regs);
  end;
end;

Procedure Fos_Flush    (Comport: Byte);
Begin
  Fos_Clear_Regs;
  With Regs do
  Begin
    AH := 8;
    DX := ComPort-1;
    Intr ($14, Regs);
  end;
end;

Function  Fos_Empty (Comport: Byte) : Boolean;
Begin
  Fos_Clear_Regs;
  With Regs do
  Begin
    AH := 3;
    DX := ComPort-1;
    Intr ($14, Regs);
    Fos_Empty := ((AH AND 64) = 64);
  end;
end;

Procedure Fos_String   (Comport: Byte; OutString: String);
Var
 Pos: Byte;
begin
  For Pos := 1 to Length(OutString) do
  begin
     Fos_Write(Comport,OutString[Pos]);
   end;
OutString:='';
end;

Procedure Fos_StringCRLF  (Comport: Byte; OutString: String);
Var
 Pos: Byte;
begin
  For Pos := 1 to Length(OutString) do
  begin
     Fos_Write(ComPort,OutString[Pos]);
   end;
   Fos_Write(ComPort,Char(13));
   Fos_Write(ComPort,Char(10));
   OutString:='';
end;

Procedure Fos_Bios     (Character: Char);
 Begin
   Fos_Clear_Regs;
   With Regs do
   begin
     AH := 21;
     AL := ORD (Character);
     Intr ($14, Regs);
  end;
end;

Procedure Fos_Ansi     (Character: Char);
begin
  Fos_Clear_Regs;
  With Regs do
  Begin
    AH := 2;
    DL := ORD (Character);
    Intr ($21, Regs);
  end;
end;

Procedure Fos_WatchDog (Comport: Byte; State: Boolean);
Begin
  Fos_Clear_Regs;
  With Regs do
  Begin
    AH := 20;
    DX := ComPort-1;
    Case State of
      TRUE  : AL := 1;
      FALSE : AL := 0;
    end;
    Intr ($14, Regs);
  end;
end;

Function Fos_Hangup   (Comport: Byte) : Boolean;
var
  Tcount : Integer;
begin
  Fos_Dtr(Comport,FALSE);
  delay (600);
  Fos_Dtr(Comport,TRUE);
  if FOS_CD (ComPort)=true then begin
    Tcount:=1;
      repeat
        Fos_String (Comport,'+++');
        delay (3000);
        Fos_StringCRLF (Comport,'ATH0');
        delay(3000);
        if Fos_CD (ComPort)=false then tcount:=3;
        Tcount:=Tcount+1;
      until Tcount=4;
  end;

  if Fos_Cd (ComPort)=true then Fos_Hangup:=False Else Fos_Hangup:=True;
end;

Procedure Fos_Reboot;
Begin
  Fos_Clear_Regs;
  With Regs do
  Begin
    AH := 23;
    AL := 1;
    Intr ($14, Regs);
  end;
end;

Function Fos_CheckModem (Comport: Byte) : Boolean;
Var
  Ch     :   Char;
  Result :   String[10];
  I,Z    :   Integer;
Begin
  Fos_CheckModem:=FALSE;
  Result:='';
  For Z:=1 to 3 do begin
    Delay(500);
    Fos_Write (Comport,Char(13));
    Delay(1000);
    Fos_StringCRLF (Comport,'AT');
    Delay(1000);
    Repeat
      If Fos_Avail (Comport) then Begin
        Ch:=Fos_Receive(Comport);
        Result:=Result+Ch;
      end;
    Until Fos_Avail(1)=FALSE;
    For I:=1 to Length(Result) do Begin
      If Copy(Result,I,2)='OK' then Begin
        Fos_CheckModem:=TRUE;
       Exit;
      end;
    end;
  end;
End;

Function Fos_AtCmd (Comport: Byte; Command: String) : Boolean;
Var
  Ch     :   Char;
  Result :   String[10];
  I,Z    :   Integer;
Begin
  Fos_AtCmd:=FALSE;
  Result:='';
  For Z:=1 to 3 do begin
    Delay(500);
    Fos_Write (Comport,Char(13));
    Delay(1000);
    Fos_StringCRLF (Comport,Command);
    Delay(1000);
    Repeat
      If Fos_Avail (Comport) then Begin
        Ch:=Fos_Receive(Comport);
        Result:=Result+Ch;
      end;
    Until Fos_Avail(1)=FALSE;
    For I:=1 to Length(Result) do Begin
      If Copy(Result,I,2)='OK' then Begin
        Fos_AtCmd:=TRUE;
       Exit;
      end;
    end;
  end;
End;

*/

