diff --git a/CMakeLists.txt b/CMakeLists.txt index 8053e55..c7c55cf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,6 +122,12 @@ else (DETACH_KERNEL_DRIVER) message (STATUS "Building with kernel driver detaching disabled, use -DDETACH_KERNEL_DRIVER=ON to enable") endif (DETACH_KERNEL_DRIVER) +option(DO_NOT_REATTACH "Do not reattach kernel driver" OFF) +if (DO_NOT_REATTACH) + message (STATUS "Disabled reattaching of kernel driver") + add_definitions(-DDO_NOT_REATTACH=1) +endif (DO_NOT_REATTACH) + ######################################################################## # Add subdirectories ######################################################################## diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h index 656c55b..09a4035 100644 --- a/include/rtl-sdr.h +++ b/include/rtl-sdr.h @@ -146,8 +146,6 @@ RTLSDR_API int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq); RTLSDR_API int rtlsdr_set_if_freq(rtlsdr_dev_t *dev, uint32_t freq); -RTLSDR_API int rtlsdr_set_if_bandwidth(rtlsdr_dev_t *dev, int bw); - /*! * Get actual frequency the device is tuned to. * @@ -219,6 +217,15 @@ RTLSDR_API int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains); */ RTLSDR_API int rtlsdr_set_tuner_gain(rtlsdr_dev_t *dev, int gain); +/*! + * Set the bandwidth for the device. + * + * \param dev the device handle given by rtlsdr_open() + * \param bw bandwidth in Hz. Zero means automatic BW selection. + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_tuner_bandwidth(rtlsdr_dev_t *dev, uint32_t bw); + /*! * Get actual gain the device is configured to. * @@ -386,6 +393,36 @@ RTLSDR_API int rtlsdr_read_async(rtlsdr_dev_t *dev, */ RTLSDR_API int rtlsdr_cancel_async(rtlsdr_dev_t *dev); +/*! + * Enable or disable the bias tee on GPIO PIN 0. + * + * \param dev the device handle given by rtlsdr_open() + * \param on 1 for Bias T on. 0 for Bias T off. + * \return -1 if device is not initialized. 0 otherwise. + */ +RTLSDR_API int rtlsdr_set_bias_tee(rtlsdr_dev_t *dev, int on); + +RTLSDR_API int rtlsdr_demod_write_reg(rtlsdr_dev_t *dev, uint8_t page, uint16_t addr, uint16_t val, uint8_t len); + +RTLSDR_API void rtlsdr_set_i2c_repeater(rtlsdr_dev_t *dev, int on); + +/*! + * Set the sample rate correction value for the device. + * + * \param dev the device handle given by rtlsdr_open() + * \param correction sample rate correction as fraction of the sample rate + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_sample_freq_correction_f(rtlsdr_dev_t *dev, float correction); + +/*! + * Set the sample rate correction value for the device. + * + * \param dev the device handle given by rtlsdr_open() + * \param ppm correction value in parts per million (ppm) + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_sample_freq_correction(rtlsdr_dev_t *dev, int ppm); #ifdef __cplusplus } #endif diff --git a/src/librtlsdr.c b/src/librtlsdr.c index 622f985..ab3a990 100644 --- a/src/librtlsdr.c +++ b/src/librtlsdr.c @@ -117,6 +117,7 @@ struct rtlsdr_dev { uint32_t offs_freq; /* Hz */ int corr; /* ppm */ int gain; /* tenth dB */ + int bw; struct e4k_state e4k_s; struct r82xx_config r82xx_c; struct r82xx_priv r82xx_p; @@ -724,6 +725,26 @@ int rtlsdr_set_if_freq(rtlsdr_dev_t *dev, uint32_t freq) return r; } +int rtlsdr_set_sample_freq_correction_f(rtlsdr_dev_t *dev, float correction) +{ + int r = 0; + uint8_t tmp; + int16_t offs; + int32_t offs1 = (int16_t)(correction * -1 * TWO_POW(24)); + if(offs1 > 0x1FFF) offs = 0x1FFF; + else if(offs1 < -0x1FFF) offs = -0x1FFF; + else offs = offs1; + rtlsdr_set_i2c_repeater(dev, 0); + + tmp = offs & 0xff; + r |= rtlsdr_demod_write_reg(dev, 1, 0x3f, tmp, 1); + tmp = (offs >> 8) & 0x3f; + r |= rtlsdr_demod_write_reg(dev, 1, 0x3e, tmp, 1); + + return r; +} + + int rtlsdr_set_sample_freq_correction(rtlsdr_dev_t *dev, int ppm) { int r = 0; @@ -1027,6 +1048,24 @@ int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains) } } +int rtlsdr_set_tuner_bandwidth(rtlsdr_dev_t *dev, uint32_t bw) +{ + int r = 0; + + if (!dev || !dev->tuner) + return -1; + + if (dev->tuner->set_bw) { + rtlsdr_set_i2c_repeater(dev, 1); + r = dev->tuner->set_bw(dev, bw > 0 ? bw : dev->rate); + rtlsdr_set_i2c_repeater(dev, 0); + if (r) + return r; + dev->bw = bw; + } + return r; +} + int rtlsdr_set_tuner_gain(rtlsdr_dev_t *dev, int gain) { int r = 0; @@ -1112,14 +1151,10 @@ int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t samp_rate) if ( ((double)samp_rate) != real_rate ) fprintf(stderr, "Exact sample rate is: %f Hz\n", real_rate); - if (dev->tuner && dev->tuner->set_bw) { - rtlsdr_set_i2c_repeater(dev, 1); - dev->tuner->set_bw(dev, (int)real_rate); - rtlsdr_set_i2c_repeater(dev, 0); - } - dev->rate = (uint32_t)real_rate; + rtlsdr_set_tuner_bandwidth(dev, dev->bw); + tmp = (rsamp_ratio >> 16); r |= rtlsdr_demod_write_reg(dev, 1, 0x9f, tmp, 2); tmp = rsamp_ratio & 0xffff; @@ -1681,12 +1716,14 @@ int rtlsdr_close(rtlsdr_dev_t *dev) libusb_release_interface(dev->devh, 0); #ifdef DETACH_KERNEL_DRIVER +#ifndef DO_NOT_REATTACH if (dev->driver_active) { if (!libusb_attach_kernel_driver(dev->devh, 0)) fprintf(stderr, "Reattached kernel driver\n"); else fprintf(stderr, "Reattaching kernel driver failed!\n"); } +#endif #endif libusb_close(dev->devh); @@ -1979,3 +2016,14 @@ int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len) } while (retries > 0); return -1; } + +int rtlsdr_set_bias_tee(rtlsdr_dev_t *dev, int on) +{ + if (!dev) + return -1; + + rtlsdr_set_gpio_output(dev, 0); + rtlsdr_set_gpio_bit(dev, 0, on); + + return 0; +} diff --git a/src/rtl_adsb.c b/src/rtl_adsb.c index 7092802..31056da 100644 --- a/src/rtl_adsb.c +++ b/src/rtl_adsb.c @@ -93,6 +93,7 @@ void usage(void) "\t[-e allowed_errors (default: 5)]\n" "\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" "\tfilename (a '-' dumps samples to stdout)\n" "\t (omitting the filename also uses stdout)\n\n" "Streaming with netcat:\n" @@ -368,11 +369,12 @@ int main(int argc, char **argv) int dev_index = 0; int dev_given = 0; int ppm_error = 0; + int enable_biastee = 0; pthread_cond_init(&ready, NULL); pthread_mutex_init(&ready_m, NULL); squares_precompute(); - while ((opt = getopt(argc, argv, "d:g:p:e:Q:VS")) != -1) + while ((opt = getopt(argc, argv, "d:g:p:e:Q:VST")) != -1) { switch (opt) { case 'd': @@ -397,6 +399,9 @@ int main(int argc, char **argv) case 'Q': quality = (int)(atof(optarg) * 10); break; + case 'T': + enable_biastee = 1; + break; default: usage(); return 0; @@ -467,6 +472,10 @@ int main(int argc, char **argv) /* Set the sample rate */ verbose_set_sample_rate(dev, ADSB_RATE); + rtlsdr_set_bias_tee(dev, enable_biastee); + if (enable_biastee) + fprintf(stderr, "activated bias-T on GPIO PIN 0\n"); + /* Reset endpoint before we start reading from it (mandatory) */ verbose_reset_buffer(dev); diff --git a/src/rtl_fm.c b/src/rtl_fm.c index 6c11a76..eabda50 100644 --- a/src/rtl_fm.c +++ b/src/rtl_fm.c @@ -244,6 +244,7 @@ void usage(void) "\t raw mode outputs 2x16 bit IQ pairs\n" "\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[-g tuner_gain (default: automatic)]\n" "\t[-l squelch_level (default: 0/off)]\n" //"\t for fm squelch is inverted\n" @@ -1484,6 +1485,7 @@ int main(int argc, char **argv) int r, opt; int dev_given = 0; int custom_ppm = 0; + int enable_biastee = 0; dongle_init(&dongle); demod_init(&demod); @@ -1491,7 +1493,7 @@ int main(int argc, char **argv) output_init(&output); controller_init(&controller); - while ((opt = getopt(argc, argv, "d:f:g:s:b:l:o:t:r:p:E:F:A:M:h")) != -1) { + while ((opt = getopt(argc, argv, "d:f:g:s:b:l:o:t:r:p:E:F:A:M:hT")) != -1) { switch (opt) { case 'd': dongle.dev_index = verbose_device_search(optarg); @@ -1602,6 +1604,9 @@ int main(int argc, char **argv) demod.deemph = 1; demod.squelch_level = 0;} break; + case 'T': + enable_biastee = 1; + break; case 'h': default: usage(); @@ -1672,6 +1677,11 @@ int main(int argc, char **argv) if (!custom_ppm) { verbose_ppm_eeprom(dongle.dev, &(dongle.ppm_error)); } + + rtlsdr_set_bias_tee(dongle.dev, enable_biastee); + if (enable_biastee) + fprintf(stderr, "activated bias-T on GPIO PIN 0\n"); + verbose_ppm_set(dongle.dev, dongle.ppm_error); if (strcmp(output.filename, "-") == 0) { /* Write samples to stdout */ diff --git a/src/rtl_power.c b/src/rtl_power.c index 217b745..410c4ae 100644 --- a/src/rtl_power.c +++ b/src/rtl_power.c @@ -170,6 +170,7 @@ void usage(void) "\t[-d device_index (default: 0)]\n" "\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" "\tfilename (a '-' dumps samples to stdout)\n" "\t omitting the filename also uses stdout\n" "\n" @@ -189,7 +190,7 @@ void usage(void) "\t possible values are 2M to 3.2M\n" "\t[-E enables epoch timestamps (default: off/verbose)]\n" "\t[-P enables peak hold (default: off/averaging)]\n" - "\t[-T enables trough hold (default: off/averaging)]\n" + "\t[-M enables trough hold (default: off/averaging)]\n" "\t[-L enable linear output (default: off/dB)]\n" "\t[-D direct_sampling_mode, 0 (default/off), 1 (I), 2 (Q), 3 (no-mod)]\n" "\t[-O enable offset tuning (default: off)]\n" @@ -1037,6 +1038,8 @@ int main(int argc, char **argv) int single = 0; int direct_sampling = 0; int offset_tuning = 0; + int enable_biastee = 0; + double crop = 0.0; char *freq_optarg; time_t next_tick; time_t time_now; @@ -1048,7 +1051,7 @@ int main(int argc, char **argv) init_misc(&ms); strcpy(dev_label, "DEFAULT"); - while ((opt = getopt(argc, argv, "f:i:s:r:t:d:g:p:e:w:c:F:1EPTLD:Oh")) != -1) { + while ((opt = getopt(argc, argv, "f:i:s:r:t:d:g:p:e:w:c:F:1EPMLTD:Oh")) != -1) { switch (opt) { case 'f': // lower:upper:bin_size if (f_set) { @@ -1116,7 +1119,7 @@ int main(int argc, char **argv) case 'P': ms.peak_hold = 1; break; - case 'T': + case 'M': ms.peak_hold = -1; break; case 'L': @@ -1132,6 +1135,9 @@ int main(int argc, char **argv) ms.boxcar = 0; ms.comp_fir_size = atoi(optarg); break; + case 'T': + enable_biastee = 1; + break; case 'h': default: usage(); @@ -1212,6 +1218,10 @@ int main(int argc, char **argv) } verbose_ppm_set(dev, ppm_error); + rtlsdr_set_bias_tee(dev, enable_biastee); + if (enable_biastee) + fprintf(stderr, "activated bias-T on GPIO PIN 0\n"); + if (strcmp(filename, "-") == 0) { /* Write log to stdout */ file = stdout; #ifdef _WIN32 diff --git a/src/rtl_tcp.c b/src/rtl_tcp.c index 35eadac..f21f76f 100644 --- a/src/rtl_tcp.c +++ b/src/rtl_tcp.c @@ -78,6 +78,7 @@ typedef struct { /* structure size must be multiple of 2 bytes */ static rtlsdr_dev_t *dev = NULL; +static int enable_biastee = 0; static int global_numq = 0; static struct llist *ll_buffers = 0; static int llbuf_num = 500; @@ -95,7 +96,8 @@ void usage(void) "\t[-b number of buffers (default: 15, set by library)]\n" "\t[-n max number of linked list buffers to keep (default: 500)]\n" "\t[-d device index (default: 0)]\n" - "\t[-P ppm_error (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"); exit(1); } @@ -351,6 +353,10 @@ static void *command_worker(void *arg) printf("set tuner gain by index %u\n", ntohl(cmd.param)); set_gain_by_index(dev, ntohl(cmd.param)); break; + case 0x0e: + printf("set bias tee %d\n", ntohl(cmd.param)); + rtlsdr_set_bias_tee(dev, (int)ntohl(cmd.param)); + break; default: break; } @@ -388,7 +394,7 @@ int main(int argc, char **argv) struct sigaction sigact, sigign; #endif - while ((opt = getopt(argc, argv, "a:p:f:g:s:b:n:d:P:")) != -1) { + while ((opt = getopt(argc, argv, "a:p:f:g:s:b:n:d:P:T")) != -1) { switch (opt) { case 'd': dev_index = verbose_device_search(optarg); @@ -419,6 +425,9 @@ int main(int argc, char **argv) ppm_error = atoi(optarg); custom_ppm = 1; break; + case 'T': + enable_biastee = 1; + break; default: usage(); break; @@ -492,6 +501,10 @@ int main(int argc, char **argv) fprintf(stderr, "Tuner gain set to %f dB.\n", gain/10.0); } + rtlsdr_set_bias_tee(dev, enable_biastee); + if (enable_biastee) + fprintf(stderr, "activated bias-T on GPIO PIN 0\n"); + /* Reset endpoint before we start reading from it (mandatory) */ r = rtlsdr_reset_buffer(dev); if (r < 0)