1
0
Fork 0

Compare commits

...

5 Commits

Author SHA1 Message Date
Sultan Qasim Khan 30996265e2 Add a dummy read to fix intermittent I2C errors
After keeping the I2C repeater always on and removing logic to keep
re-enabling it before every tuner I2C operation, I was occasionally
getting failures for I2C operations when retuning. I don't know why
those intermittent errors were happening, but this seems to fix the
issue. I don't know why this dummy read fixes it, or what reading
from page 0x0A even represents because the datasheet doesn't say
anything about it.
2024-03-07 17:46:07 -05:00
Sultan Qasim Khan f19f7627be Always keep I2C repeater enabled
No harm in that, since every I2C device has its own address. This makes
I2C operations interacting with the tuner much faster, since we don't
need to keep re-enabling and disabling the I2C repeater.
2024-03-07 17:46:07 -05:00
Sultan Qasim Khan cf3420abb4 r82xx: eliminate PLL lock check
In practice it almost always locks, and when it doesn't, raising VCO
current fails to help and it still doesn't lock. While it may be nice to
warn of a lock failure or slow lock, this slows down retuning, and
doesn't really help much. Eliminating the read operation speeds up
retuning considerably.
2024-03-07 17:46:07 -05:00
Sultan Qasim Khan ed335f65c5 r82xx: eliminate vco fine tune check
I don't know how important it is on other tuners, but on my R820T2,
vco_fine_tune is always equal to 2, as is vco_power_ref, so this does
nothing except slow down retuning.
2024-03-07 17:46:07 -05:00
Sultan Qasim Khan 4d5b5cf907 r82xx: keep PLL autotune at 128 kHz
Avoids both the write to make it fast and the write to slow it down,
since the register state is cached.
2024-03-07 17:46:07 -05:00
2 changed files with 17 additions and 75 deletions

View File

