forked from sdr/rtl-sdr
Compare commits
8 Commits
master
...
fast_retun
Author | SHA1 | Date |
---|---|---|
Sultan Qasim Khan | 30996265e2 | |
Sultan Qasim Khan | f19f7627be | |
Sultan Qasim Khan | cf3420abb4 | |
Sultan Qasim Khan | ed335f65c5 | |
Sultan Qasim Khan | 4d5b5cf907 | |
Sultan Qasim Khan | 2acb75cff3 | |
Sultan Qasim Khan | 0b64f07fd5 | |
Oliver Jowett | f5978e8871 |
|
@ -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;
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "rtlsdr_i2c.h"
|
||||
#include "tuner_r82xx.h"
|
||||
|
@ -243,6 +244,7 @@ static void shadow_store(struct r82xx_priv *priv, uint8_t reg, const uint8_t *va
|
|||
|
||||
if (r < 0) {
|
||||
len += r;
|
||||
val -= r;
|
||||
r = 0;
|
||||
}
|
||||
if (len <= 0)
|
||||
|
@ -253,11 +255,29 @@ static void shadow_store(struct r82xx_priv *priv, uint8_t reg, const uint8_t *va
|
|||
memcpy(&priv->regs[r], val, len);
|
||||
}
|
||||
|
||||
static bool shadow_equal(struct r82xx_priv *priv, uint8_t reg, const uint8_t *val,
|
||||
int len)
|
||||
{
|
||||
int r = reg - REG_SHADOW_START;
|
||||
|
||||
if (r < 0 || len < 0 || len > NUM_REGS - r)
|
||||
return false;
|
||||
|
||||
if (memcmp(&priv->regs[r], val, len) == 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int r82xx_write(struct r82xx_priv *priv, uint8_t reg, const uint8_t *val,
|
||||
unsigned int len)
|
||||
{
|
||||
int rc, size, pos = 0;
|
||||
|
||||
/* Avoid setting registers unnecessarily since it's slow */
|
||||
if (shadow_equal(priv, reg, val, len))
|
||||
return 0;
|
||||
|
||||
/* Store the shadow registers */
|
||||
shadow_store(priv, reg, val, len);
|
||||
|
||||
|
@ -424,43 +444,45 @@ static int r82xx_set_mux(struct r82xx_priv *priv, uint32_t freq)
|
|||
return rc;
|
||||
}
|
||||
|
||||
static inline uint8_t mask_reg8(uint8_t reg, uint8_t val, uint8_t mask)
|
||||
{
|
||||
return (reg & ~mask) | (val & mask);
|
||||
}
|
||||
|
||||
static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
|
||||
{
|
||||
int rc, i;
|
||||
unsigned sleep_time = 10000;
|
||||
uint64_t vco_freq;
|
||||
uint32_t vco_fra; /* VCO contribution by SDM (kHz) */
|
||||
uint32_t vco_min = 1770000;
|
||||
uint32_t vco_max = vco_min * 2;
|
||||
uint32_t freq_khz, pll_ref, pll_ref_khz;
|
||||
uint16_t n_sdm = 2;
|
||||
uint16_t sdm = 0;
|
||||
uint64_t vco_div;
|
||||
uint32_t vco_min = 1770000; /* kHz */
|
||||
uint32_t vco_max = vco_min * 2; /* kHz */
|
||||
uint32_t freq_khz, pll_ref;
|
||||
uint32_t sdm = 0;
|
||||
uint8_t mix_div = 2;
|
||||
uint8_t div_buf = 0;
|
||||
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 */
|
||||
freq_khz = (freq + 500) / 1000;
|
||||
pll_ref = priv->cfg->xtal;
|
||||
pll_ref_khz = (priv->cfg->xtal + 500) / 1000;
|
||||
|
||||
rc = r82xx_write_reg_mask(priv, 0x10, refdiv2, 0x10);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* set pll autotune = 128kHz */
|
||||
rc = r82xx_write_reg_mask(priv, 0x1a, 0x00, 0x0c);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* regs 0x10 to 0x16 */
|
||||
memcpy(regs, &priv->regs[0x10 - REG_SHADOW_START], 7);
|
||||
|
||||
regs[0] = mask_reg8(regs[0], refdiv2, 0x10);
|
||||
|
||||
/* set VCO current = 100 */
|
||||
rc = r82xx_write_reg_mask(priv, 0x12, 0x80, 0xe0);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
regs[2] = mask_reg8(regs[2], 0x80, 0xe0);
|
||||
|
||||
/* Calculate divider */
|
||||
while (mix_div <= 64) {
|
||||
|
@ -476,27 +498,30 @@ 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;
|
||||
|
||||
rc = r82xx_write_reg_mask(priv, 0x10, div_num << 5, 0xe0);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
regs[0] = mask_reg8(regs[0], div_num << 5, 0xe0);
|
||||
|
||||
vco_freq = (uint64_t)freq * (uint64_t)mix_div;
|
||||
nint = vco_freq / (2 * pll_ref);
|
||||
vco_fra = (vco_freq - 2 * pll_ref * nint) / 1000;
|
||||
|
||||
/* We want to approximate:
|
||||
* vco_freq / (2 * pll_ref)
|
||||
*
|
||||
* in the form:
|
||||
* nint + sdm/65536
|
||||
*
|
||||
* where nint,sdm are integers and 0 < nint, 0 <= sdm < 65536
|
||||
*
|
||||
* Scaling to fixed point and rounding:
|
||||
*
|
||||
* vco_div = 65536*(nint + sdm/65536) = int( 0.5 + 65536 * vco_freq / (2 * pll_ref) )
|
||||
* vco_div = 65536*nint + sdm = int( (pll_ref + 65536 * vco_freq) / (2 * pll_ref) )
|
||||
*/
|
||||
|
||||
vco_div = (pll_ref + 65536 * vco_freq) / (2 * pll_ref);
|
||||
nint = (uint32_t) (vco_div / 65536);
|
||||
sdm = (uint32_t) (vco_div % 65536);
|
||||
|
||||
if (nint > ((128 / vco_power_ref) - 1)) {
|
||||
fprintf(stderr, "[R82XX] No valid PLL values for %u Hz!\n", freq);
|
||||
|
@ -506,67 +531,25 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
|
|||
ni = (nint - 13) / 4;
|
||||
si = nint - 4 * ni - 13;
|
||||
|
||||
rc = r82xx_write_reg(priv, 0x14, ni + (si << 6));
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
regs[4] = ni + (si << 6);
|
||||
|
||||
/* pw_sdm */
|
||||
if (!vco_fra)
|
||||
if (sdm == 0)
|
||||
val = 0x08;
|
||||
else
|
||||
val = 0x00;
|
||||
|
||||
rc = r82xx_write_reg_mask(priv, 0x12, val, 0x08);
|
||||
regs[2] = mask_reg8(regs[2], val, 0x08);
|
||||
|
||||
regs[5] = sdm & 0xff;
|
||||
regs[6] = sdm >> 8;
|
||||
|
||||
rc = r82xx_write(priv, 0x10, regs, 7);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
/* sdm calculator */
|
||||
while (vco_fra > 1) {
|
||||
if (vco_fra > (2 * pll_ref_khz / n_sdm)) {
|
||||
sdm = sdm + 32768 / (n_sdm / 2);
|
||||
vco_fra = vco_fra - 2 * pll_ref_khz / n_sdm;
|
||||
if (n_sdm >= 0x8000)
|
||||
break;
|
||||
}
|
||||
n_sdm <<= 1;
|
||||
}
|
||||
|
||||
rc = r82xx_write_reg(priv, 0x16, sdm >> 8);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
rc = r82xx_write_reg(priv, 0x15, sdm & 0xff);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1317,6 +1300,7 @@ int r82xx_init(struct r82xx_priv *priv)
|
|||
priv->xtal_cap_sel = XTAL_HIGH_CAP_0P;
|
||||
|
||||
/* Initialize registers */
|
||||
memset(priv->regs, 0, NUM_REGS);
|
||||
rc = r82xx_write(priv, 0x05,
|
||||
r82xx_init_array, sizeof(r82xx_init_array));
|
||||
|
||||
|
|
Loading…
Reference in New Issue