From 43a6afdf28a74693074cc6355594229a33e29923 Mon Sep 17 00:00:00 2001 From: Dimitri Stolnikov Date: Sat, 29 Dec 2012 14:20:27 +0100 Subject: [PATCH] rtl_tcp: add support for tuner caps discovery --- lib/rtl_tcp/rtl_tcp_source_c.cc | 91 +++++++++++++++++++++++++-------- lib/rtl_tcp/rtl_tcp_source_f.cc | 27 ++++++++-- lib/rtl_tcp/rtl_tcp_source_f.h | 16 ++++++ 3 files changed, 111 insertions(+), 23 deletions(-) diff --git a/lib/rtl_tcp/rtl_tcp_source_c.cc b/lib/rtl_tcp/rtl_tcp_source_c.cc index 32700bf..b62b77d 100644 --- a/lib/rtl_tcp/rtl_tcp_source_c.cc +++ b/lib/rtl_tcp/rtl_tcp_source_c.cc @@ -35,6 +35,22 @@ using namespace boost::assign; +std::string get_tuner_name( enum rtlsdr_tuner tuner_type ) +{ + if ( RTLSDR_TUNER_E4000 == tuner_type ) + return "E4000"; + else if ( RTLSDR_TUNER_FC0012 == tuner_type ) + return "FC0012"; + else if ( RTLSDR_TUNER_FC0013 == tuner_type ) + return "FC0013"; + else if ( RTLSDR_TUNER_FC2580 == tuner_type ) + return "FC2580"; + else if ( RTLSDR_TUNER_R820T == tuner_type ) + return "R820T"; + else + return "Unknown"; +} + rtl_tcp_source_c_sptr make_rtl_tcp_source_c(const std::string &args) { return gnuradio::get_initial_sptr(new rtl_tcp_source_c(args)); @@ -83,7 +99,16 @@ rtl_tcp_source_c::rtl_tcp_source_c(const std::string &args) : _src = make_rtl_tcp_source_f(sizeof(float), host.c_str(), port, payload_size, false, false); - set_gain_mode(false); // enable manual gain mode by default + if ( _src->get_tuner_type() != RTLSDR_TUNER_UNKNOWN ) + { + std::cerr << "The RTL TCP server reports a " + << get_tuner_name( _src->get_tuner_type() ) + << " tuner with " << _src->get_tuner_gain_count() + << " selectable gains." + << std::endl; + } + + set_gain_mode(false); /* enable manual gain mode by default */ /* rtl tcp source provides a stream of interleaved IQ floats */ gr_deinterleave_sptr deinterleave = gr_make_deinterleave(sizeof(float)); @@ -201,26 +226,52 @@ osmosdr::gain_range_t rtl_tcp_source_c::get_gain_range( size_t chan ) { osmosdr::gain_range_t range; - // FIXME: assumption on E4000 tuner + /* the following gain values have been copied from librtlsdr */ - range += osmosdr::range_t( -1.0 ); - range += osmosdr::range_t( 1.5 ); - range += osmosdr::range_t( 4.0 ); - range += osmosdr::range_t( 6.5 ); - range += osmosdr::range_t( 9.0 ); - range += osmosdr::range_t( 11.5 ); - range += osmosdr::range_t( 14.0 ); - range += osmosdr::range_t( 16.5 ); - range += osmosdr::range_t( 19.0 ); - range += osmosdr::range_t( 21.5 ); - range += osmosdr::range_t( 24.0 ); - range += osmosdr::range_t( 29.0 ); - range += osmosdr::range_t( 34.0 ); - range += osmosdr::range_t( 42.0 ); - range += osmosdr::range_t( 43.0 ); - range += osmosdr::range_t( 45.0 ); - range += osmosdr::range_t( 47.0 ); - range += osmosdr::range_t( 49.0 ); + /* all gain values are expressed in tenths of a dB */ + const int e4k_gains[] = { -10, 15, 40, 65, 90, 115, 140, 165, 190, 215, + 240, 290, 340, 420 }; + const int fc0012_gains[] = { -99, -40, 71, 179, 192 }; + const int fc0013_gains[] = { -99, -73, -65, -63, -60, -58, -54, 58, 61, + 63, 65, 67, 68, 70, 71, 179, 181, 182, + 184, 186, 188, 191, 197 }; + const int fc2580_gains[] = { 0 /* no gain values */ }; + const int r820t_gains[] = { 0, 9, 14, 27, 37, 77, 87, 125, 144, 157, + 166, 197, 207, 229, 254, 280, 297, 328, + 338, 364, 372, 386, 402, 421, 434, 439, + 445, 480, 496 }; + const int unknown_gains[] = { 0 /* no gain values */ }; + + const int *ptr = NULL; + int len = 0; + + switch (_src->get_tuner_type()) + { + case RTLSDR_TUNER_E4000: + ptr = e4k_gains; len = sizeof(e4k_gains); + break; + case RTLSDR_TUNER_FC0012: + ptr = fc0012_gains; len = sizeof(fc0012_gains); + break; + case RTLSDR_TUNER_FC0013: + ptr = fc0013_gains; len = sizeof(fc0013_gains); + break; + case RTLSDR_TUNER_FC2580: + ptr = fc2580_gains; len = sizeof(fc2580_gains); + break; + case RTLSDR_TUNER_R820T: + ptr = r820t_gains; len = sizeof(r820t_gains); + break; + default: + ptr = unknown_gains; len = sizeof(unknown_gains); + break; + } + + if ( ptr != NULL && len > 0 ) + { + for (int i = 0; i < int(len / sizeof(int)); i++) + range += osmosdr::range_t( ptr[i] / 10.0f ); + } return range; } diff --git a/lib/rtl_tcp/rtl_tcp_source_f.cc b/lib/rtl_tcp/rtl_tcp_source_f.cc index 64399c3..3e6c0a9 100644 --- a/lib/rtl_tcp/rtl_tcp_source_f.cc +++ b/lib/rtl_tcp/rtl_tcp_source_f.cc @@ -1,6 +1,7 @@ /* -*- c++ -*- */ /* * Copyright 2012 Hoernchen + * Copyright 2012 Dimitri Stolnikov * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +34,13 @@ #include #endif +/* copied from rtl sdr code */ +typedef struct { /* structure size must be multiple of 2 bytes */ + char magic[4]; + uint32_t tuner_type; + uint32_t tuner_gain_count; +} dongle_info_t; + #define USE_SELECT 1 // non-blocking receive on all platforms #define USE_RCV_TIMEO 0 // non-blocking receive on all but Cygwin #define SRC_VERBOSE 0 @@ -83,9 +91,9 @@ rtl_tcp_source_f::rtl_tcp_source_f(size_t itemsize, : gr_sync_block ("rtl_tcp_source_f", gr_make_io_signature(0, 0, 0), gr_make_io_signature(1, 1, sizeof(float))), - d_itemsize(itemsize), + d_itemsize(itemsize), d_payload_size(payload_size), - d_eof(eof), + d_eof(eof), d_wait(wait), d_socket(-1), d_temp_offset(0) @@ -163,12 +171,25 @@ rtl_tcp_source_f::rtl_tcp_source_f(size_t itemsize, } #endif // USE_RCV_TIMEO - while(connect(d_socket, ip_src->ai_addr, ip_src->ai_addrlen) != 0); freeaddrinfo(ip_src); int flag = 1; setsockopt(d_socket, IPPROTO_TCP, TCP_NODELAY, (char *)&flag,sizeof(flag)); + + dongle_info_t dongle_info; + ret = recv(d_socket, (char*)&dongle_info, sizeof(dongle_info), 0); + if (sizeof(dongle_info) != ret) + fprintf(stderr,"failed to read dongle info\n"); + + d_tuner_type = RTLSDR_TUNER_UNKNOWN; + d_tuner_gain_count = 0; + + if (memcmp(dongle_info.magic, "RTL0", 4) == 0) + { + d_tuner_type = ntohl(dongle_info.tuner_type); + d_tuner_gain_count = ntohl(dongle_info.tuner_gain_count); + } } rtl_tcp_source_f_sptr make_rtl_tcp_source_f (size_t itemsize, diff --git a/lib/rtl_tcp/rtl_tcp_source_f.h b/lib/rtl_tcp/rtl_tcp_source_f.h index 694708a..80b079d 100644 --- a/lib/rtl_tcp/rtl_tcp_source_f.h +++ b/lib/rtl_tcp/rtl_tcp_source_f.h @@ -44,6 +44,16 @@ typedef void* optval_t; #define ssize_t int +/* copied from rtl sdr */ +enum rtlsdr_tuner { + RTLSDR_TUNER_UNKNOWN = 0, + RTLSDR_TUNER_E4000, + RTLSDR_TUNER_FC0012, + RTLSDR_TUNER_FC0013, + RTLSDR_TUNER_FC2580, + RTLSDR_TUNER_R820T +}; + class rtl_tcp_source_f; typedef boost::shared_ptr rtl_tcp_source_f_sptr; @@ -67,6 +77,9 @@ private: size_t d_temp_offset; // point to temp buffer location offset float *d_LUT; + unsigned int d_tuner_type; + unsigned int d_tuner_gain_count; + private: rtl_tcp_source_f(size_t itemsize, const char *host, unsigned short port, int payload_size, bool eof, bool wait); @@ -84,6 +97,9 @@ private: public: ~rtl_tcp_source_f(); + enum rtlsdr_tuner get_tuner_type() { return (enum rtlsdr_tuner) d_tuner_type; } + unsigned int get_tuner_gain_count() { return d_tuner_gain_count; } + int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);