SatNOGS client V2.x / SoapyRTLSDR: setting Freq Correction (PPM)

This was only when the SDR was in use by an observation running (understandably).

I found in Setting.cpp (SoapyRTLSDR) that parameter ‘corr’ should be as capital letters and value should be float:

if (name == "CORR")
{
    ppm = (int) frequency;
    rtlsdr_set_freq_correction(dev, ppm);
}

Yet another problem in source_impl.cc (gr-soapy)- incorrect support setFrequencyCorrection. ‘Frequency API’ SoapyRTLSDR::SetFrequency (Settings.cpp/SoapyRTLSDR) always get value ‘CORR’ 0ppm. The value ‘CORR’ is taken as Frequency Correction, not from ’ SATNOGS_DEV_ARGS', I believe.

Thanks @uy0ll for digging into this. Maybe this helps in finding the proper way to re-implement the frequency correction feature within the new gr-soapy-based satnogs client code.

I followed your hints and would like to add some remarks.

I don’t see an error within in gr-soapy here: The function source_impl::set_frequency_correction is a wrapper around {SoapyRTLSDR|Device}::setFrequencyCorrection and should work correctly when called. Unfortunately I don’t think it’s called with a non-zero value by the flowgraphs currently. The flowgraph template for the gr-soapy source block is calling it at soapy_source.block.yml#L371-373 using the correction0 parameter, but this parameter is always zero in all satnogs-flowgraphs (e.g. iq_receiver.grc#L402-403).


The config variable SATNOGS_DEV_ARGS is deprecated and has no effect in the new gr-soapy-based satnogs client software stack, but unfortunately wasn’t removed from satnogs-client yet. I just opened issue satnogs-client#373 to fix this. (edit 2020-03-10T20:40: SATNOGS_DEV_ARGS got a new meaning with gr-soapy, see gr-soapy#64 (comment 301344183) for its effects in gr-soapy v2.0 and earlier). It can be easily confused with the new SATNOGS_SOAPY_RX_DEVICE which serves a similar purpose now.


Sry, I think the if (name == "CORR") condition can’t be met within any SatNOGS station with latest software atm. Reason:
This code is part of SoapyRTLSDR::setFrequency,
it gets called only once by gr-soapy in
source_impl::set_frequency(size_t channel, const std::string &name, double frequency),
but in turn this gr-soapy function gets never called. And the simpler
source_impl::set_frequency(size_t channel, double frequency) is used
instead.


tl;dr: I can’t see the possibility to configure any frequency correction without modifying the flowgraphs in the latest satnogs client software stack. But it would be possible to re-implement this (lost) feature.

2 Likes

Please use the issue tracker of gr-soapy, cause there is heavy development on it to support the separate gains of each device and many things are subjected to changes.

Indeed I somehow missed issue gr-soapy#64 highly related to this topic.

1 Like

Has there been any progress on this? Is there an issue raised to cover it?

Setting a frequency correction value is something that’s pretty critical to a lot of stations. Kind of like being able to set gain properly on devices with more than one gain control knob (though I believe this has been fixed?)

2 Likes

I checked all possible options for device specific arguments in gr-soapy 2.0 explained in gr-soapy#64 (comment 301344183) mentioned previously, and by reviewing the respective code in gr-soapy, SoapyRTLSDR and SoapySDR I can conclude that the device arguments do not support any “corr/CORR” argument when using an rtl-sdr, and the set_freqeuncy_correction API is used with a hard-coded zero value by all flowgraphs as described in my previous long post.

Whether this has been fixed already I will try to answer in a future post.


