Linux

Add useful snippets of code or links to entire SDR projects.
AH6DL
Posts: 49
Joined: Sun Jun 14, 2015 7:24 am

Re: Linux

Post by AH6DL » Fri Sep 04, 2015 7:10 am

Fixing the gr-osmosdr SDRplay library is going to take some work, and I came up with a tool that should be useful in seeing if code changes actually fix anything.

Download GRC file: http://www.transmitter.com/sdrplay/sdrp ... st.grc.txt
Image

The problems are obvious when this program is run with the latest gr-osmosdr sdrplay_source_c.cc. You'll see the DC offset until the gain is changed and large spikes are obvious in the scope display.

I've made some modifications to the gr-osmosdr library. A modified sdrplay_source_c.cc is available at: http://www.transmitter.com/sdrplay/sdrp ... 0903-1.txt

This works well with my simple NBFM/AM receiver grc program (http://www.transmitter.com/sdrplay/simp ... er.grc.txt although there is a noticeable background whine on AM signals that doesn't cause NBFM signals any problems. This can be seen as increased noise on one of the channels (Q?) when viewed on the scope in the test program. The display seems to take a bit longer to settle after changing frequencies. This may be due to my deleting the data output statements in the initial buffer loading IF statement. I also was able to set tracking time for the one-shot DC removal and that could be having an impact.

The simple FM receiver has some problems and the original problems GQRX had with displaying the correct spectrum but misreading the sample rate (frequencies are off in the legend and demodulation doesn't work) are back, and I'm seeing USB buffer overflows.

I'm going to try some different values for the divisor in my modified packet sampling routine to see if that helps. I left the values where they were from a previous experiment and I think 8192 or an even higher number may work better. Please give it a try and let me know if you have any other ideas on how to fix it.

I hope to have a chance to dig deeper into this over the U.S. Labor Day holiday Monday.

73...
Doug, AH6DL
Last edited by AH6DL on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

AH6DL
Posts: 49
Joined: Sun Jun 14, 2015 7:24 am

Re: Linux

Post by AH6DL » Sun Sep 06, 2015 6:54 pm

I added some debug code to sdrplay_source_c.cc to see how the packets were being handled.

Here are the changes to the unmodified (current) sdrplay_source_c.cc:
Download: http://www.transmitter.com/sdrplay/sdrp ... -debug.txt
The modified sdrplay_source_cc::work :

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;
   int grChanged;
   int rfChanged;
   int fsChanged;

   if (_uninit)
   {
      return WORK_DONE;
   }

   if (!_running)
   {
      reinit_device();
      _running = true;
   }

   _buf_mutex.lock();

   if (_buf_offset)
   {
      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) );
      }
      cnt -= (_dev->samplesPerPacket - _buf_offset);
      std::cerr << "cnt after first IF = " << cnt << std::endl;

   }

   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 -= _dev->samplesPerPacket;
   }
   if (cnt)
   {
      _buf_offset = cnt;
   }
   std::cerr << "cnt before return = " << cnt << " noutput_items = " << noutput_items << " buffer_offset = " << _buf_offset << std::endl;
   _buf_mutex.unlock();

   return noutput_items;
}
When this code is used with my test program large spikes are visible on the output waveform and the amplitude is unstable. The console output from GQRX provides some clues as to where the problem might be. Notice the line where the buffer_offset goes negative. Is this what is causing the large spikes?

Download full log: http://www.transmitter.com/sdrplay/sdrp ... dified.txt
Sample of GQRX console output:

Code: Select all

