summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArturs Artamonovs <arturs.artamonovs@protonmail.com>2024-11-29 11:28:01 +0000
committerArturs Artamonovs <arturs.artamonovs@protonmail.com>2024-11-29 11:28:01 +0000
commit23fc08c8798d7c325a72fbee4175813efe4fe70f (patch)
tree0521f11441d267e60f7b9aa574c0defd43148b45
parent77d1cfc27fb72e442b8d8e5cbe2be143723724e5 (diff)
downloadPrySDR-23fc08c8798d7c325a72fbee4175813efe4fe70f.tar.gz
PrySDR-23fc08c8798d7c325a72fbee4175813efe4fe70f.zip
RtlSdrIQ: can read samples from rtlsdr and dump those to file
-rw-r--r--PrySDR.xcodeproj/project.pbxproj144
-rw-r--r--Radio/HW/RtlSdr/r820/r820.swift9
-rw-r--r--Radio/Utils/RtlSdrIQ/main.swift77
-rw-r--r--Utils/FileUtils.swift18
-rw-r--r--Utils/PathUtils.swift13
5 files changed, 251 insertions, 10 deletions
diff --git a/PrySDR.xcodeproj/project.pbxproj b/PrySDR.xcodeproj/project.pbxproj
index 634f2b7..9e31fe4 100644
--- a/PrySDR.xcodeproj/project.pbxproj
+++ b/PrySDR.xcodeproj/project.pbxproj
@@ -13,6 +13,7 @@
buildPhases = (
);
dependencies = (
+ 8D4068282CF88CCF0064C96D /* PBXTargetDependency */,
8D876E8D2CD4DBE80082EC54 /* PBXTargetDependency */,
8D876E8B2CD4DBE50082EC54 /* PBXTargetDependency */,
8D876E892CD4DBE20082EC54 /* PBXTargetDependency */,
@@ -26,6 +27,9 @@
/* End PBXAggregateTarget section */
/* Begin PBXBuildFile section */
+ 8D0349252CF70E220026DA77 /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = 8D0349242CF70E220026DA77 /* ArgumentParser */; };
+ 8D4068242CF8619B0064C96D /* libr820.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D5A5DB42CD4B70D0096CBD7 /* libr820.a */; };
+ 8D4068252CF8619F0064C96D /* libusb.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D5A5DDA2CD4B9100096CBD7 /* libusb.a */; };
8D5A5DAD2CD439D70096CBD7 /* libairspy.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D5A5D752CD436BC0096CBD7 /* libairspy.a */; };
8D5A5DAE2CD439DA0096CBD7 /* libairspyhf.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D5A5D9F2CD439360096CBD7 /* libairspyhf.a */; };
8D5A5DF02CD4B97E0096CBD7 /* libusb.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D5A5DDA2CD4B9100096CBD7 /* libusb.a */; };
@@ -46,6 +50,13 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
+ 8D4068272CF88CCF0064C96D /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 8DD98C392CC592540062D678 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8D0349172CF70DCD0026DA77;
+ remoteInfo = RtlSdrIQ;
+ };
8D5A5E1E2CD4C18D0096CBD7 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8DD98C392CC592540062D678 /* Project object */;
@@ -126,6 +137,15 @@
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
+ 8D0349162CF70DCD0026DA77 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
8D5A5E062CD4BAF10096CBD7 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -174,6 +194,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
+ 8D0349182CF70DCD0026DA77 /* RtlSdrIQ */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = RtlSdrIQ; sourceTree = BUILT_PRODUCTS_DIR; };
8D5A5D752CD436BC0096CBD7 /* libairspy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libairspy.a; sourceTree = BUILT_PRODUCTS_DIR; };
8D5A5D9F2CD439360096CBD7 /* libairspyhf.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libairspyhf.a; sourceTree = BUILT_PRODUCTS_DIR; };
8D5A5DB42CD4B70D0096CBD7 /* libr820.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libr820.a; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -191,6 +212,22 @@
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
+ 8D0349222CF70DD20026DA77 /* Exceptions for "Radio" folder in "RtlSdrIQ" target */ = {
+ isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
+ membershipExceptions = (
+ HW/RtlSdr/r820/r820.swift,
+ Utils/RtlSdrIQ/main.swift,
+ );
+ target = 8D0349172CF70DCD0026DA77 /* RtlSdrIQ */;
+ };
+ 8D4068302CF9BF360064C96D /* Exceptions for "Utils" folder in "RtlSdrIQ" target */ = {
+ isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
+ membershipExceptions = (
+ FileUtils.swift,
+ PathUtils.swift,
+ );
+ target = 8D0349172CF70DCD0026DA77 /* RtlSdrIQ */;
+ };
8D5A5CFA2CCD95E90096CBD7 /* Exceptions for "IQ" folder in "PrySDR" target */ = {
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
membershipExceptions = (
@@ -344,6 +381,7 @@
HW/RtlSdr/r820/src/tuner_fc0013.c,
HW/RtlSdr/r820/src/tuner_fc2580.c,
HW/RtlSdr/r820/src/tuner_r82xx.c,
+ Utils/RtlSdrIQ/main.swift,
Utils/TestAirSpy/main.swift,
Utils/TestAirSpyHF/main.swift,
Utils/TestBladeRF/main.swift,
@@ -583,6 +621,7 @@
8D876E812CD4DB950082EC54 /* Exceptions for "Radio" folder in "TestAirSpyHF" target */,
8D8770072CD4F1680082EC54 /* Exceptions for "Radio" folder in "TestBladeRF" target */,
8D8770A22CD6B4D00082EC54 /* Exceptions for "Radio" folder in "libbladerf" target */,
+ 8D0349222CF70DD20026DA77 /* Exceptions for "Radio" folder in "RtlSdrIQ" target */,
);
path = Radio;
sourceTree = "<group>";
@@ -632,12 +671,25 @@
};
8DD98C882CC788620062D678 /* Utils */ = {
isa = PBXFileSystemSynchronizedRootGroup;
+ exceptions = (
+ 8D4068302CF9BF360064C96D /* Exceptions for "Utils" folder in "RtlSdrIQ" target */,
+ );
path = Utils;
sourceTree = "<group>";
};
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
+ 8D0349152CF70DCD0026DA77 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8D4068252CF8619F0064C96D /* libusb.a in Frameworks */,
+ 8D4068242CF8619B0064C96D /* libr820.a in Frameworks */,
+ 8D0349252CF70E220026DA77 /* ArgumentParser in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
8D5A5D732CD436BC0096CBD7 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@@ -781,6 +833,7 @@
8D876E772CD4DB8F0082EC54 /* TestAirSpyHF */,
8D876FFD2CD4F1620082EC54 /* TestBladeRF */,
8D87709D2CD6B4BB0082EC54 /* libbladerf.a */,
+ 8D0349182CF70DCD0026DA77 /* RtlSdrIQ */,
);
name = Products;
sourceTree = "<group>";
@@ -840,6 +893,26 @@
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
+ 8D0349172CF70DCD0026DA77 /* RtlSdrIQ */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 8D03491E2CF70DCD0026DA77 /* Build configuration list for PBXNativeTarget "RtlSdrIQ" */;
+ buildPhases = (
+ 8D0349142CF70DCD0026DA77 /* Sources */,
+ 8D0349152CF70DCD0026DA77 /* Frameworks */,
+ 8D0349162CF70DCD0026DA77 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = RtlSdrIQ;
+ packageProductDependencies = (
+ 8D0349242CF70E220026DA77 /* ArgumentParser */,
+ );
+ productName = RtlSdrIQ;
+ productReference = 8D0349182CF70DCD0026DA77 /* RtlSdrIQ */;
+ productType = "com.apple.product-type.tool";
+ };
8D5A5D742CD436BC0096CBD7 /* libairspy */ = {
isa = PBXNativeTarget;
buildConfigurationList = 8D5A5D762CD436BC0096CBD7 /* Build configuration list for PBXNativeTarget "libairspy" */;
@@ -1081,6 +1154,9 @@
LastSwiftUpdateCheck = 1610;
LastUpgradeCheck = 1610;
TargetAttributes = {
+ 8D0349172CF70DCD0026DA77 = {
+ CreatedOnToolsVersion = 16.1;
+ };
8D5A5D742CD436BC0096CBD7 = {
CreatedOnToolsVersion = 16.0;
LastSwiftMigration = 1610;
@@ -1131,6 +1207,9 @@
);
mainGroup = 8DD98C382CC592540062D678;
minimizedProjectReferenceProxies = 1;
+ packageReferences = (
+ 8D0349232CF70E180026DA77 /* XCRemoteSwiftPackageReference "swift-argument-parser" */,
+ );
preferredProjectObjectVersion = 77;
productRefGroup = 8DD98C422CC592540062D678 /* Products */;
projectDirPath = "";
@@ -1148,6 +1227,7 @@
8D876E822CD4DBD80082EC54 /* BuildAll */,
8D876FFC2CD4F1620082EC54 /* TestBladeRF */,
8D87709C2CD6B4BB0082EC54 /* libbladerf */,
+ 8D0349172CF70DCD0026DA77 /* RtlSdrIQ */,
);
};
/* End PBXProject section */
@@ -1163,6 +1243,13 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
+ 8D0349142CF70DCD0026DA77 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
8D5A5D722CD436BC0096CBD7 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@@ -1243,6 +1330,11 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
+ 8D4068282CF88CCF0064C96D /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 8D0349172CF70DCD0026DA77 /* RtlSdrIQ */;
+ targetProxy = 8D4068272CF88CCF0064C96D /* PBXContainerItemProxy */;
+ };
8D5A5E1F2CD4C18D0096CBD7 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 8D5A5DB32CD4B70D0096CBD7 /* libr820 */;
@@ -1301,6 +1393,30 @@
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
+ 8D03491C2CF70DCD0026DA77 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = 53B26AJZ4Z;
+ ENABLE_HARDENED_RUNTIME = YES;
+ MACOSX_DEPLOYMENT_TARGET = 15.1;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Debug;
+ };
+ 8D03491D2CF70DCD0026DA77 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CODE_SIGN_STYLE = Automatic;
+ DEVELOPMENT_TEAM = 53B26AJZ4Z;
+ ENABLE_HARDENED_RUNTIME = YES;
+ MACOSX_DEPLOYMENT_TARGET = 15.1;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_VERSION = 5.0;
+ };
+ name = Release;
+ };
8D5A5D772CD436BC0096CBD7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@@ -1717,6 +1833,15 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
+ 8D03491E2CF70DCD0026DA77 /* Build configuration list for PBXNativeTarget "RtlSdrIQ" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8D03491C2CF70DCD0026DA77 /* Debug */,
+ 8D03491D2CF70DCD0026DA77 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
8D5A5D762CD436BC0096CBD7 /* Build configuration list for PBXNativeTarget "libairspy" */ = {
isa = XCConfigurationList;
buildConfigurations = (
@@ -1835,6 +1960,25 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
+
+/* Begin XCRemoteSwiftPackageReference section */
+ 8D0349232CF70E180026DA77 /* XCRemoteSwiftPackageReference "swift-argument-parser" */ = {
+ isa = XCRemoteSwiftPackageReference;
+ repositoryURL = "https://github.com/apple/swift-argument-parser.git";
+ requirement = {
+ kind = upToNextMajorVersion;
+ minimumVersion = 1.5.0;
+ };
+ };
+/* End XCRemoteSwiftPackageReference section */
+
+/* Begin XCSwiftPackageProductDependency section */
+ 8D0349242CF70E220026DA77 /* ArgumentParser */ = {
+ isa = XCSwiftPackageProductDependency;
+ package = 8D0349232CF70E180026DA77 /* XCRemoteSwiftPackageReference "swift-argument-parser" */;
+ productName = ArgumentParser;
+ };
+/* End XCSwiftPackageProductDependency section */
};
rootObject = 8DD98C392CC592540062D678 /* Project object */;
}
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>?) -> 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..<args.nsamples {
- let offsetByte = buf_ptr + i
- print("\(String(format:"%02hhX ",offsetByte.load(as: UInt8.self)))",terminator: "")
+var total_bytes:Int32 = 0
+if (args.async == false) {
+ while (total_bytes < args.nsamples) {
+ let ret = device.readSync(buf: buf_ptr, len: Int32(NUM_SAMPLES), n_read: &nbytes)
+ if ret<0 {
+ print("data read sync returned <0 = \(ret)")
+ break;
+ }
+ print("Reading samples read \(nbytes) bytes")
+ total_bytes += nbytes
+
+ let dataU8 = buf_ptr.bindMemory(to: UInt8.self, capacity: NUM_SAMPLES)
+ let bufferU8 = UnsafeBufferPointer(start: dataU8, count: NUM_SAMPLES)
+ let convertedData = Data(bufferU8)
+ /*for i in 0..<Int(nbytes) {
+ let offsetByte = buf_ptr + i
+ print("\(String(format:"%02hhX ",offsetByte.load(as: UInt8.self)))",terminator: "")
+ }*/
+ if (args.verbose) {
+ for i in 0..<bufferU8.count {
+ print("\(String(format: "%02hhX", bufferU8[i]))", terminator: "")
+ }
+ }
+
+ //dump data to file
+
+ if let file = fileHandle {
+ //print(convertedData)
+ do {
+ //try convertedData.write(to: fileUrl)
+ try file.write(contentsOf: convertedData)
+ } catch {
+ print("Cant dump data to file")
+ }
+ }
+ }
+} else {
+ print("ASYNC not implemented")
}
-device.close()
+//clean after use all structures
+device.close()
buf_ptr.deallocate()
diff --git a/Utils/FileUtils.swift b/Utils/FileUtils.swift
new file mode 100644
index 0000000..58e7124
--- /dev/null
+++ b/Utils/FileUtils.swift
@@ -0,0 +1,18 @@
+//
+// FileUtils.swift
+// PrySDR
+//
+// Created by Jacky Jack on 29/11/2024.
+//
+
+import Foundation
+
+func checkIfFileExists(_ fname: String) -> Bool {
+ let fm = FileManager.default
+ if fm.fileExists(atPath: fname) {
+ return true
+ }
+ return false
+}
+
+
diff --git a/Utils/PathUtils.swift b/Utils/PathUtils.swift
new file mode 100644
index 0000000..a82261a
--- /dev/null
+++ b/Utils/PathUtils.swift
@@ -0,0 +1,13 @@
+//
+// PathUtils.swift
+// PrySDR
+//
+// Created by Jacky Jack on 29/11/2024.
+//
+
+import Foundation
+
+//get current run directory
+func getCurrentExecutableDir() -> String {
+ return Process().currentDirectoryPath
+}