/* Program to read and edit binary eprom file for Motorola Syntor X
Read functions working 3-11-2004    Jerry Dries - N7HYV */
/* Write functions working and code changed for DOS 6.X compatibility 3-29-2004 */
/* DPL read function added 7-7-2004 */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

unsigned int mode=33,c,i,l,tx_div_b,rx_div_b;

unsigned char choice[1],channel[32][16];
unsigned int tx_div_a,rx_div_a;
unsigned long int rx_ref,tx_ref;
unsigned int j,k,band,pwr,tx_pl,rx_pl,tx_tot;
unsigned int extender,tx_div_c,rx_div_c,rx_divisor,tx_divisor;
unsigned long int rx_lo,rx_vco,tx_vco;
float rx_freq,tx_freq,frequency,rx_pl_freq,tx_pl_freq;
FILE *plug;
ldiv_t dummy;

void show_pl(void);
void show_dpl(unsigned int dpl);
int main()
{
/*
unsigned int mode=33,c,i,l,tx_div_b,rx_div_b;
unsigned int tx_div_a,rx_div_a;
unsigned long int rx_ref,tx_ref;
unsigned int j,k,band,tx_pl,rx_pl,tx_tot;
unsigned int extender,pwr,tx_div_c,rx_div_c,rx_divisor,tx_divisor;
unsigned long int rx_lo,rx_vco,tx_vco;
*/
/*
float rx_freq,tx_freq,frequency,rx_pl_freq,tx_pl_freq;
FILE *plug;
ldiv_t dummy;
*/
void display_channels(unsigned int band);
void edit_channel(unsigned int band,unsigned int mode);

printf("\v\v\tSyntor Programming\n");
printf("\v\tDE: N7HYV\n\n");
printf("Version 2.1-alpha July 7th, 2004\n\n");

plug = fopen ( "syntor.bin","rb");
fread(channel,512,1,plug);
fclose(plug);

printf("Select the band of this Syntor X\n\n");
printf("1 - Low band (29-50 MHz)\n");
printf("2 - High band (136-174 MHz)\n");
printf("\n\t? ");
scanf("%d",&band);

if (band==1)
	{
	printf("\nYou selected a Low-Band radio.\n\n");
	printf("29.7-67.5\n\n");
	rx_lo=75700000;
	}
else
	{
	printf("\nYou selected a High-Band radio.\n");
	rx_lo=53900000;
	}


while (mode>32)
        {
display_channels(band);
        printf("\nWhich channel to edit (Enter 0 to exit) ? ");
        scanf("%d",&mode);
	if (mode) 
	edit_channel(band,mode);
	if (!mode) break;
	mode=33;
	}

plug = fopen ( "syntor.bin","wb");
fwrite(channel,512,1,plug);
fclose(plug);

printf("The following was written to syntor.bin\n\n");

display_channels(band);

return 0;
} /* End of main() */

