From ff7910482453d39a776fbbe2ad79c59e87fa5132 Mon Sep 17 00:00:00 2001 From: Steve Markgraf Date: Sat, 31 Mar 2012 21:01:25 +0200 Subject: [PATCH] add support for autoprobing the tuners Signed-off-by: Steve Markgraf --- include/tuner_e4000.h | 111 ++--------------------------------------- include/tuner_fc0013.h | 4 ++ src/rtl-sdr.c | 98 +++++++++++++++++++++++++++++++++--- src/tuner_e4000.c | 2 - src/tuner_fc0013.c | 1 - 5 files changed, 99 insertions(+), 117 deletions(-) diff --git a/include/tuner_e4000.h b/include/tuner_e4000.h index 4c78f3e..5aa71f5 100644 --- a/include/tuner_e4000.h +++ b/include/tuner_e4000.h @@ -1,120 +1,15 @@ #ifndef __TUNER_E4000_H #define __TUNER_E4000_H -/** - -@file - -@brief E4000 tuner module declaration - -One can manipulate E4000 tuner through E4000 module. -E4000 module is derived from tuner module. - - - -@par Example: -@code - -// The example is the same as the tuner example in tuner_base.h except the listed lines. - - - -#include "tuner_e4000.h" - - -... - - - -int main(void) -{ - TUNER_MODULE *pTuner; - E4000_EXTRA_MODULE *pTunerExtra; - - TUNER_MODULE TunerModuleMemory; - BASE_INTERFACE_MODULE BaseInterfaceModuleMemory; -// I2C_BRIDGE_MODULE I2cBridgeModuleMemory; - - unsigned long BandwidthMode; - - - ... - - - - // Build E4000 tuner module. - BuildE4000Module( - &pTuner, - &TunerModuleMemory, - &BaseInterfaceModuleMemory, - &I2cBridgeModuleMemory, - 0xac, // I2C device address is 0xac in 8-bit format. - CRYSTAL_FREQ_16384000HZ, // Crystal frequency is 16.384 MHz. - E4000_AGC_INTERNAL // The E4000 AGC mode is internal AGC mode. - ); - - - - - - // Get E4000 tuner extra module. - pTunerExtra = (T2266_EXTRA_MODULE *)(pTuner->pExtra); - - - - - - // ==== Initialize tuner and set its parameters ===== - - ... - - // Set E4000 bandwidth. - pTunerExtra->SetBandwidthMode(pTuner, E4000_BANDWIDTH_6MHZ); - - - - - - // ==== Get tuner information ===== - - ... - - // Get E4000 bandwidth. - pTunerExtra->GetBandwidthMode(pTuner, &BandwidthMode); - - - - // See the example for other tuner functions in tuner_base.h - - - return 0; -} - - -@endcode - -*/ - - - - - -//#include "tuner_base.h" - - - - - -// The following context is implemented for E4000 source code. - - // Definition (implemeted for E4000) #define E4000_1_SUCCESS 1 #define E4000_1_FAIL 0 #define E4000_I2C_SUCCESS 1 #define E4000_I2C_FAIL 0 - +#define E4K_I2C_ADDR 0xc8 +#define E4K_CHECK_ADDR 0x02 +#define E4K_CHECK_VAL 0x40 // Function (implemeted for E4000) int diff --git a/include/tuner_fc0013.h b/include/tuner_fc0013.h index b405808..ed89465 100644 --- a/include/tuner_fc0013.h +++ b/include/tuner_fc0013.h @@ -15,6 +15,10 @@ FC0013 module is derived from tuner module. **/ +#define FC0013_I2C_ADDR 0xc6 +#define FC0013_CHECK_ADDR 0x00 +#define FC0013_CHECK_VAL 0xa3 + // Definitions enum FC0013_TRUE_FALSE_STATUS { diff --git a/src/rtl-sdr.c b/src/rtl-sdr.c index d5a0e8d..b88ac60 100644 --- a/src/rtl-sdr.c +++ b/src/rtl-sdr.c @@ -5,7 +5,7 @@ * 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. + * (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 @@ -44,7 +44,7 @@ int fc0013_init(void *dev) { return FC0013_Open(dev); } int fc0013_exit(void *dev) { return 0; } int fc0013_tune(void *dev, int freq) { /* read bandwidth mode to reapply it */ - int bw = 0; + unsigned int bw = 6; //fc0013_GetBandwidthMode(dev, &bw); // FIXME: missing return FC0013_SetFrequency(dev, freq/1000, bw & 0xff); } @@ -57,10 +57,9 @@ int fc0013_set_bw(void *dev, int bw) { } enum rtlsdr_tuners { - RTLSDR_TUNER_UNDEF, RTLSDR_TUNER_E4000, RTLSDR_TUNER_FC0012, - RTLSDR_TUNER_FC0013 + RTLSDR_TUNER_FC0013, }; typedef struct rtlsdr_tuner { @@ -161,6 +160,23 @@ int rtlsdr_write_array(rtlsdr_dev_t *dev, uint8_t block, uint16_t addr, uint8_t return r; } +int rtlsdr_i2c_write_reg(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t data) +{ + uint16_t addr = i2c_addr; + return rtlsdr_write_array(dev, IICB, addr, &data, 1); +} + +uint8_t rtlsdr_i2c_read_reg(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t reg) +{ + uint16_t addr = i2c_addr; + uint8_t data; + + rtlsdr_write_array(dev, IICB, addr, ®, 1); + rtlsdr_read_array(dev, IICB, addr, &data, 1); + + return data; +} + int rtlsdr_i2c_write(rtlsdr_dev_t *dev, uint8_t i2c_addr, uint8_t *buffer, int len) { uint16_t addr = i2c_addr; @@ -251,6 +267,27 @@ void rtlsdr_demod_write_reg(rtlsdr_dev_t *dev, uint8_t page, uint16_t addr, uint rtlsdr_demod_read_reg(dev, 0x0a, 0x01, 1); } +void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val) +{ + uint8_t r; + + gpio = 1 << gpio; + r = rtlsdr_read_reg(dev, SYSB, GPO, 1); + r = val ? (r | gpio) : (r & ~gpio); + rtlsdr_write_reg(dev, SYSB, GPO, r, 1); +} + +void rtlsdr_set_gpio_output(rtlsdr_dev_t *dev, uint8_t gpio) +{ + int r; + gpio = 1 << gpio; + + r = rtlsdr_read_reg(dev, SYSB, GPD, 1); + rtlsdr_write_reg(dev, SYSB, GPO, r & ~gpio, 1); + r = rtlsdr_read_reg(dev, SYSB, GPOE, 1); + rtlsdr_write_reg(dev, SYSB, GPOE, r | gpio, 1); +} + void rtlsdr_set_i2c_repeater(rtlsdr_dev_t *dev, int on) { rtlsdr_demod_write_reg(dev, 1, 0x01, on ? 0x18 : 0x10, 1); @@ -464,6 +501,15 @@ const char *rtlsdr_get_device_name(uint32_t index) return ""; } +/* TODO: put those defines in the tuner header once the drivers are added */ +#define FC0012_I2C_ADDR 0xc6 +#define FC0012_CHECK_ADDR 0x00 +#define FC0012_CHECK_VAL 0xa1 + +#define FC2580_I2C_ADDR 0xac +#define FC2580_CHECK_ADDR 0x01 +#define FC2580_CHECK_VAL 0x56 + rtlsdr_dev_t *rtlsdr_open(int index) { int r; @@ -473,6 +519,7 @@ rtlsdr_dev_t *rtlsdr_open(int index) libusb_device *device = NULL; uint32_t device_count = 0; struct libusb_device_descriptor dd; + uint8_t reg; dev = malloc(sizeof(rtlsdr_dev_t)); memset(dev, 0, sizeof(rtlsdr_dev_t)); @@ -514,10 +561,49 @@ rtlsdr_dev_t *rtlsdr_open(int index) rtlsdr_init_baseband(dev); - // TODO: probe the tuner and set dev->tuner member to appropriate tuner object - // dev->tuner = &tuners[...]; + /* Probe tuners */ + rtlsdr_set_i2c_repeater(dev, 1); + reg = rtlsdr_i2c_read_reg(dev, E4K_I2C_ADDR, E4K_CHECK_ADDR); + if (reg == E4K_CHECK_VAL) { + printf("Found Elonics E4000 tuner\n"); + dev->tuner = &tuners[RTLSDR_TUNER_E4000]; + goto found; + } + + reg = rtlsdr_i2c_read_reg(dev, FC0013_I2C_ADDR, FC0013_CHECK_ADDR); + if (reg == FC0013_CHECK_VAL) { + printf("Found Fitipower FC0013 tuner\n"); + dev->tuner = &tuners[RTLSDR_TUNER_FC0013]; + goto found; + } + + reg = rtlsdr_i2c_read_reg(dev, FC2580_I2C_ADDR, FC2580_CHECK_ADDR); + if ((reg & 0x7f) == FC2580_CHECK_VAL) { + printf("Found FCI 2580 tuner\n"); + //dev->tuner = &tuners[RTLSDR_TUNER_FC2580]; + // TODO: set GPIO5 low + goto found; + } + + /* initialise GPIOs (only needed for the FC0012 so far */ + rtlsdr_set_gpio_output(dev, 5); + + /* reset FC0012 before probing */ + rtlsdr_set_gpio_bit(dev, 5, 1); + rtlsdr_set_gpio_bit(dev, 5, 0); + + reg = rtlsdr_i2c_read_reg(dev, FC0012_I2C_ADDR, FC0012_CHECK_ADDR); + if (reg == FC0012_CHECK_VAL) { + printf("Found Fitipower FC0012 tuner\n"); + dev->tuner = &tuners[RTLSDR_TUNER_FC0012]; + goto found; + } + +found: + rtlsdr_set_i2c_repeater(dev, 0); return dev; + err: return NULL; } diff --git a/src/tuner_e4000.c b/src/tuner_e4000.c index 7cf7159..18aa967 100644 --- a/src/tuner_e4000.c +++ b/src/tuner_e4000.c @@ -18,9 +18,7 @@ #define I2C_BUFFER_LEN 128 #define YES 1 #define NO 0 - #define CRYSTAL_FREQ 28800000 -#define E4K_I2C_ADDR 0xc8 /* glue functions to rtl-sdr code */ int diff --git a/src/tuner_fc0013.c b/src/tuner_fc0013.c index 8da5d06..a228e03 100644 --- a/src/tuner_fc0013.c +++ b/src/tuner_fc0013.c @@ -11,7 +11,6 @@ #include "tuner_fc0013.h" #define CRYSTAL_FREQ 28800000 -#define FC0013_I2C_ADDR 0xc6 /* glue functions to rtl-sdr code */ int FC0013_Write(void *pTuner, unsigned char RegAddr, unsigned char Byte)