aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArturs Artamonovs <dos21h@gmail.com>2023-03-05 12:28:20 +0000
committerArturs Artamonovs <dos21h@gmail.com>2023-03-05 12:28:20 +0000
commit071ecbd57ed29b61bc351ba4d72ae4a6c93db351 (patch)
treee4ed5a2e66fe8d1eddf1a665483037854f557d5b
downloadpyairspyhf-071ecbd57ed29b61bc351ba4d72ae4a6c93db351.tar.gz
pyairspyhf-071ecbd57ed29b61bc351ba4d72ae4a6c93db351.zip
Initial working commit
-rw-r--r--.gitignore2
-rw-r--r--README.md15
-rw-r--r--airspyhf/__init__.py3
-rw-r--r--airspyhf/airspyhf.py5
-rw-r--r--airspyhf/libairspyhf.py200
-rw-r--r--test.py150
6 files changed, 375 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..77f5cbe
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+.idea
+airspyhf/__pycache__/
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..9cd2359
--- /dev/null
+++ b/README.md
@@ -0,0 +1,15 @@
+# README
+
+Python wrapper of airspyhf library
+
+https://github.com/airspy/airspyhf.git
+
+Project webpage main.lv
+
+## Sourcecode
+
+## Install
+
+## Links
+
+https://docs.python.org/3/library/ctypes.html \ No newline at end of file
diff --git a/airspyhf/__init__.py b/airspyhf/__init__.py
new file mode 100644
index 0000000..920681b
--- /dev/null
+++ b/airspyhf/__init__.py
@@ -0,0 +1,3 @@
+from .libairspyhf import libairspyhf, airspyhf_lib_version_t, airspyhf_device_t_p, \
+ airspyhf_sample_block_cb_fn, airspyhf_transfer_t_p, airspyhf_transfer_t
+from .airspyhf import AirSpyHF \ No newline at end of file
diff --git a/airspyhf/airspyhf.py b/airspyhf/airspyhf.py
new file mode 100644
index 0000000..e13fada
--- /dev/null
+++ b/airspyhf/airspyhf.py
@@ -0,0 +1,5 @@
+from .libairspyhf import libairspyhf
+
+class AirSpyHF:
+ def __init__(self):
+ pass \ No newline at end of file
diff --git a/airspyhf/libairspyhf.py b/airspyhf/libairspyhf.py
new file mode 100644
index 0000000..5da77ff
--- /dev/null
+++ b/airspyhf/libairspyhf.py
@@ -0,0 +1,200 @@
+import sys
+import os
+from ctypes import *
+from ctypes.util import find_library
+
+
+def load_libairspyhf():
+ if sys.platform == "linux" and 'LD_LIBRARY_PATH' in os.environ.keys():
+ ld_library_paths = [local_path for local_path in os.environ['LD_LIBRARY_PATH'].split(':') if local_path.strip()]
+ ld_library_paths = ["/home/fam/prog/python/pyairspyhf/airspyhf/libairspyhf/src"]
+ driver_files = [local_path + '/libairspyhf.so' for local_path in ld_library_paths]
+ else:
+ driver_files = []
+ driver_files += ['libairspyhf.so']
+ #driver_files += ['airspyhf.dll', 'libairspyhf.so', 'libairspyhf.dylib']
+ #driver_files += ['..//airspyhf.dll', '..//libairspyhf.so']
+ driver_files += [lambda : find_library('airspyhf'), lambda : find_library('libairspyhf')]
+ dll = None
+
+ for driver in driver_files:
+ if callable(driver):
+ driver = driver()
+ if driver is None:
+ continue
+ print(driver)
+ try:
+ dll = CDLL(driver)
+ break
+ except:
+ pass
+ else:
+ raise ImportError('Error loading libairspyhf. Make sure libairspyhf '\
+ '(and all of its dependencies) are in your path')
+
+ return dll
+
+libairspyhf = load_libairspyhf()
+
+
+#typedef struct {
+# uint32_t major_version;
+# uint32_t minor_version;
+# uint32_t revision;
+#} airspyhf_lib_version_t;
+
+airspyhf_device_t_p = c_void_p
+class airspyhf_lib_version_t(Structure):
+ _fields_ = [("major_version", c_uint32),
+ ("minor_version", c_uint32),
+ ("revision", c_uint32)]
+
+class airspyhf_complex_float_t(Structure):
+ _fields_ = [("re",c_float),
+ ("im",c_float)]
+airspyhf_complex_float_t_p = POINTER(airspyhf_complex_float_t)
+
+class airspyhf_transfer_t(Structure):
+ _fields_ = [("device",airspyhf_device_t_p),
+ ("ctx",c_void_p),
+ ("samples",airspyhf_complex_float_t_p),
+ ("sample_count",c_int),
+ ("dropped_samples",c_uint64)]
+airspyhf_transfer_t_p = POINTER(airspyhf_transfer_t)
+#airspyhf_transfer_t_p = c_void_p
+
+#typedef int (*airspyhf_sample_block_cb_fn) (airspyhf_transfer_t* transfer_fn);
+#airspyhf_sample_block_cb_fn = CFUNCTYPE(c_int, POINTER(airspyhf_transfer_t))
+airspyhf_sample_block_cb_fn = PYFUNCTYPE(c_int, POINTER(airspyhf_transfer_t))
+#void ADDCALL airspyhf_lib_version(airspyhf_lib_version_t* lib_version);
+f = libairspyhf.airspyhf_lib_version
+f.restype, f.argtypes = None, [POINTER(airspyhf_lib_version_t)]
+
+#int ADDCALL airspyhf_list_devices(uint64_t *serials, int count);
+f = libairspyhf.airspyhf_list_devices
+f.restype, f.argtypes = c_int, [POINTER(c_uint64), c_int]
+
+#int ADDCALL airspyhf_open(airspyhf_device_t** device);
+f = libairspyhf.airspyhf_open
+f.restype, f.argtypes = c_int, [POINTER(airspyhf_device_t_p)]
+
+#int ADDCALL airspyhf_open_sn(airspyhf_device_t** device, uint64_t serial_number);
+f = libairspyhf.airspyhf_open_sn
+f.restype, f.argtypes = c_int, [POINTER(airspyhf_device_t_p), c_uint64]
+
+
+#int ADDCALL airspyhf_open_fd(airspyhf_device_t** device, int fd);
+f = libairspyhf.airspyhf_open_fd
+f.restype, f.argtypes = c_int, [POINTER(airspyhf_device_t_p), c_int]
+
+#int ADDCALL airspyhf_close(airspyhf_device_t* device);
+f = libairspyhf.airspyhf_close
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p]
+
+#nt ADDCALL airspyhf_get_output_size(airspyhf_device_t* device); /* Returns the number of IQ samples to expect in the callback */
+f = libairspyhf.airspyhf_get_output_size
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p]
+
+
+#int ADDCALL airspyhf_start(airspyhf_device_t* device, airspyhf_sample_block_cb_fn callback, void* ctx);
+f = libairspyhf.airspyhf_start
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p,airspyhf_sample_block_cb_fn,py_object]
+
+#int ADDCALL airspyhf_stop(airspyhf_device_t* device);
+f = libairspyhf.airspyhf_stop
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p]
+
+#int ADDCALL airspyhf_is_streaming(airspyhf_device_t* device);
+f = libairspyhf.airspyhf_is_streaming
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p]
+
+#int ADDCALL airspyhf_is_low_if(airspyhf_device_t* device); /* Tells if the current sample rate is Zero-IF (0) or Low-IF (1) */
+f = libairspyhf.airspyhf_is_low_if
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p]
+
+#int ADDCALL airspyhf_set_freq(airspyhf_device_t* device, const uint32_t freq_hz);
+f = libairspyhf.airspyhf_set_freq
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, c_uint32]
+
+#int ADDCALL airspyhf_set_freq_double(airspyhf_device_t* device, const double freq_hz);
+f = libairspyhf.airspyhf_set_freq_double
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, c_double]
+
+#int ADDCALL airspyhf_set_lib_dsp(airspyhf_device_t* device, const uint8_t flag); /* Enables/Disables the IQ Correction, IF shift and Fine Tuning. */
+f = libairspyhf.airspyhf_set_lib_dsp
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, c_uint8]
+
+#int ADDCALL airspyhf_get_samplerates(airspyhf_device_t* device, uint32_t* buffer, const uint32_t len);
+f = libairspyhf.airspyhf_get_samplerates
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, POINTER(c_uint32), c_uint32]
+
+#int ADDCALL airspyhf_set_samplerate(airspyhf_device_t* device, uint32_t samplerate);
+f = libairspyhf.airspyhf_set_samplerate
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, c_uint32]
+
+#int ADDCALL airspyhf_get_calibration(airspyhf_device_t* device, int32_t* ppb);
+f = libairspyhf.airspyhf_get_calibration
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, POINTER(c_int32)]
+
+#int ADDCALL airspyhf_set_calibration(airspyhf_device_t* device, int32_t ppb);
+f = libairspyhf.airspyhf_set_calibration
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, c_int32]
+
+#int ADDCALL airspyhf_get_vctcxo_calibration(airspyhf_device_t* device, uint16_t* vc);
+f = libairspyhf.airspyhf_get_vctcxo_calibration
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, POINTER(c_uint16)]
+
+#int ADDCALL airspyhf_set_vctcxo_calibration(airspyhf_device_t* device, uint16_t vc);
+f = libairspyhf.airspyhf_set_vctcxo_calibration
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, c_uint16]
+
+#int ADDCALL airspyhf_set_optimal_iq_correction_point(airspyhf_device_t* device, float w);
+f = libairspyhf.airspyhf_set_optimal_iq_correction_point
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, c_float]
+
+#int ADDCALL airspyhf_iq_balancer_configure(airspyhf_device_t* device, int buffers_to_skip, int fft_integration, int fft_overlap, int correlation_integration);
+f = libairspyhf.airspyhf_iq_balancer_configure
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, c_int, c_int, c_int, c_int]
+
+#int ADDCALL airspyhf_flash_calibration(airspyhf_device_t* device); /* streaming needs to be stopped */
+f = libairspyhf.airspyhf_flash_calibration
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p]
+
+#int ADDCALL airspyhf_board_partid_serialno_read(airspyhf_device_t* device, airspyhf_read_partid_serialno_t* read_partid_serialno);
+#f = libairspyhf.airspyhf_board_partid_serialno_read(
+#f.restype, f.argtypes = c_int, [airspyhf_device_t_p]
+
+#int ADDCALL airspyhf_version_string_read(airspyhf_device_t* device, char* version, uint8_t length);
+f = libairspyhf.airspyhf_version_string_read
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, c_char_p, c_uint8]
+
+#int ADDCALL airspyhf_set_user_output(airspyhf_device_t* device, airspyhf_user_output_t pin, airspyhf_user_output_state_t value);
+
+
+#int ADDCALL airspyhf_set_hf_agc(airspyhf_device_t* device, uint8_t flag); /* 0 = off, 1 = on */
+f = libairspyhf.airspyhf_set_hf_agc
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, c_uint8]
+
+#int ADDCALL airspyhf_set_hf_agc_threshold(airspyhf_device_t* device, uint8_t flag); /* when agc on: 0 = low, 1 = high */
+f = libairspyhf.airspyhf_set_hf_agc_threshold
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, c_uint8]
+
+#int ADDCALL airspyhf_set_hf_att(airspyhf_device_t* device, uint8_t value); /* Possible values: 0..8 Range: 0..48 dB Attenuation with 6 dB steps */
+f = libairspyhf.airspyhf_set_hf_att
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, c_uint8]
+
+#int ADDCALL airspyhf_set_hf_lna(airspyhf_device_t* device, uint8_t flag); /* 0 or 1: 1 to activate LNA (alias PreAmp): 1 = +6 dB gain - compensated in digital */
+f = libairspyhf.airspyhf_set_hf_lna
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p, c_uint8]
+
+f = libairspyhf.py_test
+f.restype, f.argtypes = None, []
+
+f = libairspyhf.py_cb_wrapper
+f.restype, f.argtypes = c_int, [airspyhf_device_t_p]
+
+f = libairspyhf.py_test_cb
+f.restype, f.argtypes = c_int, [airspyhf_sample_block_cb_fn]
+
+
+__all__ = ["libairspyhf", "airspyhf_lib_version_t", "airspyhf_device_t_p", "airspyhf_sample_block_cb_fn"] \ No newline at end of file
diff --git a/test.py b/test.py
new file mode 100644
index 0000000..8a70a14
--- /dev/null
+++ b/test.py
@@ -0,0 +1,150 @@
+import os
+import airspyhf
+from ctypes import *
+import time
+import sys
+import wave
+import struct
+
+print("Check airspyHF version")
+
+p = airspyhf.airspyhf_lib_version_t()
+print(airspyhf.libairspyhf.airspyhf_lib_version(byref(p)))
+print(p.major_version)
+print(p.minor_version)
+print(p.revision)
+
+print("Get list of devices if there is any")
+ndev = airspyhf.libairspyhf.airspyhf_list_devices(None,0)
+print("Found %d devices"%(ndev))
+
+for devi in range(0,ndev):
+ serial = c_uint64(0)
+ airspyhf.libairspyhf.airspyhf_list_devices(byref(serial),devi+1)
+ print("Device %d: Serial number %s"%(int(devi),hex(serial.value) ))
+
+print("try to open device")
+#device = POINTER(c_void_p)
+#device_p = device()
+dev_p = airspyhf.airspyhf_device_t_p(None)
+ret = airspyhf.libairspyhf.airspyhf_open_sn(dev_p,0x3b52ab5dada12535)
+print("open_sn: Returned %d"%(ret))
+if (ret != 0):
+ print("airspyhf_open_sn returned != 0, error")
+ sys.exit()
+
+print("List sample rates")
+nsrates = c_uint32(0)
+
+ret = airspyhf.libairspyhf.airspyhf_get_samplerates(dev_p,byref(nsrates),c_uint32(0))
+print("ret %d"%ret)
+print("sample rates %d"% nsrates.value)
+
+supportet_samplerates = (c_uint32*4)(0)
+ret = airspyhf.libairspyhf.airspyhf_get_samplerates(dev_p,supportet_samplerates,nsrates)
+print("ret %d"%ret)
+for i in range(0,nsrates.value):
+ print("Sample rates %d"% supportet_samplerates[i])
+
+#try to get some samples
+ret = airspyhf.libairspyhf.airspyhf_set_samplerate(dev_p, supportet_samplerates[3])
+print(f"airspyhf_set_samplerate ret={ret}")
+
+ret = airspyhf.libairspyhf.airspyhf_set_hf_agc(dev_p, 1)
+print(f"airspyhf_set_hf_agc ret={ret}")
+
+ret = airspyhf.libairspyhf.airspyhf_set_hf_agc_threshold(dev_p, 0)
+print(f"airspyhf_set_hf_agc_threshold ret={ret}")
+
+
+class CBthread:
+ def __init__(self,dev_p):
+ self.dev_p = dev_p
+ self.read_samples_cb = None
+
+ def read_samples(self, transfer):
+ print("we here")
+ return 0
+
+ def start(self):
+ self.read_samples_cb = airspyhf.airspyhf_sample_block_cb_fn(self.read_samples)
+ ret = airspyhf.libairspyhf.airspyhf_start(self.dev_p, self.read_samples_cb, None)
+ print(f"airspyhf_start ret={ret}")
+
+ def wait(self):
+ print("wait called")
+
+sample_count = 0
+wave_file = wave.open("record.wav","w")
+wave_file.setnchannels(2)
+wave_file.setsampwidth(4)
+wave_file.setframerate(supportet_samplerates[1])
+#@CFUNCTYPE(c_int, airspyhf.airspyhf_transfer_t_p)
+#@PYFUNCTYPE(c_int, airspyhf.airspyhf_transfer_t_p)
+def read_samples(transfer):
+ global sample_count
+ global wave_file
+ #print("Python call back")
+ t = transfer.contents
+ bytes_to_write = t.sample_count * 4 * 2
+ rx_buffer = t.samples
+ #print(f"{bytes_to_write} bytes receieved")
+ sample_count += t.sample_count
+ for i in range(0,t.sample_count):
+ d_re = t.samples[i].re
+ d_im = t.samples[i].im
+ data = struct.pack("<f",d_re) # FIX ?!
+ wave_file.writeframesraw(data)
+ data = struct.pack("<f", d_im) # FIX ?!
+ wave_file.writeframesraw(data)
+ #print("End call back")
+ return 0
+
+
+#th = CBthread(dev_p)
+#th.start()
+
+read_samples_cb = airspyhf.airspyhf_sample_block_cb_fn(read_samples)
+
+print(read_samples)
+print(read_samples_cb)
+
+
+ret = airspyhf.libairspyhf.airspyhf_start(dev_p, airspyhf.airspyhf_sample_block_cb_fn(read_samples), None)
+print(f"airspyhf_start ret={ret}")
+
+#ret = airspyhf.libairspyhf.py_cb_wrapper(dev_p)
+#print(f"airspyhf_start ret={ret}")
+
+
+ret = airspyhf.libairspyhf.airspyhf_set_freq(dev_p, 3865000)
+print(f"airspyhf_set_freq ret={ret}")
+
+count = 0
+try:
+ while (airspyhf.libairspyhf.airspyhf_is_streaming(dev_p)) and (count < 3):
+ print("Main loop")
+ time.sleep(1)
+ count += 1
+except:
+ print("Error in main loop")
+
+ret = airspyhf.libairspyhf.airspyhf_stop(dev_p)
+print(f"airspyhf_stop ret={ret}")
+
+#Not close for now
+ret = airspyhf.libairspyhf.close(dev_p)
+print("closed: Returned %d"%(ret))
+
+print(f"Total samples received {sample_count}")
+
+airspyhf.libairspyhf.py_test()
+
+airspyhf.libairspyhf.py_test_cb(read_samples_cb)
+
+wave_file.close()
+
+print("All is ok")
+
+#th.wait()
+