forked from sdr/gr-osmosdr
reimplement buffering to make it more efficient
thanks to Hoernchen <la@tfc-server.de> for contributing a proof-of-concept implementation
This commit is contained in:
parent
08b6f7ee0a
commit
ba5e8e94b7
|
@ -43,6 +43,8 @@
|
||||||
|
|
||||||
using namespace boost::assign;
|
using namespace boost::assign;
|
||||||
|
|
||||||
|
#define BUF_SIZE (16 * 32 * 512)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a new instance of rtl_source_c and return
|
* Create a new instance of rtl_source_c and return
|
||||||
* a boost shared_ptr. This is effectively the public constructor.
|
* a boost shared_ptr. This is effectively the public constructor.
|
||||||
|
@ -76,13 +78,19 @@ rtl_source_c::rtl_source_c (const std::string &args)
|
||||||
gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (gr_complex)))
|
gr_make_io_signature (MIN_OUT, MAX_OUT, sizeof (gr_complex)))
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int dev_index = 0;
|
unsigned int dev_index = 0;
|
||||||
|
|
||||||
_buf = boost::circular_buffer<unsigned short>(1024*1024);
|
_buf_num = 32;
|
||||||
|
_buf = (unsigned short **) malloc(_buf_num * sizeof(unsigned short *));
|
||||||
|
|
||||||
|
for(unsigned int i = 0; i < _buf_num; ++i)
|
||||||
|
_buf[i] = (unsigned short *) malloc(BUF_SIZE);
|
||||||
|
|
||||||
|
_buf_head = _buf_used = _buf_offset = 0;
|
||||||
|
_samp_avail = BUF_SIZE;
|
||||||
|
|
||||||
// create a lookup table for gr_complex values
|
// create a lookup table for gr_complex values
|
||||||
for (unsigned int i = 0; i <= 0xffff; i++)
|
for (unsigned int i = 0; i <= 0xffff; i++) {
|
||||||
{
|
|
||||||
#if 1 // little endian
|
#if 1 // little endian
|
||||||
_lut.push_back( gr_complex( (float(i & 0xff) - 127.5f) *(1.0f/128.0f),
|
_lut.push_back( gr_complex( (float(i & 0xff) - 127.5f) *(1.0f/128.0f),
|
||||||
(float(i >> 8) - 127.5f) * (1.0f/128.0f) ) );
|
(float(i >> 8) - 127.5f) * (1.0f/128.0f) ) );
|
||||||
|
@ -92,6 +100,9 @@ rtl_source_c::rtl_source_c (const std::string &args)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( dev_index >= rtlsdr_get_device_count() )
|
||||||
|
throw std::runtime_error("Device index out of bounds for rtlsdr.");
|
||||||
|
|
||||||
std::cerr << "Using device #" << dev_index << " "
|
std::cerr << "Using device #" << dev_index << " "
|
||||||
<< "(" << rtlsdr_get_device_name(dev_index) << ")"
|
<< "(" << rtlsdr_get_device_name(dev_index) << ")"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
|
@ -125,6 +136,14 @@ rtl_source_c::~rtl_source_c ()
|
||||||
rtlsdr_close( _dev );
|
rtlsdr_close( _dev );
|
||||||
_dev = NULL;
|
_dev = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for(unsigned int i = 0; i < _buf_num; ++i) {
|
||||||
|
if (_buf[i])
|
||||||
|
free(_buf[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(_buf);
|
||||||
|
_buf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void rtl_source_c::_rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
|
void rtl_source_c::_rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
|
||||||
|
@ -135,20 +154,22 @@ void rtl_source_c::_rtlsdr_callback(unsigned char *buf, uint32_t len, void *ctx)
|
||||||
|
|
||||||
void rtl_source_c::rtlsdr_callback(unsigned char *buf, uint32_t len)
|
void rtl_source_c::rtlsdr_callback(unsigned char *buf, uint32_t len)
|
||||||
{
|
{
|
||||||
unsigned short * sbuf = (unsigned short *)buf;
|
if (len != BUF_SIZE) {
|
||||||
|
printf("U(%d)\n", len); fflush(stdout);
|
||||||
boost::mutex::scoped_lock lock( _buf_mutex );
|
return;
|
||||||
|
|
||||||
if (len % 2 != 0) {
|
|
||||||
printf("!!! len: %d\n", len); fflush(stdout);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < len/2; i++) {
|
{
|
||||||
if (!_buf.full()) {
|
boost::mutex::scoped_lock lock( _buf_mutex );
|
||||||
_buf.push_back( sbuf[i] );
|
|
||||||
} else {
|
int buf_tail = (_buf_head + _buf_used) % _buf_num;
|
||||||
|
memcpy(_buf[buf_tail], buf, len);
|
||||||
|
|
||||||
|
if (_buf_used == _buf_num) {
|
||||||
printf("O"); fflush(stdout);
|
printf("O"); fflush(stdout);
|
||||||
break;
|
_buf_head = (_buf_head + 1) % _buf_num;
|
||||||
|
} else {
|
||||||
|
_buf_used++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +183,7 @@ void rtl_source_c::_rtlsdr_wait(rtl_source_c *obj)
|
||||||
|
|
||||||
void rtl_source_c::rtlsdr_wait()
|
void rtl_source_c::rtlsdr_wait()
|
||||||
{
|
{
|
||||||
int ret = rtlsdr_read_async( _dev, _rtlsdr_callback, (void *)this, 0, 0 );
|
int ret = rtlsdr_read_async( _dev, _rtlsdr_callback, (void *)this, 0, BUF_SIZE );
|
||||||
|
|
||||||
_running = false;
|
_running = false;
|
||||||
|
|
||||||
|
@ -176,29 +197,49 @@ int rtl_source_c::work( int noutput_items,
|
||||||
{
|
{
|
||||||
gr_complex *out = (gr_complex *)output_items[0];
|
gr_complex *out = (gr_complex *)output_items[0];
|
||||||
|
|
||||||
|
{
|
||||||
|
boost::mutex::scoped_lock lock( _buf_mutex );
|
||||||
|
|
||||||
|
while (_buf_used < 3 && _running)
|
||||||
|
_buf_cond.wait( lock );
|
||||||
|
}
|
||||||
|
|
||||||
if (!_running)
|
if (!_running)
|
||||||
return WORK_DONE;
|
return WORK_DONE;
|
||||||
|
|
||||||
int items_left = noutput_items;
|
unsigned short *buf = _buf[_buf_head];
|
||||||
while ( items_left )
|
|
||||||
{
|
|
||||||
{
|
|
||||||
boost::mutex::scoped_lock lock( _buf_mutex );
|
|
||||||
|
|
||||||
while( _buf.empty() ) {
|
if (noutput_items <= int(_samp_avail)) {
|
||||||
_buf_cond.wait( lock );
|
for (int i = 0; i <= noutput_items; ++i)
|
||||||
}
|
*out++ = _lut[ *(buf + _buf_offset + i) ];
|
||||||
}
|
|
||||||
|
|
||||||
// convert samples to gr_complex type by using the lookup table
|
_buf_offset += noutput_items;
|
||||||
*out++ = _lut[ _buf.front() ];
|
_samp_avail -= noutput_items;
|
||||||
items_left--;
|
return noutput_items;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i <= int(_samp_avail); ++i)
|
||||||
|
*out++ = _lut[ *(buf + _buf_offset + i) ];
|
||||||
|
|
||||||
{
|
{
|
||||||
boost::mutex::scoped_lock lock( _buf_mutex );
|
boost::mutex::scoped_lock lock( _buf_mutex );
|
||||||
|
|
||||||
_buf.pop_front();
|
_buf_head = (_buf_head + 1) % _buf_num;
|
||||||
|
_buf_used--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf = _buf[_buf_head];
|
||||||
|
_buf_offset = 0;
|
||||||
|
|
||||||
|
int remaining = noutput_items - _samp_avail;
|
||||||
|
|
||||||
|
for (int i = 0; i <= remaining; ++i)
|
||||||
|
*out++ = _lut[ *(buf + _buf_offset + i) ];
|
||||||
|
|
||||||
|
_buf_offset = remaining;
|
||||||
|
|
||||||
|
_samp_avail = (BUF_SIZE/2) - remaining;
|
||||||
|
|
||||||
|
return noutput_items;
|
||||||
}
|
}
|
||||||
|
|
||||||
return noutput_items;
|
return noutput_items;
|
||||||
|
@ -213,9 +254,9 @@ osmosdr::meta_range_t rtl_source_c::get_sample_rates()
|
||||||
{
|
{
|
||||||
osmosdr::meta_range_t range;
|
osmosdr::meta_range_t range;
|
||||||
|
|
||||||
range += osmosdr::range_t( 1024000 );
|
range += osmosdr::range_t( 1024000 ); // known to work
|
||||||
range += osmosdr::range_t( 2048000 );
|
range += osmosdr::range_t( 2048000 ); // known to work
|
||||||
range += osmosdr::range_t( 3200000 );
|
range += osmosdr::range_t( 3200000 ); // max rate, may work
|
||||||
|
|
||||||
// TODO: read from the librtlsdr as soon as the api is available
|
// TODO: read from the librtlsdr as soon as the api is available
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
|
|
||||||
#include <osmosdr_api.h>
|
#include <osmosdr_api.h>
|
||||||
#include <gr_sync_block.h>
|
#include <gr_sync_block.h>
|
||||||
|
|
||||||
#include <gruel/thread.h>
|
#include <gruel/thread.h>
|
||||||
#include <boost/circular_buffer.hpp>
|
|
||||||
#include <boost/thread/mutex.hpp>
|
#include <boost/thread/mutex.hpp>
|
||||||
#include <boost/thread/condition_variable.hpp>
|
#include <boost/thread/condition_variable.hpp>
|
||||||
|
|
||||||
|
@ -117,10 +117,16 @@ private:
|
||||||
|
|
||||||
rtlsdr_dev_t *_dev;
|
rtlsdr_dev_t *_dev;
|
||||||
gruel::thread _thread;
|
gruel::thread _thread;
|
||||||
boost::circular_buffer<unsigned short> _buf;
|
unsigned short **_buf;
|
||||||
|
unsigned int _buf_num;
|
||||||
|
unsigned int _buf_head;
|
||||||
|
unsigned int _buf_used;
|
||||||
boost::mutex _buf_mutex;
|
boost::mutex _buf_mutex;
|
||||||
boost::condition_variable _buf_cond;
|
boost::condition_variable _buf_cond;
|
||||||
bool _running;
|
bool _running;
|
||||||
|
|
||||||
|
unsigned int _buf_offset;
|
||||||
|
unsigned int _samp_avail;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* INCLUDED_RTLSDR_SOURCE_C_H */
|
#endif /* INCLUDED_RTLSDR_SOURCE_C_H */
|
||||||
|
|
Loading…
Reference in New Issue