cnt after first IF = 822
cnt before return = 66 noutput_items = 1016 buffer_offset = 66
cnt after first IF = 2886
cnt before return = 114 noutput_items = 3072 buffer_offset = 114
cnt after first IF = 3958
cnt before return = 178 noutput_items = 4096 buffer_offset = 178
cnt after first IF = -67
cnt before return = -67 noutput_items = 7 buffer_offset = -67
cnt after first IF = 698
cnt before return = 194 noutput_items = 1017 buffer_offset = 194
cnt after first IF = 4038
cnt before return = 6 noutput_items = 4096 buffer_offset = 6
cnt after first IF = 2825
cnt before return = 53 noutput_items = 3071 buffer_offset = 53
cnt after first IF = 3897
cnt before return = 117 noutput_items = 4096 buffer_offset = 117
cnt after first IF = 889
cnt before return = 133 noutput_items = 1024 buffer_offset = 133
cnt after first IF = 3977
cnt before return = 197 noutput_items = 4096 buffer_offset = 197
cnt after first IF = 3016
cnt before return = 244 noutput_items = 3071 buffer_offset = 244
cnt after first IF = 4088
cnt before return = 56 noutput_items = 4096 buffer_offset = 56
cnt after first IF = 828
cnt before return = 72 noutput_items = 1024 buffer_offset = 72
cnt after first IF = 3916
I tried some different variations and it looked the the problem was being caused by this code:

Code: Select all

   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;
   }
After much experimentation, I ended up removing it. I also increased the SDRPLAY_MAX_BUF_SIZE to 8208. Changing the buffer size didn't seem to make much difference, although a larger buffer seemed more stable than the original 504 value. With the original code, the larger buffer seemed to delay the time before the spikes started appearing in the waveform.

Download code without debug: http://www.transmitter.com/sdrplay/sdrp ... 904-22.txt
Download code with debug: http://www.transmitter.com/sdrplay/sdrp ... bug-22.txt
The modified sdrplay_source_cc::work :

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;
   int grChanged;
   int rfChanged;
   int fsChanged;

   if (_uninit)
   {
      return WORK_DONE;
   }

   if (!_running)
   {
      reinit_device();
      _running = true;
   }

   _buf_mutex.lock();

   if (_buf_offset)
   {
      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) );
      }
      cnt -= (_dev->samplesPerPacket - _buf_offset);
      std::cerr << "cnt after first IF = " << cnt << std::endl;
   }

   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 -= _dev->samplesPerPacket;
   }
   std::cerr << "cnt before return = " << cnt << " noutput_items = " << noutput_items << " buffer_offset = " << _buf_offset << std::endl;
   _buf_mutex.unlock();

   return noutput_items;
}
In the test program, with this code the spikes were gone. The console output from GQRX was also more stable. Note that with the removal of that last IF statement, the first IF statement condition is never satisfied. The buffer_offset never goes negative, always ending at "0".

Download full console output: http://www.transmitter.com/sdrplay/sdrp ... 904-22.txt
Sample of GQRX console output:

Code: Select all

cnt before return = 63 noutput_items = 4095 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 52 noutput_items = 4084 buffer_offset = 0
cnt before return = 11 noutput_items = 11 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 21 noutput_items = 2037 buffer_offset = 0
cnt before return = 32 noutput_items = 2048 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 10 noutput_items = 10 buffer_offset = 0
cnt before return = 22 noutput_items = 2038 buffer_offset = 0
cnt before return = 32 noutput_items = 2048 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 32 noutput_items = 2048 buffer_offset = 0
cnt before return = 32 noutput_items = 2048 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 32 noutput_items = 2048 buffer_offset = 0
cnt before return = 32 noutput_items = 2048 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 32 noutput_items = 2048 buffer_offset = 0
cnt before return = 24 noutput_items = 2040 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 7 noutput_items = 7 buffer_offset = 0
cnt before return = 57 noutput_items = 4089 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 63 noutput_items = 4095 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 63 noutput_items = 4095 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 63 noutput_items = 4095 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
cnt before return = 63 noutput_items = 4095 buffer_offset = 0
cnt before return = 64 noutput_items = 4096 buffer_offset = 0
While this works, the demodulator output from GQRX is distorted and the sample rate appears to vary, resulting in a "warble" on cw signals. I don't understand why this output, which is more stable that that produced by the original code, produces the warble or alias on the demodulated signal. Perhaps some data is being dropped? If someone can figure out why that's happening and come up with a fix, I think we'll have a solution!

