/* Program to read and edit binary eprom file for Motorola MSF5000	*/
/* Created by modifying Syntor program created in 2004	*/
/* This version started July 2007 -  Jerry Dries - N7HYV	*/
/* November 09, 2008 Added edit routines. PTT priority still missing	*/
/* November 11, 2008 Fixed issues with frequency C divisor calcs	*/
/* April 24, 2009 PTT Priority working	*/
/* May 21, 2009 Tune frequencies update	*/
/* May 22, 2009 Checksum calculated	*/
/* May 28, 2009 Checksum might be working now	*/
/* Working on call sign data	*/
/* May 30, 2009 Working bugs in Tune channel	*/
/* March 8, 2010 Attempting to read version 4 codeplug	*/
/* March 26, 2010 Working on CW callsign	*/
/* April 2, 2010 Fixed checksum calculation	*/
/* April 10, 2011 reading byte 0x07 for channel size	*/
/* April 27, 2011 Fixed minor bug in reading call sign	*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dirent.h>

unsigned char eprom[4096],version;
unsigned int data_addr,num_channels,cw_addr,chan_size;
unsigned int max_tx=0,max_rx=0,min_tx=0x3fffffff,min_rx=0x3fffffff;
unsigned int center_rx,center_tx;
/* long int may be needed on some platforms	*/

char color=0;
struct pll_data	{
	unsigned int a : 6;
	unsigned int b : 10;
	unsigned int c : 2;
	unsigned int r;
};

char tone[42][6]={{" 67.0"},{" 69.3"},{" 71.9"},{" 74.4"},{" 77.0"},{" 79.7"},
		{" 82.5"}, {" 85.4"},{" 88.5"},{" 91.5"},{" 94.8"},{" 97.4"},
		{"100.0"}, {"103.5"},{"107.2"},{"110.9"},{"114.8"},{"118.8"},
		{"123.0"}, {"127.3"},{"131.8"},{"136.5"},{"141.3"},{"146.2"},
		{"151.4"}, {"156.7"},{"162.2"},{"167.9"},{"173.8"},{"179.9"},
		{"186.2"}, {"192.8"},{"203.5"},{"206.5"},{"210.7"},{"218.1"},
		{"225.7"}, {"229.1"},{"233.6"},{"241.8"},{"250.3"},{"254.1"}};

/* Subtract 32 from ASCII code for array address	*/
unsigned int morse[60]={0,9999,9999,9999,9999,9999,9999,9999,9999,9999,9999,9999,2650,9999,
		1638,601,682,426,362,346,342,341,597,661,677,681,9999,9999,9999,
		9999,9999,1445,9999,6,149,153,37,1,89,41,85,
		5,106,38,101,10,9,42,105,166,25,21,2,22,86,26,150,154,165};
/* ,.?/ 0-9 and A-Z entered */

void edit_channel(void);
void channel_summary(void);
void display_channel(unsigned int);
void clear_kb(void);
void edit_txf(unsigned int);
void edit_tune_tx(void);
void edit_tune_rx(void);
void edit_rxf(unsigned int);
void edit_idle(unsigned int);
void edit_enc(unsigned int);
void edit_dec(unsigned int);
void edit_squelch(unsigned int);
void edit_timers(unsigned int);
void edit_ptt_priority(unsigned int);
void edit_alarms(unsigned int);
void write_plug(void);
void existing_eprom(void);
int int_input(void);
void show_tones(void);
int checksum_verify(void);
void read_callsign(char *,int);

int main() {
	FILE *plug;
	int choice;
	unsigned int i,j,k;
	char plug_name[255];
	char temp[255];
	char *temp_ptr;
	extern unsigned int data_addr,num_channels,chan_size;
	extern unsigned char eprom[],version;

	if (sizeof(unsigned int)<4) {
		printf("Interger size too small\n");
		exit(1);
	}

	temp_ptr=getenv("TERM");
	if (temp_ptr!=NULL) {
		strcpy(temp,temp_ptr);
		printf("Found terminal type: %s\n",temp);
		if (strncmp(temp,"xterm",5)==0)
			color=1;
		if (strncmp(temp,"linux",5)==0)
			color=1;
	}
	if(color) printf("\033[1;34m");
	printf("\v\tAnalog MSF5000 Programming\n");
	printf("\v\t\tDE: N7HYV\n\n");
	if (color) printf("\033[1;31m");
	printf("\tVersion 0.9-beta May, 2009\n\n");
	if (color) printf("\033[0m");
	printf("This program reads and modifies a binary image of the\n");
	printf("analog MSF5000 codeplug EPROM.\n\n");

	existing_eprom();	/* Read code plug from file	*/
	i=checksum_verify();	/* Calculate checksum		*/
	version=eprom[0x05];	/* Verify Codeplug version	*/
	chan_size=eprom[0x07];	/* number of bytes per channel	*/
	if (version!=3) {
		if (color) printf("\033[1;31m");
		printf("\nCodePlug version %d!",version);
	        if (color) printf("\033[0m");
		printf (" This program untested for version %d.\n\n",version);
		if (version !=4) return(1);
	}

	/* read MSF5000 channel address  */
	j=eprom[0x017];
	j=j<<8;
	j=j|eprom[0x018];
	j=j&0x1fff;
	i=eprom[0x0008];
	printf("Number of radio channels appears to be %d\n",i-1);
	if ((i>17)||(i<2)) {
		/* something wrong  */
		printf("Something wrong with channel count\n");
		printf("Proceed with caution\n");
		i=2;
	}
	num_channels=i;
	data_addr=j;
	printf("First channel at address 0x%.4X\n\n",data_addr);
	printf("CW ID character speed is 0x%02X%02X\n\n",eprom[0x001f],eprom[0x0020]);

	channel_summary();

	while((choice!=88)&&(choice!=120)) {
		printf("\n");
		printf("  (E) Edit Channel\n");
		printf("  (Dn) Display Channel n\n");
		printf("  (S) Channel Summary\n");
		printf("  (W) Write Code Plug file\n");
		printf("  (X) Exit Program\n");
		printf("\nEnter option --> ");

		temp_ptr=fgets(temp,4,stdin);
		if (temp_ptr==NULL) {
                        printf("\nUnknown error/n/n");
                        continue;
                }
                choice=strlen(temp);
                if (temp[choice-1]!='\n') { /* clear keyboard buffer */
                        choice=0;
                        while (choice!='\n')
                                choice=getchar();
                }
                printf("\n");
                choice=temp[0];

		if ((choice==101)||(choice==69)) {
			edit_channel();
		}
		if ((choice==68)||(choice==100)) {
			strcpy(temp,temp+1);
			k=atoi(temp);
			printf("\n\t\t----- Channel %d -----\n",k);
			display_channel(k);
		}
		if ((choice==83)||(choice==115)) {
			channel_summary();
		}
		if ((choice==87)||(choice==119)) {
			channel_summary();
			write_plug();
		}
	}
	return 0;
} /* End of main() */