edit_channel(band,mode)
{
i=mode-1;

printf("\nEnter new Receive frequency: ");
scanf("%f",&rx_freq);

printf("Enter new Transmit frequency: ");
scanf("%f",&tx_freq);

show_pl();

printf("Enter new RX PL frequency: ");
scanf("%f",&rx_pl_freq);
/* Max RX PL Freq is 267.8 Hz */
rx_pl=(rx_pl_freq*61.1700);
rx_pl=rx_pl^0x3fff;
rx_pl=rx_pl|0x8000;

printf("Enter new TX PL frequency: ");
scanf("%f",&tx_pl_freq); printf("\n");
/* Max TX PL freq is 907 Hz */
tx_pl=(tx_pl_freq*18.0616);
tx_pl=tx_pl^0x3fff;
tx_pl=tx_pl|0x8000;

printf("tx_pl=%X rx_pl=%X\n ",tx_pl,rx_pl);
/* TOT values are in 15 second steps. 11111 is infinite, 00000 is 7 mins 45 secs */

printf("To disable the TOT, enter 0\n");
printf("TOT values step in 15 second intervals to a maximun of 465 seconds.\n");
printf("Enter the Time Out Time in seconds: ");
scanf("%d",&j); printf("\n");
dummy=ldiv(j,15);
if (dummy.rem)
	printf("Improper value. Rounded to %d seconds.\n",15*dummy.quot);
tx_tot=dummy.quot;
tx_tot=tx_tot^0x1f;
printf("TOT value is %X \n",tx_tot);

/*
printf("Enter transmit power (1=High, 0=Low) :");
scanf("%d",&pwr); printf("\n");
*/
pwr=1; /* pwr bit seems to be non functional */

/* scan list*/
	channel[i][0]=0xff;
	channel[i][1]=0xff;
	channel[i][2]=0x00;
	channel[i][3]=0x00;

/* PL */
	channel[i][4]=0x00;
	channel[i][5]=0x00;
	channel[i][6]=0x00;
	channel[i][7]=0x00;
/* add calculated PL values */
	if (tx_pl==0xbfff)
		{
		channel[i][4]=0x00;
		channel[i][5]=0xc0;
		}
	else
	{
	j=tx_pl&0x00ff;
	channel[i][4]=j;
	j=tx_pl>>8;
	channel[i][5]=j;
	}

	if (rx_pl==0xbfff)
		{
		channel[i][6]=0x00;
		channel[i][7]=0xc0;
		}
	else
		{
		j=rx_pl&0x00ff;
		channel[i][6]=j;
		j=rx_pl>>8;
		channel[i][7]=j;
		}

/* TOT, Power, Reference */
	channel[i][8]=0x00;

/* Scan control, Squelch */
	channel[i][9]=0x81;
	channel[i][10]=0xa0;

/* VCO range and C divisor (VHF) or Extender control (Lo-Band) */
	channel[i][11]=0x00;

/* B and A divisors  */
	channel[i][12]=0x00;
	channel[i][13]=0x00;
	channel[i][14]=0x00;
	channel[i][15]=0x00;
	/* TX-RX divisors now cleared */



if (band==1)
	{
	printf("Extender (y/n): ");

	while (*choice!=121 & *choice!=110)

		scanf("%c",choice);
	printf("\n");
	}

printf("You entered %2.5f\t%2.5f\t%3.1f\t%3.1f\t%c\n",rx_freq,tx_freq,rx_pl_freq,tx_pl_freq,*choice);

if (*choice==121 && band==1)
	channel[i][10]=channel[i][10]&0xfe;
else
	channel[i][10]=channel[i][10]|0x01; /*Extender control*/

rx_ref=0;
tx_ref=0;
/* Figure Reference, RX divisor A and divisor B */
	rx_freq=(rx_freq+.00005)*10000;
	rx_vco=rx_freq;
	rx_vco=rx_vco*100;
	rx_vco=rx_vco+rx_lo; /* rx_vco contains RX VCO freq in Hz */
	dummy=ldiv(rx_vco,6250);
	if (!dummy.rem) { rx_ref=6250; rx_divisor=dummy.quot; }
	dummy=ldiv(rx_vco,5000);
	if (!dummy.rem) { rx_ref=5000; rx_divisor=dummy.quot; }

	if (!rx_ref)
		{
		printf("Oops! Problem with reference frequency math\n");
		printf("rx_vco=%d",rx_vco);
		return(1);
		}

/* Figure the RX C divisor */
	for (j=1;j<4;j++)
		{
		dummy=ldiv(rx_divisor-j,3);
		if (!dummy.rem) {rx_div_c=j;break;}
		}

	if (band==2)
		{
		rx_vco=rx_vco-rx_div_c*rx_ref;
		rx_vco=rx_vco/3;
		}
	for (rx_div_a=1;rx_div_a<64;rx_div_a++)
	{
		dummy=ldiv((rx_vco - rx_div_a * 64*rx_ref), 63*rx_ref);
		if (dummy.rem==0)
		{
			rx_div_b=dummy.quot;
			break;
		}
	}

	if (rx_div_a ==64)
	{
	printf("\nOOPS!  Something went wrong with RX calc!\n\n");
	return (1);
	}
	printf("A=%d B=%d\n",rx_div_a,rx_div_b); /* Divisors now set for RX VCO */

/* Figure TX Reference */
/*tx_freq=tx_freq+.00005;*/

	tx_freq=(tx_freq+.00005)*10000;
	tx_vco=tx_freq;
	tx_vco=tx_vco*100;
	if (band==1)
		tx_vco=172800000-tx_vco;
printf("tx_vco=%d\n",tx_vco);
	/* tx_vco contains TX VCO freq in Hz */
	dummy=ldiv(tx_vco,6250);
	if (!dummy.rem) { tx_ref=6250; tx_divisor=dummy.quot; }
	dummy=ldiv(tx_vco,5000);
	if (!dummy.rem) { tx_ref=5000; tx_divisor=dummy.quot; }
	if (!tx_ref)
		{
		printf("Oops! Problem with TX reference frequency math");
		printf("tx_vco=%d",tx_vco);
		return(1);
		}

/* Figure the TX C divisor */
	for (j=1;j<4;j++)
		{
		dummy=ldiv(tx_divisor-j,3);
		printf("tx-j=%d tx-rem=%d\n",j,dummy.rem);
		if (!dummy.rem) {tx_div_c=j; break;}
		}


/* Figure TX divisor A and divisor B */

	if (band==2)
		{
		tx_vco=tx_vco-tx_div_c*tx_ref;
		tx_vco=tx_vco/3;
		}

	for (tx_div_a=1;tx_div_a<64;tx_div_a++)
	{
		dummy=ldiv((tx_vco - tx_div_a * 64*tx_ref), 63*tx_ref);
		if (dummy.rem==0)
		{
			tx_div_b=dummy.quot;
			break;
		}
	}

	if (tx_div_a ==64)
	{
	if (tx_freq<100) 
		{
		tx_div_a=0x3f; tx_div_b=0x3ff;
		}
		else
		{
		printf("\nOOPS!  Something went wrong with TX calc!\n\n");
		return (1);
		}
	}
	printf("TX_A=%d TX_B=%d\n",tx_div_a,tx_div_b); /* Divisors now set for TX VCO */


/* TOT power and reference */

if (tx_ref==6250) j=0;
if (tx_ref==5000) j=2;
if (rx_ref==5000) j=j|1;
tx_tot=tx_tot<<3;

j=j|tx_tot;
pwr=pwr<<2;
j=j|pwr;
channel[i][8]=j;



/*VCO range and C divisors */
       switch (rx_div_c) {
		case 3: j=2; break;
		case 1: j=1; break;
		case 2: j=3; break;
		case 0: printf("Problem writing div_c\n"); return(1);
		}
       switch (tx_div_c) {
		case 3: k=2; break;
		case 1: k=1; break;
		case 2: k=3; break;
		case 0: printf("Problem writing div_c\n"); return(1);
		}

k=k<<4;
j=j|k;

channel[i][11]=j;

if (band==1)
	{
	dummy=ldiv(tx_vco-104000000,10000000);
	k=dummy.quot;
	printf("quot=%x\n",k);
	switch (k){
		case 0: j=0; break;
		case 1: j=2; break;
		case 2: j=1; break;
		case 3: j=3; break;
	default: printf("Problem with tx VCO range calc\n");
	}
	j=j<<6;
	channel[i][11]=channel[i][11]|j;

	dummy=ldiv(rx_vco-104000000,10000000);
	k=dummy.quot;
	printf("quot=%x\n",k);
	switch (k){
		case 0: j=0; break;
		case 1: j=2; break;
		case 2: j=1; break;
		case 3: j=3; break;
	default: printf("Problem with rx VCO range calc\n");
	}
	j=j<<2;
	channel[i][11]=channel[i][11]|j;
	}
	
else
	{
	if (tx_vco*3 > 156000000)
		j=1;
	else
		j=3;
	j=j<<6;
	channel[i][11]=channel[i][11]|j;
	if (rx_vco*3 > 209900000)
		j=2;
	else
		j=0;
	j=j<<2;
	channel[i][11]=channel[i][11]|j;
	}


	j=rx_div_b>>6;
	k=tx_div_b>>6;
	k=k<<4;
	j=j | k;

	channel[i][12]=j;

	j=rx_div_b>>2;
	j=j & 0x0f;
	k=tx_div_b>>2;
	k=k<<4;
	j=j | k;
	channel[i][13]=j;

	j=rx_div_b & 0x03;
	k=tx_div_b & 0x03;
	j=j<<2;
	k=k<<6;
	j=j | k;
	channel[i][14]=j;

	j=rx_div_a>>4;
	k=tx_div_a & 0x30;
	j=j | k;
	channel[i][14]=channel[i][14] | j;

	j=rx_div_a & 0x0f;
	k=tx_div_a & 0x0f;
	k=k<<4;
	j=j | k;
	channel[i][15]=j;
	/* divisors now changed */

}

