-
Notifications
You must be signed in to change notification settings - Fork 3
/
UHDBindings.jl
310 lines (273 loc) · 11.5 KB
/
UHDBindings.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
module UHDBindings
using Printf
using Preferences
using Libdl
# ----------------------------------------------------
# --- Loading UHD library
# ----------------------------------------------------
# We use Yggdrasil to load the artifact responsible for UHD.
# It is possible to use a local install instead of the proposed UHD version
"""
Change UHD driver provider. Support "yggdrasil" to use shipped jll file or "local" to use custom installed library
set_provider("yggdrasil")
or
set_provider("local")
"""
function set_provider(new_provider::String)
if !(new_provider in ("yggdrasil","default", "local"))
throw(ArgumentError("Invalid provider: \"$(new_provider)\""))
end
# Set it in our runtime values, as well as saving it to disk
@set_preferences!("provider" => new_provider)
@info("New provider set; restart your Julia session for this change to take effect!")
end
function get_provider()
return @load_preference("provider","yggdrasil")
end
""" Set the path for the UHD shared library (e.g /Documents/Program/UHD/libuhd.dll or /opt/local/uhd/uhd.lib") Usefull for custom installation without messing up the PATHs
Example= set_lib_path("C://Program/UHD/bin/libUHD.dll")
"""
function set_lib_path(new_path::String)
@set_preferences!("lib_path" => new_path)
@info ("New path for UHD shared lib; restart your Julia session for this change to take effect!")
end
function get_lib_path()
return @load_preference("lib_path","libuhd")
end
const uhd_provider = get_provider()
@static if uhd_provider == "yggdrasil" || uhd_provider =="default"
# --- Using Yggdrasil jll file
using USRPHardwareDriver_jll
try
# --- We load the lib, but in two steps in case of an problem occur
# The condition here are long... As by default we use Yggdrasil we have to find if the loading operation are Ok. We first test that the lib exist and if it is not the case, we try to load the lib in the default path. If there are no such lib, we ask the user to specify it using Preferences.jl
global tmp_libUHD = USRPHardwareDriver_jll.libuhd
catch exception
# A problem occured :D. Load manually the lib
@warn "Unable to load libUHD using Yggdrasil. It probably means that the platform you use is not supported by artifact generated through Yggdrasil."
@info "We fallback to local provider. It means that UHDBindings will work if you have installed a functionnal version of UHD on your system"
# --- Change provider
set_provider("local")
# Try to load the lib using default path
myLib = get_lib_path()
try
# Load the lib for fun. If it fails, we raise a warning
libUHD_system_h = dlopen(myLib, false);
global tmp_libUHD = libUHD_system_h
catch exception2
# We cannot find the lib, say to the user to manually update the lib path (including .dll / .so / .dylib)
@warn "Unable to load the lib, the path should be updated to the appropriate location using `UHDBindings.set_lib_path`. For instance UHDBindings.set_lib_path(\"C:\\Users\\Robin\\Documents\\UHD\\bin\\uhd.dll\")"
global tmp_libUHD = "" # To have a const defined. Note that this require a session reload
end
end
# --- Point lib here it is good
const libUHD = tmp_libUHD
end
@static if uhd_provider == "local"
# --- Using local install, assuming it works
myLib = get_lib_path()
libUHD_system_h = dlopen(myLib, false);
tmp_libUHD = dlpath(libUHD_system_h)
const libUHD = tmp_libUHD
end
# ----------------------------------------------------
# --- Bindings, structure and low level functions
# ----------------------------------------------------
# --- Including the file
include("Bindings.jl");
# Export necessary structures for high API level managment
export Timestamp
export UHDBinding
# Exporting printing macros
export @infotx, @warntx;
export @inforx, @warnrx;
# ----------------------------------------------------
# --- Finding devices
# ----------------------------------------------------
include("Find.jl")
export uhd_find_devices
# ----------------------------------------------------
# --- Receiver Configuration
# ----------------------------------------------------
# All structures and functions for the Rx side
include("Rx.jl");
# Structures
export UHDRx
# Export functions
export recv,recv!;
export populateBuffer!
export getError, getTimestamp
export restartStreamer
# ----------------------------------------------------
# --- Transmitter Configuration
# ----------------------------------------------------
# All structures and functions for the Tx side
include("Tx.jl");
# Structures
export UHDTx
# Export functions
export send;
"""
Init the core parameter of the radio in Tx or in Rx mode and initiate RF parameters
# --- Syntax
openUHD(mode,sysImage,carrierFreq,samplingRate,txGain,antenna="RX2")
# --- Input parameters
- mode : String to open radio in "Tx" (transmitter) or in "Rx" (receive) mode
- carrierFreq : Desired Carrier frequency [Union{Int,Float64}]
- samplingRate : Desired bandwidth [Union{Int,Float64}]
- gain : Desired Gain [Union{Int,Float64}]
- antenna : Desired Antenna alias Dict{Symbol,Vector[String]} (e.g. Dict(:Rx=>["RX2"],:Tx=>["TRX"]))
Keywords=
- args : String with the additionnal load parameters (for instance, path to the FPHGA image) [String]
# --- Output parameters
- uhd : UHD object [UHDBinding]
"""
function openUHD(carrierFreq, samplingRate, gain;args="",channels=[0],antennas=Dict(:Rx=>["RX2"],:Tx=>["TRX"]),cpu_format="fc32",otw_format="sc16",subdev="",nbAntennaRx=1,nbAntennaTx=1,bypassStreamer=false)
# ----------------------------------------------------
# --- Handler
# ----------------------------------------------------
addressUSRP = Ref{uhd_usrp_handle}();
# --- Cal the init
@assert_uhd uhd_usrp_make(addressUSRP,args)
# --- Get the usable object
pointerUSRP = addressUSRP[];
# ----------------------------------------------------
# --- Manage dictionnaries for custom option passing
# ----------------------------------------------------
aTx = parseDict(antennas,:Tx,["TRX"])
aRx = parseDict(antennas,:Rx,["RX2"])
# ----------------------------------------------------
# --- Set Rx stage
# ----------------------------------------------------
rx = openUHDRx(pointerUSRP,carrierFreq, samplingRate, gain;channels,antennas=aRx,args,cpu_format,otw_format,subdev,nbAntennaRx,bypassStreamer)
# ----------------------------------------------------
# --- Set Tx stage
# ----------------------------------------------------
tx = openUHDTx(pointerUSRP,carrierFreq, samplingRate, gain;channels,antennas=aTx,args,cpu_format,otw_format,subdev,nbAntennaTx,bypassStreamer)
# ----------------------------------------------------
# --- Create radio
# ----------------------------------------------------
uhdBinding = UHDBinding(addressUSRP,rx,tx);
return uhdBinding;
end
export openUHD;
# Be able to get a default value
parseDict(d,key,val=0) = (haskey(d,key) ? d[key] : val)
"""
Close the USRP device (Rx or Tx mode) and release all associated objects
# --- Syntax
close(uhd)
# --- Input parameters
- uhd : UHD object [UHDBinding]
# --- Output parameters
- []
"""
function Base.close(uhdBinding::UHDBinding)
# --- Close Rx and Tx streams
close(uhdBinding.rx);
close(uhdBinding.tx);
# --- Close the USRP main object
@assert_uhd uhd_usrp_free(uhdBinding.addressUSRP);
# --- Print a flag
print("\n");
@info "USRP device is now closed.";
end
"""
Print the radio configuration
# --- Syntax
print(radio,chan=0)
# --- Input parameters
- radio : UHD object [Union{UHDBinding,UHDTx,UHDRx}]
- chan : Channel index to display (default 0)
# --- Output parameters
- []
"""
function Base.print(radio::UHDBinding,chan=0)
# --- Print the configuration of Tx and Rx
print(radio.rx,chan);
print(radio.tx,chan);
end
# All functions are defined @UHDTx or @UHDRx level, we should define configuration functions @UHDBinding level
# In such case, we will both apply configuration at Rx and Tx sides.
"""
Update sampling rate of current radio device, and update radio object with the new obtained sampling frequency. If the input parameter is the UHDBinding object, the desired sampling frequency will be applied on both Rx and Tx sides.
If the input is a [UHDRx] or a [UHDTx] object, it updates only the Rx or Tx sampling frequency
# --- Syntax
updateSamplingRate!(radio,samplingRate,chan=0)
# --- Input parameters
- radio : UHD device [Union{UHDBinding,UHDRx,UHDTx}]
- samplingRate : New desired sampling rate
- chan : Channel index to use (default 0)
# --- Output parameters
-
"""
function updateSamplingRate!(radio::UHDBinding,samplingRate,chan=0)
@sync updateSamplingRate!(radio.rx,samplingRate,chan);
@sync updateSamplingRate!(radio.tx,samplingRate,chan);
end
"""
Update carrier frequency of current radio device, and update radio object with the new obtained carrier frequency. If the input parameter is the UHDBinding object, the desired carrier frequency will be applied on both Rx and Tx sides.
If the input is a [UHDRx] or a [UHDTx] object, it updates only the Rx or Tx carrier frequency
# --- Syntax
updateCarrierFreq!(radio,carrierFreq)
# --- Input parameters
- radio : UHD device [Union{UHDBinding,UHDRx,UHDTx}]
- carrierFreq : New desired carrier frequency
- chan : Channel index to use (default 0)
# --- Output parameters
-
"""
function updateCarrierFreq!(radio::UHDBinding,carrierFreq,chan=0)
@sync updateCarrierFreq!(radio.rx,carrierFreq,chan);
@sync updateCarrierFreq!(radio.tx,carrierFreq,chan);
end
"""
Update gain of current radio device, and update radio object with the new obtained gain. If the input parameter is the UHDBinding object, the desired gain will be applied on both Rx and Tx sides.
If the input is a [UHDRx] or a [UHDTx] object, it updates only the Rx or Tx gain
# --- Syntax
updateGain!(radio,gain)
# --- Input parameters
- radio : UHD device [Union{UHDBinding,UHDRx,UHDTx}]
- gain : New desired gain
- chan : Channel index to use (default 0)
# --- Output parameters
-
"""
function updateGain!(radio::UHDBinding,gain,chan=0)
@sync updateGain!(radio.rx,gain,chan);
@sync updateGain!(radio.tx,gain,chan);
end
# When given to UHDBinding, recv and send will dispatch to the appropriate substructure
# Recv
recv(radio::UHDBinding,nbSamples) = recv(radio.rx,nbSamples);
recv!(sig::Vector{Vector{T}},radio::UHDBinding;kwargs...) where T = recv!(sig,radio.rx;kwargs...);
recv!(sig::Vector{T},radio::UHDBinding;kwargs...) where T = recv!([sig],radio.rx;kwargs...);
# Send
send(radio::UHDBinding,params...) = send(radio.tx,params...);
# Config can laos be dispatch
uhd_usrp_create_stream(radio::UHDBinding;kwargs...) = uhd_usrp_create_stream(radio.rx;kwargs...)
""""
Returns the internal radio buffer size
"""
function getBufferSize(radio)
return radio.rx.packetSize
end
# ----------------------------------------------------
# --- Common functions and structures
# ----------------------------------------------------
export updateSamplingRate!
export updateGain!
export updateCarrierFreq!
export print;
export close;
export getBufferSize
# ----------------------------------------------------
# --- Error handling
# ----------------------------------------------------
abstract type UHDException <: Exception end
struct LateCommandException <: UHDException end
struct BrokenChainException <: UHDException end
struct OverflowException <: UHDException end
struct AlignmentException <: UHDException end
struct BadPacketException <: UHDException end
end # moduled # module