And here goes the patch.
Code: Select all
From 473abf543919782019bae352529fbadd47e66c58 Mon Sep 17 00:00:00 2001
From: Jiri Luznicky <[email protected]>
Date: Fri, 4 Apr 2014 20:41:07 +0200
Subject: [PATCH] Added port of Infineon TUA9001 tuner.
---
include/rtl-sdr.h | 3 +-
include/rtlsdr_i2c.h | 3 +
include/tuner_tua9001.h | 15 +++++
rtl-sdr.rules | 6 ++
src/CMakeLists.txt | 2 +
src/librtlsdr.c | 62 ++++++++++++++++++++-
src/tuner_tua9001.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++
7 files changed, 226 insertions(+), 4 deletions(-)
create mode 100644 include/tuner_tua9001.h
create mode 100644 src/tuner_tua9001.c
diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h
index 489e117..c13e60c 100644
--- a/include/rtl-sdr.h
+++ b/include/rtl-sdr.h
@@ -176,7 +176,8 @@ enum rtlsdr_tuner {
RTLSDR_TUNER_FC0013,
RTLSDR_TUNER_FC2580,
RTLSDR_TUNER_R820T,
- RTLSDR_TUNER_R828D
+ RTLSDR_TUNER_R828D,
+ RTLSDR_TUNER_TUA9001
};
/*!
diff --git a/include/rtlsdr_i2c.h b/include/rtlsdr_i2c.h
index 7676689..f45b83c 100644
--- a/include/rtlsdr_i2c.h
+++ b/include/rtlsdr_i2c.h
@@ -5,4 +5,7 @@ uint32_t rtlsdr_get_tuner_clock(void *dev);
int rtlsdr_i2c_write_fn(void *dev, uint8_t addr, uint8_t *buf, int len);
int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len);
+int rtlsdr_i2c_tunb_write_fn(void *dev, uint8_t addr, uint8_t *buf, int len);
+void rtlsdr_set_gpio_bit_fn(void *dev, uint8_t gpio, int val);
+
#endif
diff --git a/include/tuner_tua9001.h b/include/tuner_tua9001.h
new file mode 100644
index 0000000..5c16995
--- /dev/null
+++ b/include/tuner_tua9001.h
@@ -0,0 +1,15 @@
+#ifndef __TUNER_TUA9001_H
+#define __TUNER_TUA9001_H
+
+#define TUA9001_I2C_ADDR 0xc0
+#define TUA9001_CHECK_ADDR 0x7e
+#define TUA9001_CHECK_VAL 0x2328
+
+#define TUA9001_RESETN_PIN 3
+#define TUA9001_RXEN_PIN 1
+
+int tua9001_init(void *dev);
+int tua9001_release(void *dev);
+int tua9001_set_params(void *dev, uint32_t frequency_hz, uint32_t bandwidth_hz);
+
+#endif /* __TUNER_TUA9001_H */
\ No newline at end of file
diff --git a/rtl-sdr.rules b/rtl-sdr.rules
index 4213454..94f11dc 100644
--- a/rtl-sdr.rules
+++ b/rtl-sdr.rules
@@ -24,6 +24,9 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="2838", MODE:="066
# DigitalNow Quad DVB-T PCI-E card (4x FC0012?)
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0413", ATTRS{idProduct}=="6680", MODE:="0666"
+# Leadtek Research, Inc. RTL2832 [WinFast DTV Dongle Mini] (TUA9001)
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="0413", ATTRS{idProduct}=="6a03", MODE:="0666"
+
# Leadtek WinFast DTV Dongle mini D (FC0012)
SUBSYSTEMS=="usb", ATTRS{idVendor}=="0413", ATTRS{idProduct}=="6f0f", MODE:="0666"
@@ -90,6 +93,9 @@ SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d394", MODE:="066
# Peak 102569AGPK (FC0012)
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d395", MODE:="0666"
+# Hamlet eXagerate XDVBT900BK (TUA9001)
+SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d396", MODE:="0666"
+
# KWorld KW-UB450-T USB DVB-T Pico TV (TUA9001)
SUBSYSTEMS=="usb", ATTRS{idVendor}=="1b80", ATTRS{idProduct}=="d397", MODE:="0666"
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 77e1dc4..df73116 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -27,6 +27,7 @@ add_library(rtlsdr_shared SHARED
tuner_fc0013.c
tuner_fc2580.c
tuner_r82xx.c
+ tuner_tua9001.c
)
target_link_libraries(rtlsdr_shared
@@ -45,6 +46,7 @@ add_library(rtlsdr_static STATIC
tuner_fc0013.c
tuner_fc2580.c
tuner_r82xx.c
+ tuner_tua9001.c
)
add_library(convenience_static STATIC
diff --git a/src/librtlsdr.c b/src/librtlsdr.c
index 9a3ebcd..4b7271a 100644
--- a/src/librtlsdr.c
+++ b/src/librtlsdr.c
@@ -54,6 +54,7 @@
#include "tuner_fc0013.h"
#include "tuner_fc2580.h"
#include "tuner_r82xx.h"
+#include "tuner_tua9001.h"
typedef struct rtlsdr_tuner_iface {
/* tuner interface */
@@ -248,6 +249,15 @@ int r820t_set_gain_mode(void *dev, int manual) {
return r82xx_set_gain(&devt->r82xx_p, manual, 0);
}
+int tua9001_set_freq(void *dev, uint32_t freq) {
+ return tua9001_set_params(dev,freq,8000000);
+}
+int tua9001_set_bw(void *dev, int bw_hz) {
+ return tua9001_set_params(dev,0,8000000);
+}
+int tua9001_set_gain(void *dev, int gain) { return 0; }
+int tua9001_set_gain_mode(void *dev, int manual) { return 0; }
+
/* definition order must match enum rtlsdr_tuner */
static rtlsdr_tuner_iface_t tuners[] = {
{
@@ -283,6 +293,11 @@ static rtlsdr_tuner_iface_t tuners[] = {
r820t_set_freq, r820t_set_bw, r820t_set_gain, NULL,
r820t_set_gain_mode
},
+ {
+ tua9001_init, tua9001_release,
+ tua9001_set_freq, tua9001_set_bw, tua9001_set_gain, NULL,
+ tua9001_set_gain_mode
+ }
};
typedef struct rtlsdr_dongle {
@@ -298,6 +313,7 @@ static rtlsdr_dongle_t known_devices[] = {
{ 0x0bda, 0x2832, "Generic RTL2832U" },
{ 0x0bda, 0x2838, "Generic RTL2832U OEM" },
{ 0x0413, 0x6680, "DigitalNow Quad DVB-T PCI-E card" },
+ { 0x0413, 0x6a03, "Leadtek Research, Inc. RTL2832 [WinFast DTV Dongle Mini]"},
{ 0x0413, 0x6f0f, "Leadtek WinFast DTV Dongle mini D" },
{ 0x0458, 0x707f, "Genius TVGo DVB-T03 USB dongle (Ver. B)" },
{ 0x0ccd, 0x00a9, "Terratec Cinergy T Stick Black (rev 1)" },
@@ -320,6 +336,7 @@ static rtlsdr_dongle_t known_devices[] = {
{ 0x1b80, 0xd393, "GIGABYTE GT-U7300" },
{ 0x1b80, 0xd394, "DIKOM USB-DVBT HD" },
{ 0x1b80, 0xd395, "Peak 102569AGPK" },
+ { 0x1b80, 0xd396, "Hamlet eXagerate XDVBT900BK"},
{ 0x1b80, 0xd397, "KWorld KW-UB450-T USB DVB-T Pico TV" },
{ 0x1b80, 0xd398, "Zaapa ZT-MINDVBZP" },
{ 0x1b80, 0xd39d, "SVEON STV20 DVB-T USB & FM" },
@@ -335,7 +352,7 @@ static rtlsdr_dongle_t known_devices[] = {
{ 0x1f4d, 0xb803, "GTek T803" },
{ 0x1f4d, 0xc803, "Lifeview LV5TDeluxe" },
{ 0x1f4d, 0xd286, "MyGica TD312" },
- { 0x1f4d, 0xd803, "PROlectrix DV107669" },
+ { 0x1f4d, 0xd803, "PROlectrix DV107669" }
};
#define DEFAULT_BUF_NUMBER 15
@@ -436,6 +453,14 @@ uint8_t rtlsdr_i2c_read_reg(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t reg)
return data;
}
+uint16_t rtlsdr_i2c_tunb_read_reg(rtlsdr_dev_t *dev, uint8_t i2c_addr, int8_t reg)
+{
+ uint8_t data[2] = {0,0};
+ rtlsdr_read_array(dev, TUNB, reg << 8 | i2c_addr, (uint8_t *) &data, 2);
+
+ return data[0]<<8 | data[1];
+}
+
int rtlsdr_i2c_write(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t *buffer, int len)
{
uint16_t addr = i2c_addr;
@@ -446,6 +471,16 @@ int rtlsdr_i2c_write(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t *buffer, int l
return rtlsdr_write_array(dev, IICB, addr, buffer, len);
}
+int rtlsdr_i2c_tunb_write(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t *buffer, int len)
+{
+ uint16_t addr = (buffer[0] << 8) | i2c_addr ;
+
+ if (!dev)
+ return -1;
+
+ return rtlsdr_write_array(dev, TUNB, addr, &(buffer[1]), len);
+}
+
int rtlsdr_i2c_read(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t *buffer, int len)
{
uint16_t addr = i2c_addr;
@@ -1396,7 +1431,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
libusb_device *device = NULL;
uint32_t device_count = 0;
struct libusb_device_descriptor dd;
- uint8_t reg;
+ uint16_t reg;
ssize_t cnt;
dev = malloc(sizeof(rtlsdr_dev_t));
@@ -1511,6 +1546,15 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
dev->tuner_type = RTLSDR_TUNER_R828D;
goto found;
}
+
+ reg = rtlsdr_i2c_tunb_read_reg(dev, TUA9001_I2C_ADDR, TUA9001_CHECK_ADDR);
+ if (reg == TUA9001_CHECK_VAL) {
+ fprintf(stderr, "Found Infineon TUA9001 tuner\n");
+ //rtlsdr_set_gpio_output(dev, 1);
+ //rtlsdr_set_gpio_output(dev, 4);
+ dev->tuner_type = RTLSDR_TUNER_TUA9001;
+ goto found;
+ }
/* initialise GPIOs */
rtlsdr_set_gpio_output(dev, 5);
@@ -1533,7 +1577,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
dev->tuner_type = RTLSDR_TUNER_FC0012;
goto found;
}
-
+
found:
/* use the rtl clock value by default */
dev->tun_xtal = dev->rtl_xtal;
@@ -1885,3 +1929,15 @@ int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len)
return -1;
}
+
+int rtlsdr_i2c_tunb_write_fn(void *dev, uint8_t addr, uint8_t *buf, int len)
+{
+ if (dev)
+ return rtlsdr_i2c_tunb_write(((rtlsdr_dev_t *)dev), addr, buf, len);
+
+ return -1;
+}
+
+void rtlsdr_set_gpio_bit_fn(rtlsdr_dev_t *dev, uint8_t gpio, int val){
+ rtlsdr_set_gpio_bit(dev, gpio, val);
+}
\ No newline at end of file
diff --git a/src/tuner_tua9001.c b/src/tuner_tua9001.c
new file mode 100644
index 0000000..e1bd725
--- /dev/null
+++ b/src/tuner_tua9001.c
@@ -0,0 +1,139 @@
+#include <stdint.h>
+#include <stdio.h>
+
+#include <unistd.h>
+
+#include "rtlsdr_i2c.h"
+#include "tuner_tua9001.h"
+
+#define RETURN_OK 0
+#define RETURN_ERR -1
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#define SYS_DVBT 0 /* as we know only one */
+
+struct reg_val {
+ uint8_t reg;
+ uint16_t val;
+};
+
+/* write register */
+int tua9001_wr_reg(void *dev, uint8_t reg, uint16_t val)
+{
+ int ret;
+ uint8_t buf[3] = { reg, (val >> 8) & 0xff, (val >> 0) & 0xff };
+
+ ret = rtlsdr_i2c_tunb_write_fn(dev, TUA9001_I2C_ADDR, buf, 2);
+ if (ret < 0) {
+ fprintf(stderr, "%s: i2c wr failed=%d reg=%02x\n","tuner_tua9001.c", ret, reg);
+ }
+
+ return ret;
+}
+
+int tua9001_release(void *dev)
+{
+ return 0;
+}
+
+int tua9001_init(void *dev)
+{
+ int ret = 0;
+ uint8_t i;
+ struct reg_val data[] = {
+ { 0x1e, 0x6512 },
+ { 0x25, 0xb888 },
+ { 0x39, 0x5460 },
+ { 0x3b, 0x00c0 },
+ { 0x3a, 0xf000 },
+ { 0x08, 0x0000 },
+ { 0x32, 0x0030 },
+ { 0x41, 0x703a },
+ { 0x40, 0x1c78 },
+ { 0x2c, 0x1c00 },
+ { 0x36, 0xc013 },
+ { 0x37, 0x6f18 },
+ { 0x27, 0x0008 },
+ { 0x2a, 0x0001 },
+ { 0x34, 0x0a40 },
+ };
+
+ rtlsdr_set_gpio_bit_fn(dev,TUA9001_RESETN_PIN,0);
+
+ for (i = 0; i < ARRAY_SIZE(data); i++) {
+ ret = tua9001_wr_reg(dev, data[i].reg, data[i].val);
+ if (ret < 0)
+ goto err;
+ }
+err:
+ if (ret < 0)
+ fprintf(stderr, "%s: failed=%d\n","tua9001_init", ret);
+
+ return RETURN_OK;
+}
+
+int tua9001_set_params(void *dev, uint32_t frequency_hz, uint32_t bandwidth_hz)
+{
+ int ret = 0;
+ unsigned int i;
+ uint16_t val;
+ uint32_t frequency;
+ struct reg_val data[2];
+
+ uint8_t delivery_system = SYS_DVBT;
+
+ //fprintf(stderr, "%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n", "tua9001_set_params", delivery_system ,frequency_hz, bandwidth_hz);
+
+ switch (SYS_DVBT) {
+ case SYS_DVBT:
+ switch (bandwidth_hz) {
+ case 8000000:
+ val = 0x0000;
+ break;
+ case 7000000:
+ val = 0x1000;
+ break;
+ case 6000000:
+ val = 0x2000;
+ break;
+ case 5000000:
+ val = 0x3000;
+ break;
+ default:
+ ret = -1;
+ goto err;
+ }
+ break;
+ default:
+ ret = -1;
+ goto err;
+ }
+
+ data[0].reg = 0x04;
+ data[0].val = val;
+
+ frequency = (frequency_hz - 150000000);
+ frequency /= 100;
+ frequency *= 48;
+ frequency /= 10000;
+
+ data[1].reg = 0x1f;
+ data[1].val = frequency;
+
+ rtlsdr_set_gpio_bit_fn(dev,TUA9001_RXEN_PIN,0);
+
+ for (i = 0; i < ARRAY_SIZE(data); i++) {
+ ret = tua9001_wr_reg(dev, data[i].reg, data[i].val);
+ if (ret < 0)
+ goto err;
+ }
+
+ rtlsdr_set_gpio_bit_fn(dev,TUA9001_RXEN_PIN,1);
+
+err:
+ if (ret < 0)
+ fprintf(stderr, "%s: failed=%d\n", "tua9001_set_params", ret);
+
+ return ret;
+}
\ No newline at end of file
--
1.7.10.4