#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include "common.h"

fsk_data fskdt;
fsk_data *fskdp=&fskdt;

/***************** ANSI escape format for color text *********************
ESC [ 01;<x><col>m
where	x=3	=>	Ink color
	x=4	=>	Paper color
and
	color =	0	Black
		1	Red
		2	Green
		3	Yellow
		4	Blue
		5	Magenta
		6	Cyan
		7	White

ESC [m		restores default settings.
*************************************************************************/

void printch(char a, char er)
{

	if ((a&0x7f)<32) {
		switch(a){
		case '\n':	break;
		case '\r':	return;
		case 8:		break;
		case 9:		break;
		default:	a=' ';
		}
	}
	switch(er){
	case 0:	printf("%c",a);break;
	case 1:	printf("\033[01;42m%c\033[m",a); break;
	case 2: printf("\033[01;41m%c\033[m",a); break;
	case 3: printf("\033[01;43m%c\033[m",a); break;
        case 4:
        case 5:
        case 6:
        case 7: printf("\033[2J\033[H<BRK>\n"); break;
        }
}


void read_config()
{
	int i,j;
	float x;
	FILE *fp;
	char *p, buf[256];

	if ((fp=fopen("rtty.cfg","r"))==NULL) return;

	fprintf(stderr,"#Reading setup from rtty.cfg...");
	fflush(stderr);

	for(;;) {
		fgets(buf,256,fp);
		if (feof(fp)) break;
		if (buf[0]=='#') continue;
		if ((p=strchr(buf,'='))==NULL) continue;
		*p++=0;
		x=atof(p);
                if (strcmp(buf,"MODE")==0) fskdp->mode=x;
		if (strcmp(buf,"SPACEF")==0) fskdp->spacef=x;
		if (strcmp(buf,"MARKF")==0) fskdp->markf=x;
		if (strcmp(buf,"DR")==0) {fskdp->dr=x;
			fskdp->phs=(fskdp->dr<<16)/FS;}
		if (strcmp(buf,"NBIT")==0) fskdp->nbit=x;
		if (strcmp(buf,"NSTOP")==0) {fskdp->nstop=x;
			if (x==1.5) fskdp->nstop05=1; else fskdp->nstop05=0;}
		if (strcmp(buf,"PARITY")==0) fskdp->parity=x;
                if (strcmp(buf,"CWT")==0) fskdp->cwt=x;
	}
	fprintf(stderr,"done\n");
	fclose(fp);
}

void save_settings()
{
        FILE *fp;
        if ((fp=fopen("rtty.cfg","w"))==NULL) return;
        fprintf(fp,"#-------- Modes: 0=RTTY, 1=CW, 2=HDLC -------\n");
        fprintf(fp,"MODE=%d\n#\n",fskdp->mode);
        fprintf(fp,"SPACEF=%f\n",fskdp->spacef);
        fprintf(fp,"MARKF=%f\n",fskdp->markf);
        fprintf(fp,"DR=%d\n",fskdp->dr);
        fprintf(fp,"NBIT=%d\n",fskdp->nbit);
        fprintf(fp,"NSTOP=%f\n",(fskdp->nstop05)?1.5:(float)fskdp->nstop);
        fprintf(fp,"#-------- parity: 0=none, 1=even, 2=odd ------\n");
        fprintf(fp,"PARITY=%d\n",fskdp->parity);
        fprintf(fp,"CWT=%f\n",fskdp->cwt);
        fclose(fp);
        fprintf(stderr,"\nSettings saved in file: rtty.cfg\n");
}

/****************** ENTRY POINT ****************/

main(int argc, char **argv)
{
	int i,j,a,er,nox=0;
	char *p,buf[4096];
        const char * const modename[3]={"RTTY","CW","HDLC"};
        const char * const parname[3]={"None","Even","Odd"};
        pthread_t pth;

        if (argc > 1) {
        	p=argv[1];
        	if (p[0]=='-' && p[1]=='x') nox=1;
        }

	/* default values */

	fskdp->phs=(DR<<16)/FS;	/* bit phase / sample */
	fskdp->nbit=5;		/* ASCII */
	fskdp->nstop=1;		/* STOP Bits*/
	fskdp->nstop05=1;	/* No 0.5 extra STOP bits */
	fskdp->parity=0;	/* Parity NONE */
	fskdp->spacef=FSPACE;	/* Initial Freqs */
	fskdp->markf=FMARK;
	fskdp->dr=DR;		/* Data Rate (for filters) */
        fskdp->mode=HDLC;          /* RTTY */
        fskdp->cwt=12.0;        /* CW Dot time */
        fskdp->cwatim=0;        /* no Auto-timing */

	read_config();

	set_filters(fskdp->spacef,fskdp->markf,fskdp->dr);
        init_audio();

#ifdef ENX11
        if(!nox) pthread_create(&pth, NULL, form_main , NULL);
	else
#endif
	{
		fprintf(stderr,"Current Setup:\n");
                fprintf(stderr,"Mode      : %s\n",modename[fskdp->mode]);
                if(fskdp->mode==CW)
                    fprintf(stderr,"Dot   len : %f\n",fskdp->cwt);
                else {
                    fprintf(stderr,"Data  Rate: %d baud\n",fskdp->dr);
                    if(fskdp->mode==RTTY) {
		        fprintf(stderr,"Data  Bits: %d\n",fskdp->nbit);
		        fprintf(stderr,"STOP  Bits: %d",fskdp->nstop);
		        if (fskdp->nstop05) fprintf(stderr,".5\n");
		        else fprintf(stderr,"\n");
		        fprintf(stderr,"Parity    : %s",parname[fskdp->parity]);
                    }
                    fprintf(stderr,"Space Freq: %g Hz\n",fskdp->spacef);
                }
                fprintf(stderr,"Mark  Freq: %g Hz\n",fskdp->markf);
	}

	/* Decoding loop */
	for(;;){
                fflush(stdout);
                if (fskdp->mode==RTTY) {
		    a=serial(); er=a>>8; a&=0xff;
		    if (fskdp->nbit==5) {
                        a=baudot(a);
                        if(!a) continue;
                    }
		    printch(a,er);
		    fflush(stdout);
                }
                if (fskdp->mode==HDLC){
                        i=hdlc(buf,4096);
                        if (!check_crc_ccitt(buf, i)) {
                                printf("HDLC PKT. Len=%d bytes CRC OK\n",i);
                                dump_addr(buf);
                                hdump(buf,i);
                                printf("\n");
                        }
                }
                if (fskdp->mode==CW) {
                    morsedec();
                }
	}
}
