3535
3636PY_FREQ_MIN_MHZ = 0 # 0 MHz
3737PY_FREQ_MAX_MHZ = 7_250 # 7250 MHz
38+ PY_BLOCKS_PER_TRANSFER = 16
3839
3940# hackrf sweep settings
4041AVAILABLE_SAMPLING_RATES = (2_000_000 , 4_000_000 , 6_000_000 , 8_000_000 , 10_000_000 , 12_000_000 , 14_000_000 , 16_000_000 , 18_000_000 , 20_000_000 )
4142BASEBAND_FILTER_BANDWIDTH_RATIO = 0.75
4243OFFSET_RATIO = 0.375
4344
44- PY_BLOCKS_PER_TRANSFER = 16
4545
46- sample_rate_hz = None
46+ SAMPLE_RATE = None
4747frequency_step_1 = None
4848frequency_step_2 = None
4949frequency_step_3 = None
50+ SWEEP_STYLE = None
5051
5152# hackrf sweep valiables
5253binary_output_mode = False
@@ -101,9 +102,9 @@ def init_signals():
101102
102103
103104def sweep_callback (buffer : np .ndarray , buffer_length : int , valid_length : int ) -> int :
104- global fftSize , window , pwr_1_start , pwr_1_stop , pwr_2_start , pwr_2_stop , norm_factor , data_length , sample_rate_hz
105+ global fftSize , window , pwr_1_start , pwr_1_stop , pwr_2_start , pwr_2_stop , norm_factor , data_length , SAMPLE_RATE
105106 global start_frequency , sweep_count , sweep_started , max_num_sweeps , check_max_num_sweeps , accepted_bytes , one_shot_mode , run_available
106- global binary_output_mode , file_object , callback
107+ global binary_output_mode , file_object , callback , SWEEP_STYLE
107108
108109 timestamp = datetime .datetime .now ()
109110 time_str = timestamp .strftime ("%Y-%m-%d, %H:%M:%S.%f" )
@@ -147,45 +148,66 @@ def sweep_callback(buffer: np.ndarray, buffer_length: int, valid_length: int) ->
147148 index += data_length
148149
149150 if binary_output_mode :
150- record_length = 16 + (fftSize // 4 ) * 4
151- line = struct .pack ('I' , record_length )
152- line += struct .pack ('Q' , frequency )
153- line += struct .pack ('Q' , frequency + frequency_step_1 )
154- line += struct .pack ('<' + 'f' * (fftSize // 4 ), * pwr [pwr_1_start : pwr_1_stop ])
155- line += struct .pack ('I' , record_length )
156- line += struct .pack ('Q' , frequency + frequency_step_2 )
157- line += struct .pack ('Q' , frequency + frequency_step_3 )
158- line += struct .pack ('<' + 'f' * (fftSize // 4 ), * pwr [pwr_2_start : pwr_2_stop ])
151+ if SWEEP_STYLE == pyhackrf .py_sweep_style .INTERLEAVED :
152+ record_length = 16 + (fftSize // 4 ) * 4
153+ line = struct .pack ('I' , record_length )
154+ line += struct .pack ('Q' , frequency )
155+ line += struct .pack ('Q' , frequency + frequency_step_1 )
156+ line += struct .pack ('<' + 'f' * (fftSize // 4 ), * pwr [pwr_1_start : pwr_1_stop ])
157+ line += struct .pack ('I' , record_length )
158+ line += struct .pack ('Q' , frequency + frequency_step_2 )
159+ line += struct .pack ('Q' , frequency + frequency_step_3 )
160+ line += struct .pack ('<' + 'f' * (fftSize // 4 ), * pwr [pwr_2_start : pwr_2_stop ])
161+ else :
162+ record_length = 16 + fftSize * 4
163+ line = struct .pack ('I' , record_length )
164+ line += struct .pack ('Q' , frequency )
165+ line += struct .pack ('Q' , frequency + SAMPLE_RATE )
166+ line += struct .pack ('<' + 'f' * fftSize , * pwr )
159167
160168 if file_object is None :
161169 sys .stdout .buffer .write (line )
162170 else :
163171 file_object .write (line )
164172
165173 elif callback is not None :
166- callback ({
167- 'timestamp' : time_str ,
168- 'start_frequency' : frequency ,
169- 'stop_frequency' : frequency + frequency_step_1 ,
170- 'array' : pwr [pwr_1_start : pwr_1_stop ]
171- })
172- callback ({
173- 'timestamp' : time_str ,
174- 'start_frequency' : frequency + frequency_step_2 ,
175- 'stop_frequency' : frequency + frequency_step_3 ,
176- 'array' : pwr [pwr_2_start : pwr_2_stop ]
177- })
174+ if SWEEP_STYLE == pyhackrf .py_sweep_style .INTERLEAVED :
175+ callback ({
176+ 'timestamp' : time_str ,
177+ 'start_frequency' : frequency ,
178+ 'stop_frequency' : frequency + frequency_step_1 ,
179+ 'array' : pwr [pwr_1_start : pwr_1_stop ]
180+ })
181+ callback ({
182+ 'timestamp' : time_str ,
183+ 'start_frequency' : frequency + frequency_step_2 ,
184+ 'stop_frequency' : frequency + frequency_step_3 ,
185+ 'array' : pwr [pwr_2_start : pwr_2_stop ]
186+ })
187+
188+ else :
189+ callback ({
190+ 'timestamp' : time_str ,
191+ 'start_frequency' : frequency ,
192+ 'stop_frequency' : frequency + SAMPLE_RATE ,
193+ 'array' : pwr
194+ })
178195
179196 else :
180- line = f'{ time_str } , { frequency } , { frequency + frequency_step_1 } , { sample_rate_hz / fftSize } , { fftSize } , '
181- pwr_1 = pwr [pwr_1_start : pwr_1_stop ]
182- for i in range (len (pwr_1 )):
183- line += f'{ pwr_1 [i ]:.2f} , '
184- line += f'\n { time_str } , { frequency + frequency_step_2 } , { frequency + frequency_step_3 } , { (sample_rate_hz / fftSize )} , { fftSize } , '
185- pwr_2 = pwr [pwr_2_start : pwr_2_stop ]
186- for i in range (len (pwr_2 )):
187- line += f'{ pwr_2 [i ]:.2f} , '
188- line += '\n '
197+ if SWEEP_STYLE == pyhackrf .py_sweep_style .INTERLEAVED :
198+ line = f'{ time_str } , { frequency } , { frequency + frequency_step_1 } , { SAMPLE_RATE / fftSize } , { fftSize } , '
199+ pwr_1 = pwr [pwr_1_start : pwr_1_stop ]
200+ for i in range (len (pwr_1 )):
201+ line += f'{ pwr_1 [i ]:.2f} , '
202+ line += f'\n { time_str } , { frequency + frequency_step_2 } , { frequency + frequency_step_3 } , { (SAMPLE_RATE / fftSize )} , { fftSize } , '
203+ pwr_2 = pwr [pwr_2_start : pwr_2_stop ]
204+ for i in range (len (pwr_2 )):
205+ line += f'{ pwr_2 [i ]:.2f} , '
206+ line += '\n '
207+ else :
208+ line = f'{ time_str } , { frequency } , { frequency + SAMPLE_RATE } , { SAMPLE_RATE / fftSize } , { fftSize } , '
209+ for i in range (len (pwr )):
210+ line += f'{ pwr [i ]:.2f} , '
189211
190212 if file_object is None :
191213 print (line , end = '' )
@@ -199,18 +221,23 @@ def sweep_callback(buffer: np.ndarray, buffer_length: int, valid_length: int) ->
199221
200222def pyhackrf_sweep (frequencies : list = [0 , 6000 ], lna_gain : int = 16 , vga_gain : int = 20 , bin_width : int = 100_000 ,
201223 serial_number : str = None , amp_enable : bool = False , antenna_enable : bool = False , sample_rate : int = 20_000_000 ,
202- num_sweeps : int = None , binary_output : bool = False , one_shot : bool = False , filename : str = None ,
224+ num_sweeps : int = None , binary_output : bool = False , one_shot : bool = False , filename : str = None , sweep_style : pyhackrf . py_sweep_style = pyhackrf . py_sweep_style . INTERLEAVED ,
203225 print_to_console : bool = True , device : pyhackrf .PyHackrfDevice = None ):
204226
205- global fftSize , window , pwr_1_start , pwr_1_stop , pwr_2_start , pwr_2_stop , norm_factor , data_length , sample_rate_hz
227+ global fftSize , window , pwr_1_start , pwr_1_stop , pwr_2_start , pwr_2_stop , norm_factor , data_length , SAMPLE_RATE
206228 global start_frequency , sweep_count , sweep_started , max_num_sweeps , check_max_num_sweeps , accepted_bytes , one_shot_mode , run_available
207- global binary_output_mode , file_object , callback
229+ global binary_output_mode , file_object , callback , SWEEP_STYLE
208230 global frequency_step_1 , frequency_step_2 , frequency_step_3
209231
232+ if sweep_style in pyhackrf .py_sweep_style :
233+ SWEEP_STYLE = sweep_style
234+ else :
235+ SWEEP_STYLE = pyhackrf .sweep_stylepyhackrf .py_sweep_style .INTERLEAVED
236+
210237 if sample_rate in AVAILABLE_SAMPLING_RATES :
211- sample_rate_hz = sample_rate
238+ SAMPLE_RATE = sample_rate
212239 else :
213- sample_rate_hz = 20_000_000
240+ SAMPLE_RATE = 20_000_000
214241
215242 frequency_step_1 = sample_rate // 4
216243 frequency_step_2 = sample_rate // 2
@@ -222,9 +249,9 @@ def pyhackrf_sweep(frequencies: list = [0, 6000], lna_gain: int = 16, vga_gain:
222249 accepted_bytes = 0
223250 sweep_started = False
224251
225- BASEBAND_FILTER_BANDWIDTH = int (sample_rate_hz * BASEBAND_FILTER_BANDWIDTH_RATIO )
226- OFFSET = int (sample_rate_hz * OFFSET_RATIO )
227- TUNE_STEP = sample_rate_hz / 1e6
252+ BASEBAND_FILTER_BANDWIDTH = int (SAMPLE_RATE * BASEBAND_FILTER_BANDWIDTH_RATIO )
253+ OFFSET = int (SAMPLE_RATE * OFFSET_RATIO )
254+ TUNE_STEP = SAMPLE_RATE / 1e6
228255
229256 init_signals ()
230257
@@ -249,8 +276,8 @@ def pyhackrf_sweep(frequencies: list = [0, 6000], lna_gain: int = 16, vga_gain:
249276 device .set_sweep_callback (sweep_callback )
250277
251278 if print_to_console :
252- print (f'call pyhackrf_sample_rate_set({ sample_rate_hz / 1e6 :.3f} MHz)' , file = sys .stderr )
253- device .pyhackrf_set_sample_rate_manual (sample_rate_hz , 1 )
279+ print (f'call pyhackrf_sample_rate_set({ SAMPLE_RATE / 1e6 :.3f} MHz)' , file = sys .stderr )
280+ device .pyhackrf_set_sample_rate_manual (SAMPLE_RATE , 1 )
254281
255282 if print_to_console :
256283 print (f'call pyhackrf_set_baseband_filter_bandwidth({ BASEBAND_FILTER_BANDWIDTH / 1e6 :.3f} MHz)' , file = sys .stderr )
@@ -283,15 +310,15 @@ def pyhackrf_sweep(frequencies: list = [0, 6000], lna_gain: int = 16, vga_gain:
283310
284311 start_frequency = int (frequencies [0 ] * 1e6 )
285312
286- fftSize = int (sample_rate_hz / bin_width )
313+ fftSize = int (SAMPLE_RATE / bin_width )
287314 while ((fftSize + 4 ) % 8 ):
288315 fftSize += 1
289316
290317 if fftSize < 4 :
291- raise RuntimeError (f'bin_width should be between no more than { sample_rate_hz // 4 } Hz' )
318+ raise RuntimeError (f'bin_width should be between no more than { SAMPLE_RATE // 4 } Hz' )
292319
293320 if fftSize > 8180 :
294- raise RuntimeError (f'bin_width should be between no less than { sample_rate_hz // 8180 + 1 } Hz' )
321+ raise RuntimeError (f'bin_width should be between no less than { SAMPLE_RATE // 8180 + 1 } Hz' )
295322
296323 pwr_1_start = 1 + (fftSize * 5 ) // 8
297324 pwr_1_stop = 1 + (fftSize * 5 ) // 8 + fftSize // 4
@@ -304,7 +331,7 @@ def pyhackrf_sweep(frequencies: list = [0, 6000], lna_gain: int = 16, vga_gain:
304331
305332 window = np .hanning (fftSize )
306333
307- device .pyhackrf_init_sweep (frequencies , num_ranges , pyhackrf .PY_BYTES_PER_BLOCK , int (TUNE_STEP * 1e6 ), OFFSET , pyhackrf . py_sweep_style . INTERLEAVED )
334+ device .pyhackrf_init_sweep (frequencies , num_ranges , pyhackrf .PY_BYTES_PER_BLOCK , int (TUNE_STEP * 1e6 ), OFFSET , sweep_style )
308335
309336 if amp_enable :
310337 if print_to_console :
0 commit comments