rtl_tcp: implement sample rate and gain control

This commit is contained in:
Dimitri Stolnikov 2012-05-06 19:42:27 +02:00
parent f94d8da48e
commit e38dc2f427
6 changed files with 96 additions and 29 deletions

View File

@ -115,7 +115,7 @@ of devices. If left blank, the first device found will be used.
Examples (some arguments may be optional): Examples (some arguments may be optional):
fcd=0 fcd=0
rtl=0,rtl_xtal=28.80001e6,tuner_xtal=26e6,buffers=64 ... rtl=0,rtl_xtal=28.80001e6,tuner_xtal=26e6,buffers=64 ...
rtl_tcp=host=127.0.0.1,port=1234,eof=false,wait=true,psize=16384 rtl_tcp=host=127.0.0.1,port=1234,psize=16384
uhd=0|name,mcr=52e6,nchan=2,subdev='\\\\'B:0 A:0'\\\\' ... uhd=0|name,mcr=52e6,nchan=2,subdev='\\\\'B:0 A:0'\\\\' ...
osmosdr=0|name,mcr=64e6,nchan=5,port=/dev/ttyUSB0 ... osmosdr=0|name,mcr=64e6,nchan=5,port=/dev/ttyUSB0 ...
file=/path/to/file.ext,freq=428e6,rate=1e6,repeat=true,throttle=true ... file=/path/to/file.ext,freq=428e6,rate=1e6,repeat=true,throttle=true ...

View File

