detailed error messages when r82xx_set_pll() fails with verbose flag

* see https://github.com/librtlsdr/librtlsdr/issues/91
* fixed r82xx_is_tuner_locked(): do not report lock,
 when not all necessary PLL registers were set successfully
* shortcut for 'verbose' flag: 'v'

Signed-off-by: hayati ayguen <h_ayguen@web.de>
development
hayati ayguen 2020-09-10 20:32:10 +02:00
parent 7c6b9e05f8
commit 6fc09b8915
4 changed files with 123 additions and 39 deletions

View File

@ -75,6 +75,7 @@ struct r82xx_config {
enum r82xx_chip rafael_chip;
unsigned int max_i2c_msg_len;
int use_predetect;
int verbose;
};
struct r82xx_priv {
@ -94,6 +95,7 @@ struct r82xx_priv {
uint8_t input;
uint8_t last_vco_curr;
int has_lock;
int tuner_pll_set;
int init_done;
int sideband;
int disable_dither;

View File

@ -3028,6 +3028,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
dev->r82xx_c.vco_curr_min = 0xff; /* VCO min/max current for R18/0x12 bits [7:5] in 0 .. 7. use 0xff for default */
dev->r82xx_c.vco_curr_max = 0xff; /* value is inverted: programmed is 7-value, that 0 is lowest current */
dev->r82xx_c.vco_algo = 0x00;
dev->r82xx_c.verbose = 0;
/* dev->softagc.command_thread; */
dev->softagc.agcState = SOFTSTATE_OFF;
@ -4267,9 +4268,10 @@ int rtlsdr_set_opt_string(rtlsdr_dev_t *dev, const char *opts, int verbose)
int ret = 0;
//if (verbose || dev->verbose)
// fprintf(stderr, "\nrtlsdr_set_opt_string(): parsing option '%s'\n", optPart);
if (!strcmp(optPart, "verbose")) {
if (!strcmp(optPart, "verbose") || !strcmp(optPart, "v")) {
fprintf(stderr, "\nrtlsdr_set_opt_string(): parsed option verbose\n");
dev->verbose = verbose = 1;
verbose = ++dev->verbose;
dev->r82xx_c.verbose = verbose;
ret = 0;
}
else if (!strncmp(optPart, "f=", 2)) {

View File

@ -315,7 +315,8 @@ static void check_tuner_pll(rtlsdr_dev_t *dev, int *tuner_unsupported, int *last
int r = rtlsdr_is_tuner_PLL_locked(dev);
/* printf("performed lock check:\n"); */
if (r == 1) {
printf("tuner PLL is unlocked!\n");
if (*last_lock_report != r)
printf("tuner PLL is unlocked!\n");
*last_lock_report = r;
}
else if (r == 0) {

View File

@ -756,26 +756,38 @@ static int r82xx_set_pll_yc(struct r82xx_priv *priv, uint32_t freq)
/* Set the phase splitter */
rc = r82xx_write_reg_mask(priv, 0x10, (uint8_t) (div_num << 5), 0xe0);
if(rc < 0)
if(rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll_yc(): error writing 'phase splitter' into i2c reg 0x10\n");
return rc;
}
/* Disable Dither */
val_dith = (priv->disable_dither) ? 0x10 : 0x00;
rc = r82xx_write_reg_mask(priv, 0x12, val_dith, 0x18);
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll_yc(): error writing 'dither' into i2c reg 0x12\n");
return rc;
}
/* Set the rough VCO frequency */
rc = r82xx_write_reg(priv, 0x14, (uint8_t) (ni + (si << 6)));
if(rc < 0)
if(rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll_yc(): error writing 'rough VCO frequency' into i2c reg 0x14\n");
return rc;
}
if (vco_frac == 0)
{
/* Disable frac pll */
rc = r82xx_write_reg_mask(priv, 0x12, 0x08, 0x08);
if(rc < 0)
if(rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll_yc(): error writing 'disable frac pll' into i2c reg 0x12\n");
return rc;
}
}
else
{
@ -802,30 +814,45 @@ static int r82xx_set_pll_yc(struct r82xx_priv *priv, uint32_t freq)
}
*/
rc = r82xx_write_reg(priv, 0x15, (uint8_t)(sdm & 0xff));
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll_yc(): error writing 'sdm lo' into i2c reg 0x15\n");
return rc;
}
rc = r82xx_write_reg(priv, 0x16, (uint8_t)(sdm >> 8));
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll_yc(): error writing 'sdm hi' into i2c reg 0x16\n");
return rc;
}
/* Enable frac pll */
rc = r82xx_write_reg_mask(priv, 0x12, 0x00, 0x08);
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll_yc(): error writing 'enable frac pll' into i2c reg 0x12\n");
return rc;
}
}
/* all PLL stuff / registers set for this frequency */
priv->tuner_pll_set = 1;
/***/
/* Check if PLL has locked */
rc = r82xx_read(priv, 0x00, data, 3);
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll_yc(): error reading 'pll lock status' from i2c reg 0x00..0x02\n");
return rc;
}
if (!(data[2] & 0x40)) {
#if PRINT_PLL_ERRORS
fprintf(stderr, "[R82XX] PLL not locked at Tuner LO %u Hz for RF %u Hz!\n",
freq, priv->rf_freq);
#endif
if (priv->cfg->verbose || PRINT_PLL_ERRORS)
//fprintf(stderr, "r82xx_set_pll_yc(): error writing 'sdm lo' into i2c reg 0x15\n");
fprintf(stderr, "[R82XX] PLL not locked at Tuner LO %u Hz for RF %u Hz!\n",
freq, priv->rf_freq);
priv->has_lock = 0;
return -1;
}
@ -858,13 +885,18 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
/* devt->r82xx_c.vco_max = 0xff; * value is inverted: programmed is 7-value, that 0 is lowest current */
uint8_t data[5];
priv->tuner_pll_set = 0;
if (priv->cfg->vco_algo == 2)
{
/* r82xx_set_pll_yc() assumes fixed maximum current */
if (priv->last_vco_curr != vco_curr_max) {
rc = r82xx_write_reg_mask(priv, 0x12, vco_curr_max, 0xe0);
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll(): error writing 'vco current' into i2c reg 0x12\n");
return rc;
}
priv->last_vco_curr = vco_curr_max;
}
return r82xx_set_pll_yc(priv, freq);
@ -875,19 +907,28 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
pll_ref = priv->cfg->xtal;
rc = r82xx_write_reg_mask(priv, 0x10, refdiv2, 0x10);
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll(): error writing 'refdiv2' into i2c reg 0x10\n");
return rc;
}
/* set pll autotune = 128kHz */
rc = r82xx_write_reg_mask(priv, 0x1a, 0x00, 0x0c);
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll(): error writing 'pll autotune 128kHz' into i2c reg 0x1a\n");
return rc;
}
/* set VCO current = 100 */
if (priv->last_vco_curr != vco_curr_min) {
rc = r82xx_write_reg_mask(priv, 0x12, vco_curr_min, 0xe0);
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll(): error writing 'vco current min' into i2c reg 0x12\n");
return rc;
}
priv->last_vco_curr = vco_curr_min;
}
@ -911,8 +952,11 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
}
rc = r82xx_read(priv, 0x00, data, sizeof(data));
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll(): error reading 'status' from i2c reg 0x00 .. 0x04\n");
return rc;
}
if (priv->cfg->rafael_chip == CHIP_R828D)
vco_power_ref = 1;
@ -925,8 +969,11 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
div_num = div_num + 1;
rc = r82xx_write_reg_mask(priv, 0x10, div_num << 5, 0xe0);
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll(): error writing 'div_num' into i2c reg 0x10\n");
return rc;
}
vco_freq = (uint64_t)freq * (uint64_t)mix_div;
@ -960,9 +1007,8 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
#endif
if (nint > ((128 / vco_power_ref) - 1)) {
#if PRINT_PLL_ERRORS
fprintf(stderr, "[R82XX] No valid PLL values for %u Hz!\n", freq);
#endif
if (priv->cfg->verbose || PRINT_PLL_ERRORS)
fprintf(stderr, "[R82XX] No valid PLL values for %u Hz!\n", freq);
return -1;
}
@ -970,8 +1016,11 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
si = nint - 4 * ni - 13;
rc = r82xx_write_reg(priv, 0x14, ni + (si << 6));
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll(): error writing 'ni+(si<<6)' into i2c reg 0x14\n");
return rc;
}
/* pw_sdm */
if (sdm == 0)
@ -983,22 +1032,37 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
val |= 0x10;
rc = r82xx_write_reg_mask(priv, 0x12, val, 0x18);
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll(): error writing 'dither' into i2c reg 0x12\n");
return rc;
}
rc = r82xx_write_reg(priv, 0x16, sdm >> 8);
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll(): error writing 'sdm hi' into i2c reg 0x16\n");
return rc;
}
rc = r82xx_write_reg(priv, 0x15, sdm & 0xff);
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll(): error writing 'sdm lo' into i2c reg 0x12\n");
return rc;
}
/* all PLL stuff / registers set for this frequency - except 8 kHz pll autotune */
priv->tuner_pll_set = 1;
for (i = 0; i < 2; i++) {
/* Check if PLL has locked */
rc = r82xx_read(priv, 0x00, data, 3);
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll(): error reading 'pll lock status' from i2c reg 0x00 .. 0x02\n");
return rc;
}
if ( (data[2] & 0x40) || vco_curr_max == vco_curr_min )
break;
@ -1006,18 +1070,20 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
/* Didn't lock. Increase VCO current */
if (priv->last_vco_curr != vco_curr_max) {
rc = r82xx_write_reg_mask(priv, 0x12, vco_curr_max, 0xe0);
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll(): error writing 'vco current max' into i2c reg 0x12\n");
return rc;
}
priv->last_vco_curr = vco_curr_max;
}
}
}
if (!(data[2] & 0x40)) {
#if PRINT_PLL_ERRORS
fprintf(stderr, "[R82XX] PLL not locked at Tuner LO %u Hz for RF %u Hz!\n",
freq, priv->rf_freq);
#endif
if (priv->cfg->verbose || PRINT_PLL_ERRORS)
fprintf(stderr, "[R82XX] PLL not locked at Tuner LO %u Hz for RF %u Hz!\n",
freq, priv->rf_freq);
priv->has_lock = 0;
return -1;
}
@ -1030,6 +1096,8 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
/* set pll autotune = 8kHz */
rc = r82xx_write_reg_mask(priv, 0x1a, 0x08, 0x08);
if (rc < 0 && priv->cfg->verbose)
fprintf(stderr, "r82xx_set_pll(): error writing 'pll autotune 8kHz' into i2c reg 0x1a\n");
return rc;
}
@ -1039,14 +1107,17 @@ int r82xx_is_tuner_locked(struct r82xx_priv *priv)
{
uint8_t data[5];
/* was all PLL stuff set for last frequency? */
if (! priv->tuner_pll_set)
return 1;
/* Check if PLL has locked */
int rc = r82xx_read(priv, 0x00, data, 3);
int rc = r82xx_read(priv, 0x00, data, sizeof(data));
if (rc < 0)
return -3;
if (!(data[2] & 0x40)) {
#if PRINT_PLL_ERRORS
fprintf(stderr, "[R82XX] PLL not locked at check!\n");
#endif
if (priv->cfg->verbose || PRINT_PLL_ERRORS)
fprintf(stderr, "[R82XX] PLL not locked at check!\n");
return 1;
}
return 0;
@ -1166,6 +1237,7 @@ static int r82xx_set_tv_standard(struct r82xx_priv *priv,
if (rc < 0)
return rc;
priv->tuner_pll_set = 0;
rc = r82xx_set_pll(priv, priv->rf_freq);
if (rc < 0 || !priv->has_lock)
return rc;
@ -1813,6 +1885,8 @@ int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq)
uint32_t lo_freq;
uint8_t air_cable1_in;
priv->tuner_pll_set = 0;
if (!freq)
freq = priv->rf_freq; /* ignore zero frequency; keep last one */
else
@ -1831,8 +1905,11 @@ int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq)
#endif
rc = r82xx_set_mux(priv, lo_freq);
if (rc < 0)
if (rc < 0) {
if (priv->cfg->verbose)
fprintf(stderr, "r82xx_set_freq(): error at r82xx_set_mux()\n");
goto err;
}
rc = r82xx_set_pll(priv, lo_freq);
if (rc < 0 || !priv->has_lock)
@ -1848,6 +1925,8 @@ int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq)
(air_cable1_in != priv->input)) {
priv->input = air_cable1_in;
rc = r82xx_write_reg_mask(priv, 0x05, air_cable1_in, 0x60);
if (rc < 0 && priv->cfg->verbose)
fprintf(stderr, "r82xx_set_freq(): error writing R828D's 'input selection' into i2c reg 0x05\n");
}
err: