diff --git a/app/src/main/jni/rtlsdrdevice.c b/app/src/main/jni/rtlsdrdevice.c index bb31109..6188c06 100644 --- a/app/src/main/jni/rtlsdrdevice.c +++ b/app/src/main/jni/rtlsdrdevice.c @@ -98,6 +98,7 @@ static jint SUPPORTED_COMMANDS[] = { TCP_SET_RTL_XTAL, TCP_SET_TUNER_XTAL, TCP_SET_TUNER_GAIN_BY_ID, + TCP_SET_BIAS_TEE, TCP_ANDROID_EXIT, TCP_ANDROID_GAIN_BY_PERCENTAGE }; @@ -157,6 +158,10 @@ void tcpCommandCallback(sdrtcp_t * tcpserv, void * pointer, sdr_tcp_command_t * LOGI("set tuner gain by index %d", cmd->parameter); set_gain_by_index(dev->rtl_dev, cmd->parameter); break; + case TCP_SET_BIAS_TEE: + LOGI("set bias tee %d", cmd->parameter); + rtlsdr_set_bias_tee(dev->rtl_dev, cmd->parameter); + break; case TCP_ANDROID_EXIT: LOGI("tcpCommandCallback: client requested to close rtl_tcp_andro"); sdrtcp_stop_serving_client(tcpserv); @@ -308,4 +313,4 @@ JNIEXPORT jobjectArray JNICALL Java_com_sdrtouch_rtlsdr_driver_RtlSdrDevice_getS (*env)->SetIntArrayRegion(env, result, 0, n_commands, commands); return result; -} \ No newline at end of file +} diff --git a/app/src/main/jni/tcp_commands.h b/app/src/main/jni/tcp_commands.h index 0625505..1269981 100644 --- a/app/src/main/jni/tcp_commands.h +++ b/app/src/main/jni/tcp_commands.h @@ -42,6 +42,7 @@ typedef enum TCP_SET_RTL_XTAL = 0x0b, // rtlsdr_set_xtal_freq with rtl_freq set as the parameter TCP_SET_TUNER_XTAL = 0x0c, // rtlsdr_set_xtal_freq with tuner_freq set as the parameter TCP_SET_TUNER_GAIN_BY_ID = 0x0d, // set_gain_by_index + TCP_SET_BIAS_TEE = 0x0e, // rtlsdr_set_bias_tee // Android only rtl-tcp API TCP_ANDROID_EXIT = 0x7e, // send any value to cause the driver to turn off itself diff --git a/rtlsdr/src/main/jni/src/convenience/convenience.c b/rtlsdr/src/main/jni/src/convenience/convenience.c index 517dc4e..00cc2cc 100644 --- a/rtlsdr/src/main/jni/src/convenience/convenience.c +++ b/rtlsdr/src/main/jni/src/convenience/convenience.c @@ -49,9 +49,11 @@ double atofs(char *s) case 'g': case 'G': suff *= 1e3; + /* fall-through */ case 'm': case 'M': suff *= 1e3; + /* fall-through */ case 'k': case 'K': suff *= 1e3; @@ -76,9 +78,11 @@ double atoft(char *s) case 'h': case 'H': suff *= 60; + /* fall-through */ case 'm': case 'M': suff *= 60; + /* fall-through */ case 's': case 'S': suff *= atof(s); diff --git a/rtlsdr/src/main/jni/src/librtlsdr.c b/rtlsdr/src/main/jni/src/librtlsdr.c index cdf1ca9..f567f01 100644 --- a/rtlsdr/src/main/jni/src/librtlsdr.c +++ b/rtlsdr/src/main/jni/src/librtlsdr.c @@ -103,6 +103,7 @@ struct rtlsdr_dev { void *cb_ctx; enum rtlsdr_async_status async_status; int async_cancel; + int use_zerocopy; /* rtl demod context */ uint32_t rate; /* Hz */ uint32_t rtl_xtal; /* Hz */ @@ -124,6 +125,8 @@ struct rtlsdr_dev { int dev_lost; int driver_active; unsigned int xfer_errors; + int force_bt; + int force_ds; }; void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val); @@ -329,6 +332,7 @@ static rtlsdr_dongle_t known_devices[] = { { 0x0ccd, 0x00e0, "Terratec NOXON DAB/DAB+ USB dongle (rev 2)" }, { 0x1554, 0x5020, "PixelView PV-DT235U(RN)" }, { 0x15f4, 0x0131, "Astrometa DVB-T/DVB-T2" }, + { 0x15f4, 0x0133, "HanfTek DAB+FM+DVB-T" }, { 0x185b, 0x0620, "Compro Videomate U620F"}, { 0x185b, 0x0650, "Compro Videomate U650F"}, { 0x185b, 0x0680, "Compro Videomate U680F"}, @@ -366,6 +370,7 @@ static rtlsdr_dongle_t known_devices[] = { #define BULK_TIMEOUT 0 #define EEPROM_ADDR 0xa0 +#define EEPROM_SIZE 256 enum usb_reg { USB_SYSCTL = 0x2000, @@ -569,7 +574,7 @@ void rtlsdr_set_gpio_output(rtlsdr_dev_t *dev, uint8_t gpio) gpio = 1 << gpio; r = rtlsdr_read_reg(dev, SYSB, GPD, 1); - rtlsdr_write_reg(dev, SYSB, GPO, r & ~gpio, 1); + rtlsdr_write_reg(dev, SYSB, GPD, r & ~gpio, 1); r = rtlsdr_read_reg(dev, SYSB, GPOE, 1); rtlsdr_write_reg(dev, SYSB, GPOE, r | gpio, 1); } @@ -1171,6 +1176,8 @@ int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on) if (!dev) return -1; + if(dev->force_ds) on = 2; + if (on) { if (dev->tuner && dev->tuner->exit) { rtlsdr_set_i2c_repeater(dev, 1); @@ -1243,6 +1250,10 @@ int rtlsdr_set_offset_tuning(rtlsdr_dev_t *dev, int on) if (!dev) return -1; + // RTL-SDR-BLOG Hack, enables us to turn on the bias tee by clicking on "offset tuning" in software that doesn't have specified bias tee support. + // Offset tuning is not used for R820T devices so it is no problem. + rtlsdr_set_gpio(dev, 0, on); + if ((dev->tuner_type == RTLSDR_TUNER_R820T) || (dev->tuner_type == RTLSDR_TUNER_R828D)) return -2; @@ -1445,6 +1456,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) struct libusb_device_descriptor dd; uint8_t reg; ssize_t cnt; + uint8_t buf[EEPROM_SIZE]; dev = malloc(sizeof(rtlsdr_dev_t)); if (NULL == dev) @@ -1564,11 +1576,11 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) } /* initialise GPIOs */ - rtlsdr_set_gpio_output(dev, 5); + rtlsdr_set_gpio_output(dev, 4); /* reset tuner before probing */ - rtlsdr_set_gpio_bit(dev, 5, 1); - rtlsdr_set_gpio_bit(dev, 5, 0); + rtlsdr_set_gpio_bit(dev, 4, 1); + rtlsdr_set_gpio_bit(dev, 4, 0); reg = rtlsdr_i2c_read_reg(dev, FC2580_I2C_ADDR, FC2580_CHECK_ADDR); if ((reg & 0x7f) == FC2580_CHECK_VAL) { @@ -1593,6 +1605,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) switch (dev->tuner_type) { case RTLSDR_TUNER_R828D: dev->tun_xtal = R828D_XTAL_FREQ; + /* fall-through */ case RTLSDR_TUNER_R820T: /* disable Zero-IF mode */ rtlsdr_demod_write_reg(dev, 1, 0xb1, 0x1a, 1); @@ -1606,15 +1619,26 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) /* enable spectrum inversion */ rtlsdr_demod_write_reg(dev, 1, 0x15, 0x01, 1); + break; case RTLSDR_TUNER_UNKNOWN: fprintf(stderr, "No supported tuner found\n"); - rtlsdr_set_direct_sampling(dev, 1); + rtlsdr_set_direct_sampling(dev, 2); break; default: break; } + + /* Hack to force the Bias T to always be on if we set the IR-Endpoint bit in the EEPROM to 0. Default on EEPROM is 1. */ + r = rtlsdr_read_eeprom(dev, buf, 0, EEPROM_SIZE); + dev->force_bt = (buf[7] & 0x02) ? 0 : 1; + if(dev->force_bt) rtlsdr_set_gpio(dev, 0, 1); + /* Hack to force direct sampling mode to always be on if we set the remote-enabled bit in the EEPROM to 1. Default on EEPROM is 0. */ + dev->force_ds = (buf[7] & 0x01) ? 1 : 0; + if(dev->force_ds) dev->tuner_type = RTLSDR_TUNER_UNKNOWN; + + if (dev->tuner->init) r = dev->tuner->init(dev); @@ -1625,6 +1649,9 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) return 0; err: if (dev) { + if (dev->devh) + libusb_close(dev->devh); + if (dev->ctx) libusb_exit(dev->ctx); @@ -1739,12 +1766,64 @@ static int _rtlsdr_alloc_async_buffers(rtlsdr_dev_t *dev) dev->xfer[i] = libusb_alloc_transfer(0); } - if (!dev->xfer_buf) { - dev->xfer_buf = malloc(dev->xfer_buf_num * - sizeof(unsigned char *)); + if (dev->xfer_buf) + return -2; - for(i = 0; i < dev->xfer_buf_num; ++i) + dev->xfer_buf = malloc(dev->xfer_buf_num * sizeof(unsigned char *)); + memset(dev->xfer_buf, 0, dev->xfer_buf_num * sizeof(unsigned char *)); + +#if defined(ENABLE_ZEROCOPY) && defined (__linux__) && LIBUSB_API_VERSION >= 0x01000105 + fprintf(stderr, "Allocating %d zero-copy buffers\n", dev->xfer_buf_num); + + dev->use_zerocopy = 1; + for (i = 0; i < dev->xfer_buf_num; ++i) { + dev->xfer_buf[i] = libusb_dev_mem_alloc(dev->devh, dev->xfer_buf_len); + + if (dev->xfer_buf[i]) { + /* Check if Kernel usbfs mmap() bug is present: if the + * mapping is correct, the buffers point to memory that + * was memset to 0 by the Kernel, otherwise, they point + * to random memory. We check if the buffers are zeroed + * and otherwise fall back to buffers in userspace. + */ + if (dev->xfer_buf[i][0] || memcmp(dev->xfer_buf[i], + dev->xfer_buf[i] + 1, + dev->xfer_buf_len - 1)) { + fprintf(stderr, "Detected Kernel usbfs mmap() " + "bug, falling back to buffers " + "in userspace\n"); + dev->use_zerocopy = 0; + break; + } + } else { + fprintf(stderr, "Failed to allocate zero-copy " + "buffer for transfer %d\nFalling " + "back to buffers in userspace\n", i); + dev->use_zerocopy = 0; + break; + } + } + + /* zero-copy buffer allocation failed (partially or completely) + * we need to free the buffers again if already allocated */ + if (!dev->use_zerocopy) { + for (i = 0; i < dev->xfer_buf_num; ++i) { + if (dev->xfer_buf[i]) + libusb_dev_mem_free(dev->devh, + dev->xfer_buf[i], + dev->xfer_buf_len); + } + } +#endif + + /* no zero-copy available, allocate buffers in userspace */ + if (!dev->use_zerocopy) { + for (i = 0; i < dev->xfer_buf_num; ++i) { dev->xfer_buf[i] = malloc(dev->xfer_buf_len); + + if (!dev->xfer_buf[i]) + return -ENOMEM; + } } return 0; @@ -1769,9 +1848,18 @@ static int _rtlsdr_free_async_buffers(rtlsdr_dev_t *dev) } if (dev->xfer_buf) { - for(i = 0; i < dev->xfer_buf_num; ++i) { - if (dev->xfer_buf[i]) - free(dev->xfer_buf[i]); + for (i = 0; i < dev->xfer_buf_num; ++i) { + if (dev->xfer_buf[i]) { + if (dev->use_zerocopy) { +#if defined (__linux__) && LIBUSB_API_VERSION >= 0x01000105 + libusb_dev_mem_free(dev->devh, + dev->xfer_buf[i], + dev->xfer_buf_len); +#endif + } else { + free(dev->xfer_buf[i]); + } + } } free(dev->xfer_buf); @@ -1826,7 +1914,12 @@ int rtlsdr_read_async(rtlsdr_dev_t *dev, rtlsdr_read_async_cb_t cb, void *ctx, r = libusb_submit_transfer(dev->xfer[i]); if (r < 0) { - fprintf(stderr, "Failed to submit transfer %i!\n", i); + fprintf(stderr, "Failed to submit transfer %i\n" + "Please increase your allowed " + "usbfs buffer size with the " + "following command:\n" + "echo 0 > /sys/module/usbcore" + "/parameters/usbfs_memory_mb\n", i); dev->async_status = RTLSDR_CANCELING; break; } @@ -1936,3 +2029,29 @@ int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len) return -1; } + +int rtlsdr_set_bias_tee(rtlsdr_dev_t *dev, int on) +{ + if (!dev) + return -1; + + if(dev->force_bt) on = 1; // If force_bt is on from the EEPROM, do not allow bias tee to turn off + + rtlsdr_set_gpio_output(dev, 0); + rtlsdr_set_gpio_bit(dev, 0, on); + + return 0; +} + +int rtlsdr_set_gpio(rtlsdr_dev_t *dev, int gpio_pin, int on) +{ + if (!dev) + return -1; + + if(dev->force_bt) on = 1; // If force_bt is on from the EEPROM, do not allow bias tee to turn off + + rtlsdr_set_gpio_output(dev, gpio_pin); + rtlsdr_set_gpio_bit(dev, gpio_pin, on); + + return 1; +} diff --git a/rtlsdr/src/main/jni/src/rtl_adsb.c b/rtlsdr/src/main/jni/src/rtl_adsb.c index e611e78..7aea8dd 100644 --- a/rtlsdr/src/main/jni/src/rtl_adsb.c +++ b/rtlsdr/src/main/jni/src/rtl_adsb.c @@ -96,6 +96,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" @@ -182,7 +183,7 @@ int magnitute(uint8_t *buf, int len) return len/2; } -inline uint16_t single_manchester(uint16_t a, uint16_t b, uint16_t c, uint16_t d) +static inline uint16_t single_manchester(uint16_t a, uint16_t b, uint16_t c, uint16_t d) /* takes 4 consecutive real samples, return 0 or 1, BADSAMPLE on error */ { int bit, bit_p; @@ -223,17 +224,17 @@ inline uint16_t single_manchester(uint16_t a, uint16_t b, uint16_t c, uint16_t d return BADSAMPLE; } -inline uint16_t min16(uint16_t a, uint16_t b) +static inline uint16_t min16(uint16_t a, uint16_t b) { return ab ? a : b; } -inline int preamble(uint16_t *buf, int i) +static inline int preamble(uint16_t *buf, int i) /* returns 0/1 for preamble at index i */ { int i2; @@ -371,11 +372,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': @@ -400,6 +402,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; @@ -470,6 +475,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); @@ -483,6 +492,8 @@ int main(int argc, char **argv) else { fprintf(stderr, "\nLibrary error %d, exiting...\n", r);} rtlsdr_cancel_async(dev); + pthread_cancel(demod_thread); + pthread_join(demod_thread, NULL); pthread_cond_destroy(&ready); pthread_mutex_destroy(&ready_m); diff --git a/rtlsdr/src/main/jni/src/rtl_biast.c b/rtlsdr/src/main/jni/src/rtl_biast.c new file mode 100644 index 0000000..6018450 --- /dev/null +++ b/rtlsdr/src/main/jni/src/rtl_biast.c @@ -0,0 +1,125 @@ +/* + * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver + * rtl_eeprom, EEPROM modification tool + * Copyright (C) 2012 by Steve Markgraf + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include + +#ifndef _WIN32 +#include +#else +#include +#include "getopt/getopt.h" +#endif + +#include "rtl-sdr.h" +#include "convenience/convenience.h" + +#define EEPROM_SIZE 256 +#define MAX_STR_SIZE 256 +#define STR_OFFSET 0x09 + +static rtlsdr_dev_t *dev = NULL; + +typedef struct rtlsdr_config { + uint16_t vendor_id; + uint16_t product_id; + char manufacturer[MAX_STR_SIZE]; + char product[MAX_STR_SIZE]; + char serial[MAX_STR_SIZE]; + int have_serial; + int enable_ir; + int remote_wakeup; +} rtlsdr_config_t; + + +void usage(void) +{ + fprintf(stderr, + "rtl_biast, a tool for turning the RTL-SDR.com \n" + "bias tee or any GPIO ON and OFF. Example to turn on the \n" + "bias tee: rtl_biast -d 0 -b 1\n" + "Any GPIO: rtl_biast -d 0 -g 1 -b 1\n\n" + "Usage:\n" + "\t[-d device_index (default: 0)]\n" + "\t[-b bias_on (default: 0)]\n" + "\t[-g GPIO select (default: 0)]\n"); + exit(1); +} + +int main(int argc, char **argv) +{ + int i, r, opt; + int dev_index = 0; + int dev_given = 0; + uint32_t bias_on = 0; + uint32_t gpio_pin = 0; + int device_count; + char *filename = NULL; + FILE *file = NULL; + char *manuf_str = NULL; + char *product_str = NULL; + char *serial_str = NULL; + uint8_t buf[EEPROM_SIZE]; + rtlsdr_config_t conf; + int flash_file = 0; + int default_config = 0; + int change = 0; + int ir_endpoint = 0; + char ch; + + while ((opt = getopt(argc, argv, "d:b:g:h?")) != -1) { + switch (opt) { + case 'd': + dev_index = verbose_device_search(optarg); + dev_given = 1; + break; + case 'b': + bias_on = atoi(optarg); + break; + case 'g': + gpio_pin = atoi(optarg); + break; + default: + usage(); + break; + } + } + + if (!dev_given) { + dev_index = verbose_device_search("0"); + } + + if (dev_index < 0) { + exit(1); + } + + r = rtlsdr_open(&dev, dev_index); + + rtlsdr_set_gpio(dev, gpio_pin, bias_on); + //rtlsdr_set_bias_tee(dev, bias_on); + + //rtlsdr_set_direct_sampling(dev, 1); + +exit: + rtlsdr_close(dev); + + return r >= 0 ? r : -r; +} + diff --git a/rtlsdr/src/main/jni/src/rtl_eeprom.c b/rtlsdr/src/main/jni/src/rtl_eeprom.c index 5259820..ca35f67 100644 --- a/rtlsdr/src/main/jni/src/rtl_eeprom.c +++ b/rtlsdr/src/main/jni/src/rtl_eeprom.c @@ -43,8 +43,8 @@ typedef struct rtlsdr_config { char product[MAX_STR_SIZE]; char serial[MAX_STR_SIZE]; int have_serial; - int enable_ir; - int remote_wakeup; + int enable_bt; + int direct_sampling_on; } rtlsdr_config_t; void dump_config(rtlsdr_config_t *conf) @@ -57,10 +57,10 @@ void dump_config(rtlsdr_config_t *conf) fprintf(stderr, "Serial number:\t\t%s\n", conf->serial); fprintf(stderr, "Serial number enabled:\t"); fprintf(stderr, conf->have_serial ? "yes\n": "no\n"); - fprintf(stderr, "IR endpoint enabled:\t"); - fprintf(stderr, conf->enable_ir ? "yes\n": "no\n"); - fprintf(stderr, "Remote wakeup enabled:\t"); - fprintf(stderr, conf->remote_wakeup ? "yes\n": "no\n"); + fprintf(stderr, "Bias-T Always ON:\t"); + fprintf(stderr, conf->enable_bt ? "no\n": "yes\n"); // 0 is ON for this + fprintf(stderr, "Direct Sampling Always ON:\t"); + fprintf(stderr, conf->direct_sampling_on ? "yes\n": "no\n"); fprintf(stderr, "__________________________________________\n"); } @@ -74,7 +74,8 @@ void usage(void) "\t[-m set manufacturer string]\n" "\t[-p set product string]\n" "\t[-s set serial number string]\n" - "\t[-i <0,1> disable/enable IR-endpoint]\n" + "\t[-b <\"y\",\"n\"> enable/disable bias tee always ON]\n" + "\t[-q <\"y\",\"n\"> enable/disable direct sampling always ON]\n" "\t[-g generate default config and write to device]\n" "\t[ can be one of:]\n" "\t[ realtek\t\tRealtek default (as without EEPROM)]\n" @@ -139,8 +140,8 @@ int parse_eeprom_to_conf(rtlsdr_config_t *conf, uint8_t *dat) conf->vendor_id = dat[2] | (dat[3] << 8); conf->product_id = dat[4] | (dat[5] << 8); conf->have_serial = (dat[6] == 0xa5) ? 1 : 0; - conf->remote_wakeup = (dat[7] & 0x01) ? 1 : 0; - conf->enable_ir = (dat[7] & 0x02) ? 1 : 0; + conf->direct_sampling_on = (dat[7] & 0x01) ? 1 : 0; + conf->enable_bt = (dat[7] & 0x02) ? 1 : 0; pos = get_string_descriptor(STR_OFFSET, dat, conf->manufacturer); pos = get_string_descriptor(pos, dat, conf->product); @@ -161,8 +162,8 @@ int gen_eeprom_from_conf(rtlsdr_config_t *conf, uint8_t *dat) dat[5] = (conf->product_id >> 8) & 0xff; dat[6] = conf->have_serial ? 0xa5 : 0x00; dat[7] = 0x14; - dat[7] |= conf->remote_wakeup ? 0x01 : 0x00; - dat[7] |= conf->enable_ir ? 0x02 : 0x00; + dat[7] |= conf->direct_sampling_on ? 0x01 : 0x00; + dat[7] |= conf->enable_bt ? 0x02 : 0x00; dat[8] = 0x02; pos = set_string_descriptor(STR_OFFSET, dat, conf->manufacturer); @@ -194,8 +195,8 @@ void gen_default_conf(rtlsdr_config_t *conf, int config) strcpy(conf->product, "RTL2832U DVB-T"); strcpy(conf->serial, "0"); conf->have_serial = 1; - conf->enable_ir = 0; - conf->remote_wakeup = 1; + conf->enable_bt = 0; + conf->direct_sampling_on = 1; break; case REALTEK_EEPROM: fprintf(stderr, "Realtek default OEM with EEPROM\n"); @@ -205,8 +206,8 @@ void gen_default_conf(rtlsdr_config_t *conf, int config) strcpy(conf->product, "RTL2838UHIDIR"); strcpy(conf->serial, "00000001"); conf->have_serial = 1; - conf->enable_ir = 1; - conf->remote_wakeup = 0; + conf->enable_bt = 1; + conf->direct_sampling_on = 0; break; case TERRATEC_NOXON: fprintf(stderr, "Terratec NOXON DAB Stick\n"); @@ -216,8 +217,8 @@ void gen_default_conf(rtlsdr_config_t *conf, int config) strcpy(conf->product, "DAB Stick"); strcpy(conf->serial, "0"); conf->have_serial = 1; - conf->enable_ir = 0; - conf->remote_wakeup = 1; + conf->enable_bt = 0; + conf->direct_sampling_on = 1; break; case TERRATEC_T_BLACK: fprintf(stderr, "Terratec T Stick Black\n"); @@ -227,8 +228,8 @@ void gen_default_conf(rtlsdr_config_t *conf, int config) strcpy(conf->product, "RTL2838UHIDIR"); strcpy(conf->serial, "00000001"); conf->have_serial = 1; - conf->enable_ir = 1; - conf->remote_wakeup = 0; + conf->enable_bt = 1; + conf->direct_sampling_on = 0; break; case TERRATEC_T_PLUS: fprintf(stderr, "Terratec ran T Stick+\n"); @@ -238,8 +239,8 @@ void gen_default_conf(rtlsdr_config_t *conf, int config) strcpy(conf->product, "RTL2838UHIDIR"); strcpy(conf->serial, "00000001"); conf->have_serial = 1; - conf->enable_ir = 1; - conf->remote_wakeup = 0; + conf->enable_bt = 1; + conf->direct_sampling_on = 0; break; default: break; @@ -261,10 +262,11 @@ int main(int argc, char **argv) int flash_file = 0; int default_config = 0; int change = 0; - int ir_endpoint = 0; + int enable_bt = 0; + int direct_sampling_on = 0; char ch; - while ((opt = getopt(argc, argv, "d:m:p:s:i:g:w:r:h?")) != -1) { + while ((opt = getopt(argc, argv, "d:m:p:s:b:q:g:w:r:h?")) != -1) { switch (opt) { case 'd': dev_index = atoi(optarg); @@ -281,8 +283,30 @@ int main(int argc, char **argv) serial_str = optarg; change = 1; break; - case 'i': - ir_endpoint = (atoi(optarg) > 0) ? 1 : -1; + case 'b': + if(strcmp(optarg, "y") == 0) + { + enable_bt = 1; + } + else if(strcmp(optarg, "n") == 0) + { + enable_bt = -1; + } + //enable_bt = (!strcmp(optarg, "y")) ? 1 : -1; + //ir_endpoint = (atoi(optarg) > 0) ? 1 : -1; + change = 1; + break; + case 'q': + if(strcmp(optarg, "y") == 0) + { + direct_sampling_on = 1; + } + else if(strcmp(optarg, "n") == 0) + { + direct_sampling_on = -1; + } + //direct_sampling_on = (!strcmp(optarg, "y")) ? 1 : -1; + //direct_sampling_on = (atoi(optarg) > 0) ? 1 : -1; change = 1; break; case 'g': @@ -303,6 +327,7 @@ int main(int argc, char **argv) case 'w': flash_file = 1; change = 1; + /* fall-through */ case 'r': filename = optarg; break; @@ -379,8 +404,11 @@ int main(int argc, char **argv) strncpy((char*)&conf.serial, serial_str, MAX_STR_SIZE); } - if (ir_endpoint != 0) - conf.enable_ir = (ir_endpoint > 0) ? 1 : 0; + if (enable_bt != 0) + conf.enable_bt = (enable_bt > 0) ? 0 : 1; + + if (direct_sampling_on != 0) + conf.direct_sampling_on = (direct_sampling_on > 0) ? 1 : 0; if (!change) goto exit; diff --git a/rtlsdr/src/main/jni/src/rtl_fm.c b/rtlsdr/src/main/jni/src/rtl_fm.c index e89e42d..b163979 100644 --- a/rtlsdr/src/main/jni/src/rtl_fm.c +++ b/rtlsdr/src/main/jni/src/rtl_fm.c @@ -193,6 +193,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" @@ -502,7 +503,7 @@ int polar_disc_lut(int ar, int aj, int br, int bj) if (x_abs >= atan_lut_size) { /* we can use linear range, but it is not necessary */ - return (cj > 0) ? 1<<13 : -1<<13; + return (cj > 0) ? 1<<13 : -(1<<13); } if (x > 0) { @@ -1042,12 +1043,13 @@ 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); 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); @@ -1142,6 +1144,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(); @@ -1205,6 +1210,10 @@ int main(int argc, char **argv) verbose_gain_set(dongle.dev, dongle.gain); } + 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/rtlsdr/src/main/jni/src/rtl_power.c b/rtlsdr/src/main/jni/src/rtl_power.c index aa7a138..8416176 100644 --- a/rtlsdr/src/main/jni/src/rtl_power.c +++ b/rtlsdr/src/main/jni/src/rtl_power.c @@ -133,6 +133,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" @@ -249,7 +250,7 @@ void sine_table(int size) } } -inline int16_t FIX_MPY(int16_t a, int16_t b) +static inline int16_t FIX_MPY(int16_t a, int16_t b) /* fixed point multiply and scale */ { int c = ((int)a * (int)b) >> 14; @@ -771,6 +772,7 @@ 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; @@ -781,7 +783,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:1PDOh")) != -1) { + while ((opt = getopt(argc, argv, "f:i:s:t:d:g:p:e:w:c:F:1PDOhT")) != -1) { switch (opt) { case 'f': // lower:upper:bin_size freq_optarg = strdup(optarg); @@ -849,6 +851,9 @@ int main(int argc, char **argv) boxcar = 0; comp_fir_size = atoi(optarg); break; + case 'T': + enable_biastee = 1; + break; case 'h': default: usage(); @@ -908,7 +913,7 @@ int main(int argc, char **argv) #endif if (direct_sampling) { - verbose_direct_sampling(dev, 1); + verbose_direct_sampling(dev, 2); } if (offset_tuning) { @@ -925,6 +930,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/rtlsdr/src/main/jni/src/rtl_tcp.c b/rtlsdr/src/main/jni/src/rtl_tcp.c index 317e0f3..270e9f6 100644 --- a/rtlsdr/src/main/jni/src/rtl_tcp.c +++ b/rtlsdr/src/main/jni/src/rtl_tcp.c @@ -61,15 +61,8 @@ static pthread_t command_thread; static pthread_cond_t exit_cond; static pthread_mutex_t exit_cond_lock; -static pthread_mutex_t ll_mutex; static pthread_cond_t cond; -struct llist { - char *data; - size_t len; - struct llist *next; -}; - typedef struct { /* structure size must be multiple of 2 bytes */ char magic[4]; uint32_t tuner_type; @@ -78,9 +71,18 @@ typedef struct { /* structure size must be multiple of 2 bytes */ static rtlsdr_dev_t *dev = NULL; -static int global_numq = 0; -static struct llist *ll_buffers = 0; -static int llbuf_num = 500; +static int enable_biastee = 0; + +// Ring Buffer declarations +// 8MB appears to cover several seconds at high bitrates -- about as much lag as you'd want +#define RINGBUFSZ_INIT (8*1024*1024) +static int ringbuf_sz = RINGBUFSZ_INIT; +static int ringbuf_trimsz = 512*1024; +static unsigned char *ringbuf = NULL; +static volatile unsigned int ringbuf_head = 0; +static volatile unsigned int ringbuf_tail = 0; +static unsigned int total_radio_bytes = 0; +static unsigned int max_bytes_in_flight = 0; static volatile int do_exit = 0; @@ -95,7 +97,9 @@ 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" + "\t[-D enable direct sampling (default: off)]\n"); exit(1); } @@ -143,53 +147,60 @@ static void sighandler(int signum) void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) { + static time_t lasttime = 0; + static int lastbytes = 0; + time_t curtime; + if(!do_exit) { - struct llist *rpt = (struct llist*)malloc(sizeof(struct llist)); - rpt->data = (char*)malloc(len); - memcpy(rpt->data, buf, len); - rpt->len = len; - rpt->next = NULL; - - pthread_mutex_lock(&ll_mutex); - - if (ll_buffers == NULL) { - ll_buffers = rpt; - } else { - struct llist *cur = ll_buffers; - int num_queued = 0; - - while (cur->next != NULL) { - cur = cur->next; - num_queued++; - } + unsigned int bufferleft; - if(llbuf_num && llbuf_num == num_queued-2){ - struct llist *curelem; + if (ringbuf == NULL) + { + printf("Allocate %d bytes for ringbuf.\n", ringbuf_sz); + ringbuf = (unsigned char*)malloc(ringbuf_sz); + } - free(ll_buffers->data); - curelem = ll_buffers->next; - free(ll_buffers); - ll_buffers = curelem; + bufferleft = ringbuf_sz - ((ringbuf_head < ringbuf_tail) ? (ringbuf_head - ringbuf_tail + ringbuf_sz) : (ringbuf_head - ringbuf_tail)); + if (len < bufferleft) + { + if ((ringbuf_head+len) < (unsigned int)ringbuf_sz) + { + memcpy(((unsigned char*)(ringbuf+ringbuf_head)), buf, len); } + else + { + memcpy(((unsigned char*)ringbuf+ringbuf_head), buf, ringbuf_sz-ringbuf_head); + memcpy((unsigned char*)ringbuf, buf+(ringbuf_sz-ringbuf_head), len-(ringbuf_sz-ringbuf_head)); + } + ringbuf_head = (ringbuf_head + len) % ringbuf_sz; + } + else + { + printf("overrun: head=%d tail=%d, Trimming %d bytes from tail of buffer\n", ringbuf_head, ringbuf_tail, ringbuf_trimsz); + ringbuf_tail = (ringbuf_tail + ringbuf_trimsz) % ringbuf_sz; + } - cur->next = rpt; - - if (num_queued > global_numq) - printf("ll+, now %d\n", num_queued); - else if (num_queued < global_numq) - printf("ll-, now %d\n", num_queued); - - global_numq = num_queued; + total_radio_bytes += len; + curtime = time (NULL); + if ((curtime - lasttime) > 30) + { + int nsecs = curtime - lasttime; + int nbytes = total_radio_bytes - lastbytes; + int bytes_in_flight = (ringbuf_head - ringbuf_tail); + if (bytes_in_flight < 0) + bytes_in_flight = ringbuf_sz + bytes_in_flight; + lasttime=curtime; + lastbytes=total_radio_bytes; + printf(">> [ %3.2fMB/s ] [ bytes_in_flight(cur/max) = %4dK / %4dK ]\n", + (float)nbytes/(float)nsecs/1000.0/1000.0, bytes_in_flight/1024, max_bytes_in_flight/1024); + max_bytes_in_flight=0; } - pthread_cond_signal(&cond); - pthread_mutex_unlock(&ll_mutex); } } static void *tcp_worker(void *arg) { - struct llist *curelem,*prev; - int bytesleft,bytessent, index; + int bytesleft, bytessent; struct timeval tv= {1,0}; struct timespec ts; struct timeval tp; @@ -200,47 +211,33 @@ static void *tcp_worker(void *arg) if(do_exit) pthread_exit(0); - pthread_mutex_lock(&ll_mutex); - gettimeofday(&tp, NULL); - ts.tv_sec = tp.tv_sec+5; - ts.tv_nsec = tp.tv_usec * 1000; - r = pthread_cond_timedwait(&cond, &ll_mutex, &ts); - if(r == ETIMEDOUT) { - pthread_mutex_unlock(&ll_mutex); - printf("worker cond timeout\n"); - sighandler(0); - pthread_exit(NULL); - } - - curelem = ll_buffers; - ll_buffers = 0; - pthread_mutex_unlock(&ll_mutex); - - while(curelem != 0) { - bytesleft = curelem->len; - index = 0; - bytessent = 0; - while(bytesleft > 0) { - FD_ZERO(&writefds); - FD_SET(s, &writefds); - tv.tv_sec = 1; - tv.tv_usec = 0; - r = select(s+1, NULL, &writefds, NULL, &tv); - if(r) { - bytessent = send(s, &curelem->data[index], bytesleft, 0); - bytesleft -= bytessent; - index += bytessent; - } - if(bytessent == SOCKET_ERROR || do_exit) { - printf("worker socket bye\n"); - sighandler(0); - pthread_exit(NULL); - } - } - prev = curelem; - curelem = curelem->next; - free(prev->data); - free(prev); + bytesleft = (ringbuf_head < ringbuf_tail) ? + (ringbuf_head - ringbuf_tail + ringbuf_sz) : + (ringbuf_head - ringbuf_tail); + while (bytesleft > 0) + { + FD_ZERO(&writefds); + FD_SET(s, &writefds); + tv.tv_sec = 1; + tv.tv_usec = 0; + r = select(s+1, NULL, &writefds, NULL, &tv); + if(r) { + unsigned int sendchunk; + if (ringbuf_tail < ringbuf_head) + sendchunk = ringbuf_head - ringbuf_tail; + else + sendchunk = ringbuf_sz - ringbuf_tail; + if (sendchunk > max_bytes_in_flight) + max_bytes_in_flight = sendchunk; + bytessent = send(s, (unsigned char*)(ringbuf+ringbuf_tail), sendchunk, 0); + bytesleft -= bytessent; + ringbuf_tail = (ringbuf_tail + bytessent) % ringbuf_sz; + } + if(bytessent == SOCKET_ERROR || do_exit) { + printf("worker socket bye\n"); + sighandler(0); + pthread_exit(NULL); + } } } } @@ -355,6 +352,10 @@ static void *command_worker(void *arg) printf("set tuner gain by index %d\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; } @@ -374,6 +375,7 @@ int main(int argc, char **argv) int dev_given = 0; int gain = 0; int ppm_error = 0; + int direct_sampling = 0; struct llist *curelem,*prev; pthread_attr_t attr; void *status; @@ -391,7 +393,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:d:P:T:D")) != -1) { switch (opt) { case 'd': dev_index = verbose_device_search(optarg); @@ -415,12 +417,15 @@ int main(int argc, char **argv) case 'b': buf_num = atoi(optarg); break; - case 'n': - llbuf_num = atoi(optarg); - break; case 'P': ppm_error = atoi(optarg); break; + case 'T': + enable_biastee = 1; + break; + case 'D': + direct_sampling = 1; + break; default: usage(); break; @@ -435,7 +440,7 @@ int main(int argc, char **argv) } if (dev_index < 0) { - exit(1); + exit(1); } rtlsdr_open(&dev, (uint32_t)dev_index); @@ -457,6 +462,11 @@ int main(int argc, char **argv) SetConsoleCtrlHandler( (PHANDLER_ROUTINE) sighandler, TRUE ); #endif + /* Set direct sampling */ + if (direct_sampling) { + verbose_direct_sampling(dev, 2); + } + /* Set the tuner error */ verbose_ppm_set(dev, ppm_error); @@ -491,13 +501,16 @@ 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) fprintf(stderr, "WARNING: Failed to reset buffers.\n"); pthread_mutex_init(&exit_cond_lock, NULL); - pthread_mutex_init(&ll_mutex, NULL); pthread_mutex_init(&exit_cond_lock, NULL); pthread_cond_init(&cond, NULL); pthread_cond_init(&exit_cond, NULL); @@ -523,10 +536,10 @@ int main(int argc, char **argv) while(1) { printf("listening...\n"); printf("Use the device argument 'rtl_tcp=%s:%d' in OsmoSDR " - "(gr-osmosdr) source\n" - "to receive samples in GRC and control " - "rtl_tcp parameters (frequency, gain, ...).\n", - addr, port); + "(gr-osmosdr) source\n" + "to receive samples in GRC and control " + "rtl_tcp parameters (frequency, gain, ...).\n", + addr, port); listen(listensocket,1); while(1) { @@ -577,24 +590,20 @@ int main(int argc, char **argv) closesocket(s); printf("all threads dead..\n"); - curelem = ll_buffers; - ll_buffers = 0; - - while(curelem != 0) { - prev = curelem; - curelem = curelem->next; - free(prev->data); - free(prev); - } + + // Clear stale data for next client + ringbuf_head = ringbuf_tail = 0; + memset(ringbuf, 0, ringbuf_sz); do_exit = 0; - global_numq = 0; } out: rtlsdr_close(dev); closesocket(listensocket); closesocket(s); + if (ringbuf) + free(ringbuf); #ifdef _WIN32 WSACleanup(); #endif diff --git a/rtlsdr/src/main/jni/src/rtl_test.c b/rtlsdr/src/main/jni/src/rtl_test.c index 9a6cfda..9b44097 100644 --- a/rtlsdr/src/main/jni/src/rtl_test.c +++ b/rtlsdr/src/main/jni/src/rtl_test.c @@ -53,6 +53,21 @@ #define PPM_DURATION 10 #define PPM_DUMP_TIME 5 +struct time_generic +/* holds all the platform specific values */ +{ +#ifndef _WIN32 + time_t tv_sec; + long tv_nsec; +#else + long tv_sec; + long tv_nsec; + int init; + LARGE_INTEGER frequency; + LARGE_INTEGER ticks; +#endif +}; + static enum { NO_BENCHMARK, TUNER_BENCHMARK, @@ -134,21 +149,42 @@ static void underrun_test(unsigned char *buf, uint32_t len, int mute) } #ifndef _WIN32 -static int ppm_gettime(struct timespec *ts) +static int ppm_gettime(struct time_generic *tg) { int rv = ENOSYS; + struct timespec ts; #ifdef __unix__ - rv = clock_gettime(CLOCK_MONOTONIC, ts); + rv = clock_gettime(CLOCK_MONOTONIC, &ts); + tg->tv_sec = ts.tv_sec; + tg->tv_nsec = ts.tv_nsec; #elif __APPLE__ struct timeval tv; rv = gettimeofday(&tv, NULL); - ts->tv_sec = tv.tv_sec; - ts->tv_nsec = tv.tv_usec * 1000; + tg->tv_sec = tv.tv_sec; + tg->tv_nsec = tv.tv_usec * 1000; #endif return rv; } +#endif + +#ifdef _WIN32 +static int ppm_gettime(struct time_generic *tg) +{ + int rv; + int64_t frac; + if (!tg->init) { + QueryPerformanceFrequency(&tg->frequency); + tg->init = 1; + } + rv = QueryPerformanceCounter(&tg->ticks); + tg->tv_sec = tg->ticks.QuadPart / tg->frequency.QuadPart; + frac = (int64_t)(tg->ticks.QuadPart - (tg->tv_sec * tg->frequency.QuadPart)); + tg->tv_nsec = (long)(frac * 1000000000L / (int64_t)tg->frequency.QuadPart); + return !rv; +} +#endif static int ppm_report(uint64_t nsamples, uint64_t interval) { @@ -165,8 +201,8 @@ static void ppm_test(uint32_t len) static uint64_t interval = 0; static uint64_t nsamples_total = 0; static uint64_t interval_total = 0; - struct timespec ppm_now; - static struct timespec ppm_recent; + struct time_generic ppm_now; + static struct time_generic ppm_recent; static enum { PPM_INIT_NO, PPM_INIT_DUMP, @@ -174,6 +210,7 @@ static void ppm_test(uint32_t len) } ppm_init = PPM_INIT_NO; ppm_gettime(&ppm_now); + if (ppm_init != PPM_INIT_RUN) { /* * Kyle Keen wrote: @@ -189,11 +226,11 @@ static void ppm_test(uint32_t len) } if (ppm_init == PPM_INIT_DUMP && ppm_recent.tv_sec < ppm_now.tv_sec) return; - ppm_recent.tv_sec = ppm_now.tv_sec; - ppm_recent.tv_nsec = ppm_now.tv_nsec; + ppm_recent = ppm_now; ppm_init = PPM_INIT_RUN; return; } + nsamples += (uint64_t)(len / 2UL); interval = (uint64_t)(ppm_now.tv_sec - ppm_recent.tv_sec); if (interval < ppm_duration) @@ -206,19 +243,16 @@ static void ppm_test(uint32_t len) (int)((1000000000UL * nsamples) / interval), ppm_report(nsamples, interval), ppm_report(nsamples_total, interval_total)); - ppm_recent.tv_sec = ppm_now.tv_sec; - ppm_recent.tv_nsec = ppm_now.tv_nsec; + ppm_recent = ppm_now; nsamples = 0; } -#endif static void rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx) { underrun_test(buf, len, 0); -#ifndef _WIN32 + if (test_mode == PPM_BENCHMARK) ppm_test(len); -#endif } void e4k_benchmark(void) @@ -375,7 +409,7 @@ int main(int argc, char **argv) verbose_reset_buffer(dev); if ((test_mode == PPM_BENCHMARK) && !sync_mode) { - fprintf(stderr, "Reporting PPM error measurement every %i seconds...\n", ppm_duration); + fprintf(stderr, "Reporting PPM error measurement every %u seconds...\n", ppm_duration); fprintf(stderr, "Press ^C after a few minutes.\n"); } diff --git a/rtlsdr/src/main/jni/src/tuner_r82xx.c b/rtlsdr/src/main/jni/src/tuner_r82xx.c index f620238..8074ee3 100644 --- a/rtlsdr/src/main/jni/src/tuner_r82xx.c +++ b/rtlsdr/src/main/jni/src/tuner_r82xx.c @@ -447,11 +447,16 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq) if (rc < 0) return rc; - /* set VCO current = 100 */ - rc = r82xx_write_reg_mask(priv, 0x12, 0x80, 0xe0); + /* set VCO current = 100 RTL-SDRBLOG MOD: MAX CURRENT*/ + rc = r82xx_write_reg_mask(priv, 0x12, 0x06, 0xff); if (rc < 0) return rc; + // Test turning tracking filter off + //rc = r82xx_write_reg_mask(priv, 0x1a, 0x40, 0xC0); + + + /* Calculate divider */ while (mix_div <= 64) { if (((freq_khz * mix_div) >= vco_min) && @@ -540,7 +545,7 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq) if (!i) { /* Didn't lock. Increase VCO current */ - rc = r82xx_write_reg_mask(priv, 0x12, 0x60, 0xe0); + rc = r82xx_write_reg_mask(priv, 0x12, 0x06, 0xff); if (rc < 0) return rc; } @@ -663,6 +668,9 @@ static int r82xx_sysfreq_sel(struct r82xx_priv *priv, uint32_t freq, rc = r82xx_write_reg_mask(priv, 0x11, cp_cur, 0x38); if (rc < 0) return rc; + + // RTLSDRBLOG. Improve L-band performance by setting PLL drop out to 2.0v + div_buf_cur = 0xa0; rc = r82xx_write_reg_mask(priv, 0x17, div_buf_cur, 0x30); if (rc < 0) return rc; @@ -770,78 +778,18 @@ static int r82xx_set_tv_standard(struct r82xx_priv *priv, uint8_t lt_att, flt_ext_widest, polyfil_cur; int need_calibration; - if (delsys == SYS_ISDBT) { - if_khz = 4063; - filt_cal_lo = 59000; - filt_gain = 0x10; /* +3db, 6mhz on */ - img_r = 0x00; /* image negative */ - filt_q = 0x10; /* r10[4]:low q(1'b1) */ - hp_cor = 0x6a; /* 1.7m disable, +2cap, 1.25mhz */ - ext_enable = 0x40; /* r30[6], ext enable; r30[5]:0 ext at lna max */ - loop_through = 0x00; /* r5[7], lt on */ - lt_att = 0x00; /* r31[7], lt att enable */ - flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */ - polyfil_cur = 0x60; /* r25[6:5]:min */ - } else { - if (bw <= 6) { - if_khz = 3570; - filt_cal_lo = 56000; /* 52000->56000 */ - filt_gain = 0x10; /* +3db, 6mhz on */ - img_r = 0x00; /* image negative */ - filt_q = 0x10; /* r10[4]:low q(1'b1) */ - hp_cor = 0x6b; /* 1.7m disable, +2cap, 1.0mhz */ - ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */ - loop_through = 0x00; /* r5[7], lt on */ - lt_att = 0x00; /* r31[7], lt att enable */ - flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */ - polyfil_cur = 0x60; /* r25[6:5]:min */ - } else if (bw == 7) { -#if 0 - /* - * There are two 7 MHz tables defined on the original - * driver, but just the second one seems to be visible - * by rtl2832. Keep this one here commented, as it - * might be needed in the future - */ - - if_khz = 4070; - filt_cal_lo = 60000; - filt_gain = 0x10; /* +3db, 6mhz on */ - img_r = 0x00; /* image negative */ - filt_q = 0x10; /* r10[4]:low q(1'b1) */ - hp_cor = 0x2b; /* 1.7m disable, +1cap, 1.0mhz */ - ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */ - loop_through = 0x00; /* r5[7], lt on */ - lt_att = 0x00; /* r31[7], lt att enable */ - flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */ - polyfil_cur = 0x60; /* r25[6:5]:min */ -#endif - /* 7 MHz, second table */ - if_khz = 4570; - filt_cal_lo = 63000; - filt_gain = 0x10; /* +3db, 6mhz on */ - img_r = 0x00; /* image negative */ - filt_q = 0x10; /* r10[4]:low q(1'b1) */ - hp_cor = 0x2a; /* 1.7m disable, +1cap, 1.25mhz */ - ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */ - loop_through = 0x00; /* r5[7], lt on */ - lt_att = 0x00; /* r31[7], lt att enable */ - flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */ - polyfil_cur = 0x60; /* r25[6:5]:min */ - } else { - if_khz = 4570; - filt_cal_lo = 68500; - filt_gain = 0x10; /* +3db, 6mhz on */ - img_r = 0x00; /* image negative */ - filt_q = 0x10; /* r10[4]:low q(1'b1) */ - hp_cor = 0x0b; /* 1.7m disable, +0cap, 1.0mhz */ - ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */ - loop_through = 0x00; /* r5[7], lt on */ - lt_att = 0x00; /* r31[7], lt att enable */ - flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */ - polyfil_cur = 0x60; /* r25[6:5]:min */ - } - } + /* BW < 6 MHz */ + if_khz = 3570; + filt_cal_lo = 56000; /* 52000->56000 */ + filt_gain = 0x10; /* +3db, 6mhz on */ + img_r = 0x00; /* image negative */ + filt_q = 0x10; /* r10[4]:low q(1'b1) */ + hp_cor = 0x6b; /* 1.7m disable, +2cap, 1.0mhz */ + ext_enable = 0x60; /* r30[6]=1 ext enable; r30[5]:1 ext at lna max-1 */ + loop_through = 0x01; /* r5[7], lt off */ + lt_att = 0x00; /* r31[7], lt att enable */ + flt_ext_widest = 0x00; /* r15[7]: flt_ext_wide off */ + polyfil_cur = 0x60; /* r25[6:5]:min */ /* Initialize the shadow registers */ memcpy(priv->regs, r82xx_init_array, sizeof(r82xx_init_array)); @@ -1028,7 +976,7 @@ int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain) return rc; /* set fixed VGA gain for now (16.3 dB) */ - rc = r82xx_write_reg_mask(priv, 0x0c, 0x08, 0x9f); + rc = r82xx_write_reg_mask(priv, 0x0c, 0x08, 0x9f); //init val 0x08 0x0c works well at 1.7 if (rc < 0) return rc; @@ -1196,7 +1144,7 @@ int r82xx_standby(struct r82xx_priv *priv) rc = r82xx_write_reg(priv, 0x06, 0xb1); if (rc < 0) return rc; - rc = r82xx_write_reg(priv, 0x05, 0x03); + rc = r82xx_write_reg(priv, 0x05, 0xa0); if (rc < 0) return rc; rc = r82xx_write_reg(priv, 0x07, 0x3a);