void display_channels(unsigned int band)
{
printf("Channel\t Receive\tTransmit\tToT\tType\tRX PL\tTX PL");

if (band==1)
        printf("\tExtender");

/* printf("  TX Power\n\n");*/

printf("\n");

/* start retrieval of modulus values */
        for (i=0;i<32;i++)
        {

        j=channel[i][12];
        k=j&0x000f;
        j=j&0x00f0;


        /* j now is the high bits of channel byte*/
        /* k is the low bits of channel byte */

        tx_div_b=j<<2;
        rx_div_b=k<<6;

        j=channel[i][13];
        k=j&0x000f;
        j=j&0x00f0;
        j=j>>2;
        k=k<<2;

        tx_div_b=tx_div_b+j;
        rx_div_b=rx_div_b+k;

        j=channel[i][14];
        k=j&0x000f;
        j=j&0x00f0;
        j=j>>6;

        k=k>>2;
        tx_div_b=tx_div_b+j;
        rx_div_b=rx_div_b+k;
        /*tx_div_b now contains the modulus b value for TX */
        /*rx_div_b now contains the modulus b value for RX */

        j=channel[i][14];
        k=j&0x0003;
        j=j&0x0030;
        tx_div_a=j;
        rx_div_a=k<<4;

        j=channel[i][15];
        k=j&0x000f;
        j=j&0x00f0;
        j=j>>4;

        tx_div_a=tx_div_a+j;
        rx_div_a=rx_div_a+k;

        /*tx_div_a now contains the modulus a value for TX */
        /*rx_div_a now contains the modulus a value for RX */


        j=channel[i][14];
        k=j&0x0003;
        j=j&0x0030;
        tx_div_a=j;
        rx_div_a=k<<4;

        j=channel[i][15];
        k=j&0x000f;
        j=j&0x00f0;
        j=j>>4;

        tx_div_a=tx_div_a+j;
        rx_div_a=rx_div_a+k;

        /*tx_div_a now contains the modulus a value for TX */
        /*rx_div_a now contains the modulus a value for RX */

        j=channel[i][11];
        extender=j&0x0001;

        j=channel[i][8];
        pwr=j&0x0004;   /* transmit power */
        k=j&0x0003;

        j=j&0x00f8;
        j=j>>3;
        j=j^0x1f;

/* Found a decrepency from data found...bit 0 is rx reference and bit 1 is tx reference */

                switch (k) {
                case 0: tx_ref=6250; rx_ref=6250; break;
                case 1: tx_ref=6250; rx_ref=5000; break;
                case 2: tx_ref=5000; rx_ref=6250; break;
                case 3: tx_ref=5000; rx_ref=5000; break;
                default: tx_ref=0; rx_ref=0;
                        }


        /* ref now contains the VCO reference frequency */
        /* j now contains the TOT value for TX (steps of 15 seconds) */

        tx_pl=channel[i][5];
        tx_pl=tx_pl<<8;
        tx_pl=tx_pl+channel[i][4];
        rx_pl=channel[i][7];
        rx_pl=rx_pl<<8;
        rx_pl=rx_pl+channel[i][6];

        /* search for C */
        rx_div_c=channel[i][11];
        c=rx_div_c&0x0003;

        switch (c) {
                case 0: rx_div_c=100; break;
                case 1: rx_div_c=1; break;
                case 2: rx_div_c=3; break;
                case 3: rx_div_c=2; break;
                }

        tx_div_c=channel[i][11];
        c=tx_div_c>>4;
        c=c&0x0003;

        switch (c) {
                case 0: tx_div_c=100; break;
                case 1: tx_div_c=1; break;
                case 2: tx_div_c=3; break;
                case 3: tx_div_c=2; break;
                }

        printf("%d",i+1);

        if (band==1)
                {
                frequency=(64*rx_div_a+63*rx_div_b)*rx_ref-75700000;
                printf("\t %7.3f  ",frequency/1000000);
                }
        else
                {
                frequency=((64*rx_div_a+63*rx_div_b)*3+rx_div_c)*rx_ref-53900000;
                printf("\t%7.4f  ",frequency/1000000);
                }
        if ((tx_div_a==0x003f)&&(tx_div_b==0x3ff))
        printf("\tRX Only ");
        else
        {
        if (band==1)
                frequency=172800000-(64*tx_div_a+63*tx_div_b)*tx_ref;
        else
                frequency=((64*tx_div_a+63*tx_div_b)*3+tx_div_c)*tx_ref;

        printf("\t%7.4f  ",frequency/1000000);
        }


        printf("\t%d",j*15); /* print TOT value */

                if (rx_pl&0x4000)
                {
                	/* RX Code is DPL */
                	if (!(rx_pl&0x2000))
                        	printf("\tCSQ\t");
                	else
                        	{
                        	rx_pl=rx_pl^0x187f;
                        	printf("\tDPL");
				show_dpl(rx_pl);
                        	}
                	if ((tx_pl&0x6000)==0x6000)
			{
			tx_pl=tx_pl^0x187f;
			show_dpl(tx_pl);
			}
			else
			printf("\t");
                }
                else
                /* Code is PL */
                {
                        if (tx_pl&0x8000) /* No MPL operator select */
                        {
                        tx_pl=tx_pl&0x3fff;
                        rx_pl=rx_pl&0x3fff;
                        tx_pl=tx_pl^0x3fff;
                        rx_pl=rx_pl^0x3fff;
                        tx_pl_freq=tx_pl/18.0616;
                        rx_pl_freq=rx_pl/61.17;
                        printf("\tPL");
                                if (rx_pl==0x3fff)
                                printf("\tCSQ");
                                else
                                printf("\t%3.1f",rx_pl_freq);

                        printf("\t%3.1f",tx_pl_freq);
                        }
                }


		if (!(tx_pl&0x4000))
		{
		/* TX Code is PL */
			if (tx_pl&0x8000) /* No MPL operator select */
			{
			tx_pl=tx_pl&0x3fff;
                        tx_pl=tx_pl^0x3fff;
                        tx_pl_freq=tx_pl/18.0616;
			printf("%3.1f",tx_pl_freq);
			}
		}

        if (band==1)
                {
                if (extender)
                printf("\tOff");
                else
                printf("\tOn");
                }
	/*
        if (pwr==4)
        printf("\t   High");
        else
        printf("\t   Low");
	*/

        printf("\n");


        }

}