void channel_summary() {
	char buffer[255];
	char callsign[32];
	struct pll_data rx_div,tx_div;
	unsigned int i,j,k;
	char rx_code_type,tx_code_type;
	unsigned int byte,rx_freq,tx_freq,rx_code,tx_code;
	extern unsigned int num_channels,max_tx,max_rx,min_tx,min_rx,center_rx,center_tx,chan_size;
	extern unsigned char eprom[];
	callsign[0]='\0';

	printf("\nCh\tTX Freq\t\tRX Freq\t\tTX code\t\tRX code   callsign\n");
	memset(buffer,95,79);
	*(buffer+79)='\0';
	strcat(buffer,"\n");
	printf(buffer);
	for(i=0;i<num_channels;i++) {
/*		if (version==3) byte=data_addr+23*i;
		else byte=data_addr+24*i;
*/
		byte=data_addr+(chan_size*i);
		/* Find RX A divisor	*/
		j=eprom[byte];
		rx_div.a=j>>4;
		rx_div.a&=0x0f;
		rx_div.a^=0x01;
		k=j<<4;
		k&=0x30;
		rx_div.a|=k;

		/* Find RX B divisor	*/
		j=eprom[byte+1];
		rx_div.b=j<<6;
		k=j>>2;
		k&=0x3c;
		rx_div.b|=k;
		k=eprom[byte]>>2;
		k&=0x03;
		k^=0x01;
		rx_div.b|=k;

		/* Find RX C divisor	*/
		j=eprom[byte+2];
		j=j>>4;
		j&=0x03;
		switch (j) {
			case 0: rx_div.c=0; break;
			case 1: rx_div.c=1; break;
			case 2: rx_div.c=3; break;
			case 3: rx_div.c=2; break;
			default: break;
		}

		/* Find RX Reference	*/
		j=eprom[byte+2];
		j&=0x03;
		switch (j) {
			case 1: rx_div.r=6250; break;
			case 2: rx_div.r=4166; break;
			case 3: rx_div.r=5000; break;
			default: rx_div.r=0;
		}

		if (rx_div.r==0) {
			printf("\nBad RX reference value on channel %d!\n\n",i+1);
			rx_div.r=1000;
			/*return;*/
		}

		/* Find TX A divisor	*/
		j=eprom[byte+3];
		tx_div.a=j>>4;
		tx_div.a&=0x0f;
		tx_div.a^=0x01;
		k=j<<4;
		k&=0x30;
		tx_div.a|=k;

		/* Find TX B divisor	*/
		j=eprom[byte+4];
		tx_div.b=j<<6;
		k=j>>2;
		k&=0x3c;
		tx_div.b|=k;
		k=eprom[byte+3]>>2;
		k&=0x03;
		k^=0x01;
		tx_div.b|=k;

		/* Find TX C divisor	*/
		j=eprom[byte+5];
		j=j>>4;
		j&=0x03;
		switch (j) {
			case 0: tx_div.c=0; break;
			case 1: tx_div.c=1; break;
			case 2: tx_div.c=3; break;
			case 3: tx_div.c=2; break;
			default: break;
		}

		/* Find TX Reference	*/
		j=eprom[byte+5];
		j&=0x03;
		switch (j) {
			case 1: tx_div.r=6250; break;
			case 2: tx_div.r=4166; break;
			case 3: tx_div.r=5000; break;
			default: tx_div.r=0;
		}
		if (tx_div.r==0) {
			printf("\nBad TX reference value on channel %d!\n",i+1);
			tx_div.r=1000;
			/*return;*/
		}
		/* RX Tone  */
		j=eprom[byte+13];
		rx_code=j&0xff;
		rx_code=rx_code<<8;
		j=eprom[byte+14];
		rx_code=rx_code|j;

		/* TX Tone  */
		j=eprom[byte+11];
		tx_code=j&0xff;
		tx_code=tx_code<<8;
		j=eprom[byte+12];
		tx_code=tx_code|j;

		/* Calculate Frequencies	*/
		rx_freq=3*(rx_div.a*64+rx_div.b*63);
		rx_freq+=rx_div.c;
		rx_freq*=rx_div.r;
		rx_freq+=10700000;

		tx_freq=3*(tx_div.a*64+tx_div.b*63);
		tx_freq+=tx_div.c;
		tx_freq*=tx_div.r;

		/* Calculate Tune Frequencies	*/
		if (i<(num_channels-1)) {
			if (tx_freq>max_tx)
				max_tx=tx_freq;
			if (rx_freq>max_rx)
				max_rx=rx_freq;
			if (tx_freq<min_tx)
				min_tx=tx_freq;
			if (rx_freq<min_rx)
				min_rx=rx_freq;
		}

		/* Calculate squelch codes	*/
		
		if ((tx_code&0x8000)==0) {
			tx_code_type=0; /* PL Tone */
			tx_code=tx_code&0x7fff;
		}
		else {
			tx_code_type=1; /* DPL Code */
			j=tx_code&0x0380;
			j=j<<1;
			j=j|(tx_code&0x0070);
			j=j|((tx_code&0x000e)>>1);
			tx_code=j;
		}

		if ((rx_code&0x8000)==0) {
			rx_code_type=0; /* PL Tone */
			rx_code=rx_code&0x3fff;
		}
		else {
			rx_code_type=1; /* DPL Code */
			j=rx_code&0x0380;
			j=j<<1;
			j=j|(rx_code&0x0070);
			j=j|((rx_code&0x000e)>>1);
			rx_code=j;
		}

		read_callsign(callsign,eprom[byte+18]);

		printf("%2d\t%009.5f\t%009.5f",i+1,(double)tx_freq/1000000,(double)rx_freq/1000000);
		if (tx_code_type==0)  /* PL Tone	*/ {
			printf("\t%05.1f Hz",(double)tx_code*.04926);
		}
		else		/* DPL Code	*/
			printf("\t%03X  DPL",tx_code);

		if (rx_code_type==0)  /* PL Tone	*/ {
			printf("\t%05.1f Hz",(double)rx_code*.01642);
		}
		else		/* DPL Code	*/
			printf("\t%03X  DPL",rx_code);

		printf("  %s",callsign);
		printf("\n");
	}
		printf("\n\t\tThe last channel is the Tune channel\n\n");

/*
printf("Max TX is %d\n",max_tx);
printf("Min TX is %d\n",min_tx);
printf("Max RX is %d\n",max_rx);
printf("Min RX is %d\n",min_rx);
*/
	center_rx=(max_rx+min_rx)/2;
	center_rx=(unsigned int) (center_rx/rx_div.r);
	center_rx=center_rx*rx_div.r;
/* printf("Center RX is %d\n",center_rx);	*/
	center_tx=(max_tx+min_tx)/2;
	center_tx=(unsigned int) (center_tx/tx_div.r);
	center_tx=center_tx*tx_div.r;
printf("\tCenter Frequncies: TX - %d\t",center_tx);
printf("RX - %d\n",center_rx);
	return;
}

void display_channel(unsigned int channel) {
	unsigned int j,k,freq;
	unsigned int tx_div_a,tx_div_b,tx_div_c;
	unsigned int rx_div_a,rx_div_b,rx_div_c;
	unsigned int idle_div_a,idle_div_b,idle_div_c;
	unsigned int line_priority,local_priority,rpt_priority;
	unsigned int line_tot,local_tot,rpt_tot,tail;
	unsigned int rpt_control,rx_ref,tx_ref,idle_ref;
	unsigned int rx_tone,tx_tone,rx_gate;
	unsigned int rx_code_type,tx_code_type;
	unsigned int buff_i;
	unsigned int address;
	char buffer[127];
	char rx_code[5],tx_code[5];
	extern unsigned char eprom[];
	extern unsigned int chan_size;
	extern char color;
	char callsign[32];
	callsign[0]='\0';

/*	if (version==3) address=(data_addr+(23*(channel-1)));
	else address=(data_addr+(24*(channel-1)));
*/
	address=data_addr+(chan_size*(channel-1));


			/* read rx_div_a  */
	j=eprom[address];
	k=j>>4;
	rx_div_a=k&0x0f;
	rx_div_a=rx_div_a^0x01;
	k=j<<4;
	k=k&0x30;
	rx_div_a=rx_div_a|k;

	/* read rx_div_b  */
	k=j>>2;
	k=k^0x01;
	rx_div_b=k&0x03;
	j=eprom[address+1];
	k=j>>2;
	k=k&0x3c;
	rx_div_b=rx_div_b|k;
	k=j<<6;
	k=k&0x3c0;
	rx_div_b=rx_div_b|k;

	/* read rx_div_c  */
	j=eprom[address+2];
	k=j>>4;
	k&=0x03;
	switch (k) {
		case 0: rx_div_c=0; break;
		case 1: rx_div_c=1; break;
		case 2: rx_div_c=3; break;
		case 3: rx_div_c=2; break;
		default: break;
	}

	/* read rx_ref  */
	k=j&0x03;
	switch (k) {
		case 0: rx_ref=0; break;
		case 1: rx_ref=6250; break;
		case 2: rx_ref=4167; break;
		case 3: rx_ref=5000;
	}

	/* read tx_div_a  */
	j=eprom[address+3];
	k=j>>4;
	tx_div_a=k&0x0f;
	tx_div_a=tx_div_a^0x01;
	k=j<<4;
	k=k&0x30;
	tx_div_a=tx_div_a|k;

	/* read tx_div_b  */
	k=j>>2;
	k=k^0x01;
	tx_div_b=k&0x03;
	j=eprom[address+4];
	k=j>>2;
	k=k&0x3c;
	tx_div_b=tx_div_b|k;
	k=j<<6;
	k=k&0x3c0;
	tx_div_b=tx_div_b|k;

	/* read tx_div_c  */
	j=eprom[address+5];
	k=j>>4;
	k&=0x03;
	switch (k) {
		case 0: tx_div_c=0; break;
		case 1: tx_div_c=1; break;
		case 2: tx_div_c=3; break;
		case 3: tx_div_c=2; break;
		default: break;
	}

	/* read tx_ref  */
	k=j&0x03;
	switch (k) {
		case 0: tx_ref=0; break;
		case 1: tx_ref=6250; break;
		case 2: tx_ref=4167; break;
		case 3: tx_ref=5000;
	}

	/* TX priority  */
	j=eprom[address+7];
	k=j&0x30;
	line_priority=k>>4;
	k=j&0x0c;
	local_priority=k>>2;
	rpt_priority=j&0x03;


	/* read idle_div_a  */
	j=eprom[address+19];
	k=j>>4;
	idle_div_a=k&0x0f;
	idle_div_a=idle_div_a^0x01;
	k=j<<4;
	k=k&0x30;
	idle_div_a=idle_div_a|k;

	/* read idle_div_b  */
	k=j>>2;
	k=k^0x01;
	idle_div_b=k&0x03;
	j=eprom[address+20];
	k=j>>2;
	k=k&0x3c;
	idle_div_b=idle_div_b|k;
	k=j<<6;
	k=k&0x3c0;
	idle_div_b=idle_div_b|k;

	/* read idle_div_c  */
	j=eprom[address+21];
	k=j>>4;
	k&=0x03;
	switch (k) {
		case 0: idle_div_c=0; break;
		case 1: idle_div_c=1; break;
		case 2: idle_div_c=3; break;
		case 3: idle_div_c=2; break;
		default: break;
	}

	/* read idle_ref  */
	k=eprom[address+21]&0x03;
	switch (k) {
		case 0: idle_ref=0; break;
		case 1: idle_ref=6250; break;
		case 2: idle_ref=4167; break;
		case 3: idle_ref=5000;
	}

	/* Timers  */
	j=eprom[address+8];
	line_tot=j*15;
	j=eprom[address+9];
	local_tot=j*15;
	j=eprom[address+10];
	k=j&0x1f;
	rpt_tot=k*15;
	k=j>>5;
	tail=k;

	/* RX Tone  */
	j=eprom[address+13];
	rx_tone=j&0xff;
	rx_tone=rx_tone<<8;
	j=eprom[address+14];
	rx_tone=rx_tone|j;

	/* TX Tone  */
	j=eprom[address+11];
	tx_tone=j&0xff;
	tx_tone=tx_tone<<8;
	j=eprom[address+12];
	tx_tone=tx_tone|j;
/*	tx_tone=tx_tone^0x3fff;	*/

	if ((tx_tone&0x8000)==0) {
		tx_code_type=0; /* PL Tone */
		tx_tone=tx_tone&0x7fff;
	}
	else {
		tx_code_type=1; /* DPL Code */
		buff_i=tx_tone&0x0380;
		buff_i=buff_i<<1;
		buff_i=buff_i|(tx_tone&0x0070);
		buff_i=buff_i|((tx_tone&0x000e)>>1);
		sprintf(tx_code,"%03X",buff_i);
	}

	if ((rx_tone&0x8000)==0) {
		rx_code_type=0; /* PL Tone */
		rx_tone=rx_tone&0x3fff;
	}
	else {
		rx_code_type=1; /* DPL Code */
		buff_i=rx_tone&0x0380;
		buff_i=buff_i<<1;
		buff_i=buff_i|(rx_tone&0x0070);
		buff_i=buff_i|((rx_tone&0x000e)>>1);
		sprintf(rx_code,"%03X",buff_i);
	}

	/* Repeater Control  */
	rpt_control=eprom[address+16];

	/* Receiver Control  */
	rx_gate=eprom[address+6];
	rx_gate=rx_gate>>4;
	rx_gate=rx_gate&0x05;	/* Some unknown bits here !  */

	/* print the channel data  */

	freq=((64*tx_div_a+63*tx_div_b)*3+tx_div_c)*tx_ref;
	printf("TX Freq: %3.4f MHz",(double)freq/1000000);

	freq=((64*rx_div_a+63*rx_div_b)*3+rx_div_c)*rx_ref+10700000;
	printf("\t\tRX Freq: %3.4f MHz\n",(double)freq/1000000);

	if (tx_code_type==0)
		printf("TX Tone: %3.1f    Hz\t\t",(double)tx_tone*.04926);
	else
		printf("TX  DPL: %s\t\t\t",tx_code);
	if (rx_code_type==0)
		printf("RX Tone: %3.1f	  Hz\n",(double)rx_tone*.01642);
	else
		printf("RX  DPL: %s\n",rx_code);

	printf("TX  Ref:   %1.3f  KHz\t\tRX  Ref:   %1.3f  KHz\n",(double)tx_ref/1000,(double)rx_ref/1000);

	freq=((64*idle_div_a+63*idle_div_b)*3+idle_div_c)*idle_ref;
	printf("Idle   : %3.4f MHz\t\t",(double)freq/1000000);
	switch (rx_gate) {
		case 1: strcpy(buffer,"Squelch"); break;
		case 4: strcpy(buffer,"Code"); break;
		case 5: strcpy(buffer,"Sql + Code"); break;
		default:sprintf(buffer,"Unknown %d",rx_gate);
	}
	printf("RX control: %s\n",buffer);

	printf("Local PTT TOT: %3d\t\tWireline PTT TOT : %3d\n",local_tot,line_tot);
	printf("Repeater TOT : %3d\t\tRepeater Hangtime: %3d\n",rpt_tot,tail);

	j=rpt_control&0x0f;
	switch (j) {
		case 5: printf("Repeater key : Sql + Code\t"); break;
		case 1: printf("Repeater key : Squelch\t"); break;
		case 4: printf("Repeater key : Code\t\t");break;
	}

	/* ID Control goes here	*/
	j=eprom[address+17];
	j&=0xe0;
	j>>=5;
	printf("CW ID is ");
	switch (j) {
		case 0: printf("Disabled\n"); break;
		case 4: printf("Enabled\n"); break;
		case 5: printf("Enabled with PL\n"); break;
		default: printf("\n");
	}

	j=rpt_control&0xf0;
	j=j>>4;
	switch (j) {
		case 5: printf("Repeater hold: Sql + Code\t"); break;
		case 1: printf("Repeater hold: Squelch\t"); break;
		case 4: printf("Repeater hold: Code\t\t");break;
	}

	/* Call Sign goes here	*/
	read_callsign(callsign,channel-1);
	printf("Call Sign: %s\n",callsign);

	printf("RPT TX priority is %d\tLocal TX Priority is %d\tWireline TX Priority is %d\n",
						rpt_priority,local_priority,line_priority);

	j=eprom[address+17];
	j&=0x02;
	j>>=1;
	printf("Alarms on Wireline is ");
	if (color==1) {
		if (j) printf("\033[1;31mDisabled\033[0m");
		else printf("\033[1;32mEnabled\033[0m");
	}
	else {
		if (j) printf("Disabled");
		else printf("Enabled");
	}
	printf("\n");
	return;
}

