gr-dvbs2rx icon indicating copy to clipboard operation
gr-dvbs2rx copied to clipboard

the plutosdr integer check is errorneous

Open wucke13 opened this issue 3 months ago • 0 comments

Problem

Passing 2e5 as sampling rate does not convert the float to an int, thus failing to initialize the plutosdr source:

$ dvbs2-rx --samp-rate 2e5 --source plutosdr --plutosdr-addr 192.168.2.1 
log :info: Starting DVB-S2 Rx 
Traceback (most recent call last): 
  File "/nix/store/ndymc3sszvcnsps8p1skmj7ww88izg17-gr-dvbs2rx-1.4.0/bin/.dvbs2-rx-wrapped", line 1631, in <module> 
    main() 
  File "/nix/store/ndymc3sszvcnsps8p1skmj7ww88izg17-gr-dvbs2rx-1.4.0/bin/.dvbs2-rx-wrapped", line 1587, in main 
    tb = DVBS2RxTopBlock(options) 
         ^^^^^^^^^^^^^^^^^^^^^^^^ 
  File "/nix/store/ndymc3sszvcnsps8p1skmj7ww88izg17-gr-dvbs2rx-1.4.0/bin/.dvbs2-rx-wrapped", line 156, in __init__ 
    source_block = self.connect_source() 
                   ^^^^^^^^^^^^^^^^^^^^^ 
  File "/nix/store/ndymc3sszvcnsps8p1skmj7ww88izg17-gr-dvbs2rx-1.4.0/bin/.dvbs2-rx-wrapped", line 755, in connect_source 
    source = self.setup_plutosdr_source() 
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
  File "/nix/store/ndymc3sszvcnsps8p1skmj7ww88izg17-gr-dvbs2rx-1.4.0/bin/.dvbs2-rx-wrapped", line 665, in setup_plutosdr_source 
    iio_pluto_source.set_samplerate(self.samp_rate) 
TypeError: set_samplerate(): incompatible function arguments. The following argument types are supported: 
    1. (self: gnuradio.iio.iio_python.fmcomms2_source_fc32, samplerate: int) -> None 

Invoked with: <gnuradio.iio.iio_python.fmcomms2_source_fc32 object at 0x7f1abfe218f0>, 200000.0

However, using an actual floating point value as sampling rate does trigger the plutosdr float to integer magic:

$ dvbs2-rx --samp-rate 200000.5 --source plutosdr --plutosdr-addr 192.168.2.1 
log :info: Starting DVB-S2 Rx 
log :warning: An integer sample rate is required by the PlutoSDR. Setting rate to 200000 samples/sec. 
log :warning: The OOT symbol synchronizer requires an even integer sps >= 2 (current sps=0.2000005) 
log :info: Switching to the in-tree symbol synchronizer 
Traceback (most recent call last): 
  File "/nix/store/ndymc3sszvcnsps8p1skmj7ww88izg17-gr-dvbs2rx-1.4.0/bin/.dvbs2-rx-wrapped", line 1631, in <module> 
    main() 
  File "/nix/store/ndymc3sszvcnsps8p1skmj7ww88izg17-gr-dvbs2rx-1.4.0/bin/.dvbs2-rx-wrapped", line 1587, in main 
    tb = DVBS2RxTopBlock(options) 
         ^^^^^^^^^^^^^^^^^^^^^^^^ 
  File "/nix/store/ndymc3sszvcnsps8p1skmj7ww88izg17-gr-dvbs2rx-1.4.0/bin/.dvbs2-rx-wrapped", line 160, in __init__ 
    self.connect_dvbs2rx(source_block, sink_block) 
  File "/nix/store/ndymc3sszvcnsps8p1skmj7ww88izg17-gr-dvbs2rx-1.4.0/bin/.dvbs2-rx-wrapped", line 912, in connect_dvbs2rx 
    symbol_sync = digital.symbol_sync_cc( 
                  ^^^^^^^^^^^^^^^^^^^^^^^ 
IndexError: nominal samples per symbol must be > 1

(Ignore the following crash, this is likely related to having a weird sampling rate)

Cause

The reason for this is an error in the business logic. The conditional responsible for the conversion

https://github.com/igorauad/gr-dvbs2rx/blob/c22b350912f31d87e397ef3ff470ac81cef943e0/apps/dvbs2-rx#L146

uses pythons float.is_integer() method to check, if the sampling rate is already and integer value, and only converts if it is not integer. However, aforementioned function does not check the value type, but rather if the float has no digits other than 0 behind the decimal:

Return True if the float instance is finite with integral value, and False otherwise:

Therefore, the float 2e5 will not be converted to an integer type, because it already is re-presentable as an integer type (having no relevant decimal digits). However, the plutosdr checks the actual data type to be int.

Solutions

Solution one: fix conditional to check value type

Actually check the type: http://docs.python.org/library/functions.html#isinstance

if self.source == 'plutosdr' and isinstance(self.samp_rate, float):
    # ...

Solution two: just omit the type check

Let's be real; converting one float to an integer when running on the plutosdr is not such a costly operation that one should make it conditional/on demand. Doing such micro-optimizations is prone to introduce bugs, like, it just did! So ditch the secondary check, always convert to int if running on plutosdr:

if self.source == 'plutosdr':
    # ...

Thanks

Thanks to @C4H6O6U for helping me discover and understand this bug!

wucke13 avatar Mar 10 '24 13:03 wucke13