void show_pl(void)
{
int i;
int tone[44]={670,693,719,744,770,797,825,854,885,915,948,974,1000,1035,1072,1109,1148,1188,1230,1273,1318,1365,1413,1462,1514,1567,1622,1679,1738,1799,1862,1928,2033,2065,2107,2181,2257,2291,2336,2418,2503,2541};
char *pl_code[44]={"XZ","WZ","XA","WA","XB","WB","YZ","YA","YB","ZZ","ZA","ZB","1Z","1A","1B","2Z","2A","2B","3Z","3A","3B","4Z","4A","4B","5Z","5A","5B","6Z","6A","6B","7Z","7A","M1","8Z","M2","M3","M4","9Z","M5","M6","M7","OZ"};
float tone_freq;
printf("\n\nFreq  Code\t\tFreq   Code\t\tFreq   Code\n\n");
for (i=0;i<14;i++)
	{
	tone_freq=tone[i];
	printf("%3.1f  %s\t\t",tone_freq/10,pl_code[i]);
	tone_freq=tone[i+14];
	printf("%3.1f  %s\t\t",tone_freq/10,pl_code[i+14]);
	tone_freq=tone[i+28];
	printf("%3.1f  %s\n",tone_freq/10,pl_code[i+28]);
	}
printf("\n");
return;
}

void show_dpl(unsigned int dpl)
{
unsigned int x;
/* First Digit */
x=dpl>>10;
x=x&0x0002;
x=x|(dpl>>12&0x0001);
x=x<<1;
x=x|(dpl&0x0001);
printf("\t%X",x);

/* Second Digit */
x=dpl<<1;
x=x&0x0004;
x=x|(dpl>>1&0x0002);
x=x|(dpl>>3&0x0001);
printf("%X",x);

/* Third Digit */
x=dpl>>2;
x=x&0x0004;
x=x|(dpl>>4&0x0002);
x=x|(dpl>>6&0x0001);
printf("%X",x);
return;
}