@ -572,11 +572,6 @@ void rtlsdr_set_gpio_output(rtlsdr_dev_t *dev, uint8_t gpio)
rtlsdr_write_reg(dev, SYSB, GPOE, r | gpio, 1);
}
void rtlsdr_set_i2c_repeater(rtlsdr_dev_t *dev, int on)
{
rtlsdr_demod_write_reg(dev, 1, 0x01, on ? 0x18 : 0x10, 1);
}
int rtlsdr_set_fir(rtlsdr_dev_t *dev)
{
uint8_t fir[20];
@ -623,9 +618,9 @@ void rtlsdr_init_baseband(rtlsdr_dev_t *dev)
rtlsdr_write_reg(dev, SYSB, DEMOD_CTL_1, 0x22, 1);
rtlsdr_write_reg(dev, SYSB, DEMOD_CTL, 0xe8, 1);
/* reset demod (bit 3, soft_rst) */
rtlsdr_demod_write_reg(dev, 1, 0x01, 0x14, 1);
rtlsdr_demod_write_reg(dev, 1, 0x01, 0x10, 1);
/* reset demod (bit 3, soft_rst) and enable I2C repeater */
rtlsdr_demod_write_reg(dev, 1, 0x01, 0x1C, 1);
rtlsdr_demod_write_reg(dev, 1, 0x01, 0x18, 1);
/* disable spectrum inversion and adjacent channel rejection */
rtlsdr_demod_write_reg(dev, 1, 0x15, 0x00, 1);
@ -672,9 +667,8 @@ int rtlsdr_deinit_baseband(rtlsdr_dev_t *dev)
return -1;
if (dev->tuner && dev->tuner->exit) {
rtlsdr_set_i2c_repeater(dev, 1);
rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1); /* dummy read */
r = dev->tuner->exit(dev); /* deinitialize tuner */
rtlsdr_set_i2c_repeater(dev, 0);
}
/* poweroff demodulator and ADCs */
@ -891,9 +885,8 @@ int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq)
if (dev->direct_sampling) {
r = rtlsdr_set_if_freq(dev, freq);
} else if (dev->tuner && dev->tuner->set_freq) {
rtlsdr_set_i2c_repeater(dev, 1);
rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1); /* dummy read */
r = dev->tuner->set_freq(dev, freq - dev->offs_freq);
rtlsdr_set_i2c_repeater(dev, 0);
}
if (!r)
@ -1015,9 +1008,8 @@ int rtlsdr_set_tuner_bandwidth(rtlsdr_dev_t *dev, uint32_t bw)
return -1;
if (dev->tuner->set_bw) {
rtlsdr_set_i2c_repeater(dev, 1);
rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1); /* dummy read */
r = dev->tuner->set_bw(dev, bw > 0 ? bw : dev->rate);
rtlsdr_set_i2c_repeater(dev, 0);
if (r)
return r;
dev->bw = bw;
@ -1033,9 +1025,8 @@ int rtlsdr_set_tuner_gain(rtlsdr_dev_t *dev, int gain)
return -1;
if (dev->tuner->set_gain) {
rtlsdr_set_i2c_repeater(dev, 1);
rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1); /* dummy read */
r = dev->tuner->set_gain((void *)dev, gain);
rtlsdr_set_i2c_repeater(dev, 0);
}
if (!r)
@ -1062,9 +1053,8 @@ int rtlsdr_set_tuner_if_gain(rtlsdr_dev_t *dev, int stage, int gain)
return -1;
if (dev->tuner->set_if_gain) {
rtlsdr_set_i2c_repeater(dev, 1);
rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1); /* dummy read */
r = dev->tuner->set_if_gain(dev, stage, gain);
rtlsdr_set_i2c_repeater(dev, 0);
}
return r;
@ -1078,9 +1068,8 @@ int rtlsdr_set_tuner_gain_mode(rtlsdr_dev_t *dev, int mode)
return -1;
if (dev->tuner->set_gain_mode) {
rtlsdr_set_i2c_repeater(dev, 1);
rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1); /* dummy read */
r = dev->tuner->set_gain_mode((void *)dev, mode);
rtlsdr_set_i2c_repeater(dev, 0);
}
return r;
@ -1115,9 +1104,8 @@ int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t samp_rate)
dev->rate = (uint32_t)real_rate;
if (dev->tuner && dev->tuner->set_bw) {
rtlsdr_set_i2c_repeater(dev, 1);
rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1); /* dummy read */
dev->tuner->set_bw(dev, dev->bw > 0 ? dev->bw : dev->rate);
rtlsdr_set_i2c_repeater(dev, 0);
}
tmp = (rsamp_ratio >> 16);
@ -1127,9 +1115,9 @@ int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t samp_rate)
r |= rtlsdr_set_sample_freq_correction(dev, dev->corr);
/* reset demod (bit 3, soft_rst) */
r |= rtlsdr_demod_write_reg(dev, 1, 0x01, 0x14, 1);
r |= rtlsdr_demod_write_reg(dev, 1, 0x01, 0x10, 1);
/* reset demod (bit 3, soft_rst) and enable I2C repeater */
r |= rtlsdr_demod_write_reg(dev, 1, 0x01, 0x1C, 1);
r |= rtlsdr_demod_write_reg(dev, 1, 0x01, 0x18, 1);
/* recalculate offset frequency if offset tuning is enabled */
if (dev->offs_freq)
@ -1171,9 +1159,8 @@ int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on)
if (on) {
if (dev->tuner && dev->tuner->exit) {
rtlsdr_set_i2c_repeater(dev, 1);
rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1); /* dummy read */
r = dev->tuner->exit(dev);
rtlsdr_set_i2c_repeater(dev, 0);
}
/* disable Zero-IF mode */
@ -1192,9 +1179,8 @@ int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on)
dev->direct_sampling = on;
} else {
if (dev->tuner && dev->tuner->init) {
rtlsdr_set_i2c_repeater(dev, 1);
rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1); /* dummy read */
r |= dev->tuner->init(dev);
rtlsdr_set_i2c_repeater(dev, 0);
}
if ((dev->tuner_type == RTLSDR_TUNER_R820T) ||
@ -1253,7 +1239,6 @@ int rtlsdr_set_offset_tuning(rtlsdr_dev_t *dev, int on)
r |= rtlsdr_set_if_freq(dev, dev->offs_freq);
if (dev->tuner && dev->tuner->set_bw) {
rtlsdr_set_i2c_repeater(dev, 1);
if (on) {
bw = 2 * dev->offs_freq;
} else if (dev->bw > 0) {
@ -1261,8 +1246,8 @@ int rtlsdr_set_offset_tuning(rtlsdr_dev_t *dev, int on)
} else {
bw = dev->rate;
}
rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1); /* dummy read */
dev->tuner->set_bw(dev, bw);
rtlsdr_set_i2c_repeater(dev, 0);
}
if (dev->freq > dev->offs_freq)
@ -1544,8 +1529,6 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
r = rtlsdr_get_usb_strings(dev, dev->manufact, dev->product, NULL);
/* Probe tuners */
rtlsdr_set_i2c_repeater(dev, 1);
reg = rtlsdr_i2c_read_reg(dev, E4K_I2C_ADDR, E4K_CHECK_ADDR);
if (reg == E4K_CHECK_VAL) {
fprintf(stderr, "Found Elonics E4000 tuner\n");
@ -1637,8 +1620,6 @@ found:
if (dev->tuner->init)
r = dev->tuner->init(dev);
rtlsdr_set_i2c_repeater(dev, 0);
*out_dev = dev;
return 0;

View File

@ -464,8 +464,7 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
uint8_t div_num = 0;
uint8_t vco_power_ref = 2;
uint8_t refdiv2 = 0;
uint8_t ni, si, nint, vco_fine_tune, val;
uint8_t data[5];
uint8_t ni, si, nint, val;
uint8_t regs[7];
/* Frequency in kHz */
@ -499,20 +498,9 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
mix_div = mix_div << 1;
}
rc = r82xx_read(priv, 0x00, data, sizeof(data));
if (rc < 0)
return rc;
if (priv->cfg->rafael_chip == CHIP_R828D)
vco_power_ref = 1;
vco_fine_tune = (data[4] & 0x30) >> 4;
if (vco_fine_tune > vco_power_ref)
div_num = div_num - 1;
else if (vco_fine_tune < vco_power_ref)
div_num = div_num + 1;
regs[0] = mask_reg8(regs[0], div_num << 5, 0xe0);
vco_freq = (uint64_t)freq * (uint64_t)mix_div;
@ -560,35 +548,8 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
if (rc < 0)
return rc;
for (i = 0; i < 2; i++) {
// usleep_range(sleep_time, sleep_time + 1000);
/* Check if PLL has locked */
rc = r82xx_read(priv, 0x00, data, 3);
if (rc < 0)
return rc;
if (data[2] & 0x40)
break;
if (!i) {
/* Didn't lock. Increase VCO current */
rc = r82xx_write_reg_mask(priv, 0x12, 0x60, 0xe0);
if (rc < 0)
return rc;
}
}
if (!(data[2] & 0x40)) {
fprintf(stderr, "[R82XX] PLL not locked!\n");
priv->has_lock = 0;
return 0;
}
priv->has_lock = 1;
/* set pll autotune = 8kHz */
rc = r82xx_write_reg_mask(priv, 0x1a, 0x08, 0x08);
return rc;
}