void clear_kb() {	/*Clear keyboard buffer	*/
	int x=1;
	while (x) {
		x=fgetc(stdin);
		if (x=='\n') break;
	}
}

void edit_channel()
	{
	unsigned char c;
	int i,j;
	unsigned int ch_addr;
	char choice[10];
/*	unsigned int new_freq;	*/
	extern unsigned int data_addr,chan_size;
	extern char color;
	extern unsigned char eprom[],version;
	char * temp_ptr;

	ch_addr=data_addr;
	j=1;
	if(eprom[0x08]!=2) {
		printf("Which channel to modify? --> ");
		j=int_input();
/*		printf("\nChannel to edit is %d\n",j);	*/
		if (j>eprom[0x08]) {
			if (color)
				printf("\033[0;31m");
			printf("\n*** Invalid channel ***\n");
			if (color)
				printf("\033[0m");
			return;
		}
	}	
/*	if (version==3) ch_addr=23*(j-1)+data_addr;
	else ch_addr=24*(j-1)+data_addr;
*/
	ch_addr=chan_size*(j-1)+data_addr;	
	
/*	printf("\nCurrent configuration of Channel %d\n",j);
	if (j==eprom[0x08])
		printf("\t*** Tune Channel ***\n");
	display_channel(j);
*/
	i=32;	
	while((i!=88)&&(i!=120)) {
		printf("\n\tCurrent configuration of Channel %d\n\n",j);
		if (j==eprom[0x08])
		printf("\t\t*** Tune Channel ***\n\n");
		display_channel(j);
		printf("\n(T) TX Frequency\t(R) RX Frequency\n");
		printf("(E) Encode tone/code\t(D) Decode tone/code\n");
		printf("(I) Idle Frequency\t(S) Squelch settings\n");
		printf("(M) Timers\t\t(P) PTT Priorities\n");
		printf("(A) Alarms\n");
		printf("(X) Exit to main menu\n");
		printf("\nWhich field to modify? --> ");

                temp_ptr=fgets(choice,3,stdin);
                if (temp_ptr==NULL) {
                        printf("\nUnknown error/n/n");
                        continue;
                }
                i=strlen(choice);
                if (choice[i-1]!='\n') { /* clear keyboard buffer */
                        i=0;
                        while (i!='\n')
                                i=getchar();
                }
                printf("\n");
                i=choice[0];

		if ((i==84)||(i==116)) {  /* T	*/
			edit_txf(ch_addr);
			continue;
		}
		if ((i==82)||(i==114)) {  /* R	*/
			edit_rxf(ch_addr);
			continue;
		}
		if ((i==69)||(i==101)) {  /* E	*/
			edit_enc(ch_addr);
			continue;
		}
		if ((i==68)||(i==100)) {  /* D	*/
			edit_dec(ch_addr);
			continue;
		}
		if ((i==73)||(i==105)) {  /* I	*/
			edit_idle(ch_addr);
			continue;
		}
		if ((i==83)||(i==115)) {  /* S	*/
			edit_squelch(ch_addr);
			continue;
		}
		if ((i==77)||(i==109)) {  /* M	*/
			edit_timers(ch_addr);
			continue;
		}
		if ((i==80)||(i==112)) {  /* P	*/
			edit_ptt_priority(ch_addr);
			continue;
		}
		if ((i==65)||(i==97)) {	/* A	*/
			edit_alarms(ch_addr);
			continue;
		}
	}
	return;
}

void edit_txf(unsigned int address)
	{
	unsigned int freq,total_div,ref,i,j;
	struct pll_data tx_div;
	extern unsigned char eprom[];

	printf("\nEdit TX Frequency info at address %X\n\n",address);
	printf("Enter the new Transmit Frequency in Hz--> ");
	scanf("%d",&freq);
	clear_kb();
	if (freq>max_tx)
		max_tx=freq;
	if (freq<min_tx)
		min_tx=freq;
	printf("\nCalculating for %3.5f MHz\n",(double)freq/1000000);
	/* Figure Reference	*/
	if (freq%6250==0)
		{
		printf("6.25 KHz works for reference\n");
		ref=6250;
		eprom[address+5]&=0xfc;
		eprom[address+5]|=0x01;
	}
	else if	(freq%5000==0){
		ref=5000;
		eprom[address+5]&=0xfc;
		eprom[address+5]|=0x03;
		printf("Using 5.00 KHz for reference\n");
	}
	else 	{
		if (color)
			printf("\033[41m");
		printf("Frequency does not work!\n");
		if (color)
			printf("\033[0m");
		return;
		}
	
	total_div=freq/ref;
	printf("total divider is %d\n",total_div);
	tx_div.c=total_div%3;
/* *** Do we want to use 3 instead of 0?  *** */
	printf("div c: %d\n",tx_div.c);
	j=(total_div-tx_div.c)/3;
	printf("div 64a and 63b must add to %d\n",j);
	for (i=1;i<64;i++)
		{
		if((j-(64*i))%63==0)
			{
			tx_div.a=i;
			break;
			}
		}
	tx_div.b=(j-(64*i))/63;
	printf("a=%d\tb=%d\n",tx_div.a,tx_div.b);

	eprom[address+5]&=0xcf;

	switch (tx_div.c) {
		case 3: eprom[address+5]|=0x20; break;
		case 1:	eprom[address+5]|=0x10;break;
		case 2: eprom[address+5]|=0x30;break;
		case 0: eprom[address+5]|=0x00;break;
	}

	eprom[address+4]=0;
	eprom[address+4]|=tx_div.b<<2;
	eprom[address+4]&=0xf0;
	i=tx_div.b>>6;
	i&=0x0f;
	eprom[address+4]|=i;

	eprom[address+3]=0;
	eprom[address+3]|=tx_div.b<<2;
	eprom[address+3]&=0x0c;
	eprom[address+3]|=tx_div.a<<4;
	i=tx_div.a>>4;
	i&=0x0003;
	eprom[address+3]|=i;
	eprom[address+3]^=0x14;

	/* Change Tune freq	*/
	channel_summary();
	edit_tune_tx();

	return;
	}