My final attempt to remove the "warble" was to add back in the final IF statement, but leave it to "WHILE" to pull the packets from the SDRPlay. I ended up with an SDRPLAY_MAX_BUF_SIZE 4112 in this version but as noted that didn't appear to make any difference (better or worse).

Download code without debug: http://www.transmitter.com/sdrplay/sdrp ... 904-23.txt
Download code with debug: http://www.transmitter.com/sdrplay/sdrp ... 904-23.txt
The modified sdrplay_source_cc::work :

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;
   int grChanged;
   int rfChanged;
   int fsChanged;

   if (_uninit)
   {
      return WORK_DONE;
   }

   if (!_running)
   {
      reinit_device();
      _running = true;
   }

   _buf_mutex.lock();

   if (_buf_offset)
   {
      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) );
      }
      cnt -= (_dev->samplesPerPacket - _buf_offset);
      std::cerr << "cnt after first IF = " << cnt << std::endl;

   }

   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 -= _dev->samplesPerPacket;
   }
   if (cnt)
   {
      _buf_offset = cnt;
   }
   std::cerr << "cnt before return = " << cnt << " noutput_items = " << noutput_items << " buffer_offset = " << _buf_offset << std::endl;
   _buf_mutex.unlock();

   return noutput_items;
}
With this modification, the spikes returned on the scope in the test program. In GQRX there was some distortion, although not as bad as with 22. Note that in the GQRX console output, the negative buffer offset has returned, possibly indicating where the spikes are occurring.

Download full console output: http://www.transmitter.com/sdrplay/sdrp ... 904-23.txt
Sample of GQRX console output:

Code: Select all

cnt before return = 14 noutput_items = 4095 buffer_offset = 14
cnt after first IF = 3858
cnt before return = 78 noutput_items = 4096 buffer_offset = 78
cnt after first IF = 3910
cnt before return = 130 noutput_items = 4084 buffer_offset = 130
cnt after first IF = 3974
cnt before return = 194 noutput_items = 4096 buffer_offset = 194
cnt after first IF = -47
cnt before return = -47 noutput_items = 11 buffer_offset = -47
cnt after first IF = 3786
cnt before return = 6 noutput_items = 4085 buffer_offset = 6
cnt after first IF = 3850
cnt before return = 70 noutput_items = 4096 buffer_offset = 70
cnt after first IF = 3914
cnt before return = 134 noutput_items = 4096 buffer_offset = 134
cnt after first IF = 3978
cnt before return = 198 noutput_items = 4096 buffer_offset = 198
cnt after first IF = 4042
cnt before return = 10 noutput_items = 4096 buffer_offset = 10
cnt after first IF = 3854
cnt before return = 74 noutput_items = 4096 buffer_offset = 74
cnt after first IF = 3918
cnt before return = 138 noutput_items = 4096 buffer_offset = 138
cnt after first IF = 3982
cnt before return = 202 noutput_items = 4096 buffer_offset = 202
cnt after first IF = 4038
I'm not sure if these problems can be fixed using the current method reading packets in sdrplay_source_c::work. I'm hoping that there may be one change to the conditions in the IF statements or WHILE loop that will resolve the issues, but I haven't found it yet. I'm still examining the SDR-J code to see if it provides any clues. The Mirics API documentation example code isn't detailed enough to be useful, at least for me.

I hope my experiments help someone else find a way to get SDRplay working with gr-osmosdr. Once that's cracked it shouldn't be difficult to get ADSB and Meteor M2 LRPT reception working as well as making GQRX more usable for general radio reception.

Any ideas?

73...
...Doug AH6DL
Last edited by AH6DL on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

AH6DL
Posts: 49
Joined: Sun Jun 14, 2015 7:24 am

Re: Linux

Post by AH6DL » Mon Sep 07, 2015 12:45 am

After playing around a bit, I think the test-0904-22 of sdrplay_source_c.cc is the most stable. See the previous posting for details.

The major problem with it is the cyclic amplitude and frequency shift. It is occurring at a regular rate so it should be possible to eliminate it.

You can see the impact of the amplitude shift in this display from GQRX running the 0904-22 code tuned to WWV/WWVH:
Image

