/* seric.c */
/* heavily borrowed from my program to control the ic-735 via rs-232 */

#include <exec/types.h>
#include <exec/exec.h>
#include <intuition/intuition.h>
#include <intuition/intuitionbase.h>
#include <graphics/text.h>
#include <devices/serial.h>
#include <ctype.h>
#include <libraries/dos.h>
extern short debug;
extern char *speed;
extern struct MsgPort *crp,*CreatePort();
extern struct IOStdReq *iop;
extern char *AllocMem();
extern struct Window *mywindow;
extern long readbit,windbit,waitbits,Wait();
extern char tmpstr[];
extern short done_flag;
/* flag for stream char processing */
char gotstream = 0;
/* actual pass and stream chars */
extern char passchr,vhfstream,hfstream;
/*   */
long getbits;
ULONG class;
USHORT code;

/* msg structure for GetMsg() */
struct IntuiMessage *NewMessage = 0L, *GetMsg();

/* declarations for the serial stuff */
struct IOExtSer *Read_Request;
unsigned char rs_in[2];
struct IOExtSer *Write_Request;
unsigned char rs_out[2];
int serflags;
short tapr_flag = 0;    /* Using tapr upgrade? */
short BaudRate = 9600;
initser()
{
   long error;
   Read_Request = (struct IOExtSer *)AllocMem
                  ((long)sizeof(*Read_Request),
                   (long)MEMF_PUBLIC|MEMF_CLEAR);
   serflags = Read_Request->io_SerFlags =
                    SERF_SHARED | SERF_XDISABLED | SERF_7WIRE;
   Read_Request->IOSer.io_Message.mn_ReplyPort =
                                            CreatePort("Read_RS",0L);
   if(OpenDevice(SERIALNAME,NULL,Read_Request,NULL))   {
      puts("Cant open Read device\n");
      DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
      FreeMem(Read_Request,(long)sizeof(*Read_Request));
      return(1);
   }
   Read_Request->IOSer.io_Command = CMD_READ;
   Read_Request->IOSer.io_Length = 1L;
   Read_Request->IOSer.io_Data = (APTR) &rs_in[0];

   Write_Request = (struct IOExtSer *)AllocMem
                             ((long)sizeof(*Write_Request),
                              (long)MEMF_PUBLIC|MEMF_CLEAR);
   Write_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED | SERF_7WIRE;
   Write_Request->IOSer.io_Message.mn_ReplyPort =
                                 CreatePort("Write_RS",0L);
   if(OpenDevice(SERIALNAME,NULL,Write_Request,NULL))   {
      puts("Cant open Write device\n");
getout:
      CloseDevice(Read_Request);
      DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
      FreeMem(Write_Request,(long)sizeof(*Write_Request));
      DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
      FreeMem(Read_Request,(long)sizeof(*Read_Request));
      return(1);
   }
   Write_Request->IOSer.io_Command = CMD_WRITE;
   Write_Request->IOSer.io_Length = 1L;
   Write_Request->IOSer.io_Data = (APTR) &rs_out[0];
   Read_Request->IOSer.io_Command = SDCMD_SETPARAMS;
   Read_Request->io_SerFlags =  SERF_SHARED | SERF_XDISABLED | SERF_7WIRE;
   if((error = DoIO(Read_Request)) != 0) {
      sprintf(tmpstr,"error 0 #%ld from setcommand in seric.c\n",error);
      ttputs(tmpstr);
      goto getout;
   }
   Read_Request->io_Baud = BaudRate;
   if((error = DoIO(Read_Request)) != 0) {
      sprintf(tmpstr,"error 1 #%ld from setcommand in seric.c\n",error);
      ttputs(tmpstr);
      goto getout;
   }
   Read_Request->io_ReadLen = 8;
   Read_Request->io_WriteLen = 8;
   if((error = DoIO(Read_Request)) != 0) {
      sprintf(tmpstr,"error 2 #%ld from setcommand in seric.c\n",error);
      ttputs(tmpstr);
      goto getout;
   }
   Read_Request->io_RBufLen = 4096L;
   if((error = DoIO(Read_Request)) != 0) {
      sprintf(tmpstr,"error 3 #%ld from setcommand in seric.c\n",error);
      ttputs(tmpstr);
      goto getout;
   }
   Read_Request->IOSer.io_Command = CMD_READ;

   BeginIO(Read_Request);

   readbit = (1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit);
   waitbits |= readbit;
   return(0);
}

cleanser()
{
   AbortIO(Read_Request);
   AbortIO(Write_Request);
   CloseDevice(Read_Request);
   CloseDevice(Write_Request);
   DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
   FreeMem(Write_Request,(long)sizeof(*Write_Request));
   DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
   FreeMem(Read_Request,(long)sizeof(*Read_Request));
}