void edit_rxf(unsigned int address)
	{
	unsigned int freq,total_div,ref,i,j;
	struct pll_data rx_div;
	extern unsigned char eprom[];
	extern unsigned int max_rx,min_rx;

	printf("\nEdit RX Frequency info at address %X\n\n",address);
	printf("Enter the new Receive Frequency in Hz--> ");
	scanf("%d",&freq);
	clear_kb();
	if (freq>max_rx)
		max_rx=freq;
	if (freq<min_rx)
		min_rx=freq;
	freq-=10700000;
	printf("\nCalculating for %3.5f MHz\n",(double)freq/1000000);

	/* Figure Reference	*/
	i=freq%6250;
	if (i==0)
		{
		printf("6.25 KHz works for reference\n");
		ref=6250;
		eprom[address+2]&=0xfc;
		eprom[address+2]|=0x01;
	}
	else if	(freq%5000==0){
		ref=5000;
		eprom[address+2]&=0xfc;
		eprom[address+2]|=0x03;
		printf("Using 5.00 KHz for reference\n");
	}
	else 	{
		if (color)
			printf("\033[41m");
		printf("Frequency does not work!\n");
		if (color)
			printf("\033[0m");
		return;
	}
	total_div=freq/ref;
	printf("total divider is %d\n",total_div);
	rx_div.c=total_div%3;
/* *** Do we want to use 3 instead of 0?  *** */
	printf("div c: %d\n",rx_div.c);
	j=(total_div-rx_div.c)/3;
	printf("div 64a and 63b must add to %d\n",j);
	for (i=1;i<64;i++)
		{
		if((j-(64*i))%63==0)
			{
			rx_div.a=i;
			break;
			}
		}
	rx_div.b=(j-(64*i))/63;
	printf("a=%d\tb=%d\n",rx_div.a,rx_div.b);


	eprom[address+2]&=0xcf;

	switch (rx_div.c) {
		case 3: eprom[address+2]|=0x20; break;
		case 1:	eprom[address+2]|=0x10;break;
		case 2: eprom[address+2]|=0x30;break;
		case 0: eprom[address+2]|=0x00;break;
	}	

	eprom[address+1]=0;
	eprom[address+1]|=rx_div.b<<2;
	eprom[address+1]&=0xf0;
	i=rx_div.b>>6;
	i&=0x0f;
	eprom[address+1]|=i;

	eprom[address]=0;
	eprom[address]|=rx_div.b<<2;
	eprom[address]&=0x0c;
	eprom[address]|=rx_div.a<<4;
	i=rx_div.a>>4;
	i&=0x0003;
	eprom[address]|=i;
	eprom[address]^=0x14;

	/* Change Tune RX	*/
	channel_summary();
	edit_tune_rx();
	return;
	}

void edit_idle(unsigned int address)
	{
	unsigned int freq,a,b,c,total_div,ref,i,j;
	struct pll_data tx_div;
	extern unsigned char eprom[];

	printf("\nEdit TX VCO Idle Frequency info at address %X\n\n",address);
	printf("Enter the new Idle Frequency in Hz--> ");
	scanf("%d",&freq);
	clear_kb();
	printf("\nCalculating for %3.5f MHz\n",(double)freq/1000000);
	/* Figure Reference	*/
	if (freq%6250==0)
		{
		printf("6.25 KHz works for reference\n");
		ref=6250;
		eprom[address+21]&=0xfc;
		eprom[address+21]|=0x01;
	}
	else if	(freq%5000==0){
		ref=5000;
		eprom[address+21]&=0xfc;
		eprom[address+21]|=0x03;
		printf("Using 5.00 KHz for reference\n");
	}
	else 	{
		if (color)
			printf("\033[41m");
		printf("Frequency does not work!\n");
		if (color)
			printf("\033[0m");
		return;
		}
	
	total_div=freq/ref;
	printf("total divider is %d\n",total_div);
	c=total_div%3;
	printf("div c: %d\n",c);
	j=(total_div-c)/3;
	printf("div 64a and 63b must add to %d\n",j);
	for (i=1;i<64;i++)
		{
		if((j-(64*i))%63==0)
			{
			a=i;
			break;
			}
		}
	b=(j-(64*i))/63;
	printf("a=%d\tb=%d\n",a,b);

	eprom[address+21]&=0xcf;

	switch (c) {
		case 3: eprom[address+21]|=0x20; break;
		case 1:	eprom[address+21]|=0x10;break;
		case 2: eprom[address+21]|=0x30;break;
		case 0: eprom[address+21]|=0x00;break;
	}

	eprom[address+20]=0;
	eprom[address+20]|=b<<2;
	eprom[address+20]&=0xf0;
	i=b>>6;
	i&=0x0f;
	eprom[address+20]|=i;

	eprom[address+19]=0;
	eprom[address+19]|=b<<2;
	eprom[address+19]&=0x0c;
	eprom[address+19]|=a<<4;
	i=a>>4;
	i&=0x0003;
	eprom[address+19]|=i;
	eprom[address+19]^=0x14;

	return;
}

void edit_tune_tx()
	{
	unsigned int address,freq,total_div,ref,i,j;
	struct pll_data tx_div;
	extern unsigned char eprom[];
	extern unsigned int center_tx;
	address=data_addr+(23*num_channels)-23;
	printf("\nEdit Tune TX Frequency info at address %X\n\n",address);
	freq=center_tx;
	printf("\nCalculating for %3.5f MHz\n",(double)freq/1000000);
	/* Figure Reference	*/
	if (freq%6250==0)
		{
		printf("6.25 KHz works for reference\n");
		ref=6250;
		eprom[address+5]&=0xfc;
		eprom[address+5]|=0x01;
	}
	else if	(freq%5000==0){
		ref=5000;
		eprom[address+5]&=0xfc;
		eprom[address+5]|=0x03;
		printf("Using 5.00 KHz for reference\n");
	}
	else 	{
		if (color)
			printf("\033[41m");
		printf("Frequency does not work!\n");
		if (color)
			printf("\033[0m");
		return;
		}
	
	total_div=freq/ref;
	printf("total divider is %d\n",total_div);
	tx_div.c=total_div%3;
/* *** Do we want to use 3 instead of 0?  *** */
	printf("div c: %d\n",tx_div.c);
	j=(total_div-tx_div.c)/3;
	printf("div 64a and 63b must add to %d\n",j);
	for (i=1;i<64;i++)
		{
		if((j-(64*i))%63==0)
			{
			tx_div.a=i;
			break;
			}
		}
	tx_div.b=(j-(64*i))/63;
	printf("a=%d\tb=%d\n",tx_div.a,tx_div.b);

	eprom[address+5]&=0xcf;

	switch (tx_div.c) {
		case 3: eprom[address+5]|=0x20; break;
		case 1:	eprom[address+5]|=0x10;break;
		case 2: eprom[address+5]|=0x30;break;
		case 0: eprom[address+5]|=0x00;break;
	}

	eprom[address+4]=0;
	eprom[address+4]|=tx_div.b<<2;
	eprom[address+4]&=0xf0;
	i=tx_div.b>>6;
	i&=0x0f;
	eprom[address+4]|=i;

	eprom[address+3]=0;
	eprom[address+3]|=tx_div.b<<2;
	eprom[address+3]&=0x0c;
	eprom[address+3]|=tx_div.a<<4;
	i=tx_div.a>>4;
	i&=0x0003;
	eprom[address+3]|=i;
	eprom[address+3]^=0x14;

	return;
	}

