From 43c4028b00b25fbe2de9ca108d389f752f112eae Mon Sep 17 00:00:00 2001 From: hayati ayguen Date: Thu, 1 Sep 2016 01:06:48 +0200 Subject: [PATCH] direct sampling mode switching depending on center_frequency added API function rtlsdr_set_ds_mode(dev, enum rtlsdr_ds_mode, freq_threshold) added CLI option '-D' to rtl_(fm|power|tcp) for mode and threshold frequency Signed-off-by: hayati ayguen --- include/rtl-sdr.h | 19 +++++++++++++++ src/librtlsdr.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++ src/rtl_fm.c | 16 ++++++++++++- src/rtl_power.c | 19 +++++++++++++-- src/rtl_tcp.c | 16 ++++++++++++- 5 files changed, 125 insertions(+), 4 deletions(-) diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h index 16c0924..c99bdb1 100755 --- a/include/rtl-sdr.h +++ b/include/rtl-sdr.h @@ -342,6 +342,25 @@ RTLSDR_API int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on); */ RTLSDR_API int rtlsdr_get_direct_sampling(rtlsdr_dev_t *dev); +enum rtlsdr_ds_mode { + RTLSDR_DS_IQ = 0, /* I/Q quadrature sampling of tuner output */ + RTLSDR_DS_I, /* 1: direct sampling on I branch: usually not connected */ + RTLSDR_DS_Q, /* 2: direct sampling on Q branch: HF on rtl-sdr v3 dongle */ + RTLSDR_DS_I_BELOW, /* 3: direct sampling on I branch when frequency below 'DS threshold frequency' */ + RTLSDR_DS_Q_BELOW /* 4: direct sampling on Q branch when frequency below 'DS threshold frequency' */ +}; + +/*! + * Set direct sampling mode with threshold + * + * \param dev the device handle given by rtlsdr_open() + * \param mode static modes 0 .. 2 as in rtlsdr_set_direct_sampling(). other modes do automatic switching + * \param freq_threshold direct sampling is used below this frequency, else quadrature mode through tuner + * set 0 for using default setting per tuner - not fully implemented yet! + * \return negative on error, 0 on success + */ +RTLSDR_API int rtlsdr_set_ds_mode(rtlsdr_dev_t *dev, enum rtlsdr_ds_mode mode, uint32_t freq_threshold); + /*! * Enable or disable offset tuning for zero-IF tuners, which allows to avoid * problems caused by the DC offset of the ADCs and 1/f noise. diff --git a/src/librtlsdr.c b/src/librtlsdr.c index 005d68a..06d2495 100644 --- a/src/librtlsdr.c +++ b/src/librtlsdr.c @@ -119,6 +119,8 @@ struct rtlsdr_dev { uint32_t offs_freq; /* Hz */ int corr; /* ppm */ int gain; /* tenth dB */ + enum rtlsdr_ds_mode direct_sampling_mode; + uint32_t direct_sampling_threshold; /* Hz */ struct e4k_state e4k_s; struct r82xx_config r82xx_c; struct r82xx_priv r82xx_p; @@ -131,6 +133,7 @@ struct rtlsdr_dev { void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val); static int rtlsdr_set_if_freq(rtlsdr_dev_t *dev, uint32_t freq); +static int rtlsdr_update_ds(rtlsdr_dev_t *dev, uint32_t freq); /* generic tuner interface functions, shall be moved to the tuner implementations */ int e4000_init(void *dev) { @@ -997,6 +1000,9 @@ int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq) if (!dev || !dev->tuner) return -1; + if (dev->direct_sampling_mode > RTLSDR_DS_Q) + rtlsdr_update_ds(dev, freq); + if (dev->direct_sampling) { r = rtlsdr_set_if_freq(dev, freq); } else if (dev->tuner && dev->tuner->set_freq) { @@ -1486,6 +1492,59 @@ int rtlsdr_get_direct_sampling(rtlsdr_dev_t *dev) return dev->direct_sampling; } +int rtlsdr_set_ds_mode(rtlsdr_dev_t *dev, enum rtlsdr_ds_mode mode, uint32_t freq_threshold) +{ + if (!dev) + return -1; + + uint32_t center_freq = rtlsdr_get_center_freq(dev); + if ( !center_freq ) + return -2; + + if (!freq_threshold) { + switch(dev->tuner_type) { + default: + case RTLSDR_TUNER_UNKNOWN: freq_threshold = 28800000; break; /* no idea!!! */ + case RTLSDR_TUNER_E4000: freq_threshold = 50*1000000; break; /* E4K_FLO_MIN_MHZ */ + case RTLSDR_TUNER_FC0012: freq_threshold = 28800000; break; /* no idea!!! */ + case RTLSDR_TUNER_FC0013: freq_threshold = 28800000; break; /* no idea!!! */ + case RTLSDR_TUNER_FC2580: freq_threshold = 28800000; break; /* no idea!!! */ + case RTLSDR_TUNER_R820T: freq_threshold = 24000000; break; /* ~ */ + case RTLSDR_TUNER_R828D: freq_threshold = 28800000; break; /* no idea!!! */ + } + } + + dev->direct_sampling_mode = mode; + dev->direct_sampling_threshold = freq_threshold; + + if (mode <= RTLSDR_DS_Q) + rtlsdr_set_direct_sampling(dev, mode); + + return rtlsdr_set_center_freq(dev, center_freq); +} + +static int rtlsdr_update_ds(rtlsdr_dev_t *dev, uint32_t freq) +{ + int curr_ds = rtlsdr_get_direct_sampling(dev); + if ( curr_ds < 0 ) + return -1; + + int new_ds = 0; + switch (dev->direct_sampling_mode) { + default: + case RTLSDR_DS_IQ: break; + case RTLSDR_DS_I: new_ds = 1; break; + case RTLSDR_DS_Q: new_ds = 2; break; + case RTLSDR_DS_I_BELOW: new_ds = (freq < dev->direct_sampling_threshold) ? 1 : 0; break; + case RTLSDR_DS_Q_BELOW: new_ds = (freq < dev->direct_sampling_threshold) ? 2 : 0; break; + } + + if ( curr_ds != new_ds ) + return rtlsdr_set_direct_sampling(dev, new_ds); + + return 0; +} + int rtlsdr_set_offset_tuning(rtlsdr_dev_t *dev, int on) { int r = 0; diff --git a/src/rtl_fm.c b/src/rtl_fm.c index ed0285d..872a32b 100644 --- a/src/rtl_fm.c +++ b/src/rtl_fm.c @@ -209,6 +209,8 @@ void usage(void) "\t[-s sample_rate (default: 24k)]\n" "\t[-d device_index (default: 0)]\n" "\t[-T enable bias-T on GPIO PIN 0 (works for rtl-sdr.com v3 dongles)]\n" + "\t[-D direct_sampling_mode (default: 0, 1 = I, 2 = Q, 3 = I below threshold, 4 = Q below threshold)]\n" + "\t[-D direct_sampling_threshold_frequency (default: 0 use tuner specific frequency threshold for 3 and 4)]\n" "\t[-g tuner_gain (default: automatic)]\n" "\t[-w tuner_bandwidth (default: automatic. enables offset tuning)]\n" "\t[-l squelch_level (default: 0/off)]\n" @@ -1166,6 +1168,8 @@ int main(int argc, char **argv) int dev_given = 0; int custom_ppm = 0; int enable_biastee = 0; + enum rtlsdr_ds_mode ds_mode = RTLSDR_DS_IQ; + uint32_t ds_temp, ds_threshold = 0; int timeConstant = 75; /* default: U.S. 75 uS */ int rtlagc = 0; dongle_init(&dongle); @@ -1173,7 +1177,7 @@ int main(int argc, char **argv) output_init(&output); controller_init(&controller); - while ((opt = getopt(argc, argv, "d:f:g:s:b:l:L:o:t:r:p:E:q:F:A:M:c:h:w:Tv")) != -1) { + while ((opt = getopt(argc, argv, "d:f:g:s:b:l:L:o:t:r:p:E:q:F:A:M:c:h:w:D:Tv")) != -1) { switch (opt) { case 'd': dongle.dev_index = verbose_device_search(optarg); @@ -1289,6 +1293,13 @@ int main(int argc, char **argv) case 'T': enable_biastee = 1; break; + case 'D': + ds_temp = (uint32_t)( atofs(optarg) + 0.5 ); + if (ds_temp <= RTLSDR_DS_Q_BELOW) + ds_mode = (enum rtlsdr_ds_mode)ds_temp; + else + ds_threshold = ds_temp; + break; case 'v': ++verbosity; break; @@ -1375,6 +1386,9 @@ int main(int argc, char **argv) verbose_ppm_set(dongle.dev, dongle.ppm_error); + /* Set direct sampling with threshold */ + rtlsdr_set_ds_mode(dongle.dev, ds_mode, ds_threshold); + verbose_set_bandwidth(dongle.dev, dongle.bandwidth); if (verbosity && dongle.bandwidth) diff --git a/src/rtl_power.c b/src/rtl_power.c index 1b785be..6e48d61 100644 --- a/src/rtl_power.c +++ b/src/rtl_power.c @@ -137,6 +137,8 @@ void usage(void) "\t[-g tuner_gain (default: automatic)]\n" "\t[-p ppm_error (default: 0)]\n" "\t[-T enable bias-T on GPIO PIN 0 (works for rtl-sdr.com v3 dongles)]\n" + "\t[-D direct_sampling_mode (default: 0, 1 = I, 2 = Q, 3 = I below threshold, 4 = Q below threshold)]\n" + "\t[-D direct_sampling_threshold_frequency (default: 0 use tuner specific frequency threshold for 3 and 4)]\n" "\tfilename (a '-' dumps samples to stdout)\n" "\t (omitting the filename also uses stdout)\n" "\n" @@ -776,6 +778,8 @@ int main(int argc, char **argv) int direct_sampling = 0; int offset_tuning = 0; int enable_biastee = 0; + enum rtlsdr_ds_mode ds_mode = RTLSDR_DS_IQ; + uint32_t ds_temp, ds_threshold = 0; double crop = 0.0; char *freq_optarg; time_t next_tick; @@ -786,7 +790,7 @@ int main(int argc, char **argv) double (*window_fn)(int, int) = rectangle; freq_optarg = ""; - while ((opt = getopt(argc, argv, "f:i:s:t:d:g:p:e:w:c:F:1PDOTh")) != -1) { + while ((opt = getopt(argc, argv, "f:i:s:t:d:g:p:e:w:c:F:D:1POTh")) != -1) { switch (opt) { case 'f': // lower:upper:bin_size freq_optarg = strdup(optarg); @@ -845,7 +849,15 @@ int main(int argc, char **argv) peak_hold = 1; break; case 'D': - direct_sampling = 1; + if(!optarg) { + direct_sampling = 1; + } else { + ds_temp = (uint32_t)( atofs(optarg) + 0.5 ); + if (ds_temp <= RTLSDR_DS_Q_BELOW) + ds_mode = (enum rtlsdr_ds_mode)ds_temp; + else + ds_threshold = ds_temp; + } break; case 'O': offset_tuning = 1; @@ -919,6 +931,9 @@ int main(int argc, char **argv) verbose_direct_sampling(dev, 1); } + /* Set direct sampling with threshold */ + rtlsdr_set_ds_mode(dev, ds_mode, ds_threshold); + if (offset_tuning) { verbose_offset_tuning(dev); } diff --git a/src/rtl_tcp.c b/src/rtl_tcp.c index 13ecc84..6afe1d4 100644 --- a/src/rtl_tcp.c +++ b/src/rtl_tcp.c @@ -107,6 +107,8 @@ void usage(void) "\t[-d device index (default: 0)]\n" "\t[-P ppm_error (default: 0)]\n" "\t[-T enable bias-T on GPIO PIN 0 (works for rtl-sdr.com v3 dongles)]\n" + "\t[-D direct_sampling_mode (default: 0, 1 = I, 2 = Q, 3 = I below threshold, 4 = Q below threshold)]\n" + "\t[-D direct_sampling_threshold_frequency (default: 0 use tuner specific frequency threshold for 3 and 4)]\n" "\t[-v increase verbosity (default: 0)]\n"); exit(1); } @@ -470,6 +472,8 @@ int main(int argc, char **argv) int wait_ir = 10000; pthread_t thread_ir; uint32_t frequency = 100000000, samp_rate = 2048000; + enum rtlsdr_ds_mode ds_mode = RTLSDR_DS_IQ; + uint32_t ds_temp, ds_threshold = 0; struct sockaddr_in local, remote; uint32_t buf_num = 0; /* buf_len: @@ -506,7 +510,7 @@ int main(int argc, char **argv) struct sigaction sigact, sigign; #endif - while ((opt = getopt(argc, argv, "a:p:I:W:f:g:s:b:l:n:d:P:w:vT")) != -1) { + while ((opt = getopt(argc, argv, "a:p:I:W:f:g:s:b:l:n:d:P:w:D:vT")) != -1) { switch (opt) { case 'd': dev_index = verbose_device_search(optarg); @@ -554,6 +558,13 @@ int main(int argc, char **argv) case 'T': enable_biastee = 1; break; + case 'D': + ds_temp = (uint32_t)( atofs(optarg) + 0.5 ); + if (ds_temp <= RTLSDR_DS_Q_BELOW) + ds_mode = (enum rtlsdr_ds_mode)ds_temp; + else + ds_threshold = ds_temp; + break; default: usage(); break; @@ -601,6 +612,9 @@ int main(int argc, char **argv) if (r < 0) fprintf(stderr, "WARNING: Failed to set sample rate.\n"); + /* Set direct sampling with threshold */ + rtlsdr_set_ds_mode(dev, ds_mode, ds_threshold); + /* Set the frequency */ r = rtlsdr_set_center_freq(dev, frequency); if (r < 0)