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 --- PrySDR.xcodeproj/project.pbxproj | 418 +++++++++++++++++++++++++++++++++--- PrySDR/main.swift | 1 + Radio/HW/AirSpyHF/AirSpyHF.swift | 112 +++++++++- Radio/HW/AirSpyHF/src/airspyhf.c | 11 +- Radio/HW/AirSpyHF/src/airspyhf.h | 66 ++++++ Radio/Utils/AirSpyHFIQ/main.swift | 147 +++++++++++++ Radio/Utils/AirSpyIQ/main.swift | 11 + Radio/Utils/RtlSdrIQ/main.swift | 1 + Radio/Utils/TestAirSpy/main.swift | 2 +- Radio/Utils/TestAirSpyHF/main.swift | 19 +- Radio/Utils/TestBladeRF/main.swift | 2 +- Radio/Utils/TestRtlSdr/main.swift | 2 +- Utils/Version.swift | 8 + 13 files changed, 756 insertions(+), 44 deletions(-) create mode 100644 Radio/Utils/AirSpyHFIQ/main.swift create mode 100644 Radio/Utils/AirSpyIQ/main.swift create mode 100644 Utils/Version.swift diff --git a/PrySDR.xcodeproj/project.pbxproj b/PrySDR.xcodeproj/project.pbxproj index 9e31fe4..5ae568c 100644 --- a/PrySDR.xcodeproj/project.pbxproj +++ b/PrySDR.xcodeproj/project.pbxproj @@ -13,6 +13,14 @@ buildPhases = ( ); dependencies = ( + 8D4068682CFDC0940064C96D /* PBXTargetDependency */, + 8D4068662CFDC0900064C96D /* PBXTargetDependency */, + 8D4068642CFDC08D0064C96D /* PBXTargetDependency */, + 8D4068622CFDC08A0064C96D /* PBXTargetDependency */, + 8D4068602CFDC0850064C96D /* PBXTargetDependency */, + 8D40685E2CFDC07C0064C96D /* PBXTargetDependency */, + 8D40685C2CFDC0790064C96D /* PBXTargetDependency */, + 8D40685A2CFDC0710064C96D /* PBXTargetDependency */, 8D4068282CF88CCF0064C96D /* PBXTargetDependency */, 8D876E8D2CD4DBE80082EC54 /* PBXTargetDependency */, 8D876E8B2CD4DBE50082EC54 /* PBXTargetDependency */, @@ -30,6 +38,10 @@ 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 */; }; + 8D4068532CFDBB6A0064C96D /* libusb.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D5A5DDA2CD4B9100096CBD7 /* libusb.a */; }; + 8D4068552CFDBB6D0064C96D /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = 8D4068542CFDBB6D0064C96D /* ArgumentParser */; }; + 8D4068562CFDBB740064C96D /* libairspyhf.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 8D5A5D9F2CD439360096CBD7 /* libairspyhf.a */; }; + 8D4068582CFDBB8F0064C96D /* ArgumentParser in Frameworks */ = {isa = PBXBuildFile; productRef = 8D4068572CFDBB8F0064C96D /* ArgumentParser */; }; 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 */; }; @@ -57,6 +69,62 @@ remoteGlobalIDString = 8D0349172CF70DCD0026DA77; remoteInfo = RtlSdrIQ; }; + 8D4068592CFDC0710064C96D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8DD98C392CC592540062D678 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D876FFC2CD4F1620082EC54; + remoteInfo = TestBladeRF; + }; + 8D40685B2CFDC0790064C96D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8DD98C392CC592540062D678 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D4068352CFDA69C0064C96D; + remoteInfo = AirSpyHFIQ; + }; + 8D40685D2CFDC07C0064C96D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8DD98C392CC592540062D678 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D4068442CFDA6B80064C96D; + remoteInfo = AirSpyIQ; + }; + 8D40685F2CFDC0850064C96D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8DD98C392CC592540062D678 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D5A5D742CD436BC0096CBD7; + remoteInfo = libairspy; + }; + 8D4068612CFDC08A0064C96D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8DD98C392CC592540062D678 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D5A5D9E2CD439360096CBD7; + remoteInfo = libairspyhf; + }; + 8D4068632CFDC08D0064C96D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8DD98C392CC592540062D678 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D87709C2CD6B4BB0082EC54; + remoteInfo = libbladerf; + }; + 8D4068652CFDC0900064C96D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8DD98C392CC592540062D678 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D5A5DB32CD4B70D0096CBD7; + remoteInfo = libr820; + }; + 8D4068672CFDC0940064C96D /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 8DD98C392CC592540062D678 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 8D5A5DD92CD4B9100096CBD7; + remoteInfo = libusb; + }; 8D5A5E1E2CD4C18D0096CBD7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 8DD98C392CC592540062D678 /* Project object */; @@ -146,6 +214,24 @@ ); runOnlyForDeploymentPostprocessing = 1; }; + 8D4068342CFDA69C0064C96D /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; + 8D4068432CFDA6B80064C96D /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; 8D5A5E062CD4BAF10096CBD7 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -194,20 +280,22 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ - 8D0349182CF70DCD0026DA77 /* RtlSdrIQ */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = RtlSdrIQ; sourceTree = BUILT_PRODUCTS_DIR; }; + 8D0349182CF70DCD0026DA77 /* rtlsdr_iq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = rtlsdr_iq; sourceTree = BUILT_PRODUCTS_DIR; }; + 8D4068362CFDA69C0064C96D /* airspyhf_iq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = airspyhf_iq; sourceTree = BUILT_PRODUCTS_DIR; }; + 8D4068452CFDA6B80064C96D /* airspy_iq */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = airspy_iq; 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; }; 8D5A5DDA2CD4B9100096CBD7 /* libusb.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libusb.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 8D5A5E082CD4BAF10096CBD7 /* TestRtlSdr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TestRtlSdr; sourceTree = BUILT_PRODUCTS_DIR; }; + 8D5A5E082CD4BAF10096CBD7 /* test_rtlsdr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = test_rtlsdr; sourceTree = BUILT_PRODUCTS_DIR; }; 8D5A5E162CD4BEAF0096CBD7 /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = System/Library/Frameworks/IOKit.framework; sourceTree = SDKROOT; }; 8D5A5E182CD4BEB60096CBD7 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; 8D5A5E1A2CD4BECD0096CBD7 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - 8D876E5E2CD4CE890082EC54 /* TestAirSpy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TestAirSpy; sourceTree = BUILT_PRODUCTS_DIR; }; - 8D876E772CD4DB8F0082EC54 /* TestAirSpyHF */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TestAirSpyHF; sourceTree = BUILT_PRODUCTS_DIR; }; - 8D876FFD2CD4F1620082EC54 /* TestBladeRF */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = TestBladeRF; sourceTree = BUILT_PRODUCTS_DIR; }; + 8D876E5E2CD4CE890082EC54 /* test_airpsy */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = test_airpsy; sourceTree = BUILT_PRODUCTS_DIR; }; + 8D876E772CD4DB8F0082EC54 /* test_airspyhf */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = test_airspyhf; sourceTree = BUILT_PRODUCTS_DIR; }; + 8D876FFD2CD4F1620082EC54 /* test_bladerf */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = test_bladerf; sourceTree = BUILT_PRODUCTS_DIR; }; 8D87709D2CD6B4BB0082EC54 /* libbladerf.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libbladerf.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 8DD98C412CC592540062D678 /* PrySDR */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = PrySDR; sourceTree = BUILT_PRODUCTS_DIR; }; + 8DD98C412CC592540062D678 /* prysdr */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = prysdr; sourceTree = BUILT_PRODUCTS_DIR; }; 8DD98C722CC632040062D678 /* MatrixXT.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MatrixXT.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -225,9 +313,71 @@ membershipExceptions = ( FileUtils.swift, PathUtils.swift, + Version.swift, ); target = 8D0349172CF70DCD0026DA77 /* RtlSdrIQ */; }; + 8D4068402CFDA6A30064C96D /* Exceptions for "Radio" folder in "AirSpyHFIQ" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + HW/AirSpyHF/AirSpyHF.swift, + Utils/AirSpyHFIQ/main.swift, + ); + target = 8D4068352CFDA69C0064C96D /* AirSpyHFIQ */; + }; + 8D40684F2CFDA6BD0064C96D /* Exceptions for "Radio" folder in "AirSpyIQ" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Utils/AirSpyIQ/main.swift, + ); + target = 8D4068442CFDA6B80064C96D /* AirSpyIQ */; + }; + 8D40686B2CFDE4BD0064C96D /* Exceptions for "Utils" folder in "TestAirSpyHF" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Version.swift, + ); + target = 8D876E762CD4DB8F0082EC54 /* TestAirSpyHF */; + }; + 8D40686D2CFDE4C10064C96D /* Exceptions for "Utils" folder in "AirSpyHFIQ" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + FileUtils.swift, + PathUtils.swift, + Version.swift, + ); + target = 8D4068352CFDA69C0064C96D /* AirSpyHFIQ */; + }; + 8D406AB22CFF0D1F0064C96D /* Exceptions for "Utils" folder in "TestRtlSdr" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Version.swift, + ); + target = 8D5A5E072CD4BAF10096CBD7 /* TestRtlSdr */; + }; + 8D406AB32CFF0D1F0064C96D /* Exceptions for "Utils" folder in "TestAirSpy" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Version.swift, + ); + target = 8D876E5D2CD4CE890082EC54 /* TestAirSpy */; + }; + 8D406AB42CFF0D1F0064C96D /* Exceptions for "Utils" folder in "TestBladeRF" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + Version.swift, + ); + target = 8D876FFC2CD4F1620082EC54 /* TestBladeRF */; + }; + 8D406AB52CFF0D1F0064C96D /* Exceptions for "Utils" folder in "AirSpyIQ" target */ = { + isa = PBXFileSystemSynchronizedBuildFileExceptionSet; + membershipExceptions = ( + FileUtils.swift, + PathUtils.swift, + Version.swift, + ); + target = 8D4068442CFDA6B80064C96D /* AirSpyIQ */; + }; 8D5A5CFA2CCD95E90096CBD7 /* Exceptions for "IQ" folder in "PrySDR" target */ = { isa = PBXFileSystemSynchronizedBuildFileExceptionSet; membershipExceptions = ( @@ -381,6 +531,8 @@ HW/RtlSdr/r820/src/tuner_fc0013.c, HW/RtlSdr/r820/src/tuner_fc2580.c, HW/RtlSdr/r820/src/tuner_r82xx.c, + Utils/AirSpyHFIQ/main.swift, + Utils/AirSpyIQ/main.swift, Utils/RtlSdrIQ/main.swift, Utils/TestAirSpy/main.swift, Utils/TestAirSpyHF/main.swift, @@ -622,6 +774,8 @@ 8D8770072CD4F1680082EC54 /* Exceptions for "Radio" folder in "TestBladeRF" target */, 8D8770A22CD6B4D00082EC54 /* Exceptions for "Radio" folder in "libbladerf" target */, 8D0349222CF70DD20026DA77 /* Exceptions for "Radio" folder in "RtlSdrIQ" target */, + 8D4068402CFDA6A30064C96D /* Exceptions for "Radio" folder in "AirSpyHFIQ" target */, + 8D40684F2CFDA6BD0064C96D /* Exceptions for "Radio" folder in "AirSpyIQ" target */, ); path = Radio; sourceTree = ""; @@ -672,7 +826,13 @@ 8DD98C882CC788620062D678 /* Utils */ = { isa = PBXFileSystemSynchronizedRootGroup; exceptions = ( + 8D406AB22CFF0D1F0064C96D /* Exceptions for "Utils" folder in "TestRtlSdr" target */, + 8D406AB32CFF0D1F0064C96D /* Exceptions for "Utils" folder in "TestAirSpy" target */, + 8D40686B2CFDE4BD0064C96D /* Exceptions for "Utils" folder in "TestAirSpyHF" target */, + 8D406AB42CFF0D1F0064C96D /* Exceptions for "Utils" folder in "TestBladeRF" target */, 8D4068302CF9BF360064C96D /* Exceptions for "Utils" folder in "RtlSdrIQ" target */, + 8D40686D2CFDE4C10064C96D /* Exceptions for "Utils" folder in "AirSpyHFIQ" target */, + 8D406AB52CFF0D1F0064C96D /* Exceptions for "Utils" folder in "AirSpyIQ" target */, ); path = Utils; sourceTree = ""; @@ -690,6 +850,23 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 8D4068332CFDA69C0064C96D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 8D4068562CFDBB740064C96D /* libairspyhf.a in Frameworks */, + 8D4068552CFDBB6D0064C96D /* ArgumentParser in Frameworks */, + 8D4068532CFDBB6A0064C96D /* libusb.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8D4068422CFDA6B80064C96D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8D5A5D732CD436BC0096CBD7 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -773,6 +950,7 @@ 8D87714A2CD7A6A40082EC54 /* libr820.a in Frameworks */, 8D8771492CD7A69B0082EC54 /* libbladerf.a in Frameworks */, 8D5A5DAE2CD439DA0096CBD7 /* libairspyhf.a in Frameworks */, + 8D4068582CFDBB8F0064C96D /* ArgumentParser in Frameworks */, 8D5A5DAD2CD439D70096CBD7 /* libairspy.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -822,18 +1000,20 @@ 8DD98C422CC592540062D678 /* Products */ = { isa = PBXGroup; children = ( - 8DD98C412CC592540062D678 /* PrySDR */, + 8DD98C412CC592540062D678 /* prysdr */, 8DD98C722CC632040062D678 /* MatrixXT.xctest */, 8D5A5D752CD436BC0096CBD7 /* libairspy.a */, 8D5A5D9F2CD439360096CBD7 /* libairspyhf.a */, 8D5A5DB42CD4B70D0096CBD7 /* libr820.a */, 8D5A5DDA2CD4B9100096CBD7 /* libusb.a */, - 8D5A5E082CD4BAF10096CBD7 /* TestRtlSdr */, - 8D876E5E2CD4CE890082EC54 /* TestAirSpy */, - 8D876E772CD4DB8F0082EC54 /* TestAirSpyHF */, - 8D876FFD2CD4F1620082EC54 /* TestBladeRF */, + 8D5A5E082CD4BAF10096CBD7 /* test_rtlsdr */, + 8D876E5E2CD4CE890082EC54 /* test_airpsy */, + 8D876E772CD4DB8F0082EC54 /* test_airspyhf */, + 8D876FFD2CD4F1620082EC54 /* test_bladerf */, 8D87709D2CD6B4BB0082EC54 /* libbladerf.a */, - 8D0349182CF70DCD0026DA77 /* RtlSdrIQ */, + 8D0349182CF70DCD0026DA77 /* rtlsdr_iq */, + 8D4068362CFDA69C0064C96D /* airspyhf_iq */, + 8D4068452CFDA6B80064C96D /* airspy_iq */, ); name = Products; sourceTree = ""; @@ -910,7 +1090,46 @@ 8D0349242CF70E220026DA77 /* ArgumentParser */, ); productName = RtlSdrIQ; - productReference = 8D0349182CF70DCD0026DA77 /* RtlSdrIQ */; + productReference = 8D0349182CF70DCD0026DA77 /* rtlsdr_iq */; + productType = "com.apple.product-type.tool"; + }; + 8D4068352CFDA69C0064C96D /* AirSpyHFIQ */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8D40683A2CFDA69C0064C96D /* Build configuration list for PBXNativeTarget "AirSpyHFIQ" */; + buildPhases = ( + 8D4068322CFDA69C0064C96D /* Sources */, + 8D4068332CFDA69C0064C96D /* Frameworks */, + 8D4068342CFDA69C0064C96D /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = AirSpyHFIQ; + packageProductDependencies = ( + 8D4068542CFDBB6D0064C96D /* ArgumentParser */, + ); + productName = AirSpyHFIQ; + productReference = 8D4068362CFDA69C0064C96D /* airspyhf_iq */; + productType = "com.apple.product-type.tool"; + }; + 8D4068442CFDA6B80064C96D /* AirSpyIQ */ = { + isa = PBXNativeTarget; + buildConfigurationList = 8D4068492CFDA6B80064C96D /* Build configuration list for PBXNativeTarget "AirSpyIQ" */; + buildPhases = ( + 8D4068412CFDA6B80064C96D /* Sources */, + 8D4068422CFDA6B80064C96D /* Frameworks */, + 8D4068432CFDA6B80064C96D /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = AirSpyIQ; + packageProductDependencies = ( + ); + productName = AirSpyIQ; + productReference = 8D4068452CFDA6B80064C96D /* airspy_iq */; productType = "com.apple.product-type.tool"; }; 8D5A5D742CD436BC0096CBD7 /* libairspy */ = { @@ -1008,7 +1227,7 @@ packageProductDependencies = ( ); productName = TestRtlSdr; - productReference = 8D5A5E082CD4BAF10096CBD7 /* TestRtlSdr */; + productReference = 8D5A5E082CD4BAF10096CBD7 /* test_rtlsdr */; productType = "com.apple.product-type.tool"; }; 8D876E5D2CD4CE890082EC54 /* TestAirSpy */ = { @@ -1029,7 +1248,7 @@ packageProductDependencies = ( ); productName = TestAirSpy; - productReference = 8D876E5E2CD4CE890082EC54 /* TestAirSpy */; + productReference = 8D876E5E2CD4CE890082EC54 /* test_airpsy */; productType = "com.apple.product-type.tool"; }; 8D876E762CD4DB8F0082EC54 /* TestAirSpyHF */ = { @@ -1051,7 +1270,7 @@ packageProductDependencies = ( ); productName = TestAirSpyHF; - productReference = 8D876E772CD4DB8F0082EC54 /* TestAirSpyHF */; + productReference = 8D876E772CD4DB8F0082EC54 /* test_airspyhf */; productType = "com.apple.product-type.tool"; }; 8D876FFC2CD4F1620082EC54 /* TestBladeRF */ = { @@ -1071,7 +1290,7 @@ packageProductDependencies = ( ); productName = TestBladeRF; - productReference = 8D876FFD2CD4F1620082EC54 /* TestBladeRF */; + productReference = 8D876FFD2CD4F1620082EC54 /* test_bladerf */; productType = "com.apple.product-type.tool"; }; 8D87709C2CD6B4BB0082EC54 /* libbladerf */ = { @@ -1120,9 +1339,10 @@ ); name = PrySDR; packageProductDependencies = ( + 8D4068572CFDBB8F0064C96D /* ArgumentParser */, ); productName = PrySDR; - productReference = 8DD98C412CC592540062D678 /* PrySDR */; + productReference = 8DD98C412CC592540062D678 /* prysdr */; productType = "com.apple.product-type.tool"; }; 8DD98C712CC632040062D678 /* MatrixXT */ = { @@ -1157,6 +1377,12 @@ 8D0349172CF70DCD0026DA77 = { CreatedOnToolsVersion = 16.1; }; + 8D4068352CFDA69C0064C96D = { + CreatedOnToolsVersion = 16.1; + }; + 8D4068442CFDA6B80064C96D = { + CreatedOnToolsVersion = 16.1; + }; 8D5A5D742CD436BC0096CBD7 = { CreatedOnToolsVersion = 16.0; LastSwiftMigration = 1610; @@ -1228,6 +1454,8 @@ 8D876FFC2CD4F1620082EC54 /* TestBladeRF */, 8D87709C2CD6B4BB0082EC54 /* libbladerf */, 8D0349172CF70DCD0026DA77 /* RtlSdrIQ */, + 8D4068352CFDA69C0064C96D /* AirSpyHFIQ */, + 8D4068442CFDA6B80064C96D /* AirSpyIQ */, ); }; /* End PBXProject section */ @@ -1250,6 +1478,20 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 8D4068322CFDA69C0064C96D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 8D4068412CFDA6B80064C96D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 8D5A5D722CD436BC0096CBD7 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1335,6 +1577,46 @@ target = 8D0349172CF70DCD0026DA77 /* RtlSdrIQ */; targetProxy = 8D4068272CF88CCF0064C96D /* PBXContainerItemProxy */; }; + 8D40685A2CFDC0710064C96D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8D876FFC2CD4F1620082EC54 /* TestBladeRF */; + targetProxy = 8D4068592CFDC0710064C96D /* PBXContainerItemProxy */; + }; + 8D40685C2CFDC0790064C96D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8D4068352CFDA69C0064C96D /* AirSpyHFIQ */; + targetProxy = 8D40685B2CFDC0790064C96D /* PBXContainerItemProxy */; + }; + 8D40685E2CFDC07C0064C96D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8D4068442CFDA6B80064C96D /* AirSpyIQ */; + targetProxy = 8D40685D2CFDC07C0064C96D /* PBXContainerItemProxy */; + }; + 8D4068602CFDC0850064C96D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8D5A5D742CD436BC0096CBD7 /* libairspy */; + targetProxy = 8D40685F2CFDC0850064C96D /* PBXContainerItemProxy */; + }; + 8D4068622CFDC08A0064C96D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8D5A5D9E2CD439360096CBD7 /* libairspyhf */; + targetProxy = 8D4068612CFDC08A0064C96D /* PBXContainerItemProxy */; + }; + 8D4068642CFDC08D0064C96D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8D87709C2CD6B4BB0082EC54 /* libbladerf */; + targetProxy = 8D4068632CFDC08D0064C96D /* PBXContainerItemProxy */; + }; + 8D4068662CFDC0900064C96D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8D5A5DB32CD4B70D0096CBD7 /* libr820 */; + targetProxy = 8D4068652CFDC0900064C96D /* PBXContainerItemProxy */; + }; + 8D4068682CFDC0940064C96D /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 8D5A5DD92CD4B9100096CBD7 /* libusb */; + targetProxy = 8D4068672CFDC0940064C96D /* PBXContainerItemProxy */; + }; 8D5A5E1F2CD4C18D0096CBD7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 8D5A5DB32CD4B70D0096CBD7 /* libr820 */; @@ -1400,7 +1682,7 @@ DEVELOPMENT_TEAM = 53B26AJZ4Z; ENABLE_HARDENED_RUNTIME = YES; MACOSX_DEPLOYMENT_TARGET = 15.1; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = rtlsdr_iq; SWIFT_VERSION = 5.0; }; name = Debug; @@ -1412,7 +1694,55 @@ DEVELOPMENT_TEAM = 53B26AJZ4Z; ENABLE_HARDENED_RUNTIME = YES; MACOSX_DEPLOYMENT_TARGET = 15.1; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = rtlsdr_iq; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 8D40683B2CFDA69C0064C96D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 53B26AJZ4Z; + ENABLE_HARDENED_RUNTIME = YES; + MACOSX_DEPLOYMENT_TARGET = 15.1; + PRODUCT_NAME = airspyhf_iq; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 8D40683C2CFDA69C0064C96D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 53B26AJZ4Z; + ENABLE_HARDENED_RUNTIME = YES; + MACOSX_DEPLOYMENT_TARGET = 15.1; + PRODUCT_NAME = airspyhf_iq; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 8D40684A2CFDA6B80064C96D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 53B26AJZ4Z; + ENABLE_HARDENED_RUNTIME = YES; + MACOSX_DEPLOYMENT_TARGET = 15.1; + PRODUCT_NAME = airspy_iq; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 8D40684B2CFDA6B80064C96D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + DEVELOPMENT_TEAM = 53B26AJZ4Z; + ENABLE_HARDENED_RUNTIME = YES; + MACOSX_DEPLOYMENT_TARGET = 15.1; + PRODUCT_NAME = airspy_iq; SWIFT_VERSION = 5.0; }; name = Release; @@ -1532,7 +1862,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 53B26AJZ4Z; ENABLE_HARDENED_RUNTIME = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = test_rtlsdr; SWIFT_VERSION = 5.0; }; name = Debug; @@ -1543,7 +1873,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 53B26AJZ4Z; ENABLE_HARDENED_RUNTIME = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = test_rtlsdr; SWIFT_VERSION = 5.0; }; name = Release; @@ -1554,7 +1884,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 53B26AJZ4Z; ENABLE_HARDENED_RUNTIME = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = test_airpsy; SWIFT_VERSION = 5.0; }; name = Debug; @@ -1565,7 +1895,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 53B26AJZ4Z; ENABLE_HARDENED_RUNTIME = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = test_airpsy; SWIFT_VERSION = 5.0; }; name = Release; @@ -1576,7 +1906,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 53B26AJZ4Z; ENABLE_HARDENED_RUNTIME = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = test_airspyhf; SWIFT_VERSION = 5.0; }; name = Debug; @@ -1587,7 +1917,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 53B26AJZ4Z; ENABLE_HARDENED_RUNTIME = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = test_airspyhf; SWIFT_VERSION = 5.0; }; name = Release; @@ -1616,7 +1946,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 53B26AJZ4Z; ENABLE_HARDENED_RUNTIME = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = test_bladerf; "SWIFT_OBJC_BRIDGING_HEADER[arch=*]" = ""; SWIFT_VERSION = 5.0; }; @@ -1628,7 +1958,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 53B26AJZ4Z; ENABLE_HARDENED_RUNTIME = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = test_bladerf; SWIFT_VERSION = 5.0; }; name = Release; @@ -1784,7 +2114,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 53B26AJZ4Z; ENABLE_HARDENED_RUNTIME = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = prysdr; SWIFT_VERSION = 6.0; }; name = Debug; @@ -1795,7 +2125,7 @@ CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = 53B26AJZ4Z; ENABLE_HARDENED_RUNTIME = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = prysdr; SWIFT_VERSION = 6.0; }; name = Release; @@ -1842,6 +2172,24 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 8D40683A2CFDA69C0064C96D /* Build configuration list for PBXNativeTarget "AirSpyHFIQ" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8D40683B2CFDA69C0064C96D /* Debug */, + 8D40683C2CFDA69C0064C96D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 8D4068492CFDA6B80064C96D /* Build configuration list for PBXNativeTarget "AirSpyIQ" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 8D40684A2CFDA6B80064C96D /* Debug */, + 8D40684B2CFDA6B80064C96D /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 8D5A5D762CD436BC0096CBD7 /* Build configuration list for PBXNativeTarget "libairspy" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -1978,6 +2326,16 @@ package = 8D0349232CF70E180026DA77 /* XCRemoteSwiftPackageReference "swift-argument-parser" */; productName = ArgumentParser; }; + 8D4068542CFDBB6D0064C96D /* ArgumentParser */ = { + isa = XCSwiftPackageProductDependency; + package = 8D0349232CF70E180026DA77 /* XCRemoteSwiftPackageReference "swift-argument-parser" */; + productName = ArgumentParser; + }; + 8D4068572CFDBB8F0064C96D /* ArgumentParser */ = { + isa = XCSwiftPackageProductDependency; + package = 8D0349232CF70E180026DA77 /* XCRemoteSwiftPackageReference "swift-argument-parser" */; + productName = ArgumentParser; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 8DD98C392CC592540062D678 /* Project object */; diff --git a/PrySDR/main.swift b/PrySDR/main.swift index 33f0e1d..d7941d1 100644 --- a/PrySDR/main.swift +++ b/PrySDR/main.swift @@ -6,6 +6,7 @@ // import Foundation +import ArgumentParser import libr820 import libairspy import libairspyhf 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); 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?) -> 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.. = .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) diff --git a/Utils/Version.swift b/Utils/Version.swift new file mode 100644 index 0000000..740b861 --- /dev/null +++ b/Utils/Version.swift @@ -0,0 +1,8 @@ +// +// Version.swift +// PrySDR +// +// Created by Jacky Jack on 02/12/2024. +// + +public let software_version = "2024.12" -- cgit v1.2.3