better algorithm, yielding improved SNR

git-svn-id: https://hamlib.svn.sourceforge.net/svnroot/hamlib/trunk@2236 7ae35d74-ebe9-4afe-98af-79ac388436b8
Hamlib-1.2.7
Stéphane Fillod, F8CFE 2007-11-07 19:26:39 +00:00
rodzic fe423a4f94
commit 83ca5b5fb2
1 zmienionych plików z 126 dodań i 9 usunięć

Wyświetl plik

@ -2,7 +2,7 @@
* Hamlib KIT backend - Elektor SDR USB (5/07) receiver description
* Copyright (c) 2007 by Stephane Fillod
*
* $Id: elektor507.c,v 1.1 2007-10-07 20:30:40 fillods Exp $
* $Id: elektor507.c,v 1.2 2007-11-07 19:26:39 fillods Exp $
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as
@ -223,6 +223,11 @@ int elektor507_init(RIG *rig)
priv->osc_freq = OSCFREQ;
priv->ant = ANT_AUTO;
/* DIV1N set to safe default */
priv->Div1N = 8;
priv->P = 8;
priv->Q = 2;
extra_priv = &priv->extra_priv;
/* Try to load required dll */
@ -345,6 +350,11 @@ int elektor507_init(RIG *rig)
priv->osc_freq = OSCFREQ;
priv->ant = ANT_AUTO;
/* DIV1N set to safe default */
priv->Div1N = 8;
priv->P = 8;
priv->Q = 2;
rp->parm.usb.vid = USB_VID_FTDI;
rp->parm.usb.pid = USB_PID_FTDI_FT232;
rp->parm.usb.conf = 1;
@ -628,13 +638,14 @@ int elektor507_open(RIG *rig)
* Setup the CY27EE16ZE PLL.
*/
/* Enable CLOCK3 & CLOCK5 */
ret = i2c_write_reg(rig, CY_I2C_RAM_ADR, CLKOE_REG, 0x24);
/* Enable only CLOCK5. CLOCK3 will be on demand in set_ant() */
ret = i2c_write_reg(rig, CY_I2C_RAM_ADR, CLKOE_REG, 0x20);
if (ret != 0)
return ret;
/* DIV1N set to safe default */
ret = i2c_write_reg(rig, CY_I2C_RAM_ADR, DIV1_REG, 0x0a);
priv->Div1N = 8;
ret = i2c_write_reg(rig, CY_I2C_RAM_ADR, DIV1_REG, priv->Div1N);
if (ret != 0)
return ret;
@ -663,6 +674,8 @@ int elektor507_open(RIG *rig)
}
#ifdef ORIG_ALGORITHM
static void find_P_Q(struct elektor507_priv_data *priv, freq_t freq)
{
double Min, VCO;
@ -701,14 +714,85 @@ static void find_P_Q(struct elektor507_priv_data *priv, freq_t freq)
rig_debug(RIG_DEBUG_VERBOSE, "%s: Unstable parameters for VCO=%.1f\n",
__FUNCTION__, VCO);
}
#else /* ORIG_ALGORITHM */
static void find_P_Q_DIV1N(struct elektor507_priv_data *priv, freq_t freq)
{
double Min, VCO, freq4;
int div1n_min, div1n_max;
int p, q, div1n, q_max;
Min = priv->osc_freq;
freq4 = freq*4/kHz(1);
#define vco_min 100e3
#define vco_max 500e3
/*
* Q:2..129
* P:8..2055, best 16..1023 (because of Pump)
For stable operation:
+ REF/Qtotal must not fall below 250kHz (
+ P*(REF/Qtotal) must not be above 400 MHz or below 100 MHz
*/
#if 1
q_max = priv->osc_freq/250;
#else
q_max = 100;
#endif
div1n_min = vco_min/freq4;
if (div1n_min < 2)
div1n_min = 2;
else if (div1n_min > 127)
div1n_min = 127;
div1n_max = vco_max/freq4;
if (div1n_max > 127)
div1n_max = 127;
else if (div1n_max < 2)
div1n_max = 2;
for (div1n = div1n_min; div1n <= div1n_max; div1n++) {
// P/Qtotal = FREQ4*DIV1N/REF
// (Q*int(r) + frac(r)*Q)/Q
for (q = q_max; q >= 2; q--) {
p = q*freq4*div1n/priv->osc_freq;
#if 1
if (p < 16 || p > 1023)
continue;
#endif
VCO = ((double)priv->osc_freq/q)*p;
#if 1
if (VCO < vco_min || VCO > vco_max)
continue;
#endif
if (fabs(freq4-VCO/div1n) < Min) {
Min = fabs(freq4 - VCO/div1n);
priv->Div1N = div1n;
priv->Q = q;
priv->P = p;
}
}
}
VCO = ((double)priv->osc_freq/priv->Q)*priv->P;
if (VCO < vco_min || VCO > 400e3)
rig_debug(RIG_DEBUG_VERBOSE, "%s: Unstable parameters for VCO=%.1f\n",
__FUNCTION__, VCO);
}
#endif /* ORIG_ALGORITHM */
int elektor507_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
{
struct elektor507_priv_data *priv = (struct elektor507_priv_data *)rig->state.priv;
freq_t final_freq;
int Freq;
int ret=0;
int Mux;
#ifdef ORIG_ALGORITHM
int Freq;
#endif
if (priv->ant == ANT_AUTO) {
/* Automatically select appropriate filter */
@ -727,6 +811,7 @@ int elektor507_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
* Compute PLL parameters
*/
#ifdef ORIG_ALGORITHM
Freq = freq / kHz(1);
if (Freq > 19 && Freq < 60)
@ -773,14 +858,17 @@ int elektor507_set_freq(RIG *rig, vfo_t vfo, freq_t freq)
priv->Div1N = 4;
find_P_Q(priv, freq);
}
#else
find_P_Q_DIV1N(priv, freq);
#endif
elektor507_get_freq(rig, vfo, &final_freq);
rig_debug(RIG_DEBUG_VERBOSE, "%s: Freq=%d kHz, delta=%d Hz, Div1N=%d, P=%d, Q=%d\n",
__FUNCTION__, Freq, (int)(final_freq-freq), priv->Div1N, priv->P, priv->Q);
rig_debug(RIG_DEBUG_VERBOSE, "%s: Freq=%.0f kHz, delta=%d Hz, Div1N=%d, P=%d, Q=%d\n",
__FUNCTION__, freq/kHz(1), (int)(final_freq-freq), priv->Div1N, priv->P, priv->Q);
if ((double)priv->osc_freq/priv->Q < 250)
rig_debug(RIG_DEBUG_VERBOSE,
rig_debug(RIG_DEBUG_WARN,
"%s: Unstable parameters for REF/Qtotal=%.1f\n",
__FUNCTION__, (double)priv->osc_freq/priv->Q);
@ -857,7 +945,12 @@ int elektor507_set_ant(RIG * rig, vfo_t vfo, ant_t ant)
priv->FT_port &= 0x63; //0,1 = I2C, 2,3,4=MUX, 5,6=Attenuator
priv->FT_port |= Mux << 2;
#if 0
ret = elektor507_ftdi_write_data(rig, &priv->FT_port, 1);
#else
/* Enable CLOCK3 on demand */
ret = i2c_write_reg(rig, CY_I2C_RAM_ADR, CLKOE_REG, 0x20 | (ant==RIG_ANT_3 ? 0x04 : 0));
#endif
return (ret != 0) ? -RIG_EIO : RIG_OK;
}
@ -870,6 +963,8 @@ static int cy_update_pll(RIG *rig, unsigned char IICadr)
{
struct elektor507_priv_data *priv = (struct elektor507_priv_data *)rig->state.priv;
int P0, R40, R41, R42;
unsigned char Div1N;
unsigned char Clk3_src;
int Pump;
int ret;
@ -900,7 +995,29 @@ static int cy_update_pll(RIG *rig, unsigned char IICadr)
if (ret != 0)
return ret;
ret = i2c_write_reg(rig, IICadr, DIV1_REG, priv->Div1N);
switch (priv->Div1N) {
case 2:
/* Fixed /2 divider option */
Clk3_src = 0x80;
Div1N = 8;
break;
case 3:
/* Fixed /3 divider option */
Clk3_src = 0xc0;
Div1N = 6;
break;
default:
Div1N = priv->Div1N;
Clk3_src = 0x40;
}
ret = i2c_write_reg(rig, IICadr, DIV1_REG, Div1N);
if (ret != 0)
return ret;
/* Set 2 low bits of CLKSRC for CLOCK5. DIV1CLK is set already */
ret = i2c_write_reg(rig, IICadr, CLKSRC_REG+2, Clk3_src|0x07);
if (ret != 0)
return ret;