// COMM.C - Comunication-window-routines
// Written by Stefan Pfeiffer, DL1ELY, 950819
// Last modification: 950827
// (C) 1995 by Stefan Pfeiffer, DL1ELY@DB0PKE

#include "dvideo.h"
#include "comm.h"
#include "fivenine.h"
#include "sio.h"
#include "secmem.h"
#include <string.h>
#include <stdarg.h>
#include <stdio.h>

char **comm_buf = NULL;

unsigned int comm_lines;
unsigned int comm_write;
unsigned int comm_out;

char tnc_port[20];
char tnc_baudrate[10];
char tncport;
char tnc_type;

char tnc_channels;
unsigned tnc_channel_buf;
unsigned tnc_tx_buf;
char tnc_mycall[10];

struct ch_des *chan;
char tnc_chan;

unsigned long *timer = MK_FP(0x0040,0x006C);


void tnc_init()
{
   char ch;
   char len;
   char type;
   char buf[256];

   if(!tnc_port[0])
   {
      tnc_type = TNC_NONE;
      return;
   };

   strupr(tnc_port);
   if(!strcmp(tnc_port,"NONE"))
   {
      tnc_type = TNC_NONE;
      return;
   };

   if(!strcmp(tnc_port,"TFPC"))
   {
      tnc_type = TNC_TFPC;
      return;
   };

   tnc_type = TNC;
   tncport = atoi(tnc_port);

   if((tncport<1)||(tncport>>4))
   {
      tnc_type = TNC_NONE;
      return;
   };

   com[tncport] = sec_alloc(sizeof(struct port_des));
   memset(com[tncport],0,sizeof(struct port_des));
   com[tncport]->com = tncport;
   com[tncport]->baudrate = atol(tnc_baudrate);

   if(!com[tncport]->baudrate)
   {
      tnc_type = TNC_NONE;
      return;
   };

   sio_init_port(com[tncport]);
   tnc2hostmode(com[tncport]);

   sprintf(buf,"Y%u",tnc_channels);
   tnc_send_cmd(com[tncport],0,buf);
   tnc_rx(com[tncport],&ch,&type,&len,buf);

   tnc_send_cmd(com[tncport],0,"MUSIC");
   tnc_rx(com[tncport],&ch,&type,&len,buf);

   chan = sec_alloc(tnc_channels*sizeof(struct ch_des));
   memset(chan,0,tnc_channels*sizeof(struct ch_des));

   for(tnc_chan = 0;tnc_chan<=tnc_channels;tnc_chan++)
   {
      sprintf(buf,"I %s",tnc_mycall);

      strcpy(chan[tnc_chan].mycall,tnc_mycall);
      chan[tnc_chan].state = NOT_CONNECTED;
      chan[tnc_chan].rx_buf = sec_alloc(tnc_channel_buf*sizeof(char *));
      chan[tnc_chan].tx_buf = sec_alloc(tnc_tx_buf*sizeof(char *));

      tnc_send_cmd(com[tncport],tnc_chan,buf);
      tnc_rx(com[tncport],&ch,&type,&len,buf);
   };

   tnc_chan = 0;
};


void tnc_poll()
{
   char ch;
   char type;
   char len;
   char buf[260];
   char hlp[81];
   char cp, cp2;

   tnc_send_cmd(com[tncport],tnc_chan,"G");
   tnc_rx(com[tncport],&ch,&type,&len,buf);

   if((type == 5) || (type == 4))
   {
      buf[len+1] = 0;
      comm_printf(buf);
   };
   if(type == 6)
   {
      cp = 0;
      while(cp<=len)
      {
         cp2 = 0;
         while(buf[cp]!=13 && (cp<=len) && (cp2<80))
         {
            if(buf[cp]>=32)
            {
               hlp[cp2] = buf[cp];
            }
            else hlp[cp2] = '.';
            cp++;
            cp2++;
         };
         cp++;
         hlp[cp2] = 0;
         comm_printf(hlp);
      };
   };
 
   tnc_chan++;
   if(tnc_chan>tnc_channels) tnc_chan = 0;
};


void tnc_deinit()
{
   char ch;
   char type;
   char len;
   char buf[260];

   if(tnc_type == TNC)
   {
      for(tnc_chan = 0;tnc_chan<=tnc_channels;tnc_chan++)
      {
         sec_free(chan[tnc_chan].rx_buf);
         sec_free(chan[tnc_chan].tx_buf);
      };
      sec_free(chan);

      tnc_send_cmd(com[tncport],0,"JHOST0");
      tnc_rx(com[tncport],&ch,&type,&len,buf);
      sec_free(com[tncport]);
      tncport = 0;
      tnc_type = TNC_NONE;
   };
   return;
};

void comm_init(unsigned int lines)
{
   if(comm_buf) return;

   comm_buf = sec_alloc(lines*sizeof(char *));
   memset(comm_buf,0,lines*sizeof(char *));

   comm_lines = lines;
   comm_write = 0;
   comm_out = 0;
};

