Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

read with RTLSDR sometimes returns TIMEOUT or OVERFLOW #13

Closed
mbaz opened this issue Sep 3, 2021 · 6 comments
Closed

read with RTLSDR sometimes returns TIMEOUT or OVERFLOW #13

mbaz opened this issue Sep 3, 2021 · 6 comments

Comments

@mbaz
Copy link

mbaz commented Sep 3, 2021

julia> SoapySDR.activate!(stream)

Allocating 15 zero-copy buffers
julia> x = Base.read(stream, 1000);
ERROR: TIMEOUT
Stacktrace:
 [1] SoapySDRDevice_readStream(device::SoapySDR.Device, stream::SoapySDR.Stream{ComplexF32}, buffs::Base.RefValue{Tuple{Ptr{ComplexF32}}}, numElems::Int64, timeoutUs::Float64)
   @ SoapySDR ~/.julia/packages/SoapySDR/ElzKN/src/lowlevel/Device.jl:493
 [2] #_read!#15
   @ ~/.julia/packages/SoapySDR/ElzKN/src/highlevel.jl:517 [inlined]
 [3] _read!(s::SoapySDR.Stream{ComplexF32}, buffers::Tuple{Vector{ComplexF32}})
   @ SoapySDR ~/.julia/packages/SoapySDR/ElzKN/src/highlevel.jl:513
 [4] read(s::SoapySDR.Stream{ComplexF32}, n::Int64; kwargs::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ SoapySDR ~/.julia/packages/SoapySDR/ElzKN/src/highlevel.jl:535
 [5] read(s::SoapySDR.Stream{ComplexF32}, n::Int64)
   @ SoapySDR ~/.julia/packages/SoapySDR/ElzKN/src/highlevel.jl:534
 [6] top-level scope
   @ REPL[7]:1

This seems to happen a few times (from 1 to maybe 10) after activate!() is called. Once read succeeds, it never seems to fail again.

@sjkelly
Copy link
Collaborator

sjkelly commented Sep 4, 2021

Some other notes. This is fine looping for several minutes:

julia> using SoapySDR, SoapyRTLSDR_jll
julia> channel = Devices()[1].rx[1]
julia> stream = SoapySDR.Stream(ComplexF32, [channel])
julia> SoapySDR.activate!(stream)
Allocating 15 zero-copy buffers
julia> n = Int64(SoapySDR.SoapySDRDevice_getStreamMTU(stream.d, stream))
131072
julia> while true; Base.read(stream, n); end

But this fails almost immediately:

julia> while true; Base.read(stream, 1000); end
OERROR: OVERFLOW
Stacktrace:
 [1] SoapySDRDevice_readStream(device::SoapySDR.Device, stream::SoapySDR.Stream{ComplexF32}, buffs::Base.RefValue{Tuple{Ptr{ComplexF32}}}, numElems::Int64, timeoutUs::Float64)
   @ SoapySDR ~/.julia/dev/SoapySDR/src/lowlevel/Device.jl:493
 [2] #_read!#15
   @ ~/.julia/dev/SoapySDR/src/highlevel.jl:517 [inlined]
 [3] _read!(s::SoapySDR.Stream{ComplexF32}, buffers::Tuple{Vector{ComplexF32}})
   @ SoapySDR ~/.julia/dev/SoapySDR/src/highlevel.jl:513
 [4] read(s::SoapySDR.Stream{ComplexF32}, n::Int64; kwargs::Base.Iterators.Pairs{Union{}, Union{}, Tuple{}, NamedTuple{(), Tuple{}}})
   @ SoapySDR ~/.julia/dev/SoapySDR/src/highlevel.jl:535
 [5] read(s::SoapySDR.Stream{ComplexF32}, n::Int64)
   @ SoapySDR ~/.julia/dev/SoapySDR/src/highlevel.jl:534
 [6] top-level scope
   @ ./REPL[7]:1


@sjkelly
Copy link
Collaborator

sjkelly commented Sep 5, 2021

Okay so some further investigation. I think this is actually expected behavior. The stream is buffered in the SoapySDR layer, and read by us. If we don't read fast enough, it will throw the buffer overflow error. Wrapping in SoapySDR.activate! and SoapySDR.deactivate! calls fixes this issue, like so:

SoapySDR.activate!(stream); read(stream, 1000); SoapySDR.deactivate!(stream)

This should be documented and explained, so I will leave this open for further discussion and ideation.

@mbaz
Copy link
Author

mbaz commented Sep 6, 2021

Related: pothosware/SoapyAirspy#10 (comment)

It seems that the ideal number of samples to request is sdr.getStreamMTU(readStream) . Is that function wrapped in SoapySDR.jll? I couldn't find it.

@sjkelly
Copy link
Collaborator

sjkelly commented Sep 6, 2021

It is not handled at the highlevel API yet, but the following should work:

julia> stream = SoapySDR.Stream(ComplexF32, [channel])
julia> SoapySDR.activate!(stream)
julia> n = Int64(SoapySDR.SoapySDRDevice_getStreamMTU(stream.d, stream))

I think a reasonable solution here will be to use readavailable to implicitly read the MTU amount.
I really appreciate the testing and bug reports. I should be able to get the High Level API modified and documented in the next couple days to avoid these issues.

@sjkelly
Copy link
Collaborator

sjkelly commented Sep 7, 2021

FYI with #18 this becomes simply:

julia> stream = SoapySDR.Stream([channel])
julia> SoapySDR.activate!(stream)
julia> samples = read(stream)

So the MTU is now baked-in and a stream type is no longer needed, we use the native format supported by the device (multiple dispatch FTW!).

@sjkelly sjkelly mentioned this issue Sep 12, 2021
@sjkelly
Copy link
Collaborator

sjkelly commented Sep 14, 2021

With #22 these error should not occur. Please comment and reopen if otherwise.

@sjkelly sjkelly closed this as completed Sep 14, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants