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;