void edit_tune_rx()
	{
	unsigned int address,freq,total_div,ref,i,j;
	struct pll_data rx_div;
	extern unsigned char eprom[];
	extern unsigned int center_rx;

	printf("\nEdit Tune RX Frequency info at address %X\n\n",address);
	address=data_addr+(23*num_channels)-23;
	freq=center_rx-10700000;
	printf("\nCalculating for %3.5f MHz\n",(double)freq/1000000);

	/* Figure Reference	*/
	i=freq%6250;
	if (i==0)
		{
		printf("6.25 KHz works for reference\n");
		ref=6250;
		eprom[address+2]&=0xfc;
		eprom[address+2]|=0x01;
	}
	else if	(freq%5000==0){
		ref=5000;
		eprom[address+2]&=0xfc;
		eprom[address+2]|=0x03;
		printf("Using 5.00 KHz for reference\n");
	}
	else 	{
		if (color)
			printf("\033[41m");
		printf("Frequency does not work!\n");
		if (color)
			printf("\033[0m");
		return;
	}
	total_div=freq/ref;
	printf("total divider is %d\n",total_div);
	rx_div.c=total_div%3;
/* *** Do we want to use 3 instead of 0?  *** */
	printf("div c: %d\n",rx_div.c);
	j=(total_div-rx_div.c)/3;
	printf("div 64a and 63b must add to %d\n",j);
	for (i=1;i<64;i++)
		{
		if((j-(64*i))%63==0)
			{
			rx_div.a=i;
			break;
			}
		}
	rx_div.b=(j-(64*i))/63;
	printf("a=%d\tb=%d\n",rx_div.a,rx_div.b);


	eprom[address+2]&=0xcf;

	switch (rx_div.c) {
		case 3: eprom[address+2]|=0x20; break;
		case 1:	eprom[address+2]|=0x10;break;
		case 2: eprom[address+2]|=0x30;break;
		case 0: eprom[address+2]|=0x00;break;
	}	

	eprom[address+1]=0;
	eprom[address+1]|=rx_div.b<<2;
	eprom[address+1]&=0xf0;
	i=rx_div.b>>6;
	i&=0x0f;
	eprom[address+1]|=i;

	eprom[address]=0;
	eprom[address]|=rx_div.b<<2;
	eprom[address]&=0x0c;
	eprom[address]|=rx_div.a<<4;
	i=rx_div.a>>4;
	i&=0x0003;
	eprom[address]|=i;
	eprom[address]^=0x14;
	return;
	}

void edit_enc(unsigned int address) {
	int i,j,tone,code_type=15;
	char entry[15];
	char temp[127];
	int new_tone;
	char * success;
	extern unsigned char eprom[];

	show_tones();
	printf("\nEdit TX code info at address %X\n\n",address);
	printf("Enter CTCSS frequency or Digital code -> ");

        success=fgets(entry,8,stdin);
        if (success==NULL) {
                printf("\nUnknown Error\n");
                return;
        }
        i=sscanf(entry,"%d%s",&tone,temp);
        if (i==1) { /* DPL */
		if (tone==0)
			code_type=0;
		else
			code_type=2;
        }
        if (i==2) {
		code_type=1;
        	if (strncmp(temp,".",1)==0) {
                	tone*=10;
			strcpy(entry,temp+1);
			entry[1]='\0';
                	j=atoi(entry);
			tone+=j;
		}
        }
	if (code_type>2)
		return;
	switch (code_type) {
		case 0: /* Carrier */
			printf("No transmit code (carrier)\n");
			eprom[address+15]&=0x3f;
			break;
		case 1: /* CTCSS */
			printf("CTCSS transmit tone (PL) %.1f\n",(float)tone/10);
			new_tone=(double)tone/.4926;
			printf("PL data bytes: %4x\n",new_tone);
			eprom[address+12]=new_tone&0xff;
			new_tone>>=8;
			eprom[address+11]=new_tone&0x3f;
			eprom[address+5]|=0x40;
			eprom[address+15]&=0x38;
			eprom[address+15]|=0x85;
			break;
		case 2: /* DPL */
			printf("Digital Squelch code (DPL)\n");
			printf("Function not written yet\n");
			break;
		default: break;
	}

	return;
}

void edit_dec(unsigned int address) {
	int i,j,tone,code_type=15;
	char entry[15];
	char temp[127];
	int new_tone;
	char * success;
	extern unsigned char eprom[];

	show_tones();
	printf("\nEdit RX code info at address %X\n\n",address);
	printf("Enter CTCSS frequency or Digital code -> ");

        success=fgets(entry,8,stdin);
        if (success==NULL) {
                printf("\nUnknown Error\n");
                return;
        }
        i=sscanf(entry,"%d%s",&tone,temp);
        if (i==1) { /* DPL */
		if (tone==0)
			code_type=0;
		else
			code_type=2;
        }
        if (i==2) {
		code_type=1;
        	if (strncmp(temp,".",1)==0) {
                	tone*=10;
			strcpy(entry,temp+1);
			entry[1]='\0';
                	j=atoi(entry);
			tone+=j;
		}
        }
	if (code_type>2)
		return;
	switch (code_type) {
		case 0: /* Carrier */
			printf("No receive code (carrier)\n");
			eprom[address+6]=0x90;
			eprom[address+15]&=0xcf;
			break;
		case 1: /* CTCSS */
			printf("CTCSS receive tone (PL) %.1f\n",(float)tone/10);
			new_tone=(double)tone/.1642;
			printf("PL data bytes: %4x\n",new_tone);
			eprom[address+14]=new_tone&0xff;
			new_tone>>=8;
			eprom[address+13]=new_tone&0x3f;
			eprom[address+15]&=0xc5;
			eprom[address+15]|=0x25;
			break;
		case 2: /* DPL */
			printf("Digital Squelch code (DPL)\n");
			printf("Function not written yet\n");
			break;
		default: break;
	}

	return;
}

