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 <h_ayguen@web.de>
development
hayati ayguen 2020-09-10 07:33:41 +02:00
parent c7d071e17e
commit 1819a8db99
6 changed files with 113 additions and 5 deletions

View File

@ -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.
*

View File

@ -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

View File

@ -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);

View File

@ -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 */

View File

@ -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;

View File

@ -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)
{