It’s being worked on. In the gr-soapy master branch the device, stream & channel settings API was redesigned by @surligas (gr-soapy!116 (merged)) and satnogs-flowgraphs was updated to support this new API (satnogs-flowgraphs!11 (merged)). Exposing the new device/stream/channel/tune settings through satnogs-client, satnogs-config & satnogs-client-ansible is a ToDo (satnogs-client#374, satnogs-client-ansible#72 & satnogs-config#19).
Once those issues are resolved, setting the gain properly should be possible with the full granularity offered by SoapySDR (given there are no bugs in the device-specific soapy modules).

The missing frequency correction support is not fixed yet, but tracked in satnogs-flowgraphs#7 now.

The progress / explanation:

Frequency Correction in Soapy[RTL]SDR

Some confusion about this fact was caused by the SoapySDR wiki page showing the device argument corr until today (archive):

Freq Correction [corr]: Default 0 (parts per million)

In fact, this device argument was removed before the first release of SoapyRTLSDR in SoapyRTLSDR@6bfc9a9, but remained in the wiki until I updated the wiki page today.

Frequency Correction in gr-soapy

gr-soapy is supporting the Soapy Frontend Corrections API correctly since it’s first release (see gr-soapy@v1.0.1:/lib/source_impl.h#L198-203).

Frequency Correction in satnogs-flowgraphs

satnogs-flowgraphs is using a hardcoded correction value of zero as described in an earlier post in this thread. This bug is tracked in satnogs-flowgraphs#7.

Everything were installed latest from git, unfortunately still no effect: https://network.satnogs.org/observations/1913449/

Are you sure about that?

Looking at some of your other observations, it looks OK.

For example:
https://network.satnogs.org/observations/1915217/ - GOMX-1 looks fairly well centred
https://network.satnogs.org/observations/1915082/

I also see you are running a fork of gr-satnogs?

1 Like

I use gr-satnogs supplemented by the direwolf_agc for the better reception AFSK1200 and also have to use the PPM value set manually in Settings.cpp (Soapy RTL SDR):

void SoapyRTLSDR::setFrequency(
const int direction,
const size_t channel,
const std::string &name,
const double frequency,
const SoapySDR::Kwargs &args)
{
if (name == “RF”)
{
centerFrequency = (uint32_t) frequency;
resetBuffer = true;
rtlsdr_set_center_freq(dev, centerFrequency);
}

if (name == "CORR")
{
SoapySDR_logf(SOAPY_SDR_WARNING, "SoapyRTLSDR::setFrequency: get \"CORR\"= '%f'", frequency);
    ppm = (int) frequency;
   ppm = 60;
 SoapySDR_logf(SOAPY_SDR_WARNING, "SoapyRTLSDR:setFrequency: set manually PPM= '%d'", ppm);
    rtlsdr_set_freq_correction(dev, ppm);
}

Here is how it works:

Mar 25 05:23:17 SatNOGS satnogs-client[7310]: satnogsclient.scheduler.tasks - WARNING - Script: satnogs_strand1_decoder.py
Mar 25 05:23:23 SatNOGS satnogs-client[7310]: Found Rafael Micro R820T tuner
Mar 25 05:23:23 SatNOGS satnogs-client[7310]: Found Rafael Micro R820T tuner
Mar 25 05:23:24 SatNOGS satnogs-client[7310]: [R82XX] PLL not locked!
Mar 25 05:23:24 SatNOGS satnogs-client[7310]: [INFO] Using format CF32.
Mar 25 05:23:24 SatNOGS satnogs-client[7310]: [WARNING] SoapyRTLSDR::setFrequency: get “CORR”= ‘0.000000’
Mar 25 05:23:24 SatNOGS satnogs-client[7310]: [WARNING] SoapyRTLSDR:setFrequency: set manually PPM= ‘60’

Well I guess the point there is… if you are using your own fork of gr-satnogs, how are you expecting to be able to test the new PPM correction setting?

I did not make any changes to the source code of any of their gr-satnogs modules. A separate an out-of-tree module direwolf_agc was added to the library, which is included only in the unique flowgraph satnogs_afsk1200.grc (example above is for STRAND-1).

The problem is obviously in the Device.cpp (SoapySDR):

this->setFrequency(direction, channel, “CORR”, value);

but appropriate API is empty:

void SoapySDR::Device::setFrequency(const int, const size_t, const std::string &, const double, const Kwargs &)
{
return;
}

It is not clear how the PPM parameter can be passed to SoapyRTLSDR.

Paging @surligas I guess…

The PPM parameter is set inside the SoapyRTLSDR implementation of setFrequency:

SoapyRTLSDR never get non-zero PPM parameter (see above) :

double value = 60.0;
this->setFrequency(dir, chan, “CORR”, value);

P.S. It turns out that the reason for the incorrect setting PPM is that at the start of the source_impl.cc (gr-soapy), the PPM value is always set 0, and other PPM values ​​take effect only when the PPM parameter is changed (see test “soapy-ppm.grc” video) .

It was possible to solve the problem by changing the order of the initial soapy commands (as it was earlier in Gnuradio v3.7) that were generated in the Python code.

Code generated by GRCC:

    # Setup Frequency correction. If set to 0 internally the source block
    # will handle the case if no frequency correction is supported
    self.soapy_source_0_0.set_frequency_correction(0,ppm)
    self.soapy_source_0_0.set_agc(0,False)
    self.soapy_source_0_0.set_frequency(0,"BB",bb_freq)
    self.soapy_source_0_0.set_frequency(0, rx_freq - lo_offset)
    self.soapy_source_0_0.set_antenna(0,antenna)

The correct order of commands:

    self.soapy_source_0_0.set_frequency(0, rx_freq - lo_offset)
    self.soapy_source_0_0.set_frequency(0,"BB",bb_freq)
    self.soapy_source_0_0.set_agc(0,False)
    self.soapy_source_0_0.set_antenna(0,antenna)
    # Setup Frequency correction. If set to 0 internally the source block
    # will handle the case if no frequency correction is supported
    self.soapy_source_0_0.set_frequency_correction(0,ppm)

Is it possible to ensure the correct sequence of the generated Python code for Gnuradio v3.8?

I made changes to the gr-soapy_source.block.yml (gr-soapy) file - the following code:

    # Setup Frequency correction. If set to 0 internally the source block
    # will handle the case if no frequency correction is supported 
    self.${id}.set_frequency_correction(0,${correction0})
    % if context.get('nchan')() > 1:
    self.${id}.set_frequency_correction(1,${correction1})
    % endif

moved to a new place following the text:

       % if context.get('devname')() in ['bladerf']:
        self.${id}.set_gain(0,"rxvga1", ${rxvga1_gain})
        self.${id}.set_gain(0,"rxvga2", ${rxvga2_gain})
        % endif
    % endif

Thanks to changes in gr-soapy, there are no problems now.

If this really is an issue, can you please raise an issue at: https://gitlab.com/librespacefoundation/gr-soapy/-/issues

Done