From 77d1cfc27fb72e442b8d8e5cbe2be143723724e5 Mon Sep 17 00:00:00 2001 From: Arturs Artamonovs Date: Thu, 28 Nov 2024 11:37:28 +0000 Subject: RtlSdrIQ: read samples from device. Using command line arguments --- PrySDR/main.swift | 5 +++ Radio/HW/RtlSdr/r820/r820.swift | 79 +++++++++++++++++++++++++-------------- Radio/Utils/RtlSdrIQ/main.swift | 62 ++++++++++++++++++++++++++++++ Radio/Utils/TestRtlSdr/main.swift | 14 +++++-- 4 files changed, 128 insertions(+), 32 deletions(-) create mode 100644 Radio/Utils/RtlSdrIQ/main.swift diff --git a/PrySDR/main.swift b/PrySDR/main.swift index 47bdc00..33f0e1d 100644 --- a/PrySDR/main.swift +++ b/PrySDR/main.swift @@ -6,6 +6,11 @@ // import Foundation +import libr820 +import libairspy +import libairspyhf +import libbladerf print("PrySDR") +print("We will start soon on exploring things") diff --git a/Radio/HW/RtlSdr/r820/r820.swift b/Radio/HW/RtlSdr/r820/r820.swift index f5e1177..3f6d4a9 100644 --- a/Radio/HW/RtlSdr/r820/r820.swift +++ b/Radio/HW/RtlSdr/r820/r820.swift @@ -6,14 +6,45 @@ // //https://www.kodeco.com/7181017-unsafe-swift-using-pointers-and-interacting-with-c +// THis is just a wrapper for fun + import Foundation -//import TestRtlSdr import libr820 + +/// Gets the number of rtlsdr's detected in system +/// - Returns: return number of devices detected +/// +func getDeviceCount() -> UInt32 { + return rtlsdr_get_device_count() +} + +/// Search for device index from serial number +/// - Parameters: +/// - serial: serial string of device +/// - Returns: return the index number if found, -1 if not found +/// +func getIndexBySerial(serial: String) -> Int32 +{ + return rtlsdr_get_index_by_serial(serial);//is this ok? +} + +//TODO: investigate getDeviceName +/* +func getDeviceName(index: UInt32) -> String { + return rtlsdr_get_device_name(index) +}*/ + +//TODO: investigate getDeviceUsbString + +/* + func getDeviceUsbString() { + return rtlsdr_get_device_usb_strings(); + }*/ + +/// Wrapper for librtlsdr functions that's not operating on device public class R820API { - - func R820() { print("Start device API") } @@ -21,24 +52,23 @@ public class R820API { func getDeviceCount() -> UInt32 { return rtlsdr_get_device_count() } - - - } +/// Wrapper for rtlsdr that works with device API public class R820Tuner { var deviceInitalized:Bool = false var dev: OpaquePointer? = nil /** - Function to initialise tunner - - Parameters: - - + Function to initialise tunner, do nothing at the moment */ func R820Tuner() { print("Initialise tunner") } + /// open device by Index, checks if device allready were initialised within class + /// - Parameters: + /// - index: device index to open func open(index devId: UInt32) { let err = rtlsdr_open(&dev,devId) if (err != 0) { @@ -48,6 +78,7 @@ public class R820Tuner { deviceInitalized = true } + /// close device if it was opened before func close() { if self.deviceInitalized { rtlsdr_close(dev); @@ -55,25 +86,6 @@ public class R820Tuner { } } - func getDeviceCount()->UInt32 { - return rtlsdr_get_device_count(); - } - - /* - func getDeviceName(index: UInt32) -> String { - return rtlsdr_get_device_name(index) - } - */ - - /* - func getDeviceUsbString() { - return rtlsdr_get_device_usb_strings(); - }*/ - func getIndexBySerial(serial: String) -> Int32 - { - return rtlsdr_get_index_by_serial(serial);//is this ok? - } - func setXtalFreq(rtlFreq: UInt32, tunnerFreq: UInt32) -> Int32 { return rtlsdr_set_xtal_freq(dev, rtlFreq, tunnerFreq); } @@ -171,6 +183,15 @@ public class R820Tuner { return rtlsdr_reset_buffer(dev) } + /// Read the data from buffer in sync manner + /// - Parameters: + /// - buf: input buffer + /// - len: input buffer length + /// - n_read: number of bytes received + /// - Returns: -1 if there is no device, 0 on success or one of LIBUSB error + /// LIBUSB_ERROR_TIMEOUT, LIBUSB_ERROR_PIPE,LIBUSB_ERROR_OVERFLOW + /// LIBUSB_ERROR_NO_DEVICE, LIBUSB_ERROR_BUSY LIBUSB_ERROR_INVALID_PARAM + /// func readSync(buf:UnsafeMutableRawPointer?,len: Int32,n_read:UnsafeMutablePointer?) -> Int32 { return rtlsdr_read_sync(dev, buf, len, n_read); } @@ -183,6 +204,8 @@ public class R820Tuner { return rtlsdr_read_async(dev, cb, ctx, buf_num, buf_len) } + /// Cancel async operation for sighandlders + /// to exit from callbacks func cancelAsync() -> Int32 { return rtlsdr_cancel_async(dev); } diff --git a/Radio/Utils/RtlSdrIQ/main.swift b/Radio/Utils/RtlSdrIQ/main.swift new file mode 100644 index 0000000..20573a9 --- /dev/null +++ b/Radio/Utils/RtlSdrIQ/main.swift @@ -0,0 +1,62 @@ +// +// main.swift +// RtlSdrIQ +// +// Created by Jacky Jack on 27/11/2024. +// + +import Foundation +import libr820 +import ArgumentParser + +//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 = 2048000 + @Option(name:.shortAndLong) var gain: Int = 0 + @Option(name: .shortAndLong) var frequency: Int = 100000000 + @Option(name:.shortAndLong) var nsamples: Int = 1024 + @Flag(name: .shortAndLong) var verbose: Bool = false + @Flag(name: .shortAndLong) var async: Bool = false +} + +let args = CommandLineArgs.parseOrExit() + +//check that there is any devices +let count = getDeviceCount() +if count < 1 { + print("There is not R820 tunner found on this machine") + exit(0) +} + +//check that argument index is withing range +if (args.device_idx < 0) || (args.device_idx > count-1) { + print("Index is out of range, devices found \(count)") + exit(0) +} + +//initialise structure without a connected driver +let device = R820Tuner() +device.open(index: UInt32(args.device_idx)) + +let _ = device.setSampleRate(samplerate: UInt32(args.samplerate)) +let _ = device.setCenterFreq(freq: UInt32(args.frequency)) +if args.gain == 0 { + let _ = device.setAgcMode(on: 1) +} else { + let _ = device.setTunerGain(gain: Int32(args.gain)) +} +let _ = device.resetBuffer() +let buf_ptr = UnsafeMutableRawPointer.allocate(byteCount: args.nsamples, alignment: 1) +var nbytes:Int32 = 0 +let r = device.readSync(buf: buf_ptr, len: Int32(args.nsamples), n_read: &nbytes) +print("Reading samples return code (\(r)) read \(nbytes) bytes\n") +for i in 0..