From 22a920d0a6df6c2945b026b611791a4b18ccd87a Mon Sep 17 00:00:00 2001 From: hayati ayguen Date: Sun, 28 Jul 2019 01:21:21 +0200 Subject: [PATCH] merge of great additions, e.g. rtlsdr_set_tuner_sideband() * rtlsdr_set_tuner_sideband(): - "HF-Hase" Bernhard Kistinger (DB9PP) found out, that one of the undocumented I2C register bits of R820T tuner controls the used tuner/mixer lower or supper sideband. That was by testing/playing with a special QIRX version, showing and allowing change of all I2C registers. - previous additions in rtl_tcp allowed control of I2C registers; in addition register contents can be transmitted periodically (to QIRX) - "Oldenburger" developed a first version controlling the sideband bit, and additional spectral flipping (spectrum inversion) in the RTL2832 - i've merged Oldenburger's changes with my rtlsdr_set_tuner_band_center() => altogether, there's no spectrum inversion, the band center stays, just the IF filters (steep lowpass and not-so-steep highpass) switch positions * Oldenburger's changes for FC0012 tuner * Oldenburger added description of R820T's I2C registers * rtl_tcp's new response channel now occupies an additional port, usally 1235, which is +1 of default control port. this can be deactivated by command line Signed-off-by: hayati ayguen --- include/controlThread.h | 43 +++ include/rtl-sdr.h | 9 + include/rtl_tcp.h | 3 + include/tuner_fc0012.h | 2 + include/tuner_r82xx.h | 8 +- src/CMakeLists.txt | 2 +- src/controlThread.c | 230 ++++++++++++++ src/librtlsdr.c | 270 ++++++++++++++--- src/rtl_tcp.c | 54 +++- src/rtl_udp.c | 9 + src/tuner_fc0012.c | 98 ++++-- src/tuner_r82xx.c | 655 +++++++++++++++++++++------------------- 12 files changed, 995 insertions(+), 388 deletions(-) create mode 100644 include/controlThread.h create mode 100644 src/controlThread.c diff --git a/include/controlThread.h b/include/controlThread.h new file mode 100644 index 0000000..0cccae1 --- /dev/null +++ b/include/controlThread.h @@ -0,0 +1,43 @@ +/* + * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver + * Copyright (C) 2019 <> + * + * 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 . + */ + +#ifndef __RTL_CONTROL_THREAD_H +#define __RTL_CONTROL_THREAD_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + rtlsdr_dev_t *dev; + SOCKET port; + int wait; + int report_i2c; + char *addr; + int* pDoExit; +} +ctrl_thread_data_t; +void *ctrl_thread_fn(void *arg); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h index 026cab1..6adb993 100755 --- a/include/rtl-sdr.h +++ b/include/rtl-sdr.h @@ -253,6 +253,15 @@ RTLSDR_API int rtlsdr_set_tuner_bandwidth(rtlsdr_dev_t *dev, uint32_t bw ); */ RTLSDR_API int rtlsdr_set_tuner_band_center(rtlsdr_dev_t *dev, int32_t if_band_center_freq ); +/*! + * Set the mixer sideband for the device. + * + * \param dev the device handle given by rtlsdr_open() + * \param sideband mixer sideband 0 means lower sideband, 1 means upper sideband. + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_tuner_sideband(rtlsdr_dev_t *dev, int sideband); + /*! * Get actual gain the device is configured to. * diff --git a/include/rtl_tcp.h b/include/rtl_tcp.h index 3d2477e..d01dadc 100644 --- a/include/rtl_tcp.h +++ b/include/rtl_tcp.h @@ -65,6 +65,9 @@ enum RTL_TCP_COMMANDS { * the bandwidth (from SET_TUNER_BANDWIDTH) * is set to be centered at given IF frequency */ SET_TUNER_AGC_VARIANT = 0x46, /* set tuner agc algorithm/variant */ + SET_SIDEBAND = 0x47, /* Mixer Sideband for R820T */ + REPORT_I2C_REGS = 0x48, /* perodically report I2C registers + * - if reverse channel is enabled */ }; #ifdef __cplusplus diff --git a/include/tuner_fc0012.h b/include/tuner_fc0012.h index 9dd5356..3406551 100644 --- a/include/tuner_fc0012.h +++ b/include/tuner_fc0012.h @@ -32,5 +32,7 @@ int fc0012_init(void *dev); int fc0012_set_params(void *dev, uint32_t freq, uint32_t bandwidth); int fc0012_set_gain(void *dev, int gain); +int fc0012_set_i2c_register(void *dev, unsigned i2c_register, unsigned data); +int fc0012_get_i2c_register(void *dev, unsigned char* data, int len); #endif diff --git a/include/tuner_r82xx.h b/include/tuner_r82xx.h index c94e9ab..70c8bad 100755 --- a/include/tuner_r82xx.h +++ b/include/tuner_r82xx.h @@ -35,7 +35,7 @@ #define R82XX_IF_FREQ 3570000 #define REG_SHADOW_START 5 -#define NUM_REGS 30 +#define NUM_REGS 32 #define NUM_IMR 5 #define IMR_TRIAL 9 @@ -89,6 +89,7 @@ struct r82xx_priv { uint8_t input; int has_lock; int init_done; + int sideband; /* Store current mode */ uint32_t delsys; @@ -140,14 +141,17 @@ 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_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain); 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_set_agc_mode(struct r82xx_priv *priv, int agc_mode, int *rtl_vga_control); + int r82xx_set_i2c_register(struct r82xx_priv *priv, unsigned i2c_register, unsigned data, unsigned mask); +int r82xx_get_i2c_register(struct r82xx_priv *priv, unsigned char* data, int len); int r82xx_set_i2c_override(struct r82xx_priv *priv, unsigned i2c_register, unsigned data, unsigned mask); int r82xx_set_bandwidth(struct r82xx_priv *priv, int bandwidth, uint32_t rate, uint32_t * applied_bw, int apply); int r82xx_set_bw_center(struct r82xx_priv *priv, int32_t if_band_center_freq); +/* Mixer Sideband: 0: lower, 1: upper */ +int r82xx_set_sideband(struct r82xx_priv *priv, int sideband); int r82xx_read_cache_reg(struct r82xx_priv *priv, int reg); int r82xx_write_reg_mask(struct r82xx_priv *priv, uint8_t reg, uint8_t val,uint8_t bit_mask); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 68d71b0..c544791 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -119,7 +119,7 @@ endif() # Build utility ######################################################################## add_executable(rtl_sdr rtl_sdr.c) -add_executable(rtl_tcp rtl_tcp.c) +add_executable(rtl_tcp rtl_tcp.c controlThread.c) add_executable(rtl_udp rtl_udp.c) add_executable(rtl_test rtl_test.c) add_executable(rtl_fm rtl_fm.c) diff --git a/src/controlThread.c b/src/controlThread.c new file mode 100644 index 0000000..f7a2d56 --- /dev/null +++ b/src/controlThread.c @@ -0,0 +1,230 @@ +/* + * rtl-sdr, turns your Realtek RTL2832 based DVB dongle into a SDR receiver + * Copyright (C) 2012 by Steve Markgraf + * Copyright (C) 2012-2013 by Hoernchen + * + * 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 +#include +#include + +#ifndef _WIN32 +#include +#include +#include +#include +#include +#include +#include +#include +#else +#include +#include "getopt/getopt.h" +#define usleep(x) Sleep(x/1000) +#endif + +#ifdef NEED_PTHREADS_WORKARROUND +#define HAVE_STRUCT_TIMESPEC +#endif +#include + +#include "rtl-sdr.h" +#include "rtl_tcp.h" +#include "controlThread.h" +#include "convenience/convenience.h" + +#include "tuner_r82xx.h" + +#ifdef _WIN32 +#pragma comment(lib, "ws2_32.lib") + +typedef int socklen_t; + +#else +#define closesocket close +#define SOCKADDR struct sockaddr +#define SOCKET int +#define SOCKET_ERROR -1 +#endif + +/* we need a message id in the protocol: 1st 2 byte (little endian) == message id */ +#define USE_MSGID_IN_PROTOCOL 1 + +#define NUM_I2C_REGISTERS 32 +#define TX_BUF_LEN (NUM_I2C_REGISTERS +4) //2 len, 1 head, 1 tail + + +ctrl_thread_data_t ctrl_thread_data; + +void *ctrl_thread_fn(void *arg) +{ + unsigned char reg_values [NUM_I2C_REGISTERS]; +#if USE_MSGID_IN_PROTOCOL + unsigned char txbuf [2+2 +1+NUM_I2C_REGISTERS+1]; //2 type, 2 length, 1 head, 1 tail +#else + unsigned char txbuf [NUM_I2C_REGISTERS+4]; //2 length, 1 head, 1 tail +#endif + int r = 1; + struct timeval tv = { 1,0 }; + struct linger ling = { 1,0 }; + SOCKET listensocket; + SOCKET controlSocket; + struct sockaddr_in local, remote; + socklen_t rlen; + + int error = 0; + int ret = 0, len, result; + fd_set connfds; + fd_set writefds; + int bytesleft, bytessent, index; + + ctrl_thread_data_t *data = (ctrl_thread_data_t *)arg; + + rtlsdr_dev_t *dev = data->dev; + int port = data->port; + int wait = data->wait; + int report_i2c = data->report_i2c; + char *addr = data->addr; + int* do_exit = data->pDoExit; + u_long blockmode = 1; + + + memset(reg_values, 0, NUM_I2C_REGISTERS); + + memset(&local, 0, sizeof(local)); + local.sin_family = AF_INET; + local.sin_port = htons(port); + local.sin_addr.s_addr = inet_addr(addr); + + listensocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + + setsockopt(listensocket, SOL_SOCKET, SO_REUSEADDR, (char *)&r, sizeof(int)); + setsockopt(listensocket, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); + int retval = bind(listensocket, (struct sockaddr *)&local, sizeof(local)); + if (retval == SOCKET_ERROR) + error = WSAGetLastError(); +#ifdef _WIN32 + ioctlsocket(listensocket, FIONBIO, &blockmode); +#else + r = fcntl(listensocket, F_GETFL, 0); + r = fcntl(listensocket, F_SETFL, r | O_NONBLOCK); +#endif + + while (1) { + printf("listening on Control port %d...\n", port); + retval = listen(listensocket, 1); + if (retval == SOCKET_ERROR) +#ifdef _WIN32 + error = WSAGetLastError(); +#else + ; +#endif + while (1) { + FD_ZERO(&connfds); + FD_SET(listensocket, &connfds); + tv.tv_sec = 1; + tv.tv_usec = 0; + r = select(listensocket + 1, &connfds, NULL, NULL, &tv); + if (*do_exit) { + goto close; + } + else if (r) { + rlen = sizeof(remote); + controlSocket = accept(listensocket, (struct sockaddr *)&remote, &rlen); + break; + } + } + + setsockopt(controlSocket, SOL_SOCKET, SO_LINGER, (char *)&ling, sizeof(ling)); + + printf("Control client accepted!\n"); + usleep(5000000); + + while (1) { + + /* check if i2c reporting is to be (de)activated */ + if ( report_i2c && !data->report_i2c ) + report_i2c = 0; + else if ( !report_i2c && data->report_i2c ) + report_i2c = 1; + + /* @TODO: check if something else has to be transmitted */ + + if ( !report_i2c ) + goto sleep; + + result = rtlsdr_get_tuner_i2c_register(dev, reg_values, NUM_I2C_REGISTERS); + /* printf("rtlsdr_get_tuner_i2c_register\n"); */ + memset(txbuf, 0, TX_BUF_LEN); + if (result) + goto sleep; + + /* Little Endian */ + len = 0; + /* we need some message id: use enum RTL_TCP_COMMANDS */ +#if USE_MSGID_IN_PROTOCOL + txbuf[len++] = REPORT_I2C_REGS & 0x0FF; + txbuf[len++] = (REPORT_I2C_REGS >> 8) & 0x0FF; + /* following message length in Little Endian */ + txbuf[len++] = TX_BUF_LEN - 2 - 2; /* sub message id and length field */ +#else + txbuf[len++] = TX_BUF_LEN - 2; /* sub message id and length field */ +#endif + txbuf[len++] = 0; + + /* now the message contents */ + txbuf[len++] = 0x55; /* @CS: do we need this? */ + memcpy(&txbuf[len], reg_values, NUM_I2C_REGISTERS); + txbuf[TX_BUF_LEN - 1] = 0xaa; /* @CS: do we need this? */ + len = sizeof(txbuf); + + /* now start (possibly blocking) transmission */ + bytessent = 0; + bytesleft = len; + index = 0; + + while (bytesleft > 0) { + FD_ZERO(&writefds); + FD_SET(controlSocket, &writefds); + tv.tv_sec = 1; + tv.tv_usec = 0; + r = select(controlSocket + 1, NULL, &writefds, NULL, &tv); + if (r) { + bytessent = send(controlSocket, &txbuf[index], bytesleft, 0); + bytesleft -= bytessent; + index += bytessent; + } + if (bytessent == SOCKET_ERROR || *do_exit) { + goto close; + } + } +sleep: + usleep(wait); + } +close: + closesocket(controlSocket); + if (*do_exit) + { + closesocket(listensocket); + printf("Control Thread terminates\n"); + break; + } + } + return 0; +} + diff --git a/src/librtlsdr.c b/src/librtlsdr.c index 052ece7..986d05b 100644 --- a/src/librtlsdr.c +++ b/src/librtlsdr.c @@ -107,7 +107,9 @@ typedef struct rtlsdr_tuner_iface { int (*set_gain_mode)(void *, int manual); int (*set_i2c_register)(void *, unsigned i2c_register, unsigned data /* byte */, unsigned mask /* byte */ ); int (*set_i2c_override)(void *, unsigned i2c_register, unsigned data /* byte */, unsigned mask /* byte */ ); - unsigned (*get_i2c_register)(void *, int i2c_register); + unsigned (*get_i2c_register)(void *, int i2c_register); /* read single register */ + int (*get_i2c_reg_array)(void *, unsigned char* data, int len); /* -cs- */ + int (*set_sideband)(void *, int sideband); } rtlsdr_tuner_iface_t; enum rtlsdr_async_status { @@ -206,6 +208,8 @@ struct rtlsdr_dev { uint32_t bw; uint32_t offs_freq; /* Hz */ int32_t if_band_center_freq; /* Hz - rtlsdr_set_tuner_band_center() */ + int tuner_if_freq; + int tuner_sideband; int corr; /* ppm */ int gain; /* tenth dB */ enum rtlsdr_ds_mode direct_sampling_mode; @@ -216,6 +220,9 @@ struct rtlsdr_dev { /* soft tuner agc */ struct softagc_state softagc; + /* -cs- Concurrent lock for the periodic reading of I2C registers */ + pthread_mutex_t cs_mutex; + /* UDP controller server */ #ifdef WITH_UDP_SERVER #define UDP_TX_BUFLEN 1024 @@ -241,14 +248,13 @@ struct rtlsdr_dev { int rc_active; int verbose; int dev_num; - uint8_t saved_27; - int handled; }; -void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val); +static void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val); static int rtlsdr_demod_write_reg(rtlsdr_dev_t *dev, uint8_t page, uint16_t addr, uint16_t val, uint8_t len); 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); +static int rtlsdr_set_spectrum_inversion(rtlsdr_dev_t *dev, int sideband); static void softagc_init(rtlsdr_dev_t *dev); static void softagc_uninit(rtlsdr_dev_t *dev); @@ -310,7 +316,6 @@ int e4000_set_gain_mode(void *dev, int manual) { return e4k_enable_manual_gain(&devt->e4k_s, manual); } -int _fc0012_init(void *dev) { return fc0012_init(dev); } int fc0012_exit(void *dev) { return 0; } int fc0012_set_freq(void *dev, uint32_t freq) { /* select V-band/U-band filter */ @@ -318,8 +323,10 @@ int fc0012_set_freq(void *dev, uint32_t freq) { return fc0012_set_params(dev, freq, 6000000); } int fc0012_set_bw(void *dev, int bw, uint32_t *applied_bw, int apply) { return 0; } -int _fc0012_set_gain(void *dev, int gain) { return fc0012_set_gain(dev, gain); } int fc0012_set_gain_mode(void *dev, int manual) { return 0; } +int _fc0012_set_i2c_register(void *dev, unsigned i2c_register, unsigned data, unsigned mask ) { + return fc0012_set_i2c_register(dev, i2c_register, data); +} int _fc0013_init(void *dev) { return fc0013_init(dev); } int fc0013_exit(void *dev) { return 0; } @@ -372,7 +379,6 @@ int r820t_set_freq(void *dev, uint32_t freq) { return r82xx_set_freq(&devt->r82xx_p, freq); } -#define BWC_MUL_SIGN + int r820t_set_bw(void *dev, int bw, uint32_t *applied_bw, int apply) { int r, iffreq; @@ -383,15 +389,27 @@ int r820t_set_bw(void *dev, int bw, uint32_t *applied_bw, int apply) { return 0; if(iffreq < 0) { r = iffreq; + if ( devt->verbose ) + fprintf(stderr, "r820t_set_bw(%d): r82xx_set_bandwidth() returned error %d\n", bw, r); + return r; + } + devt->tuner_if_freq = iffreq; + + iffreq = (devt->tuner_sideband) /* -1 for USB; +1 for LSB */ + ? ( devt->tuner_if_freq - devt->if_band_center_freq ) + : ( devt->tuner_if_freq + devt->if_band_center_freq ); + r = rtlsdr_set_if_freq(devt, iffreq ); + if (r) + { + if ( devt->verbose ) + fprintf(stderr, "r820t_set_bw(%d): rtlsdr_set_if_freq(%d) returned error %d\n", bw, iffreq, r); return r; } - iffreq = iffreq BWC_MUL_SIGN devt->if_band_center_freq; - r = rtlsdr_set_if_freq(devt, iffreq ); - if (r) - return r; - - return rtlsdr_set_center_freq(devt, devt->freq); + r = rtlsdr_set_center_freq(devt, devt->freq); + if ( r && devt->verbose ) + fprintf(stderr, "r820t_set_bw(%d): rtlsdr_set_center_freq(%d) returned error %d\n", bw, devt->freq, r); + return r; } int r820t_set_bw_center(void *dev, int32_t if_band_center_freq) { @@ -401,16 +419,28 @@ int r820t_set_bw_center(void *dev, int32_t if_band_center_freq) { iffreq = r82xx_set_bw_center(&devt->r82xx_p, if_band_center_freq); if(iffreq < 0) { r = iffreq; + if ( devt->verbose ) + fprintf(stderr, "r820t_set_bw_center(%d): r82xx_set_bw_center() returned error %d\n", if_band_center_freq, r); + return r; + } + devt->tuner_if_freq = iffreq; + devt->if_band_center_freq = if_band_center_freq; + + iffreq = (devt->tuner_sideband) /* -1 for USB; +1 for LSB */ + ? ( devt->tuner_if_freq - devt->if_band_center_freq ) + : ( devt->tuner_if_freq + devt->if_band_center_freq ); + r = rtlsdr_set_if_freq(devt, iffreq ); + if (r) + { + if ( devt->verbose ) + fprintf(stderr, "r820t_set_bw_center(%d): rtlsdr_set_if_freq(%d) returned error %d\n", if_band_center_freq, iffreq, r); return r; } - devt->if_band_center_freq = if_band_center_freq; - iffreq = iffreq BWC_MUL_SIGN devt->if_band_center_freq; - r = rtlsdr_set_if_freq(devt, iffreq ); - if (r) - return r; - - return rtlsdr_set_center_freq(devt, devt->freq); + r = rtlsdr_set_center_freq(devt, devt->freq); + if ( r && devt->verbose ) + fprintf(stderr, "r820t_set_bw_center(%d): rtlsdr_set_center_freq(%d) returned error %d\n", if_band_center_freq, devt->freq, r); + return r; } int rtlsdr_vga_control( rtlsdr_dev_t* devt, int rc, int rtl_vga_control ) { @@ -469,6 +499,49 @@ int r820t_set_i2c_register(void *dev, unsigned i2c_register, unsigned data, unsi rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; return r82xx_set_i2c_register(&devt->r82xx_p, i2c_register, data, mask); } + + +/* -cs- */ +int r820t_get_i2c_reg_array(void *dev, unsigned char* data, int len) { + rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; + return r82xx_get_i2c_register(&devt->r82xx_p, data, len); +} + +int r820t_set_sideband(void *dev, int sideband) { + int r; + rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; + + if ( devt->verbose ) + fprintf(stderr, "r820t_set_sideband(%d): r82xx_set_sideband() ..\n", sideband); + r = r82xx_set_sideband(&devt->r82xx_p, sideband); + if(r < 0) { + if ( devt->verbose ) + fprintf(stderr, "r820t_set_sideband(%d): r82xx_set_sideband() returned %d\n", sideband, r); + return r; + } + + if ( devt->verbose ) + fprintf(stderr, "r820t_set_sideband(%d): rtlsdr_set_spectrum_inversion() ..\n", sideband); + r = rtlsdr_set_spectrum_inversion(devt, sideband); + if (r) { + if ( devt->verbose ) + fprintf(stderr, "r820t_set_sideband(%d): rtlsdr_set_spectrum_inversion() returned %d\n", sideband, r); + return r; + } + + if (!devt->freq) + return r; + + if ( devt->verbose ) + fprintf(stderr, "r820t_set_sideband(%d): rtlsdr_set_center_freq(%d) ..\n", sideband, devt->freq); + r = rtlsdr_set_center_freq(devt, devt->freq); + if (r) { + if ( devt->verbose ) + fprintf(stderr, "r820t_set_sideband(%d): rtlsdr_set_center_freq(%d) returned %d\n", sideband, devt->freq, r); + } + return r; +} + int r820t_set_i2c_override(void *dev, unsigned i2c_register, unsigned data, unsigned mask ) { rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; return r82xx_set_i2c_override(&devt->r82xx_p, i2c_register, data, mask); @@ -478,37 +551,40 @@ int r820t_set_i2c_override(void *dev, unsigned i2c_register, unsigned data, unsi /* definition order must match enum rtlsdr_tuner */ static rtlsdr_tuner_iface_t tuners[] = { { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* dummy for unknown tuners */ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* dummy for unknown tuners */ }, { e4000_init, e4000_exit, e4000_set_freq, e4000_set_bw, NULL, e4000_set_gain, e4000_set_if_gain, - e4000_set_gain_mode, NULL, NULL, NULL + e4000_set_gain_mode, NULL, NULL, NULL, NULL, NULL }, + { - _fc0012_init, fc0012_exit, - fc0012_set_freq, fc0012_set_bw, NULL, _fc0012_set_gain, NULL, - fc0012_set_gain_mode, NULL, NULL, NULL + fc0012_init, fc0012_exit, + fc0012_set_freq, fc0012_set_bw, NULL, fc0012_set_gain, NULL, + fc0012_set_gain_mode, _fc0012_set_i2c_register, NULL, NULL, fc0012_get_i2c_register, NULL }, { _fc0013_init, fc0013_exit, fc0013_set_freq, fc0013_set_bw, NULL, _fc0013_set_gain, NULL, - fc0013_set_gain_mode, NULL, NULL, NULL + fc0013_set_gain_mode, NULL, NULL, NULL, NULL, NULL }, { fc2580_init, fc2580_exit, _fc2580_set_freq, fc2580_set_bw, NULL, fc2580_set_gain, NULL, - fc2580_set_gain_mode, NULL, NULL, NULL + fc2580_set_gain_mode, NULL, NULL, NULL, NULL, NULL }, { r820t_init, r820t_exit, r820t_set_freq, r820t_set_bw, r820t_set_bw_center, r820t_set_gain, NULL, - r820t_set_gain_mode, r820t_set_i2c_register, r820t_set_i2c_override, r820t_get_i2c_register + r820t_set_gain_mode, r820t_set_i2c_register, r820t_set_i2c_override, r820t_get_i2c_register, r820t_get_i2c_reg_array, + r820t_set_sideband }, { r820t_init, r820t_exit, r820t_set_freq, r820t_set_bw, r820t_set_bw_center, r820t_set_gain, NULL, - r820t_set_gain_mode, r820t_set_i2c_register, r820t_set_i2c_override, r820t_get_i2c_register + r820t_set_gain_mode, r820t_set_i2c_register, r820t_set_i2c_override, r820t_get_i2c_register, r820t_get_i2c_reg_array, + r820t_set_sideband }, }; @@ -848,7 +924,13 @@ void rtlsdr_set_gpio_output(rtlsdr_dev_t *dev, uint8_t gpio) void rtlsdr_set_i2c_repeater(rtlsdr_dev_t *dev, int on) { + if (on) + pthread_mutex_lock(&dev->cs_mutex); + rtlsdr_demod_write_reg(dev, 1, 0x01, on ? 0x18 : 0x10, 1); + + if (!on) + pthread_mutex_unlock(&dev->cs_mutex); } int rtlsdr_set_fir(rtlsdr_dev_t *dev) @@ -996,6 +1078,18 @@ static int rtlsdr_set_if_freq(rtlsdr_dev_t *dev, uint32_t freq) return r; } +static int rtlsdr_set_spectrum_inversion(rtlsdr_dev_t *dev, int sideband) +{ + int r; + if(sideband) + /* disable spectrum inversion */ + r = rtlsdr_demod_write_reg(dev, 1, 0x15, 0x00, 1); + else + /* enable spectrum inversion */ + r = rtlsdr_demod_write_reg(dev, 1, 0x15, 0x01, 1); + return r; +} + int rtlsdr_set_sample_freq_correction(rtlsdr_dev_t *dev, int ppm) { int r = 0; @@ -1223,7 +1317,6 @@ int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq) rtlsdr_set_i2c_repeater(dev, 1); r = dev->tuner->set_freq(dev, freq - dev->offs_freq); rtlsdr_set_i2c_repeater(dev, 0); - reactivate_softagc(dev, SOFTSTATE_RESET); } if (!r) @@ -1231,13 +1324,6 @@ int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq) else dev->freq = 0; - /* restore filters */ - if (dev->handled) { - rtlsdr_set_i2c_repeater(dev, 1); - dev->tuner->set_i2c_register(dev, 27, dev->saved_27, 255); - rtlsdr_set_i2c_repeater(dev, 0); - } - return r; } @@ -1585,6 +1671,56 @@ int rtlsdr_set_tuner_gain_mode(rtlsdr_dev_t *dev, int mode) return r; } +int rtlsdr_set_tuner_sideband(rtlsdr_dev_t *dev, int sideband) +{ + int r = 0, iffreq; + rtlsdr_dev_t *devt = dev; + + if (!dev || !dev->tuner) + return -1; + + if (dev->tuner->set_sideband) { + if ( devt->verbose ) + fprintf(stderr, "rtlsdr_set_tuner_sideband(%d): tuner.set_sideband() ..\n", sideband); + + rtlsdr_set_i2c_repeater(dev, 1); + r = dev->tuner->set_sideband((void *)dev, sideband); + rtlsdr_set_i2c_repeater(dev, 0); + + if (r) + { + if ( devt->verbose ) + fprintf(stderr, "rtlsdr_set_tuner_sideband(%d): tuner.set_sideband() returned error %d\n", sideband, r); + return r; + } + devt->tuner_sideband = sideband; + + iffreq = (devt->tuner_sideband) /* -1 for USB; +1 for LSB */ + ? ( devt->tuner_if_freq - devt->if_band_center_freq ) + : ( devt->tuner_if_freq + devt->if_band_center_freq ); + fprintf(stderr, "rtlsdr_set_tuner_sideband(%d): rtlsdr_set_if_freq(%d) ..\n", sideband, iffreq); + r = rtlsdr_set_if_freq(devt, iffreq ); + if (r) + { + if ( devt->verbose ) + fprintf(stderr, "rtlsdr_set_tuner_sideband(%d): rtlsdr_set_if_freq(%d) returned error %d\n", sideband, iffreq); + return r; + } + + if (!devt->freq) + return r; + if (devt->verbose ) + fprintf(stderr, "rtlsdr_set_tuner_sideband(%d): rtlsdr_set_center_freq(%d) ..\n", sideband, devt->freq); + r = rtlsdr_set_center_freq(devt, devt->freq); + if (r && devt->verbose ) + fprintf(stderr, "rtlsdr_set_tuner_sideband(%d): rtlsdr_set_center_freq(%d) returned error %d\n", sideband, devt->freq, r); + + return r; + } + + return r; +} + int rtlsdr_set_tuner_i2c_register(rtlsdr_dev_t *dev, unsigned i2c_register, unsigned mask /* byte */, unsigned data /* byte */ ) { int r = 0; @@ -1608,6 +1744,23 @@ int rtlsdr_set_tuner_i2c_register(rtlsdr_dev_t *dev, unsigned i2c_register, unsi return r; } +/* -cs- */ +int rtlsdr_get_tuner_i2c_register(rtlsdr_dev_t *dev, unsigned char* data, int len) +{ + int r = 0; + + if (!dev || !dev->tuner) + return -1; + + if (dev->tuner->get_i2c_register) { + rtlsdr_set_i2c_repeater(dev, 1); + r = dev->tuner->get_i2c_reg_array((void *)dev, data, len); + rtlsdr_set_i2c_repeater(dev, 0); + } + return r; +} + + int rtlsdr_set_tuner_i2c_override(rtlsdr_dev_t *dev, unsigned i2c_register, unsigned mask /* byte */, unsigned data /* byte */ ) { int r = 0; @@ -2242,6 +2395,7 @@ static int parse(char *message, rtlsdr_dev_t *dev) uint8_t mask = 0xff, reg=0; uint32_t freq; int32_t bandcenter; + int sideband; int retCode; str1 = message; @@ -2270,7 +2424,8 @@ static int parse(char *message, rtlsdr_dev_t *dev) * f # set rtl center frequency * b # set tuner bandwidth * c # set tuner bandwidth center in output. value in [ -1 600 000 .. 1 600 000 ] - * + * v # set tuner sideband inversion + * * a # 0: LNA/Mixer = auto; VGA = fixed 26.5 dB * # -1: LNA/Mixer = last value from prev rtlsdr_set_tuner_gain; VGA = auto * # >0: LNA/Mixer = from rtlsdr_set_tuner_gain(tunerAgcMode); VGA = auto @@ -2304,6 +2459,7 @@ static int parse(char *message, rtlsdr_dev_t *dev) if (!strcmp(token, "f")) comm = 256 + 1; if (!strcmp(token, "b")) comm = 256 + 2; if (!strcmp(token, "c")) comm = 256 + 3; + if (!strcmp(token, "v")) comm = 256 + 4; if (!strcmp(token, "a")) comm = 512 + 1; if (!strcmp(token, "m")) comm = 512 + 2; if (!strcmp(token, "M")) comm = 512 + 3; @@ -2367,7 +2523,6 @@ static int parse(char *message, rtlsdr_dev_t *dev) return -1; } } else if (comm == 64 +2 || comm == 64 +3 ) { - dev->saved_27 = dev->tuner->get_i2c_register(dev,27); if ( dev->verbose ) { fprintf(stderr, "parsed 'set i2c register %s %d = x%02X value %d = %s = %s with mask %s = %s'\n" @@ -2451,6 +2606,15 @@ static int parse(char *message, rtlsdr_dev_t *dev) if ( dev->verbose ) fprintf(stderr, " rtlsdr_set_tuner_band_center() returned %d\n", retCode); break; + case 4: /* sideband */ + sideband = (int32_t)freqVal; + if ( dev->verbose ) + fprintf(stderr, "parsed sideband = %d = %s from token '%s'\n", + sideband, (sideband ? "USB" : "LSB"), token); + retCode = rtlsdr_set_tuner_sideband(dev, sideband); + if ( dev->verbose ) + fprintf(stderr, " rtlsdr_set_tuner_sideband() returned %d\n", retCode); + break; default: break; } @@ -2505,6 +2669,7 @@ static int parse(char *message, rtlsdr_dev_t *dev) "f \n" "b \n" "c \n" + "v \n" "a \n" "m \n" "M \n" ); @@ -2614,6 +2779,13 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) dev->softagc.rpcNumGains = 0; dev->softagc.rpcGainValues = NULL; + /* -cs- */ + #ifdef __MINGW32__ + dev->cs_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; + #else + dev->cs_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + #endif + /* UDP controller server */ #ifdef WITH_UDP_SERVER dev->udpPortNo = 0; /* default port 32323 .. but deactivated - by default */ @@ -2745,6 +2917,8 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) fprintf(stderr, "Found Fitipower FC0012 tuner\n"); rtlsdr_set_gpio_output(dev, 6); dev->tuner_type = RTLSDR_TUNER_FC0012; + /* rtlsdr_set_gpio_output(dev, 5); */ + /* rtlsdr_set_gpio_bit(dev, 5, 1); */ goto found; } @@ -2785,7 +2959,6 @@ found: rtlsdr_set_i2c_repeater(dev, 0); *out_dev = dev; - return 0; err: if (dev) { @@ -2843,10 +3016,6 @@ int rtlsdr_close(rtlsdr_dev_t *dev) libusb_exit(dev->ctx); - if (dev->handled) { - dev->handled = 0; - } - free(dev); return 0; @@ -3508,7 +3677,6 @@ static int rtlsdr_read_regs(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uin static int rtlsdr_write_reg_mask(rtlsdr_dev_t *d, int block, uint16_t reg, uint8_t val, uint8_t mask) { - int ret; uint8_t tmp; /* no need for read if whole reg is written */ @@ -3561,7 +3729,7 @@ int rtlsdr_ir_query(rtlsdr_dev_t *d, uint8_t *buf, size_t buf_len) ret = rtlsdr_write_reg_mask(d, init_tab[i].block, init_tab[i].reg, init_tab[i].val, init_tab[i].mask); if (ret < 0) { - fprintf(stderr, "write %zd reg %d %.4x %.2x %.2x failed\n", i, init_tab[i].block, + fprintf(stderr, "write %ld reg %d %.4x %.2x %.2x failed\n", (unsigned long)i, init_tab[i].block, init_tab[i].reg, init_tab[i].val, init_tab[i].mask); goto err; } @@ -3639,7 +3807,7 @@ const char * rtlsdr_get_opt_help(int longInfo) if ( longInfo ) return "\t[-O\tset RTL options string seperated with ':' ]\n" - "\t\tverbose:f=:bw=:bc=\n" + "\t\tverbose:f=:bw=:bc=:sb=\n" "\t\tagc=:agcv=<>:gain=:dagc=\n" "\t\tds=:T=\n" #ifdef WITH_UDP_SERVER @@ -3694,6 +3862,12 @@ int rtlsdr_set_opt_string(rtlsdr_dev_t *dev, const char *opts, int verbose) fprintf(stderr, "\nrtlsdr_set_opt_string(): parsed band center %d\n", (int)if_band_center_freq); ret = rtlsdr_set_tuner_band_center(dev, if_band_center_freq ); } + else if (!strncmp(optPart, "sb=", 3)) { + int32_t sideband = (int32_t)(atoi(optPart +3)); + if (verbose) + fprintf(stderr, "\nrtlsdr_set_opt_string(): parsed sideband %d == %s\n", (int)sideband, (sideband ? "Upper" : "Lower") ); + ret = rtlsdr_set_tuner_sideband(dev, sideband ); + } else if (!strncmp(optPart, "agc=", 4)) { int manual = 1 - atoi(optPart +4); /* invert logic */ if (verbose) @@ -3781,8 +3955,6 @@ int rtlsdr_set_opt_string(rtlsdr_dev_t *dev, const char *opts, int verbose) #ifdef WITH_UDP_SERVER if (dev->udpPortNo && dev->srv_started == 0 && dev->tuner_type==RTLSDR_TUNER_R820T) { - dev->handled = 1; - dev->saved_27 = dev->tuner->get_i2c_register(dev,27); /* highest/lowest corner for LPNF and LPF */ /* signal(SIGPIPE, SIG_IGN); */ if(pthread_create(&dev->srv_thread, NULL, srv_server, dev)) { fprintf(stderr, "Error creating thread\n"); diff --git a/src/rtl_tcp.c b/src/rtl_tcp.c index 60b2b46..c1176a8 100644 --- a/src/rtl_tcp.c +++ b/src/rtl_tcp.c @@ -61,6 +61,10 @@ typedef int socklen_t; #define SOCKET_ERROR -1 #endif +#include "controlThread.h" + +static ctrl_thread_data_t ctrldata; + static SOCKET s; static pthread_t tcp_worker_thread; @@ -108,7 +112,8 @@ void usage(void) ); fprintf(stderr, "Usage:\t[-a listen address]\n" - "\t[-p listen port (default: 1234)]\n" + "\t[-p control listen port (default: 1234)]\n" + "\t[-r response listen port: 0 = off; 1 (=default) for On at control listen port +1; or port]\n" "\t[-I infrared sensor listen port (default: 0=none)]\n" "\t[-W infrared sensor query wait interval usec (default: 10000)]\n" "\t[-f frequency to tune to [Hz]]\n" @@ -434,6 +439,19 @@ static void *command_worker(void *arg) printf("set tuner agc variant to %i\n", itmp); rtlsdr_set_tuner_agc_mode(dev, itmp); break; + case SET_SIDEBAND: + tmp = ntohl(cmd.param); + if(tmp) + tmp = 1; + printf("set to %s sideband\n", (tmp ? "upper" : "lower") ); + rtlsdr_set_tuner_sideband(dev, tmp); + break; + case REPORT_I2C_REGS: + tmp = ntohl(cmd.param); + if(tmp) + tmp = 1; + ctrldata.report_i2c = tmp; /* (de)activate reporting */ + break; default: break; } @@ -521,6 +539,10 @@ int main(int argc, char **argv) int port_ir = 0; int wait_ir = 10000; pthread_t thread_ir; + pthread_t thread_ctrl; /* -cs- for periodically reading the register values */ + int port_resp = 1; + int report_i2c = 0; + int do_exit_thrd_ctrl = 0; uint32_t frequency = 100000000, samp_rate = 2048000; enum rtlsdr_ds_mode ds_mode = RTLSDR_DS_IQ; @@ -563,7 +585,7 @@ int main(int argc, char **argv) struct sigaction sigact, sigign; #endif - opt_str = "a:p:f:g:s:b:n:d:P:O:TI:W:l:w:D:v"; + opt_str = "a:p:f:g:s:b:n:d:P:O:TI:W:l:w:D:vr:"; while ((opt = getopt(argc, argv, opt_str)) != -1) { switch (opt) { case 'd': @@ -585,6 +607,10 @@ int main(int argc, char **argv) case 'p': port = atoi(optarg); break; + case 'r': + port_resp = atoi(optarg); + report_i2c = 0; + break; case 'I': port_ir = atoi(optarg); break; @@ -724,6 +750,25 @@ int main(int argc, char **argv) pthread_create(&thread_ir, NULL, &ir_thread_fn, (void *)(&data)); } +#if 0 + fprintf(stderr, "enabling Response channel with I2C reporting\n"); + port_resp = 1; + report_i2c = 1; +#endif + if ( port_resp == 1 ) + port_resp = port + 1; + ctrldata.port = port_resp; + ctrldata.dev = dev; + ctrldata.addr = addr; + ctrldata.wait = 500000; /* = 0.5 sec */ + ctrldata.report_i2c = report_i2c; + ctrldata.pDoExit = &do_exit_thrd_ctrl; + if ( port_resp ) { + fprintf(stderr, "activating Response channel on port %d with %s I2C reporting\n" + , port_resp, (report_i2c ? "active" : "inactive") ); + pthread_create(&thread_ctrl, NULL, &ctrl_thread_fn, &ctrldata); + } + memset(&local,0,sizeof(local)); local.sin_family = AF_INET; local.sin_port = htons(port); @@ -825,6 +870,11 @@ out: closesocket(listensocket); /* if (port_ir) pthread_join(thread_ir, &status); */ + if ( port_resp ) { + do_exit_thrd_ctrl = 1; + pthread_join(thread_ctrl, &status); + } + closesocket(s); #ifdef _WIN32 WSACleanup(); diff --git a/src/rtl_udp.c b/src/rtl_udp.c index b5cccbd..b86564f 100644 --- a/src/rtl_udp.c +++ b/src/rtl_udp.c @@ -440,6 +440,15 @@ static void *command_worker(void *arg) printf("set tuner agc variant to %i\n", itmp); rtlsdr_set_tuner_agc_mode(dev, itmp); break; + case SET_SIDEBAND: + tmp = ntohl(cmd.param); + if(tmp) { + tmp = 1; + printf("set to upper sideband\n"); + } else + printf("set to lower sideband\n"); + rtlsdr_set_tuner_sideband(dev, tmp); + break; default: break; } diff --git a/src/tuner_fc0012.c b/src/tuner_fc0012.c index 768cf1c..aa9c056 100644 --- a/src/tuner_fc0012.c +++ b/src/tuner_fc0012.c @@ -54,38 +54,92 @@ static int fc0012_readreg(void *dev, uint8_t reg, uint8_t *val) return 0; } +/* expose/permit tuner specific i2c register hacking! */ +int fc0012_set_i2c_register(void *dev, unsigned i2c_register, unsigned data) +{ + uint8_t reg = i2c_register & 0xFF; + uint8_t reg_val = data & 0xFF; + return fc0012_writereg(dev, reg, reg_val); +} + +int fc0012_get_i2c_register(void *dev, unsigned char* data, int len) +{ + int len1; + + data[0] = 0; + /* The lower 16 I2C registers can be read with the normal read fct, + * the upper ones are read from the cache */ + if(len < 16) + len1 = len; + else + len1 = 16; + if (rtlsdr_i2c_write_fn(dev, FC0012_I2C_ADDR, data, 1) < 0) + return -1; + if (rtlsdr_i2c_read_fn(dev, FC0012_I2C_ADDR, data, len1) < 0) + return -1; + + if(len > 16) + { + len1 = len - 16; + data[16] = 16; + if (rtlsdr_i2c_write_fn(dev, FC0012_I2C_ADDR, data+16, 1) < 0) + return -1; + if (rtlsdr_i2c_read_fn(dev, FC0012_I2C_ADDR, data+16, len1) < 0) + return -1; + } + + return 0; +} + +static int print_registers(void *dev) +{ + uint8_t data[32]; + unsigned int i; + + if (fc0012_get_i2c_register(dev, data, 32) < 0) + return -1; + for(i=0; i<16; i++) + printf("%02x ", data[i]); + printf("\n"); + for(i=16; i<32; i++) + printf("%02x ", data[i]); + printf("\n"); + return 0; +} + + /* Incomplete list of register settings: * - * Name Reg Bits Desc - * CHIP_ID 0x00 0-7 Chip ID (constant 0xA1) - * RF_A 0x01 0-3 Number of count-to-9 cycles in RF - * divider (suggested: 2..9) - * RF_M 0x02 0-7 Total number of cycles (to-8 and to-9) - * in RF divider + * Name Reg BitsDesc + * CHIP_ID 0x00 0-7 Chip ID (constant 0xA1) + * RF_A 0x01 0-3 Number of count-to-9 cycles in RF + * divider (suggested: 2..9) + * RF_M 0x02 0-7 Total number of cycles (to-8 and to-9) + * in RF divider * RF_K_HIGH 0x03 0-6 Bits 8..14 of fractional divider - * RF_K_LOW 0x04 0-7 Bits 0..7 of fractional RF divider + * RF_K_LOW 0x04 0-7 Bits 0..7 of fractional RF divider * RF_OUTDIV_A 0x05 3-7 Power of two required? * LNA_POWER_DOWN 0x06 0 Set to 1 to switch off low noise amp * RF_OUTDIV_B 0x06 1 Set to select 3 instead of 2 for the - * RF output divider + * RF output divider * VCO_SPEED 0x06 3 Select tuning range of VCO: - * 0 = Low range, (ca. 1.1 - 1.5GHz) - * 1 = High range (ca. 1.4 - 1.8GHz) + * 0 = Low range, (ca. 1.1 - 1.5GHz) + * 1 = High range (ca. 1.4 - 1.8GHz) * BANDWIDTH 0x06 6-7 Set bandwidth. 6MHz = 0x80, 7MHz=0x40 - * 8MHz=0x00 + * 8MHz=0x00 * XTAL_SPEED 0x07 5 Set to 1 for 28.8MHz Crystal input - * or 0 for 36MHz + * or 0 for 36MHz * 0x08 0-7 * EN_CAL_RSSI 0x09 4 Enable calibrate RSSI - * (Receive Signal Strength Indicator) + * (Receive Signal Strength Indicator) * LNA_FORCE 0x0d 0 * AGC_FORCE 0x0d ? - * LNA_GAIN 0x13 3-4 Low noise amp gain - * LNA_COMPS 0x15 3 ? * VCO_CALIB 0x0e 7 Set high then low to calibrate VCO - * (fast lock?) + * (fast lock?) * VCO_VOLTAGE 0x0e 0-6 Read Control voltage of VCO - * (big value -> low freq) + * (big value -> low freq) + * LNA_GAIN 0x13 3-4 Low noise amp gain + * LNA_COMPS 0x15 3 ? */ int fc0012_init(void *dev) @@ -112,8 +166,8 @@ int fc0012_init(void *dev) 0x00, /* reg. 0x0e */ 0x00, /* reg. 0x0f */ 0x00, /* reg. 0x10: may also be 0x0d */ - 0x00, /* reg. 0x11 */ - 0x1f, /* reg. 0x12: Set to maximum gain */ + 0x0a, /* reg. 0x11 */ + 0x51, /* reg. 0x12: Set to maximum gain */ 0x08, /* reg. 0x13: Set to Middle Gain: 0x08, Low Gain: 0x00, High Gain: 0x10, enable IX2: 0x80 */ 0x00, /* reg. 0x14 */ @@ -133,7 +187,7 @@ int fc0012_init(void *dev) #endif reg[0x07] |= 0x20; -// if (priv->dual_master) +/* if (priv->dual_master) */ reg[0x0c] |= 0x02; for (i = 1; i < sizeof(reg); i++) { @@ -278,7 +332,7 @@ int fc0012_set_params(void *dev, uint32_t freq, uint32_t bandwidth) ret = fc0012_writereg(dev, 0x0e, 0x00); if (!ret) { -// msleep(10); + /* msleep(10); */ ret = fc0012_readreg(dev, 0x0e, &tmp); } if (ret) @@ -340,6 +394,6 @@ int fc0012_set_gain(void *dev, int gain) } ret = fc0012_writereg(dev, 0x13, tmp); - + /* print_registers(dev); */ return ret; } diff --git a/src/tuner_r82xx.c b/src/tuner_r82xx.c index 24381f5..015084e 100644 --- a/src/tuner_r82xx.c +++ b/src/tuner_r82xx.c @@ -30,26 +30,277 @@ #include "rtlsdr_i2c.h" #include "tuner_r82xx.h" -#define WITH_ASYM_FILTER 1 +#define WITH_ASYM_FILTER 0 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) #define MHZ(x) ((x)*1000*1000) #define KHZ(x) ((x)*1000) +/* +Reg Bitmap Symbol Description +------------------------------------------------------------------------------------ +R0 [7:0] CHIP_ID reference check point for read mode +0x00 0x96 +------------------------------------------------------------------------------------ +R1 ? +0x01 +------------------------------------------------------------------------------------ +R2 [7] 0 +0x02 [6:0] VCO_INDICATOR +------------------------------------------------------------------------------------ +R3 [7:4] RF_INDICATOR LNA gain +0x03 0: Lowest, 15: Highest + [3:0] Mixer gain + 0: Lowest, 15: Highest +------------------------------------------------------------------------------------ +R4 ? +0x04 +------------------------------------------------------------------------------------ +R5 [7] PWD_LT Loop through ON/OFF +0x05 0: on, 1: off + [6] 0 + [5] PWD_LNA1 LNA 1 power control + 0:on, 1:off + [4] LNA_GAIN_MODE LNA gain mode switch + 0: auto, 1: manual + [3:0] LNA_GAIN LNA manual gain control + 15: max gain, 0: min gain +------------------------------------------------------------------------------------ +R6 [7] PWD_PDET1 Power detector 1 on/off +0x06 0: on, 1: off + [6] PWD_PDET3 Power detector 3 on/off + 0: off, 1: on + [5] FILT_3DB Filter gain 3db + 0:0db, 1:+3db + [4:3] 10 + [2:0] PW_LNA LNA power control + 000: max, 111: min +------------------------------------------------------------------------------------ +R7 [7] Mixer Sideband +0x07 0: lower, 1: upper + [6] PWD_MIX Mixer power + 0:off, 1:on + [5] PW0_MIX Mixer current control + 0:max current, 1:normal current + [4] MIXGAIN_MODE Mixer gain mode + 0:manual mode, 1:auto mode + [3:0] MIX_GAIN Mixer manual gain control + 0000->min, 1111->max +------------------------------------------------------------------------------------ +R8 [7] PWD_AMP Mixer buffer power on/off +0x08 0: off, 1:on + [6] PW0_AMP Mixer buffer current setting + 0: high current, 1: low current + [5:0] IMR_G Image Gain Adjustment + 0: min, 63: max +------------------------------------------------------------------------------------ +R9 [7] PWD_IFFILT IF Filter power on/off +0x09 0: filter on, 1: off + [6] PW1_IFFILT IF Filter current + 0: high current, 1: low current + [5:0] IMR_P Image Phase Adjustment + 0: min, 63: max +------------------------------------------------------------------------------------ +R10 [7] PWD_FILT Filter power on/off +0x0A 0: channel filter off, 1: on + [6:5] PW_FILT Filter power control + 00: highest power, 11: lowest power + [4] 1 + [3:0] FILT_CODE Filter bandwidth manual fine tune + 0000 Widest, 1111 narrowest +------------------------------------------------------------------------------------ +R11 [7:5] FILT_BW Filter bandwidth manual course tunnel +0x0B 000: widest + 010 or 001: middle + 111: narrowest + [4] 0 + [3:0] HPF High pass filter corner control + 0000: highest + 1111: lowest +------------------------------------------------------------------------------------ +R12 [7] 1 +0x0C [6] PWD_VGA VGA power control + 0: vga power off, 1: vga power on + [5] 1 + [4] VGA_MODE VGA GAIN manual / pin selector + 1: IF vga gain controlled by vagc pin + 0: IF vga gain controlled by vga_code[3:0] + [3:0] VGA_CODE IF vga manual gain control + 0000: -12.0 dB + 1111: +40.5 dB; -3.5dB/step +------------------------------------------------------------------------------------ +R13 [7:4] LNA_VTHH LNA agc power detector voltage threshold high setting +0x0D 1111: 1.94 V + 0000: 0.34 V, ~0.1 V/step + [3:0] LNA_VTHL LNA agc power detector voltage threshold low setting + 1111: 1.94 V + 0000: 0.34 V, ~0.1 V/step +------------------------------------------------------------------------------------ +R14 [7:4] MIX_VTH_H MIXER agc power detector voltage threshold high setting +0x0E 1111: 1.94 V + 0000: 0.34 V, ~0.1 V/step + [3:0] MIX_VTH_L MIXER agc power detector voltage threshold low setting + 1111: 1.94 V + 0000: 0.34 V, ~0.1 V/step +------------------------------------------------------------------------------------ +R15 [7] filter extension widest + 0: off, 1: on +0x0F [4] CLK_OUT_ENB Clock out pin control + 0: clk output on, 1: off + [3] 1 + [2] set cali clk + 0: off, 1: on + [1] CLK_AGC_ENB AGC clk control + 0: internal agc clock on, 1: off + [0] GPIO 0 +------------------------------------------------------------------------------------ +R16 [7:5] SEL_DIV PLL to Mixer divider number control +0x10 000: mixer in = vco out /2 + 001: mixer in = vco out / 4 + 010: mixer in = vco out / 8 + 011: mixer in = vco out + [4] REFDIV PLL Reference frequency Divider + 0 -> fref=xtal_freq + 1 -> fref=xta_freql / 2 (for Xtal >24MHz) + [3:2] 01 + [1:0] CAPX Internal xtal cap setting + 00->no cap + 01->10pF + 10->20pF + 11->30pF +------------------------------------------------------------------------------------ +R17 [7:6] PW_LDO_A PLL analog low drop out regulator switch +0x11 00: off + 01: 2.1V + 10: 2.0V + 11: 1.9V + [5:3] cp_cur + 101: 0.2, 111: auto + [2:0] 011 +------------------------------------------------------------------------------------ +R18 [7:5] set VCO current +0x12 [4] PW_SDM 0 + [3:0] 000 +------------------------------------------------------------------------------------ +R19 [7:6] 00 + [5:0] VER_NUM 0x31 +------------------------------------------------------------------------------------ +R20 [7:6] SI2C PLL integer divider number input Si2c +0x14 Nint=4*Ni2c+Si2c+13 + PLL divider number Ndiv = (Nint + Nfra)*2 + [5:0] NI2C PLL integer divider number input Ni2c +------------------------------------------------------------------------------------ +R21 [7:0] SDM_IN[8:1] PLL fractional divider number input SDM[16:1] +0x15 Nfra=SDM_IN[16]*2^-1+SDM_IN[15]*2^-2+... +R22 [7:0] SDM_IN[16:9] +SDM_IN[2]*2^-15+SDM_IN[1]*2^-16 +0x16 +------------------------------------------------------------------------------------ +R23 [7:6] PW_LDO_D PLL digital low drop out regulator supply current switch +0x17 00: 1.8V,8mA + 01: 1.8V,4mA + 10: 2.0V,8mA + 11: OFF + [5:4] div_buf_cur + 10: 200u, 11: 150u + [3] OPEN_D Open drain + 0: High-Z, 1: Low-Z + [2:0] 100 +------------------------------------------------------------------------------------ +R25 [7] PWD_RFFILT RF Filter power +0x19 0: off, 1:on + [6:5] RF poly filter current + 00: min + [4] SW_AGC Switch agc_pin + 0:agc=agc_in + 1:agc=agc_in2 + [3:2] 11 +------------------------------------------------------------------------------------ +R26 [7:6] RFMUX Tracking Filter switch +0x1A 00: TF on + 01: Bypass + [5:4] AGC clk + 00: 300ms, 01: 300ms, 10: 80ms, 11: 20ms + [3:2] PLL_AUTO_CLK PLL auto tune clock rate + 00: 128 kHz + 01: 32 kHz + 10: 8 kHz + [1:0] RFFILT RF FILTER band selection + 00: highest band + 01: med band + 10: low band +------------------------------------------------------------------------------------ +R27 [7:4] TF_NCH 0000 highest corner for LPNF +0x1B 1111 lowerst corner for LPNF + [3:0] TF_LP 0000 highest corner for LPF + 1111 lowerst corner for LPF +------------------------------------------------------------------------------------ +R28 [7:4] PDET3_GAIN Power detector 3 (Mixer) TOP(take off point) control +0x1C 0: Highest, 15: Lowest + [3] discharge mode + 0: on + [2] 1 + [0] 0 +------------------------------------------------------------------------------------ +R29 [7:6] 11 +0x1D [5:3] PDET1_GAIN Power detector 1 (LNA) TOP(take off point) control + 0: Highest, 7: Lowest + [2:0] PDET2_GAIN Power detector 2 TOP(take off point) control + 0: Highest, 7: Lowest +------------------------------------------------------------------------------------ +R30 [7] 0 +0x1E [6] FILTER_EXT Filter extension under weak signal + 0: Disable, 1: Enable + [5:0] PDET_CLK Power detector timing control (LNA discharge current) + 111111: max, 000000: min +------------------------------------------------------------------------------------ +R31 [7] Loop through attenuation +0x1F 0: Enable, 1: Disable + [6:2] 10000 +------------------------------------------------------------------------------------ +R0...R4 read, R5...R15 read/write, R16..R31 write +*/ + + /* * Static constants */ /* Those initial values start from REG_SHADOW_START */ -static const uint8_t r82xx_init_array[NUM_REGS] = { - 0x83, 0x32, 0x75, /* 05 to 07 */ - 0xc0, 0x40, 0xd6, 0x6c, /* 08 to 0b */ - 0xf5, 0x63, 0x75, 0x68, /* 0c to 0f */ - 0x6c, 0x83, 0x80, 0x00, /* 10 to 13 */ - 0x0f, 0x00, 0xc0, 0x30, /* 14 to 17 */ - 0x48, 0xcc, 0x60, 0x00, /* 18 to 1b */ - 0x54, 0xae, 0x4a, 0xc0 /* 1c to 1f */ +static const uint8_t r82xx_init_array[] = { + 0x80, /* Reg 0x05 */ + 0x12, /* Reg 0x06 */ + 0x70, /* Reg 0x07 */ + + 0xc0, /* Reg 0x08 */ + 0x40, /* Reg 0x09 */ + 0xdb, /* Reg 0x0a */ + 0x6b, /* Reg 0x0b */ + + 0xf0, /* Reg 0x0c */ + 0x53, /* Reg 0x0d */ + 0x75, /* Reg 0x0e */ + 0x68, /* Reg 0x0f */ + + 0x6c, /* Reg 0x10 */ + 0xbb, /* Reg 0x11 */ + 0x80, /* Reg 0x12 */ + VER_NUM & 0x3f, /* Reg 0x13 */ + + 0x0f, /* Reg 0x14 */ + 0x00, /* Reg 0x15 */ + 0xc0, /* Reg 0x16 */ + 0x30, /* Reg 0x17 */ + + 0x48, /* Reg 0x18 */ + 0xec, /* Reg 0x19 */ + 0x60, /* Reg 0x1a */ + 0x00, /* Reg 0x1b */ + + 0x24, /* Reg 0x1c */ + 0xdd, /* Reg 0x1d */ + 0x0e, /* Reg 0x1e */ + 0x40 /* Reg 0x1f */ }; /* Tuner frequency ranges */ @@ -225,14 +476,6 @@ static const struct r82xx_freq_range freq_ranges[] = { } }; -static int r82xx_xtal_capacitor[][2] = { - { 0x0b, XTAL_LOW_CAP_30P }, - { 0x02, XTAL_LOW_CAP_20P }, - { 0x01, XTAL_LOW_CAP_10P }, - { 0x00, XTAL_LOW_CAP_0P }, - { 0x10, XTAL_HIGH_CAP_0P }, -}; - /* * I2C read/write code and shadow registers logic */ @@ -369,11 +612,6 @@ static int r82xx_read(struct r82xx_priv *priv, uint8_t reg, uint8_t *val, int le uint8_t *p = &priv->buf[1]; priv->buf[0] = reg; - - rc = rtlsdr_i2c_write_fn(priv->rtl_dev, priv->cfg->i2c_addr, priv->buf, 1); - if (rc < 1) - return rc; - rc = rtlsdr_i2c_read_fn(priv->rtl_dev, priv->cfg->i2c_addr, p, len); if (rc != len) { @@ -391,6 +629,23 @@ static int r82xx_read(struct r82xx_priv *priv, uint8_t reg, uint8_t *val, int le return 0; } +static void print_registers(struct r82xx_priv *priv) +{ + uint8_t data[5]; + int rc; + unsigned int i; + + rc = r82xx_read(priv, 0x00, data, sizeof(data)); + if (rc < 0) + return; + for(i=0; icfg->use_predetect) { rc = r82xx_write_reg_mask(priv, 0x06, pre_dect, 0x40); @@ -691,19 +876,6 @@ static int r82xx_sysfreq_sel(struct r82xx_priv *priv, uint32_t freq, return rc; } - rc = r82xx_write_reg_mask(priv, 0x1d, lna_top, 0xc7); - if (rc < 0) - return rc; - rc = r82xx_write_reg_mask(priv, 0x1c, mixer_top, 0xf8); - if (rc < 0) - return rc; - rc = r82xx_write_reg(priv, 0x0d, lna_vth_l); - if (rc < 0) - return rc; - rc = r82xx_write_reg(priv, 0x0e, mixer_vth_l); - if (rc < 0) - return rc; - priv->input = air_cable1_in; /* Air-IN only for Astrometa */ @@ -714,16 +886,6 @@ static int r82xx_sysfreq_sel(struct r82xx_priv *priv, uint32_t freq, if (rc < 0) return rc; - rc = r82xx_write_reg_mask(priv, 0x11, cp_cur, 0x38); - if (rc < 0) - return rc; - rc = r82xx_write_reg_mask(priv, 0x17, div_buf_cur, 0x30); - if (rc < 0) - return rc; - rc = r82xx_write_reg_mask_ext(priv, 0x0a, filter_cur, 0x60, __FUNCTION__); - if (rc < 0) - return rc; - /* * Set LNA */ @@ -734,11 +896,6 @@ static int r82xx_sysfreq_sel(struct r82xx_priv *priv, uint32_t freq, if (rc < 0) return rc; - /* 0: normal mode */ - rc = r82xx_write_reg_mask(priv, 0x1c, 0, 0x04); - if (rc < 0) - return rc; - /* 0: PRE_DECT off */ rc = r82xx_write_reg_mask(priv, 0x06, 0, 0x40); if (rc < 0) @@ -749,27 +906,11 @@ static int r82xx_sysfreq_sel(struct r82xx_priv *priv, uint32_t freq, if (rc < 0) return rc; -// msleep(250); - /* write LNA TOP = 3 */ rc = r82xx_write_reg_mask(priv, 0x1d, 0x18, 0x38); if (rc < 0) return rc; - /* - * write discharge mode - * FIXME: IMHO, the mask here is wrong, but it matches - * what's there at the original driver - */ - rc = r82xx_write_reg_mask(priv, 0x1c, mixer_top, 0x04); - if (rc < 0) - return rc; - - /* LNA discharge current */ - rc = r82xx_write_reg_mask(priv, 0x1e, lna_discharge, 0x1f); - if (rc < 0) - return rc; - /* agc clk 60hz */ rc = r82xx_write_reg_mask(priv, 0x1a, 0x20, 0x30); if (rc < 0) @@ -785,20 +926,6 @@ static int r82xx_sysfreq_sel(struct r82xx_priv *priv, uint32_t freq, if (rc < 0) return rc; - /* - * write discharge mode - * FIXME: IMHO, the mask here is wrong, but it matches - * what's there at the original driver - */ - rc = r82xx_write_reg_mask(priv, 0x1c, mixer_top, 0x04); - if (rc < 0) - return rc; - - /* LNA discharge current */ - rc = r82xx_write_reg_mask(priv, 0x1e, lna_discharge, 0x1f); - if (rc < 0) - return rc; - /* agc clk 1Khz, external det1 cap 1u */ rc = r82xx_write_reg_mask(priv, 0x1a, 0x00, 0x30); if (rc < 0) @@ -812,75 +939,40 @@ static int r82xx_sysfreq_sel(struct r82xx_priv *priv, uint32_t freq, } static int r82xx_set_tv_standard(struct r82xx_priv *priv, - unsigned bw, enum r82xx_tuner_type type, uint32_t delsys) { int rc, i; - uint32_t if_khz, filt_cal_lo; uint8_t data[5]; - uint8_t filt_gain, img_r, filt_q, hp_cor, ext_enable, loop_through; - uint8_t lt_att, flt_ext_widest, polyfil_cur; - int need_calibration; + + int need_calibration = 1; /* 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)); - - /* Init Flag & Xtal_check Result (inits VGA gain, needed?)*/ - rc = r82xx_write_reg_mask(priv, 0x0c, 0x00, 0x0f); - if (rc < 0) - return rc; - - /* version */ - rc = r82xx_write_reg_mask(priv, 0x13, VER_NUM, 0x3f); - if (rc < 0) - return rc; + uint32_t filt_cal_lo = 56000; /* 52000->56000 */ + uint8_t filt_q = 0x10; /* r10[4]:low q(1'b1) */ /* for LT Gain test */ if (type != TUNER_ANALOG_TV) { rc = r82xx_write_reg_mask(priv, 0x1d, 0x00, 0x38); if (rc < 0) return rc; -// usleep_range(1000, 2000); } priv->if_band_center_freq = 0; - priv->int_freq = if_khz * 1000; + priv->int_freq = 3570 * 1000; + priv->sideband = 0; /* Check if standard changed. If so, filter calibration is needed */ /* as we call this function only once in rtlsdr, force calibration */ - need_calibration = 1; if (need_calibration) { for (i = 0; i < 2; i++) { - /* Set filt_cap */ - rc = r82xx_write_reg_mask_ext(priv, 0x0b, hp_cor, 0x60, __FUNCTION__); - if (rc < 0) - return rc; /* set cali clk =on */ rc = r82xx_write_reg_mask(priv, 0x0f, 0x04, 0x04); if (rc < 0) return rc; - /* X'tal cap 0pF for PLL */ - rc = r82xx_write_reg_mask(priv, 0x10, 0x00, 0x03); - if (rc < 0) - return rc; - rc = r82xx_set_pll(priv, filt_cal_lo * 1000); if (rc < 0 || !priv->has_lock) return rc; @@ -890,8 +982,6 @@ static int r82xx_set_tv_standard(struct r82xx_priv *priv, if (rc < 0) return rc; -// usleep_range(1000, 2000); - /* Stop Trigger */ rc = r82xx_write_reg_mask_ext(priv, 0x0b, 0x00, 0x10, __FUNCTION__); if (rc < 0) @@ -921,50 +1011,10 @@ static int r82xx_set_tv_standard(struct r82xx_priv *priv, if (rc < 0) return rc; - /* Set BW, Filter_gain, & HP corner */ - rc = r82xx_write_reg_mask_ext(priv, 0x0b, hp_cor, 0xef, __FUNCTION__); - if (rc < 0) - return rc; - - /* Set Img_R */ - rc = r82xx_write_reg_mask(priv, 0x07, img_r, 0x80); - if (rc < 0) - return rc; - - /* Set filt_3dB, V6MHz */ - rc = r82xx_write_reg_mask(priv, 0x06, filt_gain, 0x30); - if (rc < 0) - return rc; - - /* channel filter extension */ - rc = r82xx_write_reg_mask_ext(priv, 0x1e, ext_enable, 0x60, __FUNCTION__); - if (rc < 0) - return rc; - - /* Loop through */ - rc = r82xx_write_reg_mask(priv, 0x05, loop_through, 0x80); - if (rc < 0) - return rc; - - /* Loop through attenuation */ - rc = r82xx_write_reg_mask(priv, 0x1f, lt_att, 0x80); - if (rc < 0) - return rc; - - /* filter extension widest */ - rc = r82xx_write_reg_mask(priv, 0x0f, flt_ext_widest, 0x80); - if (rc < 0) - return rc; - - /* RF poly filter current */ - rc = r82xx_write_reg_mask(priv, 0x19, polyfil_cur, 0x60); - if (rc < 0) - return rc; - /* Store current standard. If it changes, re-calibrate the tuner */ priv->delsys = delsys; priv->type = type; - priv->bw = bw; + priv->bw = 3; return 0; } @@ -1125,6 +1175,26 @@ int r82xx_set_i2c_register(struct r82xx_priv *priv, unsigned i2c_register, unsig return r82xx_write_reg_mask(priv, reg, reg_val, reg_mask); } +//-cs- +int r82xx_get_i2c_register(struct r82xx_priv *priv, unsigned char* data, int len) +{ + int rc, i, len1; + + // The lower 5 I2C registers can be read with the normal read fct, the upper ones are read from the cache + if(len < 5) + len1 = len; + else + len1 = 5; + rc = r82xx_read(priv, 0x00, data, len1); + if (rc < 0) + return rc; + if(len > 5) + for (i = 5; i < len; i++) + data[i] = r82xx_read_cache_reg(priv, i); + return 0; +} +//-cs- end + int r82xx_set_i2c_override(struct r82xx_priv *priv, unsigned i2c_register, unsigned data, unsigned mask) { uint8_t reg = i2c_register & 0xFF; @@ -1170,11 +1240,6 @@ int r82xx_set_i2c_override(struct r82xx_priv *priv, unsigned i2c_register, unsig } -/* Bandwidth contribution by low-pass filter. */ -static const int r82xx_if_low_pass_bw_table[] = { - 1700000, 1600000, 1550000, 1450000, 1200000, 900000, 700000, 550000, 450000, 350000 -}; - struct IFinfo { @@ -1261,6 +1326,15 @@ static const struct IFinfo IFi[] = { { 3, 1950+3, 1500, 30, 0x0F, 0x8F, 0x60 } }; + +/* settings from Oldenburger: +static const int r82xx_bws[]= { 300, 450, 600, 900, 1100, 1200, 1300, 1500, 1800, 2200, 3000, 5000 }; +static const uint8_t r82xx_0xa[]= { 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0f, 0x0f, 0x04, 0x0b }; +static const uint8_t r82xx_0xb[]= { 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xaf, 0x8f, 0x8f, 0x6b }; +static const int r82xx_if[] = { 1700, 1650, 1600, 1500, 1400, 1350, 1320, 1270, 1400, 1600, 2000, 3570 }; +*/ + + static const int r82xx_bw_tablen = sizeof(IFi) / sizeof(IFi[0]); @@ -1456,17 +1530,33 @@ int r82xx_set_bw_center(struct r82xx_priv *priv, int32_t if_band_center_freq) return priv->int_freq; } +int r82xx_set_sideband(struct r82xx_priv *priv, int sideband) +{ + int rc; + priv->sideband = sideband; + rc = r82xx_write_reg_mask(priv, 0x07, (sideband << 7) & 0x80, 0x80); + if (rc < 0) + return rc; + return 0; +} + int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq) { int rc = -1; - uint32_t lo_freq = freq + priv->int_freq + priv->if_band_center_freq; + uint32_t lo_freq; + uint8_t air_cable1_in; + + if(priv->sideband) + lo_freq = freq - priv->int_freq + priv->if_band_center_freq; + else + lo_freq = freq + priv->int_freq + priv->if_band_center_freq; + #if 0 - fprintf(stderr, "%s(freq = %u) --> intfreq %u, ifcenter %d --> f %u\n" - , __FUNCTION__, (unsigned)freq + fprintf(stderr, "%s(freq = %u) @ %s--> intfreq %u, ifcenter %d --> f %u\n" + , __FUNCTION__, (unsigned)freq, (priv->sideband ? "USB" : "LSB") , (unsigned)priv->int_freq, (int)priv->if_band_center_freq , (unsigned)lo_freq ); #endif - uint8_t air_cable1_in; rc = r82xx_set_mux(priv, lo_freq); if (rc < 0) @@ -1548,65 +1638,6 @@ int r82xx_standby(struct r82xx_priv *priv) * r82xx device init logic */ -static int r82xx_xtal_check(struct r82xx_priv *priv) -{ - int rc; - unsigned int i; - uint8_t data[3], val; - - /* Initialize the shadow registers */ - memcpy(priv->regs, r82xx_init_array, sizeof(r82xx_init_array)); - - /* cap 30pF & Drive Low */ - rc = r82xx_write_reg_mask(priv, 0x10, 0x0b, 0x0b); - if (rc < 0) - return rc; - - /* set pll autotune = 128kHz */ - rc = r82xx_write_reg_mask(priv, 0x1a, 0x00, 0x0c); - if (rc < 0) - return rc; - - /* set manual initial reg = 111111; */ - rc = r82xx_write_reg_mask(priv, 0x13, 0x7f, 0x7f); - if (rc < 0) - return rc; - - /* set auto */ - rc = r82xx_write_reg_mask(priv, 0x13, 0x00, 0x40); - if (rc < 0) - return rc; - - /* Try several xtal capacitor alternatives */ - for (i = 0; i < ARRAY_SIZE(r82xx_xtal_capacitor); i++) { - rc = r82xx_write_reg_mask(priv, 0x10, - r82xx_xtal_capacitor[i][0], 0x1b); - if (rc < 0) - return rc; - -// usleep_range(5000, 6000); - - rc = r82xx_read(priv, 0x00, data, sizeof(data)); - if (rc < 0) - return rc; - if (!(data[2] & 0x40)) - continue; - - val = data[2] & 0x3f; - - if (priv->cfg->xtal == 16000000 && (val > 29 || val < 23)) - break; - - if (val != 0x3f) - break; - } - - if (i == ARRAY_SIZE(r82xx_xtal_capacitor)) - return -1; - - return r82xx_xtal_capacitor[i][1]; -} - int r82xx_init(struct r82xx_priv *priv) { int rc; @@ -1629,11 +1660,11 @@ int r82xx_init(struct r82xx_priv *priv) rc = r82xx_write_arr(priv, 0x05, r82xx_init_array, sizeof(r82xx_init_array)); - rc = r82xx_set_tv_standard(priv, 3, TUNER_DIGITAL_TV, 0); + rc = r82xx_set_tv_standard(priv, TUNER_DIGITAL_TV, 0); if (rc < 0) goto err; - rc = r82xx_sysfreq_sel(priv, 0, TUNER_DIGITAL_TV, SYS_DVBT); + rc = r82xx_sysfreq_sel(priv, TUNER_DIGITAL_TV); #if USE_R82XX_ENV_VARS priv->printI2C = 0;