Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/SoapySDR.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ include("device/channel.jl")
include("device/stream.jl")
include("device/sensor.jl")
include("device/time.jl")
include("device/settings.jl")

# helpers
include("typemap.jl")
include("unithelpers.jl")
include("wrappers.jl") # TODO: get rid of this

# high-level functionality
include("components.jl")
Expand Down
63 changes: 36 additions & 27 deletions src/components.jl
Original file line number Diff line number Diff line change
Expand Up @@ -58,32 +58,38 @@ for (e, f) in zip(
),
)
@eval begin
$f(channel::Channel) = $f(channel.device, channel.direction, channel.idx)
$(Symbol(string(e, "List")))(channel::Channel) =
ComponentList{$e}(StringList($f(channel)...))
function $(Symbol(string(e, "List")))(channel::Channel)
len = Ref{Csize_t}()
ptr = $f(channel.device, channel.direction, channel.idx, len)
strlist = StringList(ptr, len[])
return ComponentList{$e}(strlist)
end
end
end

function ComponentList(::Type{T}, d::Device) where {T<:AbstractComponent}
if T <: SensorComponent
ComponentList{SensorComponent}(StringList(SoapySDRDevice_listSensors(d.ptr)...))
len = Ref{Csize_t}()
ptr = if T <: SensorComponent
SoapySDRDevice_listSensors(d, len)
elseif T <: TimeSource
ComponentList{TimeSource}(StringList(SoapySDRDevice_listTimeSources(d.ptr)...))
SoapySDRDevice_listTimeSources(d, len)
elseif T <: ClockSource
ComponentList{ClockSource}(StringList(SoapySDRDevice_listClockSources(d.ptr)...))
SoapySDRDevice_listClockSources(d, len)
elseif T <: UART
ComponentList{UART}(StringList(SoapySDRDevice_listUARTs(d.ptr)...))
SoapySDRDevice_listUARTs(d, len)
elseif T <: GPIO
ComponentList{GPIO}(StringList(SoapySDRDevice_listGPIOBanks(d.ptr)...))
SoapySDRDevice_listGPIOBanks(d, len)
elseif T <: Register
ComponentList{Register}(StringList(SoapySDRDevice_listRegisterInterfaces(d.ptr)...))
SoapySDRDevice_listRegisterInterfaces(d, len)
end
strlist = StringList(ptr, len[])
ComponentList{T}(strlist)
end

function ComponentList(::Type{T}, d::Device, c::Channel) where {T<:AbstractComponent}
len = Ref{Csize_t}()
if T <: SensorComponent
s = SoapySDRDevice_listChannelSensors(d.ptr, c.direction, c.idx, len)
s = SoapySDRDevice_listChannelSensors(d, c.direction, c.idx, len)
ComponentList{SensorComponent}(StringList(s, len[]))
end
end
Expand All @@ -107,15 +113,15 @@ end


function Base.getindex(d::Device, se::SensorComponent)
unsafe_string(SoapySDRDevice_readSensor(d.ptr, se.name))
unsafe_string(SoapySDRDevice_readSensor(d, se.name))
end

function Base.getindex(d::Device, se::Setting)
unsafe_string(SoapySDRDevice_readSetting(d.ptr, se.name))
unsafe_string(SoapySDRDevice_readSetting(d, se.name))
end

function Base.getindex(d::Device, se::Tuple{Register,<:Integer})
SoapySDRDevice_readRegister(d.ptr, se[1].name, se[2])
SoapySDRDevice_readRegister(d, se[1].name, se[2])
end