The frequency shift isn't obvious in the display but can be heard with the USB demodulator.

I think that what is happening is that part of I and/or Q data is being lost at some point either when it is being grabbed from the SDRplay API or output to gr-osmosdr. For example, the correct I and Q data might be 3192 and 2800 but it is being seen as 3168 and 2776. This would impact both frequency and amplitude if some bits (the 5 lowest in this example) were dropped.

If I have a chance tomorrow or later tonight, I want to see if I can set up my B200 USRP as a CW signal source to provide a stable signal to the SDRplay. Then I hope I can capture the numeric output from the SDRplay and see if I can identify what bits are being dropped and where.

Any help in tracking this down or suggestions for code changes would be appreciated!

73...
...Doug
Last edited by AH6DL on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

AH6DL
Posts: 49
Joined: Sun Jun 14, 2015 7:24 am

Re: Linux

Post by AH6DL » Mon Sep 07, 2015 5:10 pm

I tried changing the 0904-22 code and modifying the comparison in the "while" loop. I was able to reduce the remaining "cnt" close to zero but this resulted in lower frequency, but more disruptive, errors. I also tried different divisors when storing the buffers and there was either no improvement or the output was worse. Maximum buffer size was dropped back to 504 with no noticeable improvement or degradation.

As this point I've got to think the current method of getting data from the SDRplay API into gr-osmosdr is broken and a new approach is needed, perhaps dumping the data to a ring buffer as is done in some of the SDR-J programs and outputting the data to gr-osmosdr from that.

73...
...Doug AH6DL
Last edited by AH6DL on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

AH6DL
Posts: 49
Joined: Sun Jun 14, 2015 7:24 am

Re: Linux

Post by AH6DL » Tue Sep 08, 2015 6:58 am

When you keep running into dead-ends, sometimes it's best to go back to the beginning and start over.

Taking a different approach to putting a band-aid on the SDRplay gr-osmosdr code -- I say band-aid because this is not a complete solution, I decided to go back to the original code and add an "if" statement to eliminate the possibility of having a negative buffer offset. This eliminated the large spikes visible in the IQ waveforms in my test program's scope display but did not introduce a constant error that appeared as spurs on any demodulated output when using my 0904-22 modifications, as seen in the GQRX display I posted earlier.

Here is the modified sdrplay_source_c::work code (scroll down to see the added "if" before "buf_mutex.unlock()":

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;
   int grChanged;
   int rfChanged;
   int fsChanged;

   if (_uninit)
   {
      return WORK_DONE;
   }

   if (!_running)
   {
      reinit_device();
      _running = true;
   }

   _buf_mutex.lock();

   if (_buf_offset)
   {
      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) );
      }
      cnt -= (_dev->samplesPerPacket - _buf_offset);
   }

   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 -= _dev->samplesPerPacket;
   }
   _buf_offset = 0;
   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;
   }

   if (_buf_offset < 0)
   {
       _buf_offset = 0;
   }
   _buf_mutex.unlock();
 
   return noutput_items;
}
Note this is NOT a complete solution. There are still some disruptions in the output that are audible (and visible on the audio display) when listening to a single carrier in USB mode on GQRX. However, the static is gone and the amplitude, at least based on my limited testing tonight, is stable. Progress!

Download the sdrplay_source_c.cc code without the debugging output at:
http://www.transmitter.com/sdrplay/sdrp ... 907-25.txt

For those interested in removing the remaining artifacts, here is the version with the debugging output:
http://www.transmitter.com/sdrplay/sdrp ... 907-25.txt

When building gr-osmosdr from source, rename the desired file to sdrplay_source_c.cc and put it in the "gr-osmosdr/lib/sdrplay/" directory in the source code. If using Arch Linux, be sure to modify the PKGBUILD to prevent it from over-writing the modified source. That caught me more than once after upgrading the base gr-osmosdr source from git.

Let me know if this works for you!

73...
...Doug
Last edited by AH6DL on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

