; **
; |                                                                                  |
; | SupraFaxModem v32/v32bis driver                                                  |
; |                                                                                  |
; | Original by Andy Mell                                                            |
; |                                                                                  |
; | Modem setup amended extensively by Tudor G Jones 25 November 1992                |
; |                                                                                  |
; | Full messages issued everywhere, take them out If you don't like them.           |
; |                                                                                  |
; | 'Switch' statements used instead of nested 'If' to make code more readable.      |
; |                                                                                  |
; **

modem_initialise ()             
{
   integer oldtx=port_txspeed(),oldrx=port_rxspeed()

   port_rxclear()
   port_txspeed(9600)
   port_rxspeed(9600)

   type "AT"+cr
   pause(50)
   port_rxclear()

; **
; |                                                                                  |
; | Switch command echo off first (really only needed for testing)                   |
; |                                                                                  |
; **

   type "ATE0"+cr

   if (waitfor("OK",150))

      {
      port_txspeed(oldtx)
      port_rxspeed(oldrx)
      return(0)
      }

; **
; |                                                                                  |
; | All the configuration stuff. Only set what if different to the defaults!         |
; |                                                                                  |
; | ATB0     CCITT default in v21/22 modes                                           |
; | ATM3     No speaker during dial - speaker until connect                          |
; | ATW1     Error correction results reported                                       |
; | AT&C1    Use DCD to detect carrier                                               |
; | AT&K3    RTS/CTS Flow control                                                    |
; | AT&P1    UK pulse dial make/break ratio                                          |
; | AT&D2    Drop carrier on low DTR                                                 |
; | ATT      Default to tone dialling                                                |
; | ATS95=46 Extended results on connect                                             |
; |                                                                                  |
; **

   type "ATB0M3W1&C1&K3&P1&D2TS95=46"+cr

   if (waitfor("OK",150))

      {
      port_txspeed(oldtx)
      port_rxspeed(oldrx)
      return(0)
      }

   port_txspeed(oldtx)
   port_rxspeed(oldrx)

   prints newline+"SupraFaxModem driver loaded"+newline

   return(1)
}

modem_shutdown ()
{                                
   return(1)
}

modem_connect ()
{
   port_dtr(1)
   port_rts(1)
   prints "Modem connect"+newline
   type "ATO"+cr
   
   return(_processmessage(""))
}

; **
; |                                                                                  |
; | Flip DTR + RTS to force a hungup.                                                |
; | Next comes the clever bit (worked out by Andy Mell). We extract the reason for   |
; | the disconnection from S86 and display a meaningfull message.                    |
; |                                                                                  |
; **

modem_disconnect ()
{
   string response[4]

   port_rts(0)
   port_dtr(0)
   pause 50
   port_dtr(1)
   port_rts(1)
   type cr

   port_txspeed(9600)
   port_rxspeed(9600)

   type "ATS86?"+cr

   repeat

      {
      response=$modeminput(30,modem_replywait)
      }
   until(strcmp($left(response,1),"0")==0)

   response=$left(response,3)

   switch(response)
 
      {

      case$("000")
      
         {
         prints "Normal disconnect, No errors"+newline
         return
         }

      case$("004")

         {
         prints "Loss of Carrier"+newline
         return
         }

      case$("005")

         {
         prints "V.42 negotiation failed"+newline
         return
         }

      case$("009")

         {
         prints "Modems could not find common protocol"+newline
         return
         }
       
      case$("012")

         {
         prints "Normal disconnect initiated by remote modem"+newline
         return
         }

      case$("013")

         {
         prints "Remote modem did not respond after 10 retransmissions of same message"+newline
         return
         }

      case$("014")
 
         {
         prints "Protocol violation"+newline
         return
         }
         
      default

         {
         prints "Reason for disconnect unknown "+response+newline
         return
         }

   }

}

modem_dial (string number[40],integer how)
{
   string dialtype[1]

   port_dtr(1)
   port_rts(1)
   port_rxclear()

   if (how==0)

      {
      dialtype="P"
      }
   else

      {
      dialtype="T"
      }
             
   prints "Dialing . . ."+newline

   type "ATD"+dialtype+number+cr
  
   return(_processmessage(""))
}

; **
; |                                                                                  |
; | When we get an answer watch out for both normal modem connects and also FAX      |
; | connects.                                                                        |
; | Write a FAX machine in an Arcterm script? - Yes I'm mad! (Says Andy)             |
; |                                                                                  |
; **

modem_answer ()
{
   string response[30]

   type "ATS0=1"+cr

   repeat

      {
      response=$modeminput(30,modem_replywait)

      if strcmp($left(response,3),"FAX")

         {
         dorequest("Eeek. Incoming Fax, tell it to go away for now"+newline)
         return(0)
         }

      }
   until(strcmp($left(response,7),"CONNECT"))
                   
   return(_processmessage(response))
}

; **
; |                                                                                  |
; | This routine is called before every connection to really set the error correction|
; | protocol. Because of trouble since RISCOS 3.1 I cannot get my serial port to     |
; | work at more than 9600. So if a particular speed is selected in the Dial         |
; | Directory (other than 19k2) I fix the line speed. If the line speed is fixed by  |
; | using S36=# then the modem to computer speed is also set to this. Therefore I    |
; | cannot use V42bis (BTLZ) or MNP 5 compression.                                   |
; | Here comes clever bit number two. The directory entry allows for MNP 2-10 as a   |
; | option and as nobody uses MNP 6-9 (I believe only used by Miracom internally)    |
; | I make use of them for special options and testing. Neat eh. Hugo please don't   |
; | remove them!                                                                     |
; |                                                                                  |
; | When the Serial Port's new serial card is available just set the TX/RX speed to  |
; | anything other than 2400, 9600 or 14400 in the Dial Directory entry.             |
; |                                                                                  |
; **

modem_errorcontrol (string option[10])
{
   integer speed=port_txspeed()

   prints "Setting line speed at "
   print speed
   prints newline

   switch(speed)

      {

      case(2400)

         {
         type "ATS37=6N0"+cr
         }

      case(9600)

         {
         type "ATS37=9N0"+cr
         }

      case(14400)
       
         {
         type "ATS37=11N0"+cr
         }

      default

         {
         type "ATN1"+cr
         }

      }

   waitfor("OK"+$chr(13)+$chr(10),100)

   prints "Setting Error Controls "

   switch(option)
                     
      {                           

      case$("MNP5")

         {
         set(linklevel,mnp) 
         type("AT&Q5\N2%C0"+cr)
         prints "MNP Reliable"+newline
         }
         
      case$("Vasscom")

         {
         set(linklevel,vasscom)
         type("AT&Q5\N0&M0%C0"+cr)
         prints "Direct Async"+newline
         }
         
      case$("V42bis")

         {
;        set(linklevel,v42bis)
         type("AT&Q5\N3%C1"+cr)
         prints "V42(LAPM error correction), V42bis(BTLZ compression)"+newline 
         }
                    
      case$("MNP8")

         {
         set(linklevel,none) 
         type("AT&Q5\N3%C0"+cr)
         prints "V42(LAPM error correction), no V42bis(BTLZ compression)"+newline        
         }

      case$("MNP9")

         {
         set(linklevel,none) 
         type("AT&Q0\N1%C0S46=136S36=1%M0"+cr)
         prints "Testing connection"+newline        
         }

      case$("OFF","Off","","MNP2","MNP3","MNP4","MNP6","MNP7","MNP10")
  
         {
         set(linklevel,none) 
         type("AT&Q5\N0%C0"+cr)
         prints "Normal reliable connection"+newline
         }

      }
                    
   waitfor("OK"+$chr(13)+$chr(10),100)

   pause(50)

   return
}

; **
; |                                                                                  |
; | Message routine changed a lot! I even use it recursively, seems to work too.     |
; | I try to issue a full message not just the terse response from the modem.        |
; |                                                                                  |
; **

_processmessage (string already[30])
{
   string retcode[30]
   string chk[5]

   if (len(already)!=0)

      {
      retcode=already
      }
   else 
   
      {
      retcode=$modeminput(30,modem_replywait)

      while (len(retcode)==0)

         {
         retcode=$modeminput(30,modem_replywait)
         }
  
      }

   if (len(retcode)>=4)
      
      {
      chk=$left(retcode,4)
      }
   else

      {
       chk=retcode
      }

   switch(chk)

      {

      case$("BUSY")

         {
         prints "The line is Busy"+newline
         return(2)
         }

      case$("NO D")

         {
         prints "No dialtone could be detected"+newline
         return(3)
         } 

      case$("NO A")


         {
         prints "No answer was received from the remote modem"+newline
         modem_disconnect()
         return(1)
         }
                                       
      case$("NO C")
        
         {
         prints "No carrier could be found at the called number"+newline
         modem_disconnect()
         return(1)
         }

      case$("CONN")

         {
         prints retcode+newline
         return(0)
         }

      case$("RING")

         {
         prints "Someone has just rung us!"+newline
         return(0)
         } 
      
      case$("CARR","PROT","COMP","OK")
        
         {
         prints retcode+newline
         return(_processmessage(""))
         }

      default

         {
         if (comparei($left(retcode,2),"AT"))

            {
            return(_processmessage(""))
            }
         else

            {
            prints "Unknown data "+retcode+newline
            modem_disconnect()
            return(1)
            }

         }

      }
}