/*
   If rflag is zero then read a character from the keyboard
   otherwise read a char from the serial port.
*/
short not_done = 1;
unsigned char gotchar = 0;    /* character at terminal */
unsigned char tncchar = 0;    /* char at tnc */
rdchar(rflag)
short rflag;
{
   unsigned char c;
   int i,mx,my,ch;
/*
   if(!rflag) {
      if(c = gotchar) {
         gotchar = 0;
         return(c);
      }
      waitbits = windbit;
   }
   else {
      waitbits = readbit;
   }
*/
   if(!rflag) {
      if(c = gotchar) {
         gotchar = 0;
         return(c);
      }
   }
   else {
      if(c = tncchar) {
         tncchar = 0;
         return(c);
      }
   }
   waitbits = windbit | readbit;
   not_done = 1;
   while(not_done)  {
      getbits = Wait(waitbits);
      if(windbit & getbits) {
         while(NewMessage = GetMsg(mywindow->UserPort)) {
            class = NewMessage->Class;
            code = NewMessage->Code;
            switch( class ) {
            case CLOSEWINDOW:
               if(done_flag)done(1);
               break;
            case RAWKEY:
            /* toasc also maps the Fn keys into the range 0320 - 0331 */
               c = toasc(code); /* change it to ascii */
               ReplyMsg(NewMessage);
               if(c == 0)break;
               if(c == '\033') {
                  sprintf(tmpstr,"rdchar-%x rflag = %d\n",
                           Read_Request->io_Status,rflag);
                  ttputs(tmpstr);
               }
               if(!rflag)return(c);
               break;
/*
            case MOUSEBUTTONS:
               mx = (NewMessage->MouseX)>>3;
               my = (NewMessage->MouseY)>>3;
               ReplyMsg( NewMessage );
               switch(code) {
               case SELECTDOWN:
                  break;
               case SELECTUP:
                  break;
               case MENUDOWN:
                  break;
               case MENUUP:
                  break;
               }
               break;
*/
            default:
               ReplyMsg( NewMessage );
            }   /* end of switch (class) */
         }
      }
      if(readbit & getbits) {
         if(CheckIO(Read_Request)) {
            WaitIO(Read_Request);
            ch = rs_in[0];
            if(tapr_flag)ch &= 0177;
            BeginIO(Read_Request);
            /* This detects any of the forms ~a |a ~~ and || .
               In the case of ~a or |a it removes both chars from the
               data stream but prints them on the screen.
               In the case of ~~ or || it passes ONE of them and
               prints one of them on the screen. The other is deleted.
            */
            if(gotstream) {
               if(ch == gotstream) {
                  gotstream = 0;
                  ttputc(gotstream);
               }
               else {
                  gotstream = 0;
                  ttputc(gotstream);
                  ttputc(ch);
                  continue;
               }
            }
            else {
               if((ch == vhfstream) || (ch == hfstream)) {
                  gotstream = ch;
                  continue;
               }
            }
            if(rflag)return(ch);
         }
      }
   }
   cleanup();
   exit();
}
/* check for character at console */
conchar()
{

   if(gotchar)return(1);
   if(NewMessage = GetMsg(mywindow->UserPort)) {
      class = NewMessage->Class;
      code = NewMessage->Code;
      ReplyMsg(NewMessage);
      if(class == RAWKEY) {
         /* toasc also maps the Fn keys into the range 0320 - 0331 */
         gotchar = toasc(code); /* change it to ascii */
      }
   }
   return(gotchar);
}
/* flags to look for the hf and vhf stream chars */
char seenpass = 0,seenstream = 0;
/* send character to the serial port */
schar(ch)
int ch;
{
   /* look for pass character and streamswitch chars */
   /* This does not modify them. It is simply looking for stream
      chars sent to the TNC which will change the current stream.
      A pass char in front of the stream char 'escapes' the
      switch function and passes it as raw data.
   */
   if(!seenpass) {
      if(ch == passchr) {
         seenpass = 1;
      }
      else {
         if(seenstream) {
            seenstream = 0;
         }
         else {
            if((ch == vhfstream) || (ch == hfstream)) {
               seenstream = ch;
            }
         }
      }
   }
   else {
      seenpass = 0;
   }
   Write_Request->IOSer.io_Command = CMD_WRITE;
   Write_Request->IOSer.io_Length = 1L;
   Write_Request->IOSer.io_Data = (APTR) &rs_out[0];
   rs_out[0] = ch;
   DoIO(Write_Request);
}

/* send the command string in s */
sends(s)
unsigned char *s;
{
   register unsigned char *p;
   register short i;
   i = 0;
   p = s;
   while(*p) {
      /* look for pass character and streamswitch chars */
      if(!seenpass) {
         if(*p == passchr) {
            seenpass = 1;
         }
         else {
            if(seenstream) {
               seenstream = 0;
            }
            else {
               if((*p == vhfstream) || (*p == hfstream)) {
                  seenstream = *p;
               }
            }
         }
      }
      else {
         seenpass = 0;
      }
      p++;
      i++;
   }
   if(i == 0)return;
   Write_Request->IOSer.io_Command = CMD_WRITE;
   Write_Request->IOSer.io_Length = i;
   Write_Request->IOSer.io_Data = (APTR) s;
   DoIO(Write_Request);
}
