/* SCS simple terminal
    Copyright 2005-2012 SCS GmbH & Co. KG, Hanau, Germany
    written by Peter Mack (peter.mack@scs-ptc.com)

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <linux/serial.h>

#include "lock.h"

// GLOBAL AND EXTERNAL VARIABLES
extern void checkSerialData();
extern int sockfd, n;
extern char recvBuff[];   // must indicate an array!
extern struct sockaddr_in serv_addr;
extern const char serveraddr[];  // must indicate an array!
char writebuffer[50];
extern int length;

//FUNCTIONS  
extern int socketstart();
extern void sendmessage();
extern void checkSerialData();




// for use with a patched kernel module please comment out the following line


#define BB0(x) ((uint8_t)x)             // Bust int32 into Bytes
#define BB1(x) ((uint8_t)(x>>8))
#define BB2(x) ((uint8_t)(x>>16))


//#define BAUDRATE	B38400	// custom divisor only works if baud is set to 38400 !
#define BAUDRATE	B115200	// this is the proper baudrate for the SCS PTC-IIIusb and a good choice for the PTC-II modem series

char serdev[] = "/dev/ttyUSB0";
int	ser;
int	run;
char 	buf[30];
unsigned long	frequency;   // to hold the frequency in Hz
void sigHandler (int sig)
{
    if (sig == SIGINT || sig == SIGTERM || sig == SIGQUIT || sig == SIGKILL || sig == SIGHUP)
    {
	run = 0;
    }
}

int main (void)
{
	fd_set	readfds, testfds;
	ssize_t rd;
	
	struct termios	new_termios, old_termios;
	struct serial_struct sstruct;
        FILE *fp1;   // file pointer for capture file 
        int	command, bytectr;  // GLG use


        printf("Hello, world!\n");


	printf ("SimpleTerm\n(c) 2005-2012 SCS GmbH & Co. KG, Hanau, Germany\npress CTRL-C to end program\n");

	if (lock_device (serdev) < 0)
	{
		// error
		fprintf (stderr, "Could not lock %s\n", serdev);
		return EXIT_FAILURE;
	}

	if ((ser = open (serdev, O_RDWR | O_NOCTTY)) == -1)
	{
		// Error
		fprintf (stderr, "Could not open %s\n", serdev);
		unlock_device (serdev);
		return EXIT_FAILURE;
	}

	if(socketstart()!=0 ) 
		{ 
                 printf ("Could not open telnet socket \n");
		}

	tcgetattr(ser, &old_termios);

	new_termios = old_termios;

	new_termios.c_cc[VTIME] = 0;
	new_termios.c_cc[VMIN] = 1;
	new_termios.c_iflag = 0;
	new_termios.c_iflag |= IGNBRK;
	new_termios.c_oflag = 0;
	new_termios.c_lflag = 0;
	new_termios.c_cflag |= (CS8 | CRTSCTS | CREAD | CLOCAL);
	new_termios.c_cflag &= ~(CSTOPB | PARENB | PARODD | HUPCL);

	cfsetispeed(&new_termios, BAUDRATE);
	cfsetospeed(&new_termios, BAUDRATE);

	tcsetattr(ser, TCSANOW, &new_termios);



	signal (SIGALRM, sigHandler);
	signal (SIGINT, sigHandler);
	signal (SIGTERM, sigHandler);
	signal (SIGQUIT, sigHandler);
	signal (SIGKILL, sigHandler);
	signal (SIGHUP, sigHandler);

	FD_ZERO (&readfds);
	FD_SET (ser, &readfds);
	FD_SET (0, &readfds);

	write (ser, "\r", 1);

        printf("\n\n\n TYPE !  (EXCLAMATION POINT)  TO EXIT CLEANLY \n\n\n");


	run = 1;
 
	while (run)
	{
		testfds = readfds;
		if (select (FD_SETSIZE, &testfds, NULL, NULL, NULL) < 0)
		{
			//fprintf (stderr, "Select error!\n");
			//return EXIT_FAILURE;
			goto EXIT;
		}

		if (FD_ISSET (ser, &testfds))
		{
		
                  do {
                 	rd = read (ser, buf, 1);
                     } while ( (rd!=1) || (buf[0] != 0xFE)  );
                  // if we get here, it has seen an FE, one more confirms
                        do { 
                             rd = read(ser, buf, 1);
                            }  while (rd!=1); // read until we get the next char
                        if (buf[0]==0xFE) 
                        {
                        printf("Command Initiation: %x \n",buf[0]);
                  // having seen two FE's we are indeed at a command
                        command = 1;
                        bytectr = 0;
                        do {
                            rd = read (ser, buf+bytectr, 1);
                            printf("Char: %x \n",buf[bytectr]);
                            if ( (buf[bytectr] == 0xFD) || (bytectr>20) ) 
                                {
                                 command=0;  // we stop capturing additional characters
                                 
                                 }
                            else bytectr++;   
                            }  while (command ==1) ;
                        
                        checkSerialData(bytectr);
                         } // end of if(buf[0]==0xFE)
                        

		}

		if (FD_ISSET (0, &testfds))
		{
			rd = read (0, buf, 256);
			buf[rd - 1] = '\r';
			write (ser, buf, rd);
                        if (strchr(buf, 0x21) != NULL) // exlamation point hex 21 
                        {
                         printf("Finishing capture \n");
                         run=0;  // this will cause the loop to move to EXIT: 
                         }

		}
	}

EXIT:
	close (ser);
	unlock_device (serdev);

 

	printf ("\n");

	return EXIT_SUCCESS;
}



// --------------------------TRY TWO TO DO CAT---------------------------

//  The minimum command we have to listen for is change frequency
//  5 bytes:   MM MK KK HH  01   is the command
//  where MMM are the megaherts  (eg  01 4
//  and the KKK are the kilohertz  (eg   234 
//  so for example   01, 42, 345, 56, 01 means
//  change frequency to 14,234.56 kilohertz


void checkSerialData(int cmdlength) {
  int packed; 
  int i = strlen(buf);
  printf("Length of command: %d \n", i);
  //printf("Hex of command:  %x \n",buf);

    if (cmdlength < 5) 
    {
    printf("Short:  %3x \n",buf);
    return;
    }

 // if you got here then there are at least 5 ints (?bytes?)  waiting: get it.

printf( ">=5 bytes\n");
//  0 =  CI-V of called radio
//  1 =  CI-V of calling from
//  2 =  Command   3= subcommand if exists
//  3 =  10Hz/1Hz
//  4 =  1kHz/100Hz
//  5 =  100kHz/10kHz
//  6 =  10 MHz/1MHz
//  7 we really don't need
//printf( "Command:  %5x \n ", buf);

    // now chek for the ICOM command in the first byte of command
    switch (buf[2]) 
    {
       
   
        case 0x5:             // #5 is for frequency set
// frequency is in packed BCD; binary coded decimal;
// so left 4 bits give top decimal number 0-9  and right 4 bits give bottom decimal number 0-9


//        case CAT_FREQ_SET:
            // convert the 4 bytes of numbers (tens of MHz), (hundreds of kHz), (kHz), (tens of hz)
          frequency = 0UL; 
          packed = buf[6];
          frequency =     1000000UL *   (unsigned long) ( ((packed & 0xF0)>>4 )* 10  +   (packed & 0x0F) ) ;
          packed = buf[5];
          frequency = frequency +  10000UL *   (unsigned long) ( ((packed & 0xF0)>>4 )* 10  +   (packed & 0x0F));
          packed = buf[4];
          frequency = frequency + 100UL *   (unsigned long) ( ((packed & 0xF0)>>4 )* 10  +   (packed & 0x0F)); 
          packed = buf[3];
          frequency = frequency  + 1UL *  (unsigned long) ( ((packed & 0xF0)>>4 )* 10  +   (packed & 0x0F)); 

	  printf("\nFrequency:  %lu \n",frequency);
	  sprintf(writebuffer,"FREQ %lu \n",frequency);
          sendmessage(writebuffer);
            break;
        case 0x06:  // #6 is for setting operating mode
        if( buf[3]==0x00)
               {
                // Use LSB mode
                printf("LSB \n");
	  	sprintf(writebuffer,"MODE LSB \n");
          	sendmessage(writebuffer);
               }
        if( buf[3]==0x01)
               {
               //  Use USB mode
               printf("USB \n");
	  	sprintf(writebuffer,"MODE USB \n");
          	sendmessage(writebuffer);
               }
        if( buf[3]==0x03)
               {
               // Use CW mode
               printf ("CW \n");
	  	sprintf(writebuffer,"MODE CW \n");
          	sendmessage(writebuffer);
               }
        if( buf[3] ==0x07)
               {
               // Use CW-R mode (USB)
               printf ("CW-R USB");
	  	sprintf(writebuffer,"MODE CWR \n");
          	sendmessage(writebuffer);
               }
    
        break;
 
        case 0x1A:  // #1a is for setting data operating mode
        if( buf[3]==0x00)
               {
                // Use LSB-D mode
                printf("LSB Data\n");
		// no difference at present
	  	sprintf(writebuffer,"MODE LSB \n");
          	sendmessage(writebuffer);
               }
        if( buf[3]==0x01)
               {
               //  Use USB-D mode
               printf("USB Data \n");
               // no difference at present
	  	sprintf(writebuffer,"MODE USB \n");
          	sendmessage(writebuffer);
                //SET THE AUDIO BANDWIDTH
	  	sprintf(writebuffer,"BW 2800 \n");
          	sendmessage(writebuffer);
               }
        if( buf[3]==0x03)
               {
               // Use CW mode
               printf ("CW-Data \n");
	  	sprintf(writebuffer,"MODE CW \n");
          	sendmessage(writebuffer);
                }
        if( (buf[3] ==0x06) & (buf[4]==0x01) )
               {
               // Use usb-D mode (USB)
               printf (" USB DATA");
	  	sprintf(writebuffer,"MODE USB \n");
          	sendmessage(writebuffer);
                //SET THE AUDIO BANDWIDTH
	  	sprintf(writebuffer,"BW 2800 \n");
          	sendmessage(writebuffer);
               }
        if( buf[3] ==0x07)
               {
               // Use CW-R mode (USB)
               printf ("CW-R Data USB");
	  	sprintf(writebuffer,"MODE CWR \n");
          	sendmessage(writebuffer);
               }
    
        break;
        case 0x1C:             // #0x1c controls TX/RX
        if (buf[3]==0x00 & buf[4]==0x00) 
               {
                // go into receive mode
                printf("Into RCV \n");
	  	sprintf(writebuffer,"RX \n");
          	sendmessage(writebuffer);
               }
        if (buf[3]==0x00 & buf[4]==0x01)
               {
                // go into transmit mode
                printf("TRANSMIT \n");
	  	sprintf(writebuffer,"TX \n");
          	sendmessage(writebuffer);
               }
        break;      
   



       
        default:
            printf("Other cmd \n");
//            Serial.write(ACK);x
            break;
    }

}    





