From 1819a8db997a086755865411dff76e588f66c507 Mon Sep 17 00:00:00 2001 From: hayati ayguen Date: Thu, 10 Sep 2020 07:33:41 +0200 Subject: [PATCH] bugfix for vco options, added rtlsdr_is_tuner_PLL_locked() to API * bugfix for vco options: moved init of vco variables: parsed options got overwritten at r820t_init(). see https://github.com/librtlsdr/librtlsdr/issues/91 * added IS_TUNER_PLL_LOCKED (=0x55) command to rtl_tcp protocol * rtl_tcp is checking rtlsdr_is_tuner_PLL_locked() automatically every 3 seconds - when idle: https://github.com/librtlsdr/librtlsdr/issues/91#issuecomment-689830755 Signed-off-by: hayati ayguen --- include/rtl-sdr.h | 15 +++++++++++++++ include/rtl_tcp.h | 3 ++- include/tuner_r82xx.h | 1 + src/librtlsdr.c | 32 ++++++++++++++++++++++++++++---- src/rtl_tcp.c | 43 +++++++++++++++++++++++++++++++++++++++++++ src/tuner_r82xx.c | 24 ++++++++++++++++++++++++ 6 files changed, 113 insertions(+), 5 deletions(-) diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h index f24f6a8..6bf71f4 100755 --- a/include/rtl-sdr.h +++ b/include/rtl-sdr.h @@ -172,6 +172,20 @@ RTLSDR_API int rtlsdr_read_eeprom(rtlsdr_dev_t *dev, uint8_t *data, */ RTLSDR_API int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq); +/*! + * Check, if tuner PLL (frequency) is still locked. + * Tuner/PLL might loose lock (at high frequencies), + * e.g. for temperature reasons + * + * \param dev the device handle given by rtlsdr_open() + * \return 1: PLL is NOT locked + * \return 0: PLL HAS lock + * \return < 0: if device handle is invalid or some other error + * \return -2: not supported for devices' tuner + */ +RTLSDR_API int rtlsdr_is_tuner_PLL_locked(rtlsdr_dev_t *dev); + + /*! * Get actual frequency the device is tuned to. * @@ -180,6 +194,7 @@ RTLSDR_API int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq); */ RTLSDR_API uint32_t rtlsdr_get_center_freq(rtlsdr_dev_t *dev); + /*! * Set the frequency correction value for the device. * diff --git a/include/rtl_tcp.h b/include/rtl_tcp.h index 8182df0..81659de 100644 --- a/include/rtl_tcp.h +++ b/include/rtl_tcp.h @@ -75,7 +75,8 @@ enum RTL_TCP_COMMANDS { GPIO_WRITE_PIN = 0x52, /* rtlsdr_set_gpio_output() and rtlsdr_set_gpio_bit() */ GPIO_READ_PIN = 0x53, /* rtlsdr_get_gpio_bit() */ GPIO_GET_BYTE = 0x54, /* rtlsdr_get_gpio_byte() */ - + + IS_TUNER_PLL_LOCKED = 0x55, /* rtlsdr_is_tuner_PLL_locked() */ }; #ifdef __cplusplus diff --git a/include/tuner_r82xx.h b/include/tuner_r82xx.h index 3781662..ab00ea2 100755 --- a/include/tuner_r82xx.h +++ b/include/tuner_r82xx.h @@ -149,6 +149,7 @@ enum r82xx_delivery_system { int r82xx_standby(struct r82xx_priv *priv); int r82xx_init(struct r82xx_priv *priv); int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq); +int r82xx_is_tuner_locked(struct r82xx_priv *priv); int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain, int extended_mode, int lna_gain, int mixer_gain, int vga_gain, int *rtl_vga_control); int r82xx_get_rf_gain(struct r82xx_priv *priv); int r82xx_get_if_gain(struct r82xx_priv *priv); diff --git a/src/librtlsdr.c b/src/librtlsdr.c index dee9805..86a3d16 100644 --- a/src/librtlsdr.c +++ b/src/librtlsdr.c @@ -381,10 +381,6 @@ int r820t_init(void *dev) { devt->r82xx_c.rafael_chip = CHIP_R820T; } - devt->r82xx_c.vco_curr_min = 0xff; /* VCO min/max current for R18/0x12 bits [7:5] in 0 .. 7. use 0xff for default */ - devt->r82xx_c.vco_curr_max = 0xff; /* value is inverted: programmed is 7-value, that 0 is lowest current */ - devt->r82xx_c.vco_algo = 0x00; - rtlsdr_get_xtal_freq(devt, NULL, &devt->r82xx_c.xtal); devt->r82xx_c.max_i2c_msg_len = 8; @@ -1457,6 +1453,29 @@ int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq) return r; } + +int rtlsdr_is_tuner_PLL_locked(rtlsdr_dev_t *dev) +{ + int r = -1; + + #if LOG_API_CALLS && LOG_API_SET_FREQ + fprintf(stderr, "LOG: rtlsdr_is_tuner_PLL_locked()\n"); + #endif + + if (!dev || !dev->tuner) + return -1; + + if (dev->tuner_type != RTLSDR_TUNER_R820T && dev->tuner_type != RTLSDR_TUNER_R828D ) + return -2; + + rtlsdr_set_i2c_repeater(dev, 1); + r = r82xx_is_tuner_locked(&dev->r82xx_p); + rtlsdr_set_i2c_repeater(dev, 0); + + return r; +} + + uint32_t rtlsdr_get_center_freq(rtlsdr_dev_t *dev) { #ifdef _ENABLE_RPC @@ -3005,6 +3024,11 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) dev->gpio_state = 0; dev->called_set_opt = 0; + /* fprintf(stderr, "\n*********************************\ninit/overwrite tuner VCO settings\n"); */ + 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->softagc.command_thread; */ dev->softagc.agcState = SOFTSTATE_OFF; dev->softagc.softAgcMode = SOFTAGC_OFF; /* SOFTAGC_FREQ_CHANGE SOFTAGC_ATTEN SOFTAGC_ALL */ diff --git a/src/rtl_tcp.c b/src/rtl_tcp.c index 41d5f0d..47e9d89 100644 --- a/src/rtl_tcp.c +++ b/src/rtl_tcp.c @@ -310,6 +310,30 @@ static int set_gain_by_index(rtlsdr_dev_t *_dev, unsigned int index) return res; } +static void check_tuner_pll(rtlsdr_dev_t *dev, int *tuner_unsupported) +{ + int r = rtlsdr_is_tuner_PLL_locked(dev); + /* printf("performed lock check:\n"); */ + if (r == 1) + printf("tuner PLL is unlocked!\n"); +#if 0 + else if (r == 0) + printf("tuner PLL is locked.\n"); +#endif + else if (r == -2) { + printf("error at PLL-locked check: tuner not supported! No further tests.\n"); + *tuner_unsupported = 1; + } + else if (r < 0) + printf("error checking tuner PLL!\n"); + else + printf("unknown error at tuner PLL check!\n"); + fflush(stdout); +} + + + + #ifdef _WIN32 #define __attribute__(x) #pragma pack(push, 1) @@ -327,6 +351,8 @@ static void *command_worker(void *arg) fd_set readfds; struct command cmd={0, 0}; struct timeval tv= {1, 0}; + unsigned tuner_check_timeout = 0; + int tuner_unsupported = 0; int r = 0; uint32_t tmp; int32_t itmp; @@ -344,6 +370,19 @@ static void *command_worker(void *arg) if(r) { received = recv(s, (char*)&cmd+(sizeof(cmd)-left), left, 0); left -= received; + /* printf("received %d bytes\n", received); */ + } + else if (!tuner_unsupported) + { + /* timeout: nothing happend */ + ++tuner_check_timeout; + if (tuner_check_timeout >= 3) + { + /* automatic check every 3 seconds */ + check_tuner_pll(dev, &tuner_unsupported); + tuner_check_timeout = 0; + } + fflush(stdout); } if(received == SOCKET_ERROR || do_exit) { printf("comm recv bye\n"); @@ -572,6 +611,10 @@ static void *command_worker(void *arg) (iitmp >>7) & 1, (iitmp >>6) & 1, (iitmp >>5) & 1, (iitmp >>4) & 1, (iitmp >>3) & 1, (iitmp >>2) & 1, (iitmp >>1) & 1, iitmp & 1 ); break; + case IS_TUNER_PLL_LOCKED: + check_tuner_pll(dev, &tuner_unsupported); + tuner_check_timeout = 0; + break; default: printf("unknown command 0x%02x\n", cmd.cmd); break; diff --git a/src/tuner_r82xx.c b/src/tuner_r82xx.c index 938b7d1..2c6085c 100644 --- a/src/tuner_r82xx.c +++ b/src/tuner_r82xx.c @@ -891,6 +891,11 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq) priv->last_vco_curr = vco_curr_min; } +#if 0 + fprintf(stderr, "vco_last = 0x%02x; vcocmin << 5 = 0x%02x; vcocmax << 5 = 0x%02x\n", + (unsigned)priv->last_vco_curr, (unsigned)vco_curr_min, (unsigned)vco_curr_max); +#endif + /* Calculate divider */ while (mix_div <= 64) { if (((freq_khz * mix_div) >= vco_min) && @@ -1029,6 +1034,25 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq) return rc; } + +int r82xx_is_tuner_locked(struct r82xx_priv *priv) +{ + uint8_t data[5]; + + /* Check if PLL has locked */ + int rc = r82xx_read(priv, 0x00, data, 3); + if (rc < 0) + return -3; + if (!(data[2] & 0x40)) { +#if PRINT_PLL_ERRORS + fprintf(stderr, "[R82XX] PLL not locked at check!\n"); +#endif + return 1; + } + return 0; +} + + static int r82xx_sysfreq_sel(struct r82xx_priv *priv, enum r82xx_tuner_type type) {