AH6DL
Posts: 49
Joined: Sun Jun 14, 2015 7:24 am

Re: Linux

Post by AH6DL » Wed Sep 09, 2015 6:57 am

I've got the sdrplay_source_c.cc code working quite a bit better. SSB reception works well and the output is generally stable. To ensure the buffer size wasn't an issue, I upped it to 2064 for this version. Lower values may work fine.

The latest revision is at http://www.transmitter.com/sdrplay/sdrp ... 908-31.txt

This version includes debug code but it only outputs if there is a problem. What I've found is that as the incoming packets are being processed the "if (_buf_offset)" statement leads to a situation where after the "for" loop ends, the result of "cnt -= (_dev->samplesPerPacket - _buf_offset);" goes below zero. This usually happens when most of the count has been filled in the previous pass and "cnt" is already at a relatively low value.

By adding a condition that "cnt > 160" to the first if statement, I was able to greatly reduce the number times the cnt went below zero. A higher value may work better. I will investigate that later. I haven't seen this modification introduce any additional noise in the output, unlike some of my earlier experiments.

Here is the code for sdrplay_source_c::work:

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;
   int grChanged;
   int rfChanged;
   int fsChanged;

   if (_uninit)
   {
      return WORK_DONE;
   }

   if (!_running)
   {
      reinit_device();
      _running = true;
   }

   _buf_mutex.lock();

   if (_buf_offset && (cnt > 160)  )
   {
      for (int i = _buf_offset; (i < _dev->samplesPerPacket) && (_buf_offset > 0); i++)
      {
         *out++ = gr_complex( float(_bufi[i]) * (1.0f/2048.0f), float(_bufq[i]) * (1.0f/2048.0f) );
      }
      cnt -= (_dev->samplesPerPacket - _buf_offset);
      if (cnt < 0)
      {    
         std::cerr << "cnt at if (_buf_offset) = " << cnt << " _buf_offset = " << _buf_offset << " samplesPerPacket = " << _dev->samplesPerPacket << std::endl;
      }

   }

   while ((cnt - _dev->samplesPerPacket) >= 0)
   {
      mir_sdr_ReadPacket(_bufi.data(), _bufq.data(), &sampNum, &grChanged, &rfChanged, &fsChanged);
      for (int i = 0; (i < _dev->samplesPerPacket) && (_buf_offset > 0); i++)
      {
         *out++ = gr_complex( float(_bufi[i]) * (1.0f/2048.0f), float(_bufq[i]) * (1.0f/2048.0f) );
      }
      cnt -= _dev->samplesPerPacket;
      if (cnt < 0)
      {    
         std::cerr << "cnt at while = " << cnt << std::endl;
      }
   }
   _buf_offset = 0;

   if (cnt)
   {
      mir_sdr_ReadPacket(_bufi.data(), _bufq.data(), &sampNum, &grChanged, &rfChanged, &fsChanged);
      for (int i = 0; (i < cnt) && (cnt > 0); i++)
      {
         *out++ = gr_complex( float(_bufi[i]) * (1.0f/2048.0f), float(_bufq[i]) * (1.0f/2048.0f) );
      }
      if (cnt < 0)
      {    
         std::cerr << "cnt at if (cnt) = " << cnt << std::endl;
      }
      _buf_offset = cnt;
   }

   if (_buf_offset < 0)
   {
       std::cerr << "_buff_offset at last if " << _buf_offset << std::endl;    
       _buf_offset = _buf_offset;
   }
   
   _buf_mutex.unlock();
 
   return noutput_items;
}
I left some of the debug output in this code because if everything is working well, you shouldn't see it! Note that I'm no longer forcing the _buf_offset to zero. Once I'm happy with how the code is working the last "if" statement will be removed.

I'd appreciate comments from anyone able to test this code on their setup. If you are having trouble with it, let me know.

73...
...Doug
Last edited by AH6DL on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

AH6DL
Posts: 49
Joined: Sun Jun 14, 2015 7:24 am

Re: Linux

Post by AH6DL » Thu Sep 10, 2015 7:12 am