void edit_squelch(unsigned int address) {
	char status[2][5]={{" No "},{" Yes"}};
	int r,k,h,code,noise,aux;
	extern unsigned char eprom[];

	code=eprom[address+6]&0x40;
	code>>=6;
	noise=eprom[address+6]&0x10;
	noise>>=4;
	aux=eprom[address+6]&0x20;
	aux>>=5;
	printf("Control gates are ANDed together\n");
	printf("\t\tCurrently ___________________\n");
	printf("\t\t\tCode\tAux\tCarrier\n");
	printf("Receiver Squelch\t%s\t%s\t%s\n",status[code],status[aux],status[noise]);
	code=eprom[address+16]&0x04;
	code>>=2;
	noise=eprom[address+16]&0x01;
	aux=eprom[address+16]&0x02;
	aux>>=1;
	printf("Repeater Key\t\t%s\t%s\t%s\n",status[code],status[aux],status[noise]);
	code=eprom[address+16]&0x40;
	code>>=6;
	noise=eprom[address+16]&0x10;
	noise>>=4;
	aux=eprom[address+16]&0x20;
	aux>>=1;
	printf("Repeater Hold\t\t%s\t%s\t%s\n",status[code],status[aux],status[noise]);

	printf("\nSelect new options: 3=Both 2=Code 1=Carrier 0=Disable\n");
	printf("\nEnter Receiver control -> ");
	r=int_input();
	printf("Enter Repeater Key control -> ");
	k=int_input();
	if(k!=0) {
		printf("Enter Repeater Hold control -> ");
		h=int_input();
	}

	switch (r) {
		case 0: eprom[address+6]=0x80; break;
		case 1: eprom[address+6]=0x90; break;
		case 2: eprom[address+6]=0xc0; break;
		case 3: eprom[address+6]=0xd0; break;
		default: break;
	}
	switch (k) {
		case 0: eprom[address+16]=0x00; break;
		case 1: eprom[address+16]&=0xf0; eprom[address+16]|=0x01; break;
		case 2: eprom[address+16]&=0xf0; eprom[address+16]|=0x04; break;
		case 3: eprom[address+16]&=0xf0; eprom[address+16]|=0x05; break;
		default: break;
	}
	if (k!=0)
		switch (h) {
			case 0: eprom[address+16]&=0x0f; break;
			case 1: eprom[address+16]&=0x0f; eprom[address+16]|=0x10; break;
			case 2: eprom[address+16]&=0x0f; eprom[address+16]|=0x40; break;
			case 3: eprom[address+16]&=0x0f; eprom[address+16]|=0x50; break;
			default: break;
		}
	return;
}
void show_tones() {
	extern char tone[42][6];
	extern char color;
	int i;
	extern unsigned char eprom[];
	printf("\tMSF5000 PL tone chart\n");
	printf("%s\t",tone[0]);
	if (color==1)
		printf("\033[1;31m");
	printf("%s\t",tone[1]);
	if (color==1)
		printf("\033[0m");
	printf("%s\t%s\t%s\t%s\n",tone[2],tone[3],tone[4],tone[5]);
	printf("%s\t%s\t%s\t%s\t%s\t",tone[6],tone[7],tone[8],tone[9],tone[10]);
	if (color==1)
		printf("\033[1;31m");
	printf("%s\n",tone[11]);
	if (color==1)
		printf("\033[0m");
        for (i=12;i<25;i+=6)
		printf("%s\t%s\t%s\t%s\t%s\t%s\n",tone[i],tone[i+1],tone[i+2],tone[i+3],tone[i+4],tone[i+5]);
	printf("%s\t%s\t",tone[30],tone[31]);
	if (color==1)
		printf("\033[1;31m");
	printf("%s\t",tone[32]);
	if (color==1)
		printf("\033[0m");
	printf("%s\t%s\t%s\n",tone[33],tone[34],tone[35]);
	printf("%s\t",tone[36]);
	if (color==1)
		printf("\033[1;31m");
	printf("%s\t",tone[37]);
	if (color==1)
		printf("\033[0m");
	printf("%s\t%s\t%s\t",tone[38],tone[39],tone[40]);
	if (color==1)
		printf("\033[1;31m");
	printf("%s\n",tone[41]);
	if (color==1)
		printf("\033[0m");
	if (color==1)
		printf("\033[1;31m");
	printf("The tones in red may not be available on all radios\n");
	if (color==1)
		printf("\033[0m");
	return;
}

void edit_timers(unsigned int address) {
	unsigned char c;
	int i;
	extern unsigned char eprom[];
	c=eprom[address+8];
	c&=0x1f;
	printf("\n\n\tCurrent timer settings\n\n");
	printf("Wireline PTT\t\t");
	if (c==0)
		printf("disabled\n");
	else printf("%3d seconds\n",c*15);
	c=eprom[address+9];
	c&=0x1f;
	printf("Local PTT\t\t");
	if (c==0)
		printf("disabled\n");
	else printf("%3d seconds\n",c*15);
	c=eprom[address+10];
	c&=0x1f;
	printf("Repeater ToT\t\t");
	if (c==0)
		printf("disabled\n");
	else printf("%3d seconds\n",c*15);
	c=eprom[address+10];
	c&=0xe0;
	c>>=5;
	if (c==0)
		printf("Repeater Dropout (Tail) is disabled\n");
	else {
		printf("Repeater Dropout (Tail)\t%3d ",c);
		if (c==1)
			printf("second\n");
		else
			printf("seconds\n");
	}
	printf("\nPTT timers have a maximum of 465 seconds in 15 second steps\n");
	printf("Repeater drop out timer has a maximum of 7 seconds in 1 second steps\n");
	printf("\nEnter new Wireline ToT (0-31) -> ");
	i=int_input();
	if (i<0) {
		printf("Unchanged\n");
	}
	else {
	c=i&0x1f;
	eprom[address+8]=c;
	}
	printf("Enter new Local PTT ToT (0-31) -> ");
	i=int_input();
	if (i<0) {
		printf("Unchanged\n");
	}
	else {
	c=i&0x1f;
	eprom[address+9]=c;
	}
	printf("Enter new Repeater ToT (0-31) -> ");
	i=int_input();
	if (i<0) {
		printf("Unchanged\n");
	}
	else {
	c=i&0x1f;
	eprom[address+10]&=0xe0;
	eprom[address+10]|=c;
	}

	printf("Enter new Repeater Dropout (0-7) -> ");
	i=int_input();
	if (i<0) {
		printf("Unchanged\n");
	}
	else {
	c=i&0x07;
	c<<=5;
	eprom[address+10]&=0x1f;
	eprom[address+10]|=c;
	}

	c=eprom[address+8];
	c&=0x1f;
	printf("\n\n\tNew timer settings\n\n");
	printf("Wireline PTT\t\t");
	if (c==0)
		printf("disabled\n");
	else printf("%3d seconds",c*15);
	if (c>4)
		printf("\t%.1f minutes\n",(float)c*.25);
	else printf("\n");
	c=eprom[address+9];
	c&=0x1f;
	printf("Local PTT\t\t");
	if (c==0)
		printf("disabled\n");
	else printf("%3d seconds",c*15);
	if (c>4)
		printf("\t%.1f minutes\n",(float)c*.25);
	else printf("\n");
	c=eprom[address+10];
	c&=0x1f;
	printf("Repeater ToT\t\t");
	if (c==0)
		printf("disabled\n");
	else printf("%3d seconds",c*15);
	if (c>4)
		printf("\t%.1f minutes\n",(float)c*.25);
	else printf("\n");
	c=eprom[address+10];
	c&=0xe0;
	c>>=5;
	if (c==0)
		printf("Repeater Dropout (Tail) is disabled\n");
	else {
		printf("Repeater Dropout (Tail)\t%3d ",c);
		if (c==1)
			printf("second\n");
		else
			printf("seconds\n");
	}
	return;
}

void edit_ptt_priority(unsigned int address) {
	unsigned char c;
	int i;
	extern unsigned char eprom[];
	extern char color;
	c=eprom[address+7]&0x3f;
	printf("\nPTT priority determines which input is present at the transmitter\n");
	printf("\"1\" is the higest priority, \"0\" is disabled\n");
	printf("\n\t____ Current settings ____\n");
	printf("\t\tWireline\t%d\n",(c&0x30)>>4);
	printf("\t\tLocal\t\t%d\n",(c&0x0c)>>2);
	printf("\t\tRepeater\t%d\n\n",c&0x03);
	eprom[address+7]&=0xc0;
	printf("Enter the Priority level for the Wireline input: ");
	i=int_input();
	i=i<<4;
	i&=0x30;
	eprom[address+7]|=i;
	printf("Enter the Priority level for the Local (front panel) input: ");
	i=int_input();
	i=i<<2;
	i&=0x0c;
	eprom[address+7]|=i;
	printf("Enter the Priority level for Receiver (Repeater): ");
	i=int_input();
 	i&=0x03;
	eprom[address+7]|=i;

	if (!eprom[address+7]&0x3f){
		if (color==1)
			printf("\033[1;31m");
		printf("\n*** Warning! All transmit inputs are disabled ***\n");
		if (color==1)
			printf("\033[0m");
	}
	return;
}

void edit_alarms(unsigned int address) {
	extern unsigned char eprom[];
	extern char color;

	if (color==1)
		printf("\033[1;31m");
	printf("Various alarms are sent on the Wireline.\n");
	if (color==1)
		printf("\033[0m");

	return;
}

