2222
2323# distutils: language = c++
2424# cython: language_level=3str
25+ # cython: freethreading_compatible = True
2526try :
2627 from pyfftw.interfaces.numpy_fft import fft, fftshift # type: ignore
2728except ImportError :
@@ -46,9 +47,10 @@ import sys
4647
4748cnp.import_array()
4849
49- PY_FREQ_MIN_MHZ = 0 # 0 MHz
50- PY_FREQ_MAX_MHZ = 7 _250 # 7250 MHz
51- PY_FREQ_MAX_HZ = PY_FREQ_MAX_MHZ * 1e6 # Hz
50+ FREQ_MIN_MHZ = 0 # 0 MHz
51+ FREQ_MAX_MHZ = 7 _250 # 7250 MHz
52+ FREQ_MIN_HZ = int (FREQ_MIN_MHZ * 1e6 ) # HZ
53+ FREQ_MAX_HZ = int (FREQ_MAX_MHZ * 1e6 ) # Hz
5254PY_BLOCKS_PER_TRANSFER = 16
5355
5456# hackrf sweep settings
@@ -107,16 +109,18 @@ cpdef int sweep_callback(c_pyhackrf.PyHackrfDevice device, cnp.ndarray[cnp.int8_
107109 cdef str time_str = datetime.datetime.now().strftime(' %Y -%m -%d , %H :%M :%S .%f ' )
108110
109111 cdef dict device_data = device.device_data
110- cdef double norm_factor = 1 / device_data[' fft_size' ]
111112 cdef uint32_t data_length = device_data[' fft_size' ] * 2
112113 cdef object sweep_style = device_data[' sweep_style' ]
113114 cdef uint32_t sample_rate = device_data[' sample_rate' ]
114115 cdef uint32_t fft_size = device_data[' fft_size' ]
115116 cdef cnp.ndarray window = device_data[' window' ]
117+ cdef double psd_norm = device_data[' psd_norm' ]
116118 cdef uint8_t device_id = device_data[' device_id' ]
119+ cdef double divider = 1 / 128
117120
118121 cdef uint64_t start_frequency = device_data[' start_frequency' ]
119122
123+ cdef cnp.ndarray fft_out
120124 cdef cnp.ndarray raw_iq
121125 cdef cnp.ndarray pwr
122126
@@ -149,22 +153,23 @@ cpdef int sweep_callback(c_pyhackrf.PyHackrfDevice device, cnp.ndarray[cnp.int8_
149153 device_data[' sweep_started' ] = True
150154
151155 if not working_sdrs[device_id].load():
152- device_data[' notify_finished ' ].set()
156+ device_data[' close_ready ' ].set()
153157 return - 1
154158
155159 if not device_data[' sweep_started' ]:
156160 index += pyhackrf.PY_BYTES_PER_BLOCK
157161 continue
158162
159- if PY_FREQ_MAX_HZ < frequency:
163+ if FREQ_MAX_HZ < frequency:
160164 index += pyhackrf.PY_BYTES_PER_BLOCK
161165 continue
162166
163167 index += (pyhackrf.PY_BYTES_PER_BLOCK - data_length)
164168
165- raw_iq = buffer [index:index + data_length:2 ] / 128 + 1j * buffer [index + 1 :index + data_length:2 ] / 128
169+ raw_iq = buffer [index:index + data_length:2 ] * divider + 1j * buffer [index + 1 :index + data_length:2 ] * divider
166170 raw_iq = (raw_iq - raw_iq.mean()) * window
167- pwr = np.log10(np.abs(fft(raw_iq) * norm_factor) ** 2 ) * 10.0
171+ fft_out = fft(raw_iq)
172+ pwr = np.log10((fft_out.real** 2 + fft_out.imag** 2 ) * psd_norm + 1e-300 ) * 10.0
168173
169174 if sweep_style == pyhackrf.py_sweep_style.LINEAR:
170175 pwr = fftshift(pwr)
@@ -251,7 +256,6 @@ def pyhackrf_sweep(frequencies: list[int] | None = None, sample_rate: int = 20_0
251256 cdef uint8_t device_id = init_signals()
252257 cdef c_pyhackrf.PyHackrfDevice device
253258 cdef uint32_t offset = 0
254- cdef int i
255259
256260 pyhackrf.pyhackrf_init()
257261
@@ -323,10 +327,10 @@ def pyhackrf_sweep(frequencies: list[int] | None = None, sample_rate: int = 20_0
323327 step_count = 1 + (frequencies[2 * i + 1 ] - frequencies[2 * i] - 1 ) // TUNE_STEP
324328 frequencies[2 * i + 1 ] = int (frequencies[2 * i] + step_count * TUNE_STEP)
325329
326- if frequencies[2 * i] < PY_FREQ_MIN_MHZ :
327- raise RuntimeError (f' min frequency must must be greater than {PY_FREQ_MIN_MHZ } MHz.' )
328- if frequencies[2 * i + 1 ] > PY_FREQ_MAX_MHZ :
329- raise RuntimeError (f' max frequency may not be higher {PY_FREQ_MAX_MHZ } MHz.' )
330+ if frequencies[2 * i] < FREQ_MIN_MHZ :
331+ raise RuntimeError (f' min frequency must must be greater than {FREQ_MIN_MHZ } MHz.' )
332+ if frequencies[2 * i + 1 ] > FREQ_MAX_MHZ :
333+ raise RuntimeError (f' max frequency may not be higher {FREQ_MAX_MHZ } MHz.' )
330334
331335 if print_to_console:
332336 sys.stderr.write(f' Sweeping from {frequencies[2 * i]} MHz to {frequencies[2 * i + 1]} MHz\n ' )
@@ -354,7 +358,8 @@ def pyhackrf_sweep(frequencies: list[int] | None = None, sample_rate: int = 20_0
354358 ' start_frequency' : int (frequencies[0 ] * 1e6 ),
355359 ' fft_size' : fft_size,
356360 ' window' : np.hanning(fft_size),
357- ' notify_finished' : threading.Event(),
361+ ' psd_norm' : 1 / (sample_rate * np.dot(np.hanning(fft_size), np.hanning(fft_size))),
362+ ' close_ready' : threading.Event(),
358363
359364 ' binary_output' : binary_output,
360365 ' one_shot' : one_shot,
@@ -408,7 +413,7 @@ def pyhackrf_sweep(frequencies: list[int] | None = None, sample_rate: int = 20_0
408413 sys.stderr.write(f' Total sweeps: {device_data["sweep_count"]} in {time_now - time_start:.5f} seconds ({sweep_rate :.2f} sweeps/second)\n ' )
409414
410415 working_sdrs[device_id].store(0 )
411- device_data[' notify_finished ' ].wait()
416+ device_data[' close_ready ' ].wait()
412417 sdr_ids.pop(device.serialno, None )
413418
414419 if antenna_enable:
0 commit comments