@ -435,7 +435,7 @@ bool rtl_source_c::get_gain_mode( size_t chan )
return _auto_gain; return _auto_gain;
} }
double pick_closest_gain(osmosdr::gain_range_t &gains, double required) static double pick_closest_gain(osmosdr::gain_range_t &gains, double required)
{ {
double result = required; double result = required;
double distance = 100; double distance = 100;

View File

@ -46,12 +46,12 @@ rtl_tcp_source_c::rtl_tcp_source_c(const std::string &args) :
{ {
std::string host = "127.0.0.1"; std::string host = "127.0.0.1";
unsigned short port = 1234; unsigned short port = 1234;
bool eof = false;
bool wait = true;
int payload_size = 16384; int payload_size = 16384;
_freq = 0; _freq = 0;
_rate = 0; _rate = 0;
_gain = 0;
_auto_gain = false;
dict_t dict = params_to_dict(args); dict_t dict = params_to_dict(args);
@ -61,12 +61,6 @@ rtl_tcp_source_c::rtl_tcp_source_c(const std::string &args) :
if (dict.count("port")) if (dict.count("port"))
port = boost::lexical_cast< unsigned short >( dict["port"] ); port = boost::lexical_cast< unsigned short >( dict["port"] );
if (dict.count("eof"))
eof = "true" == dict["eof"] ? true : false;
if (dict.count("wait"))
wait = "true" == dict["wait"] ? true : false;
if (dict.count("psize")) if (dict.count("psize"))
payload_size = boost::lexical_cast< int >( dict["psize"] ); payload_size = boost::lexical_cast< int >( dict["psize"] );
@ -80,7 +74,9 @@ rtl_tcp_source_c::rtl_tcp_source_c(const std::string &args) :
payload_size = 16384; payload_size = 16384;
_src = make_rtl_tcp_source_f(sizeof(float), host.c_str(), port, payload_size, _src = make_rtl_tcp_source_f(sizeof(float), host.c_str(), port, payload_size,
eof, wait); false, false);
set_gain_mode(false); // enable manual gain mode by default
/* rtl tcp source provides a stream of interleaved IQ floats */ /* rtl tcp source provides a stream of interleaved IQ floats */
gr_deinterleave_sptr deinterleave = gr_make_deinterleave(sizeof(float)); gr_deinterleave_sptr deinterleave = gr_make_deinterleave(sizeof(float));
@ -117,13 +113,24 @@ osmosdr::meta_range_t rtl_tcp_source_c::get_sample_rates( void )
{ {
osmosdr::meta_range_t range; osmosdr::meta_range_t range;
range += osmosdr::range_t( get_sample_rate() ); range += osmosdr::range_t( 1024000 ); // known to work
range += osmosdr::range_t( 1800000 ); // known to work
range += osmosdr::range_t( 2048000 ); // known to work
range += osmosdr::range_t( 2400000 ); // may work
range += osmosdr::range_t( 2600000 ); // may work
range += osmosdr::range_t( 2800000 ); // may work
range += osmosdr::range_t( 3000000 ); // may work
range += osmosdr::range_t( 3200000 ); // max rate, may work
return range; return range;
} }
double rtl_tcp_source_c::set_sample_rate( double rate ) double rtl_tcp_source_c::set_sample_rate( double rate )
{ {
_src->set_sample_rate( int(rate) );
_rate = rate;
return get_sample_rate(); return get_sample_rate();
} }
@ -170,7 +177,26 @@ std::vector<std::string> rtl_tcp_source_c::get_gain_names( size_t chan )
osmosdr::gain_range_t rtl_tcp_source_c::get_gain_range( size_t chan ) osmosdr::gain_range_t rtl_tcp_source_c::get_gain_range( size_t chan )
{ {
osmosdr::gain_range_t range(0, 0); osmosdr::gain_range_t range;
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 );
return range; return range;
} }
@ -182,16 +208,45 @@ osmosdr::gain_range_t rtl_tcp_source_c::get_gain_range( const std::string & name
bool rtl_tcp_source_c::set_gain_mode( bool mode, size_t chan ) bool rtl_tcp_source_c::set_gain_mode( bool mode, size_t chan )
{ {
_src->set_gain_mode(int(!mode));
_auto_gain = mode;
return get_gain_mode(chan); return get_gain_mode(chan);
} }
bool rtl_tcp_source_c::get_gain_mode( size_t chan ) bool rtl_tcp_source_c::get_gain_mode( size_t chan )
{ {
return true; return _auto_gain;
}
static double pick_closest_gain(osmosdr::gain_range_t &gains, double required)
{
double result = required;
double distance = 100;
BOOST_FOREACH(osmosdr::range_t gain, gains)
{
double diff = fabs(gain.start() - required);
if (diff < distance) {
distance = diff;
result = gain.start();
}
}
return result;
} }
double rtl_tcp_source_c::set_gain( double gain, size_t chan ) double rtl_tcp_source_c::set_gain( double gain, size_t chan )
{ {
osmosdr::gain_range_t gains = rtl_tcp_source_c::get_gain_range( chan );
double picked_gain = pick_closest_gain( gains, gain );
_src->set_gain( int(picked_gain * 10.0) );
_gain = gain;
return get_gain(chan); return get_gain(chan);
} }

View File

@ -75,7 +75,8 @@ public:
std::string get_antenna( size_t chan = 0 ); std::string get_antenna( size_t chan = 0 );
private: private:
double _freq, _rate; double _freq, _rate, _gain;
bool _auto_gain;
rtl_tcp_source_f_sptr _src; rtl_tcp_source_f_sptr _src;
}; };

View File

@ -82,9 +82,7 @@ rtl_tcp_source_f::rtl_tcp_source_f(size_t itemsize,
d_eof(eof), d_eof(eof),
d_wait(wait), d_wait(wait),
d_socket(-1), d_socket(-1),
d_residual(0), d_temp_offset(0)
d_temp_offset(0),
curr_freq(0)
{ {
int ret = 0; int ret = 0;
struct sockaddr_in cliaddr; struct sockaddr_in cliaddr;
@ -248,12 +246,24 @@ struct command{
void rtl_tcp_source_f::set_freq(int freq) void rtl_tcp_source_f::set_freq(int freq)
{ {
struct command cmd; struct command cmd = { 0x01, freq };
send(d_socket, (const char*)&cmd, sizeof(cmd), 0);
if (freq != curr_freq) { }
cmd.cmd = 0x01;
cmd.param = freq; void rtl_tcp_source_f::set_sample_rate(int sample_rate)
send(d_socket, (const char*)&cmd, sizeof(cmd), 0); {
curr_freq = freq; struct command cmd = { 0x02, sample_rate };
} send(d_socket, (const char*)&cmd, sizeof(cmd), 0);
}
void rtl_tcp_source_f::set_gain_mode(int manual)
{
struct command cmd = { 0x03, manual };
send(d_socket, (const char*)&cmd, sizeof(cmd), 0);
}
void rtl_tcp_source_f::set_gain(int gain)
{
struct command cmd = { 0x04, gain };
send(d_socket, (const char*)&cmd, sizeof(cmd), 0);
} }

View File

@ -66,9 +66,7 @@ private:
bool d_wait; // wait if data if not immediately available bool d_wait; // wait if data if not immediately available
int d_socket; // handle to socket int d_socket; // handle to socket
unsigned char *d_temp_buff; // hold buffer between calls unsigned char *d_temp_buff; // hold buffer between calls
ssize_t d_residual; // hold information about number of bytes stored in the temp buffer size_t d_temp_offset; // point to temp buffer location offset
size_t d_temp_offset; // point to temp buffer location offset
int curr_freq;
float *d_LUT; float *d_LUT;
private: private:
@ -93,6 +91,9 @@ private:
gr_vector_void_star &output_items); gr_vector_void_star &output_items);
void set_freq(int freq); void set_freq(int freq);
void set_sample_rate(int sample_rate);
void set_gain_mode(int manual);
void set_gain(int gain);
}; };