void existing_eprom() {
        FILE *eprom_data;
        char *temp_ptr;
        char choice[128],code_file[128];
        DIR *dir_p;
        struct dirent *dirent_p;
        int i,width=0;
	extern unsigned char eprom[];
        printf("Listing of current directory:\n");
        dir_p=opendir(".");

        while (NULL !=(dirent_p=readdir(dir_p))) {
                i=printf(" %s\t",dirent_p -> d_name);
		if (i<16) printf("\t");
		if (i<8) printf("\t");
                width++;
	       	if (width%3==0){
			printf("\n");
			if (color) printf("\033[1;30m");
		}
		if (width%6==0){
			if (color) printf("\033[0m");
		}
        }
        closedir(dir_p);
	if (color) printf("\033[0m");
        printf("\n");
	i=0;
        /* --------------------------------------------------------------*/
        codeplug:
        printf("\nEnter file to read -->  ");
        temp_ptr=fgets(choice,125,stdin);
        if (temp_ptr==NULL) {
                printf("Unknown error/n/n");
                goto codeplug;
        }
        i=strlen(choice);
        if (choice[i-1]!='\n') { /* clear keyboard buffer */
                i=0;
                while (i!='\n')
                        i=getchar();
        }
        sscanf(choice,"%s",code_file);
        printf("\nOpening %s\t",code_file);
        eprom_data = fopen (code_file,"rb");
        if (!eprom_data) {
                printf("Error opening %s!\n",code_file);
                goto codeplug;
        }
        fread(eprom,4096,1,eprom_data);
        fclose(eprom_data);
        printf("%s read into buffer\n",code_file);
}

void write_plug()
	{
	char plug_name[255];
	unsigned int i,j=0;
	unsigned int temp,last_word,checksum=0;
	FILE *plug;
	extern unsigned char eprom[];
	extern unsigned int chan_size;
	/* Calculate checksum	*/
printf("Number of channels is %d\n",num_channels);
/*	if (version==3)
		last_word=num_channels*23+data_addr;
	else
		last_word=num_channels*24+data_addr;
*/
	last_word=num_channels*chan_size+data_addr;
	last_word-=1;
	last_word &= 0x0ffe;
	last_word|=0x2000;
	printf("Last Word is at address 0x%4X\n",last_word);
	eprom[0x03]=last_word&0x00ff;
	eprom[0x02]=last_word>>8;
/* some code plugs have an extra set of bytes set to 00 00	*/
/* don't know why yet	*/
	for (i=2;i<(last_word-0x2000)+1;i+=2) {
		temp=eprom[i]<<8;
		temp+=eprom[i+1];
		checksum+=temp;
		checksum&=0xffff;
	}
	checksum&=0xffff;
	printf("Checksum is 0x%4X\n",checksum);
	eprom[0x01]=checksum&0x00ff;
	eprom[0x00]=checksum>>8;

	printf("Enter the name of code plug file (existing file will be replaced) --> ");
	fgets(plug_name,255,stdin);
	do
		{
		i=plug_name[j];
		j++;
	} while (i>44);
	plug_name[j-1]=0;

	printf("\nWriting buffer to %s\n",plug_name);
	plug = fopen ( plug_name,"wb");
	if (!plug)
		{
		if (color)
			printf("\033[1;31m");
		printf("Error opening %s\n",plug_name);
		if (color)
			printf("\033[0m");
		return;
		}
	fwrite(eprom,4096,1,plug);
	fclose(plug);
	return;
}

int checksum_verify() {
	int i;
	unsigned int checksum=0,temp,last_byte;
	extern unsigned char eprom[];
	extern char color; 
	last_byte=eprom[0x02]<<8;
	last_byte+=eprom[0x03];
printf("Last byte is %X\t\t",last_byte);
	for (i=2;i<(last_byte-0x2000)+1;i+=2) {
		temp=eprom[i]<<8;
		temp+=eprom[i+1];
		checksum+=temp;
		checksum&=0xffff;
	}
printf("Checksum is %X\n",checksum);
	temp=eprom[0]<<8;
	temp+=eprom[1];
	if (temp==checksum) {
		if (color) printf("\033[1;32m");
		printf("Checksum Good\n");
		if (color) printf("\033[0m");
		return(0);
	}
	else {
	if (color) printf("\033[1;31m");
	printf("Checksum FAILED!\n");
	if (color) printf("\033[0m");
	return(1);
	}
}

void read_callsign(char *call, int channel) {

	/* Calculate callsign	*/
	extern unsigned int cw_addr;
	extern unsigned char eprom[];
	extern unsigned int num_channels;
	unsigned int i,j,k,letter;
	char buffer[64];
	call[0]='\0';
/*	if ((num_channels-1)==channel) return;*/
	cw_addr=eprom[0x11];
	cw_addr<<=8;
	cw_addr&=0x0fff;
	cw_addr+=eprom[0x12];
	cw_addr+=(21*channel);
	j=0; k=0; letter=0;

	for (i=0;i<22;i++) {
		j=eprom[cw_addr+i];
		if (j==0) {
			if (letter!=0){
				for (k=0;k<60;k++) {
					if (letter==morse[k]) {
						sprintf(buffer,"%c",k+32);
						strcat(call,buffer);
						break;
					}
				}
				letter=0;
			}
			break;
		}

		k=j>>6;
		if (k==1 | k==2) {
			letter <<=2;
			letter|=k;
		}
		if (k==0 | k==3) { /* End of character	*/
			for (k=0;k<60;k++) {
				if (letter==morse[k]) {
					sprintf(buffer,"%c",k+32);
					strcat(call,buffer);
					break;
				}
			}
			letter=0;
		}
		k=j>>4;
		k&=0x03;
		if (k==1 | k==2) {
			letter <<=2;
			letter|=k;
		}
		if (k==0 | k==3) { /* End of character	*/
			for (k=0;k<60;k++) {
				if (letter==morse[k]) {
					sprintf(buffer,"%c",k+32);
					strcat(call,buffer);
					break;
				}
			}
			letter=0;
		}
		k=j>>2;
		k&=0x03;
		if (k==1 | k==2) {
			letter <<=2;
			letter|=k;
		}
		if (k==0 | k==3) { /* End of character	*/
			for (k=0;k<60;k++) {
				if (letter==morse[k]) {
					sprintf(buffer,"%c",k+32);
					strcat(call,buffer);
					break;
				}
			}
			letter=0;
		}
		k=j&0x03;
		if (k==1 | k==2) {
			letter <<=2;
			letter|=k;
		}
		if (k==0 | k==3) { /* End of character	*/
			for (k=0;k<60;k++) {
				if (letter==morse[k]) {
					sprintf(buffer,"%c",k+32);
					strcat(call,buffer);
					break;
				}
			}
			letter=0;
		}	
	}
	return;
}

/* Linux integer sizes larger than DOS	*/
/* These are scaled to smaller integer sizes	*/
int int_input(void) {
	char * temp_ptr;
	char temp_buf[8], choice[8];
	int i,result;
	get_input:
	temp_ptr=fgets(choice,7,stdin);
	if (temp_ptr==NULL) {
		printf("error, try again: ");
		goto get_input;
	}
	i=strlen(choice);
	if (choice[i-1]!='\n') { /* clear buffer */
		i=0;
		while (i!='\n')
			i=getchar();
	}
	i=sscanf(choice,"%d%s",&result,temp_buf);
	if (i<1) {
		printf("error -> ");
		goto get_input;
	}
	return (result);
}


