summaryrefslogtreecommitdiff
path: root/Radio
diff options
context:
space:
mode:
Diffstat (limited to 'Radio')
-rw-r--r--Radio/HW/AirSpyHF/AirSpyHF.swift112
-rw-r--r--Radio/HW/AirSpyHF/src/airspyhf.c11
-rw-r--r--Radio/HW/AirSpyHF/src/airspyhf.h66
-rw-r--r--Radio/Utils/AirSpyHFIQ/main.swift147
-rw-r--r--Radio/Utils/AirSpyIQ/main.swift11
-rw-r--r--Radio/Utils/RtlSdrIQ/main.swift1
-rw-r--r--Radio/Utils/TestAirSpy/main.swift2
-rw-r--r--Radio/Utils/TestAirSpyHF/main.swift19
-rw-r--r--Radio/Utils/TestBladeRF/main.swift2
-rw-r--r--Radio/Utils/TestRtlSdr/main.swift2
10 files changed, 359 insertions, 14 deletions
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<airspyhf_device_t>? = .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<UInt64> = .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<UInt32>.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<UInt32>.allocate(capacity: Int(nsrate.pointee))
+ let rawPointer = UnsafeMutablePointer<UInt32>?(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..<nsrate.pointee {
+ sample_rates.append(sampleBuffer[Int(idx)])
+ }
+
+ return sample_rates
+ }
+
+ func setSampleRate(_ samplerate:UInt32) -> 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 <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -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 <stdbool.h>
#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "libusb.h"
+#include <pthread.h>
+#include <math.h>
#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);
diff --git a/Radio/Utils/AirSpyHFIQ/main.swift b/Radio/Utils/AirSpyHFIQ/main.swift
new file mode 100644
index 0000000..6fc7501
--- /dev/null
+++ b/Radio/Utils/AirSpyHFIQ/main.swift
@@ -0,0 +1,147 @@
+//
+// main.swift
+// AirSpyHFIQ
+//
+// Created by Jacky Jack on 02/12/2024.
+//
+
+import Foundation
+import ArgumentParser
+import libairspyhf
+
+//set the command line arguments
+struct CommandLineArgs: ParsableCommand {
+ @Argument var file:String = ""
+ @Option(name:.shortAndLong) var device_idx: Int = 0
+ @Option(name:.shortAndLong) var samplerate: Int = 192000
+ @Option(name:.shortAndLong) var gain: Int = 0
+ @Option(name:.shortAndLong) var frequency: Int = 100000000
+ @Option(name:.shortAndLong) var nsamples: Int = 1024
+ @Flag(help:"Version \(software_version)") var version: Bool = false
+ @Flag(name: .shortAndLong) var verbose: Bool = false
+}
+
+let args = CommandLineArgs.parseOrExit()
+
+if (args.version) {
+ print("AirSpyHFIQ version \(software_version)")
+ exit(0)
+}
+
+var libersion:airspyhf_lib_version_t = airspyhf_lib_version_t()
+
+airspyhf_lib_version(&libersion)
+print("libairspyhf \(libersion.major_version).\(libersion.minor_version).\(libersion.revision)")
+
+let ndev = airspyhf_list_devices(nil, 0)
+print("Found \(ndev) AirSpyHF devices")
+if ndev < 0 {
+ exit(0)
+}
+
+//prepare file descriptor if args specify that
+let currentExePath = Process().currentDirectoryPath
+var fileDescriptor = FileManager.default
+var fileArgUrl:URL?
+var fileHandle:FileHandle?
+if (args.file != "") {
+ fileArgUrl = URL(fileURLWithFileSystemRepresentation: args.file, isDirectory: false, relativeTo: nil)
+ if (checkIfFileExists(args.file)) {
+ //remove file
+ do {
+ try fileDescriptor.removeItem(atPath: fileArgUrl!.path())
+ } catch {
+ print("Couldn't delete file that exists \(fileArgUrl!.path())")
+ }
+ }
+
+ //create file
+ fileDescriptor.createFile(atPath: fileArgUrl!.path(), contents: nil)
+ try fileHandle = FileHandle(forWritingTo: fileArgUrl!)
+ try fileHandle?.seekToEnd()
+}
+
+//will try the first one first
+var device:AirSpyHF?
+do {
+ device = try AirSpyHF(idx: 0)
+} catch {
+ print("Cant attach to device")
+}
+
+let samplerates = device!.getSampleRates()
+print(samplerates)
+
+if (!samplerates.contains(UInt32(args.samplerate))) {
+ print("Unsupported sample rate")
+ exit(0)
+}
+
+//set sample rate
+var fret:Int32 = -1
+fret = device!.setSampleRate(UInt32(args.samplerate))
+print("samplerate err=\(fret)")
+fret = device!.setFreq(UInt32(args.frequency))
+print("setfreq err=\(fret)")
+fret = device!.setHfAgc(1)
+print("sethfagc err=\(fret)")
+fret = device!.setHfAgcThreshold(0)
+print("agcthreshold err=\(fret)")
+fret = device!.setHfLNA(1)
+print("hflna err=\(fret)")
+
+var sdr_run = true
+var total_samples:Int32=0
+func rf_callback(_ transffer: UnsafeMutablePointer<airspyhf_transfer_t>?) -> Int32 {
+
+ let sample_count = transffer?.pointee.sample_count
+ let rx_bufffer = transffer?.pointee.samples
+ // samples are = float * IQ (I and Q)
+ let bytes_to_write = sample_count! * 4 * 2
+
+ total_samples += sample_count!
+ if total_samples > args.nsamples {
+ sdr_run = false
+ return 0
+ }
+
+ if let file = fileHandle {
+ let convertedData = Data(bytes: rx_bufffer!, count: Int(bytes_to_write))
+ do {
+ try file.write(contentsOf: convertedData)
+ } catch {
+ print("Cant dump data to file")
+ }
+ }
+
+ return 0
+}
+
+let _ = device!.start(rf_callback)
+
+let _ = device!.setFreq(UInt32(args.frequency))
+
+var count=3
+var old_total:Int32=1
+while ((device!.isStreaming() == 1) && (sdr_run == true)) {
+ //print("Streaming ... total \(total_samples) bytes")
+ //check till the number of samples are written to file or aquired
+ sleep(1)
+ if (old_total == total_samples) {
+ count += 1
+ } else {
+ count = 0
+ }
+ old_total = total_samples
+ if (count > 10) {
+ break
+ }
+}
+
+let _ = device!.stop()
+
+print("Closing device. Read \(total_samples) samples")
+device!.close()
+
+
+
diff --git a/Radio/Utils/AirSpyIQ/main.swift b/Radio/Utils/AirSpyIQ/main.swift
new file mode 100644
index 0000000..2d6f0fd
--- /dev/null
+++ b/Radio/Utils/AirSpyIQ/main.swift
@@ -0,0 +1,11 @@
+//
+// main.swift
+// AirSpyIQ
+//
+// Created by Jacky Jack on 02/12/2024.
+//
+
+import Foundation
+import ArgumentParser
+import libairspy
+
diff --git a/Radio/Utils/RtlSdrIQ/main.swift b/Radio/Utils/RtlSdrIQ/main.swift
index c3d5732..227f222 100644
--- a/Radio/Utils/RtlSdrIQ/main.swift
+++ b/Radio/Utils/RtlSdrIQ/main.swift
@@ -19,6 +19,7 @@ struct CommandLineArgs: ParsableCommand {
@Option(name:.shortAndLong) var gain: Int = 0
@Option(name:.shortAndLong) var frequency: Int = 100000000
@Option(name:.shortAndLong) var nsamples: Int = 1024
+ @Flag(help:"Version \(software_version)") var version: Bool = false
@Flag(name: .shortAndLong) var verbose: Bool = false
@Flag(name: .shortAndLong) var async: Bool = false
}
diff --git a/Radio/Utils/TestAirSpy/main.swift b/Radio/Utils/TestAirSpy/main.swift
index 8ec4ede..13b37d2 100644
--- a/Radio/Utils/TestAirSpy/main.swift
+++ b/Radio/Utils/TestAirSpy/main.swift
@@ -9,5 +9,5 @@ import Foundation
import libairspy
-print("Hello, World!")
+print("Version \(software_version)")
airspy_init()
diff --git a/Radio/Utils/TestAirSpyHF/main.swift b/Radio/Utils/TestAirSpyHF/main.swift
index 24a74f8..8166f2b 100644
--- a/Radio/Utils/TestAirSpyHF/main.swift
+++ b/Radio/Utils/TestAirSpyHF/main.swift
@@ -8,8 +8,23 @@
import Foundation
import libairspyhf
-print("Hello, World!")
+print("Version \(software_version)")
var libersion:airspyhf_lib_version_t = airspyhf_lib_version_t()
airspyhf_lib_version(&libersion)
-print("\(libersion.major_version)")
+print("libairspyhf \(libersion.major_version).\(libersion.minor_version).\(libersion.revision)")
+
+let ndev = airspyhf_list_devices(nil, 0)
+print("Found \(ndev) AirSpyHF devices")
+if ndev < 0 {
+ exit(0)
+}
+
+for i in 0..<ndev {
+ let serialPtr: UnsafeMutablePointer<UInt64> = .allocate(capacity: 1)
+ airspyhf_list_devices(serialPtr, i+1)
+
+ print("Device \(i): \(serialPtr.pointee)")
+}
+
+
diff --git a/Radio/Utils/TestBladeRF/main.swift b/Radio/Utils/TestBladeRF/main.swift
index f728832..62246e3 100644
--- a/Radio/Utils/TestBladeRF/main.swift
+++ b/Radio/Utils/TestBladeRF/main.swift
@@ -8,7 +8,7 @@
import Foundation
import libbladerf
-print("Hello, World!")
+print("Version \(software_version)")
var version:bladerf_version = bladerf_version()
bladerf_version(&version)
diff --git a/Radio/Utils/TestRtlSdr/main.swift b/Radio/Utils/TestRtlSdr/main.swift
index 39e1c06..3eb2830 100644
--- a/Radio/Utils/TestRtlSdr/main.swift
+++ b/Radio/Utils/TestRtlSdr/main.swift
@@ -8,7 +8,7 @@
import Foundation
import libr820
-
+print("Version \(software_version)")
let count = getDeviceCount()
print("Found \(count) r820 devices")
//rtldev.open(index: 0)