void comm_output()
{
/*   if((comm_out!=comm_write) && pr_lines)
   {
      if(pr_lines>1) dmove(0,9,lastrow,7+pr_lines,0,8);
      dfill(0,7+pr_lines,lastrow,7+pr_lines,' ',textcol);
      dprint(0,7+pr_lines,textcol,comm_buf[comm_out]);
      comm_out++;
      if(comm_out == comm_lines) comm_out = 0;
   };*/
};

void comm_printf(char *fmt, ...)
{
   va_list vl;
   char buf[81];

   va_start(vl,fmt);
   vsprintf(buf,fmt,vl);
   va_end(vl);

   if(comm_buf[comm_write]) sec_free(comm_buf[comm_write]);
   comm_buf[comm_write] = sec_alloc(strlen(buf)+1);
   strcpy(comm_buf[comm_write],buf);
   comm_write++;
   if(comm_write == comm_lines) comm_write = 0;
};

void comm_end()
{
   unsigned int i;

   for(i=0;i<comm_lines;i++)
      if(comm_buf[i][0]) sec_free(comm_buf[i]);

   sec_free(comm_buf);
   comm_buf = NULL;
};


void tnc_send_cmd(struct port_des *p, char ch, char *buf)
{
   char tnc_buf[260];

   tnc_buf[0] = ch;
   tnc_buf[1] = 0x01;
   tnc_buf[2] = strlen(buf)-1;
   strcpy(&tnc_buf[3],buf);

   sio_tx(p,strlen(buf)+3,tnc_buf);
};

void tnc_send_data(struct port_des *p, char ch, char *buf)
{
   char tnc_buf[260];

   tnc_buf[0] = ch;
   tnc_buf[1] = 0x00;
   tnc_buf[2] = strlen(buf)-1;
   strcpy(&tnc_buf[3],buf);

   sio_tx(p,strlen(buf)+3,tnc_buf);
};

void tnc_rx(struct port_des *p, char *ch, char *type, char *len, char *buf)
{  
   char i;
   unsigned long start;

   start = *timer;
   while((!sio_rx_bytes(p)) && (*timer<start+6)) ;

   if(!sio_rx_bytes(p))
   {
      tnc_resync(p);
      return;
   };
   sio_rx(p,1,ch);

   start = *timer;
   while((!sio_rx_bytes(p)) && (*timer<start+6)) ;

   if(!sio_rx_bytes(p))
   {
      tnc_resync(p);
      return;
   };
   sio_rx(p,1,type);

   switch(*type)
   {
      case 0:
         len = 0;
         *buf = 0;
         break;
      case 1:
      case 2:
      case 3:
      case 4:
      case 5:
         *len = 0;

         do
         {
            while((!sio_rx_bytes(p)) && (*timer<start+6)) ;
               
            if(!sio_rx_bytes(p))
            {
               tnc_resync(p);
               return;
            };
            sio_rx(p,1,buf);
            buf++;
            (*len)++;
         } while(*(buf-1));
         (*len)--;
         break;
      case 6:
      case 7:
         while((!sio_rx_bytes(p)) && (*timer<start+6)) ;
            
         if(!sio_rx_bytes(p))
         {
            tnc_resync(p);
            return;
         };
         sio_rx(p,1,len);
         i = (*len)+1;

         for(;i;i--)
         {
            while((!sio_rx_bytes(p)) && (*timer<start+6)) ;
               
            if(!sio_rx_bytes(p))
            {
               tnc_resync(p);
               return;
            };
            sio_rx(p,1,buf);
            buf++;
         };
         *buf = 0;
         break;
   };
   return;
};


void tnc2hostmode(struct port_des far *p)
{
   char buf[260];
   char ch;
   char type;
   char len;

   buf[0] = 0x11;
   buf[1] = 0x18;
   buf[2] = 0x1B;
   strcpy(&buf[3],"JHOST1");
   buf[9] = 0x0D;
   
   sio_tx(p,10,buf);
   delay(200);
   while(sio_rx_bytes(p)) sio_rx(p,1,buf);

   tnc_send_cmd(p,0,"G");
   tnc_rx(p,&ch,&type,&len,buf);

   if(type>6) tnc_resync(p);
};

void tnc_resync(struct port_des *p)
{
   unsigned counter;
   char buf[260];
   char ch;
   char type;
   char len;

   counter = 0;
   do
   {
      buf[0] = 1;
      sio_tx(p,1,buf);

      sound(100);
      delay(100);
      nosound();
      counter++;
   } while((!sio_rx_bytes(p)) && (counter<300));

   if(counter == 300)
   {
      sound(50);
      delay(500);
      nosound();
      tnc_type = TNC_NONE;
   }
   else
   {
      tnc_rx(p,&ch,&type,&len,buf);
      sound(800);
      delay(100);
      nosound();
   };
};


