Re: Linux - Working!!
Posted: Sun Sep 20, 2015 8:00 am
After much testing using the debug code in my previous post, I think I now have a version of the gr-osmosdr library sdrplay_source_c_cc that will work as well as it can without major code modification such as using a FIFO buffer to allow fixed output packet size. I'm not seeing any dropped packets, the static is gone, and the baseband display is stable.
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:
Download the complete source code from:
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
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