From 23fc08c8798d7c325a72fbee4175813efe4fe70f Mon Sep 17 00:00:00 2001 From: Arturs Artamonovs Date: Fri, 29 Nov 2024 11:28:01 +0000 Subject: RtlSdrIQ: can read samples from rtlsdr and dump those to file --- Radio/HW/RtlSdr/r820/r820.swift | 9 +++-- Radio/Utils/RtlSdrIQ/main.swift | 77 ++++++++++++++++++++++++++++++++++++----- 2 files changed, 76 insertions(+), 10 deletions(-) (limited to 'Radio') diff --git a/Radio/HW/RtlSdr/r820/r820.swift b/Radio/HW/RtlSdr/r820/r820.swift index 3f6d4a9..4c8859f 100644 --- a/Radio/HW/RtlSdr/r820/r820.swift +++ b/Radio/HW/RtlSdr/r820/r820.swift @@ -189,8 +189,13 @@ public class R820Tuner { /// - 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 + /// on success, the number of bytes actually transferred + /// LIBUSB_ERROR_TIMEOUT if the transfer timed out + /// LIBUSB_ERROR_PIPE if the control request was not supported by the device + /// LIBUSB_ERROR_NO_DEVICE if the device has been disconnected + /// LIBUSB_ERROR_BUSY if called from event handling context + /// LIBUSB_ERROR_INVALID_PARAM if the transfer size is larger than the operating system and/or hardware can support (see Transfer length limitations) + /// another LIBUSB_ERROR code on other failures /// func readSync(buf:UnsafeMutableRawPointer?,len: Int32,n_read:UnsafeMutablePointer?) -> Int32 { return rtlsdr_read_sync(dev, buf, len, n_read); diff --git a/Radio/Utils/RtlSdrIQ/main.swift b/Radio/Utils/RtlSdrIQ/main.swift index 20573a9..c3d5732 100644 --- a/Radio/Utils/RtlSdrIQ/main.swift +++ b/Radio/Utils/RtlSdrIQ/main.swift @@ -9,13 +9,15 @@ import Foundation import libr820 import ArgumentParser +let NUM_SAMPLES=1024 + //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 frequency: Int = 100000000 @Option(name:.shortAndLong) var nsamples: Int = 1024 @Flag(name: .shortAndLong) var verbose: Bool = false @Flag(name: .shortAndLong) var async: Bool = false @@ -40,6 +42,7 @@ if (args.device_idx < 0) || (args.device_idx > count-1) { let device = R820Tuner() device.open(index: UInt32(args.device_idx)) +//prepare dongle to receive some data let _ = device.setSampleRate(samplerate: UInt32(args.samplerate)) let _ = device.setCenterFreq(freq: UInt32(args.frequency)) if args.gain == 0 { @@ -48,15 +51,73 @@ if args.gain == 0 { let _ = device.setTunerGain(gain: Int32(args.gain)) } let _ = device.resetBuffer() -let buf_ptr = UnsafeMutableRawPointer.allocate(byteCount: args.nsamples, alignment: 1) + +//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() +} + +//prepare loop buffers to process data +let buf_ptr = UnsafeMutableRawPointer.allocate(byteCount: NUM_SAMPLES, 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..