Another day, another problem. Additional testing with the code in the previous email showed that packets were being dropped. This resulted in T8 CW reception, no noticeable problems with SSB and AM reception, but patterned noise in a NOAA 15 APT recording made on a pass this afternoon. The lost packets were clearly visible in the GQRX waterfall display.

Going back to a previous version I tested last night, I determined that having the _buf_offset go below zero wasn't an issue unless it was negative by more the total number of packets per sample. I removed the changes to the first "if" statement and retested. No spikes were visible in the test program and CW signals became T9. USB reception was good -- I picked up a ham in Ireland on 20 meters tonight from my QTH in Hawaii using the SDRplay, GQRX and a discone antenna.

I still think a better method of transferring data from the SDRplay to gr-osmosdr is needed. I'm not 100% sure that at least some packets are not being lost with tonight's code. I've been fooled before when modifications that worked one night failed the following night. I'm still seeing fluctuation in the band-band output that could simply be SW propagation or something worse like corrupted data. Once I get my SDR transmitter signal generator test setup configured I should be able to tell if there are any misread packets by looking at the demodulated base-band audio.

Download the latest modified version at: http://www.transmitter.com/sdrplay/sdrp ... 909-33.txt

Note that I kept the SDRPLAY_MAX_BUF_SIZE at 2064. same as last night's test code.

Here is the modified sdrplay_source_c::work code. Note that the main change is adding a condition that before the data is processed, the _buf_offset must be greater than zero.

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;
   int grChanged;
   int rfChanged;
   int fsChanged;

   if (_uninit)
   {
      return WORK_DONE;
   }

   if (!_running)
   {
      reinit_device();
      _running = true;
   }

   _buf_mutex.lock();

   if (_buf_offset)
   {
      for (int i = _buf_offset; (i < _dev->samplesPerPacket) && (_buf_offset > 0); i++)
      {
         *out++ = gr_complex( float(_bufi[i]) * (1.0f/2048.0f), float(_bufq[i]) * (1.0f/2048.0f) );
      }
      cnt -= (_dev->samplesPerPacket - _buf_offset);

   }

   while ((cnt - _dev->samplesPerPacket) >= 0)
   {
      mir_sdr_ReadPacket(_bufi.data(), _bufq.data(), &sampNum, &grChanged, &rfChanged, &fsChanged);
      for (int i = 0; (i < _dev->samplesPerPacket) && (_buf_offset > 0); i++)
      {
         *out++ = gr_complex( float(_bufi[i]) * (1.0f/2048.0f), float(_bufq[i]) * (1.0f/2048.0f) );
      }
      cnt -= _dev->samplesPerPacket;
   }
   _buf_offset = 0;

   if (cnt)
   {
      mir_sdr_ReadPacket(_bufi.data(), _bufq.data(), &sampNum, &grChanged, &rfChanged, &fsChanged);
      for (int i = 0; (i < cnt) && (cnt > 0); i++)
      {
         *out++ = gr_complex( float(_bufi[i]) * (1.0f/2048.0f), float(_bufq[i]) * (1.0f/2048.0f) );
      }
      _buf_offset = cnt;
   }
   
   _buf_mutex.unlock();
 
   return noutput_items;
}
If anyone reading this is up to compiling their own gr-osmosdr code, I'd appreciate it if someone could test this revision and let me know how it works for them. Note that if testing with GQRX, I had problems with the default.conf getting corrupted. Save a working copying to another file in case this happens to you. I've also seen some cases where I and Q are reversed on start-up, mostly in GNUradio applications. Making a huge gain change (high gain to low gain and back) or, worst case, restarting the prgram should fix it. If things are really screwed up it might be necessary to unplug and replug the USB cable from the SDRplay.

Let me know how this works for you!

73...
...Doug AH6DL
Last edited by AH6DL on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

amish
Posts: 6
Joined: Wed Sep 02, 2015 6:17 am

Re: Linux

Post by amish » Fri Sep 11, 2015 11:45 am

Hi Doug,

I got some time today to compile and test your code. Though could not test for long but the jitter has reduced although the AM stations showed fluctuations.Please find the attached image.

