I'm still "hearing" (they aren't visible on the display) a few minor fluctuations in a test signal on GQRX that I think is due to variable packet size. Normal packets contain 4096 samples. However, output packets smaller than the sample packet size occur regularly, with a few under 10 samples. This must be having some impact on the receiver's processing. A FIFO buffer would eliminate this variance. I'm working on it, but it has turned out to be much more difficult than I originally thought to integrate with the existing sdrplay source code as the I and Q signals need to be combined in the FIFO when read from the SDRplay and then separated again on output to the receiver.
As I suspected, the main problem was in the if (_buf_offset) code. The original code couldn't handle cases where the requested number of samples was less than one packet (varies with sample rate -- usually 336 samples) from the sdrplay. My code resolves the problem in a somewhat inelegant fashion, with another "if", but it works. I also added a test at the end of sdrplay_source_c::work to flag any errors.
Here is the modified sdrplay_source_c::work code:
Code: Select all
int sdrplay_source_c::work( int noutput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items )
{
gr_complex *out = (gr_complex *)output_items[0];
int cnt = noutput_items;
unsigned int sampNum;
unsigned int sampNumStart;
int grChanged;
int rfChanged;
int fsChanged;
if (_uninit)
{
return WORK_DONE;
}
if (!_running)
{
reinit_device();
_running = true;
}
_buf_mutex.lock();
sampNumStart = sampNum;
int first_offset = _buf_offset;
if (_buf_offset > 0)
{
for (int i = _buf_offset; i < _dev->samplesPerPacket; i++)
{
*out++ = gr_complex( float(_bufi[i]) * (1.0f/2048.0f), float(_bufq[i]) * (1.0f/2048.0f) );
}
if (cnt > ( _dev ->samplesPerPacket - _buf_offset ))
{
cnt = cnt - (_dev->samplesPerPacket - _buf_offset);
}
else
{
_buf_offset = _buf_offset + cnt;
cnt = 0;
}
}
while ((cnt - _dev->samplesPerPacket) > 0)
{
mir_sdr_ReadPacket(_bufi.data(), _bufq.data(), &sampNum, &grChanged, &rfChanged, &fsChanged);
for (int i = 0; i < _dev->samplesPerPacket; i++)
{
*out++ = gr_complex( float(_bufi[i]) * (1.0f/2048.0f), float(_bufq[i]) * (1.0f/2048.0f) );
}
cnt = cnt - _dev->samplesPerPacket;
}
if (cnt)
{
mir_sdr_ReadPacket(_bufi.data(), _bufq.data(), &sampNum, &grChanged, &rfChanged, &fsChanged);
for (int i = 0; i < cnt; i++)
{
*out++ = gr_complex( float(_bufi[i]) * (1.0f/2048.0f), float(_bufq[i]) * (1.0f/2048.0f) );
}
_buf_offset = cnt;
}
int items = sampNum - sampNumStart;
if ( (items + _dev->samplesPerPacket - first_offset - noutput_items) != (_dev->samplesPerPacket - _buf_offset))
{
std::cerr << "Sampling Error! " << "cnt before return = " << cnt << " noutput_items = " << noutput_items << " first_offset = " << first_offset << " buffer_offset = " << _buf_offset << " Items = " << items << " SpP - _buf_offset = " << _dev->samplesPerPacket - _buf_offset << std::endl;
}
_buf_mutex.unlock();
return noutput_items;
}
http://www.transmitter.com/sdrplay/sdrp ... 919-49.txt
I just got this working this evening and will do more testing over the next few days. I've been fooled before into thinking I had a solution but it in reality I'd just moved the problem to a spot where I wasn't looking. With extensive debug code and the gnuradio-companion test receiver, a steady signal source from my Ettus B200, and spot checks with GQRX I feel more confident in this version. Please compile it and let me know you experience with it. I'd be especially interested in hearing from anyone building this on OS-X -- it should solve the gr-osmosdr problems there as well.
73....
....Doug AH6DL