From abbe14bebb2935b017b980e6fc2bfc5e94052049 Mon Sep 17 00:00:00 2001 From: Arturs Artamonovs Date: Wed, 4 Dec 2024 11:07:17 +0000 Subject: AirSpyHFIQ: read samples from airspyhf and dump those to fc32 file --- Radio/HW/AirSpyHF/AirSpyHF.swift | 112 ++++++++++++++++++++++++++++++++++++++- Radio/HW/AirSpyHF/src/airspyhf.c | 11 ++-- Radio/HW/AirSpyHF/src/airspyhf.h | 66 +++++++++++++++++++++++ 3 files changed, 180 insertions(+), 9 deletions(-) (limited to 'Radio/HW/AirSpyHF') diff --git a/Radio/HW/AirSpyHF/AirSpyHF.swift b/Radio/HW/AirSpyHF/AirSpyHF.swift index 3affcff..ea835af 100644 --- a/Radio/HW/AirSpyHF/AirSpyHF.swift +++ b/Radio/HW/AirSpyHF/AirSpyHF.swift @@ -7,9 +7,117 @@ import libairspyhf +enum AirspyHFError: Error { + case InvalidDevice +} + /// Wrapper for libairspyhf library class AirSpyHF { - init() { - //airspyhf_ + + var dev:UnsafeMutablePointer? = .allocate(capacity: 1) + + /* + init() { + + }*/ + + /// Initialise by index + init(idx: Int32) throws { + let ndev = airspyhf_list_devices(nil, 0) + if ((idx < 0) || (idx >= ndev)) { + throw AirspyHFError.InvalidDevice + } + let serialPtr: UnsafeMutablePointer = .allocate(capacity: 1) + airspyhf_list_devices(serialPtr, idx+1) + if serialPtr.pointee == 0 { + print("Cant get serial number of device index \(idx)") + throw AirspyHFError.InvalidDevice + } + try openSN(serial: serialPtr.pointee) + + } + + func openSN(serial: UInt64) throws { + let ret = airspyhf_open_sn(&dev, serial) + print("ret=\(ret)") + if (ret != AIRSPYHF_SUCCESS.rawValue) { + print("Cant open device with serial numner \(serial)") + throw AirspyHFError.InvalidDevice + } + } + + /* + /// Initialise by serial number + init(serial: UInt64) { + + }*/ + + func getSampleRates() -> [UInt32] { + var sample_rates:[UInt32] = [] + var ret: Int32 + + let nsrate = UnsafeMutablePointer.allocate(capacity: 1) + ret = airspyhf_get_samplerates(dev, nsrate, 0) + if ret == AIRSPYHF_ERROR.rawValue { + print("Error uptaining the sample number") + return [] + } + + let sampleBuffer = UnsafeMutableBufferPointer.allocate(capacity: Int(nsrate.pointee)) + let rawPointer = UnsafeMutablePointer?(sampleBuffer.baseAddress!) + ret = airspyhf_get_samplerates(dev, rawPointer, nsrate.pointee) + if (ret == AIRSPYHF_ERROR.rawValue) { + print("Error geting sample rates. Not processed") + } + print("Found \(nsrate.pointee) samplerates") + for idx in 0.. Int32 { + let ret = airspyhf_set_samplerate(dev, samplerate) + return ret + } + + func setHfAgc(_ flag: UInt8) -> Int32{ + let ret = airspyhf_set_hf_agc(dev, flag) + return ret + } + + func setHfAgcThreshold(_ flag: UInt8) -> Int32 { + let ret = airspyhf_set_hf_agc_threshold(dev, flag) + return ret + } + + func setHfLNA(_ flag: UInt8) -> Int32 { + let ret = airspyhf_set_hf_lna(dev, flag) + return ret + } + + func start(_ callback: airspyhf_sample_block_cb_fn) -> Int32 { + let ret = airspyhf_start(dev, callback, nil) + return ret + } + + func stop() -> Int32 { + let ret = airspyhf_stop(dev) + return ret + } + + func setFreq(_ frequency: UInt32) -> Int32 { + let ret = airspyhf_set_freq(dev, frequency) + return ret + } + + func isStreaming() -> Int32 { + let ret = airspyhf_is_streaming(dev) + return ret + } + + func close() { + airspyhf_close(dev) } } diff --git a/Radio/HW/AirSpyHF/src/airspyhf.c b/Radio/HW/AirSpyHF/src/airspyhf.c index efacd03..c5ca337 100644 --- a/Radio/HW/AirSpyHF/src/airspyhf.c +++ b/Radio/HW/AirSpyHF/src/airspyhf.c @@ -28,6 +28,7 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI #define _CRT_SECURE_NO_WARNINGS #endif +#include #include #include #include @@ -55,9 +56,9 @@ typedef int bool; #define SAMPLES_TO_TRANSFER (1024 * 2) #define SERIAL_NUMBER_UNUSED (0) #define FILE_DESCRIPTOR_UNUSED (-1) -#define RAW_BUFFER_COUNT (8) #define AIRSPYHF_SERIAL_SIZE (28) + #define MAX_SAMPLERATE_INDEX (100) #define DEFAULT_SAMPLERATE (768000) @@ -81,15 +82,10 @@ static const char str_prefix_serial_airspyhf[STR_PREFIX_SERIAL_AIRSPYHF_SIZE] = #define IQ_BALANCER_EVAL_SKIP (RAW_BUFFER_COUNT) -#pragma pack(push,1) -typedef struct { - int16_t im; - int16_t re; -} airspyhf_complex_int16_t; -#pragma pack(pop) +/* typedef struct airspyhf_device { libusb_context* usb_context; @@ -136,6 +132,7 @@ typedef struct airspyhf_device airspyhf_complex_float_t *output_buffer; void* ctx; } airspyhf_device_t; +*/ typedef struct flash_config { diff --git a/Radio/HW/AirSpyHF/src/airspyhf.h b/Radio/HW/AirSpyHF/src/airspyhf.h index 2879120..d58a84a 100644 --- a/Radio/HW/AirSpyHF/src/airspyhf.h +++ b/Radio/HW/AirSpyHF/src/airspyhf.h @@ -26,7 +26,14 @@ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSI #ifndef __AIRSPYHF_H__ #define __AIRSPYHF_H__ +#include #include +#include +#include +#include +#include "libusb.h" +#include +#include #define AIRSPYHF_VERSION "1.8.0" #define AIRSPYHF_VER_MAJOR 1 @@ -61,6 +68,8 @@ extern "C" { #endif +#define RAW_BUFFER_COUNT (8) + enum airspyhf_error { AIRSPYHF_SUCCESS = 0, @@ -86,6 +95,13 @@ enum airspyhf_board_id AIRSPYHF_BOARD_ID_INVALID = 0xFF, }; +#pragma pack(push,1) +typedef struct { + int16_t im; + int16_t re; +} airspyhf_complex_int16_t; +#pragma pack(pop) + typedef struct airspyhf_device airspyhf_device_t; typedef struct { @@ -96,6 +112,7 @@ typedef struct { uint64_t dropped_samples; } airspyhf_transfer_t; + typedef struct { uint32_t major_version; uint32_t minor_version; @@ -107,6 +124,55 @@ typedef struct { typedef int (*airspyhf_sample_block_cb_fn) (airspyhf_transfer_t* transfer_fn); + + +typedef struct airspyhf_device +{ + libusb_context* usb_context; + libusb_device_handle* usb_device; + struct libusb_transfer** transfers; + airspyhf_sample_block_cb_fn callback; + pthread_t transfer_thread; + pthread_t consumer_thread; + bool transfer_thread_running; + bool consumer_thread_running; + pthread_cond_t consumer_cv; + pthread_mutex_t consumer_mp; + uint32_t supported_samplerate_count; + uint32_t *supported_samplerates; + uint8_t *samplerate_architectures; + uint32_t supported_att_step_count; + float *supported_att_steps; + volatile uint32_t current_samplerate; + volatile double freq_hz; + volatile uint32_t freq_khz; + volatile double freq_delta_hz; + volatile double freq_shift; + volatile int32_t calibration_ppb; + volatile int32_t calibration_vctcxo; + volatile uint32_t frontend_options; + volatile float optimal_point; + uint8_t enable_dsp; + uint8_t is_low_if; + float filter_gain; + airspyhf_complex_float_t vec; + struct iq_balancer_t *iq_balancer; + volatile int32_t iq_balancer_eval_skip; + uint32_t transfer_count; + int32_t transfer_live; + uint32_t buffer_size; + uint32_t dropped_buffers; + uint32_t dropped_buffers_queue[RAW_BUFFER_COUNT]; + airspyhf_complex_int16_t *received_samples_queue[RAW_BUFFER_COUNT]; + volatile bool streaming; + volatile bool stop_requested; + volatile int received_samples_queue_head; + volatile int received_samples_queue_tail; + volatile int received_buffer_count; + airspyhf_complex_float_t *output_buffer; + void* ctx; +} airspyhf_device_t; + extern ADDAPI void ADDCALL airspyhf_lib_version(airspyhf_lib_version_t* lib_version); extern ADDAPI int ADDCALL airspyhf_list_devices(uint64_t *serials, int count); extern ADDAPI int ADDCALL airspyhf_open(airspyhf_device_t** device); -- cgit v1.2.3