I will hopefully get some time tomorrow to do look into the changes. Thanks for your efforts
Last edited by amish on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason
73
VU2AIE

AH6DL
Posts: 49
Joined: Sun Jun 14, 2015 7:24 am

Re: Linux

Post by AH6DL » Fri Sep 11, 2015 3:24 pm

@Amish - Thanks for testing it. Last night i configured my B200 as a 440 MHz signal generator and did some more testing of the original and modified code. As I suspected, even the latest code is dropping or corrupting packets, just different ones.

Comparing the baseband output from my Airspy and the SDRplay is like day and night. With GQRX, using Airspy, the 440 MHz signal shows up as a single beat note in the baseband (audio) spectrum display with a flat baseline > 30 dB down in USB/LSB mode. Switching to SDRplay, the base-band noise floor is much higher, showing up as a hump around the main audio or as spurious peaks (like an alias or intermod) 20 dB or less below the beat note.

With the modified code, this noise is lower in amplitude but less random than with the unmodified code. The noise makes digital reception difficult, although with the -33 code was I was to decode a N19 pass and create an image (unlike with the earlier versions). However, the patterned noise was visible in it. I'm using Arch Linux and have created multiple gr-osmosdr packages so I can easily switch between different versions for comparison.

Now that i have a test generator setup and can do repeatable testing I may try a few more tweaks to the existing gr-osmosdr SDRplay library. That code, using two IF statements, a WHILE loop, and multiple FOR loops to handle moving data from the SDRplay to gr-osmosdr is the problem. There are too many places for packets to be lost or corrupted. With the debug code I can see the program returning a run of 4095 or 4096 samples and then try to deal with a remaining 3 or 5 samples. Unfortunately now I see all of my modifications simply group or move the errors to different spots. None of them solves the base problem.

SDR-J uses a completely different approach but the process is so different it would probably take a complete rewrite of the SDRplay code. It seems to me there has to be simpler way to do this!

73...
...Doug AH6DL
Last edited by AH6DL on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

AH6DL
Posts: 49
Joined: Sun Jun 14, 2015 7:24 am

Re: Linux

Post by AH6DL » Sun Sep 13, 2015 1:27 am

I modified my gnuradio-companion test program to show AM demodulated base-band output, both as a scope display and an FFT frequency display. This made it a bit easier to track problems.
The modified code is available here: http://www.transmitter.com/sdrplay/sdrp ... -2.grc.txt

Here are the results from some different versions of the sdrplay_source_c.cc code.

Unmodified code - notice the large spikes in the I/Q scope plot
Image

Modified code from test-0909-33 - notice the lack of large spikes but significant base-band noise around the audio tone
Image

And, for comparison, the same program, same sample rate, using an Airspy SDR and the gr-osmosdr Airspy library:
Image

As I feared, my modifications weren't fixing anything, just moving the errors to different spots.

I added several lines of debug output to the original sdrplay_source_c.cc code.
Download it here http://www.transmitter.com/sdrplay/sdrp ... 911-34.txt

Using the SampNum to track what was happening to the packets, I could see where the code was messing up. It appears to be in the if (_buf_offset) statement. You can see this in my analysis of the debug output in this gnumeric screenshot:
Image

I can now see what's going, but changing the comparisons in the if (_buf_offset) statement and associated for loop did not resolve the problem. I could eliminate the first three missing packets but that caused problems with later packets.

Comparing the Airspy "work" code and the SDRplay "work" code, I think I can use the same FIFO technique in the SDRplay code that Airspy is using their gr-osmosdr library. This will require modification of the include file (sdrplay_source_c.h. If it works, it will provide a much simpler solution than the the current code. However, if anyone has a eureka moment looking the the analysis and the current sdrplay_source_c.cc code, let me know and I'll give it a try.

I'm hoping to wrap this up soon!

73...
...Doug AH6DL
Last edited by AH6DL on Thu Jan 01, 1970 12:00 am, edited 0 times in total.
Reason: No reason

Post Reply