Skip to content
Snippets Groups Projects
app_rpt.c 176 KiB
Newer Older
  • Learn to ignore specific revisions
  • /* Doug Hall RBI-1 serial data definitions:
     *
     * Byte 0: Expansion external outputs 
     * Byte 1: 
     *	Bits 0-3 are BAND as follows:
     *	Bits 4-5 are POWER bits as follows:
     *		00 - Low Power
     *		01 - Hi Power
     *		02 - Med Power
     *	Bits 6-7 are always set
     * Byte 2:
     *	Bits 0-3 MHZ in BCD format
     *	Bits 4-5 are offset as follows:
     *		00 - minus
     *		01 - plus
     *		02 - simplex
     *		03 - minus minus (whatever that is)
     *	Bit 6 is the 0/5 KHZ bit
     *	Bit 7 is always set
     * Byte 3:
     *	Bits 0-3 are 10 KHZ in BCD format
     *	Bits 4-7 are 100 KHZ in BCD format
     * Byte 4: PL Tone code and encode/decode enable bits
     *	Bits 0-5 are PL tone code (comspec binary codes)
     *	Bit 6 is encode enable/disable
     *	Bit 7 is decode enable/disable
     */
    
    /* take the frequency from the 10 mhz digits (and up) and convert it
       to a band number */
    
    static int rbi_mhztoband(char *str)
    
    int	i;
    
    	i = atoi(str) / 10; /* get the 10's of mhz */
    	switch(i)
    	{
    	    case 2:
    		return 10;
    	    case 5:
    		return 11;
    	    case 14:
    		return 2;
    	    case 22:
    		return 3;
    	    case 44:
    		return 4;
    	    case 124:
    		return 0;
    	    case 125:
    		return 1;
    	    case 126:
    		return 8;
    	    case 127:
    		return 5;
    	    case 128:
    		return 6;
    	    case 129:
    		return 7;
    	    default:
    		break;
    
    /* take a PL frequency and turn it into a code */
    static int rbi_pltocode(char *str)
    
    Jim Dixon's avatar
    Jim Dixon committed
    
    
    	s = strchr(str,'.');
    	i = 0;
    	if (s) i = atoi(s + 1);
    	i += atoi(str) * 10;
    	switch(i)
    
    	    case 670:
    		return 0;
    	    case 719:
    		return 1;
    	    case 744:
    		return 2;
    	    case 770:
    		return 3;
    	    case 797:
    		return 4;
    	    case 825:
    		return 5;
    	    case 854:
    		return 6;
    	    case 885:
    		return 7;
    	    case 915:
    		return 8;
    	    case 948:
    		return 9;
    	    case 974:
    		return 10;
    	    case 1000:
    		return 11;
    	    case 1035:
    		return 12;
    	    case 1072:
    		return 13;
    	    case 1109:
    		return 14;
    	    case 1148:
    		return 15;
    	    case 1188:
    		return 16;
    	    case 1230:
    		return 17;
    	    case 1273:
    		return 18;
    	    case 1318:
    		return 19;
    	    case 1365:
    		return 20;
    	    case 1413:
    		return 21;
    	    case 1462:
    		return 22;
    	    case 1514:
    		return 23;
    	    case 1567:
    		return 24;
    	    case 1622:
    		return 25;
    	    case 1679:
    		return 26;
    	    case 1738:
    		return 27;
    	    case 1799:
    		return 28;
    	    case 1862:
    		return 29;
    	    case 1928:
    		return 30;
    	    case 2035:
    		return 31;
    	    case 2107:
    		return 32;
    	    case 2181:
    		return 33;
    	    case 2257:
    		return 34;
    	    case 2336:
    		return 35;
    	    case 2418:
    		return 36;
    	    case 2503:
    		return 37;
    
    	return -1;
    }
    
    /*
    * Shift out a formatted serial bit stream
    */
    
    static void rbi_out_parallel(struct rpt *myrpt,unsigned char *data)
        {
        int i,j;
        unsigned char od,d;
        static volatile long long delayvar;
    
        for(i = 0 ; i < 5 ; i++){
            od = *data++; 
            for(j = 0 ; j < 8 ; j++){
                d = od & 1;
                outb(d,myrpt->iobase);
    	    /* >= 15 us */
    	    for(delayvar = 1; delayvar < 15000; delayvar++); 
                od >>= 1;
                outb(d | 2,myrpt->iobase);
    	    /* >= 30 us */
    	    for(delayvar = 1; delayvar < 30000; delayvar++); 
                outb(d,myrpt->iobase);
    	    /* >= 10 us */
    	    for(delayvar = 1; delayvar < 10000; delayvar++); 
                }
            }
    	/* >= 50 us */
            for(delayvar = 1; delayvar < 50000; delayvar++); 
        }
    
    static void rbi_out(struct rpt *myrpt,unsigned char *data)
    {
    struct zt_radio_param r;
    
    	memset(&r,0,sizeof(struct zt_radio_param));
    	r.radpar = ZT_RADPAR_REMMODE;
    	r.data = ZT_RADPAR_REM_RBI1;
    	/* if setparam ioctl fails, its probably not a pciradio card */
    	if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
    	{
    		rbi_out_parallel(myrpt,data);
    		return;
    	}
    	r.radpar = ZT_RADPAR_REMCOMMAND;
    	memcpy(&r.data,data,5);
    	if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&r) == -1)
    	{
    		ast_log(LOG_WARNING,"Cannot send RBI command for channel %s\n",myrpt->rxchannel->name);
    		return;
    	}
    }
    
    
    static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes, char *rxbuf,
    
            int rxmaxbytes, int asciiflag)
    {
    	int i;
    	struct zt_radio_param prm;
    
    	if(debug){
    		printf("String output was: ");
    		for(i = 0; i < txbytes; i++)
    			printf("%02X ", (unsigned char ) txbuf[i]);
    		printf("\n");
    	}
    
            prm.radpar = ZT_RADPAR_REMMODE;
            if (asciiflag)  prm.data = ZT_RADPAR_REM_SERIAL_ASCII;
            else prm.data = ZT_RADPAR_REM_SERIAL;
    	if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
            prm.radpar = ZT_RADPAR_REMCOMMAND;
            prm.data = rxmaxbytes;
            memcpy(prm.buf,txbuf,txbytes);
            prm.index = txbytes;
    	if (ioctl(myrpt->rxchannel->fds[0],ZT_RADIO_SETPARAM,&prm) == -1) return -1;
            if (rxbuf)
            {
                    *rxbuf = 0;
                    memcpy(rxbuf,prm.buf,prm.index);
            }
            return(prm.index);
    }
    
    static int setrbi(struct rpt *myrpt)
    {
    
    char tmp[MAXREMSTR] = "",*s;
    unsigned char rbicmd[5];
    
    int	band,txoffset = 0,txpower = 0,txpl;
    
    	/* must be a remote system */
    	if (!myrpt->remote) return(0);
    	/* must have rbi hardware */
    	if (strncmp(myrpt->remote,remote_rig_rbi,3)) return(0);
    	strncpy(tmp, myrpt->freq, sizeof(tmp) - 1);
    	s = strchr(tmp,'.');
    	/* if no decimal, is invalid */
    	
    	if (s == NULL){
    		if(debug)
    			printf("@@@@ Frequency needs a decimal\n");
    		return -1;
    	}
    	
    	*s++ = 0;
    	if (strlen(tmp) < 2){
    		if(debug)
    			printf("@@@@ Bad MHz digits: %s\n", tmp);
    	 	return -1;
    	}
    	 
    	if (strlen(s) < 3){
    		if(debug)
    			printf("@@@@ Bad KHz digits: %s\n", s);
    	 	return -1;
    	}
    
    	if ((s[2] != '0') && (s[2] != '5')){
    		if(debug)
    			printf("@@@@ KHz must end in 0 or 5: %c\n", s[2]);
    	 	return -1;
    	}
    	 
    	band = rbi_mhztoband(tmp);
    	if (band == -1){
    		if(debug)
    			printf("@@@@ Bad Band: %s\n", tmp);
    	 	return -1;
    	}
    	
    	txpl = rbi_pltocode(myrpt->txpl);
    	
    	if (txpl == -1){
    		if(debug)
    			printf("@@@@ Bad TX PL: %s\n", myrpt->txpl);
    	 	return -1;
    	}
    
    	
    	switch(myrpt->offset)
    	{
    	    case REM_MINUS:
    		txoffset = 0;
    		break;
    	    case REM_PLUS:
    		txoffset = 0x10;
    		break;
    	    case REM_SIMPLEX:
    		txoffset = 0x20;
    		break;
    	}
    	switch(myrpt->powerlevel)
    	{
    	    case REM_LOWPWR:
    		txpower = 0;
    		break;
    	    case REM_MEDPWR:
    		txpower = 0x20;
    		break;
    	    case REM_HIPWR:
    		txpower = 0x10;
    		break;
    	}
    	rbicmd[0] = 0;
    	rbicmd[1] = band | txpower | 0xc0;
    	rbicmd[2] = (*(s - 2) - '0') | txoffset | 0x80;
    	if (s[2] == '5') rbicmd[2] |= 0x40;
    	rbicmd[3] = ((*s - '0') << 4) + (s[1] - '0');
    	rbicmd[4] = txpl;
    	if (myrpt->txplon) rbicmd[4] |= 0x40;
    	if (myrpt->rxplon) rbicmd[4] |= 0x80;
    	rbi_out(myrpt,rbicmd);
    	return 0;
    }
    
    
    /* Check for valid rbi frequency */
    /* Hard coded limits now, configurable later, maybe? */
    
    
    Jim Dixon's avatar
    Jim Dixon committed
    static int check_freq_rbi(int m, int d, int *defmode)
    
    Jim Dixon's avatar
    Jim Dixon committed
    	int dflmd = REM_MODE_FM;
    
    
    	if(m == 50){ /* 6 meters */
    		if(d < 10100)
    			return -1;
    	}
    	else if((m >= 51) && ( m < 54)){
                    ;
    	}
    	else if(m == 144){ /* 2 meters */
    		if(d < 10100)
    			return -1;
    	}
    	else if((m >= 145) && (m < 148)){
    		;
    	}
     	else if((m >= 222) && (m < 225)){ /* 1.25 meters */
    		;
    	}
    	else if((m >= 430) && (m < 450)){ /* 70 centimeters */
    		;
    	}
    	else if((m >= 1240) && (m < 1300)){ /* 23 centimeters */
    		;
    	}
    	else
    		return -1;
    
    Jim Dixon's avatar
    Jim Dixon committed
    	
    	if(defmode)
    		*defmode = dflmd;	
    
    
    
    	return 0;
    }
    
    /*
    * Split frequency into mhz and decimals
    */
     
    static int split_freq(char *mhz, char *decimals, char *freq)
    {
    	char freq_copy[MAXREMSTR];
    	char *decp;
    
    	decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
    	if(decp){
    		*decp++ = 0;
    		strncpy(mhz, freq_copy, MAXREMSTR);
    		strcpy(decimals, "00000");
    		strncpy(decimals, decp, strlen(decp));
    		decimals[5] = 0;
    		return 0;
    	}
    	else
    		return -1;
    
    }
    	
    
    Jim Dixon's avatar
    Jim Dixon committed
    /*
    * Split ctcss frequency into hertz and decimal
    */
     
    static int split_ctcss_freq(char *hertz, char *decimal, char *freq)
    {
    	char freq_copy[MAXREMSTR];
    	char *decp;
    
    	decp = strchr(strncpy(freq_copy, freq, MAXREMSTR),'.');
    	if(decp){
    		*decp++ = 0;
    		strncpy(hertz, freq_copy, MAXREMSTR);
    		strncpy(decimal, decp, strlen(decp));
    		decimal[strlen(decp)] = '\0';
    		return 0;
    	}
    	else
    		return -1;
    }
    
    
    
    
    /*
    * FT-897 I/O handlers
    */
    
    /* Check to see that the frequency is valid */
    /* Hard coded limits now, configurable later, maybe? */
    
    
    
    Jim Dixon's avatar
    Jim Dixon committed
    static int check_freq_ft897(int m, int d, int *defmode)
    
    Jim Dixon's avatar
    Jim Dixon committed
    	int dflmd = REM_MODE_FM;
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd =	REM_MODE_LSB; 
    
    		if(d < 80001)
    			return -1;
    	}
    	else if(m == 3){ /* 80 meters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_LSB;
    
    		if(d < 75001)
    			return -1;
    	}
    	else if(m == 7){ /* 40 meters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_LSB;
    		if((d < 15001) || (d > 29999))
    
    			return -1;
    	}
    	else if(m == 14){ /* 20 meters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_USB;
    
    		if((d < 15001) || (d > 34999))
    			return -1;
    	}
    	else if(m == 18){ /* 17 meters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_USB;
    		if((d < 11001) || (d > 16797))
    
    			return -1;
    	}
    	else if(m == 21){ /* 15 meters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_USB;
    
    		if((d < 20001) || (d > 44999))
    			return -1;
    	}
    	else if(m == 24){ /* 12 meters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_USB;
    
    		if((d < 93001) || (d > 98999))
    			return -1;
    	}
    	else if(m == 28){ /* 10 meters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_USB;
    
    Jim Dixon's avatar
    Jim Dixon committed
    		if(d >= 51000)
    			dflmd = REM_MODE_FM;
    		else
    			dflmd = REM_MODE_USB;
    
    		if(d > 69999)
    			return -1;
    	}
    	else if(m == 50){ /* 6 meters */
    		if(d < 10100)
    			return -1;
    
    Jim Dixon's avatar
    Jim Dixon committed
    		if(d >= 30000)
    			dflmd = REM_MODE_FM;
    		else
    			dflmd = REM_MODE_USB;
    
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_FM;
    
    	}
    	else if(m == 144){ /* 2 meters */
    		if(d < 10100)
    			return -1;
    
    Jim Dixon's avatar
    Jim Dixon committed
    		if(d >= 30000)
    			dflmd = REM_MODE_FM;
    		else
    			dflmd = REM_MODE_USB;
    
    Jim Dixon's avatar
    Jim Dixon committed
    		dflmd = REM_MODE_FM;
    
    	}
    	else if((m >= 430) && (m < 450)){ /* 70 centimeters */
    
    Jim Dixon's avatar
    Jim Dixon committed
    		if(m  < 438)
    			dflmd = REM_MODE_USB;
    		else
    			dflmd = REM_MODE_FM;
    
    Jim Dixon's avatar
    Jim Dixon committed
    
    	if(defmode)
    		*defmode = dflmd;
    
    
    	return 0;
    }
    
    /*
    * Set a new frequency for the FT897
    */
    
    static int set_freq_ft897(struct rpt *myrpt, char *newfreq)
    {
    	char mhz[MAXREMSTR];
    	char decimals[MAXREMSTR];
    	unsigned char cmdstr[5];
    	int fd,m,d;
    
    	fd = 0;
    	if(debug) 
    		printf("New frequency: %s\n",newfreq);
    
    	if(split_freq(mhz, decimals, newfreq))
    		return -1; 
    
    	m = atoi(mhz);
    	d = atoi(decimals);
    
    	/* The FT-897 likes packed BCD frequencies */
    
    	cmdstr[0] = ((m / 100) << 4) + ((m % 100)/10);			/* 100MHz 10Mhz */
    	cmdstr[1] = ((m % 10) << 4) + (d / 10000);			/* 1MHz 100KHz */
    	cmdstr[2] = (((d % 10000)/1000) << 4) + ((d % 1000)/ 100);	/* 10KHz 1KHz */
    	cmdstr[3] = (((d % 100)/10) << 4) + (d % 10);			/* 100Hz 10Hz */
    	cmdstr[4] = 0x01;						/* command */
    
    	return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
    
    }
    
    /* ft-897 simple commands */
    
    static int simple_command_ft897(struct rpt *myrpt, char command)
    {
    	unsigned char cmdstr[5];
    	
    	memset(cmdstr, 0, 5);
    
    	cmdstr[4] = command;	
    
    	return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
    
    }
    
    /* ft-897 offset */
    
    static int set_offset_ft897(struct rpt *myrpt, char offset)
    {
    	unsigned char cmdstr[5];
    	
    	memset(cmdstr, 0, 5);
    
    	switch(offset){
    		case	REM_SIMPLEX:
    			cmdstr[0] = 0x89;
    			break;
    
    		case	REM_MINUS:
    			cmdstr[0] = 0x09;
    			break;
    		
    		case	REM_PLUS:
    			cmdstr[0] = 0x49;
    			break;	
    
    		default:
    			return -1;
    	}
    
    	cmdstr[4] = 0x09;	
    
    	return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
    }
    
    /* ft-897 mode */
    
    static int set_mode_ft897(struct rpt *myrpt, char newmode)
    {
    	unsigned char cmdstr[5];
    	
    	memset(cmdstr, 0, 5);
    	
    	switch(newmode){
    		case	REM_MODE_FM:
    			cmdstr[0] = 0x08;
    			break;
    
    		case	REM_MODE_USB:
    			cmdstr[0] = 0x01;
    			break;
    
    		case	REM_MODE_LSB:
    			cmdstr[0] = 0x00;
    			break;
    
    		case	REM_MODE_AM:
    			cmdstr[0] = 0x04;
    			break;
    		
    		default:
    			return -1;
    	}
    	cmdstr[4] = 0x07;	
    
    	return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
    }
    
    /* Set tone encode and decode modes */
    
    static int set_ctcss_mode_ft897(struct rpt *myrpt, char txplon, char rxplon)
    {
    	unsigned char cmdstr[5];
    	
    	memset(cmdstr, 0, 5);
    	
    	if(rxplon && txplon)
    		cmdstr[0] = 0x2A; /* Encode and Decode */
    	else if (!rxplon && txplon)
    		cmdstr[0] = 0x4A; /* Encode only */
    	else if (rxplon && !txplon)
    		cmdstr[0] = 0x3A; /* Encode only */
    	else
    		cmdstr[0] = 0x8A; /* OFF */
    
    	cmdstr[4] = 0x0A;	
    
    	return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
    }
    
    
    /* Set transmit and receive ctcss tone frequencies */
    
    static int set_ctcss_freq_ft897(struct rpt *myrpt, char *txtone, char *rxtone)
    {
    	unsigned char cmdstr[5];
    
    Jim Dixon's avatar
    Jim Dixon committed
    	char hertz[MAXREMSTR],decimal[MAXREMSTR];
    
    Jim Dixon's avatar
    Jim Dixon committed
    	if(split_ctcss_freq(hertz, decimal, txtone))
    
    Jim Dixon's avatar
    Jim Dixon committed
    	d = atoi(decimal);
    
    	
    	cmdstr[0] = ((h / 100) << 4) + (h % 100)/ 10;
    	cmdstr[1] = ((h % 10) << 4) + (d % 10);
    	
    	if(rxtone){
    	
    
    Jim Dixon's avatar
    Jim Dixon committed
    		if(split_ctcss_freq(hertz, decimal, rxtone))
    
    Jim Dixon's avatar
    Jim Dixon committed
    		d = atoi(decimal);
    
    	
    		cmdstr[2] = ((h / 100) << 4) + (h % 100)/ 10;
    		cmdstr[3] = ((h % 10) << 4) + (d % 10);
    	}
    	cmdstr[4] = 0x0B;	
    
    	return serial_remote_io(myrpt, cmdstr, 5, NULL, 0, 0);
    }	
    
    
    
    static int set_ft897(struct rpt *myrpt)
    {
    	int res;
    	
    	if(debug)
    		printf("@@@@ lock on\n");
    
    	res = simple_command_ft897(myrpt, 0x00);				/* LOCK on */	
    
    	if(debug)
    		printf("@@@@ ptt off\n");
    
    	if(!res)
    		res = simple_command_ft897(myrpt, 0x88);		/* PTT off */
    
    	if(debug)
    		printf("Modulation mode\n");
    
    	if(!res)
    		res = set_mode_ft897(myrpt, myrpt->remmode);		/* Modulation mode */
    
    	if(debug)
    		printf("Split off\n");
    
    	if(!res)
    		simple_command_ft897(myrpt, 0x82);			/* Split off */
    
    	if(debug)
    		printf("Frequency\n");
    
    	if(!res)
    		res = set_freq_ft897(myrpt, myrpt->freq);		/* Frequency */
    	if((myrpt->remmode == REM_MODE_FM)){
    		if(debug)
    			printf("Offset\n");
    		if(!res)
    			res = set_offset_ft897(myrpt, myrpt->offset);	/* Offset if FM */
    		if((!res)&&(myrpt->rxplon || myrpt->txplon)){
    			if(debug)
    				printf("CTCSS tone freqs.\n");
    			res = set_ctcss_freq_ft897(myrpt, myrpt->txpl, myrpt->rxpl); /* CTCSS freqs if CTCSS is enabled */
    		}
    		if(!res){
    			if(debug)
    				printf("CTCSS mode\n");
    			res = set_ctcss_mode_ft897(myrpt, myrpt->txplon, myrpt->rxplon); /* CTCSS mode */
    		}
    	}
    	if((myrpt->remmode == REM_MODE_USB)||(myrpt->remmode == REM_MODE_LSB)){
    		if(debug)
    			printf("Clarifier off\n");
    		simple_command_ft897(myrpt, 0x85);			/* Clarifier off if LSB or USB */
    	}
    	return res;
    }
    
    static int closerem_ft897(struct rpt *myrpt)
    {
    	simple_command_ft897(myrpt, 0x88); /* PTT off */
    	return 0;
    }	
    
    /*
    * Bump frequency up or down by a small amount 
    * Return 0 if the new frequnecy is valid, or -1 if invalid
    * Interval is in Hz, resolution is 10Hz 
    */
    
    static int multimode_bump_freq_ft897(struct rpt *myrpt, int interval)
    {
    	int m,d;
    	char mhz[MAXREMSTR], decimals[MAXREMSTR];
    
    	if(debug)
    		printf("Before bump: %s\n", myrpt->freq);
    
    	if(split_freq(mhz, decimals, myrpt->freq))
    		return -1;
    	
    	m = atoi(mhz);
    	d = atoi(decimals);
    
    	d += (interval / 10); /* 10Hz resolution */
    	if(d < 0){
    		m--;
    		d += 100000;
    	}
    	else if(d >= 100000){
    		m++;
    		d -= 100000;
    	}
    
    
    Jim Dixon's avatar
    Jim Dixon committed
    	if(check_freq_ft897(m, d, NULL)){
    
    		if(debug)
    			printf("Bump freq invalid\n");
    		return -1;
    	}
    
    	snprintf(myrpt->freq, MAXREMSTR, "%d.%05d", m, d);
    
    	if(debug)
    		printf("After bump: %s\n", myrpt->freq);
    
    	return set_freq_ft897(myrpt, myrpt->freq);	
    }
    
    
    
    /*
    * Dispatch to correct I/O handler 
    */
    
    static int setrem(struct rpt *myrpt)
    {
    	if(!strcmp(myrpt->remote, remote_rig_ft897))
    		return set_ft897(myrpt);
    	else if(!strcmp(myrpt->remote, remote_rig_rbi))
    		return setrbi(myrpt);
    	else
    		return -1;
    }
    
    static int closerem(struct rpt *myrpt)
    {
    	if(!strcmp(myrpt->remote, remote_rig_ft897))
    		return closerem_ft897(myrpt);
    	else
    		return 0;
    }
    
    /*
    * Dispatch to correct frequency checker
    */
    
    
    Jim Dixon's avatar
    Jim Dixon committed
    static int check_freq(struct rpt *myrpt, int m, int d, int *defmode)
    
    {
    	if(!strcmp(myrpt->remote, remote_rig_ft897))
    
    Jim Dixon's avatar
    Jim Dixon committed
    		return check_freq_ft897(m, d, defmode);
    
    	else if(!strcmp(myrpt->remote, remote_rig_rbi))
    
    Jim Dixon's avatar
    Jim Dixon committed
    		return check_freq_rbi(m, d, defmode);
    
    	else
    		return -1;
    }
    
    /*
    * Return 1 if rig is multimode capable
    */
    
    static int multimode_capable(struct rpt *myrpt)
    {
    	if(!strcmp(myrpt->remote, remote_rig_ft897))
    		return 1;
    	return 0;
    }	
    
    /*
    * Dispatch to correct frequency bumping function
    */
    
    static int multimode_bump_freq(struct rpt *myrpt, int interval)
    {
    	if(!strcmp(myrpt->remote, remote_rig_ft897))
    		return multimode_bump_freq_ft897(myrpt, interval);
    	else
    		return -1;
    }
    
    
    /*
    * Queue announcment that scan has been stopped 
    */
    
    static void stop_scan(struct rpt *myrpt, int flag)
    {
    	myrpt->hfscanmode = 0;
    	myrpt->hfscanstatus = ((flag) ? -2 : -1);
    }
    
    /*
    * This is called periodically when in scan mode
    */
    
    
    static int service_scan(struct rpt *myrpt)
    {
    	int res, interval;
    	char mhz[MAXREMSTR], decimals[MAXREMSTR], k10=0i, k100=0;
    
    	switch(myrpt->hfscanmode){
    
    		case HF_SCAN_DOWN_SLOW:
    			interval = -10; /* 100Hz /sec */
    			break;
    
    		case HF_SCAN_DOWN_QUICK:
    			interval = -50; /* 500Hz /sec */
    			break;
    
    		case HF_SCAN_DOWN_FAST:
    			interval = -200; /* 2KHz /sec */
    			break;
    
    		case HF_SCAN_UP_SLOW:
    			interval = 10; /* 100Hz /sec */
    			break;
    
    		case HF_SCAN_UP_QUICK:
    			interval = 50; /* 500 Hz/sec */
    			break;
    
    		case HF_SCAN_UP_FAST:
    			interval = 200; /* 2KHz /sec */
    			break;
    
    		default:
    			myrpt->hfscanmode = 0; /* Huh? */
    			return -1;
    	}
    
    	res = split_freq(mhz, decimals, myrpt->freq);
    		
    	if(!res){
    		k100 =decimals[0];
    		k10 = decimals[1];
    		res = multimode_bump_freq(myrpt, interval);
    	}
    
    	if(!res)
    		res = split_freq(mhz, decimals, myrpt->freq);
    
    
    	if(res){
    		stop_scan(myrpt,1);
    		return -1;
    	}
    
    	/* Announce 10KHz boundaries */
    	if(k10 != decimals[1]){
    		int myhund = (interval < 0) ? k100 : decimals[0];
    		int myten = (interval < 0) ? k10 : decimals[1];
    		myrpt->hfscanstatus = (myten == '0') ? (myhund - '0') * 100 : (myten - '0') * 10;
    	}
    	return res;
    
    }
    
    
    
    Jim Dixon's avatar
    Jim Dixon committed
    static int rmt_telem_start(struct rpt *myrpt, struct ast_channel *chan, int delay)
    {
    			myrpt->remotetx = 0;
    			ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
    			if (!myrpt->remoterx)
    				ast_indicate(chan,AST_CONTROL_RADIO_KEY);
    			if (ast_safe_sleep(chan, delay) == -1)
    					return -1;
    			return 0;
    }
    
    
    static int rmt_telem_finish(struct rpt *myrpt, struct ast_channel *chan)
    {
    
    struct zt_params par;
    
    	if (ioctl(myrpt->txchannel->fds[0],ZT_GET_PARAMS,&par) == -1)
    	{
    		return -1;
    
    	}
    	if (!par.rxisoffhook)
    	{
    		ast_indicate(myrpt->remchannel,AST_CONTROL_RADIO_UNKEY);
    		myrpt->remoterx = 0;
    	}
    	else
    	{
    		myrpt->remoterx = 1;
    	}
    	return 0;
    }
    
    
    static int rmt_sayfile(struct rpt *myrpt, struct ast_channel *chan, int delay, char *filename)
    {
    	int res;
    
    	res = rmt_telem_start(myrpt, chan, delay);
    
    	if(!res)
    		res = sayfile(chan, filename);
    	
    	if(!res)
    		res = rmt_telem_finish(myrpt, chan);
    	return res;
    }
    
    static int rmt_saycharstr(struct rpt *myrpt, struct ast_channel *chan, int delay, char *charstr)
    {
    	int res;
    
    	res = rmt_telem_start(myrpt, chan, delay);
    
    	if(!res)
    		res = saycharstr(chan, charstr);
    	
    	if(!res)
    		res = rmt_telem_finish(myrpt, chan);
    	return res;
    }