function Base.setindex!(c::Channel, gain, ge::GainElement)
Expand Down Expand Up @@ -153,11 +159,11 @@ dev[(SoapySDR.Register("LMS7002M"), 0x1234)] = 0x5678 # this is also equivalent,
```
"""
function Base.setindex!(d::Device, val::Tuple{<:Integer,<:Integer}, se::Register)
SoapySDRDevice_writeRegister(d.ptr, se.name, val[1], val[2])
SoapySDRDevice_writeRegister(d, se.name, val[1], val[2])
end

function Base.setindex!(d::Device, val::Integer, se::Tuple{Register,<:Integer})
SoapySDRDevice_writeRegister(d.ptr, se[1].name, se[2], val)
SoapySDRDevice_writeRegister(d, se[1].name, se[2], val)
end


Expand Down Expand Up @@ -192,39 +198,42 @@ function _hzrange(soapyr::SoapySDRRange)
end

function bandwidth_ranges(c::Channel)
(ptr, len) = SoapySDRDevice_getBandwidthRange(c.device.ptr, c.direction, c.idx)
len = Ref{Csize_t}()
ptr = SoapySDRDevice_getBandwidthRange(c.device, c.direction, c.idx, len)
ptr == C_NULL && return SoapySDRRange[]
arr = map(_hzrange, unsafe_wrap(Array, Ptr{SoapySDRRange}(ptr), (len,)))
arr = map(_hzrange, unsafe_wrap(Array, Ptr{SoapySDRRange}(ptr), (len[],)))
SoapySDR_free(ptr)
arr
end

function frequency_ranges(c::Channel)
(ptr, len) = SoapySDRDevice_getFrequencyRange(c.device.ptr, c.direction, c.idx)
len = Ref{Csize_t}()
ptr = SoapySDRDevice_getFrequencyRange(c.device, c.direction, c.idx, len)
ptr == C_NULL && return SoapySDRRange[]
arr = map(_hzrange, unsafe_wrap(Array, Ptr{SoapySDRRange}(ptr), (len,)))
arr = map(_hzrange, unsafe_wrap(Array, Ptr{SoapySDRRange}(ptr), (len[],)))
SoapySDR_free(ptr)
arr
end

function frequency_ranges(c::Channel, fe::FrequencyComponent)
(ptr, len) =
SoapySDRDevice_getFrequencyRangeComponent(c.device.ptr, c.direction, c.idx, fe.name)
len = Ref{Csize_t}()
ptr = SoapySDRDevice_getFrequencyRangeComponent(c.device, c.direction, c.idx, fe.name, len)
ptr == C_NULL && return SoapySDRRange[]
arr = map(_hzrange, unsafe_wrap(Array, Ptr{SoapySDRRange}(ptr), (len,)))
arr = map(_hzrange, unsafe_wrap(Array, Ptr{SoapySDRRange}(ptr), (len[],)))
SoapySDR_free(ptr)
arr
end

function gain_range(c::Channel, ge::GainElement)
ptr = SoapySDRDevice_getGainElementRange(c.device.ptr, c.direction, c.idx, ge.name)
ptr = SoapySDRDevice_getGainElementRange(c.device, c.direction, c.idx, ge.name)
ptr
end

function sample_rate_ranges(c::Channel)
(ptr, len) = SoapySDRDevice_getSampleRateRange(c.device.ptr, c.direction, c.idx)
len = Ref{Csize_t}()
ptr = SoapySDRDevice_getSampleRateRange(c.device, c.direction, c.idx, len)
ptr == C_NULL && return SoapySDRRange[]
arr = map(_hzrange, unsafe_wrap(Array, Ptr{SoapySDRRange}(ptr), (len,)))
arr = map(_hzrange, unsafe_wrap(Array, Ptr{SoapySDRRange}(ptr), (len[],)))
SoapySDR_free(ptr)
arr
end
Expand All @@ -236,7 +245,7 @@ List the natively supported sample rates for a given channel.
"""
function list_sample_rates(c::Channel)
len = Ref{Csize_t}(0)
ptr = SoapySDRDevice_listSampleRates(c.device.ptr, c.direction, c.idx, len)
ptr = SoapySDRDevice_listSampleRates(c.device, c.direction, c.idx, len)
arr = unsafe_wrap(Array, Ptr{Float64}(ptr), (len[],)) * Hz
SoapySDR_free(ptr)
arr
Expand Down
70 changes: 36 additions & 34 deletions src/device/channel.jl
Original file line number Diff line number Diff line change
Expand Up @@ -117,74 +117,76 @@ end

function Base.getproperty(c::Channel, s::Symbol)
if s === :info
return KWArgs(SoapySDRDevice_getChannelInfo(c.device.ptr, c.direction, c.idx))
return KWArgs(SoapySDRDevice_getChannelInfo(c.device, c.direction, c.idx))
elseif s === :antenna
ant = SoapySDRDevice_getAntenna(c.device.ptr, c.direction, c.idx)
ant = SoapySDRDevice_getAntenna(c.device, c.direction, c.idx)
return Antenna(Symbol(ant == C_NULL ? "" : unsafe_string(ant)))
elseif s === :antennas
return AntennaList(c)
elseif s === :gain
return SoapySDRDevice_getGain(c.device.ptr, c.direction, c.idx) * dB
return SoapySDRDevice_getGain(c.device, c.direction, c.idx) * dB
elseif s === :gain_elements
return GainElementList(c)
elseif s === :dc_offset_mode
if !SoapySDRDevice_hasDCOffsetMode(c.device.ptr, c.direction, c.idx)
if !SoapySDRDevice_hasDCOffsetMode(c.device, c.direction, c.idx)
return missing
end
return SoapySDRDevice_getDCOffsetMode(c.device.ptr, c.direction, c.idx)
return SoapySDRDevice_getDCOffsetMode(c.device, c.direction, c.idx)
elseif s === :dc_offset
if !SoapySDRDevice_hasDCOffset(c.device.ptr, c.direction, c.idx)
if !SoapySDRDevice_hasDCOffset(c.device, c.direction, c.idx)
return missing
end
i = Ref{Cdouble}(0)
q = Ref{Cdouble}(0)
SoapySDRDevice_getDCOffset(c.device.ptr, c.direction, c.idx, i, q)
SoapySDRDevice_getDCOffset(c.device, c.direction, c.idx, i, q)
return i[], q[]
elseif s === :iq_balance_mode
if !SoapySDRDevice_hasIQBalanceMode(c.device.ptr, c.direction, c.idx)
if !SoapySDRDevice_hasIQBalanceMode(c.device, c.direction, c.idx)
return missing
end
return SoapySDRDevice_getIQBalanceMode(c.device.ptr, c.direction, c.idx)
return SoapySDRDevice_getIQBalanceMode(c.device, c.direction, c.idx)
elseif s === :iq_balance
if !SoapySDRDevice_hasIQBalance(c.device.ptr, c.direction, c.idx)
if !SoapySDRDevice_hasIQBalance(c.device, c.direction, c.idx)
return missing
end
i = Ref{Cdouble}(0)
q = Ref{Cdouble}(0)
SoapySDRDevice_getIQBalance(c.device.ptr, c.direction, c.idx, i, q)
SoapySDRDevice_getIQBalance(c.device, c.direction, c.idx, i, q)
return Complex(i[], q[])
elseif s === :gain_mode
if !SoapySDRDevice_hasGainMode(c.device.ptr, c.direction, c.idx)
if !SoapySDRDevice_hasGainMode(c.device, c.direction, c.idx)
return missing
end
return SoapySDRDevice_getGainMode(c.device.ptr, c.direction, c.idx)
return SoapySDRDevice_getGainMode(c.device, c.direction, c.idx)
elseif s === :frequency_correction
if !SoapySDRDevice_hasFrequencyCorrection(c.device.ptr, c.direction, c.idx)
if !SoapySDRDevice_hasFrequencyCorrection(c.device, c.direction, c.idx)
return missing
end
# TODO: ppm unit?
return SoapySDRDevice_getFrequencyCorrection(c.device.ptr, c.direction, c.idx)
return SoapySDRDevice_getFrequencyCorrection(c.device, c.direction, c.idx)
elseif s === :sample_rate
return SoapySDRDevice_getSampleRate(c.device.ptr, c.direction, c.idx) * Hz
return SoapySDRDevice_getSampleRate(c.device, c.direction, c.idx) * Hz
elseif s === :sensors
ComponentList(SensorComponent, c.device, c)
elseif s === :bandwidth
return SoapySDRDevice_getBandwidth(c.device.ptr, c.direction, c.idx) * Hz
return SoapySDRDevice_getBandwidth(c.device, c.direction, c.idx) * Hz
elseif s === :frequency
return SoapySDRDevice_getFrequency(c.device.ptr, c.direction, c.idx) * Hz
return SoapySDRDevice_getFrequency(c.device, c.direction, c.idx) * Hz
elseif s === :fullduplex
return Bool(SoapySDRDevice_getFullDuplex(c.device.ptr, c.direction, c.idx))
return Bool(SoapySDRDevice_getFullDuplex(c.device, c.direction, c.idx))
elseif s === :stream_formats
slist =
StringList(SoapySDRDevice_getStreamFormats(c.device.ptr, c.direction, c.idx)...)
len = Ref{Csize_t}()
ptr = SoapySDRDevice_getStreamFormats(c.device, c.direction, c.idx, len)
slist = StringList(ptr, len[])
return map(_stream_map_soapy2jl, slist)
elseif s === :native_stream_format
fmt, _ = SoapySDRDevice_getNativeStreamFormat(c.device.ptr, c.direction, c.idx)
fullscale = Ref{Cdouble}()
fmt = SoapySDRDevice_getNativeStreamFormat(c.device, c.direction, c.idx, fullscale)
return _stream_map_soapy2jl(fmt == C_NULL ? "" : unsafe_string(fmt))
elseif s === :fullscale
_, fullscale =
SoapySDRDevice_getNativeStreamFormat(c.device.ptr, c.direction, c.idx)
return fullscale
fullscale = Ref{Cdouble}()
fmt = SoapySDRDevice_getNativeStreamFormat(c.device, c.direction, c.idx, fullscale)
return fullscale[]
elseif s === :frequency_components
return FrequencyComponentList(c)
else
Expand Down Expand Up @@ -223,16 +225,16 @@ end
function Base.setproperty!(c::Channel, s::Symbol, v)
if s === :antenna
if v isa Antenna
SoapySDRDevice_setAntenna(c.device.ptr, c.direction, c.idx, v.name)
SoapySDRDevice_setAntenna(c.device, c.direction, c.idx, v.name)
elseif v isa Symbol || v isa String
SoapySDRDevice_setAntenna(c.device.ptr, c.direction, c.idx, v)
SoapySDRDevice_setAntenna(c.device, c.direction, c.idx, v)
else
throw(ArgumentError("antenna must be an Antenna or a Symbol"))
end
elseif s === :frequency
if isa(v, Quantity)
SoapySDRDevice_setFrequency(
c.device.ptr,
c.device,
c.direction,
c.idx,
uconvert(u"Hz", v).val,
Expand All @@ -249,26 +251,26 @@ function Base.setproperty!(c::Channel, s::Symbol, v)
end
elseif s === :bandwidth
SoapySDRDevice_setBandwidth(
c.device.ptr,
c.device,
c.direction,
c.idx,
uconvert(u"Hz", v).val,
)
elseif s === :gain_mode
SoapySDRDevice_setGainMode(c.device.ptr, c.direction, c.idx, v)
SoapySDRDevice_setGainMode(c.device, c.direction, c.idx, v)
elseif s === :gain
SoapySDRDevice_setGain(c.device.ptr, c.direction, c.idx, uconvert(u"dB", v).val)
SoapySDRDevice_setGain(c.device, c.direction, c.idx, uconvert(u"dB", v).val)
elseif s === :sample_rate
SoapySDRDevice_setSampleRate(
c.device.ptr,
c.device,
c.direction,
c.idx,
uconvert(u"Hz", v).val,
)
elseif s === :dc_offset_mode
SoapySDRDevice_setDCOffsetMode(c.device.ptr, c.direction, c.idx, v)
SoapySDRDevice_setDCOffsetMode(c.device, c.direction, c.idx, v)
elseif s === :iq_balance
SoapySDRDevice_setIQBalance(c.device.ptr, c.direction, c.idx, real(v), imag(v))
SoapySDRDevice_setIQBalance(c.device, c.direction, c.idx, real(v), imag(v))
else
throw(ArgumentError("Channel has no property: $s"))
end
Expand Down
5 changes: 5 additions & 0 deletions src/device/settings.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
function SettingInfo(dev::Device)
len = Ref{Csize_t}()
ptr = SoapySDRDevice_getSettingInfo(dev, len)
ArgInfoList(ptr, len[])
end
20 changes: 13 additions & 7 deletions src/device/stream.jl
Original file line number Diff line number Diff line change
Expand Up @@ -185,17 +185,22 @@ function Base.read!(
end
GC.@preserve buffers while total_nread < samples_to_read
# collect list of pointers to pass to SoapySDR
isopen(s) || throw(InvalidStateException("stream is closed!", :closed))
buff_ptrs = pointer(map(b -> pointer(b, total_nread + 1), buffers))
nread, out_flags, timens = SoapySDRDevice_readStream(
out_flags = Ref{Cint}()
timens = Ref{Clonglong}()
nread = SoapySDRDevice_readStream(
s.d,
s,
buff_ptrs,
samples_to_read - total_nread,
out_flags,
timens,
timeout_us,
)

if typeof(flags) <: Ref
flags[] |= out_flags
flags[] |= out_flags[]
end

if nread < 0
Expand All @@ -213,7 +218,7 @@ function Base.read!(
timeout = timeout_s,
total_nread,
samples_to_read,
flags = join(flags_to_set(out_flags), ","),
flags = join(flags_to_set(out_flags[]), ","),
)
return buffers
end
Expand Down Expand Up @@ -321,18 +326,19 @@ function Base.write(

GC.@preserve buffers while total_nwritten < samples_to_write
buff_ptrs = pointer(map(b -> pointer(b, total_nwritten + 1), buffers))
nwritten, out_flags = SoapySDRDevice_writeStream(
out_flags = Ref{Cint}(0)
nwritten = SoapySDRDevice_writeStream(
s.d,
s,
buff_ptrs,
samples_to_write - total_nwritten,
0,
flags,
0,
timeout_us,
)

if typeof(flags) <: Ref
flags[] |= out_flags
flags[] |= out_flags[]
end

if nwritten < 0
Expand All @@ -350,7 +356,7 @@ function Base.write(
timeout = timeout_s,
total_nwritten,
samples_to_write,
flags = join(flags_to_set(out_flags), ","),
flags = join(flags_to_set(out_flags[]), ","),
)
return buffers
end
Expand Down
Loading