//
// Hearsay II Fast Hayes modem driver 14/08/92
// Copyright  RISC Developments Limited 1992
// 
// An example of writing a driver for a fast modem with MNP etc.
//
//

int modemrxrate;
int modemtxrate;
int physicalrate;
int modembits;
int modemstop;
int modemparity;
int modemport;
int modemflow;
int modemlink;
int modemanswer;
int modemtonedial;





// count or purge buffer

int modem_countpurge(int rxtx,int code)
{
 return(devcon(Device_CountPurge,modemport,rxtx,code));
}


// generate break for time cs

void modem_break(int time)
{
 devcon(Device_Break,modemport,time,0);
}


// tell modem to use a given sort of flow control

void modem_setflow(int flow)
{
 devcon(Device_Flow,modemport,flow,1);
 modemflow=flow;
}


// read flow control in use

int modem_readflow(void)
{
 modemflow=devcon(Device_Flow,modemport,0,0);
 return(modemflow);
}


// tell modem to use a given sort of link level protocol

int modem_link(int link)
{
 // if MNP is selected then make the modem do the work

 if(link==MNP)
 {
  internal_link(0);
  modemlink=link;
 }
 else modemlink=internal_link(link);

 return(modemlink);
}


// read rx baud rate at which modem is talking to outside world

int modem_readrxrate(void)
{
 return(modemrxrate);
}


// set rx rate

void modem_setrxrate(int rate)
{
 switch(rate)
 {
    case  75:
             modemrxrate=rate;
             modemtxrate=1200;
             modemanswer=1;
             break;

     default:
             if(modemtxrate==75 && rate==1200) modemrxrate=rate;
             else                              modemrxrate=modemtxrate=rate;
             break;

 }
}



// read tx baud rate at which modem is talking to outside world

int modem_readtxrate(void)
{
 return(modemtxrate);
}


// set tx rate


void modem_settxrate(int rate)
{
 switch(rate)
 {
    case  75:
             modemtxrate=rate;
             modemrxrate=1200;
             modemanswer=0;
             break;


     default:
             if(modemrxrate==75 && rate=1200) modemtxrate=rate;
             else                             modemtxrate=modemrxrate=rate;
             break;

 }
}


// read number of data bits

int modem_readbits(void)
{
 return(modembits);
}


// set number of data bits

void modem_setbits(int bits)
{
 devcon(Device_DataBits,modemport,bits,1);

 modembits=devcon(Device_DataBits,modemport,0,0);
 modemparity=devcon(Device_ParityBits,modemport,0,0);
 modemstop=devcon(Device_StopBits,modemport,0,0);
}


// read parity bits

int modem_readparity(void)
{
 return(modemparity);
}


// set parity bits

void modem_setparity(int parity)
{
 devcon(Device_ParityBits,modemport,parity,1);

 modembits=devcon(Device_DataBits,modemport,0,0);
 modemparity=devcon(Device_ParityBits,modemport,0,0);
 modemstop=devcon(Device_StopBits,modemport,0,0);
}


// read stop bits

int modem_readstop(void)
{
 return(modemstop);
}


// set stop bits

void modem_setstop(int stop)
{
 devcon(Device_StopBits,modemport,stop,1);

 modembits=devcon(Device_DataBits,modemport,0,0);
 modemparity=devcon(Device_ParityBits,modemport,0,0);
 modemstop=devcon(Device_StopBits,modemport,0,0);
}


// read answer/originate mode

int modem_readanswer(void)
{
 return(modemanswer);
}


// set answer/originate mode

void modem_setanswer(int answer)
{
 modemanswer=answer;
}


// set to tone/pulse dial

int modem_tonedial(int tonedial)
{
 modemtonedial=tonedial;
 return(modemtonedial);
}



// is the modem on line ?

int modem_online(void)
{
 return(devcon(Device_Status,modemport,0,-1) & SERIAL_DCD);
}




void modempreamble(void)
{
 sprints("AT");

 if(modemlink==MNP) sprints("&K3");  // set error correction mode
 else               sprints("&K0");  // set normal mode

 if(modemtxrate==1200 && modemrxrate==1200) sprints("&N15");
 else
 if(modemtxrate==2400 && modemrxrate==2400) sprints("&N14");
 else
 if(modemtxrate==4800 && modemrxrate==4800) sprints("&N19");
 else
 if(modemtxrate==9600 && modemrxrate==9600) sprints("&N18");
 else                                       sprints("&N0");
}




void modemcon(void)
{
 string connect;

 sreads(connect,6000,100);        // read echo'd command 
 tprints(connect);

 while(sreads(connect,6000,100))    // look for connect message
 {
  if((connect/"CONNECT")==0)
  {
   onlinechange(1);
   break;
  }
  else
  if(connect/"RINGING"==0)
  {
   tprints(connect);
   continue;
  }

  if(slen(connect)>1)
   break;
 }

 tprints(connect);
}


void modem_autoanswer(int rings)
{
 string connect;
 int    speed;

 modempreamble();
 sprints("S0="+itos(rings)+"|M");

 if(rings)
 {
  while(1)
  {
   if(sreads(connect,6000,100))
   {
    if((connect/"CONNECT")==0)
    {
     onlinechange(1);
     break;
    }
   }
  }
 }
}


// dial a number and attempt to go on line

void modem_dial(string number)
{
 string s;

 while(sreads(s,50,100)) // wait till any pre-dial string has been sent
 tprints(s);
 modempreamble();
 sprints((modemtonedial?"DT":"DP")+number+"|M");
 modemcon();
}


// reconnect

void modem_reconnect(void)
{
 sprints("ATO|M");
}


// talk to modem

void modem_talk(void)
{
 pause(100);
 sprints("+++");
 pause(100);
}


// put modem off line

void modem_disconnect(void)
{
 pause(100);
 sprints("+++");
 pause(200);
 sprints("ATH0|M");
}


// put modem on line

void modem_connect(void)
{
 modempreamble();
 sprints(modemanswer?"A|M":"D|M");
 modemcon();
}


// cancel modem operation

void modem_interrupt(void)
{
 sprints("|M"); 
}


// called when Hearsay is about to terminate
// good time to hang up line etc.

void modem_terminate(void)
{
 devcon(Device_Select,modemport,0,0);
}



/* return 0 if succesful */

int modem_initiate(int port)
{
 modemport=port;

 if(!devcon(Device_Claim,modemport,0,0)) return(2);

 devcon(Device_Select,modemport,1,0);

 devcon(Device_Channel,modemport,0,0);

// note that just here the baud rate is not defined.
// but shortly after this function exits it will be.
// that implies you must check that anything the function sends is sent.

 physicalrate=38400;
 devcon(Device_RxRate,modemport,physicalrate,1);
 devcon(Device_TxRate,modemport,physicalrate,1);

 modem_setbits(8);
 modem_setparity(0);
 modem_setstop(1);

 setpoll(0);

 sprints("ATQ0V1&C1&B1&H3E1S0=0S10=50|M");
 pause(50);

 setpoll(1);

 return(0);
}


// called when driver is installed

void main(void)
{

}

