mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-10 07:37:25 -05:00
Compare commits
5 Commits
v0.5.2
...
v0.6.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22ffb656be | ||
|
|
de80d2a6c1 | ||
|
|
a320b4a24f | ||
|
|
fc13777211 | ||
|
|
75347f9d0a |
4
.github/workflows/gradle.yml
vendored
4
.github/workflows/gradle.yml
vendored
@@ -22,10 +22,10 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 17
|
||||
- name: Set up JDK 19
|
||||
uses: actions/setup-java@v2
|
||||
with:
|
||||
java-version: '17'
|
||||
java-version: '19'
|
||||
distribution: 'liberica'
|
||||
java-package: 'jdk+fx'
|
||||
- name: Build with Gradle
|
||||
|
||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -4,7 +4,7 @@
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" project-jdk-name="liberica-19.0.1.fx" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_19_PREVIEW" project-jdk-name="liberica-19.0.1.fx" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
36
artifacts/sdrplay-api-headers/README.txt
Normal file
36
artifacts/sdrplay-api-headers/README.txt
Normal file
@@ -0,0 +1,36 @@
|
||||
Auto-generating Java code from SDRPlay API using jextract.
|
||||
|
||||
Note: the api headers in the 3.11 folder are equivalent to the 3.08 headers. The only
|
||||
difference from the 3.07 headers is the addition of the boolean 'valid' flag to DeviceT structure.
|
||||
|
||||
1. Download JDK19 compatible build of jextract JDK: https://jdk.java.net/jextract/
|
||||
2. If generating on windows platform, modify the sdrplay_api.h to remove the windows
|
||||
pieces of the file. Specifically:
|
||||
2a. Comment out these lines but leave the *HANDLE typedef:
|
||||
|
||||
//#if defined(_M_X64) || defined(_M_IX86) || defined(_M_ARM64)
|
||||
//#include "windows.h"
|
||||
//#elif defined (__GNUC__)
|
||||
typedef void *HANDLE;
|
||||
//#endif
|
||||
|
||||
//#ifndef _SDRPLAY_DLL_QUALIFIER
|
||||
//#if !defined(STATIC_LIB) && (defined(_M_X64) || defined(_M_IX86) || defined(_M_ARM64))
|
||||
//#define _SDRPLAY_DLL_QUALIFIER __declspec(dllimport)
|
||||
//#elif defined(STATIC_LIB) || defined(__GNUC__)
|
||||
//#define _SDRPLAY_DLL_QUALIFIER
|
||||
//#endif
|
||||
//#endif // _SDRPLAY_DLL_QUALIFIER
|
||||
|
||||
2b. Remove the '_SDRPLAY_DLL_QUALIFIER' from in front of the method declarations
|
||||
|
||||
2c. Change the 3.11 version string to 3.08 either in the header file, or in the generated java class
|
||||
|
||||
3. Open command prompt to the root source code where the generated files should be placed:
|
||||
..\SDRtrunk\sdrplay-api\src\main\java
|
||||
|
||||
4. Generate the code:
|
||||
c:\Users\Denny\Downloads\jdk-19-ea2-panama\bin\jextract "C:\Users\Denny\git\sdrtrunk\sdrplay-api\api\v3_11\sdrplay_api.h" -l libsdrplay_api --source
|
||||
|
||||
5. Do this for all versions of the API.
|
||||
|
||||
229
artifacts/sdrplay-api-headers/v3_07/sdrplay_api.h
Normal file
229
artifacts/sdrplay-api-headers/v3_07/sdrplay_api.h
Normal file
@@ -0,0 +1,229 @@
|
||||
#ifndef SDRPLAY_API_H
|
||||
#define SDRPLAY_API_H
|
||||
|
||||
#include "sdrplay_api_dev.h"
|
||||
#include "sdrplay_api_rx_channel.h"
|
||||
#include "sdrplay_api_callback.h"
|
||||
|
||||
//#if defined(_M_X64) || defined(_M_IX86)
|
||||
//#include "windows.h"
|
||||
//#elif defined (__GNUC__)
|
||||
typedef void *HANDLE;
|
||||
//#endif
|
||||
|
||||
//#ifndef _SDRPLAY_DLL_QUALIFIER
|
||||
//#if !defined(STATIC_LIB) && (defined(_M_X64) || defined(_M_IX86))
|
||||
//#define _SDRPLAY_DLL_QUALIFIER __declspec(dllimport)
|
||||
//#elif defined(STATIC_LIB) || defined(__GNUC__)
|
||||
//#define _SDRPLAY_DLL_QUALIFIER
|
||||
//#endif
|
||||
//#endif // _SDRPLAY_DLL_QUALIFIER
|
||||
|
||||
// Application code should check that it is compiled against the same API version
|
||||
// sdrplay_api_ApiVersion() returns the API version
|
||||
#define SDRPLAY_API_VERSION (float)(3.07)
|
||||
|
||||
// API Constants
|
||||
#define SDRPLAY_MAX_DEVICES (16)
|
||||
#define SDRPLAY_MAX_TUNERS_PER_DEVICE (2)
|
||||
|
||||
#define SDRPLAY_MAX_SER_NO_LEN (64)
|
||||
#define SDRPLAY_MAX_ROOT_NM_LEN (32)
|
||||
|
||||
#define SDRPLAY_RSP1_ID (1)
|
||||
#define SDRPLAY_RSP1A_ID (255)
|
||||
#define SDRPLAY_RSP2_ID (2)
|
||||
#define SDRPLAY_RSPduo_ID (3)
|
||||
#define SDRPLAY_RSPdx_ID (4)
|
||||
|
||||
// Enum types
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_Success = 0,
|
||||
sdrplay_api_Fail = 1,
|
||||
sdrplay_api_InvalidParam = 2,
|
||||
sdrplay_api_OutOfRange = 3,
|
||||
sdrplay_api_GainUpdateError = 4,
|
||||
sdrplay_api_RfUpdateError = 5,
|
||||
sdrplay_api_FsUpdateError = 6,
|
||||
sdrplay_api_HwError = 7,
|
||||
sdrplay_api_AliasingError = 8,
|
||||
sdrplay_api_AlreadyInitialised = 9,
|
||||
sdrplay_api_NotInitialised = 10,
|
||||
sdrplay_api_NotEnabled = 11,
|
||||
sdrplay_api_HwVerError = 12,
|
||||
sdrplay_api_OutOfMemError = 13,
|
||||
sdrplay_api_ServiceNotResponding = 14,
|
||||
sdrplay_api_StartPending = 15,
|
||||
sdrplay_api_StopPending = 16,
|
||||
sdrplay_api_InvalidMode = 17,
|
||||
sdrplay_api_FailedVerification1 = 18,
|
||||
sdrplay_api_FailedVerification2 = 19,
|
||||
sdrplay_api_FailedVerification3 = 20,
|
||||
sdrplay_api_FailedVerification4 = 21,
|
||||
sdrplay_api_FailedVerification5 = 22,
|
||||
sdrplay_api_FailedVerification6 = 23,
|
||||
sdrplay_api_InvalidServiceVersion = 24
|
||||
} sdrplay_api_ErrT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_Update_None = 0x00000000,
|
||||
|
||||
// Reasons for master only mode
|
||||
sdrplay_api_Update_Dev_Fs = 0x00000001,
|
||||
sdrplay_api_Update_Dev_Ppm = 0x00000002,
|
||||
sdrplay_api_Update_Dev_SyncUpdate = 0x00000004,
|
||||
sdrplay_api_Update_Dev_ResetFlags = 0x00000008,
|
||||
|
||||
sdrplay_api_Update_Rsp1a_BiasTControl = 0x00000010,
|
||||
sdrplay_api_Update_Rsp1a_RfNotchControl = 0x00000020,
|
||||
sdrplay_api_Update_Rsp1a_RfDabNotchControl = 0x00000040,
|
||||
|
||||
sdrplay_api_Update_Rsp2_BiasTControl = 0x00000080,
|
||||
sdrplay_api_Update_Rsp2_AmPortSelect = 0x00000100,
|
||||
sdrplay_api_Update_Rsp2_AntennaControl = 0x00000200,
|
||||
sdrplay_api_Update_Rsp2_RfNotchControl = 0x00000400,
|
||||
sdrplay_api_Update_Rsp2_ExtRefControl = 0x00000800,
|
||||
|
||||
sdrplay_api_Update_RspDuo_ExtRefControl = 0x00001000,
|
||||
|
||||
sdrplay_api_Update_Master_Spare_1 = 0x00002000,
|
||||
sdrplay_api_Update_Master_Spare_2 = 0x00004000,
|
||||
|
||||
// Reasons for master and slave mode
|
||||
// Note: sdrplay_api_Update_Tuner_Gr MUST be the first value defined in this section!
|
||||
sdrplay_api_Update_Tuner_Gr = 0x00008000,
|
||||
sdrplay_api_Update_Tuner_GrLimits = 0x00010000,
|
||||
sdrplay_api_Update_Tuner_Frf = 0x00020000,
|
||||
sdrplay_api_Update_Tuner_BwType = 0x00040000,
|
||||
sdrplay_api_Update_Tuner_IfType = 0x00080000,
|
||||
sdrplay_api_Update_Tuner_DcOffset = 0x00100000,
|
||||
sdrplay_api_Update_Tuner_LoMode = 0x00200000,
|
||||
|
||||
sdrplay_api_Update_Ctrl_DCoffsetIQimbalance = 0x00400000,
|
||||
sdrplay_api_Update_Ctrl_Decimation = 0x00800000,
|
||||
sdrplay_api_Update_Ctrl_Agc = 0x01000000,
|
||||
sdrplay_api_Update_Ctrl_AdsbMode = 0x02000000,
|
||||
sdrplay_api_Update_Ctrl_OverloadMsgAck = 0x04000000,
|
||||
|
||||
sdrplay_api_Update_RspDuo_BiasTControl = 0x08000000,
|
||||
sdrplay_api_Update_RspDuo_AmPortSelect = 0x10000000,
|
||||
sdrplay_api_Update_RspDuo_Tuner1AmNotchControl = 0x20000000,
|
||||
sdrplay_api_Update_RspDuo_RfNotchControl = 0x40000000,
|
||||
sdrplay_api_Update_RspDuo_RfDabNotchControl = 0x80000000,
|
||||
} sdrplay_api_ReasonForUpdateT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_Update_Ext1_None = 0x00000000,
|
||||
|
||||
// Reasons for master only mode
|
||||
sdrplay_api_Update_RspDx_HdrEnable = 0x00000001,
|
||||
sdrplay_api_Update_RspDx_BiasTControl = 0x00000002,
|
||||
sdrplay_api_Update_RspDx_AntennaControl = 0x00000004,
|
||||
sdrplay_api_Update_RspDx_RfNotchControl = 0x00000008,
|
||||
sdrplay_api_Update_RspDx_RfDabNotchControl = 0x00000010,
|
||||
sdrplay_api_Update_RspDx_HdrBw = 0x00000020,
|
||||
|
||||
// Reasons for master and slave mode
|
||||
} sdrplay_api_ReasonForUpdateExtension1T;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_DbgLvl_Disable = 0,
|
||||
sdrplay_api_DbgLvl_Verbose = 1,
|
||||
sdrplay_api_DbgLvl_Warning = 2,
|
||||
sdrplay_api_DbgLvl_Error = 3,
|
||||
sdrplay_api_DbgLvl_Message = 4,
|
||||
} sdrplay_api_DbgLvl_t;
|
||||
|
||||
// Device structure
|
||||
typedef struct
|
||||
{
|
||||
char SerNo[SDRPLAY_MAX_SER_NO_LEN];
|
||||
unsigned char hwVer;
|
||||
sdrplay_api_TunerSelectT tuner;
|
||||
sdrplay_api_RspDuoModeT rspDuoMode;
|
||||
double rspDuoSampleFreq;
|
||||
HANDLE dev;
|
||||
} sdrplay_api_DeviceT;
|
||||
|
||||
// Device parameter structure
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_DevParamsT *devParams;
|
||||
sdrplay_api_RxChannelParamsT *rxChannelA;
|
||||
sdrplay_api_RxChannelParamsT *rxChannelB;
|
||||
} sdrplay_api_DeviceParamsT;
|
||||
|
||||
// Extended error message structure
|
||||
typedef struct
|
||||
{
|
||||
char file[256];
|
||||
char function[256];
|
||||
int line;
|
||||
char message[1024];
|
||||
} sdrplay_api_ErrorInfoT;
|
||||
|
||||
// Comman API function types
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_Open_t)(void);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_Close_t)(void);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_ApiVersion_t)(float *apiVer);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_LockDeviceApi_t)(void);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_UnlockDeviceApi_t)(void);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_GetDevices_t)(sdrplay_api_DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_SelectDevice_t)(sdrplay_api_DeviceT *device);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_ReleaseDevice_t)(sdrplay_api_DeviceT *device);
|
||||
typedef const char* (*sdrplay_api_GetErrorString_t)(sdrplay_api_ErrT err);
|
||||
typedef sdrplay_api_ErrorInfoT* (*sdrplay_api_GetLastError_t)(sdrplay_api_DeviceT *device);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_DisableHeartbeat_t)(void);
|
||||
|
||||
// Device API function types
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_DebugEnable_t)(HANDLE dev, sdrplay_api_DbgLvl_t dbgLvl);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_GetDeviceParams_t)(HANDLE dev, sdrplay_api_DeviceParamsT **deviceParams);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_Init_t)(HANDLE dev, sdrplay_api_CallbackFnsT *callbackFns, void *cbContext);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_Uninit_t)(HANDLE dev);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_Update_t)(HANDLE dev, sdrplay_api_TunerSelectT tuner, sdrplay_api_ReasonForUpdateT reasonForUpdate, sdrplay_api_ReasonForUpdateExtension1T reasonForUpdateExt1);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoActiveTuner_t)(HANDLE dev, sdrplay_api_TunerSelectT *tuner, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t)(double *currentSampleRate);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoMode_t)(sdrplay_api_DeviceT *currDevice, sdrplay_api_DeviceParamsT **deviceParams,
|
||||
sdrplay_api_RspDuoModeT rspDuoMode, double sampleRate, sdrplay_api_TunerSelectT tuner,
|
||||
sdrplay_api_Bw_MHzT bwType, sdrplay_api_If_kHzT ifType, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
||||
|
||||
// API function definitions
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
// Comman API function definitions
|
||||
sdrplay_api_ErrT sdrplay_api_Open(void);
|
||||
sdrplay_api_ErrT sdrplay_api_Close(void);
|
||||
sdrplay_api_ErrT sdrplay_api_ApiVersion(float *apiVer);
|
||||
sdrplay_api_ErrT sdrplay_api_LockDeviceApi(void);
|
||||
sdrplay_api_ErrT sdrplay_api_UnlockDeviceApi(void);
|
||||
sdrplay_api_ErrT sdrplay_api_GetDevices(sdrplay_api_DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs);
|
||||
sdrplay_api_ErrT sdrplay_api_SelectDevice(sdrplay_api_DeviceT *device);
|
||||
sdrplay_api_ErrT sdrplay_api_ReleaseDevice(sdrplay_api_DeviceT *device);
|
||||
const char* sdrplay_api_GetErrorString(sdrplay_api_ErrT err);
|
||||
sdrplay_api_ErrorInfoT* sdrplay_api_GetLastError(sdrplay_api_DeviceT *device);
|
||||
sdrplay_api_ErrT sdrplay_api_DisableHeartbeat(void); // Must be called before sdrplay_api_SelectDevice()
|
||||
|
||||
// Device API function definitions
|
||||
sdrplay_api_ErrT sdrplay_api_DebugEnable(HANDLE dev, sdrplay_api_DbgLvl_t enable);
|
||||
sdrplay_api_ErrT sdrplay_api_GetDeviceParams(HANDLE dev, sdrplay_api_DeviceParamsT **deviceParams);
|
||||
sdrplay_api_ErrT sdrplay_api_Init(HANDLE dev, sdrplay_api_CallbackFnsT *callbackFns, void *cbContext);
|
||||
sdrplay_api_ErrT sdrplay_api_Uninit(HANDLE dev);
|
||||
sdrplay_api_ErrT sdrplay_api_Update(HANDLE dev, sdrplay_api_TunerSelectT tuner, sdrplay_api_ReasonForUpdateT reasonForUpdate, sdrplay_api_ReasonForUpdateExtension1T reasonForUpdateExt1);
|
||||
sdrplay_api_ErrT sdrplay_api_SwapRspDuoActiveTuner(HANDLE dev, sdrplay_api_TunerSelectT *currentTuner, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
||||
sdrplay_api_ErrT sdrplay_api_SwapRspDuoDualTunerModeSampleRate(HANDLE dev, double *currentSampleRate);
|
||||
sdrplay_api_ErrT sdrplay_api_SwapRspDuoMode(sdrplay_api_DeviceT *currDevice, sdrplay_api_DeviceParamsT **deviceParams,
|
||||
sdrplay_api_RspDuoModeT rspDuoMode, double sampleRate, sdrplay_api_TunerSelectT tuner,
|
||||
sdrplay_api_Bw_MHzT bwType, sdrplay_api_If_kHzT ifType, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //SDRPLAY_API_H
|
||||
78
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_callback.h
Normal file
78
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_callback.h
Normal file
@@ -0,0 +1,78 @@
|
||||
#ifndef SDRPLAY_API_CALLBACK_H
|
||||
#define SDRPLAY_API_CALLBACK_H
|
||||
|
||||
// Event callback enums
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_Overload_Detected = 0,
|
||||
sdrplay_api_Overload_Corrected = 1,
|
||||
} sdrplay_api_PowerOverloadCbEventIdT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_MasterInitialised = 0,
|
||||
sdrplay_api_SlaveAttached = 1,
|
||||
sdrplay_api_SlaveDetached = 2,
|
||||
sdrplay_api_SlaveInitialised = 3,
|
||||
sdrplay_api_SlaveUninitialised = 4,
|
||||
sdrplay_api_MasterDllDisappeared = 5,
|
||||
sdrplay_api_SlaveDllDisappeared = 6,
|
||||
} sdrplay_api_RspDuoModeCbEventIdT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_GainChange = 0,
|
||||
sdrplay_api_PowerOverloadChange = 1,
|
||||
sdrplay_api_DeviceRemoved = 2,
|
||||
sdrplay_api_RspDuoModeChange = 3,
|
||||
} sdrplay_api_EventT;
|
||||
|
||||
// Event callback parameter structs
|
||||
typedef struct
|
||||
{
|
||||
unsigned int gRdB;
|
||||
unsigned int lnaGRdB;
|
||||
double currGain;
|
||||
} sdrplay_api_GainCbParamT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_PowerOverloadCbEventIdT powerOverloadChangeType;
|
||||
} sdrplay_api_PowerOverloadCbParamT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_RspDuoModeCbEventIdT modeChangeType;
|
||||
} sdrplay_api_RspDuoModeCbParamT;
|
||||
|
||||
// Event parameters overlay
|
||||
typedef union
|
||||
{
|
||||
sdrplay_api_GainCbParamT gainParams;
|
||||
sdrplay_api_PowerOverloadCbParamT powerOverloadParams;
|
||||
sdrplay_api_RspDuoModeCbParamT rspDuoModeParams;
|
||||
} sdrplay_api_EventParamsT;
|
||||
|
||||
// Stream callback parameter structs
|
||||
typedef struct
|
||||
{
|
||||
unsigned int firstSampleNum;
|
||||
int grChanged;
|
||||
int rfChanged;
|
||||
int fsChanged;
|
||||
unsigned int numSamples;
|
||||
} sdrplay_api_StreamCbParamsT;
|
||||
|
||||
// Callback function prototypes
|
||||
typedef void (*sdrplay_api_StreamCallback_t)(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext);
|
||||
typedef void (*sdrplay_api_EventCallback_t)(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext);
|
||||
|
||||
// Callback function struct
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_StreamCallback_t StreamACbFn;
|
||||
sdrplay_api_StreamCallback_t StreamBCbFn;
|
||||
sdrplay_api_EventCallback_t EventCbFn;
|
||||
} sdrplay_api_CallbackFnsT;
|
||||
|
||||
#endif //SDRPLAY_API_CALLBACK_H
|
||||
55
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_control.h
Normal file
55
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_control.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef SDRPLAY_API_CONTROL_H
|
||||
#define SDRPLAY_API_CONTROL_H
|
||||
|
||||
// Control parameter enums
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_AGC_DISABLE = 0,
|
||||
sdrplay_api_AGC_100HZ = 1,
|
||||
sdrplay_api_AGC_50HZ = 2,
|
||||
sdrplay_api_AGC_5HZ = 3,
|
||||
sdrplay_api_AGC_CTRL_EN = 4
|
||||
} sdrplay_api_AgcControlT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_ADSB_DECIMATION = 0,
|
||||
sdrplay_api_ADSB_NO_DECIMATION_LOWPASS = 1,
|
||||
sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_2MHZ = 2,
|
||||
sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_3MHZ = 3
|
||||
} sdrplay_api_AdsbModeT;
|
||||
|
||||
// Control parameter structs
|
||||
typedef struct
|
||||
{
|
||||
unsigned char DCenable; // default: 1
|
||||
unsigned char IQenable; // default: 1
|
||||
} sdrplay_api_DcOffsetT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char enable; // default: 0
|
||||
unsigned char decimationFactor; // default: 1
|
||||
unsigned char wideBandSignal; // default: 0
|
||||
} sdrplay_api_DecimationT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_AgcControlT enable; // default: sdrplay_api_AGC_50HZ
|
||||
int setPoint_dBfs; // default: -60
|
||||
unsigned short attack_ms; // default: 0
|
||||
unsigned short decay_ms; // default: 0
|
||||
unsigned short decay_delay_ms; // default: 0
|
||||
unsigned short decay_threshold_dB; // default: 0
|
||||
int syncUpdate; // default: 0
|
||||
} sdrplay_api_AgcT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_DcOffsetT dcOffset;
|
||||
sdrplay_api_DecimationT decimation;
|
||||
sdrplay_api_AgcT agc;
|
||||
sdrplay_api_AdsbModeT adsbMode; //default: sdrplay_api_ADSB_DECIMATION
|
||||
} sdrplay_api_ControlParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_CONTROL_H
|
||||
51
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_dev.h
Normal file
51
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_dev.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef SDRPLAY_API_DEV_H
|
||||
#define SDRPLAY_API_DEV_H
|
||||
|
||||
#include "sdrplay_api_rsp1a.h"
|
||||
#include "sdrplay_api_rsp2.h"
|
||||
#include "sdrplay_api_rspDuo.h"
|
||||
#include "sdrplay_api_rspDx.h"
|
||||
|
||||
// Dev parameter enums
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_ISOCH = 0,
|
||||
sdrplay_api_BULK = 1
|
||||
} sdrplay_api_TransferModeT;
|
||||
|
||||
// Dev parameter structs
|
||||
typedef struct
|
||||
{
|
||||
double fsHz; // default: 2000000.0
|
||||
unsigned char syncUpdate; // default: 0
|
||||
unsigned char reCal; // default: 0
|
||||
} sdrplay_api_FsFreqT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int sampleNum; // default: 0
|
||||
unsigned int period; // default: 0
|
||||
} sdrplay_api_SyncUpdateT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char resetGainUpdate; // default: 0
|
||||
unsigned char resetRfUpdate; // default: 0
|
||||
unsigned char resetFsUpdate; // default: 0
|
||||
} sdrplay_api_ResetFlagsT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double ppm; // default: 0.0
|
||||
sdrplay_api_FsFreqT fsFreq;
|
||||
sdrplay_api_SyncUpdateT syncUpdate;
|
||||
sdrplay_api_ResetFlagsT resetFlags;
|
||||
sdrplay_api_TransferModeT mode; // default: sdrplay_api_ISOCH
|
||||
unsigned int samplesPerPkt; // default: 0 (output param)
|
||||
sdrplay_api_Rsp1aParamsT rsp1aParams;
|
||||
sdrplay_api_Rsp2ParamsT rsp2Params;
|
||||
sdrplay_api_RspDuoParamsT rspDuoParams;
|
||||
sdrplay_api_RspDxParamsT rspDxParams;
|
||||
} sdrplay_api_DevParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_DEV_H
|
||||
22
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_rsp1a.h
Normal file
22
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_rsp1a.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef SDRPLAY_API_RSP1A_H
|
||||
#define SDRPLAY_API_RSP1A_H
|
||||
|
||||
#define RSPIA_NUM_LNA_STATES 10
|
||||
#define RSPIA_NUM_LNA_STATES_AM 7
|
||||
#define RSPIA_NUM_LNA_STATES_LBAND 9
|
||||
|
||||
// RSP1A parameter enums
|
||||
|
||||
// RSP1A parameter structs
|
||||
typedef struct
|
||||
{
|
||||
unsigned char rfNotchEnable; // default: 0
|
||||
unsigned char rfDabNotchEnable; // default: 0
|
||||
} sdrplay_api_Rsp1aParamsT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char biasTEnable; // default: 0
|
||||
} sdrplay_api_Rsp1aTunerParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_RSP1A_H
|
||||
35
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_rsp2.h
Normal file
35
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_rsp2.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef SDRPLAY_API_RSP2_H
|
||||
#define SDRPLAY_API_RSP2_H
|
||||
|
||||
#define RSPII_NUM_LNA_STATES 9
|
||||
#define RSPII_NUM_LNA_STATES_AMPORT 5
|
||||
#define RSPII_NUM_LNA_STATES_420MHZ 6
|
||||
|
||||
// RSP2 parameter enums
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_Rsp2_ANTENNA_A = 5,
|
||||
sdrplay_api_Rsp2_ANTENNA_B = 6,
|
||||
} sdrplay_api_Rsp2_AntennaSelectT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_Rsp2_AMPORT_1 = 1,
|
||||
sdrplay_api_Rsp2_AMPORT_2 = 0,
|
||||
} sdrplay_api_Rsp2_AmPortSelectT;
|
||||
|
||||
// RSP2 parameter structs
|
||||
typedef struct
|
||||
{
|
||||
unsigned char extRefOutputEn; // default: 0
|
||||
} sdrplay_api_Rsp2ParamsT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char biasTEnable; // default: 0
|
||||
sdrplay_api_Rsp2_AmPortSelectT amPortSel; // default: sdrplay_api_Rsp2_AMPORT_2
|
||||
sdrplay_api_Rsp2_AntennaSelectT antennaSel; // default: sdrplay_api_Rsp2_ANTENNA_A
|
||||
unsigned char rfNotchEnable; // default: 0
|
||||
} sdrplay_api_Rsp2TunerParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_RSP2_H
|
||||
40
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_rspDuo.h
Normal file
40
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_rspDuo.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef SDRPLAY_API_RSPduo_H
|
||||
#define SDRPLAY_API_RSPduo_H
|
||||
|
||||
#define RSPDUO_NUM_LNA_STATES 10
|
||||
#define RSPDUO_NUM_LNA_STATES_AMPORT 5
|
||||
#define RSPDUO_NUM_LNA_STATES_AM 7
|
||||
#define RSPDUO_NUM_LNA_STATES_LBAND 9
|
||||
|
||||
// RSPduo parameter enums
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_RspDuoMode_Unknown = 0,
|
||||
sdrplay_api_RspDuoMode_Single_Tuner = 1,
|
||||
sdrplay_api_RspDuoMode_Dual_Tuner = 2,
|
||||
sdrplay_api_RspDuoMode_Master = 4,
|
||||
sdrplay_api_RspDuoMode_Slave = 8,
|
||||
} sdrplay_api_RspDuoModeT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_RspDuo_AMPORT_1 = 1,
|
||||
sdrplay_api_RspDuo_AMPORT_2 = 0,
|
||||
} sdrplay_api_RspDuo_AmPortSelectT;
|
||||
|
||||
// RSPduo parameter structs
|
||||
typedef struct
|
||||
{
|
||||
int extRefOutputEn; // default: 0
|
||||
} sdrplay_api_RspDuoParamsT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char biasTEnable; // default: 0
|
||||
sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel; // default: sdrplay_api_RspDuo_AMPORT_2
|
||||
unsigned char tuner1AmNotchEnable; // default: 0
|
||||
unsigned char rfNotchEnable; // default: 0
|
||||
unsigned char rfDabNotchEnable; // default: 0
|
||||
} sdrplay_api_RspDuoTunerParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_RSPduo_H
|
||||
45
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_rspDx.h
Normal file
45
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_rspDx.h
Normal file
@@ -0,0 +1,45 @@
|
||||
#ifndef SDRPLAY_API_RSPDX_H
|
||||
#define SDRPLAY_API_RSPDX_H
|
||||
|
||||
#include "sdrplay_api_tuner.h"
|
||||
|
||||
#define RSPDX_NUM_LNA_STATES 28 // Number of LNA states in all bands (except where defined differently below)
|
||||
#define RSPDX_NUM_LNA_STATES_AMPORT2_0_12 19 // Number of LNA states when using AM Port 2 between 0 and 12MHz
|
||||
#define RSPDX_NUM_LNA_STATES_AMPORT2_12_60 20 // Number of LNA states when using AM Port 2 between 12 and 60MHz
|
||||
#define RSPDX_NUM_LNA_STATES_VHF_BAND3 27 // Number of LNA states in VHF and Band3
|
||||
#define RSPDX_NUM_LNA_STATES_420MHZ 21 // Number of LNA states in 420MHz band
|
||||
#define RSPDX_NUM_LNA_STATES_LBAND 19 // Number of LNA states in L-band
|
||||
#define RSPDX_NUM_LNA_STATES_DX 26 // Number of LNA states in DX path
|
||||
|
||||
// RSPdx parameter enums
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_RspDx_ANTENNA_A = 0,
|
||||
sdrplay_api_RspDx_ANTENNA_B = 1,
|
||||
sdrplay_api_RspDx_ANTENNA_C = 2,
|
||||
} sdrplay_api_RspDx_AntennaSelectT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_RspDx_HDRMODE_BW_0_200 = 0,
|
||||
sdrplay_api_RspDx_HDRMODE_BW_0_500 = 1,
|
||||
sdrplay_api_RspDx_HDRMODE_BW_1_200 = 2,
|
||||
sdrplay_api_RspDx_HDRMODE_BW_1_700 = 3,
|
||||
} sdrplay_api_RspDx_HdrModeBwT;
|
||||
|
||||
// RSPdx parameter structs
|
||||
typedef struct
|
||||
{
|
||||
unsigned char hdrEnable; // default: 0
|
||||
unsigned char biasTEnable; // default: 0
|
||||
sdrplay_api_RspDx_AntennaSelectT antennaSel; // default: sdrplay_api_RspDx_ANTENNA_A
|
||||
unsigned char rfNotchEnable; // default: 0
|
||||
unsigned char rfDabNotchEnable; // default: 0
|
||||
} sdrplay_api_RspDxParamsT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_RspDx_HdrModeBwT hdrBw; // default: sdrplay_api_RspDx_HDRMODE_BW_1_700
|
||||
} sdrplay_api_RspDxTunerParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_RSPDX_H
|
||||
21
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_rx_channel.h
Normal file
21
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_rx_channel.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef SDRPLAY_API_RX_CHANNEL_H
|
||||
#define SDRPLAY_API_RX_CHANNEL_H
|
||||
|
||||
#include "sdrplay_api_tuner.h"
|
||||
#include "sdrplay_api_control.h"
|
||||
#include "sdrplay_api_rsp1a.h"
|
||||
#include "sdrplay_api_rsp2.h"
|
||||
#include "sdrplay_api_rspDuo.h"
|
||||
#include "sdrplay_api_rspDx.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_TunerParamsT tunerParams;
|
||||
sdrplay_api_ControlParamsT ctrlParams;
|
||||
sdrplay_api_Rsp1aTunerParamsT rsp1aTunerParams;
|
||||
sdrplay_api_Rsp2TunerParamsT rsp2TunerParams;
|
||||
sdrplay_api_RspDuoTunerParamsT rspDuoTunerParams;
|
||||
sdrplay_api_RspDxTunerParamsT rspDxTunerParams;
|
||||
} sdrplay_api_RxChannelParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_RX_CHANNEL_H
|
||||
93
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_tuner.h
Normal file
93
artifacts/sdrplay-api-headers/v3_07/sdrplay_api_tuner.h
Normal file
@@ -0,0 +1,93 @@
|
||||
#ifndef SDRPLAY_API_TUNER_H
|
||||
#define SDRPLAY_API_TUNER_H
|
||||
|
||||
#define MAX_BB_GR (59)
|
||||
|
||||
// Tuner parameter enums
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_BW_Undefined = 0,
|
||||
sdrplay_api_BW_0_200 = 200,
|
||||
sdrplay_api_BW_0_300 = 300,
|
||||
sdrplay_api_BW_0_600 = 600,
|
||||
sdrplay_api_BW_1_536 = 1536,
|
||||
sdrplay_api_BW_5_000 = 5000,
|
||||
sdrplay_api_BW_6_000 = 6000,
|
||||
sdrplay_api_BW_7_000 = 7000,
|
||||
sdrplay_api_BW_8_000 = 8000
|
||||
} sdrplay_api_Bw_MHzT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_IF_Undefined = -1,
|
||||
sdrplay_api_IF_Zero = 0,
|
||||
sdrplay_api_IF_0_450 = 450,
|
||||
sdrplay_api_IF_1_620 = 1620,
|
||||
sdrplay_api_IF_2_048 = 2048
|
||||
} sdrplay_api_If_kHzT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_LO_Undefined = 0,
|
||||
sdrplay_api_LO_Auto = 1,
|
||||
sdrplay_api_LO_120MHz = 2,
|
||||
sdrplay_api_LO_144MHz = 3,
|
||||
sdrplay_api_LO_168MHz = 4
|
||||
} sdrplay_api_LoModeT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_EXTENDED_MIN_GR = 0,
|
||||
sdrplay_api_NORMAL_MIN_GR = 20
|
||||
} sdrplay_api_MinGainReductionT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_Tuner_Neither = 0,
|
||||
sdrplay_api_Tuner_A = 1,
|
||||
sdrplay_api_Tuner_B = 2,
|
||||
sdrplay_api_Tuner_Both = 3,
|
||||
} sdrplay_api_TunerSelectT;
|
||||
|
||||
// Tuner parameter structs
|
||||
typedef struct
|
||||
{
|
||||
float curr;
|
||||
float max;
|
||||
float min;
|
||||
} sdrplay_api_GainValuesT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int gRdB; // default: 50
|
||||
unsigned char LNAstate; // default: 0
|
||||
unsigned char syncUpdate; // default: 0
|
||||
sdrplay_api_MinGainReductionT minGr; // default: sdrplay_api_NORMAL_MIN_GR
|
||||
sdrplay_api_GainValuesT gainVals; // output parameter
|
||||
} sdrplay_api_GainT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double rfHz; // default: 200000000.0
|
||||
unsigned char syncUpdate; // default: 0
|
||||
} sdrplay_api_RfFreqT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char dcCal; // default: 3 (Periodic mode)
|
||||
unsigned char speedUp; // default: 0 (No speedup)
|
||||
int trackTime; // default: 1 (=> time in uSec = (72 * 3 * trackTime) / 24e6 = 9uSec)
|
||||
int refreshRateTime; // default: 2048 (=> time in uSec = (72 * 3 * refreshRateTime) / 24e6 = 18432uSec)
|
||||
} sdrplay_api_DcOffsetTunerT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_Bw_MHzT bwType; // default: sdrplay_api_BW_0_200
|
||||
sdrplay_api_If_kHzT ifType; // default: sdrplay_api_IF_Zero
|
||||
sdrplay_api_LoModeT loMode; // default: sdrplay_api_LO_Auto
|
||||
sdrplay_api_GainT gain;
|
||||
sdrplay_api_RfFreqT rfFreq;
|
||||
sdrplay_api_DcOffsetTunerT dcOffsetTuner;
|
||||
} sdrplay_api_TunerParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_TUNER_H
|
||||
230
artifacts/sdrplay-api-headers/v3_11/sdrplay_api.h
Normal file
230
artifacts/sdrplay-api-headers/v3_11/sdrplay_api.h
Normal file
@@ -0,0 +1,230 @@
|
||||
#ifndef SDRPLAY_API_H
|
||||
#define SDRPLAY_API_H
|
||||
|
||||
#include "sdrplay_api_dev.h"
|
||||
#include "sdrplay_api_rx_channel.h"
|
||||
#include "sdrplay_api_callback.h"
|
||||
|
||||
//#if defined(_M_X64) || defined(_M_IX86) || defined(_M_ARM64)
|
||||
//#include "windows.h"
|
||||
//#elif defined (__GNUC__)
|
||||
typedef void *HANDLE;
|
||||
//#endif
|
||||
|
||||
//#ifndef _SDRPLAY_DLL_QUALIFIER
|
||||
//#if !defined(STATIC_LIB) && (defined(_M_X64) || defined(_M_IX86) || defined(_M_ARM64))
|
||||
//#define _SDRPLAY_DLL_QUALIFIER __declspec(dllimport)
|
||||
//#elif defined(STATIC_LIB) || defined(__GNUC__)
|
||||
//#define _SDRPLAY_DLL_QUALIFIER
|
||||
//#endif
|
||||
//#endif // _SDRPLAY_DLL_QUALIFIER
|
||||
|
||||
// Application code should check that it is compiled against the same API version
|
||||
// sdrplay_api_ApiVersion() returns the API version
|
||||
#define SDRPLAY_API_VERSION (float)(3.11)
|
||||
|
||||
// API Constants
|
||||
#define SDRPLAY_MAX_DEVICES (16)
|
||||
#define SDRPLAY_MAX_TUNERS_PER_DEVICE (2)
|
||||
|
||||
#define SDRPLAY_MAX_SER_NO_LEN (64)
|
||||
#define SDRPLAY_MAX_ROOT_NM_LEN (32)
|
||||
|
||||
#define SDRPLAY_RSP1_ID (1)
|
||||
#define SDRPLAY_RSP1A_ID (255)
|
||||
#define SDRPLAY_RSP2_ID (2)
|
||||
#define SDRPLAY_RSPduo_ID (3)
|
||||
#define SDRPLAY_RSPdx_ID (4)
|
||||
|
||||
// Enum types
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_Success = 0,
|
||||
sdrplay_api_Fail = 1,
|
||||
sdrplay_api_InvalidParam = 2,
|
||||
sdrplay_api_OutOfRange = 3,
|
||||
sdrplay_api_GainUpdateError = 4,
|
||||
sdrplay_api_RfUpdateError = 5,
|
||||
sdrplay_api_FsUpdateError = 6,
|
||||
sdrplay_api_HwError = 7,
|
||||
sdrplay_api_AliasingError = 8,
|
||||
sdrplay_api_AlreadyInitialised = 9,
|
||||
sdrplay_api_NotInitialised = 10,
|
||||
sdrplay_api_NotEnabled = 11,
|
||||
sdrplay_api_HwVerError = 12,
|
||||
sdrplay_api_OutOfMemError = 13,
|
||||
sdrplay_api_ServiceNotResponding = 14,
|
||||
sdrplay_api_StartPending = 15,
|
||||
sdrplay_api_StopPending = 16,
|
||||
sdrplay_api_InvalidMode = 17,
|
||||
sdrplay_api_FailedVerification1 = 18,
|
||||
sdrplay_api_FailedVerification2 = 19,
|
||||
sdrplay_api_FailedVerification3 = 20,
|
||||
sdrplay_api_FailedVerification4 = 21,
|
||||
sdrplay_api_FailedVerification5 = 22,
|
||||
sdrplay_api_FailedVerification6 = 23,
|
||||
sdrplay_api_InvalidServiceVersion = 24
|
||||
} sdrplay_api_ErrT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_Update_None = 0x00000000,
|
||||
|
||||
// Reasons for master only mode
|
||||
sdrplay_api_Update_Dev_Fs = 0x00000001,
|
||||
sdrplay_api_Update_Dev_Ppm = 0x00000002,
|
||||
sdrplay_api_Update_Dev_SyncUpdate = 0x00000004,
|
||||
sdrplay_api_Update_Dev_ResetFlags = 0x00000008,
|
||||
|
||||
sdrplay_api_Update_Rsp1a_BiasTControl = 0x00000010,
|
||||
sdrplay_api_Update_Rsp1a_RfNotchControl = 0x00000020,
|
||||
sdrplay_api_Update_Rsp1a_RfDabNotchControl = 0x00000040,
|
||||
|
||||
sdrplay_api_Update_Rsp2_BiasTControl = 0x00000080,
|
||||
sdrplay_api_Update_Rsp2_AmPortSelect = 0x00000100,
|
||||
sdrplay_api_Update_Rsp2_AntennaControl = 0x00000200,
|
||||
sdrplay_api_Update_Rsp2_RfNotchControl = 0x00000400,
|
||||
sdrplay_api_Update_Rsp2_ExtRefControl = 0x00000800,
|
||||
|
||||
sdrplay_api_Update_RspDuo_ExtRefControl = 0x00001000,
|
||||
|
||||
sdrplay_api_Update_Master_Spare_1 = 0x00002000,
|
||||
sdrplay_api_Update_Master_Spare_2 = 0x00004000,
|
||||
|
||||
// Reasons for master and slave mode
|
||||
// Note: sdrplay_api_Update_Tuner_Gr MUST be the first value defined in this section!
|
||||
sdrplay_api_Update_Tuner_Gr = 0x00008000,
|
||||
sdrplay_api_Update_Tuner_GrLimits = 0x00010000,
|
||||
sdrplay_api_Update_Tuner_Frf = 0x00020000,
|
||||
sdrplay_api_Update_Tuner_BwType = 0x00040000,
|
||||
sdrplay_api_Update_Tuner_IfType = 0x00080000,
|
||||
sdrplay_api_Update_Tuner_DcOffset = 0x00100000,
|
||||
sdrplay_api_Update_Tuner_LoMode = 0x00200000,
|
||||
|
||||
sdrplay_api_Update_Ctrl_DCoffsetIQimbalance = 0x00400000,
|
||||
sdrplay_api_Update_Ctrl_Decimation = 0x00800000,
|
||||
sdrplay_api_Update_Ctrl_Agc = 0x01000000,
|
||||
sdrplay_api_Update_Ctrl_AdsbMode = 0x02000000,
|
||||
sdrplay_api_Update_Ctrl_OverloadMsgAck = 0x04000000,
|
||||
|
||||
sdrplay_api_Update_RspDuo_BiasTControl = 0x08000000,
|
||||
sdrplay_api_Update_RspDuo_AmPortSelect = 0x10000000,
|
||||
sdrplay_api_Update_RspDuo_Tuner1AmNotchControl = 0x20000000,
|
||||
sdrplay_api_Update_RspDuo_RfNotchControl = 0x40000000,
|
||||
sdrplay_api_Update_RspDuo_RfDabNotchControl = 0x80000000,
|
||||
} sdrplay_api_ReasonForUpdateT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_Update_Ext1_None = 0x00000000,
|
||||
|
||||
// Reasons for master only mode
|
||||
sdrplay_api_Update_RspDx_HdrEnable = 0x00000001,
|
||||
sdrplay_api_Update_RspDx_BiasTControl = 0x00000002,
|
||||
sdrplay_api_Update_RspDx_AntennaControl = 0x00000004,
|
||||
sdrplay_api_Update_RspDx_RfNotchControl = 0x00000008,
|
||||
sdrplay_api_Update_RspDx_RfDabNotchControl = 0x00000010,
|
||||
sdrplay_api_Update_RspDx_HdrBw = 0x00000020,
|
||||
|
||||
// Reasons for master and slave mode
|
||||
} sdrplay_api_ReasonForUpdateExtension1T;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_DbgLvl_Disable = 0,
|
||||
sdrplay_api_DbgLvl_Verbose = 1,
|
||||
sdrplay_api_DbgLvl_Warning = 2,
|
||||
sdrplay_api_DbgLvl_Error = 3,
|
||||
sdrplay_api_DbgLvl_Message = 4,
|
||||
} sdrplay_api_DbgLvl_t;
|
||||
|
||||
// Device structure
|
||||
typedef struct
|
||||
{
|
||||
char SerNo[SDRPLAY_MAX_SER_NO_LEN];
|
||||
unsigned char hwVer;
|
||||
sdrplay_api_TunerSelectT tuner;
|
||||
sdrplay_api_RspDuoModeT rspDuoMode;
|
||||
unsigned char valid;
|
||||
double rspDuoSampleFreq;
|
||||
HANDLE dev;
|
||||
} sdrplay_api_DeviceT;
|
||||
|
||||
// Device parameter structure
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_DevParamsT *devParams;
|
||||
sdrplay_api_RxChannelParamsT *rxChannelA;
|
||||
sdrplay_api_RxChannelParamsT *rxChannelB;
|
||||
} sdrplay_api_DeviceParamsT;
|
||||
|
||||
// Extended error message structure
|
||||
typedef struct
|
||||
{
|
||||
char file[256];
|
||||
char function[256];
|
||||
int line;
|
||||
char message[1024];
|
||||
} sdrplay_api_ErrorInfoT;
|
||||
|
||||
// Comman API function types
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_Open_t)(void);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_Close_t)(void);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_ApiVersion_t)(float *apiVer);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_LockDeviceApi_t)(void);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_UnlockDeviceApi_t)(void);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_GetDevices_t)(sdrplay_api_DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_SelectDevice_t)(sdrplay_api_DeviceT *device);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_ReleaseDevice_t)(sdrplay_api_DeviceT *device);
|
||||
typedef const char* (*sdrplay_api_GetErrorString_t)(sdrplay_api_ErrT err);
|
||||
typedef sdrplay_api_ErrorInfoT* (*sdrplay_api_GetLastError_t)(sdrplay_api_DeviceT *device);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_DisableHeartbeat_t)(void);
|
||||
|
||||
// Device API function types
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_DebugEnable_t)(HANDLE dev, sdrplay_api_DbgLvl_t dbgLvl);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_GetDeviceParams_t)(HANDLE dev, sdrplay_api_DeviceParamsT **deviceParams);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_Init_t)(HANDLE dev, sdrplay_api_CallbackFnsT *callbackFns, void *cbContext);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_Uninit_t)(HANDLE dev);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_Update_t)(HANDLE dev, sdrplay_api_TunerSelectT tuner, sdrplay_api_ReasonForUpdateT reasonForUpdate, sdrplay_api_ReasonForUpdateExtension1T reasonForUpdateExt1);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoActiveTuner_t)(HANDLE dev, sdrplay_api_TunerSelectT *tuner, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoDualTunerModeSampleRate_t)(double *currentSampleRate, double newSampleRate);
|
||||
typedef sdrplay_api_ErrT (*sdrplay_api_SwapRspDuoMode_t)(sdrplay_api_DeviceT *currDevice, sdrplay_api_DeviceParamsT **deviceParams,
|
||||
sdrplay_api_RspDuoModeT rspDuoMode, double sampleRate, sdrplay_api_TunerSelectT tuner,
|
||||
sdrplay_api_Bw_MHzT bwType, sdrplay_api_If_kHzT ifType, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
||||
|
||||
// API function definitions
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
// Comman API function definitions
|
||||
sdrplay_api_ErrT sdrplay_api_Open(void);
|
||||
sdrplay_api_ErrT sdrplay_api_Close(void);
|
||||
sdrplay_api_ErrT sdrplay_api_ApiVersion(float *apiVer);
|
||||
sdrplay_api_ErrT sdrplay_api_LockDeviceApi(void);
|
||||
sdrplay_api_ErrT sdrplay_api_UnlockDeviceApi(void);
|
||||
sdrplay_api_ErrT sdrplay_api_GetDevices(sdrplay_api_DeviceT *devices, unsigned int *numDevs, unsigned int maxDevs);
|
||||
sdrplay_api_ErrT sdrplay_api_SelectDevice(sdrplay_api_DeviceT *device);
|
||||
sdrplay_api_ErrT sdrplay_api_ReleaseDevice(sdrplay_api_DeviceT *device);
|
||||
const char* sdrplay_api_GetErrorString(sdrplay_api_ErrT err);
|
||||
sdrplay_api_ErrorInfoT* sdrplay_api_GetLastError(sdrplay_api_DeviceT *device);
|
||||
sdrplay_api_ErrT sdrplay_api_DisableHeartbeat(void); // Must be called before sdrplay_api_SelectDevice()
|
||||
|
||||
// Device API function definitions
|
||||
sdrplay_api_ErrT sdrplay_api_DebugEnable(HANDLE dev, sdrplay_api_DbgLvl_t enable);
|
||||
sdrplay_api_ErrT sdrplay_api_GetDeviceParams(HANDLE dev, sdrplay_api_DeviceParamsT **deviceParams);
|
||||
sdrplay_api_ErrT sdrplay_api_Init(HANDLE dev, sdrplay_api_CallbackFnsT *callbackFns, void *cbContext);
|
||||
sdrplay_api_ErrT sdrplay_api_Uninit(HANDLE dev);
|
||||
sdrplay_api_ErrT sdrplay_api_Update(HANDLE dev, sdrplay_api_TunerSelectT tuner, sdrplay_api_ReasonForUpdateT reasonForUpdate, sdrplay_api_ReasonForUpdateExtension1T reasonForUpdateExt1);
|
||||
sdrplay_api_ErrT sdrplay_api_SwapRspDuoActiveTuner(HANDLE dev, sdrplay_api_TunerSelectT *currentTuner, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
||||
sdrplay_api_ErrT sdrplay_api_SwapRspDuoDualTunerModeSampleRate(HANDLE dev, double *currentSampleRate, double newSampleRate);
|
||||
sdrplay_api_ErrT sdrplay_api_SwapRspDuoMode(sdrplay_api_DeviceT *currDevice, sdrplay_api_DeviceParamsT **deviceParams,
|
||||
sdrplay_api_RspDuoModeT rspDuoMode, double sampleRate, sdrplay_api_TunerSelectT tuner,
|
||||
sdrplay_api_Bw_MHzT bwType, sdrplay_api_If_kHzT ifType, sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //SDRPLAY_API_H
|
||||
79
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_callback.h
Normal file
79
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_callback.h
Normal file
@@ -0,0 +1,79 @@
|
||||
#ifndef SDRPLAY_API_CALLBACK_H
|
||||
#define SDRPLAY_API_CALLBACK_H
|
||||
|
||||
// Event callback enums
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_Overload_Detected = 0,
|
||||
sdrplay_api_Overload_Corrected = 1,
|
||||
} sdrplay_api_PowerOverloadCbEventIdT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_MasterInitialised = 0,
|
||||
sdrplay_api_SlaveAttached = 1,
|
||||
sdrplay_api_SlaveDetached = 2,
|
||||
sdrplay_api_SlaveInitialised = 3,
|
||||
sdrplay_api_SlaveUninitialised = 4,
|
||||
sdrplay_api_MasterDllDisappeared = 5,
|
||||
sdrplay_api_SlaveDllDisappeared = 6,
|
||||
} sdrplay_api_RspDuoModeCbEventIdT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_GainChange = 0,
|
||||
sdrplay_api_PowerOverloadChange = 1,
|
||||
sdrplay_api_DeviceRemoved = 2,
|
||||
sdrplay_api_RspDuoModeChange = 3,
|
||||
sdrplay_api_DeviceFailure = 4,
|
||||
} sdrplay_api_EventT;
|
||||
|
||||
// Event callback parameter structs
|
||||
typedef struct
|
||||
{
|
||||
unsigned int gRdB;
|
||||
unsigned int lnaGRdB;
|
||||
double currGain;
|
||||
} sdrplay_api_GainCbParamT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_PowerOverloadCbEventIdT powerOverloadChangeType;
|
||||
} sdrplay_api_PowerOverloadCbParamT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_RspDuoModeCbEventIdT modeChangeType;
|
||||
} sdrplay_api_RspDuoModeCbParamT;
|
||||
|
||||
// Event parameters overlay
|
||||
typedef union
|
||||
{
|
||||
sdrplay_api_GainCbParamT gainParams;
|
||||
sdrplay_api_PowerOverloadCbParamT powerOverloadParams;
|
||||
sdrplay_api_RspDuoModeCbParamT rspDuoModeParams;
|
||||
} sdrplay_api_EventParamsT;
|
||||
|
||||
// Stream callback parameter structs
|
||||
typedef struct
|
||||
{
|
||||
unsigned int firstSampleNum;
|
||||
int grChanged;
|
||||
int rfChanged;
|
||||
int fsChanged;
|
||||
unsigned int numSamples;
|
||||
} sdrplay_api_StreamCbParamsT;
|
||||
|
||||
// Callback function prototypes
|
||||
typedef void (*sdrplay_api_StreamCallback_t)(short *xi, short *xq, sdrplay_api_StreamCbParamsT *params, unsigned int numSamples, unsigned int reset, void *cbContext);
|
||||
typedef void (*sdrplay_api_EventCallback_t)(sdrplay_api_EventT eventId, sdrplay_api_TunerSelectT tuner, sdrplay_api_EventParamsT *params, void *cbContext);
|
||||
|
||||
// Callback function struct
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_StreamCallback_t StreamACbFn;
|
||||
sdrplay_api_StreamCallback_t StreamBCbFn;
|
||||
sdrplay_api_EventCallback_t EventCbFn;
|
||||
} sdrplay_api_CallbackFnsT;
|
||||
|
||||
#endif //SDRPLAY_API_CALLBACK_H
|
||||
55
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_control.h
Normal file
55
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_control.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef SDRPLAY_API_CONTROL_H
|
||||
#define SDRPLAY_API_CONTROL_H
|
||||
|
||||
// Control parameter enums
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_AGC_DISABLE = 0,
|
||||
sdrplay_api_AGC_100HZ = 1,
|
||||
sdrplay_api_AGC_50HZ = 2,
|
||||
sdrplay_api_AGC_5HZ = 3,
|
||||
sdrplay_api_AGC_CTRL_EN = 4
|
||||
} sdrplay_api_AgcControlT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_ADSB_DECIMATION = 0,
|
||||
sdrplay_api_ADSB_NO_DECIMATION_LOWPASS = 1,
|
||||
sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_2MHZ = 2,
|
||||
sdrplay_api_ADSB_NO_DECIMATION_BANDPASS_3MHZ = 3
|
||||
} sdrplay_api_AdsbModeT;
|
||||
|
||||
// Control parameter structs
|
||||
typedef struct
|
||||
{
|
||||
unsigned char DCenable; // default: 1
|
||||
unsigned char IQenable; // default: 1
|
||||
} sdrplay_api_DcOffsetT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char enable; // default: 0
|
||||
unsigned char decimationFactor; // default: 1
|
||||
unsigned char wideBandSignal; // default: 0
|
||||
} sdrplay_api_DecimationT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_AgcControlT enable; // default: sdrplay_api_AGC_50HZ
|
||||
int setPoint_dBfs; // default: -60
|
||||
unsigned short attack_ms; // default: 0
|
||||
unsigned short decay_ms; // default: 0
|
||||
unsigned short decay_delay_ms; // default: 0
|
||||
unsigned short decay_threshold_dB; // default: 0
|
||||
int syncUpdate; // default: 0
|
||||
} sdrplay_api_AgcT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_DcOffsetT dcOffset;
|
||||
sdrplay_api_DecimationT decimation;
|
||||
sdrplay_api_AgcT agc;
|
||||
sdrplay_api_AdsbModeT adsbMode; //default: sdrplay_api_ADSB_DECIMATION
|
||||
} sdrplay_api_ControlParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_CONTROL_H
|
||||
51
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_dev.h
Normal file
51
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_dev.h
Normal file
@@ -0,0 +1,51 @@
|
||||
#ifndef SDRPLAY_API_DEV_H
|
||||
#define SDRPLAY_API_DEV_H
|
||||
|
||||
#include "sdrplay_api_rsp1a.h"
|
||||
#include "sdrplay_api_rsp2.h"
|
||||
#include "sdrplay_api_rspDuo.h"
|
||||
#include "sdrplay_api_rspDx.h"
|
||||
|
||||
// Dev parameter enums
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_ISOCH = 0,
|
||||
sdrplay_api_BULK = 1
|
||||
} sdrplay_api_TransferModeT;
|
||||
|
||||
// Dev parameter structs
|
||||
typedef struct
|
||||
{
|
||||
double fsHz; // default: 2000000.0
|
||||
unsigned char syncUpdate; // default: 0
|
||||
unsigned char reCal; // default: 0
|
||||
} sdrplay_api_FsFreqT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned int sampleNum; // default: 0
|
||||
unsigned int period; // default: 0
|
||||
} sdrplay_api_SyncUpdateT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char resetGainUpdate; // default: 0
|
||||
unsigned char resetRfUpdate; // default: 0
|
||||
unsigned char resetFsUpdate; // default: 0
|
||||
} sdrplay_api_ResetFlagsT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double ppm; // default: 0.0
|
||||
sdrplay_api_FsFreqT fsFreq;
|
||||
sdrplay_api_SyncUpdateT syncUpdate;
|
||||
sdrplay_api_ResetFlagsT resetFlags;
|
||||
sdrplay_api_TransferModeT mode; // default: sdrplay_api_ISOCH
|
||||
unsigned int samplesPerPkt; // default: 0 (output param)
|
||||
sdrplay_api_Rsp1aParamsT rsp1aParams;
|
||||
sdrplay_api_Rsp2ParamsT rsp2Params;
|
||||
sdrplay_api_RspDuoParamsT rspDuoParams;
|
||||
sdrplay_api_RspDxParamsT rspDxParams;
|
||||
} sdrplay_api_DevParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_DEV_H
|
||||
22
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_rsp1a.h
Normal file
22
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_rsp1a.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef SDRPLAY_API_RSP1A_H
|
||||
#define SDRPLAY_API_RSP1A_H
|
||||
|
||||
#define RSPIA_NUM_LNA_STATES 10
|
||||
#define RSPIA_NUM_LNA_STATES_AM 7
|
||||
#define RSPIA_NUM_LNA_STATES_LBAND 9
|
||||
|
||||
// RSP1A parameter enums
|
||||
|
||||
// RSP1A parameter structs
|
||||
typedef struct
|
||||
{
|
||||
unsigned char rfNotchEnable; // default: 0
|
||||
unsigned char rfDabNotchEnable; // default: 0
|
||||
} sdrplay_api_Rsp1aParamsT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char biasTEnable; // default: 0
|
||||
} sdrplay_api_Rsp1aTunerParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_RSP1A_H
|
||||
35
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_rsp2.h
Normal file
35
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_rsp2.h
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef SDRPLAY_API_RSP2_H
|
||||
#define SDRPLAY_API_RSP2_H
|
||||
|
||||
#define RSPII_NUM_LNA_STATES 9
|
||||
#define RSPII_NUM_LNA_STATES_AMPORT 5
|
||||
#define RSPII_NUM_LNA_STATES_420MHZ 6
|
||||
|
||||
// RSP2 parameter enums
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_Rsp2_ANTENNA_A = 5,
|
||||
sdrplay_api_Rsp2_ANTENNA_B = 6,
|
||||
} sdrplay_api_Rsp2_AntennaSelectT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_Rsp2_AMPORT_1 = 1,
|
||||
sdrplay_api_Rsp2_AMPORT_2 = 0,
|
||||
} sdrplay_api_Rsp2_AmPortSelectT;
|
||||
|
||||
// RSP2 parameter structs
|
||||
typedef struct
|
||||
{
|
||||
unsigned char extRefOutputEn; // default: 0
|
||||
} sdrplay_api_Rsp2ParamsT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char biasTEnable; // default: 0
|
||||
sdrplay_api_Rsp2_AmPortSelectT amPortSel; // default: sdrplay_api_Rsp2_AMPORT_2
|
||||
sdrplay_api_Rsp2_AntennaSelectT antennaSel; // default: sdrplay_api_Rsp2_ANTENNA_A
|
||||
unsigned char rfNotchEnable; // default: 0
|
||||
} sdrplay_api_Rsp2TunerParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_RSP2_H
|
||||
40
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_rspDuo.h
Normal file
40
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_rspDuo.h
Normal file
@@ -0,0 +1,40 @@
|
||||
#ifndef SDRPLAY_API_RSPduo_H
|
||||
#define SDRPLAY_API_RSPduo_H
|
||||
|
||||
#define RSPDUO_NUM_LNA_STATES 10
|
||||
#define RSPDUO_NUM_LNA_STATES_AMPORT 5
|
||||
#define RSPDUO_NUM_LNA_STATES_AM 7
|
||||
#define RSPDUO_NUM_LNA_STATES_LBAND 9
|
||||
|
||||
// RSPduo parameter enums
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_RspDuoMode_Unknown = 0,
|
||||
sdrplay_api_RspDuoMode_Single_Tuner = 1,
|
||||
sdrplay_api_RspDuoMode_Dual_Tuner = 2,
|
||||
sdrplay_api_RspDuoMode_Master = 4,
|
||||
sdrplay_api_RspDuoMode_Slave = 8,
|
||||
} sdrplay_api_RspDuoModeT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_RspDuo_AMPORT_1 = 1,
|
||||
sdrplay_api_RspDuo_AMPORT_2 = 0,
|
||||
} sdrplay_api_RspDuo_AmPortSelectT;
|
||||
|
||||
// RSPduo parameter structs
|
||||
typedef struct
|
||||
{
|
||||
int extRefOutputEn; // default: 0
|
||||
} sdrplay_api_RspDuoParamsT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char biasTEnable; // default: 0
|
||||
sdrplay_api_RspDuo_AmPortSelectT tuner1AmPortSel; // default: sdrplay_api_RspDuo_AMPORT_2
|
||||
unsigned char tuner1AmNotchEnable; // default: 0
|
||||
unsigned char rfNotchEnable; // default: 0
|
||||
unsigned char rfDabNotchEnable; // default: 0
|
||||
} sdrplay_api_RspDuoTunerParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_RSPduo_H
|
||||
46
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_rspDx.h
Normal file
46
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_rspDx.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#ifndef SDRPLAY_API_RSPDX_H
|
||||
#define SDRPLAY_API_RSPDX_H
|
||||
|
||||
#include "sdrplay_api_tuner.h"
|
||||
|
||||
#define RSPDX_NUM_LNA_STATES 28 // Number of LNA states in all bands (except where defined differently below)
|
||||
#define RSPDX_NUM_LNA_STATES_AMPORT2_0_12 19 // Number of LNA states when using AM Port 2 between 0 and 12MHz
|
||||
#define RSPDX_NUM_LNA_STATES_AMPORT2_12_50 20 // Number of LNA states when using AM Port 2 between 12 and 50MHz
|
||||
#define RSPDX_NUM_LNA_STATES_AMPORT2_50_60 25 // Number of LNA states when using AM Port 2 between 50 and 60MHz
|
||||
#define RSPDX_NUM_LNA_STATES_VHF_BAND3 27 // Number of LNA states in VHF and Band3
|
||||
#define RSPDX_NUM_LNA_STATES_420MHZ 21 // Number of LNA states in 420MHz band
|
||||
#define RSPDX_NUM_LNA_STATES_LBAND 19 // Number of LNA states in L-band
|
||||
#define RSPDX_NUM_LNA_STATES_DX 22 // Number of LNA states in DX path
|
||||
|
||||
// RSPdx parameter enums
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_RspDx_ANTENNA_A = 0,
|
||||
sdrplay_api_RspDx_ANTENNA_B = 1,
|
||||
sdrplay_api_RspDx_ANTENNA_C = 2,
|
||||
} sdrplay_api_RspDx_AntennaSelectT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_RspDx_HDRMODE_BW_0_200 = 0,
|
||||
sdrplay_api_RspDx_HDRMODE_BW_0_500 = 1,
|
||||
sdrplay_api_RspDx_HDRMODE_BW_1_200 = 2,
|
||||
sdrplay_api_RspDx_HDRMODE_BW_1_700 = 3,
|
||||
} sdrplay_api_RspDx_HdrModeBwT;
|
||||
|
||||
// RSPdx parameter structs
|
||||
typedef struct
|
||||
{
|
||||
unsigned char hdrEnable; // default: 0
|
||||
unsigned char biasTEnable; // default: 0
|
||||
sdrplay_api_RspDx_AntennaSelectT antennaSel; // default: sdrplay_api_RspDx_ANTENNA_A
|
||||
unsigned char rfNotchEnable; // default: 0
|
||||
unsigned char rfDabNotchEnable; // default: 0
|
||||
} sdrplay_api_RspDxParamsT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_RspDx_HdrModeBwT hdrBw; // default: sdrplay_api_RspDx_HDRMODE_BW_1_700
|
||||
} sdrplay_api_RspDxTunerParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_RSPDX_H
|
||||
21
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_rx_channel.h
Normal file
21
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_rx_channel.h
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef SDRPLAY_API_RX_CHANNEL_H
|
||||
#define SDRPLAY_API_RX_CHANNEL_H
|
||||
|
||||
#include "sdrplay_api_tuner.h"
|
||||
#include "sdrplay_api_control.h"
|
||||
#include "sdrplay_api_rsp1a.h"
|
||||
#include "sdrplay_api_rsp2.h"
|
||||
#include "sdrplay_api_rspDuo.h"
|
||||
#include "sdrplay_api_rspDx.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_TunerParamsT tunerParams;
|
||||
sdrplay_api_ControlParamsT ctrlParams;
|
||||
sdrplay_api_Rsp1aTunerParamsT rsp1aTunerParams;
|
||||
sdrplay_api_Rsp2TunerParamsT rsp2TunerParams;
|
||||
sdrplay_api_RspDuoTunerParamsT rspDuoTunerParams;
|
||||
sdrplay_api_RspDxTunerParamsT rspDxTunerParams;
|
||||
} sdrplay_api_RxChannelParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_RX_CHANNEL_H
|
||||
93
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_tuner.h
Normal file
93
artifacts/sdrplay-api-headers/v3_11/sdrplay_api_tuner.h
Normal file
@@ -0,0 +1,93 @@
|
||||
#ifndef SDRPLAY_API_TUNER_H
|
||||
#define SDRPLAY_API_TUNER_H
|
||||
|
||||
#define MAX_BB_GR (59)
|
||||
|
||||
// Tuner parameter enums
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_BW_Undefined = 0,
|
||||
sdrplay_api_BW_0_200 = 200,
|
||||
sdrplay_api_BW_0_300 = 300,
|
||||
sdrplay_api_BW_0_600 = 600,
|
||||
sdrplay_api_BW_1_536 = 1536,
|
||||
sdrplay_api_BW_5_000 = 5000,
|
||||
sdrplay_api_BW_6_000 = 6000,
|
||||
sdrplay_api_BW_7_000 = 7000,
|
||||
sdrplay_api_BW_8_000 = 8000
|
||||
} sdrplay_api_Bw_MHzT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_IF_Undefined = -1,
|
||||
sdrplay_api_IF_Zero = 0,
|
||||
sdrplay_api_IF_0_450 = 450,
|
||||
sdrplay_api_IF_1_620 = 1620,
|
||||
sdrplay_api_IF_2_048 = 2048
|
||||
} sdrplay_api_If_kHzT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_LO_Undefined = 0,
|
||||
sdrplay_api_LO_Auto = 1,
|
||||
sdrplay_api_LO_120MHz = 2,
|
||||
sdrplay_api_LO_144MHz = 3,
|
||||
sdrplay_api_LO_168MHz = 4
|
||||
} sdrplay_api_LoModeT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_EXTENDED_MIN_GR = 0,
|
||||
sdrplay_api_NORMAL_MIN_GR = 20
|
||||
} sdrplay_api_MinGainReductionT;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
sdrplay_api_Tuner_Neither = 0,
|
||||
sdrplay_api_Tuner_A = 1,
|
||||
sdrplay_api_Tuner_B = 2,
|
||||
sdrplay_api_Tuner_Both = 3,
|
||||
} sdrplay_api_TunerSelectT;
|
||||
|
||||
// Tuner parameter structs
|
||||
typedef struct
|
||||
{
|
||||
float curr;
|
||||
float max;
|
||||
float min;
|
||||
} sdrplay_api_GainValuesT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int gRdB; // default: 50
|
||||
unsigned char LNAstate; // default: 0
|
||||
unsigned char syncUpdate; // default: 0
|
||||
sdrplay_api_MinGainReductionT minGr; // default: sdrplay_api_NORMAL_MIN_GR
|
||||
sdrplay_api_GainValuesT gainVals; // output parameter
|
||||
} sdrplay_api_GainT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double rfHz; // default: 200000000.0
|
||||
unsigned char syncUpdate; // default: 0
|
||||
} sdrplay_api_RfFreqT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char dcCal; // default: 3 (Periodic mode)
|
||||
unsigned char speedUp; // default: 0 (No speedup)
|
||||
int trackTime; // default: 1 (=> time in uSec = (72 * 3 * trackTime) / 24e6 = 9uSec)
|
||||
int refreshRateTime; // default: 2048 (=> time in uSec = (72 * 3 * refreshRateTime) / 24e6 = 18432uSec)
|
||||
} sdrplay_api_DcOffsetTunerT;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
sdrplay_api_Bw_MHzT bwType; // default: sdrplay_api_BW_0_200
|
||||
sdrplay_api_If_kHzT ifType; // default: sdrplay_api_IF_Zero
|
||||
sdrplay_api_LoModeT loMode; // default: sdrplay_api_LO_Auto
|
||||
sdrplay_api_GainT gain;
|
||||
sdrplay_api_RfFreqT rfFreq;
|
||||
sdrplay_api_DcOffsetTunerT dcOffsetTuner;
|
||||
} sdrplay_api_TunerParamsT;
|
||||
|
||||
#endif //SDRPLAY_API_TUNER_H
|
||||
270
build.gradle
270
build.gradle
@@ -1,6 +1,8 @@
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -16,6 +18,29 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
/**
|
||||
* Instructions for building/compiling the sdrtrunk application.
|
||||
*
|
||||
* Prerequisites:
|
||||
* Install and configure an OpenJDK version 19+ that includes the JavaFX modules (e.g. Bellsoft Liberica JDK)
|
||||
* - Optional: install and configure Gradle 7.6+
|
||||
*
|
||||
* Scenario 1: run the application via gradle command line from the source code root directory:
|
||||
* command: ./gradlew run
|
||||
*
|
||||
* Scenario 2: create an application release for the current operating system
|
||||
* command: ./gradlew runtimeZipCurrent
|
||||
* Note: release image is located in the /build/image/ directory
|
||||
*
|
||||
* Scenario 3: create releases for Linux and OSX operating systems using downloaded JDKs
|
||||
* command: ./gradlew runtimeZipOthers
|
||||
* Note: release images are located in the /build/image/ directory
|
||||
*
|
||||
* Scenario 4: create release for Windows operating system using downloaded JDK
|
||||
* command: ./gradlew runtimeZipWindows
|
||||
* Note: release image is located in the /build/image/ directory
|
||||
*/
|
||||
plugins {
|
||||
id 'application'
|
||||
id 'java'
|
||||
@@ -28,8 +53,14 @@ repositories {
|
||||
maven { url "https://jitpack.io" }
|
||||
}
|
||||
|
||||
version = '0.5.2'
|
||||
sourceCompatibility = '17'
|
||||
version = '0.6.0-alpha3'
|
||||
|
||||
//Java 19 is required for this version of the Project Panama preview/incubator feature
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(19)
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main.java.srcDirs 'src/main'
|
||||
@@ -90,19 +121,46 @@ dependencies {
|
||||
implementation 'pl.edu.icm:JLargeArrays:1.6'
|
||||
}
|
||||
|
||||
def os = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem
|
||||
|
||||
/**
|
||||
* This is needed for the JDK17 vector API ... until it moves out of incubation
|
||||
* This is needed for the JDK19 panama and vector API ... until it moves out of incubation or preview
|
||||
*/
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs.add("--enable-preview") //Panama Foreign Function/Memory is preview in JDK 19
|
||||
options.compilerArgs.add("--add-modules=jdk.incubator.vector") //Needed while Panama Vector API remains in incubator
|
||||
}
|
||||
|
||||
/**
|
||||
* JVM Arguments for running the application on Windows.
|
||||
*/
|
||||
def jvmArgsWindows =
|
||||
['--add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED', //Needed for controls-fx.jar
|
||||
'--add-exports=java.desktop/com.sun.java.swing.plaf.windows=ALL-UNNAMED', //windows users for JIDE
|
||||
'--add-modules=jdk.incubator.vector', //Needed while Project Panama API is still in incubator
|
||||
'--enable-preview', //Project Panama Vector & Foreign Function APIs remain in incubator
|
||||
'--enable-native-access=ALL-UNNAMED',
|
||||
'-Djava.library.path=c:\\Program Files\\SDRplay\\API\\x64'] //Allows Project Panama Foreign Function access to system library
|
||||
|
||||
/**
|
||||
* JVM Arguments for running the application on Linux.
|
||||
*/
|
||||
def jvmArgsLinux =
|
||||
['--add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED', //Needed for controls-fx.jar
|
||||
'--add-modules=jdk.incubator.vector', //Needed while Project Panama API is still in incubator
|
||||
'--enable-preview', //Project Panama Vector & Foreign Function APIs remain in incubator
|
||||
'--enable-native-access=ALL-UNNAMED',
|
||||
'-Djava.library.path=/usr/local/lib'] //Allows Project Panama Foreign Function access to system library
|
||||
|
||||
application {
|
||||
mainClassName = "io.github.dsheirer.gui.SDRTrunk"
|
||||
applicationDefaultJvmArgs =
|
||||
['--add-exports=javafx.base/com.sun.javafx.event=ALL-UNNAMED', //Needed for controls-fx.jar
|
||||
'--add-modules=jdk.incubator.vector', //Needed while Panama Vector API remains in incubator
|
||||
'--add-exports=java.desktop/com.sun.java.swing.plaf.windows=ALL-UNNAMED'] //Windows Swing - jide-oss library
|
||||
|
||||
if(os.isWindows()) {
|
||||
applicationDefaultJvmArgs = jvmArgsWindows
|
||||
}
|
||||
else {
|
||||
applicationDefaultJvmArgs = jvmArgsLinux
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
@@ -111,7 +169,7 @@ jar {
|
||||
'Implementation-Title' : 'sdrtrunk project',
|
||||
'Implementation-Version' : archiveVersion,
|
||||
'Created-By' : "Gradle ${gradle.gradleVersion}",
|
||||
'Build-Timestamp' : new java.text.SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(new Date()),
|
||||
'Build-Timestamp' : new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ").format(new Date()),
|
||||
'Build-JDK' : "${System.properties['java.version']} (${System.properties['java.vendor']} ${System.properties['java.vm.version']}",
|
||||
'Build-OS' : "${System.properties['os.name']} (${System.properties['os.arch']} ${System.properties['os.version']}"
|
||||
)
|
||||
@@ -145,84 +203,142 @@ String jdk_osx_x86_64 = jdk_base + 'osx-x64/jdk-19.0.1-full.jdk'
|
||||
String jdk_osx_aarch64 = jdk_base + 'osx-arm64/jdk-19.0.1-full.jdk'
|
||||
String jdk_windows_x86_64 = jdk_base + 'windows-x64/jdk-19.0.1-full'
|
||||
|
||||
boolean hasTargetJdks = file(jdk_linux_x86_64).exists() || file(jdk_linux_aarch64).exists() ||
|
||||
file(jdk_osx_x86_64).exists() || file(jdk_osx_aarch64).exists() || file(jdk_windows_x86_64).exists()
|
||||
/**
|
||||
* Download URLs to download the JDK as part of the gradle build packaging process
|
||||
*/
|
||||
String jdk_download_base = 'https://download.bell-sw.com/java/19.0.1+11/bellsoft-jdk19.0.1+11-'
|
||||
String jdk_download_suffix = '-full.tar.gz'
|
||||
String jdk_download_linux_aarch64 = jdk_download_base + 'linux-aarch64' + jdk_download_suffix
|
||||
String jdk_download_linux_x86_64 = jdk_download_base + 'linux-amd64' + jdk_download_suffix
|
||||
String jdk_download_osx_x86_64 = jdk_download_base + 'macos-aarch64' + jdk_download_suffix
|
||||
String jdk_download_osx_aarch64 = jdk_download_base + 'macos-amd64' + jdk_download_suffix
|
||||
String jdk_download_windows_x86_64 = jdk_download_base + 'windows-amd64-full.zip'
|
||||
|
||||
/**
|
||||
* Auto-download target JDKs. Defaults to false, or the user can override via the gradle command line by
|
||||
* including this option: '-PdownloadJdks=true'
|
||||
* Configures the runtime zip task with additional options/settings.
|
||||
* @param rt task to configure
|
||||
* @param jvmArgs to use (windows or linux)
|
||||
* @return configured task.
|
||||
*/
|
||||
boolean downloadJdks = project.hasProperty('downloadJdks') ? project.getProperty('downloadJdks') : false
|
||||
|
||||
/**
|
||||
* Beryx Runtime plugin for creating OS and CPU targeted build(s) of the software.
|
||||
*
|
||||
* Option 1: Create a single target build using the locally installed JDK, or optionally create target builds for
|
||||
* all OS and CPU targets when pre-downloaded target JDKs are available (see 'jdk_*' properties above).
|
||||
*
|
||||
* >: gradle runtimeZip
|
||||
*
|
||||
* Option 2: Create all OS and CPU target builds by automatically downloading all JDKs needed to build the target images
|
||||
*
|
||||
* >: gradle runtimeZip -PdownloadJdks=true
|
||||
*/
|
||||
runtime {
|
||||
//Build by automatically downloading JDKs for the OS and CPU targets
|
||||
if(downloadJdks) {
|
||||
println("Building all runtime images")
|
||||
println("The [ > jre: ] build phase downloads several target JDKs and this may take a while ... please wait")
|
||||
targetPlatform(targetLinuxAarch64) {
|
||||
jdkHome = jdkDownload("https://download.bell-sw.com/java/19.0.1+11/bellsoft-jdk19.0.1+11-linux-aarch64-full.tar.gz")
|
||||
}
|
||||
targetPlatform(targetLinuxX86_64) {
|
||||
jdkHome = jdkDownload("https://download.bell-sw.com/java/19.0.1+11/bellsoft-jdk19.0.1+11-linux-amd64-full.tar.gz")
|
||||
}
|
||||
targetPlatform(targetOsxAarch64) {
|
||||
jdkHome = jdkDownload("https://download.bell-sw.com/java/19.0.1+11/bellsoft-jdk19.0.1+11-macos-aarch64-full.tar.gz")
|
||||
}
|
||||
targetPlatform(targetOsxX86_64) {
|
||||
jdkHome = jdkDownload("https://download.bell-sw.com/java/19.0.1+11/bellsoft-jdk19.0.1+11-macos-amd64-full.tar.gz")
|
||||
}
|
||||
targetPlatform(targetWindowsX86_64) {
|
||||
jdkHome = jdkDownload("https://download.bell-sw.com/java/19.0.1+11/bellsoft-jdk19.0.1+11-windows-amd64-full.zip")
|
||||
}
|
||||
}
|
||||
//Build using pre-downloaded JDKs
|
||||
else if(hasTargetJdks) {
|
||||
println("Building all runtime images using pre-downloaded JDKs")
|
||||
if(file(jdk_linux_aarch64).exists()) {
|
||||
targetPlatform(targetLinuxAarch64, jdk_linux_aarch64)
|
||||
}
|
||||
if(file(jdk_linux_x86_64).exists()) {
|
||||
targetPlatform(targetLinuxX86_64, jdk_linux_x86_64)
|
||||
}
|
||||
if(file(jdk_osx_aarch64).exists()) {
|
||||
targetPlatform(targetOsxAarch64, jdk_osx_aarch64)
|
||||
}
|
||||
if(file(jdk_osx_x86_64).exists()) {
|
||||
targetPlatform(targetOsxX86_64, jdk_osx_x86_64)
|
||||
}
|
||||
if(file(jdk_windows_x86_64).exists()) {
|
||||
targetPlatform(targetWindowsX86_64, jdk_windows_x86_64)
|
||||
}
|
||||
}
|
||||
//Build using locally installed JDK only
|
||||
else {
|
||||
println("Building a single runtime image using locally installed JDK")
|
||||
}
|
||||
def configure(org.beryx.runtime.RuntimeZipTask rt, List<String> jvmArgs) {
|
||||
//Use the correct set of JVM arguments
|
||||
rt.extension.launcherData.get().jvmArgs = jvmArgs
|
||||
|
||||
//Additional modules to include with auto-detected modules.
|
||||
//jdk.crypto.ec needed for HTTPS connections (broadcastify calls & map tile server)
|
||||
//jdk.crypto.ec - needed for HTTPS connections (broadcastify calls & map tile server)
|
||||
//jdk.incubator.vector - needed for Project Panama foreign function and vector apis
|
||||
//jdk.accessibility is used with assistive technologies like screen readers
|
||||
modules = ['jdk.crypto.ec','jdk.accessibility']
|
||||
rt.extension.addModules('jdk.crypto.ec', 'jdk.incubator.vector', 'jdk.accessibility')
|
||||
|
||||
//Use auto-detected modules and 'add' any specified modules.
|
||||
additive = true
|
||||
rt.extension.additive.set(true)
|
||||
|
||||
//Recommended options for reducing/shrinking runtime target image size
|
||||
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
|
||||
rt.extension.addOptions('--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages')
|
||||
|
||||
//Runtime images have auto appended version in image zip name. Override to include version in single target image.
|
||||
imageZip = (hasTargetJdks | downloadJdks) ? file("$buildDir/image/sdr-trunk.zip") :
|
||||
file("$buildDir/image/sdr-trunk-" + version + ".zip")
|
||||
rt.extension.imageZip.set(file("$buildDir/image/sdr-trunk.zip"))
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a release package for the current operating system.
|
||||
*
|
||||
* Note: you cannot create both Windows and Linux releases at the same time due to limitations of the Runtime plugin
|
||||
*
|
||||
* Usage: gradle runtimeZipCurrent
|
||||
* Usage: gradlew runtimeZipCurrent (windows - using gradlew)
|
||||
* Usage: ./gradlew runtimeZipCurrent (linux - using gradlew)
|
||||
*/
|
||||
tasks.register('runtimeZipCurrent', org.beryx.runtime.RuntimeZipTask) {rt ->
|
||||
def arch = System.properties.getProperty("os.arch")
|
||||
def javaHome = org.gradle.internal.jvm.Jvm.current().getJavaHome().toString()
|
||||
|
||||
if(os.isWindows()) {
|
||||
rt.extension.targetPlatform(targetWindowsX86_64, javaHome)
|
||||
configure(rt, jvmArgsWindows)
|
||||
}
|
||||
else if(os.isLinux())
|
||||
{
|
||||
if(arch.equals("amd64")) {
|
||||
rt.extension.targetPlatform(targetLinuxX86_64, javaHome)
|
||||
}
|
||||
else if(arch.equals("aarch64")) {
|
||||
rt.extension.targetPlatform(targetLinuxAarch64, javaHome)
|
||||
}
|
||||
configure(rt, jvmArgsLinux)
|
||||
}
|
||||
else if(os.isMacOsX())
|
||||
{
|
||||
if(arch.equals("amd64")) {
|
||||
rt.extension.targetPlatform(targetOsxX86_64, javaHome)
|
||||
}
|
||||
else if(arch.equals("aarch64")) {
|
||||
rt.extension.targetPlatform(targetOsxAarch64, javaHome)
|
||||
}
|
||||
configure(rt, jvmArgsLinux)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Windows release package.
|
||||
*
|
||||
* Note: you cannot create both Windows and Linux releases at the same time due to limitations of the Runtime plugin
|
||||
*
|
||||
* Usage: gradle runtimeZipWindows
|
||||
* Usage: gradlew runtimeZipWindows (windows - using gradlew)
|
||||
* Usage: ./gradlew runtimeZipWindows (linux - using gradlew)
|
||||
*/
|
||||
tasks.register('runtimeZipWindows', org.beryx.runtime.RuntimeZipTask) {rt ->
|
||||
if(file(jdk_windows_x86_64).exists()) {
|
||||
rt.extension.targetPlatform(targetWindowsX86_64, jdk_windows_x86_64, [])
|
||||
}
|
||||
else {
|
||||
rt.extension.targetPlatform(targetWindowsX86_64, jdkDownload(jdk_download_windows_x86_64))
|
||||
}
|
||||
|
||||
configure(rt, jvmArgsWindows)
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates Linux & OSX release packages.
|
||||
*
|
||||
* Note: you cannot create both Windows and Linux releases at the same time due to limitations of the Runtime plugin
|
||||
*
|
||||
* Usage: gradle runtimeZipOthers
|
||||
* Usage: gradlew runtimeZipOthers (windows - using gradlew)
|
||||
* Usage: ./gradlew runtimeZipOthers (linux - using gradlew)
|
||||
*/
|
||||
tasks.register('runtimeZipOthers', org.beryx.runtime.RuntimeZipTask) {rt ->
|
||||
//Linux aarch64
|
||||
if(file(jdk_linux_aarch64).exists()) {
|
||||
rt.extension.targetPlatform(targetLinuxAarch64, jdk_linux_aarch64, [])
|
||||
}
|
||||
else {
|
||||
rt.extension.targetPlatform(targetLinuxAarch64, jdkDownload(jdk_download_linux_aarch64))
|
||||
}
|
||||
//Linux x86-64
|
||||
if(file(jdk_linux_x86_64).exists()) {
|
||||
rt.extension.targetPlatform(targetLinuxX86_64, jdk_linux_x86_64, [])
|
||||
}
|
||||
else {
|
||||
rt.extension.targetPlatform(targetLinuxX86_64, jdkDownload(jdk_download_linux_x86_64))
|
||||
}
|
||||
//OSX aarch64
|
||||
if(file(jdk_osx_aarch64).exists()) {
|
||||
rt.extension.targetPlatform(targetOsxAarch64, jdk_osx_aarch64, [])
|
||||
}
|
||||
else {
|
||||
rt.extension.targetPlatform(targetOsxAarch64, jdkDownload(jdk_download_osx_aarch64))
|
||||
}
|
||||
//Linux x86-64
|
||||
if(file(jdk_osx_x86_64).exists()) {
|
||||
rt.extension.targetPlatform(targetOsxX86_64, jdk_osx_x86_64, [])
|
||||
}
|
||||
else {
|
||||
rt.extension.targetPlatform(targetOsxX86_64, jdkDownload(jdk_download_osx_x86_64))
|
||||
}
|
||||
|
||||
configure(rt, jvmArgsLinux);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,12 +28,11 @@ import io.github.dsheirer.source.SourceEvent;
|
||||
import io.github.dsheirer.source.tuner.channel.StreamProcessorWithHeartbeat;
|
||||
import io.github.dsheirer.source.tuner.channel.TunerChannel;
|
||||
import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Polyphase Channelizer's Tuner Channel Source implementation. Wraps a ChannelOutputProcessor instance and
|
||||
@@ -202,7 +201,6 @@ public class PolyphaseChannelSource extends TunerChannelSource implements Listen
|
||||
if(mPolyphaseChannelOutputProcessor != null)
|
||||
{
|
||||
mPolyphaseChannelOutputProcessor.setListener(null);
|
||||
mPolyphaseChannelOutputProcessor.stop();
|
||||
}
|
||||
|
||||
mPolyphaseChannelOutputProcessor = null;
|
||||
|
||||
@@ -248,7 +248,11 @@ public class SDRTrunk implements Listener<TunerEvent>
|
||||
{
|
||||
mMainGui.setVisible(true);
|
||||
Tuner tuner = tunerSpectralDisplayManager.showFirstTuner();
|
||||
updateTitle(tuner);
|
||||
|
||||
if(tuner != null)
|
||||
{
|
||||
updateTitle(tuner.getPreferredName());
|
||||
}
|
||||
}
|
||||
|
||||
if(calibrating && !GraphicsEnvironment.isHeadless())
|
||||
@@ -630,21 +634,34 @@ public class SDRTrunk implements Listener<TunerEvent>
|
||||
@Override
|
||||
public void receive(TunerEvent event)
|
||||
{
|
||||
if(event.getEvent() == TunerEvent.Event.REQUEST_MAIN_SPECTRAL_DISPLAY)
|
||||
switch(event.getEvent())
|
||||
{
|
||||
updateTitle(event.getTuner());
|
||||
case REQUEST_MAIN_SPECTRAL_DISPLAY:
|
||||
updateTitle(event.getTuner().getPreferredName());
|
||||
break;
|
||||
case REQUEST_CLEAR_MAIN_SPECTRAL_DISPLAY:
|
||||
updateTitle(null);
|
||||
break;
|
||||
case NOTIFICATION_SHUTTING_DOWN:
|
||||
Tuner currentTuner = mSpectralPanel.getTuner();
|
||||
|
||||
if(event.hasTuner() && event.getTuner().equals(currentTuner) || currentTuner == null)
|
||||
{
|
||||
updateTitle(null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the title bar with the tuner name
|
||||
* @param tuner optional
|
||||
* @param tunerName optional
|
||||
*/
|
||||
private void updateTitle(Tuner tuner)
|
||||
private void updateTitle(String tunerName)
|
||||
{
|
||||
if(tuner != null)
|
||||
if(tunerName != null)
|
||||
{
|
||||
mMainGui.setTitle(mTitle + " - " + tuner.getPreferredName());
|
||||
mMainGui.setTitle(mTitle + " - " + tunerName);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -53,7 +53,7 @@ public class PreferenceEditorFactory
|
||||
return new DirectoryPreferenceEditor(userPreferences);
|
||||
case JMBE_LIBRARY:
|
||||
return new JmbeLibraryPreferenceEditor(userPreferences);
|
||||
case SOURCE_TUNER_CHANNELIZER:
|
||||
case SOURCE_TUNERS:
|
||||
return new TunerPreferenceEditor(userPreferences);
|
||||
case TALKGROUP_FORMAT:
|
||||
return new TalkgroupFormatPreferenceEditor(userPreferences);
|
||||
|
||||
@@ -31,7 +31,7 @@ public enum PreferenceEditorType
|
||||
AUDIO_RECORD("Record"),
|
||||
AUDIO_OUTPUT("Output/Tones"),
|
||||
AUDIO_DUPLICATE_CALL_DETECTION("Duplicate Calls"),
|
||||
SOURCE_TUNER_CHANNELIZER("Tuner Channelizer"),
|
||||
SOURCE_TUNERS("Tuners"),
|
||||
TALKGROUP_FORMAT("Talkgroup & Radio ID"),
|
||||
VECTOR_CALIBRATION("Vector Calibration"),
|
||||
DEFAULT("Default");
|
||||
|
||||
@@ -22,6 +22,8 @@ package io.github.dsheirer.gui.preference;
|
||||
import io.github.dsheirer.eventbus.MyEventBus;
|
||||
import io.github.dsheirer.gui.playlist.ViewPlaylistRequest;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
import javafx.beans.value.ObservableValue;
|
||||
import javafx.geometry.Insets;
|
||||
@@ -44,9 +46,6 @@ import javafx.stage.Stage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Preferences editor dialog
|
||||
*/
|
||||
@@ -196,7 +195,7 @@ public class UserPreferencesEditor extends BorderPane
|
||||
storageItem.setExpanded(true);
|
||||
|
||||
TreeItem<String> sourceItem = new TreeItem<>("Source");
|
||||
sourceItem.getChildren().add(new TreeItem(PreferenceEditorType.SOURCE_TUNER_CHANNELIZER));
|
||||
sourceItem.getChildren().add(new TreeItem(PreferenceEditorType.SOURCE_TUNERS));
|
||||
treeRoot.getChildren().add(sourceItem);
|
||||
sourceItem.setExpanded(true);
|
||||
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui.preference.tuner;
|
||||
|
||||
/**
|
||||
* RSPduo tuner select mode preferences.
|
||||
*/
|
||||
public enum RspDuoSelectionMode
|
||||
{
|
||||
DUAL("Dual Tuner"),
|
||||
SINGLE_1("Single Tuner 1"),
|
||||
SINGLE_2("Single Tuner 2");
|
||||
|
||||
private String mLabel;
|
||||
|
||||
RspDuoSelectionMode(String label)
|
||||
{
|
||||
mLabel = label;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the enum entry from the value.
|
||||
* @param value to match
|
||||
* @return matched value or (default) DUAL if the value couldn't be matched.
|
||||
*/
|
||||
public static RspDuoSelectionMode fromValue(String value)
|
||||
{
|
||||
try
|
||||
{
|
||||
return RspDuoSelectionMode.valueOf(value);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
//Do nothing
|
||||
}
|
||||
|
||||
return DUAL;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,20 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.gui.preference.tuner;
|
||||
@@ -55,6 +52,8 @@ public class TunerPreferenceEditor extends HBox
|
||||
private Label mHelpTextPolyphaseLabel;
|
||||
private Label mHeterodyneLabel;
|
||||
private Label mHelpTextHeterodyneLabel;
|
||||
private ChoiceBox<RspDuoSelectionMode> mRspDuoTunerModeChoiceBox;
|
||||
private Label mRspDuoModeLabel;
|
||||
|
||||
public TunerPreferenceEditor(UserPreferences userPreferences)
|
||||
{
|
||||
@@ -66,19 +65,24 @@ public class TunerPreferenceEditor extends HBox
|
||||
{
|
||||
if(mEditorPane == null)
|
||||
{
|
||||
int row = 0;
|
||||
mEditorPane = new GridPane();
|
||||
mEditorPane.setVgap(10);
|
||||
mEditorPane.setHgap(10);
|
||||
mEditorPane.setPadding(new Insets(10, 10, 10, 10));
|
||||
GridPane.setHalignment(getChannelizerLabel(), HPos.LEFT);
|
||||
mEditorPane.add(getChannelizerLabel(), 0, 0);
|
||||
mEditorPane.add(getChannelizerTypeChoiceBox(), 1, 0);
|
||||
mEditorPane.add(new Separator(Orientation.HORIZONTAL), 0, 1, 2, 1);
|
||||
mEditorPane.add(getPolyphaseLabel(), 0, 2, 2, 1);
|
||||
mEditorPane.add(getHelpTextPolyphaseLabel(), 0, 3, 2, 3);
|
||||
mEditorPane.add(new Label(" "), 0, 6);
|
||||
mEditorPane.add(getHeterodyneLabel(), 0, 7, 2, 1);
|
||||
mEditorPane.add(getHelpTextHeterodyneLabel(), 0, 8, 2, 3);
|
||||
GridPane.setHalignment(getChannelizerLabel(), HPos.RIGHT);
|
||||
mEditorPane.add(getChannelizerLabel(), 0, row);
|
||||
mEditorPane.add(getChannelizerTypeChoiceBox(), 1, row);
|
||||
mEditorPane.add(getPolyphaseLabel(), 0, ++row, 2, 1);
|
||||
mEditorPane.add(getHelpTextPolyphaseLabel(), 0, ++row, 2, 3);
|
||||
row += 3;
|
||||
mEditorPane.add(new Label(" "), 0, row);
|
||||
mEditorPane.add(getHeterodyneLabel(), 0, ++row, 2, 1);
|
||||
mEditorPane.add(getHelpTextHeterodyneLabel(), 0, ++row, 2, 3);
|
||||
row += 3;
|
||||
mEditorPane.add(new Separator(Orientation.HORIZONTAL), 0, row, 2, 1);
|
||||
mEditorPane.add(getRspDuoModeLabel(), 0, ++row);
|
||||
mEditorPane.add(getRspDuoTunerModeChoiceBox(), 1, row);
|
||||
}
|
||||
|
||||
return mEditorPane;
|
||||
@@ -161,4 +165,40 @@ public class TunerPreferenceEditor extends HBox
|
||||
|
||||
return mHelpTextHeterodyneLabel;
|
||||
}
|
||||
|
||||
private ChoiceBox<RspDuoSelectionMode> getRspDuoTunerModeChoiceBox()
|
||||
{
|
||||
if(mRspDuoTunerModeChoiceBox == null)
|
||||
{
|
||||
mRspDuoTunerModeChoiceBox = new ChoiceBox<>();
|
||||
mRspDuoTunerModeChoiceBox.getItems().addAll(RspDuoSelectionMode.values());
|
||||
|
||||
RspDuoSelectionMode current = mTunerPreference.getRspDuoTunerMode();
|
||||
mRspDuoTunerModeChoiceBox.getSelectionModel().select(current);
|
||||
|
||||
mRspDuoTunerModeChoiceBox.setOnAction(event -> {
|
||||
RspDuoSelectionMode selected = mRspDuoTunerModeChoiceBox.getSelectionModel().getSelectedItem();
|
||||
mTunerPreference.setRspDuoTunerMode(selected);
|
||||
|
||||
Label label = new Label("Please restart the application for this change to take effect");
|
||||
label.setWrapText(true);
|
||||
Alert alert = new Alert(Alert.AlertType.WARNING);
|
||||
alert.getDialogPane().setContent(label);
|
||||
alert.initOwner(((Node)getRspDuoTunerModeChoiceBox()).getScene().getWindow());
|
||||
alert.show();
|
||||
});
|
||||
}
|
||||
|
||||
return mRspDuoTunerModeChoiceBox;
|
||||
}
|
||||
|
||||
private Label getRspDuoModeLabel()
|
||||
{
|
||||
if(mRspDuoModeLabel == null)
|
||||
{
|
||||
mRspDuoModeLabel = new Label("SDRPlay RSPduo Selection Mode");
|
||||
}
|
||||
|
||||
return mRspDuoModeLabel;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
|
||||
package io.github.dsheirer.preference.source;
|
||||
|
||||
import io.github.dsheirer.gui.preference.tuner.RspDuoSelectionMode;
|
||||
import io.github.dsheirer.preference.Preference;
|
||||
import io.github.dsheirer.preference.PreferenceType;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import java.util.prefs.Preferences;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.prefs.Preferences;
|
||||
|
||||
/**
|
||||
* Tuner preferences
|
||||
*/
|
||||
@@ -35,8 +35,10 @@ public class TunerPreference extends Preference
|
||||
private final static Logger mLog = LoggerFactory.getLogger(TunerPreference.class);
|
||||
private Preferences mPreferences = Preferences.userNodeForPackage(TunerPreference.class);
|
||||
private static final String PREFERENCE_KEY_CHANNELIZER_TYPE = "channelizer.type";
|
||||
private static final String PREFERENCE_KEY_RSP_DUO_TUNER_MODE = "rsp.duo.tuner.mode";
|
||||
|
||||
private ChannelizerType mChannelizerType;
|
||||
private RspDuoSelectionMode mRspDuoSelectionMode;
|
||||
|
||||
/**
|
||||
* Constructs a tuner preference with the update listener
|
||||
@@ -94,4 +96,30 @@ public class TunerPreference extends Preference
|
||||
mPreferences.put(PREFERENCE_KEY_CHANNELIZER_TYPE, mChannelizerType.name());
|
||||
notifyPreferenceUpdated();
|
||||
}
|
||||
|
||||
/**
|
||||
* RSPduo tuner select mode.
|
||||
* @return mode or a default value of DUAL
|
||||
*/
|
||||
public RspDuoSelectionMode getRspDuoTunerMode()
|
||||
{
|
||||
if(mRspDuoSelectionMode == null)
|
||||
{
|
||||
String mode = mPreferences.get(PREFERENCE_KEY_RSP_DUO_TUNER_MODE, RspDuoSelectionMode.DUAL.name());
|
||||
mRspDuoSelectionMode = RspDuoSelectionMode.fromValue(mode);
|
||||
}
|
||||
|
||||
return mRspDuoSelectionMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the RSPduo tuner select mode
|
||||
* @param mode to use
|
||||
*/
|
||||
public void setRspDuoTunerMode(RspDuoSelectionMode mode)
|
||||
{
|
||||
mRspDuoSelectionMode = mode;
|
||||
mPreferences.put(PREFERENCE_KEY_RSP_DUO_TUNER_MODE, mRspDuoSelectionMode.name());
|
||||
notifyPreferenceUpdated();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,12 +18,13 @@
|
||||
*/
|
||||
package io.github.dsheirer.sample;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Broadcasts an item to multiple listeners
|
||||
@@ -100,6 +101,10 @@ public class Broadcaster<T> implements Listener<T>
|
||||
mListeners.add(listener);
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Unexpected error while adding listener", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
mLock.unlock();
|
||||
@@ -120,6 +125,10 @@ public class Broadcaster<T> implements Listener<T>
|
||||
{
|
||||
mListeners.remove(listener);
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Unexpected error while removing listener", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
mLock.unlock();
|
||||
@@ -151,6 +160,10 @@ public class Broadcaster<T> implements Listener<T>
|
||||
listener.receive(t);
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Unexpected error while broadcasting to listeners", e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
mLock.unlock();
|
||||
|
||||
@@ -1,23 +1,20 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* * ******************************************************************************
|
||||
* * Copyright (C) 2014-2020 Dennis Sheirer
|
||||
* *
|
||||
* * This program is free software: you can redistribute it and/or modify
|
||||
* * it under the terms of the GNU General Public License as published by
|
||||
* * the Free Software Foundation, either version 3 of the License, or
|
||||
* * (at your option) any later version.
|
||||
* *
|
||||
* * This program is distributed in the hope that it will be useful,
|
||||
* * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* * GNU General Public License for more details.
|
||||
* *
|
||||
* * You should have received a copy of the GNU General Public License
|
||||
* * along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* * *****************************************************************************
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner;
|
||||
@@ -29,4 +26,9 @@ public interface ITunerErrorListener
|
||||
* @param errorMessage to set
|
||||
*/
|
||||
void setErrorMessage(String errorMessage);
|
||||
|
||||
/**
|
||||
* Indicates that the tuner has been removed from the system.
|
||||
*/
|
||||
void tunerRemoved();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -34,4 +34,10 @@ public class LoggingTunerErrorListener implements ITunerErrorListener
|
||||
{
|
||||
mLog.error("Tuner Error: " + errorMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tunerRemoved()
|
||||
{
|
||||
mLog.warn("Tuner removal detected");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -149,6 +149,20 @@ public abstract class Tuner implements ISourceEventProcessor, ITunerErrorListene
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process tuner removal error from tuner controller and propagate to an external listener.
|
||||
*/
|
||||
@Override
|
||||
public void tunerRemoved()
|
||||
{
|
||||
stop();
|
||||
|
||||
if(mTunerErrorListener != null)
|
||||
{
|
||||
mTunerErrorListener.tunerRemoved();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the channel source manager
|
||||
* @param manager to use
|
||||
|
||||
@@ -30,6 +30,7 @@ public enum TunerClass
|
||||
FUNCUBE_DONGLE_PRO_PLUS("Funcube Dongle Pro+" ),
|
||||
HACKRF("HackRF" ),
|
||||
RTL2832("RTL-2832"),
|
||||
RSP("RSP"),
|
||||
TEST_TUNER("Test"),
|
||||
RECORDING_TUNER("Recording"),
|
||||
UNKNOWN("Unknown" );
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -46,7 +46,11 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
|
||||
INativeBufferProvider, Listener<INativeBuffer>, ITunerErrorListener
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(TunerController.class);
|
||||
|
||||
//Protects access to the native buffer broadcaster for adding, removing or checking for listener count.
|
||||
protected ReentrantLock mBufferListenerLock = new ReentrantLock();
|
||||
protected Broadcaster<INativeBuffer> mNativeBufferBroadcaster = new Broadcaster();
|
||||
|
||||
protected FrequencyController mFrequencyController;
|
||||
private int mMiddleUnusableHalfBandwidth;
|
||||
private int mMeasuredFrequencyError;
|
||||
@@ -129,6 +133,19 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the tuner has been removed from the system and requests the listener to process the cleanup.
|
||||
*/
|
||||
@Override
|
||||
public void tunerRemoved()
|
||||
{
|
||||
//Request parent tuner process the shutdown and cleanup
|
||||
if(mTunerErrorListener != null)
|
||||
{
|
||||
mTunerErrorListener.tunerRemoved();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of samples contained in each complex buffer provided by this tuner.
|
||||
*
|
||||
@@ -572,7 +589,16 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
|
||||
@Override
|
||||
public void addBufferListener(Listener<INativeBuffer> listener)
|
||||
{
|
||||
mNativeBufferBroadcaster.addListener(listener);
|
||||
mBufferListenerLock.lock();
|
||||
|
||||
try
|
||||
{
|
||||
mNativeBufferBroadcaster.addListener(listener);
|
||||
}
|
||||
finally
|
||||
{
|
||||
mBufferListenerLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -581,7 +607,16 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
|
||||
@Override
|
||||
public void removeBufferListener(Listener<INativeBuffer> listener)
|
||||
{
|
||||
mNativeBufferBroadcaster.removeListener(listener);
|
||||
mBufferListenerLock.lock();
|
||||
|
||||
try
|
||||
{
|
||||
mNativeBufferBroadcaster.removeListener(listener);
|
||||
}
|
||||
finally
|
||||
{
|
||||
mBufferListenerLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -590,7 +625,20 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
|
||||
@Override
|
||||
public boolean hasBufferListeners()
|
||||
{
|
||||
return mNativeBufferBroadcaster.hasListeners();
|
||||
boolean hasListeners;
|
||||
|
||||
mBufferListenerLock.lock();
|
||||
|
||||
try
|
||||
{
|
||||
hasListeners = mNativeBufferBroadcaster.hasListeners();
|
||||
}
|
||||
finally
|
||||
{
|
||||
mBufferListenerLock.unlock();
|
||||
}
|
||||
|
||||
return hasListeners;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -598,6 +646,7 @@ public abstract class TunerController implements Tunable, ISourceEventProcessor,
|
||||
*/
|
||||
protected void broadcast(INativeBuffer complexSamples)
|
||||
{
|
||||
//Note: unprotected access to the broadcaster ... the broadcaster uses thread-save internal list
|
||||
mNativeBufferBroadcaster.broadcast(complexSamples);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -54,6 +54,24 @@ public class TunerEvent
|
||||
return mTuner != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Tuner Event [").append(getEvent().name()).append("] for tuner [");
|
||||
if(hasTuner())
|
||||
{
|
||||
sb.append(getTuner());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("No Tuner");
|
||||
}
|
||||
|
||||
sb.append("]");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Event type
|
||||
*/
|
||||
@@ -75,6 +93,7 @@ public class TunerEvent
|
||||
NOTIFICATION_SHUTTING_DOWN,
|
||||
|
||||
REQUEST_CLEAR_MAIN_SPECTRAL_DISPLAY,
|
||||
REQUEST_ENABLE_RSP_SLAVE_DEVICE,
|
||||
REQUEST_MAIN_SPECTRAL_DISPLAY,
|
||||
REQUEST_NEW_SPECTRAL_DISPLAY;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package io.github.dsheirer.source.tuner;
|
||||
|
||||
import io.github.dsheirer.gui.preference.tuner.RspDuoSelectionMode;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.source.ChannelizerType;
|
||||
import io.github.dsheirer.source.SourceException;
|
||||
@@ -53,7 +54,60 @@ import io.github.dsheirer.source.tuner.rtl.e4k.E4KTunerEditor;
|
||||
import io.github.dsheirer.source.tuner.rtl.r820t.R820TEmbeddedTuner;
|
||||
import io.github.dsheirer.source.tuner.rtl.r820t.R820TTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.rtl.r820t.R820TTunerEditor;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.RspTuner;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.DeviceSelectionMode;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.Device;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.DeviceInfo;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.Rsp1Device;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.Rsp1aDevice;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.Rsp2Device;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.RspDuoDevice;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.RspDxDevice;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp1.ControlRsp1;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp1.DiscoveredRsp1Tuner;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp1.IControlRsp1;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp1.Rsp1TunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp1.Rsp1TunerController;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp1.Rsp1TunerEditor;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp1a.ControlRsp1a;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp1a.DiscoveredRsp1aTuner;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp1a.IControlRsp1a;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp1a.Rsp1aTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp1a.Rsp1aTunerController;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp1a.Rsp1aTunerEditor;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp2.ControlRsp2;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp2.DiscoveredRsp2Tuner;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp2.IControlRsp2;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp2.Rsp2TunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp2.Rsp2TunerController;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp2.Rsp2TunerEditor;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.ControlRspDuoTuner1Master;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.ControlRspDuoTuner1Single;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.ControlRspDuoTuner2Single;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.ControlRspDuoTuner2Slave;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.DiscoveredRspDuoTuner1;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.DiscoveredRspDuoTuner2;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.IControlRspDuoTuner1;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.IControlRspDuoTuner2;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.MasterSlaveBridge;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner1Configuration;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner1Controller;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner1Editor;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner2Configuration;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner2Controller;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner2Editor;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDx.ControlRspDx;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDx.DiscoveredRspDxTuner;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDx.IControlRspDx;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDx.RspDxTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDx.RspDxTunerController;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDx.RspDxTunerEditor;
|
||||
import io.github.dsheirer.source.tuner.ui.TunerEditor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -66,6 +120,182 @@ public class TunerFactory
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(TunerFactory.class);
|
||||
|
||||
/**
|
||||
* Creates one or two (e.g. RSPduo) Discovered RSP tuner instances for the RSP device.
|
||||
* @param deviceInfo describing the RSP device
|
||||
* @param channelizerType to use with the device
|
||||
* @param selectionMode to specify how to configure an RSPduo dual-tuner device.
|
||||
* @return zero or more discovered RSP tuners.
|
||||
*/
|
||||
public static List<DiscoveredRspTuner> getRspTuners(DeviceInfo deviceInfo, ChannelizerType channelizerType, RspDuoSelectionMode selectionMode)
|
||||
{
|
||||
List<DiscoveredRspTuner> tuners = new ArrayList<>();
|
||||
|
||||
switch(deviceInfo.getDeviceType())
|
||||
{
|
||||
case RSP1:
|
||||
tuners.add(new DiscoveredRsp1Tuner(deviceInfo, channelizerType));
|
||||
break;
|
||||
case RSP1A:
|
||||
tuners.add(new DiscoveredRsp1aTuner(deviceInfo, channelizerType));
|
||||
break;
|
||||
case RSP2:
|
||||
tuners.add(new DiscoveredRsp2Tuner(deviceInfo, channelizerType));
|
||||
break;
|
||||
case RSPdx:
|
||||
tuners.add(new DiscoveredRspDxTuner(deviceInfo, channelizerType));
|
||||
break;
|
||||
case RSPduo:
|
||||
switch(selectionMode)
|
||||
{
|
||||
case SINGLE_1:
|
||||
deviceInfo.setDeviceSelectionMode(DeviceSelectionMode.SINGLE_TUNER_1);
|
||||
tuners.add(new DiscoveredRspDuoTuner1(deviceInfo, channelizerType));
|
||||
break;
|
||||
case SINGLE_2:
|
||||
deviceInfo.setDeviceSelectionMode(DeviceSelectionMode.SINGLE_TUNER_2);
|
||||
tuners.add(new DiscoveredRspDuoTuner2(deviceInfo, channelizerType));
|
||||
break;
|
||||
case DUAL:
|
||||
MasterSlaveBridge bridge = new MasterSlaveBridge();
|
||||
deviceInfo.setDeviceSelectionMode(DeviceSelectionMode.MASTER_TUNER_1);
|
||||
tuners.add(new DiscoveredRspDuoTuner1(deviceInfo, channelizerType, bridge));
|
||||
|
||||
DeviceInfo deviceInfoTuner2 = deviceInfo.clone();
|
||||
deviceInfoTuner2.setDeviceSelectionMode(DeviceSelectionMode.SLAVE_TUNER_2);
|
||||
tuners.add(new DiscoveredRspDuoTuner2(deviceInfoTuner2, channelizerType, bridge));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return tuners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates the matching RSP device described by the device info object and creates an RSP tuner instance.
|
||||
* @param deviceInfo to match
|
||||
* @param channelizerType for the tuner
|
||||
* @param tunerErrorListener to monitor the tuner's status
|
||||
* @return constructed RSP tuner instance
|
||||
* @throws SDRPlayException if the device is not available or is not supported
|
||||
*/
|
||||
public static RspTuner getRspTuner(DeviceInfo deviceInfo, ChannelizerType channelizerType,
|
||||
ITunerErrorListener tunerErrorListener) throws SDRPlayException
|
||||
{
|
||||
//API instance is retained across the lifecycle of the constructed device, so we only close it if we don't get
|
||||
//a device from it.
|
||||
SDRplay api = new SDRplay();
|
||||
|
||||
if(api.isAvailable())
|
||||
{
|
||||
Device device = api.getDevice(deviceInfo);
|
||||
|
||||
switch(device.getDeviceType())
|
||||
{
|
||||
case RSP1:
|
||||
if(device instanceof Rsp1Device rsp1Device)
|
||||
{
|
||||
IControlRsp1 controlRsp1 = new ControlRsp1(rsp1Device);
|
||||
Rsp1TunerController rsp1TunerController = new Rsp1TunerController(controlRsp1, tunerErrorListener);
|
||||
return new RspTuner(rsp1TunerController, tunerErrorListener, channelizerType);
|
||||
}
|
||||
break;
|
||||
case RSP1A:
|
||||
if(device instanceof Rsp1aDevice rsp1aDevice)
|
||||
{
|
||||
IControlRsp1a controlRsp1a = new ControlRsp1a(rsp1aDevice);
|
||||
Rsp1aTunerController rsp1aTunerController = new Rsp1aTunerController(controlRsp1a, tunerErrorListener);
|
||||
return new RspTuner(rsp1aTunerController, tunerErrorListener, channelizerType);
|
||||
}
|
||||
break;
|
||||
case RSP2:
|
||||
if(device instanceof Rsp2Device rsp2Device)
|
||||
{
|
||||
IControlRsp2 controlRsp2 = new ControlRsp2(rsp2Device);
|
||||
Rsp2TunerController rsp2TunerController = new Rsp2TunerController(controlRsp2, tunerErrorListener);
|
||||
return new RspTuner(rsp2TunerController, tunerErrorListener, channelizerType);
|
||||
}
|
||||
break;
|
||||
case RSPdx:
|
||||
if(device instanceof RspDxDevice rspDxDevice)
|
||||
{
|
||||
IControlRspDx controlRspDx = new ControlRspDx(rspDxDevice);
|
||||
RspDxTunerController rspDxTunerController = new RspDxTunerController(controlRspDx, tunerErrorListener);
|
||||
return new RspTuner(rspDxTunerController, tunerErrorListener, channelizerType);
|
||||
}
|
||||
break;
|
||||
case RSPduo:
|
||||
if(device instanceof RspDuoDevice rspDuoDevice)
|
||||
{
|
||||
switch(deviceInfo.getDeviceSelectionMode())
|
||||
{
|
||||
case SINGLE_TUNER_1:
|
||||
IControlRspDuoTuner1 controlRspDuoTuner1 = new ControlRspDuoTuner1Single(rspDuoDevice);
|
||||
RspDuoTuner1Controller rspDuoTuner1Controller = new RspDuoTuner1Controller(controlRspDuoTuner1, tunerErrorListener);
|
||||
return new RspTuner(rspDuoTuner1Controller, tunerErrorListener, channelizerType);
|
||||
case SINGLE_TUNER_2:
|
||||
IControlRspDuoTuner2 controlRspDuoTuner2 = new ControlRspDuoTuner2Single(rspDuoDevice);
|
||||
RspDuoTuner2Controller rspDuoTuner2Controller = new RspDuoTuner2Controller(controlRspDuoTuner2, tunerErrorListener);
|
||||
return new RspTuner(rspDuoTuner2Controller, tunerErrorListener, channelizerType);
|
||||
default:
|
||||
throw new SDRPlayException("This method only supports RSPduo single tuner configurations");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case default:
|
||||
mLog.warn("Unrecognized SDRplay RSP Device Type: " + device.getDeviceType() + " SER#: " + device.getSerialNumber());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw new SDRPlayException("Unable to obtain RSP tuner");
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates the matching RSP device described by the device info object and creates an RSP tuner instance.
|
||||
* @param deviceInfo to match
|
||||
* @param channelizerType for the tuner
|
||||
* @param tunerErrorListener to monitor the tuner's status
|
||||
* @param bridge to link master/slave instances together
|
||||
* @return constructed RSP tuner instance
|
||||
* @throws SDRPlayException if the device is not available or is not supported
|
||||
*/
|
||||
public static RspTuner getRspDuoTuner(DeviceInfo deviceInfo, ChannelizerType channelizerType,
|
||||
ITunerErrorListener tunerErrorListener, MasterSlaveBridge bridge) throws SDRPlayException
|
||||
{
|
||||
SDRplay api = new SDRplay();
|
||||
|
||||
if(api.isAvailable())
|
||||
{
|
||||
Device device = api.getDevice(deviceInfo);
|
||||
|
||||
switch(device.getDeviceType())
|
||||
{
|
||||
case RSPduo:
|
||||
if(device instanceof RspDuoDevice rspDuoDevice)
|
||||
{
|
||||
switch(deviceInfo.getDeviceSelectionMode())
|
||||
{
|
||||
case MASTER_TUNER_1:
|
||||
IControlRspDuoTuner1 controlRspDuoTuner1 = new ControlRspDuoTuner1Master(rspDuoDevice, bridge);
|
||||
RspDuoTuner1Controller rspDuoTuner1Controller = new RspDuoTuner1Controller(controlRspDuoTuner1, tunerErrorListener);
|
||||
return new RspTuner(rspDuoTuner1Controller, tunerErrorListener, channelizerType);
|
||||
case SLAVE_TUNER_2:
|
||||
IControlRspDuoTuner2 controlRspDuoTuner2 = new ControlRspDuoTuner2Slave(rspDuoDevice, bridge);
|
||||
RspDuoTuner2Controller rspDuoTuner2Controller = new RspDuoTuner2Controller(controlRspDuoTuner2, tunerErrorListener);
|
||||
return new RspTuner(rspDuoTuner2Controller, tunerErrorListener, channelizerType);
|
||||
default:
|
||||
throw new SDRPlayException("This method only supports RSPduo single tuner configurations");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
throw new SDRPlayException("Unable to obtain RSPduo tuner");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a USB tuner
|
||||
* @param tunerClass to instantiate
|
||||
@@ -148,6 +378,18 @@ public class TunerFactory
|
||||
return new R820TTunerConfiguration(uniqueID);
|
||||
case RECORDING:
|
||||
return RecordingTunerConfiguration.create();
|
||||
case RSP_1:
|
||||
return new Rsp1TunerConfiguration(uniqueID);
|
||||
case RSP_1A:
|
||||
return new Rsp1aTunerConfiguration(uniqueID);
|
||||
case RSP_2:
|
||||
return new Rsp2TunerConfiguration(uniqueID);
|
||||
case RSP_DUO_1:
|
||||
return new RspDuoTuner1Configuration(uniqueID);
|
||||
case RSP_DUO_2:
|
||||
return new RspDuoTuner2Configuration(uniqueID);
|
||||
case RSP_DX:
|
||||
return new RspDxTunerConfiguration(uniqueID);
|
||||
default:
|
||||
throw new IllegalArgumentException("Unrecognized tuner type [" + type.name() + "]");
|
||||
}
|
||||
@@ -169,6 +411,42 @@ public class TunerFactory
|
||||
return new FCD2TunerEditor(userPreferences, tunerManager, discoveredTuner);
|
||||
case HACKRF:
|
||||
return new HackRFTunerEditor(userPreferences, tunerManager, discoveredTuner);
|
||||
case RSP:
|
||||
if(discoveredTuner instanceof DiscoveredRspTuner discoveredRspTuner)
|
||||
{
|
||||
switch(discoveredRspTuner.getDeviceType())
|
||||
{
|
||||
case RSP1:
|
||||
return new Rsp1TunerEditor(userPreferences, tunerManager, discoveredRspTuner);
|
||||
case RSP1A:
|
||||
return new Rsp1aTunerEditor(userPreferences, tunerManager, discoveredRspTuner);
|
||||
case RSP2:
|
||||
return new Rsp2TunerEditor(userPreferences, tunerManager, discoveredRspTuner);
|
||||
case RSPdx:
|
||||
return new RspDxTunerEditor(userPreferences, tunerManager, discoveredRspTuner);
|
||||
case RSPduo:
|
||||
if(discoveredRspTuner instanceof DiscoveredRspDuoTuner1 duoTuner1)
|
||||
{
|
||||
return new RspDuoTuner1Editor(userPreferences, tunerManager, duoTuner1);
|
||||
}
|
||||
else if(discoveredRspTuner instanceof DiscoveredRspDuoTuner2 duoTuner2)
|
||||
{
|
||||
return new RspDuoTuner2Editor(userPreferences, tunerManager, duoTuner2);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Unrecognized RSPduo device type:" +
|
||||
discoveredRspTuner.getClass());
|
||||
}
|
||||
case UNKNOWN:
|
||||
throw new IllegalArgumentException("Unrecognized RSP device type: " +
|
||||
discoveredRspTuner.getDeviceType());
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Unrecognized discovered RSP tuner class: " +
|
||||
discoveredTuner.getClass());
|
||||
case RECORDING_TUNER:
|
||||
return new RecordingTunerEditor(userPreferences, tunerManager, discoveredTuner);
|
||||
case RTL2832:
|
||||
if(discoveredTuner.hasTuner())
|
||||
{
|
||||
@@ -181,8 +459,6 @@ public class TunerFactory
|
||||
}
|
||||
}
|
||||
return new RTL2832UnknownTunerEditor(userPreferences, tunerManager, discoveredTuner);
|
||||
case RECORDING_TUNER:
|
||||
return new RecordingTunerEditor(userPreferences, tunerManager, discoveredTuner);
|
||||
case TEST_TUNER:
|
||||
case UNKNOWN:
|
||||
default:
|
||||
|
||||
@@ -37,6 +37,13 @@ public enum TunerType
|
||||
HACKRF_RAD1O("RAD1O"),
|
||||
RAFAELMICRO_R820T("R820T"),
|
||||
RAFAELMICRO_R828D("R828D"),
|
||||
RSP_1("RSP1"),
|
||||
RSP_1A("RSP1A"),
|
||||
RSP_2("RSP2"),
|
||||
RSP_DUO_1("RSPduo Tuner 1"),
|
||||
RSP_DUO_2("RSPduo Tuner 2"),
|
||||
RSP_DX("RSPdx"),
|
||||
|
||||
TEST("Test"),
|
||||
RECORDING("Recording"),
|
||||
UNKNOWN("Unknown");
|
||||
|
||||
@@ -31,6 +31,7 @@ import io.github.dsheirer.source.tuner.hackrf.HackRFTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.recording.RecordingTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.rtl.e4k.E4KTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.rtl.r820t.R820TTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.RspTunerConfiguration;
|
||||
|
||||
/**
|
||||
* Abstract class to hold a configuration for a specific type of tuner
|
||||
@@ -44,6 +45,7 @@ import io.github.dsheirer.source.tuner.rtl.r820t.R820TTunerConfiguration;
|
||||
@JsonSubTypes.Type(value = HackRFTunerConfiguration.class, name = "hackRFTunerConfiguration"),
|
||||
@JsonSubTypes.Type(value = RecordingTunerConfiguration.class, name = "recordingTunerConfiguration"),
|
||||
@JsonSubTypes.Type(value = R820TTunerConfiguration.class, name = "r820TTunerConfiguration"),
|
||||
@JsonSubTypes.Type(value = RspTunerConfiguration.class, name = "rspTunerConfiguration"),
|
||||
})
|
||||
@JacksonXmlRootElement(localName = "tuner_configuration")
|
||||
public abstract class TunerConfiguration
|
||||
|
||||
@@ -147,6 +147,12 @@ public class TunerConfigurationManager implements IDiscoveredTunerStatusListener
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Monitors discovered tuner enabled status and applies configurations or updates disable state of tuners.
|
||||
* @param discoveredTuner that has a status change.
|
||||
* @param previous tuner status
|
||||
* @param current tuner status
|
||||
*/
|
||||
@Override
|
||||
public void tunerStatusUpdated(DiscoveredTuner discoveredTuner, TunerStatus previous, TunerStatus current)
|
||||
{
|
||||
@@ -157,6 +163,23 @@ public class TunerConfigurationManager implements IDiscoveredTunerStatusListener
|
||||
else if(current == TunerStatus.ENABLED)
|
||||
{
|
||||
removeDisabledTuner(discoveredTuner);
|
||||
|
||||
if(discoveredTuner.hasTuner())
|
||||
{
|
||||
TunerType tunerType = discoveredTuner.getTuner().getTunerType();
|
||||
|
||||
if(tunerType != TunerType.RECORDING)
|
||||
{
|
||||
TunerConfiguration tunerConfiguration = getTunerConfiguration(tunerType, discoveredTuner.getId());
|
||||
|
||||
if(tunerConfiguration != null)
|
||||
{
|
||||
discoveredTuner.setTunerConfiguration(tunerConfiguration);
|
||||
saveConfigurations();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -219,7 +219,10 @@ public abstract class DiscoveredTuner implements ITunerErrorListener
|
||||
*/
|
||||
public void addTunerStatusListener(IDiscoveredTunerStatusListener listener)
|
||||
{
|
||||
mListeners.add(listener);
|
||||
if(!mListeners.contains(listener))
|
||||
{
|
||||
mListeners.add(listener);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -257,6 +260,12 @@ public abstract class DiscoveredTuner implements ITunerErrorListener
|
||||
setTunerStatus(TunerStatus.ERROR);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tunerRemoved()
|
||||
{
|
||||
setTunerStatus(TunerStatus.REMOVED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this tuner has an error message.
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package io.github.dsheirer.source.tuner.manager;
|
||||
|
||||
import io.github.dsheirer.gui.preference.tuner.RspDuoSelectionMode;
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.preference.source.ChannelizerType;
|
||||
import io.github.dsheirer.source.Source;
|
||||
@@ -28,6 +29,7 @@ import io.github.dsheirer.source.config.SourceConfigTunerMultipleFrequency;
|
||||
import io.github.dsheirer.source.config.SourceConfiguration;
|
||||
import io.github.dsheirer.source.mixer.MixerManager;
|
||||
import io.github.dsheirer.source.tuner.TunerClass;
|
||||
import io.github.dsheirer.source.tuner.TunerFactory;
|
||||
import io.github.dsheirer.source.tuner.TunerType;
|
||||
import io.github.dsheirer.source.tuner.channel.ChannelSpecification;
|
||||
import io.github.dsheirer.source.tuner.channel.MultiFrequencyTunerChannelSource;
|
||||
@@ -36,6 +38,11 @@ import io.github.dsheirer.source.tuner.channel.TunerChannelSource;
|
||||
import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.configuration.TunerConfigurationManager;
|
||||
import io.github.dsheirer.source.tuner.recording.RecordingTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.DeviceInfo;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.DiscoveredRspDuoTuner1;
|
||||
import io.github.dsheirer.source.tuner.ui.DiscoveredTunerModel;
|
||||
import io.github.dsheirer.util.ThreadPool;
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -63,14 +70,13 @@ import org.usb4java.LibUsb;
|
||||
public class TunerManager implements IDiscoveredTunerStatusListener
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(TunerManager.class);
|
||||
private static final int MAXIMUM_USB_2_DATA_RATE = 480000000;
|
||||
|
||||
private UserPreferences mUserPreferences;
|
||||
private DiscoveredTunerModel mDiscoveredTunerModel = new DiscoveredTunerModel();
|
||||
private TunerConfigurationManager mTunerConfigurationManager;
|
||||
private HotplugEventSupport mHotplugEventSupport = new HotplugEventSupport();
|
||||
private Context mLibUsbApplicationContext = new Context();
|
||||
private boolean mLibUsbInitialized = false;
|
||||
private SDRplay mSDRplay;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
@@ -142,6 +148,13 @@ public class TunerManager implements IDiscoveredTunerStatusListener
|
||||
//Stop all tuners
|
||||
mDiscoveredTunerModel.releaseDiscoveredTuners();
|
||||
|
||||
//Shutdown SDRplay API instance
|
||||
if(mSDRplay != null)
|
||||
{
|
||||
mSDRplay.close();
|
||||
mSDRplay = null;
|
||||
}
|
||||
|
||||
//Shutdown LibUsb
|
||||
if(mLibUsbInitialized)
|
||||
{
|
||||
@@ -238,37 +251,7 @@ public class TunerManager implements IDiscoveredTunerStatusListener
|
||||
{
|
||||
if(!mDiscoveredTunerModel.hasUsbTuner(discoveredUSBTuner.getBus(), discoveredUSBTuner.getPortAddress()))
|
||||
{
|
||||
discoveredUSBTuner.addTunerStatusListener(this);
|
||||
|
||||
//Set the tuner to disabled if the user has previously blacklisted the tuner
|
||||
if(mTunerConfigurationManager.isDisabled(discoveredUSBTuner))
|
||||
{
|
||||
discoveredUSBTuner.setEnabled(false);
|
||||
mLog.info("Tuner: " + discoveredUSBTuner + " - Added / Disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.info("Tuner: " + discoveredUSBTuner + " - Added / Starting ...");
|
||||
//Attempt to start the discovered tuner and determine the tuner type
|
||||
discoveredUSBTuner.start();
|
||||
|
||||
if(discoveredUSBTuner.hasTuner())
|
||||
{
|
||||
TunerType tunerType = discoveredUSBTuner.getTuner().getTunerType();
|
||||
|
||||
TunerConfiguration tunerConfiguration = mTunerConfigurationManager
|
||||
.getTunerConfiguration(tunerType, discoveredUSBTuner.getId());
|
||||
|
||||
if(tunerConfiguration != null)
|
||||
{
|
||||
mLog.info("Tuner: " + discoveredUSBTuner + " - Applying Tuner Configuration");
|
||||
discoveredUSBTuner.setTunerConfiguration(tunerConfiguration);
|
||||
mTunerConfigurationManager.saveConfigurations();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mDiscoveredTunerModel.addDiscoveredTuner(discoveredUSBTuner);
|
||||
startAndConfigureTuner(discoveredUSBTuner);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,12 +265,77 @@ public class TunerManager implements IDiscoveredTunerStatusListener
|
||||
return mDiscoveredTunerModel.removeUsbTuner(bus, portAddress);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts, configures and adds the tuner to the tuner model.
|
||||
* @param discoveredTuner to add and configure
|
||||
*/
|
||||
private void startAndConfigureTuner(DiscoveredTuner discoveredTuner)
|
||||
{
|
||||
discoveredTuner.addTunerStatusListener(this);
|
||||
|
||||
//Set the tuner to disabled if the user has previously blacklisted the tuner
|
||||
if(mTunerConfigurationManager.isDisabled(discoveredTuner))
|
||||
{
|
||||
discoveredTuner.setEnabled(false);
|
||||
mLog.info("Tuner: " + discoveredTuner + " - Added / Disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.info("Tuner: " + discoveredTuner + " - Added / Starting ...");
|
||||
//Attempt to start the discovered tuner and determine the tuner type
|
||||
tunerStatusUpdated(discoveredTuner, TunerStatus.DISABLED, TunerStatus.ENABLED);
|
||||
}
|
||||
|
||||
mDiscoveredTunerModel.addDiscoveredTuner(discoveredTuner);
|
||||
}
|
||||
|
||||
/**
|
||||
* Discover SDRPlay RSP tuners
|
||||
*/
|
||||
private void discoverSdrPlayTuners()
|
||||
{
|
||||
//placeholder ...
|
||||
ChannelizerType channelizerType = mUserPreferences.getTunerPreference().getChannelizerType();
|
||||
RspDuoSelectionMode duoSelectionMode = mUserPreferences.getTunerPreference().getRspDuoTunerMode();
|
||||
|
||||
//Note: we have to keep this first API instance open while we use any RSP tuners, otherwise the additional API
|
||||
//instance(s) used by the individual tuners become unresponsive. Note sure why.
|
||||
mSDRplay = new SDRplay();
|
||||
|
||||
if(mSDRplay.isAvailable())
|
||||
{
|
||||
try
|
||||
{
|
||||
List<DeviceInfo> deviceInfos = mSDRplay.getDeviceInfos();
|
||||
|
||||
mLog.info("Discovered [" + deviceInfos.size() + "] RSP devices from SDRplay API");
|
||||
|
||||
if(deviceInfos.isEmpty())
|
||||
{
|
||||
mSDRplay.close();
|
||||
mSDRplay = null;
|
||||
return;
|
||||
}
|
||||
|
||||
for(DeviceInfo deviceInfo: deviceInfos)
|
||||
{
|
||||
List<DiscoveredRspTuner> tuners = TunerFactory.getRspTuners(deviceInfo, channelizerType, duoSelectionMode);
|
||||
|
||||
for(DiscoveredRspTuner tuner: tuners)
|
||||
{
|
||||
startAndConfigureTuner(tuner);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
mLog.info("Unable to get list of devices from SDRplay API");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mSDRplay.close();
|
||||
mSDRplay = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -329,29 +377,43 @@ public class TunerManager implements IDiscoveredTunerStatusListener
|
||||
@Override
|
||||
public void tunerStatusUpdated(DiscoveredTuner discoveredTuner, TunerStatus previous, TunerStatus current)
|
||||
{
|
||||
mTunerConfigurationManager.tunerStatusUpdated(discoveredTuner, previous, current);
|
||||
|
||||
if(previous != TunerStatus.ENABLED && current == TunerStatus.ENABLED)
|
||||
if(current == TunerStatus.ENABLED)
|
||||
{
|
||||
discoveredTuner.start();
|
||||
}
|
||||
|
||||
if(discoveredTuner.hasTuner())
|
||||
//Special handling for RSPduo to auto-update enabled state for slave device when configured for master/slave operation
|
||||
if(discoveredTuner instanceof DiscoveredRspDuoTuner1 rspDuoTuner1 && rspDuoTuner1.getDeviceInfo().getDeviceSelectionMode().isMasterMode())
|
||||
{
|
||||
String id = rspDuoTuner1.getId();
|
||||
id = id.replace(DiscoveredRspDuoTuner1.RSP_DUO_ID_PREFIX + "1", DiscoveredRspDuoTuner1.RSP_DUO_ID_PREFIX + "2");
|
||||
DiscoveredTuner rspDuoTuner2 = getDiscoveredTunerModel().getDiscoveredTuner(id);
|
||||
|
||||
if(rspDuoTuner2 != null)
|
||||
{
|
||||
TunerType tunerType = discoveredTuner.getTuner().getTunerType();
|
||||
|
||||
//Don't fetch or create a configuration for recording tuners
|
||||
if(tunerType != TunerType.RECORDING)
|
||||
if(previous == TunerStatus.ENABLED && current == TunerStatus.DISABLED)
|
||||
{
|
||||
TunerConfiguration tunerConfiguration = mTunerConfigurationManager
|
||||
.getTunerConfiguration(tunerType, discoveredTuner.getId());
|
||||
|
||||
if(tunerConfiguration != null)
|
||||
{
|
||||
discoveredTuner.setTunerConfiguration(tunerConfiguration);
|
||||
mTunerConfigurationManager.saveConfigurations();
|
||||
}
|
||||
rspDuoTuner2.setEnabled(false);
|
||||
}
|
||||
else if(previous == TunerStatus.DISABLED && current == TunerStatus.ENABLED)
|
||||
{
|
||||
rspDuoTuner2.setEnabled(true);
|
||||
rspDuoTuner2.start();
|
||||
}
|
||||
}
|
||||
|
||||
//Notify tuner configuration manager to apply tuner configurations & update disabled tuner states
|
||||
mTunerConfigurationManager.tunerStatusUpdated(rspDuoTuner1, previous, current);
|
||||
|
||||
if(rspDuoTuner2 != null)
|
||||
{
|
||||
mTunerConfigurationManager.tunerStatusUpdated(rspDuoTuner2, previous, current);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Notify tuner configuration manager to apply tuner configuration
|
||||
mTunerConfigurationManager.tunerStatusUpdated(discoveredTuner, previous, current);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -34,6 +34,12 @@ public enum TunerStatus
|
||||
*/
|
||||
DISABLED("Disabled"),
|
||||
|
||||
|
||||
/**
|
||||
* Indicates that the tuner has been removed from the system.
|
||||
*/
|
||||
REMOVED("Removed"),
|
||||
|
||||
/**
|
||||
* A tuner that has an error state and is unusable
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.DeviceSelectionMode;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.Status;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.UpdateReason;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.callback.IDeviceEventListener;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.callback.IStreamListener;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.Device;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.AgcMode;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.GainReduction;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.IfMode;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.LoMode;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Base RSP control implementation
|
||||
*/
|
||||
public abstract class ControlRsp<T extends Device> implements IControlRsp
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(ControlRsp.class);
|
||||
private T mDevice;
|
||||
protected RspSampleRate mSampleRate = RspSampleRate.RATE_8_000;
|
||||
protected int mGain;
|
||||
private IDeviceEventListener mDeviceEventListener;
|
||||
private IStreamListener mStreamListener;
|
||||
|
||||
//Streaming control lock and boolean status indicator. Access to the boolean indicator is protected by the lock.
|
||||
protected ReentrantLock mStreamingLock = new ReentrantLock();
|
||||
protected boolean mStreaming = false;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param device for the device, obtained from the API
|
||||
*/
|
||||
public ControlRsp(T device)
|
||||
{
|
||||
mDevice = device;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerSelect getTunerSelect()
|
||||
{
|
||||
return TunerSelect.TUNER_1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws SDRPlayException
|
||||
{
|
||||
if(hasDevice())
|
||||
{
|
||||
getDevice().select();
|
||||
|
||||
//Enable automatic DC and I/Q correction
|
||||
getDevice().getCompositeParameters().getControlAParameters().getDcOffset().setDC(true);
|
||||
getDevice().getCompositeParameters().getControlAParameters().getDcOffset().setIQ(true);
|
||||
|
||||
//Setup IF, LO, and AGC Mode
|
||||
getDevice().getCompositeParameters().getControlAParameters().getAgc().setAgcMode(AgcMode.DISABLE);
|
||||
getDevice().setIfMode(IfMode.IF_ZERO);
|
||||
getDevice().setLoMode(LoMode.AUTO);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SDRPlayException("Unable to start - device is null");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() throws SDRPlayException
|
||||
{
|
||||
if(hasDevice())
|
||||
{
|
||||
stopStream();
|
||||
getDevice().release();
|
||||
clearDevice();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startStream()
|
||||
{
|
||||
mStreamingLock.lock();
|
||||
|
||||
try
|
||||
{
|
||||
if(hasDevice())
|
||||
{
|
||||
if(!mStreaming)
|
||||
{
|
||||
getDevice().initStreamA(getDeviceEventListener(), getStreamListener());
|
||||
mStreaming = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error("Unable to start RSP device sample stream - device not started");
|
||||
}
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
if(se.getStatus() == Status.FAIL)
|
||||
{
|
||||
mLog.error("Unable to start RSP streaming - device may have been unplugged - removing.");
|
||||
if(mDeviceEventListener != null)
|
||||
{
|
||||
mDeviceEventListener.processDeviceRemoval(getTunerSelect());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error("Unable to initialize/start streaming for RSP device", se);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
mStreamingLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopStream()
|
||||
{
|
||||
mStreamingLock.lock();
|
||||
|
||||
try
|
||||
{
|
||||
if(hasDevice() && mStreaming)
|
||||
{
|
||||
getDevice().uninitialize();
|
||||
}
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
mLog.error("Unable to uninitialize/stop streaming for RSP device");
|
||||
}
|
||||
finally
|
||||
{
|
||||
mStreaming = false;
|
||||
mStreamingLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeviceSelectionMode getDeviceSelectionMode()
|
||||
{
|
||||
//Default device selection mode for all tuners except the RSPduo
|
||||
return DeviceSelectionMode.SINGLE_TUNER_1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Device descriptor for this device
|
||||
*/
|
||||
public T getDevice()
|
||||
{
|
||||
return mDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* RSP device was unplugged from USB bus. Clear the device and do not attempt any further interaction with the
|
||||
* device via the API.
|
||||
*/
|
||||
@Override
|
||||
public void deviceRemoved()
|
||||
{
|
||||
clearDevice();
|
||||
|
||||
mStreamingLock.lock();
|
||||
|
||||
try
|
||||
{
|
||||
mStreaming = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
mStreamingLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears/nullifies the device. This should be invoked after stopping the device to prevent reuse.
|
||||
*/
|
||||
public void clearDevice()
|
||||
{
|
||||
mDevice = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this control has a non-null device.
|
||||
* @return true if non-null device.
|
||||
*/
|
||||
public boolean hasDevice()
|
||||
{
|
||||
return getDevice() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sample rate
|
||||
* @param sampleRate enumeration value.
|
||||
* @throws SDRPlayException
|
||||
*/
|
||||
@Override
|
||||
public void setSampleRate(RspSampleRate sampleRate) throws SDRPlayException
|
||||
{
|
||||
if(hasDevice())
|
||||
{
|
||||
mSampleRate = sampleRate;
|
||||
getDevice().getTuner().setBandwidth(sampleRate.getBandwidth());
|
||||
getDevice().getCompositeParameters().getDeviceParameters().getSamplingFrequency()
|
||||
.setSampleRate(sampleRate.getSampleRate());
|
||||
getDevice().update(getTunerSelect(), UpdateReason.DEVICE_SAMPLE_RATE);
|
||||
getDevice().getCompositeParameters().getControlAParameters().getDecimation().setWideBandSignal(true);
|
||||
getDevice().setDecimation(sampleRate.getDecimation());
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SDRPlayException("RSP tuner has not been started - can't apply sample rate");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the gain index
|
||||
* @param gain index value (0 - 28)
|
||||
* @throws SDRPlayException
|
||||
*/
|
||||
@Override
|
||||
public void setGain(int gain) throws SDRPlayException
|
||||
{
|
||||
validateGain(gain);
|
||||
|
||||
if(gain != mGain)
|
||||
{
|
||||
mGain = gain;
|
||||
getDevice().getTuner().setGain(mGain);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void acknowledgePowerOverload(TunerSelect tunerSelect) throws SDRPlayException
|
||||
{
|
||||
if(hasDevice())
|
||||
{
|
||||
getDevice().acknowledgePowerOverload(tunerSelect);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SDRPlayException("Device is not initialized");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTunedFrequency() throws SDRPlayException
|
||||
{
|
||||
if(hasDevice())
|
||||
{
|
||||
return getDevice().getTuner().getFrequency();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SDRPlayException("Device is not initialized");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTunedFrequency(long frequency) throws SDRPlayException
|
||||
{
|
||||
if(hasDevice())
|
||||
{
|
||||
getDevice().getTuner().setFrequency(frequency);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SDRPlayException("Device is not initialized");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Current sample rate setting
|
||||
*/
|
||||
@Override
|
||||
public RspSampleRate getSampleRateEnumeration()
|
||||
{
|
||||
return mSampleRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Current sample rate
|
||||
*/
|
||||
@Override
|
||||
public double getCurrentSampleRate()
|
||||
{
|
||||
return getSampleRateEnumeration().getEffectiveSampleRate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Current gain index
|
||||
* @return gain index
|
||||
*/
|
||||
@Override
|
||||
public int getGain()
|
||||
{
|
||||
return mGain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that the requested gain index setting is within the range of valid gain values.
|
||||
* @param gain to validate
|
||||
* @throws SDRPlayException if the gain index value is outside the range of valid values.
|
||||
*/
|
||||
protected void validateGain(int gain) throws SDRPlayException
|
||||
{
|
||||
if(gain < GainReduction.MIN_GAIN_INDEX || gain > GainReduction.MAX_GAIN_INDEX)
|
||||
{
|
||||
throw new SDRPlayException("Invalid gain index value [" + gain + "]. Valid range is " +
|
||||
GainReduction.MIN_GAIN_INDEX + " - " + GainReduction.MAX_GAIN_INDEX);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers listeners to receive device events and sample streams.
|
||||
* @param deviceEventListener to receive device events
|
||||
* @param streamListener to receive sample stream and related parameters.
|
||||
*/
|
||||
@Override
|
||||
public void resister(IDeviceEventListener deviceEventListener, IStreamListener streamListener)
|
||||
{
|
||||
mDeviceEventListener = deviceEventListener;
|
||||
mStreamListener = streamListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registered device event listener
|
||||
* @return device event listener or null if a listener has not been registered.
|
||||
*/
|
||||
protected IDeviceEventListener getDeviceEventListener()
|
||||
{
|
||||
return mDeviceEventListener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registered stream listener
|
||||
* @return stream listener or null if a listener has not been registered.
|
||||
*/
|
||||
protected IStreamListener getStreamListener()
|
||||
{
|
||||
return mStreamListener;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay;
|
||||
|
||||
import io.github.dsheirer.preference.source.ChannelizerType;
|
||||
import io.github.dsheirer.source.tuner.TunerClass;
|
||||
import io.github.dsheirer.source.tuner.TunerFactory;
|
||||
import io.github.dsheirer.source.tuner.manager.DiscoveredTuner;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.DeviceInfo;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.DeviceType;
|
||||
|
||||
/**
|
||||
* Discovered SDRplay RSP tuner
|
||||
*/
|
||||
public abstract class DiscoveredRspTuner<R extends IControlRsp> extends DiscoveredTuner
|
||||
{
|
||||
private final DeviceInfo mDeviceInfo;
|
||||
private final ChannelizerType mChannelizerType;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param deviceInfo to select the device from the API
|
||||
*/
|
||||
public DiscoveredRspTuner(DeviceInfo deviceInfo, ChannelizerType channelizerType)
|
||||
{
|
||||
mDeviceInfo = deviceInfo;
|
||||
mChannelizerType = channelizerType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about the discovered RSP device
|
||||
* @return device info
|
||||
*/
|
||||
public DeviceInfo getDeviceInfo()
|
||||
{
|
||||
return mDeviceInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Channelizer type to use for the tuner
|
||||
*/
|
||||
protected ChannelizerType getChannelizerType()
|
||||
{
|
||||
return mChannelizerType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerClass getTunerClass()
|
||||
{
|
||||
return TunerClass.RSP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Type of RSP tuner device
|
||||
*/
|
||||
public DeviceType getDeviceType()
|
||||
{
|
||||
return mDeviceInfo.getDeviceType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs and starts the tuner
|
||||
*/
|
||||
@Override
|
||||
public void start()
|
||||
{
|
||||
if(isAvailable() && !hasTuner())
|
||||
{
|
||||
try
|
||||
{
|
||||
mTuner = TunerFactory.getRspTuner(getDeviceInfo(), getChannelizerType(), this);
|
||||
}
|
||||
catch(Exception se)
|
||||
{
|
||||
setErrorMessage("Tuner unavailable [" + getId() + "]");
|
||||
mTuner = null;
|
||||
}
|
||||
|
||||
if(hasTuner())
|
||||
{
|
||||
try
|
||||
{
|
||||
mTuner.start();
|
||||
}
|
||||
catch(Exception se)
|
||||
{
|
||||
setErrorMessage("Error starting tuner [" + getId() + "]");
|
||||
mTuner = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId()
|
||||
{
|
||||
return getDeviceType().name() + " SER#" + getDeviceInfo().getSerialNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return getId();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.DeviceSelectionMode;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.callback.IDeviceEventListener;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.callback.IStreamListener;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.Device;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
|
||||
|
||||
/**
|
||||
* Control interface for base RSP device
|
||||
*/
|
||||
public interface IControlRsp
|
||||
{
|
||||
DeviceSelectionMode getDeviceSelectionMode();
|
||||
|
||||
/**
|
||||
* Device descriptor for this RSP
|
||||
* @return device descriptor
|
||||
*/
|
||||
Device getDevice();
|
||||
|
||||
/**
|
||||
* Process an RSP device removal. Device memory resources should be nullified and the software should not attempt
|
||||
* any further interaction with the device via the API.
|
||||
*/
|
||||
void deviceRemoved();
|
||||
|
||||
/**
|
||||
* Selected tuner for this RSP.
|
||||
* @return selected tuner.
|
||||
*/
|
||||
TunerSelect getTunerSelect();
|
||||
|
||||
/**
|
||||
* Starts the device
|
||||
*/
|
||||
void start() throws SDRPlayException;
|
||||
|
||||
/**
|
||||
* Stops the device
|
||||
*/
|
||||
void stop() throws SDRPlayException;
|
||||
|
||||
/**
|
||||
* Registers listeners to receive device events and streaming samples when startStream() is invoked.
|
||||
* @param deviceEventListener to receive device events
|
||||
* @param streamListener to receive sample stream and related parameters.
|
||||
*/
|
||||
void resister(IDeviceEventListener deviceEventListener, IStreamListener streamListener);
|
||||
|
||||
/**
|
||||
* Starts the sample stream and delivers the samples to the registered listener.
|
||||
*/
|
||||
void startStream();
|
||||
|
||||
/**
|
||||
* Stops the sample stream.
|
||||
*/
|
||||
void stopStream();
|
||||
|
||||
/**
|
||||
* Callback to acknowledge a power overload event.
|
||||
* @param tunerSelect identifies the tuner where the power overload is happening.
|
||||
*/
|
||||
void acknowledgePowerOverload(TunerSelect tunerSelect) throws SDRPlayException;
|
||||
|
||||
/**
|
||||
* Current center tune frequency
|
||||
* @return frequency in Hertz
|
||||
*/
|
||||
long getTunedFrequency() throws SDRPlayException;
|
||||
|
||||
/**
|
||||
* Sets the center tune frequency
|
||||
* @param frequency in Hertz
|
||||
*/
|
||||
void setTunedFrequency(long frequency) throws SDRPlayException;
|
||||
|
||||
/**
|
||||
* Current sample rate enumeration value
|
||||
* @return sample rate enumeration.
|
||||
*/
|
||||
RspSampleRate getSampleRateEnumeration();
|
||||
|
||||
/**
|
||||
* Sets the sample rate.
|
||||
* @param rspSampleRate enumeration value.
|
||||
*/
|
||||
void setSampleRate(RspSampleRate rspSampleRate) throws SDRPlayException;
|
||||
|
||||
/**
|
||||
* Current sample rate value.
|
||||
* @return sample rate in Hertz
|
||||
*/
|
||||
double getCurrentSampleRate();
|
||||
|
||||
/**
|
||||
* Sets the gain index value.
|
||||
* @param gain index value (0 - 28)
|
||||
*/
|
||||
void setGain(int gain) throws SDRPlayException;
|
||||
|
||||
/**
|
||||
* Current gain index value
|
||||
* @return gain index value (0 - 28)
|
||||
*/
|
||||
int getGain();
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay;
|
||||
|
||||
import io.github.dsheirer.buffer.AbstractNativeBuffer;
|
||||
import io.github.dsheirer.sample.complex.ComplexSamples;
|
||||
import io.github.dsheirer.sample.complex.InterleavedComplexSamples;
|
||||
import java.util.Iterator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Native buffer implementation for RSP tuner I/Q sample buffers.
|
||||
*
|
||||
* Note: in testing with API v3.07, the daemon returns 2016 samples in each of the I and Q arrays.
|
||||
*/
|
||||
public class RspNativeBuffer extends AbstractNativeBuffer
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(RspNativeBuffer.class);
|
||||
private static final float SAMPLE_TO_FLOAT = 1.0f / 32768.0f;
|
||||
private short[] mISamples;
|
||||
private short[] mQSamples;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param i samples array
|
||||
* @param q samples array
|
||||
* @param timestamp for the first sample
|
||||
* @param samplesPerMillisecond used to calculate sub-buffer fragment timestamp offsets from the start of this buffer.
|
||||
*/
|
||||
public RspNativeBuffer(short[] i, short[] q, long timestamp, float samplesPerMillisecond)
|
||||
{
|
||||
super(timestamp, samplesPerMillisecond);
|
||||
mISamples = i;
|
||||
mQSamples = q;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator over samples that produces complex sample buffers.
|
||||
*/
|
||||
@Override
|
||||
public Iterator<ComplexSamples> iterator()
|
||||
{
|
||||
return new SampleIterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator over samples that produces interleaved complex sample buffers
|
||||
*/
|
||||
@Override
|
||||
public Iterator<InterleavedComplexSamples> iteratorInterleaved()
|
||||
{
|
||||
return new InterleavedSampleIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sampleCount()
|
||||
{
|
||||
return mISamples.length * 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Iterator providing (non-interleaved) complex sample buffers
|
||||
*/
|
||||
private class SampleIterator implements Iterator<ComplexSamples>
|
||||
{
|
||||
private int mSamplePointer;
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
return mSamplePointer < mISamples.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComplexSamples next()
|
||||
{
|
||||
float[] i = new float[mISamples.length];
|
||||
float[] q = new float[mISamples.length];
|
||||
|
||||
for(int x = 0; x < mISamples.length; x++)
|
||||
{
|
||||
i[x] = mISamples[x] * SAMPLE_TO_FLOAT;
|
||||
q[x] = mQSamples[x] * SAMPLE_TO_FLOAT;
|
||||
}
|
||||
|
||||
mSamplePointer += mISamples.length;
|
||||
|
||||
return new ComplexSamples(i, q, getTimestamp());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Interator providing interleaved sample buffers.
|
||||
*/
|
||||
private class InterleavedSampleIterator implements Iterator<InterleavedComplexSamples>
|
||||
{
|
||||
private int mSamplePointer;
|
||||
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
return mSamplePointer < mISamples.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InterleavedComplexSamples next()
|
||||
{
|
||||
float[] samples = new float[mISamples.length * 2];
|
||||
|
||||
int index = 0;
|
||||
|
||||
for(int x = 0; x < mISamples.length; x++)
|
||||
{
|
||||
samples[index++] = mISamples[x] * SAMPLE_TO_FLOAT;
|
||||
samples[index++] = mQSamples[x] * SAMPLE_TO_FLOAT;
|
||||
}
|
||||
|
||||
mSamplePointer += mISamples.length;
|
||||
|
||||
return new InterleavedComplexSamples(samples, getTimestamp());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.Decimate;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.Bandwidth;
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* RSP device Sample Rate, Bandwidth and Decimation enumeration
|
||||
*
|
||||
* Note: final effective sample rate must be greater than IF bandwidth setting to avoid aliasing. The available IF
|
||||
* bandwidth values effectively dictate the available sample rates
|
||||
*/
|
||||
public enum RspSampleRate
|
||||
{
|
||||
RATE_0_250(8_000_000, 016_000, Bandwidth.BW_0_300, Decimate.X32, "0.250 MHz (0.234 usable)"),
|
||||
RATE_0_500(8_000_000, 024_000, Bandwidth.BW_0_600, Decimate.X16, "0.500 MHz (0.476 usable)"),
|
||||
RATE_1_000(8_000_000, 100_000, Bandwidth.BW_1_536, Decimate.X8, "1.000 MHz (0.900 usable)"),
|
||||
RATE_1_500(6_000_000, 140_000, Bandwidth.BW_1_536, Decimate.X4, "1.500 MHz (1.360 usable)"),
|
||||
RATE_3_000(6_000_000, 300_000, Bandwidth.BW_5_000, Decimate.X2, "3.000 MHz (2.700 usable)"),
|
||||
RATE_4_000(8_000_000, 340_000, Bandwidth.BW_5_000, Decimate.X2, "4.000 MHz (3.560 usable)"),
|
||||
RATE_5_000(5_000_000, 880_000, Bandwidth.BW_5_000, Decimate.X1, "5.000 MHz (4.120 usable)"),
|
||||
RATE_6_000(6_000_000, 800_000, Bandwidth.BW_6_000, Decimate.X1, "6.000 MHz (5.200 usable)"),
|
||||
RATE_7_000(7_000_000, 1_040_000, Bandwidth.BW_7_000, Decimate.X1, "7.000 MHz (5.960 usable)"),
|
||||
RATE_8_000(8_000_000, 1_060_000, Bandwidth.BW_8_000, Decimate.X1, "8.000 MHz (6.940 usable)"),
|
||||
RATE_9_000(9_000_000, 1_620_000, Bandwidth.BW_8_000, Decimate.X1, "9.000 MHz (7.380 usable)"),
|
||||
RATE_10_000(10_000_000, 1_500_000, Bandwidth.BW_8_000, Decimate.X1, "10.000 MHz (8.500 usable)"),
|
||||
|
||||
/**
|
||||
* Note: in dual tuner mode, available sample rates are 6 or 8 MHz with an effective output rate of
|
||||
* 2 MHz. Decimation is applied against the final 2 MHz rate, not the original 6/8 sampling rate.
|
||||
*/
|
||||
DUO_RATE_0_500(8_000_000, 50_000, Bandwidth.BW_8_000, Decimate.X4, "0.500 MHz (0.450 usable)"),
|
||||
DUO_RATE_1_000(8_000_000, 50_000, Bandwidth.BW_8_000, Decimate.X2, "1.000 MHz (0.950 usable)"),
|
||||
DUO_RATE_1_500(6_000_000, 0, Bandwidth.BW_6_000, Decimate.X1, "1.500 MHz (1.500 usable)"),
|
||||
DUO_RATE_2_000(8_000_000, 0, Bandwidth.BW_8_000, Decimate.X1, "2.000 MHz (2.000 usable)"),
|
||||
|
||||
UNDEFINED(0, 0, Bandwidth.UNDEFINED, Decimate.X1, "UNDEFINED");
|
||||
|
||||
private long mSampleRate;
|
||||
private long mUnusable;
|
||||
private Bandwidth mBandwidth;
|
||||
private Decimate mDecimation;
|
||||
private String mDescription;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param sampleRate in hertz
|
||||
* @param unusable bandwidth (total) in Hertz due to IF or decimation filter roll-off at spectrum edges
|
||||
* @param bandwidth of the frequency spectrum
|
||||
* @param decimation to be applied to the original sample rate to achieve the effective sample rate
|
||||
* @param description for UI display
|
||||
*/
|
||||
RspSampleRate(long sampleRate, long unusable, Bandwidth bandwidth, Decimate decimation, String description)
|
||||
{
|
||||
mSampleRate = sampleRate;
|
||||
mUnusable = unusable;
|
||||
mBandwidth = bandwidth;
|
||||
mDecimation = decimation;
|
||||
mDescription = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Single tuner sample rates for all devices operating in single tuner mode
|
||||
*/
|
||||
public static EnumSet<RspSampleRate> SINGLE_TUNER_SAMPLE_RATES = EnumSet.range(RATE_0_250, RATE_10_000);
|
||||
|
||||
/**
|
||||
* RSPduo dual-tuner mode sample rates
|
||||
*/
|
||||
public static EnumSet<RspSampleRate> DUAL_TUNER_SAMPLE_RATES = EnumSet.range(DUO_RATE_0_500, DUO_RATE_2_000);
|
||||
|
||||
/**
|
||||
* Sample Rate
|
||||
* @return sample rate (Hz)
|
||||
*/
|
||||
public long getSampleRate()
|
||||
{
|
||||
return mSampleRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Usable bandwidth in range 0.0 to 1.0, where 1.0 is 100% usable bandwidth
|
||||
*/
|
||||
public double getUsableBandwidth()
|
||||
{
|
||||
if(getSampleRate() != 0)
|
||||
{
|
||||
return 1.0 - ((double)mUnusable / (double)getEffectiveSampleRate());
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is a sample rate supported by the RSPduo operating in dual-tuner mode.
|
||||
* @return true if this is a dual-tuner sample rate.
|
||||
*/
|
||||
public boolean isDualTunerSampleRate()
|
||||
{
|
||||
return DUAL_TUNER_SAMPLE_RATES.contains(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample size in bits. Can be used to adjust spectral display for effective dynamic range.
|
||||
* @return sample size in bits.
|
||||
*/
|
||||
public int getSampleSize()
|
||||
{
|
||||
return mDecimation.getSampleSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decimation rate to be applied against sample rate.
|
||||
* @return decimation value
|
||||
*/
|
||||
public Decimate getDecimation()
|
||||
{
|
||||
return mDecimation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this sample rate specifies decimation
|
||||
*/
|
||||
public boolean hasDecimation()
|
||||
{
|
||||
return getDecimation().isEnabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Effective Sample Rate (sample rate / decimation). Note: for RSPduo operating in dual-tuner mode, an
|
||||
* inherent x4 decimation is applied in the hardware.
|
||||
* @return effective sample rate (Hz)
|
||||
*/
|
||||
public long getEffectiveSampleRate()
|
||||
{
|
||||
if(isDualTunerSampleRate())
|
||||
{
|
||||
//Dual tuner sample rate is specified at 8 MHz, but there is an inherent x4 decimation to 2 MHz
|
||||
//on top of the user specified decimation rate.
|
||||
return getSampleRate() / getDecimation().getValue() / 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
return getSampleRate() / getDecimation().getValue();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bandwidth entry
|
||||
*/
|
||||
public Bandwidth getBandwidth()
|
||||
{
|
||||
return mBandwidth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default string representation to use the UI description/label.
|
||||
* @return string representation of the entry
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay;
|
||||
|
||||
import io.github.dsheirer.preference.source.ChannelizerType;
|
||||
import io.github.dsheirer.source.tuner.ITunerErrorListener;
|
||||
import io.github.dsheirer.source.tuner.Tuner;
|
||||
import io.github.dsheirer.source.tuner.TunerClass;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.IControlRspDuoTuner1;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.IControlRspDuoTuner2;
|
||||
|
||||
/**
|
||||
* Generic RSP tuner with a device specific tuner controller implementation.
|
||||
*/
|
||||
public class RspTuner extends Tuner
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param tunerController for controlling the tuner
|
||||
* @param tunerErrorListener to process errors from this tuner
|
||||
* @param channelizerType to use with this tuner
|
||||
*/
|
||||
public RspTuner(RspTunerController tunerController, ITunerErrorListener tunerErrorListener, ChannelizerType channelizerType)
|
||||
{
|
||||
super(tunerController, tunerErrorListener, channelizerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumUSBBitsPerSecond()
|
||||
{
|
||||
//12-bits per sample, 2 samples per frame, 10 MHz sample rate
|
||||
return 320_000_000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueID()
|
||||
{
|
||||
return getRspTunerController().getControlRsp().getDevice().getSerialNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerClass getTunerClass()
|
||||
{
|
||||
return TunerClass.RSP;
|
||||
}
|
||||
|
||||
/**
|
||||
* RSP Tuner controller for this tuner
|
||||
*/
|
||||
public RspTunerController getRspTunerController()
|
||||
{
|
||||
return (RspTunerController)getTunerController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferredName()
|
||||
{
|
||||
if(getRspTunerController().getControlRsp() instanceof IControlRspDuoTuner1 &&
|
||||
getRspTunerController().getControlRsp().getDevice() != null)
|
||||
{
|
||||
return getRspTunerController().getControlRsp().getDevice().getDeviceType() +
|
||||
" SER:" + getRspTunerController().getControlRsp().getDevice().getSerialNumber() + " Tuner 1";
|
||||
}
|
||||
else if(getRspTunerController().getControlRsp() instanceof IControlRspDuoTuner2 &&
|
||||
getRspTunerController().getControlRsp().getDevice() != null)
|
||||
{
|
||||
return getRspTunerController().getControlRsp().getDevice().getDeviceType() +
|
||||
" SER:" + getRspTunerController().getControlRsp().getDevice().getSerialNumber() + " Tuner 2";
|
||||
}
|
||||
else if(getRspTunerController().getControlRsp() instanceof IControlRsp &&
|
||||
getRspTunerController().getControlRsp().getDevice() != null)
|
||||
{
|
||||
return getRspTunerController().getControlRsp().getDevice().getDeviceType() +
|
||||
" SER:" + getRspTunerController().getControlRsp().getDevice().getSerialNumber();
|
||||
}
|
||||
else
|
||||
{
|
||||
return "RSP Tuner - Device Not Available";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getSampleSize()
|
||||
{
|
||||
return getRspTunerController().getControlRsp().getSampleRateEnumeration().getSampleSize();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.GainReduction;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp1a.Rsp1aTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rsp2.Rsp2TunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner1Configuration;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDuo.RspDuoTuner2Configuration;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.rspDx.RspDxTunerConfiguration;
|
||||
|
||||
/**
|
||||
* Abstract RSP tuner configuration
|
||||
*/
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
|
||||
@JsonSubTypes({
|
||||
@JsonSubTypes.Type(value = Rsp1aTunerConfiguration.class, name = "rsp1aTunerConfiguration"),
|
||||
@JsonSubTypes.Type(value = Rsp2TunerConfiguration.class, name = "rsp2TunerConfiguration"),
|
||||
@JsonSubTypes.Type(value = RspDuoTuner1Configuration.class, name = "rspDuoTuner1Configuration"),
|
||||
@JsonSubTypes.Type(value = RspDuoTuner2Configuration.class, name = "rspDuoTuner2Configuration"),
|
||||
@JsonSubTypes.Type(value = RspDxTunerConfiguration.class, name = "rspDxTunerConfiguration"),
|
||||
})
|
||||
public abstract class RspTunerConfiguration extends TunerConfiguration
|
||||
{
|
||||
public static final RspSampleRate DEFAULT_SINGLE_TUNER_SAMPLE_RATE = RspSampleRate.RATE_8_000;
|
||||
public static final RspSampleRate DEFAULT_DUAL_TUNER_SAMPLE_RATE = RspSampleRate.DUO_RATE_2_000;
|
||||
|
||||
private RspSampleRate mRspSampleRate = DEFAULT_SINGLE_TUNER_SAMPLE_RATE;
|
||||
private int mGain = 14;
|
||||
|
||||
/**
|
||||
* JAXB Constructor
|
||||
*/
|
||||
public RspTunerConfiguration()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance with the specified unique id
|
||||
* @param uniqueId for the tuner
|
||||
*/
|
||||
public RspTunerConfiguration(String uniqueId)
|
||||
{
|
||||
super(uniqueId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample rate for the tuner
|
||||
*/
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "sampleRate")
|
||||
public RspSampleRate getSampleRate()
|
||||
{
|
||||
return mRspSampleRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sample rate for the tuner
|
||||
*/
|
||||
public void setSampleRate(RspSampleRate rspSampleRate)
|
||||
{
|
||||
mRspSampleRate = rspSampleRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gain index to use
|
||||
* @return gain index, 0 - 28
|
||||
*/
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "gain")
|
||||
public int getGain()
|
||||
{
|
||||
return mGain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the gain index
|
||||
* @param gain index, 0 - 28
|
||||
*/
|
||||
public void setGain(int gain)
|
||||
{
|
||||
if(GainReduction.MIN_GAIN_INDEX <= gain && gain <= GainReduction.MAX_GAIN_INDEX)
|
||||
{
|
||||
mGain = gain;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay;
|
||||
|
||||
import io.github.dsheirer.buffer.INativeBuffer;
|
||||
import io.github.dsheirer.sample.Listener;
|
||||
import io.github.dsheirer.source.SourceException;
|
||||
import io.github.dsheirer.source.tuner.ITunerErrorListener;
|
||||
import io.github.dsheirer.source.tuner.TunerController;
|
||||
import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.callback.IDeviceEventListener;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.callback.IStreamListener;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.callback.StreamCallbackParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.event.EventType;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.event.GainCallbackParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.event.PowerOverloadCallbackParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.event.RspDuoModeCallbackParameters;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Abstract/Base RSP tuner controller
|
||||
*/
|
||||
public abstract class RspTunerController<I extends IControlRsp> extends TunerController
|
||||
implements IDeviceEventListener, IStreamListener
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(RspTunerController.class);
|
||||
protected static final long MINIMUM_FREQUENCY = 100_000;
|
||||
protected static final long MAXIMUM_FREQUENCY = 2_000_000_000;
|
||||
protected static final int MIDDLE_UNUSABLE_BANDWIDTH = 0;
|
||||
private I mControlRsp;
|
||||
|
||||
/**
|
||||
* Abstract tuner controller class. The tuner controller manages frequency bandwidth and currently tuned channels
|
||||
* that are being fed samples from the tuner.
|
||||
*
|
||||
* @param controlRsp that is the RSP tuner
|
||||
* @param tunerErrorListener to monitor errors produced from this tuner controller
|
||||
*/
|
||||
public RspTunerController(I controlRsp, ITunerErrorListener tunerErrorListener)
|
||||
{
|
||||
super(tunerErrorListener);
|
||||
mControlRsp = controlRsp;
|
||||
|
||||
//Register this controller to receive device events and sample streams when startStream() is invoked.
|
||||
mControlRsp.resister(this, this);
|
||||
|
||||
setMinimumFrequency(MINIMUM_FREQUENCY);
|
||||
setMaximumFrequency(MAXIMUM_FREQUENCY);
|
||||
setMiddleUnusableHalfBandwidth(MIDDLE_UNUSABLE_BANDWIDTH);
|
||||
setUsableBandwidthPercentage(1.0); //Initial value
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(TunerConfiguration config) throws SourceException
|
||||
{
|
||||
if(config instanceof RspTunerConfiguration rtc)
|
||||
{
|
||||
//This sets the frequency and software PPM
|
||||
super.apply(config);
|
||||
|
||||
try
|
||||
{
|
||||
setSampleRate(rtc.getSampleRate());
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
mLog.error("Error setting RSP sample rate to " + rtc.getSampleRate(), se);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
getControlRsp().setGain(rtc.getGain());
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
mLog.error("Error setting RSP gain index to " + rtc.getGain());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The RSP control for this tuner controller
|
||||
*/
|
||||
public I getControlRsp()
|
||||
{
|
||||
return mControlRsp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerSelect getTunerSelect()
|
||||
{
|
||||
return mControlRsp.getTunerSelect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processStream(short[] inphase, short[] quadrature,
|
||||
StreamCallbackParameters parameters, boolean reset)
|
||||
{
|
||||
//RSP I/Q sample buffers are small and don't currently get fragmented by the RspNativeBuffer, so we don't
|
||||
//calculate the sub-buffer samples per millisecond value -- just use a constant value of 0.
|
||||
mNativeBufferBroadcaster.broadcast(new RspNativeBuffer(inphase, quadrature, System.currentTimeMillis(), 0.0f));
|
||||
|
||||
if(reset)
|
||||
{
|
||||
// mLog.info(getControlRsp().getDeviceDescriptor().getDeviceType() + " - sample stream was reset");
|
||||
}
|
||||
if(parameters.isGainReductionChanged())
|
||||
{
|
||||
// mLog.info("^^^ Got a gain reduction change");
|
||||
}
|
||||
if(parameters.isRfFrequencyChanged())
|
||||
{
|
||||
// mLog.info("^^^ Got a frequency changed");
|
||||
}
|
||||
if(parameters.isSampleRateChanged())
|
||||
{
|
||||
// mLog.info("^^^ Got a sample rate changed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts this RSP tuner and attempts to claim the device via the API
|
||||
* @throws SourceException
|
||||
*/
|
||||
@Override
|
||||
public void start() throws SourceException
|
||||
{
|
||||
try
|
||||
{
|
||||
mControlRsp.start();
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
throw new SourceException("Unable to select tuner - in use");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop()
|
||||
{
|
||||
try
|
||||
{
|
||||
mControlRsp.stop();
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
mLog.error("Error releasing RSP tuner device", se);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the listener to receive native buffers and starts the sample stream when this is the first listener.
|
||||
* @param listener to add
|
||||
*/
|
||||
@Override
|
||||
public void addBufferListener(Listener<INativeBuffer> listener)
|
||||
{
|
||||
mBufferListenerLock.lock();
|
||||
|
||||
try
|
||||
{
|
||||
if(!hasBufferListeners())
|
||||
{
|
||||
mControlRsp.startStream();
|
||||
}
|
||||
|
||||
super.addBufferListener(listener);
|
||||
}
|
||||
finally
|
||||
{
|
||||
mBufferListenerLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the listener from receiving native buffers and stops the sample stream when this is the last listener.
|
||||
* @param listener to remove
|
||||
*/
|
||||
@Override
|
||||
public void removeBufferListener(Listener<INativeBuffer> listener)
|
||||
{
|
||||
mBufferListenerLock.lock();
|
||||
|
||||
try
|
||||
{
|
||||
super.removeBufferListener(listener);
|
||||
|
||||
if(!hasBufferListeners())
|
||||
{
|
||||
mControlRsp.stopStream();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
mBufferListenerLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Currently tuned frequency
|
||||
* @return frequency in Hertz
|
||||
* @throws SourceException if there is an error
|
||||
*/
|
||||
@Override
|
||||
public long getTunedFrequency() throws SourceException
|
||||
{
|
||||
try
|
||||
{
|
||||
return getControlRsp().getTunedFrequency();
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
throw new SourceException("Error setting tuned frequency", se);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the center tuned frequency.
|
||||
* @param frequency in Hertz
|
||||
* @throws SourceException if there is an error
|
||||
*/
|
||||
@Override
|
||||
public void setTunedFrequency(long frequency) throws SourceException
|
||||
{
|
||||
try
|
||||
{
|
||||
getControlRsp().setTunedFrequency(frequency);
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
throw new SourceException("Unable to set center frequency [" + frequency + "]", se);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sample rate
|
||||
* @param rspSampleRate to apply
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setSampleRate(RspSampleRate rspSampleRate) throws SDRPlayException
|
||||
{
|
||||
getControlRsp().setSampleRate(rspSampleRate);
|
||||
|
||||
try
|
||||
{
|
||||
mFrequencyController.setSampleRate((int) rspSampleRate.getEffectiveSampleRate());
|
||||
}
|
||||
catch(SourceException se)
|
||||
{
|
||||
mLog.error("Error setting sample rate in frequency controller");
|
||||
}
|
||||
|
||||
//Update the usable bandwidth based on the sample rate and filtered bandwidth
|
||||
setUsableBandwidthPercentage(rspSampleRate.getUsableBandwidth());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getCurrentSampleRate() throws SourceException
|
||||
{
|
||||
return getControlRsp().getCurrentSampleRate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBufferSampleCount()
|
||||
{
|
||||
return 128;
|
||||
}
|
||||
|
||||
//Device Event Listener interface methods ...
|
||||
@Override
|
||||
public void processEvent(EventType eventType, TunerSelect tunerSelect) {}
|
||||
@Override
|
||||
public void processGainChange(TunerSelect tunerSelect, GainCallbackParameters parameters) {}
|
||||
@Override
|
||||
public void processRspDuoModeChange(TunerSelect tunerSelect, RspDuoModeCallbackParameters parameters) {}
|
||||
@Override
|
||||
public void processPowerOverload(TunerSelect tunerSelect, PowerOverloadCallbackParameters parameters)
|
||||
{
|
||||
if(getControlRsp() != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
getControlRsp().acknowledgePowerOverload(tunerSelect);
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
mLog.error("Unable to acknowledge power overload for [" + tunerSelect + "]", se);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processDeviceRemoval(TunerSelect tunerSelect)
|
||||
{
|
||||
mLog.info("Processing device removal for tuner [" + tunerSelect + "] controller class [" + getClass().getSimpleName() + "]");
|
||||
//Command the control RSP to nullify the device so that we cease all attempts to control the device via the API
|
||||
if(getControlRsp() != null)
|
||||
{
|
||||
getControlRsp().deviceRemoved();
|
||||
}
|
||||
|
||||
//Signal that tuner is removed so parent tuner and discovered tuner wrapper can do graceful removal/cleanup
|
||||
tunerRemoved();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay;
|
||||
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.GainReduction;
|
||||
import io.github.dsheirer.source.tuner.ui.TunerEditor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JSlider;
|
||||
|
||||
/**
|
||||
* Abstract RSP tuner editor
|
||||
*/
|
||||
public abstract class RspTunerEditor<C extends RspTunerConfiguration> extends TunerEditor<RspTuner,C>
|
||||
{
|
||||
private Logger mLog = LoggerFactory.getLogger(RspTunerEditor.class);
|
||||
private JSlider mGainSlider;
|
||||
private JLabel mGainValueLabel;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param userPreferences for preference settings
|
||||
* @param tunerManager to notify for state changes
|
||||
* @param discoveredTuner to be edited.
|
||||
*/
|
||||
public RspTunerEditor(UserPreferences userPreferences, TunerManager tunerManager, DiscoveredRspTuner discoveredTuner)
|
||||
{
|
||||
super(userPreferences, tunerManager, discoveredTuner);
|
||||
}
|
||||
|
||||
private RspTunerController getTunerController()
|
||||
{
|
||||
return (RspTunerController) getTuner().getTunerController();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gain reduction slider control
|
||||
*/
|
||||
protected JSlider getGainSlider()
|
||||
{
|
||||
if(mGainSlider == null)
|
||||
{
|
||||
mGainSlider = new JSlider(JSlider.HORIZONTAL, GainReduction.MIN_GAIN_INDEX,
|
||||
GainReduction.MAX_GAIN_INDEX, GainReduction.MIN_GAIN_INDEX);
|
||||
mGainSlider.setEnabled(false);
|
||||
mGainSlider.setMajorTickSpacing(1);
|
||||
mGainSlider.setPaintTicks(true);
|
||||
mGainSlider.addChangeListener(event ->
|
||||
{
|
||||
int gain = mGainSlider.getValue();
|
||||
|
||||
if(hasTuner() && !isLoading())
|
||||
{
|
||||
try
|
||||
{
|
||||
getTunerController().getControlRsp().setGain(gain);
|
||||
save();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Couldn't set RSP gain to:" + gain, e);
|
||||
JOptionPane.showMessageDialog(mGainSlider, "Couldn't set RSP gain value to " + gain);
|
||||
}
|
||||
}
|
||||
|
||||
getGainValueLabel().setText(String.valueOf(gain));
|
||||
});
|
||||
}
|
||||
|
||||
return mGainSlider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Label for displaying current gain index value
|
||||
*/
|
||||
protected JLabel getGainValueLabel()
|
||||
{
|
||||
if(mGainValueLabel == null)
|
||||
{
|
||||
mGainValueLabel = new JLabel("0");
|
||||
mGainValueLabel.setEnabled(false);
|
||||
}
|
||||
|
||||
return mGainValueLabel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.RspDuoMode;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* Enumeration of modes that indicate how each SDRplay RSP device can be selected
|
||||
*/
|
||||
public enum DeviceSelectionMode
|
||||
{
|
||||
//All RSP devices
|
||||
SINGLE_TUNER_1("Single Tuner 1", RspDuoMode.SINGLE_TUNER, TunerSelect.TUNER_1),
|
||||
SINGLE_TUNER_2("Single Tuner 2", RspDuoMode.SINGLE_TUNER, TunerSelect.TUNER_2),
|
||||
MASTER_TUNER_1("Master - Tuner 1", RspDuoMode.MASTER, TunerSelect.TUNER_1),
|
||||
SLAVE_TUNER_2("Slave - Tuner 2", RspDuoMode.SLAVE, TunerSelect.TUNER_2);
|
||||
|
||||
private String mDescription;
|
||||
private RspDuoMode mRspDuoMode;
|
||||
private TunerSelect mTunerSelect;
|
||||
|
||||
/**
|
||||
* Private constructor
|
||||
* @param description of the mode
|
||||
* @param rspDuoMode that corresponds to the mode
|
||||
* @param tunerSelect tuner(s) that correspond to the mode
|
||||
*/
|
||||
DeviceSelectionMode(String description, RspDuoMode rspDuoMode, TunerSelect tunerSelect)
|
||||
{
|
||||
mDescription = description;
|
||||
mRspDuoMode = rspDuoMode;
|
||||
mTunerSelect = tunerSelect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of all selection modes available for the RSPduo
|
||||
*/
|
||||
public static final EnumSet<DeviceSelectionMode> MASTER_MODES = EnumSet.of(MASTER_TUNER_1);
|
||||
public static final EnumSet<DeviceSelectionMode> SLAVE_MODES = EnumSet.of(SLAVE_TUNER_2);
|
||||
public static final EnumSet<DeviceSelectionMode> SINGLE_TUNER_MODES = EnumSet.of(SINGLE_TUNER_1, SINGLE_TUNER_2);
|
||||
|
||||
/**
|
||||
* RSPduo mode associated with the selection mode
|
||||
*/
|
||||
public RspDuoMode getRspDuoMode()
|
||||
{
|
||||
return mRspDuoMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this mode is designated as a master mode.
|
||||
*/
|
||||
public boolean isMasterMode()
|
||||
{
|
||||
return MASTER_MODES.contains(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this mode is designated as a slave mode.
|
||||
*/
|
||||
public boolean isSlaveMode()
|
||||
{
|
||||
return SLAVE_MODES.contains(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is a single-tuner mode
|
||||
*/
|
||||
public boolean isSingleTunerMode()
|
||||
{
|
||||
return SINGLE_TUNER_MODES.contains(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tuner(s) associated with the selection mode
|
||||
*/
|
||||
public TunerSelect getTunerSelect()
|
||||
{
|
||||
return mTunerSelect;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
SDRplay API 3.07
|
||||
Auto-created from sdrplay api header files using JDK 17 jextract tool:
|
||||
|
||||
1. Install the sdrplay api
|
||||
2. On Linux, headers are located here: /usr/local/include/*.h
|
||||
3. cd into the (project)/jSDRplay/sdrplay-api/src/main/java/ directory
|
||||
4. Run: jextract -t io.github.dsheirer.sdrplay.api /usr/local/include/sdrplay_api.h -l libsdrplay_api --source
|
||||
|
||||
IntelliJ setup
|
||||
1. Run configuration
|
||||
2. JVM Option: --enable-native-access=ALL-UNNAMED
|
||||
3. Add library location to the java.library.path:
|
||||
Linux: /usr/local/lib
|
||||
Windows: ??
|
||||
MacOS: ??
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api;
|
||||
|
||||
/**
|
||||
* SDRplay checked exception.
|
||||
*/
|
||||
public class SDRPlayException extends Exception
|
||||
{
|
||||
private Status mStatus = Status.UNKNOWN;
|
||||
|
||||
/**
|
||||
* Creates an exception
|
||||
* @param message for the exception
|
||||
*/
|
||||
public SDRPlayException(String message)
|
||||
{
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an operation exception
|
||||
* @param message for the exception
|
||||
* @param status of the operation
|
||||
*/
|
||||
public SDRPlayException(String message, Status status)
|
||||
{
|
||||
super(message + " Status:" + status);
|
||||
mStatus = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an exception
|
||||
* @param message for the exception
|
||||
* @param throwable nested exception
|
||||
*/
|
||||
public SDRPlayException(String message, Throwable throwable)
|
||||
{
|
||||
super(message, throwable);
|
||||
}
|
||||
|
||||
public Status getStatus()
|
||||
{
|
||||
return mStatus;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* SDRplay failed update request checked exception.
|
||||
*/
|
||||
public class SDRPlayUpdateException extends SDRPlayException
|
||||
{
|
||||
private List<UpdateReason> mUpdateReasons = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Creates an operation exception
|
||||
* @param status of the operation
|
||||
* @param updateReasons that were submitted
|
||||
*/
|
||||
public SDRPlayUpdateException(Status status, List<UpdateReason> updateReasons)
|
||||
{
|
||||
super("Unable to update device parameters: " + updateReasons, status);
|
||||
}
|
||||
|
||||
/**
|
||||
* List of update reasons that failed.
|
||||
*/
|
||||
public List<UpdateReason> getUpdateReasons()
|
||||
{
|
||||
return mUpdateReasons;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,714 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.callback.CallbackFunctions;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.callback.IDeviceEventListener;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.callback.IStreamListener;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.Device;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.DeviceFactory;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.DeviceInfo;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.DeviceType;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.IDeviceStruct;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.error.DebugLevel;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.error.ErrorInformation;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.composite.CompositeParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.composite.CompositeParametersFactory;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.util.Flag;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_DeviceT;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_ErrorInfoT;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_h;
|
||||
import java.lang.foreign.MemoryAddress;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.foreign.MemorySession;
|
||||
import java.lang.foreign.ValueLayout;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* SDRplay API wrapper.
|
||||
*
|
||||
* Note: the jextract auto-generated RuntimeHelper contains a static block that attempts to load the sdrplay_api
|
||||
* library. This approach fails because the API is installed to a non-default location. Comment out the library
|
||||
* load code in the RuntimeHelper and we'll directly load the library.
|
||||
*
|
||||
* // System.loadLibrary("libsdrplay_api");
|
||||
*/
|
||||
public class SDRplay
|
||||
{
|
||||
public static final String SDRPLAY_API_LIBRARY_NAME = "sdrplay_api";
|
||||
public static final String SDRPLAY_API_PATH_LINUX_AND_OSX = "/usr/local/lib/libsdrplay_api.so";
|
||||
public static final String SDRPLAY_API_PATH_WINDOWS = System.getenv("ProgramFiles") +
|
||||
"\\SDRplay\\API\\" + (System.getProperty("sun.arch.data.model").contentEquals("64") ? "x64" : "x86") +
|
||||
"\\" + SDRPLAY_API_LIBRARY_NAME;
|
||||
public static final String JAVA_LIBRARY_PATH_KEY = "java.library.path";
|
||||
|
||||
private static final Logger mLog = LoggerFactory.getLogger(SDRplay.class);
|
||||
|
||||
/**
|
||||
* Foreign memory allocation resource scope
|
||||
*/
|
||||
private final MemorySession mGlobalMemorySession = MemorySession.global();
|
||||
|
||||
/**
|
||||
* Indicates if libsdrplay_api.xx library was found and loaded.
|
||||
*/
|
||||
private boolean mSdrplayLibraryLoaded;
|
||||
|
||||
/**
|
||||
* Indicates if the library is available, meaning that the host system library was loaded AND it supports the
|
||||
* correct API version
|
||||
*/
|
||||
private boolean mAvailable;
|
||||
|
||||
/**
|
||||
* Map of (reusable) callback functions for each device. Key value is the device handle memory address
|
||||
*/
|
||||
private final Map<MemoryAddress, CallbackFunctions> mDeviceCallbackFunctionsMap = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Detected version of the API installed on the local system.
|
||||
*/
|
||||
private Version mVersion;
|
||||
|
||||
/**
|
||||
* Controls logging of library load status so that it only gets logged once. Set to false once initial logging complete
|
||||
*/
|
||||
private static boolean sLibraryLoadStatusLogging = true;
|
||||
|
||||
/**
|
||||
* Constructs an instance of the SDRPLay API
|
||||
*/
|
||||
public SDRplay()
|
||||
{
|
||||
mSdrplayLibraryLoaded = loadLibrary();
|
||||
|
||||
if(mSdrplayLibraryLoaded)
|
||||
{
|
||||
Status openStatus = open();
|
||||
if(sLibraryLoadStatusLogging)
|
||||
{
|
||||
mLog.info("API library - open status: " + openStatus);
|
||||
}
|
||||
mAvailable = openStatus.success() && getVersion().isSupported();
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sLibraryLoadStatusLogging)
|
||||
{
|
||||
mLog.info("API library was not loaded");
|
||||
}
|
||||
mAvailable = false;
|
||||
}
|
||||
|
||||
if(isAvailable())
|
||||
{
|
||||
if(sLibraryLoadStatusLogging)
|
||||
{
|
||||
mLog.info("API library v" + getVersion() + " - loaded");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(sLibraryLoadStatusLogging)
|
||||
{
|
||||
mLog.info("API library is not available.");
|
||||
}
|
||||
}
|
||||
|
||||
sLibraryLoadStatusLogging = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Global Memory Session for this API instance
|
||||
*/
|
||||
private MemorySession getGlobalMemorySession()
|
||||
{
|
||||
return mGlobalMemorySession;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to load the SDRPlay API library from the local system.
|
||||
*
|
||||
* @return true if library was loaded successfully.
|
||||
*/
|
||||
private boolean loadLibrary()
|
||||
{
|
||||
try
|
||||
{
|
||||
String libraryPath = getSDRplayLibraryPath();
|
||||
if(sLibraryLoadStatusLogging)
|
||||
{
|
||||
mLog.info("Loading API Library from default install path: " + libraryPath);
|
||||
}
|
||||
System.loadLibrary(SDRPLAY_API_LIBRARY_NAME);
|
||||
return true;
|
||||
}
|
||||
catch(Throwable t)
|
||||
{
|
||||
mLog.error("Unable to load SDRplay API library from default install path. Loading from java system library path");
|
||||
|
||||
try
|
||||
{
|
||||
System.loadLibrary(SDRPLAY_API_LIBRARY_NAME);
|
||||
return true;
|
||||
}
|
||||
catch(Throwable t2)
|
||||
{
|
||||
String name = System.mapLibraryName(SDRPLAY_API_LIBRARY_NAME);
|
||||
|
||||
if(sLibraryLoadStatusLogging)
|
||||
{
|
||||
mLog.warn("SDRPlay API library not found/installed on this system. Ensure the API is installed either " +
|
||||
"in the default install location or the install location is included in the " +
|
||||
"'java.library.path' JVM property contains path to the library file [" + name +
|
||||
"]. Current library path property contents: " + System.getProperty(JAVA_LIBRARY_PATH_KEY));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of devices available via the API
|
||||
* @return list of device infos.
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public List<DeviceInfo> getDeviceInfos() throws SDRPlayException
|
||||
{
|
||||
return DeviceFactory.parseDeviceInfos(getDeviceStructures());
|
||||
}
|
||||
|
||||
/**
|
||||
* List of device structures for devices available from the API
|
||||
* @return list of device structures
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public List<IDeviceStruct> getDeviceStructures() throws SDRPlayException
|
||||
{
|
||||
List<IDeviceStruct> deviceStructs = new ArrayList<>();
|
||||
|
||||
//Get a version-correct array of DeviceT structures
|
||||
MemorySegment devicesArray = DeviceFactory.createDeviceArray(getVersion(), getGlobalMemorySession());
|
||||
|
||||
MemorySegment deviceCount = getGlobalMemorySession().allocate(ValueLayout.JAVA_INT, 0);
|
||||
|
||||
Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_GetDevices(devicesArray, deviceCount,
|
||||
sdrplay_api_h.SDRPLAY_MAX_DEVICES()));
|
||||
|
||||
if(status.success())
|
||||
{
|
||||
int count = deviceCount.get(ValueLayout.JAVA_INT, 0);
|
||||
deviceStructs.addAll(DeviceFactory.parseDeviceStructs(getVersion(), devicesArray, count));
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error("Couldn't load RSP devices from API. Status: " + status);
|
||||
}
|
||||
|
||||
return deviceStructs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find an RSP device descriptor by serial number.
|
||||
* @param serialNumber to search for
|
||||
* @return matching device descriptor, or null.
|
||||
* @throws SDRPlayException if there is an error parsing the device structures
|
||||
*/
|
||||
public DeviceInfo getDevice(String serialNumber) throws SDRPlayException
|
||||
{
|
||||
for(DeviceInfo deviceInfo: getDeviceInfos())
|
||||
{
|
||||
if(deviceInfo.getSerialNumber().equals(serialNumber))
|
||||
{
|
||||
return deviceInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the device that matches the device info argument.
|
||||
* @param deviceInfo to match
|
||||
* @return non-null device
|
||||
* @throws SDRPlayException
|
||||
*/
|
||||
public Device getDevice(DeviceInfo deviceInfo) throws SDRPlayException
|
||||
{
|
||||
Device device = null;
|
||||
|
||||
if(isAvailable())
|
||||
{
|
||||
List<IDeviceStruct> deviceStructs = getDeviceStructures();
|
||||
|
||||
for(IDeviceStruct deviceStruct: deviceStructs)
|
||||
{
|
||||
if(deviceInfo.matches(deviceStruct))
|
||||
{
|
||||
device = DeviceFactory.createDevice(this, deviceStruct);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(device == null)
|
||||
{
|
||||
throw new SDRPlayException("Unable to find RSP device");
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds the first device that matches the specified device type.
|
||||
*
|
||||
* @param deviceType to find
|
||||
* @return the specified device type or null.
|
||||
*/
|
||||
public DeviceInfo getDeviceInfo(DeviceType deviceType) throws SDRPlayException
|
||||
{
|
||||
for(DeviceInfo deviceInfo : getDeviceInfos())
|
||||
{
|
||||
if(deviceInfo.getDeviceType() == deviceType)
|
||||
{
|
||||
return deviceInfo;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the device for exclusive use. This method is invoked by the device instance.
|
||||
*
|
||||
* @param memorySegment of the device in foreign memory
|
||||
* @throws SDRPlayException if the device argument was not created by this API instance or if unable to lock or
|
||||
* unlock the device API for exclusive use, or if unable to select the device.
|
||||
*/
|
||||
public void select(MemorySegment memorySegment) throws SDRPlayException
|
||||
{
|
||||
lockDeviceApi();
|
||||
Status selectStatus = Status.fromValue(sdrplay_api_h.sdrplay_api_SelectDevice(memorySegment));
|
||||
unlockDeviceApi();
|
||||
|
||||
if(selectStatus.fail())
|
||||
{
|
||||
throw new SDRPlayException("Unable to select the device", selectStatus);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases the device from exclusive use. This method is invoked by the device instance.
|
||||
*
|
||||
* @param memorySegment of the device in foreign memory
|
||||
* @throws SDRPlayException if the device argument was not created by this API instance or if unable to release
|
||||
* the device
|
||||
*/
|
||||
public void release(MemorySegment memorySegment) throws SDRPlayException
|
||||
{
|
||||
Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_ReleaseDevice(memorySegment));
|
||||
|
||||
if(status.fail())
|
||||
{
|
||||
mLog.info("API call to release device failed, however device is effectively released now.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the initial composite parameters for each device. This should only be invoked once, on
|
||||
* startup, for each device. Changes made to the device parameters should invoke update() method to apply changes.
|
||||
*
|
||||
* @param deviceType to load parameters
|
||||
* @param deviceHandle to device
|
||||
* @return constructed device composite paramaters
|
||||
*/
|
||||
public CompositeParameters getCompositeParameters(DeviceType deviceType, MemoryAddress deviceHandle) throws SDRPlayException
|
||||
{
|
||||
//Allocate a pointer that the api will fill with the memory address of the device parameters in memory.
|
||||
MemorySegment pointer = getGlobalMemorySession().allocate(ValueLayout.ADDRESS);
|
||||
Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_GetDeviceParams(deviceHandle, pointer));
|
||||
|
||||
if(status.success())
|
||||
{
|
||||
//Get the memory address from the pointer's memory segment to where the structure is located
|
||||
MemoryAddress memoryAddress = pointer.get(ValueLayout.ADDRESS, 0);
|
||||
|
||||
//The structure's memory is already allocated ... wrap a memory segment around it
|
||||
MemorySegment memorySegment = sdrplay_api_DeviceT.ofAddress(memoryAddress, mGlobalMemorySession);
|
||||
return CompositeParametersFactory.create(deviceType, memorySegment, mGlobalMemorySession);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SDRPlayException("Error retrieving device composite parameters", status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a device for use.
|
||||
*
|
||||
* @param deviceHandle to the device
|
||||
* @param callbackFunctions to receive stream data from A and (optionally) B channels and events.
|
||||
* @throws SDRPlayException if the device is not selected of if unable to init the device
|
||||
*/
|
||||
private void init(MemoryAddress deviceHandle, MemorySegment callbackFunctions) throws SDRPlayException
|
||||
{
|
||||
//Since we don't need/use the callback context ... setup as a pointer to the callback functions
|
||||
MemorySegment contextPointer = getGlobalMemorySession().allocate(ValueLayout.ADDRESS, callbackFunctions);
|
||||
Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_Init(deviceHandle, callbackFunctions, contextPointer));
|
||||
|
||||
if(!status.success())
|
||||
{
|
||||
throw new SDRPlayException("Error while initializing device", status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a device for single-tuner use or for dual-tuner use as stream A
|
||||
*
|
||||
* @param device to initialize
|
||||
* @param deviceHandle to the device
|
||||
* @param eventListener to receive events for this device
|
||||
* @param streamListener to receive samples for stream A
|
||||
* @throws SDRPlayException if the device is not selected of if unable to init the device
|
||||
*/
|
||||
public void initA(Device device, MemoryAddress deviceHandle, IDeviceEventListener eventListener,
|
||||
IStreamListener streamListener) throws SDRPlayException
|
||||
{
|
||||
CallbackFunctions callbackFunctions = mDeviceCallbackFunctionsMap.get(deviceHandle);
|
||||
|
||||
if(callbackFunctions == null)
|
||||
{
|
||||
callbackFunctions = new CallbackFunctions(getGlobalMemorySession(), eventListener, streamListener,
|
||||
device.getStreamCallbackListener());
|
||||
mDeviceCallbackFunctionsMap.put(deviceHandle, callbackFunctions);
|
||||
}
|
||||
else
|
||||
{
|
||||
callbackFunctions.setDeviceEventListener(eventListener);
|
||||
callbackFunctions.setStreamAListener(streamListener);
|
||||
}
|
||||
|
||||
init(deviceHandle, callbackFunctions.getCallbackFunctionsMemorySegment());
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes a device for dual-tuner use as stream B
|
||||
*
|
||||
* @param device to initialize
|
||||
* @param deviceHandle to the device
|
||||
* @param eventListener to receive events for this device
|
||||
* @param streamListener to receive samples for stream B
|
||||
* @throws SDRPlayException if the device is not selected of if unable to init the device
|
||||
*/
|
||||
public void initB(Device device, MemoryAddress deviceHandle, IDeviceEventListener eventListener,
|
||||
IStreamListener streamListener) throws SDRPlayException
|
||||
{
|
||||
CallbackFunctions callbackFunctions = mDeviceCallbackFunctionsMap.get(deviceHandle);
|
||||
|
||||
if(callbackFunctions == null)
|
||||
{
|
||||
callbackFunctions = new CallbackFunctions(getGlobalMemorySession(), eventListener, streamListener, streamListener,
|
||||
device.getStreamCallbackListener());
|
||||
mDeviceCallbackFunctionsMap.put(deviceHandle, callbackFunctions);
|
||||
}
|
||||
else
|
||||
{
|
||||
callbackFunctions.setDeviceEventListener(eventListener);
|
||||
callbackFunctions.setStreamAListener(streamListener);
|
||||
}
|
||||
|
||||
init(deviceHandle, callbackFunctions.getCallbackFunctionsMemorySegment());
|
||||
}
|
||||
|
||||
/**
|
||||
* Un-Initializes a device from use.
|
||||
*
|
||||
* @param deviceHandle to the device
|
||||
* @throws SDRPlayException if error during uninit or if device is not selected
|
||||
*/
|
||||
public void uninit(MemoryAddress deviceHandle) throws SDRPlayException
|
||||
{
|
||||
Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_Uninit(deviceHandle));
|
||||
|
||||
if(status.fail() && status != Status.NOT_INITIALIZED)
|
||||
{
|
||||
throw new SDRPlayException("Error while un-initializing device", status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies updates made to the device parameters. The device parameter that was updated is specified in the
|
||||
* update reason.
|
||||
* <p>
|
||||
* Note: this method is synchronized to prevent multiple threads from attempting to send update requests
|
||||
* concurrently, which will cause a failed request.
|
||||
*
|
||||
* @param device to update
|
||||
* @param deviceHandle for the device
|
||||
* @param tunerSelect identifies which tuner to apply the updates
|
||||
* @param updateReasons identifying what was updated
|
||||
* @throws SDRPlayException if the device is not selected, or if unable to update the device parameters
|
||||
*/
|
||||
public synchronized void update(Device device, MemoryAddress deviceHandle, TunerSelect tunerSelect,
|
||||
UpdateReason... updateReasons) throws SDRPlayException
|
||||
{
|
||||
int reasons = UpdateReason.getReasons(updateReasons);
|
||||
int extendedReasons = UpdateReason.getExtendedReasons(updateReasons);
|
||||
|
||||
Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_Update(deviceHandle, tunerSelect.getValue(),
|
||||
reasons, extendedReasons));
|
||||
|
||||
if(status.fail())
|
||||
{
|
||||
throw new SDRPlayUpdateException(status, Arrays.stream(updateReasons).toList());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve error information for the last error for the specified device.
|
||||
*
|
||||
* @param deviceSegment for the device
|
||||
* @return error information
|
||||
*/
|
||||
private ErrorInformation getLastError(MemorySegment deviceSegment)
|
||||
{
|
||||
MemoryAddress errorAddress = sdrplay_api_h.sdrplay_api_GetLastError(deviceSegment);
|
||||
MemorySegment errorSegment = sdrplay_api_ErrorInfoT.ofAddress(errorAddress, mGlobalMemorySession);
|
||||
return new ErrorInformation(errorSegment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the debug level logging for the specified device
|
||||
*
|
||||
* @param deviceHandle for the device
|
||||
* @param debugLevel to set
|
||||
* @throws SDRPlayException if the device is not selected or if unable to set/change the debug level.
|
||||
*/
|
||||
public void setDebugLevel(MemoryAddress deviceHandle, DebugLevel debugLevel) throws SDRPlayException
|
||||
{
|
||||
Status status = Status.UNKNOWN;
|
||||
|
||||
if(getVersion() == Version.V3_07)
|
||||
{
|
||||
//V3.07 used a debug level argument
|
||||
status = Status.fromValue(sdrplay_api_h.sdrplay_api_DebugEnable(deviceHandle, debugLevel.getValue()));
|
||||
}
|
||||
else if(getVersion().gte(Version.V3_08))
|
||||
{
|
||||
//V3.08+ uses a 0:1 flag to enable debug logging. The method signature didn't change -- still takes an integer
|
||||
boolean enable = debugLevel != DebugLevel.DISABLE;
|
||||
status = Status.fromValue(sdrplay_api_h.sdrplay_api_DebugEnable(deviceHandle, Flag.of(enable)));
|
||||
}
|
||||
|
||||
if(status.fail())
|
||||
{
|
||||
throw new SDRPlayException("Unable to set debug level", status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the SDRplay API is available and that the API library has been located and loaded for use and
|
||||
* it the API version is supported by this jsdrplay library.
|
||||
*/
|
||||
public boolean isAvailable()
|
||||
{
|
||||
return mAvailable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the API service. MUST be invoked before accessing any of the API functions/methods.
|
||||
*/
|
||||
private Status open()
|
||||
{
|
||||
return Status.fromValue(sdrplay_api_h.sdrplay_api_Open());
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes the API service. MUST be invoked before shutdown, after all SDRPlay API operations are completed.
|
||||
*
|
||||
* Note: when using multiple instances of this class, only invoke close() on a single instance. With linux API
|
||||
* version 3.07, if you invoked close() on one instance, then all of the other instances become unusable for
|
||||
* performing device operations (e.g. release(), etc). This may be an artifact of the way that the Java
|
||||
* Foreign Function support is implemented, but not sure. dls 1-Jan-2023
|
||||
*/
|
||||
public Status close()
|
||||
{
|
||||
if(mSdrplayLibraryLoaded)
|
||||
{
|
||||
Status closeStatus;
|
||||
|
||||
try
|
||||
{
|
||||
closeStatus = Status.fromValue(sdrplay_api_h.sdrplay_api_Close());
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
closeStatus = Status.FAIL;
|
||||
mLog.error("Error closing SDRPlay API");
|
||||
}
|
||||
|
||||
mSdrplayLibraryLoaded = false;
|
||||
mAvailable = false;
|
||||
return closeStatus;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Status.API_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies the API version.
|
||||
* Note: if the library is not found or loaded, or if the API version is not a supported version, this method
|
||||
* returns UNKNOWN
|
||||
*
|
||||
* @return version.
|
||||
*/
|
||||
public Version getVersion()
|
||||
{
|
||||
if(mVersion == null)
|
||||
{
|
||||
if(mSdrplayLibraryLoaded)
|
||||
{
|
||||
MemorySegment apiVersion = getGlobalMemorySession().allocate(ValueLayout.JAVA_FLOAT, 0);
|
||||
Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_ApiVersion(apiVersion));
|
||||
if(status.success())
|
||||
{
|
||||
float version = apiVersion.get(ValueLayout.JAVA_FLOAT, 0);
|
||||
mVersion = Version.fromValue(version);
|
||||
}
|
||||
}
|
||||
|
||||
if(mVersion == null)
|
||||
{
|
||||
mVersion = Version.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
return mVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to lock the API for exclusive use of the current application. Once locked, no other applications
|
||||
* will be able to use the API. Typically used to lock the API prior to calling sdrplay_api_GetDevices() to
|
||||
* ensure only one application can select a given device. After completing device selection using
|
||||
* sdrplay_api_SelectDevice(), sdrplay_api_UnlockDeviceApi() can be used to release the API. May also
|
||||
* be used prior to calling sdrplay_api_ReleaseDevice() if it is necessary to reselect the same device.
|
||||
*/
|
||||
private void lockDeviceApi() throws SDRPlayException
|
||||
{
|
||||
if(isAvailable())
|
||||
{
|
||||
Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_LockDeviceApi());
|
||||
if(status.fail())
|
||||
{
|
||||
throw new SDRPlayException("Unable to lock Device API for exclusive use", status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SDRPlayException("API is unavailable", Status.API_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlocks the device from exclusive access.
|
||||
*
|
||||
* @throws SDRPlayException if unable to unlock the Device API
|
||||
*/
|
||||
private void unlockDeviceApi() throws SDRPlayException
|
||||
{
|
||||
if(isAvailable())
|
||||
{
|
||||
Status status = Status.fromValue(sdrplay_api_h.sdrplay_api_UnlockDeviceApi());
|
||||
|
||||
if(status.fail())
|
||||
{
|
||||
throw new SDRPlayException("Unable to unlock Device API", status);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SDRPlayException("API is unavailable", Status.API_UNAVAILABLE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies the java library path for the sdrplay api library at runtime.
|
||||
*/
|
||||
public static String getSDRplayLibraryPath()
|
||||
{
|
||||
if(SystemUtils.IS_OS_WINDOWS)
|
||||
{
|
||||
return SDRPLAY_API_PATH_WINDOWS;
|
||||
}
|
||||
else if(SystemUtils.IS_OS_LINUX)
|
||||
{
|
||||
return SDRPLAY_API_PATH_LINUX_AND_OSX;
|
||||
}
|
||||
else if(SystemUtils.IS_OS_MAC_OSX)
|
||||
{
|
||||
return SDRPLAY_API_PATH_LINUX_AND_OSX;
|
||||
}
|
||||
|
||||
mLog.error("Unrecognized operating system. Cannot identify sdrplay api library path");
|
||||
return "";
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
/**
|
||||
* Note: on windows, add the following environment variable to the IntelliJ launcher:
|
||||
* -Djava.library.path="C:\Program Files\SDRplay\API\x64"
|
||||
*
|
||||
* Alternately, we can add this location to the Windows PATH environment variable and
|
||||
* Java will look there for the library, without having to specify it as a launcher
|
||||
* option. This would allow for users that have installed the API to an alternate location.
|
||||
*/
|
||||
SDRplay sdrplay = new SDRplay();
|
||||
Status status = sdrplay.open();
|
||||
mLog.info("Open Status: " + status);
|
||||
|
||||
try
|
||||
{
|
||||
for(DeviceInfo deviceInfo: sdrplay.getDeviceInfos())
|
||||
{
|
||||
mLog.info("Found: " + deviceInfo);
|
||||
}
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
mLog.info("Error", se);
|
||||
}
|
||||
|
||||
Status closeStatus = sdrplay.close();
|
||||
mLog.info("Close Status: " + closeStatus);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_h;
|
||||
|
||||
public enum Status
|
||||
{
|
||||
SUCCESS(sdrplay_api_h.sdrplay_api_Success(), "Success"),
|
||||
FAIL(sdrplay_api_h.sdrplay_api_Fail(), "Fail"),
|
||||
INVALID_PARAMETER(sdrplay_api_h.sdrplay_api_InvalidParam(), "Invalid Parameter. Null pointer or invalid operating mode"),
|
||||
OUT_OF_RANGE(sdrplay_api_h.sdrplay_api_OutOfRange(), "Out of Range. One or more parameters are set incorrectly"),
|
||||
GAIN_UPDATE_ERROR(sdrplay_api_h.sdrplay_api_GainUpdateError(), "Gain Update Error"),
|
||||
RF_UPDATE_ERROR(sdrplay_api_h.sdrplay_api_RfUpdateError(), "Frequency Update Error"),
|
||||
FS_UPDATE_ERROR(sdrplay_api_h.sdrplay_api_FsUpdateError(), "Sample Rate Update Error"),
|
||||
HARDWARE_ERROR(sdrplay_api_h.sdrplay_api_HwError(), "Hardware Error during tuner initialization"),
|
||||
ALIASING_ERROR(sdrplay_api_h.sdrplay_api_AliasingError(), "Aliasing Error"),
|
||||
ALREADY_INITIALIZED(sdrplay_api_h.sdrplay_api_AlreadyInitialised(), "Already Initialized"),
|
||||
NOT_INITIALIZED(sdrplay_api_h.sdrplay_api_NotInitialised(), "Not Initialized"),
|
||||
NOT_ENABLED(sdrplay_api_h.sdrplay_api_NotEnabled(), "Not Enabled"),
|
||||
HARDWARE_VERSION_ERROR(sdrplay_api_h.sdrplay_api_HwVerError(), "Hardware Version Error"),
|
||||
OUT_OF_MEMORY(sdrplay_api_h.sdrplay_api_OutOfMemError(), "Out Of Memory"),
|
||||
SERVICE_NOT_RESPONDING(sdrplay_api_h.sdrplay_api_ServiceNotResponding(), "Service Not Responding"),
|
||||
START_PENDING(sdrplay_api_h.sdrplay_api_StartPending(), "Start Pending"),
|
||||
STOP_PENDING(sdrplay_api_h.sdrplay_api_StopPending(), "Stop Pending"),
|
||||
INVALID_MODE(sdrplay_api_h.sdrplay_api_InvalidMode(), "Invalid Mode"),
|
||||
FAILED_VERIFICATION_1(sdrplay_api_h.sdrplay_api_FailedVerification1(), "Failed Verification 1"),
|
||||
FAILED_VERIFICATION_2(sdrplay_api_h.sdrplay_api_FailedVerification2(), "Failed Verification 2"),
|
||||
FAILED_VERIFICATION_3(sdrplay_api_h.sdrplay_api_FailedVerification3(), "Failed Verification 3"),
|
||||
FAILED_VERIFICATION_4(sdrplay_api_h.sdrplay_api_FailedVerification4(), "Failed Verification 4"),
|
||||
FAILED_VERIFICATION_5(sdrplay_api_h.sdrplay_api_FailedVerification5(), "Failed Verification 5"),
|
||||
FAILED_VERIFICATION_6(sdrplay_api_h.sdrplay_api_FailedVerification6(), "Failed Verification 6"),
|
||||
INVALID_SERVICE_VERSION(sdrplay_api_h.sdrplay_api_InvalidServiceVersion(), "Invalid Service Version"),
|
||||
|
||||
//Custom status codes
|
||||
API_UNAVAILABLE(-2, "SDRplay API is not installed or it has an unsupported version"),
|
||||
UNKNOWN(-1, "Unknown");
|
||||
|
||||
private int mValue;
|
||||
private String mDescription;
|
||||
|
||||
Status(int value, String description)
|
||||
{
|
||||
mValue = value;
|
||||
mDescription = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Status code value
|
||||
*/
|
||||
public int getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is a SUCCESS status.
|
||||
*/
|
||||
public boolean success()
|
||||
{
|
||||
return this == Status.SUCCESS;
|
||||
}
|
||||
|
||||
public boolean fail()
|
||||
{
|
||||
return this != Status.SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the status from a return code
|
||||
* @param value to lookup
|
||||
* @return status or UKNOWN if the code is not recognized
|
||||
*/
|
||||
public static Status fromValue(int value)
|
||||
{
|
||||
for(Status status: Status.values())
|
||||
{
|
||||
if(status.getValue() == value)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_h;
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* Update reason.
|
||||
*
|
||||
* These entries are used to notify the SDRplay API once settings are updated on the device.
|
||||
*/
|
||||
public enum UpdateReason
|
||||
{
|
||||
//Master Only mode
|
||||
DEVICE_SAMPLE_RATE(sdrplay_api_h.sdrplay_api_Update_Dev_Fs(), "Sample Rate"),
|
||||
DEVICE_PPM(sdrplay_api_h.sdrplay_api_Update_Dev_Ppm(), "PPM"),
|
||||
DEVICE_SYNC_UPDATE(sdrplay_api_h.sdrplay_api_Update_Dev_SyncUpdate(), "Sync Update"),
|
||||
DEVICE_RESET_FLAGS(sdrplay_api_h.sdrplay_api_Update_Dev_ResetFlags(), "Reset Flags"),
|
||||
|
||||
RSP1A_BIAS_T_CONTROL(sdrplay_api_h.sdrplay_api_Update_Rsp1a_BiasTControl(), "RSP1A Bias-T Control"),
|
||||
RSP1A_RF_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_Rsp1a_RfNotchControl(), "RSP1A RF Notch Control"),
|
||||
RSP1A_RF_DAB_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_Rsp1a_RfDabNotchControl(), "RSP1A RF DAB Notch Control"),
|
||||
|
||||
RSP2_BIAS_T_CONTROL(sdrplay_api_h.sdrplay_api_Update_Rsp2_BiasTControl(), "RSP2 Bias-T Control"),
|
||||
RSP2_AM_PORT_SELECT(sdrplay_api_h.sdrplay_api_Update_Rsp2_AmPortSelect(), "RSP2 AM Port Select"),
|
||||
RSP2_ANTENNA_CONTROL(sdrplay_api_h.sdrplay_api_Update_Rsp2_AntennaControl(), "RSP2 Antenna Control"),
|
||||
RSP2_RF_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_Rsp2_RfNotchControl(), "RSP2 RF Notch Control"),
|
||||
RSP2_EXT_REF_CONTROL(sdrplay_api_h.sdrplay_api_Update_Rsp2_ExtRefControl(), "RSP2 External Reference Control"),
|
||||
|
||||
RSP_DUO_EXT_REF_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDuo_ExtRefControl(), "RSPduo External Reference Control"),
|
||||
|
||||
SPARE_1(sdrplay_api_h.sdrplay_api_Update_Master_Spare_1(), "Spare 1"),
|
||||
SPARE_2(sdrplay_api_h.sdrplay_api_Update_Master_Spare_2(), "Spare 2"),
|
||||
|
||||
//Master and Slave mode
|
||||
TUNER_GAIN_REDUCTION(sdrplay_api_h.sdrplay_api_Update_Tuner_Gr(), "Tuner Gain Reduction"),
|
||||
TUNER_GAIN_REDUCTION_LIMITS(sdrplay_api_h.sdrplay_api_Update_Tuner_GrLimits(), "Tuner Gain Reduction Limits"),
|
||||
TUNER_FREQUENCY_RF(sdrplay_api_h.sdrplay_api_Update_Tuner_Frf(), "Tuner Frequency RF"),
|
||||
TUNER_BANDWIDTH_TYPE(sdrplay_api_h.sdrplay_api_Update_Tuner_BwType(), "Tuner Bandwidth Type"),
|
||||
TUNER_IF_TYPE(sdrplay_api_h.sdrplay_api_Update_Tuner_IfType(), "Tuner IF Type"),
|
||||
TUNER_DC_OFFSET(sdrplay_api_h.sdrplay_api_Update_Tuner_DcOffset(), "Tuner DC Offset"),
|
||||
TUNER_LO_MODE(sdrplay_api_h.sdrplay_api_Update_Tuner_LoMode(), "Tuner LO Mode"),
|
||||
|
||||
CONTROL_DC_OFFSET_IQ_IMBALANCE(sdrplay_api_h.sdrplay_api_Update_Ctrl_DCoffsetIQimbalance(), "Control DC Offset IQ Imbalance"),
|
||||
CONTROL_DECIMATION(sdrplay_api_h.sdrplay_api_Update_Ctrl_Decimation(), "Control Decimation"),
|
||||
CONTROL_AGC(sdrplay_api_h.sdrplay_api_Update_Ctrl_Agc(), "Control AGC"),
|
||||
CONTROL_ADSB_MODE(sdrplay_api_h.sdrplay_api_Update_Ctrl_AdsbMode(), "Control ADSB Mode"),
|
||||
CONTROL_OVERLOAD_MESSAGE_ACK(sdrplay_api_h.sdrplay_api_Update_Ctrl_OverloadMsgAck(), "Control Overload Message Ack"),
|
||||
|
||||
RSP_DUO_BIAS_T_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDuo_BiasTControl(), "RSPduo Bias-T Control"),
|
||||
RSP_DUO_AM_PORT_SELECT(sdrplay_api_h.sdrplay_api_Update_RspDuo_AmPortSelect(), "RSPduo AM Port Select"),
|
||||
RSP_DUO_TUNER_1_AM_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDuo_Tuner1AmNotchControl(), "RSPduo Tuner 1 AM Notch Control"),
|
||||
RSP_DUO_RF_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDuo_RfNotchControl(), "RSPduo RF Notch Control"),
|
||||
RSP_DUO_RF_DAB_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDuo_RfDabNotchControl(), "RSPduo RF DAB Notch Control"),
|
||||
|
||||
//Extension 1
|
||||
EXTENSION_RSP_DX_HDR_ENABLE(sdrplay_api_h.sdrplay_api_Update_RspDx_HdrEnable(), "RSPdx HDR Enable"),
|
||||
EXTENSION_RSP_DX_BIAS_T_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDx_BiasTControl(), "RSPdx Bias-T Control"),
|
||||
EXTENSION_RSP_DX_ANTENNA_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDx_AntennaControl(), "RSPdx Antenna Control"),
|
||||
EXTENSION_RSP_DX_RF_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDx_RfNotchControl(), "RSPdx RF Notch Control"),
|
||||
EXTENSION_RSP_DX_RF_DAB_NOTCH_CONTROL(sdrplay_api_h.sdrplay_api_Update_RspDx_RfDabNotchControl(), "RSPdx RF DAB Notch Control"),
|
||||
EXTENSION_RSP_DX_HDR_BANDWIDTH(sdrplay_api_h.sdrplay_api_Update_RspDx_HdrBw(), "RSPdx HDR Bandwidth"),
|
||||
EXTENSION_NONE(sdrplay_api_h.sdrplay_api_Update_Ext1_None(), "NONE"),
|
||||
|
||||
|
||||
NONE(sdrplay_api_h.sdrplay_api_Update_None(), "NONE");
|
||||
|
||||
private int mValue;
|
||||
private String mDescription;
|
||||
|
||||
UpdateReason(int value, String description)
|
||||
{
|
||||
mValue = value;
|
||||
mDescription = description;
|
||||
}
|
||||
|
||||
public static EnumSet<UpdateReason> EXTENSIONS = EnumSet.range(EXTENSION_RSP_DX_HDR_ENABLE, EXTENSION_NONE);
|
||||
|
||||
|
||||
/**
|
||||
* Many of the update reasons described in this enumeration are submitted asynchronously, since the API is
|
||||
* non-blocking. However, the device event listener responses are limited to just three events: Frequency, Gain,
|
||||
* and Sample Rate. This constant describes the three update reasons that correspond to the device events.
|
||||
*/
|
||||
public static EnumSet<UpdateReason> ASYNC_UPDATE_RESPONSES = EnumSet.of(DEVICE_SAMPLE_RATE, TUNER_FREQUENCY_RF, TUNER_GAIN_REDUCTION);
|
||||
|
||||
/**
|
||||
* Numeric value
|
||||
*/
|
||||
public int getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is an extended update reason entry.
|
||||
*/
|
||||
public boolean isExtended()
|
||||
{
|
||||
return EXTENSIONS.contains(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this update reason is one of the limited set of asynchronous update operation response types.
|
||||
*/
|
||||
public boolean isAsyncUpdateResponse()
|
||||
{
|
||||
return ASYNC_UPDATE_RESPONSES.contains(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the entry from a return code
|
||||
* @param value to lookup
|
||||
* @return entry or UNKNOWN if the code is not recognized
|
||||
*/
|
||||
public static UpdateReason fromValue(int value)
|
||||
{
|
||||
for(UpdateReason status: UpdateReason.values())
|
||||
{
|
||||
if(status.getValue() == value)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a combined logical OR value of the non-extended update reasons. Extended reason values will
|
||||
* be ignored for this calculation.
|
||||
*
|
||||
* @param reasons to combine
|
||||
* @return combined (logical OR) value.
|
||||
*/
|
||||
public static int getReasons(UpdateReason ... reasons)
|
||||
{
|
||||
int combined = UpdateReason.NONE.getValue();
|
||||
|
||||
for(UpdateReason reason: reasons)
|
||||
{
|
||||
if(!reason.isExtended())
|
||||
{
|
||||
combined += reason.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a combined logical OR value of the extended update reasons. Non-extended reason values will
|
||||
* be ignored for this calculation.
|
||||
*
|
||||
* @param reasons to combine
|
||||
* @return combined (logical OR) value.
|
||||
*/
|
||||
public static int getExtendedReasons(UpdateReason ... reasons)
|
||||
{
|
||||
int combined = UpdateReason.EXTENSION_NONE.getValue();
|
||||
|
||||
for(UpdateReason reason: reasons)
|
||||
{
|
||||
if(reason.isExtended())
|
||||
{
|
||||
combined += reason.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* SDRPlay API Versions
|
||||
*/
|
||||
public enum Version
|
||||
{
|
||||
UNKNOWN(0.0f, false),
|
||||
V3_07(3.07f, true),
|
||||
V3_08(3.08f, true),
|
||||
V3_09(3.09f, true),
|
||||
V3_10(3.10f, true),
|
||||
V3_11(3.11f, true);
|
||||
|
||||
private float mValue;
|
||||
private boolean mSupported;
|
||||
private static final Logger mLog = LoggerFactory.getLogger(Version.class);
|
||||
|
||||
Version(float value, boolean supported)
|
||||
{
|
||||
mValue = value;
|
||||
mSupported = supported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the API version is supported by the jsdrplay library
|
||||
*/
|
||||
public boolean isSupported()
|
||||
{
|
||||
return mSupported;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this version is greater than or equal to the specified version.
|
||||
* @param version to compare
|
||||
* @return true if this version is greater than or equal to
|
||||
*/
|
||||
public boolean gte(Version version)
|
||||
{
|
||||
return this.ordinal() >= version.ordinal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Numeric API version/value
|
||||
*/
|
||||
public float getVersion()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the version from the specified value.
|
||||
* @param value to lookup
|
||||
* @return version or UNKNOWN
|
||||
*/
|
||||
public static Version fromValue(float value)
|
||||
{
|
||||
|
||||
for(Version version: values())
|
||||
{
|
||||
if(version.mValue == value)
|
||||
{
|
||||
return version;
|
||||
}
|
||||
}
|
||||
|
||||
mLog.warn("Unrecognized SDRplay API version [" + value + "]");
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.valueOf(mValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.async;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
/**
|
||||
* Asynchronous operation that implements the Future interface with utility methods for callback on completion, or
|
||||
* converting to a synchronous (ie blocking) operation.
|
||||
* @param <R> expected return type upon completion of the operation
|
||||
*/
|
||||
public class AsyncFuture<R> implements Future<R>
|
||||
{
|
||||
private R mResult;
|
||||
private Throwable mError;
|
||||
private boolean mCancelled;
|
||||
private boolean mCompleted = false;
|
||||
private ReentrantLock mLock = new ReentrantLock();
|
||||
private IAsyncCallback mCallback;
|
||||
|
||||
/**
|
||||
* Sets the result and completes this future.
|
||||
* @param result to apply.
|
||||
*/
|
||||
public synchronized void setResult(R result)
|
||||
{
|
||||
if(mCompleted)
|
||||
{
|
||||
throw new IllegalStateException("Future is already completed.");
|
||||
}
|
||||
|
||||
mResult = result;
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an error resulting from the operation and completes this future.
|
||||
* @param error produced from the operation
|
||||
*/
|
||||
public synchronized void setError(Throwable error)
|
||||
{
|
||||
if(mCompleted)
|
||||
{
|
||||
throw new IllegalStateException("Future is already completed.");
|
||||
}
|
||||
|
||||
mError = error;
|
||||
finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* (Optional) error produced from the operation.
|
||||
*/
|
||||
public Throwable getError()
|
||||
{
|
||||
return mError;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this future had an error during the operation
|
||||
*/
|
||||
public boolean hasError()
|
||||
{
|
||||
return mError != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup task that completes the future and notifies an optional registered callback.
|
||||
*/
|
||||
private void finish()
|
||||
{
|
||||
mLock.lock();
|
||||
|
||||
try
|
||||
{
|
||||
mCompleted = true;
|
||||
|
||||
if(mCallback != null)
|
||||
{
|
||||
mCallback.complete(this);
|
||||
mCallback = null;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
mLock.unlock();
|
||||
}
|
||||
|
||||
notifyAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Signals a desire to cancel this future operation.
|
||||
*
|
||||
* Note: it is up to the implementer to monitor this cancel state.
|
||||
* @param mayInterruptIfRunning not implemented.
|
||||
* @return true always.
|
||||
*/
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning)
|
||||
{
|
||||
mCancelled = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this future has been cancelled.
|
||||
*/
|
||||
@Override
|
||||
public boolean isCancelled()
|
||||
{
|
||||
return mCancelled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this future has completed.
|
||||
*/
|
||||
@Override
|
||||
public boolean isDone()
|
||||
{
|
||||
return mCompleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocking call to wait indefinitely for the result of the operation.
|
||||
* @return result of the operation
|
||||
* @throws InterruptedException if the calling thread is interrupted while waiting
|
||||
* @throws ExecutionException if there is an error produced from the operation
|
||||
*/
|
||||
@Override
|
||||
public synchronized R get() throws InterruptedException, ExecutionException
|
||||
{
|
||||
while(!mCompleted)
|
||||
{
|
||||
wait();
|
||||
}
|
||||
|
||||
if(mError != null)
|
||||
{
|
||||
throw new ExecutionException(mError);
|
||||
}
|
||||
|
||||
return mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocking call to synchronously get the result of the operation.
|
||||
* @param timeout to wait
|
||||
* @param unit for the timeout
|
||||
* @return result once completed
|
||||
* @throws InterruptedException if the calling thread is interrupted while waiting
|
||||
* @throws ExecutionException if there is an error produced from the operation
|
||||
* @throws TimeoutException if the timeout is exceeded while waiting.
|
||||
*/
|
||||
@Override
|
||||
public synchronized R get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
|
||||
{
|
||||
if(!mCompleted)
|
||||
{
|
||||
wait(unit.toMillis(timeout));
|
||||
}
|
||||
|
||||
if(!mCompleted)
|
||||
{
|
||||
throw new TimeoutException("Get timeout [" + timeout + " " + unit + "] exceeded without completion");
|
||||
}
|
||||
|
||||
if(mError != null)
|
||||
{
|
||||
throw new ExecutionException(mError);
|
||||
}
|
||||
|
||||
return mResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the callback to receive the result once the operation completes. If the operation is completed, the
|
||||
* callback is immediately notified, otherwise the callback will be notified later.
|
||||
* @param callback to be notified once the operation is completed.
|
||||
*/
|
||||
public synchronized void callback(IAsyncCallback callback)
|
||||
{
|
||||
if(mCallback != null)
|
||||
{
|
||||
throw new IllegalArgumentException("Callback has been registered - only one callback is supported.");
|
||||
}
|
||||
|
||||
mLock.lock();
|
||||
|
||||
try
|
||||
{
|
||||
if(mCompleted)
|
||||
{
|
||||
callback.complete(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
mCallback = callback;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
mLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.async;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.Status;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.UpdateReason;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
|
||||
|
||||
/**
|
||||
* Asynchronous future for an SDRplay API update operation.
|
||||
*/
|
||||
public class AsyncUpdateFuture extends AsyncFuture<Status>
|
||||
{
|
||||
private TunerSelect mTunerSelect;
|
||||
private UpdateReason mUpdateReason;
|
||||
private UpdateReason mExpectedResponse;
|
||||
private boolean mSubmitted;
|
||||
|
||||
/**
|
||||
* Creates a to-be completed future where a successful update with return success or an unsuccessful update will
|
||||
* return an exception.
|
||||
* @param tunerSelect for the tuner to be updated
|
||||
* @param updateReason of what is to be updated
|
||||
* @param expectedResponse to be received to indicate the async operation is completed
|
||||
*/
|
||||
public AsyncUpdateFuture(TunerSelect tunerSelect, UpdateReason updateReason, UpdateReason expectedResponse)
|
||||
{
|
||||
mTunerSelect = tunerSelect;
|
||||
mUpdateReason = updateReason;
|
||||
mExpectedResponse = expectedResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tuner(s) for the update
|
||||
*/
|
||||
public TunerSelect getTunerSelect()
|
||||
{
|
||||
return mTunerSelect;
|
||||
}
|
||||
|
||||
/**
|
||||
* UpdateReason that is being updated
|
||||
*/
|
||||
public UpdateReason getUpdateReason()
|
||||
{
|
||||
return mUpdateReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expected response to this update operation
|
||||
*/
|
||||
public UpdateReason getExpectedResponse()
|
||||
{
|
||||
return mExpectedResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flag to indicate if this update has been submitted and is currently awaiting results.
|
||||
*/
|
||||
public boolean isSubmitted()
|
||||
{
|
||||
return mSubmitted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets flag to indicate that this update has been submitted.
|
||||
*/
|
||||
public void setSubmitted(boolean submitted)
|
||||
{
|
||||
mSubmitted = submitted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the completed async operation matches this submitted async update future
|
||||
* @param completedAsyncUpdate to compare
|
||||
* @return true if there is a match
|
||||
*/
|
||||
public boolean matches(CompletedAsyncUpdate completedAsyncUpdate)
|
||||
{
|
||||
return getTunerSelect().equals(completedAsyncUpdate.getTunerSelect()) &&
|
||||
getExpectedResponse().equals(completedAsyncUpdate.getUpdateReason());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.async;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.UpdateReason;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
|
||||
|
||||
/**
|
||||
* Completed asynchronous update operation
|
||||
*/
|
||||
public class CompletedAsyncUpdate
|
||||
{
|
||||
private TunerSelect mTunerSelect;
|
||||
private UpdateReason mUpdateReason;
|
||||
|
||||
/**
|
||||
* Creates a completed update.
|
||||
*/
|
||||
public CompletedAsyncUpdate(TunerSelect tunerSelect, UpdateReason updateReason)
|
||||
{
|
||||
mTunerSelect = tunerSelect;
|
||||
mUpdateReason = updateReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tuner(s) for the update
|
||||
*/
|
||||
public TunerSelect getTunerSelect()
|
||||
{
|
||||
return mTunerSelect;
|
||||
}
|
||||
|
||||
/**
|
||||
* UpdateReason that is being updated
|
||||
*/
|
||||
public UpdateReason getUpdateReason()
|
||||
{
|
||||
return mUpdateReason;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.async;
|
||||
|
||||
/**
|
||||
* Callback interface to be notified when an async future has completed or has resulted in an error
|
||||
*/
|
||||
public interface IAsyncCallback
|
||||
{
|
||||
/**
|
||||
* Callback method once the future is completed or produces an error.
|
||||
* @param future that is being monitored
|
||||
*/
|
||||
void complete(AsyncFuture future);
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.callback;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_CallbackFnsT;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_EventCallback_t;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_StreamCallback_t;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.foreign.MemorySession;
|
||||
|
||||
/**
|
||||
* Callback functions (sdrplay_api_CallbackFnsT) factory
|
||||
*/
|
||||
public class CallbackFunctions
|
||||
{
|
||||
private DeviceEventAdapter mDeviceEventAdapter;
|
||||
private StreamCallbackAdapter mStreamACallbackAdapter;
|
||||
private StreamCallbackAdapter mStreamBCallbackAdapter;
|
||||
private MemorySegment mCallbackFunctionsMemorySegment;
|
||||
|
||||
/**
|
||||
* Constructs a callback functions for single-tuner use.
|
||||
* @param memorySession for native memory allocation
|
||||
* @param deviceEventListener for device events
|
||||
* @param streamListener for streaming samples
|
||||
* @param streamCallbackListener for streaming events
|
||||
*/
|
||||
public CallbackFunctions(MemorySession memorySession, IDeviceEventListener deviceEventListener,
|
||||
IStreamListener streamListener, IStreamCallbackListener streamCallbackListener)
|
||||
{
|
||||
//Create the event callback function
|
||||
mDeviceEventAdapter = new DeviceEventAdapter(memorySession, deviceEventListener);
|
||||
MemorySegment eventFunction = sdrplay_api_EventCallback_t.allocate(mDeviceEventAdapter, memorySession);
|
||||
|
||||
//Create the stream A callback function
|
||||
mStreamACallbackAdapter = new StreamCallbackAdapter(memorySession, streamListener, streamCallbackListener);
|
||||
MemorySegment streamAFunction = sdrplay_api_StreamCallback_t.allocate(mStreamACallbackAdapter, memorySession);
|
||||
|
||||
//Create the callback functions union and populate the callback functions
|
||||
mCallbackFunctionsMemorySegment = sdrplay_api_CallbackFnsT.allocate(memorySession);
|
||||
sdrplay_api_CallbackFnsT.EventCbFn$set(mCallbackFunctionsMemorySegment, eventFunction.address());
|
||||
sdrplay_api_CallbackFnsT.StreamACbFn$set(mCallbackFunctionsMemorySegment, streamAFunction.address());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a callback functions for dual-tuner use.
|
||||
* @param memorySession for native memory allocation
|
||||
* @param deviceEventListener for device events
|
||||
* @param streamAListener for streaming samples from the master tuner
|
||||
* @param streamBListener for streaming samples from the slave tuner
|
||||
* @param streamCallbackListener for streaming events
|
||||
*/
|
||||
public CallbackFunctions(MemorySession memorySession, IDeviceEventListener deviceEventListener,
|
||||
IStreamListener streamAListener, IStreamListener streamBListener,
|
||||
IStreamCallbackListener streamCallbackListener)
|
||||
{
|
||||
//Create the event callback function
|
||||
mDeviceEventAdapter = new DeviceEventAdapter(memorySession, deviceEventListener);
|
||||
MemorySegment eventFunction = sdrplay_api_EventCallback_t.allocate(mDeviceEventAdapter, memorySession);
|
||||
|
||||
//Create the stream A callback function
|
||||
mStreamACallbackAdapter = new StreamCallbackAdapter(memorySession, streamAListener, streamCallbackListener);
|
||||
MemorySegment streamAFunction = sdrplay_api_StreamCallback_t.allocate(mStreamACallbackAdapter, memorySession);
|
||||
|
||||
//Create the stream B callback function
|
||||
mStreamBCallbackAdapter = new StreamCallbackAdapter(memorySession, streamBListener, streamCallbackListener);
|
||||
MemorySegment streamBFunction = sdrplay_api_StreamCallback_t.allocate(mStreamBCallbackAdapter, memorySession);
|
||||
|
||||
//Create the callback functions union and populate the callback functions
|
||||
mCallbackFunctionsMemorySegment = sdrplay_api_CallbackFnsT.allocate(memorySession);
|
||||
sdrplay_api_CallbackFnsT.EventCbFn$set(mCallbackFunctionsMemorySegment, eventFunction.address());
|
||||
sdrplay_api_CallbackFnsT.StreamACbFn$set(mCallbackFunctionsMemorySegment, streamAFunction.address());
|
||||
sdrplay_api_CallbackFnsT.StreamBCbFn$set(mCallbackFunctionsMemorySegment, streamBFunction.address());
|
||||
}
|
||||
|
||||
/**
|
||||
* Foreign memory segment for the callback functions.
|
||||
*/
|
||||
public MemorySegment getCallbackFunctionsMemorySegment()
|
||||
{
|
||||
return mCallbackFunctionsMemorySegment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the device event listener
|
||||
* @param listener to receive device events
|
||||
*/
|
||||
public void setDeviceEventListener(IDeviceEventListener listener)
|
||||
{
|
||||
mDeviceEventAdapter.setListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the stream A listener
|
||||
* @param listener to receive samples for stream A
|
||||
*/
|
||||
public void setStreamAListener(IStreamListener listener)
|
||||
{
|
||||
mStreamACallbackAdapter.setListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the stream B listener
|
||||
* @param listener to receive samples for stream B
|
||||
*/
|
||||
public void setStreamBListener(IStreamListener listener)
|
||||
{
|
||||
mStreamBCallbackAdapter.setListener(listener);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.callback;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.event.EventParametersFactory;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.event.EventType;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_EventCallback_t;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_EventParamsT;
|
||||
import java.lang.foreign.MemoryAddress;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.foreign.MemorySession;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Adapter for Device Event callbacks. Implements foreign interface and transfers foreign memory event details to
|
||||
* native Java and invokes the appropriate interface methods for an event listener.
|
||||
*/
|
||||
public class DeviceEventAdapter implements sdrplay_api_EventCallback_t
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(DeviceEventAdapter.class);
|
||||
|
||||
private MemorySession mMemorySession;
|
||||
private IDeviceEventListener mDeviceEventListener;
|
||||
|
||||
/**
|
||||
* Constructs an instance.
|
||||
* @param memorySession to use in creating foreign memory segments to access foreign structures.
|
||||
* @param listener to receive translated device events.
|
||||
*/
|
||||
public DeviceEventAdapter(MemorySession memorySession, IDeviceEventListener listener)
|
||||
{
|
||||
if(memorySession == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Resource scope must be non-null");
|
||||
}
|
||||
|
||||
mMemorySession = memorySession;
|
||||
|
||||
setListener(listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the device event listener
|
||||
* @param listener to receive device events
|
||||
*/
|
||||
public void setListener(IDeviceEventListener listener)
|
||||
{
|
||||
if(listener == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Device event listener must be non-null");
|
||||
}
|
||||
|
||||
mDeviceEventListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(int eventTypeId, int tunerSelectId, MemoryAddress eventParametersPointer,
|
||||
MemoryAddress callbackContext)
|
||||
{
|
||||
MemorySegment memorySegment = sdrplay_api_EventParamsT.ofAddress(eventParametersPointer, mMemorySession);
|
||||
EventType eventType = EventType.fromValue(eventTypeId);
|
||||
TunerSelect tunerSelect = TunerSelect.fromValue(tunerSelectId);
|
||||
|
||||
switch(eventType)
|
||||
{
|
||||
case GAIN_CHANGE -> {
|
||||
mDeviceEventListener.processGainChange(tunerSelect,
|
||||
EventParametersFactory.createGainCallbackParameters(memorySegment));
|
||||
}
|
||||
case POWER_OVERLOAD_CHANGE -> {
|
||||
mDeviceEventListener.processPowerOverload(tunerSelect,
|
||||
EventParametersFactory.createPowerOverloadCallbackParameters(memorySegment));
|
||||
}
|
||||
case DEVICE_REMOVED -> {
|
||||
mDeviceEventListener.processDeviceRemoval(tunerSelect);
|
||||
}
|
||||
case RSP_DUO_MODE_CHANGE -> {
|
||||
mDeviceEventListener.processRspDuoModeChange(tunerSelect,
|
||||
EventParametersFactory.createRspDuoModeCallbackParameters(memorySegment));
|
||||
}
|
||||
case UNKNOWN -> {
|
||||
mLog.warn("Unknown device event callback ignored. Please contact the library developer as this may " +
|
||||
"indicate a change to the SDRPlay API change. Tuner:" + tunerSelect + " Event Type ID:" +
|
||||
eventTypeId);
|
||||
mDeviceEventListener.processEvent(eventType, tunerSelect);
|
||||
}
|
||||
default -> {
|
||||
throw new IllegalStateException("DeviceEventAdapter must be updated handle EventType." + eventType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.callback;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.event.EventType;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.event.GainCallbackParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.event.PowerOverloadCallbackParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.event.RspDuoModeCallbackParameters;
|
||||
|
||||
/**
|
||||
* Device event listener. Receives events for the device, impacting one or both (if equipped) tuners on the device.
|
||||
*/
|
||||
public interface IDeviceEventListener
|
||||
{
|
||||
/**
|
||||
* Process a device event
|
||||
* @param eventType identifies the type of event
|
||||
* @param tunerSelect identifies which tuner(s) are included in the event (A, B, BOTH, or NEITHER)
|
||||
*/
|
||||
void processEvent(EventType eventType, TunerSelect tunerSelect);
|
||||
|
||||
/**
|
||||
* Process a gain change event
|
||||
* @param tunerSelect identifies which tuner(s) are included in the event (A, B, BOTH, or NEITHER)
|
||||
* @param gainCallbackParameters containing event details
|
||||
*/
|
||||
void processGainChange(TunerSelect tunerSelect, GainCallbackParameters gainCallbackParameters);
|
||||
|
||||
/**
|
||||
* Process a power overload event
|
||||
* @param tunerSelect identifies which tuner(s) are included in the event (A, B, BOTH, or NEITHER)
|
||||
* @param parameters containing event details
|
||||
*/
|
||||
void processPowerOverload(TunerSelect tunerSelect, PowerOverloadCallbackParameters parameters);
|
||||
|
||||
/**
|
||||
* Process an RSP-Duo mode change event
|
||||
* @param tunerSelect identifies which tuner(s) are included in the event (A, B, BOTH, or NEITHER)
|
||||
* @param parameters containing event details
|
||||
*/
|
||||
void processRspDuoModeChange(TunerSelect tunerSelect, RspDuoModeCallbackParameters parameters);
|
||||
|
||||
/**
|
||||
* Process a device removed (ie unplugged) event
|
||||
* @param tunerSelect identifies which tuner(s) are included in the event (A, B, BOTH, or NEITHER)
|
||||
*/
|
||||
void processDeviceRemoval(TunerSelect tunerSelect);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.callback;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
|
||||
|
||||
public interface IStreamCallbackListener
|
||||
{
|
||||
/**
|
||||
* Process stream callback parameters and reset value received over the stream callback interface.
|
||||
* @param parameters to process
|
||||
* @param reset value
|
||||
*/
|
||||
void process(TunerSelect tunerSelect, StreamCallbackParameters parameters, int reset);
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.callback;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
|
||||
|
||||
/**
|
||||
* Stream Listener interface.
|
||||
*/
|
||||
public interface IStreamListener
|
||||
{
|
||||
/**
|
||||
* Process samples from a single stream of I/Q samples
|
||||
* @param xi array of Inphase samples
|
||||
* @param xq array of Quadrature samples
|
||||
* @param streamCallbackParameters stream callback parameters
|
||||
* @param reset indicates if a re-initialization has occurred within the API and that local buffering should be reset
|
||||
*/
|
||||
void processStream(short[] xi, short[] xq, StreamCallbackParameters streamCallbackParameters,
|
||||
boolean reset);
|
||||
|
||||
/**
|
||||
* Indicates which tuner this stream listener is for. Note: this is used to manage asynchronous Updates to ensure
|
||||
* that submitted updates get correctly mapped and resolved in the Device update manager.
|
||||
* @return
|
||||
*/
|
||||
TunerSelect getTunerSelect();
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.callback;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.util.Flag;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_StreamCallback_t;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_StreamCbParamsT;
|
||||
import java.lang.foreign.MemoryAddress;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.foreign.MemorySession;
|
||||
import java.lang.foreign.ValueLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* I/Q sample stream callback adapter. Implements the native interface and transfers the native callback data to an
|
||||
* implementation of the Java IStreamListener interface.
|
||||
*/
|
||||
public class StreamCallbackAdapter implements sdrplay_api_StreamCallback_t
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(StreamCallbackAdapter.class);
|
||||
private MemorySession mMemorySession;
|
||||
private IStreamListener mStreamListener;
|
||||
private IStreamCallbackListener mStreamCallbackListener;
|
||||
|
||||
/**
|
||||
* Constructs an instance of the callback implementation
|
||||
* @param memorySession for defining new foreign memory segments
|
||||
* @param streamListener to receive transferred I/Q samples and event details
|
||||
* @param listener to receive callback parameters
|
||||
*/
|
||||
public StreamCallbackAdapter(MemorySession memorySession, IStreamListener streamListener,
|
||||
IStreamCallbackListener listener)
|
||||
{
|
||||
if(memorySession == null)
|
||||
{
|
||||
throw new IllegalArgumentException("Resource scope must be non-null");
|
||||
}
|
||||
|
||||
mMemorySession = memorySession;
|
||||
mStreamCallbackListener = listener;
|
||||
setListener(streamListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the listener for receiving samples
|
||||
* @param listener to receive stream samples
|
||||
*/
|
||||
public void setListener(IStreamListener listener)
|
||||
{
|
||||
mStreamListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives callback of foreign memory data, transfers it to Java, and passes to the listener.
|
||||
* @param iSamplesPointer array foreign memory address
|
||||
* @param qSamplesPointer array foreign memory address
|
||||
* @param parametersPointer associated with the callback - foreign memory address
|
||||
* @param sampleCount number of samples in each of the I and Q arrays
|
||||
* @param reset 0 or 1, translated to a boolean
|
||||
* @param deviceContext of the device that sourced the samples
|
||||
*/
|
||||
@Override
|
||||
public void apply(MemoryAddress iSamplesPointer, MemoryAddress qSamplesPointer, MemoryAddress parametersPointer,
|
||||
int sampleCount, int reset, MemoryAddress deviceContext)
|
||||
{
|
||||
if(mStreamListener != null || mStreamCallbackListener != null)
|
||||
{
|
||||
//Translate the callback parameters pointer to a memory segment and re-construct the parameters as a Java object
|
||||
StreamCallbackParameters parameters = new StreamCallbackParameters(sdrplay_api_StreamCbParamsT
|
||||
.ofAddress(parametersPointer, mMemorySession));
|
||||
|
||||
if(mStreamCallbackListener != null)
|
||||
{
|
||||
mStreamCallbackListener.process(mStreamListener.getTunerSelect(), parameters, reset);
|
||||
}
|
||||
|
||||
if(mStreamListener != null)
|
||||
{
|
||||
//Allocate memory segments from I/Q pointers, transfer from native to JVM array, and send to listener
|
||||
long arrayByteSize = ValueLayout.JAVA_SHORT.byteSize() * sampleCount;
|
||||
MemorySegment iSamples = MemorySegment.ofAddress(iSamplesPointer, arrayByteSize, mMemorySession);
|
||||
MemorySegment qSamples = MemorySegment.ofAddress(qSamplesPointer, arrayByteSize, mMemorySession);
|
||||
short[] i = iSamples.toArray(ValueLayout.JAVA_SHORT);
|
||||
short[] q = qSamples.toArray(ValueLayout.JAVA_SHORT);
|
||||
mStreamListener.processStream(i, q, parameters, Flag.evaluate(reset));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.callback;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.util.Flag;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_StreamCbParamsT;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
|
||||
/**
|
||||
* Stream Callback Parameters structure (sdrplay_api_StreamCbParamsT)
|
||||
*/
|
||||
public class StreamCallbackParameters
|
||||
{
|
||||
private int mFirstSampleNumber;
|
||||
private boolean mGainReductionChanged;
|
||||
private boolean mRfFrequencyChanged;
|
||||
private boolean mSampleRateChanged;
|
||||
private long mNumberSamples;
|
||||
|
||||
/**
|
||||
* Constructs an instance from the foreign memory segment
|
||||
*/
|
||||
public StreamCallbackParameters(MemorySegment memorySegment)
|
||||
{
|
||||
mFirstSampleNumber = sdrplay_api_StreamCbParamsT.firstSampleNum$get(memorySegment);
|
||||
mGainReductionChanged = Flag.evaluate(sdrplay_api_StreamCbParamsT.grChanged$get(memorySegment));
|
||||
mRfFrequencyChanged = Flag.evaluate(sdrplay_api_StreamCbParamsT.rfChanged$get(memorySegment));
|
||||
mSampleRateChanged = Flag.evaluate(sdrplay_api_StreamCbParamsT.fsChanged$get(memorySegment));
|
||||
mNumberSamples = sdrplay_api_StreamCbParamsT.numSamples$get(memorySegment);
|
||||
}
|
||||
|
||||
/**
|
||||
* First sample number
|
||||
*/
|
||||
public int getFirstSampleNumber()
|
||||
{
|
||||
return mFirstSampleNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if gain reduction value has changed
|
||||
*/
|
||||
public boolean isGainReductionChanged()
|
||||
{
|
||||
return mGainReductionChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if RF center frequency has changed
|
||||
*/
|
||||
public boolean isRfFrequencyChanged()
|
||||
{
|
||||
return mRfFrequencyChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if sample rate has changed
|
||||
*/
|
||||
public boolean isSampleRateChanged()
|
||||
{
|
||||
return mSampleRateChanged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of samples
|
||||
*/
|
||||
public long getNumberSamples()
|
||||
{
|
||||
return mNumberSamples;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
/**
|
||||
* Software decimation rates supported by the API for SDRPlay RSP devices
|
||||
*/
|
||||
public enum Decimate
|
||||
{
|
||||
X1(1, 16),
|
||||
X2(2, 16),
|
||||
X4(4, 17),
|
||||
X8(8, 17),
|
||||
X16(16, 18),
|
||||
X32(32, 20);
|
||||
|
||||
private int mValue;
|
||||
private int mSampleSize;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param value
|
||||
* @param sampleSize in bits to represent effective dynamic range.
|
||||
*/
|
||||
Decimate(int value, int sampleSize)
|
||||
{
|
||||
mValue = value;
|
||||
mSampleSize = sampleSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decimation value.
|
||||
* @return
|
||||
*/
|
||||
public int getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample size in bits to represent effective dynamic range for the decimation value.
|
||||
*/
|
||||
public int getSampleSize()
|
||||
{
|
||||
return mSampleSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if software decimation is enabled.
|
||||
* @return true for all values except X1.
|
||||
*/
|
||||
public boolean isEnabled()
|
||||
{
|
||||
return !this.equals(X1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
if(this.equals(X1))
|
||||
{
|
||||
return "None";
|
||||
}
|
||||
|
||||
return "x" + getValue();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,696 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.Status;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.UpdateReason;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.async.AsyncUpdateFuture;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.async.CompletedAsyncUpdate;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.callback.IDeviceEventListener;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.callback.IStreamCallbackListener;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.callback.IStreamListener;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.callback.StreamCallbackParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.error.DebugLevel;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.composite.CompositeParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.IfMode;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.LoMode;
|
||||
import java.lang.foreign.MemoryAddress;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Abstract device structure (sdrplay_api_DeviceT)
|
||||
*/
|
||||
public abstract class Device<T extends CompositeParameters<?,?>, R extends RspTuner<?,?>>
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(Device.class);
|
||||
|
||||
private SDRplay mSDRplay;
|
||||
private final UpdateRequestManager mUpdateRequestManager = new UpdateRequestManager();
|
||||
private final IDeviceStruct mDeviceStruct;
|
||||
protected boolean mSelected = false;
|
||||
protected boolean mInitialized = false;
|
||||
private T mCompositeParameters;
|
||||
|
||||
/**
|
||||
* Constructs an SDRPlay device from the foreign memory segment
|
||||
* @param sdrPlay api instance that created this device
|
||||
* @param deviceStruct to parse or access the fields of the device structure
|
||||
*/
|
||||
public Device(SDRplay sdrPlay, IDeviceStruct deviceStruct)
|
||||
{
|
||||
mSDRplay = sdrPlay;
|
||||
mDeviceStruct = deviceStruct;
|
||||
}
|
||||
|
||||
/**
|
||||
* Version specific device structure parser
|
||||
*/
|
||||
protected IDeviceStruct getDeviceStruct()
|
||||
{
|
||||
return mDeviceStruct;
|
||||
}
|
||||
|
||||
/**
|
||||
* API that owns this device
|
||||
*/
|
||||
protected SDRplay getAPI()
|
||||
{
|
||||
return mSDRplay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream callback listener for parameter change events.
|
||||
*/
|
||||
public IStreamCallbackListener getStreamCallbackListener()
|
||||
{
|
||||
return mUpdateRequestManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the device parameters for this device. Subsequent calls once the parameters are created are ignored.
|
||||
* @throws SDRPlayException if the device is not selected or if there is an issue loading the parameters
|
||||
*/
|
||||
private void loadDeviceParameters() throws SDRPlayException
|
||||
{
|
||||
if(selected())
|
||||
{
|
||||
mCompositeParameters = (T)getAPI().getCompositeParameters(getDeviceType(), getDeviceHandle());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the debug logging level for this device.
|
||||
* @param debugLevel to set
|
||||
*/
|
||||
public void setDebugLevel(DebugLevel debugLevel)
|
||||
{
|
||||
try
|
||||
{
|
||||
mSDRplay.setDebugLevel(getDeviceHandle(), debugLevel);
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
mLog.info("Unable to set debug level [" + debugLevel + "] for device - not selected", se);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects this device for exclusive use and loads the device composite parameters.
|
||||
* @throws SDRPlayException if unable to select the device or if unable to load the composite parameters for use.
|
||||
*/
|
||||
public void select() throws SDRPlayException
|
||||
{
|
||||
if(!selected())
|
||||
{
|
||||
getAPI().select(getDeviceMemorySegment());
|
||||
mSelected = true;
|
||||
loadDeviceParameters();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this device has been selected via the SDRplay api
|
||||
*/
|
||||
protected boolean selected()
|
||||
{
|
||||
return mSelected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the device is valid and ready for use
|
||||
*/
|
||||
public boolean isValid()
|
||||
{
|
||||
return getDeviceStruct().isValid();
|
||||
}
|
||||
|
||||
/**
|
||||
* Releases this device from exclusive use.
|
||||
*/
|
||||
public void release() throws SDRPlayException
|
||||
{
|
||||
if(selected())
|
||||
{
|
||||
mSelected = false;
|
||||
getAPI().release(getDeviceMemorySegment());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this device is initialized for use
|
||||
*/
|
||||
public boolean isInitialized()
|
||||
{
|
||||
return mInitialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this device for single-tuner use and starts the tuner providing raw signal samples to the stream
|
||||
* listener and device events to the event listener.
|
||||
*
|
||||
* Note: invoke select() to select this device for exclusive use before invoking this method. If this device has
|
||||
* previously been initialized, an exception is thrown. Use uninit() to uninitialize this device and stop the
|
||||
* sample stream and event notifications.
|
||||
*
|
||||
* @param eventListener to receive device event notifications
|
||||
* @param streamListener to receive samples from stream. Stream is from either Tuner 1 or Tuner 2 when
|
||||
* the device is selected for single-tuner mode.
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void initStreamA(IDeviceEventListener eventListener, IStreamListener streamListener) throws SDRPlayException
|
||||
{
|
||||
if(!isSelected())
|
||||
{
|
||||
throw new SDRPlayException("Device must be selected before it can be initialized");
|
||||
}
|
||||
|
||||
if(isInitialized())
|
||||
{
|
||||
throw new SDRPlayException("Device has already been initialized with listeners");
|
||||
}
|
||||
|
||||
getAPI().initA(Device.this, getDeviceHandle(), eventListener, streamListener);
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes this device for dual-tuner stream B use and starts the tuner providing raw signal samples to the stream
|
||||
* listener and device events to the event listener.
|
||||
*
|
||||
* Note: invoke select() to select this device for exclusive use before invoking this method. If this device has
|
||||
* previously been initialized, an exception is thrown. Use uninit() to uninitialize this device and stop the
|
||||
* sample stream and event notifications.
|
||||
*
|
||||
* @param eventListener to receive device event notifications
|
||||
* @param streamListener to receive samples from stream. Stream is from either Tuner 1 or Tuner 2 when
|
||||
* the device is selected for single-tuner mode.
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void initStreamB(IDeviceEventListener eventListener, IStreamListener streamListener) throws SDRPlayException
|
||||
{
|
||||
if(!isSelected())
|
||||
{
|
||||
throw new SDRPlayException("Device must be selected before it can be initialized");
|
||||
}
|
||||
|
||||
if(isInitialized())
|
||||
{
|
||||
throw new SDRPlayException("Device has already been initialized with listeners");
|
||||
}
|
||||
|
||||
getAPI().initB(Device.this, getDeviceHandle(), eventListener, streamListener);
|
||||
mInitialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Uninitializes this device from use. Note: call is ignored if this device hasn't been initialized
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void uninitialize() throws SDRPlayException
|
||||
{
|
||||
if(isInitialized())
|
||||
{
|
||||
getAPI().uninit(getDeviceHandle());
|
||||
mInitialized = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SDRPlayException("Attempt to uninit a device that has not been initialized previously");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates this device after parameter change, only when the device is initialized. If the device is not yet
|
||||
* initialized, the update request is ignored.
|
||||
*
|
||||
* @throws SDRPlayException if unable to apply updates
|
||||
*/
|
||||
public void update(TunerSelect tunerSelect, UpdateReason ... updateReasons) throws SDRPlayException
|
||||
{
|
||||
if(isInitialized())
|
||||
{
|
||||
submitUpdate(tunerSelect, updateReasons);
|
||||
}
|
||||
}
|
||||
|
||||
private String toString(UpdateReason ... updateReasons)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
boolean first = true;
|
||||
|
||||
for(UpdateReason updateReason: updateReasons)
|
||||
{
|
||||
if(first)
|
||||
{
|
||||
sb.append("[");
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append(", ");
|
||||
}
|
||||
|
||||
sb.append(updateReason.name());
|
||||
|
||||
first = false;
|
||||
}
|
||||
|
||||
sb.append("]");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronous update request. This method should only be used for Frequency, Gain and Sample Rate updates.
|
||||
* @param tunerSelect tuner being updated
|
||||
* @param updateReason for the parameter that is being updated
|
||||
* @param expectedResponse that is one of Gain, Frequency, or Sample Rate.
|
||||
* @return a future that has already been completed, or if initialized a future that will be completed.
|
||||
*/
|
||||
protected AsyncUpdateFuture updateAsync(TunerSelect tunerSelect, UpdateReason updateReason, UpdateReason expectedResponse)
|
||||
{
|
||||
if(!expectedResponse.isAsyncUpdateResponse())
|
||||
{
|
||||
throw new IllegalArgumentException("Invalid expected response: " + expectedResponse +
|
||||
". Valid values are: " + UpdateReason.ASYNC_UPDATE_RESPONSES);
|
||||
}
|
||||
|
||||
if(isInitialized())
|
||||
{
|
||||
return mUpdateRequestManager.update(tunerSelect, updateReason, expectedResponse);
|
||||
}
|
||||
|
||||
//If not initialized, return success.
|
||||
AsyncUpdateFuture future = new AsyncUpdateFuture(tunerSelect, updateReason, expectedResponse);
|
||||
future.setResult(Status.SUCCESS);
|
||||
return future;
|
||||
}
|
||||
|
||||
/**
|
||||
* Submits an update request to the API. This method is used/managed by the update request manager.
|
||||
* @param tunerSelect for the update
|
||||
* @param updateReasons to apply
|
||||
* @throws SDRPlayException if there is an issue.
|
||||
*/
|
||||
private void submitUpdate(TunerSelect tunerSelect, UpdateReason ... updateReasons) throws SDRPlayException
|
||||
{
|
||||
getAPI().update(Device.this, getDeviceHandle(), tunerSelect, updateReasons);
|
||||
}
|
||||
|
||||
/**
|
||||
* Acknowledge tuner power overload events
|
||||
* @param tunerSelect identifying which tuner(s)
|
||||
* @throws SDRPlayException on error
|
||||
*/
|
||||
public void acknowledgePowerOverload(TunerSelect tunerSelect) throws SDRPlayException
|
||||
{
|
||||
// mLog.info("Acknowledging power overload message for tuner [" + tunerSelect + "]");
|
||||
|
||||
//There's a bug (feature?) in the API ... when you un-initialize the device, it causes a power overload event
|
||||
// and if you acknowledge it, you get an error that the device is not initialized.
|
||||
if(isInitialized())
|
||||
{
|
||||
try
|
||||
{
|
||||
update(tunerSelect, UpdateReason.CONTROL_OVERLOAD_MESSAGE_ACK);
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
//Ignore the not initialized exception that can happen when shutting down the receiver, otherwise
|
||||
//rethrow the exception.
|
||||
if(se.getStatus() != Status.NOT_INITIALIZED)
|
||||
{
|
||||
throw se;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tuner selection.
|
||||
* @return tuner select. Defaults to TUNER_1 for all but the RSPduo where it is overridden for tuner 2.
|
||||
*/
|
||||
public TunerSelect getTunerSelect()
|
||||
{
|
||||
return TunerSelect.TUNER_1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Foreign memory segment representing this device.
|
||||
*/
|
||||
protected MemorySegment getDeviceMemorySegment()
|
||||
{
|
||||
return getDeviceStruct().getDeviceMemorySegment();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle to this device.
|
||||
*
|
||||
* Note: this device must be selected for exclusive use before you can access this handle.
|
||||
*
|
||||
* @throws SDRPlayException if this method is accessed before the device has been successfully selected
|
||||
*/
|
||||
MemoryAddress getDeviceHandle() throws SDRPlayException
|
||||
{
|
||||
if(!selected())
|
||||
{
|
||||
throw new SDRPlayException("This device must be selected for exclusive use before accessing/using the " +
|
||||
"device handle");
|
||||
}
|
||||
|
||||
return getDeviceStruct().getDeviceHandle();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tuner for this device
|
||||
* @return tuner appropriate for the device type
|
||||
* @throws SDRPlayException for various reasons include device not selected or API unavailable
|
||||
*/
|
||||
public abstract R getTuner() throws SDRPlayException;
|
||||
|
||||
/**
|
||||
* Composite parameters for this device
|
||||
*/
|
||||
public T getCompositeParameters()
|
||||
{
|
||||
return mCompositeParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this device has composite parameters
|
||||
*/
|
||||
public boolean hasCompositeParameters()
|
||||
{
|
||||
return mCompositeParameters != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this device is available and has been selected for exclusive use.
|
||||
*/
|
||||
public boolean isSelected()
|
||||
{
|
||||
return mSelected;
|
||||
}
|
||||
|
||||
/**
|
||||
* Device type
|
||||
*/
|
||||
public DeviceType getDeviceType()
|
||||
{
|
||||
return getDeviceStruct().getDeviceType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Serial number
|
||||
*/
|
||||
public String getSerialNumber()
|
||||
{
|
||||
return getDeviceStruct().getSerialNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* Current sample rate
|
||||
*/
|
||||
public double getSampleRate()
|
||||
{
|
||||
return getCompositeParameters().getDeviceParameters().getSamplingFrequency().getSampleRate();
|
||||
}
|
||||
|
||||
public void setIfMode(IfMode ifMode)
|
||||
{
|
||||
getCompositeParameters().getTunerAParameters().setIfMode(ifMode);
|
||||
}
|
||||
|
||||
public void setLoMode(LoMode loMode)
|
||||
{
|
||||
getCompositeParameters().getTunerAParameters().setLoMode(loMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables wideband signal mode. This should be set according to the IFMode, where IFMode.ZERO is
|
||||
* wideband and all others are not wideband.
|
||||
* @param enable
|
||||
*/
|
||||
public void setWidebandSignal(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getCompositeParameters().getControlAParameters().getDecimation().setWideBandSignal(enable);
|
||||
|
||||
if(isInitialized())
|
||||
{
|
||||
update(getTunerSelect(), UpdateReason.CONTROL_DECIMATION);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the software-based decimation factor for the final sample rate.
|
||||
* @param decimate value where X1 is no decimation and all others are decimation enabled values.
|
||||
* @throws SDRPlayException if there is an error while setting decimation
|
||||
*/
|
||||
public void setDecimation(Decimate decimate) throws SDRPlayException
|
||||
{
|
||||
getCompositeParameters().getControlAParameters().getDecimation().setDecimationFactor(decimate.getValue());
|
||||
getCompositeParameters().getControlAParameters().getDecimation().setEnabled(decimate.isEnabled());
|
||||
|
||||
if(isInitialized())
|
||||
{
|
||||
update(getTunerSelect(), UpdateReason.CONTROL_DECIMATION);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("SDRPplay Device").append("\n");
|
||||
sb.append("\tType: ").append(getDeviceType()).append("\n");
|
||||
sb.append("\tSerial Number: ").append(getSerialNumber()).append("\n");
|
||||
sb.append("\tSelected: ").append(isSelected());
|
||||
if(hasCompositeParameters())
|
||||
{
|
||||
sb.append("\t").append(getCompositeParameters());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Thread-safe manager for asynchronous update request queue processing for an initialized RSP device.
|
||||
*
|
||||
* Once a device has been initialized, any changes to frequency, gain or sample rate require submitting an update
|
||||
* request to the device to apply the parameter change(s). However, since the API supports non-blocking operation,
|
||||
* the operation executes asynchronously. The API supports only a single update request operation
|
||||
* to be in-progress at a time and any overlapping update requests are met with an unsuccessful status code return
|
||||
* from the update method.
|
||||
*/
|
||||
class UpdateRequestManager implements IStreamCallbackListener
|
||||
{
|
||||
private static final long UPDATE_QUEUE_PROCESSING_INTERVAL_MS = 75;
|
||||
private final ScheduledExecutorService mExecutorService = Executors.newSingleThreadScheduledExecutor();
|
||||
private final Queue<AsyncUpdateFuture> mUpdateQueue = new ConcurrentLinkedQueue();
|
||||
private final Queue<CompletedAsyncUpdate> mCompletedUpdateQueue = new ConcurrentLinkedQueue();
|
||||
private final ReentrantLock mLock = new ReentrantLock();
|
||||
|
||||
/**
|
||||
* Submits an update request for the specified tuner and update reason for queued processing. This is a
|
||||
* non-blocking operation and the update is performed by a thread from the thread pool.
|
||||
* @param tunerSelect to apply the update
|
||||
* @param updateReason to update
|
||||
* @return an asynchronous future to monitor the progress of the update request
|
||||
*/
|
||||
public AsyncUpdateFuture update(TunerSelect tunerSelect, UpdateReason updateReason, UpdateReason expectedResponse)
|
||||
{
|
||||
AsyncUpdateFuture future = new AsyncUpdateFuture(tunerSelect, updateReason, expectedResponse);
|
||||
mUpdateQueue.add(future);
|
||||
processQueuesImmediately();
|
||||
return future;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules a process queues task for immediate execution. Non-blocking.
|
||||
*/
|
||||
private void processQueuesImmediately()
|
||||
{
|
||||
processQueuesAfterDelay(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules a process queues task after the delay. Non-blocking
|
||||
* @param delay in milliseconds, or zero for immediate.
|
||||
*/
|
||||
private void processQueuesAfterDelay(long delay)
|
||||
{
|
||||
mExecutorService.schedule(() -> processQueues(), delay, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the pending and completed update operation queues. Submits new update requests one at a time and
|
||||
* awaits a stream callback notification that the matching update reason has been applied/updated. Ensures
|
||||
* that only a single update operation is in-progress at any given time.
|
||||
*/
|
||||
private synchronized void processQueues()
|
||||
{
|
||||
mLock.lock();
|
||||
|
||||
try
|
||||
{
|
||||
if(mUpdateQueue.isEmpty())
|
||||
{
|
||||
//If we have no pending updates, we don't care about any completed update results
|
||||
mCompletedUpdateQueue.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
boolean processing = true;
|
||||
|
||||
while(processing)
|
||||
{
|
||||
processing = false;
|
||||
|
||||
AsyncUpdateFuture futureUpdate = mUpdateQueue.peek();
|
||||
|
||||
if(futureUpdate != null)
|
||||
{
|
||||
if(futureUpdate.isSubmitted())
|
||||
{
|
||||
//Process the completion queue
|
||||
while(!mCompletedUpdateQueue.isEmpty())
|
||||
{
|
||||
CompletedAsyncUpdate completedUpdate = mCompletedUpdateQueue.poll();
|
||||
|
||||
if(completedUpdate != null)
|
||||
{
|
||||
if(futureUpdate.matches(completedUpdate))
|
||||
{
|
||||
//Clear the remaining completed updates
|
||||
mCompletedUpdateQueue.clear();
|
||||
|
||||
//Remove and (successfully) complete the current future
|
||||
mUpdateQueue.remove();
|
||||
futureUpdate.setResult(Status.SUCCESS);
|
||||
|
||||
//Signal to immediately reprocess the queue
|
||||
processing = true;
|
||||
|
||||
//Break out of the completed update queue processing
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Clear the completed queue and submit the update
|
||||
mCompletedUpdateQueue.clear();
|
||||
|
||||
try
|
||||
{
|
||||
submitUpdate(futureUpdate.getTunerSelect(), futureUpdate.getUpdateReason());
|
||||
futureUpdate.setSubmitted(true);
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
futureUpdate = mUpdateQueue.poll();
|
||||
futureUpdate.setError(se);
|
||||
//Set continuous to true to immediately reprocess the next update
|
||||
processing = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
mLock.unlock();
|
||||
}
|
||||
|
||||
if(!mUpdateQueue.isEmpty())
|
||||
{
|
||||
processQueuesAfterDelay(UPDATE_QUEUE_PROCESSING_INTERVAL_MS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives an update completion event. This is a non-blocking operation since this method will be invoked
|
||||
* by the stream callback thread, and we don't want to impact the delivery of streaming samples or events.
|
||||
*
|
||||
* @param tunerSelect tuner that was updated
|
||||
* @param updateReason for what was updated
|
||||
*/
|
||||
public void completed(TunerSelect tunerSelect, UpdateReason updateReason)
|
||||
{
|
||||
mCompletedUpdateQueue.add(new CompletedAsyncUpdate(tunerSelect, updateReason));
|
||||
mExecutorService.schedule(this::processQueues, 0, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the update queue.
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
mLock.lock();
|
||||
|
||||
try
|
||||
{
|
||||
while(!mUpdateQueue.isEmpty())
|
||||
{
|
||||
AsyncUpdateFuture future = mUpdateQueue.poll();
|
||||
future.setResult(Status.UNKNOWN);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
mLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements the IStreamCallbackListener interface to receive change notifications from update requests.
|
||||
* @param parameters to process
|
||||
* @param reset value with flags
|
||||
*/
|
||||
@Override
|
||||
public void process(TunerSelect tunerSelect, StreamCallbackParameters parameters, int reset)
|
||||
{
|
||||
if(parameters.isSampleRateChanged())
|
||||
{
|
||||
completed(tunerSelect, UpdateReason.DEVICE_SAMPLE_RATE);
|
||||
}
|
||||
if(parameters.isRfFrequencyChanged())
|
||||
{
|
||||
completed(tunerSelect, UpdateReason.TUNER_FREQUENCY_RF);
|
||||
}
|
||||
if(parameters.isGainReductionChanged())
|
||||
{
|
||||
completed(tunerSelect, UpdateReason.TUNER_GAIN_REDUCTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.Version;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_DeviceT;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_h;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
import java.lang.foreign.SegmentAllocator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Factory methods for creating new RSP Device instances
|
||||
*/
|
||||
public class DeviceFactory
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(DeviceFactory.class);
|
||||
|
||||
/**
|
||||
* Creates a foreign memory segment for a DeviceT array, appropriate for the specified version.
|
||||
* @param version value
|
||||
* @param segmentAllocator to allocate the foreign memory
|
||||
* @return devices array
|
||||
*/
|
||||
public static MemorySegment createDeviceArray(Version version, SegmentAllocator segmentAllocator)
|
||||
{
|
||||
if(version.gte(Version.V3_08))
|
||||
{
|
||||
return sdrplay_api_DeviceT.allocateArray(sdrplay_api_h.SDRPLAY_MAX_DEVICES(), segmentAllocator);
|
||||
}
|
||||
else if(version == Version.V3_07)
|
||||
{
|
||||
return sdrplay_api_DeviceT.allocateArray(sdrplay_api_h.SDRPLAY_MAX_DEVICES(), segmentAllocator);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unrecognized version: " + version);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses device information from a list of device structures
|
||||
* @param deviceStructs representing devices to parse
|
||||
* @return a list of device infos
|
||||
*/
|
||||
public static List<DeviceInfo> parseDeviceInfos(List<IDeviceStruct> deviceStructs)
|
||||
{
|
||||
List<DeviceInfo> deviceInfos = new ArrayList<>();
|
||||
|
||||
for(IDeviceStruct deviceStruct: deviceStructs)
|
||||
{
|
||||
deviceInfos.add(new DeviceInfo(deviceStruct));
|
||||
}
|
||||
|
||||
return deviceInfos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses device information from a memory segment containing an array of device structures.
|
||||
* @param version of the API
|
||||
* @param devicesArray memory segment
|
||||
* @param count of device structures in the devicesArray.
|
||||
* @return a list of device infos
|
||||
* @throws exception if version is unrecognized or unsupported
|
||||
*/
|
||||
public static List<IDeviceStruct> parseDeviceStructs(Version version, MemorySegment devicesArray, int count)
|
||||
throws SDRPlayException
|
||||
{
|
||||
List<IDeviceStruct> deviceStructs = new ArrayList<>();
|
||||
|
||||
if(version.gte(Version.V3_08))
|
||||
{
|
||||
devicesArray.elements(sdrplay_api_DeviceT.$LAYOUT())
|
||||
.limit(count).forEach(memorySegment ->
|
||||
deviceStructs.add(DeviceFactory.createDeviceStruct(version, memorySegment)));
|
||||
}
|
||||
else if(version == Version.V3_07)
|
||||
{
|
||||
devicesArray.elements(sdrplay_api_DeviceT.$LAYOUT()).limit(count).forEach(memorySegment ->
|
||||
{
|
||||
deviceStructs.add(DeviceFactory.createDeviceStruct(version, memorySegment));
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new SDRPlayException("Unrecognized version: " + version);
|
||||
}
|
||||
|
||||
return deviceStructs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an SDRplay device from the foreign memory Device instance.
|
||||
* @param sdrPlay for device callback support
|
||||
* @param deviceMemorySegment instance for the device
|
||||
* @return correctly typed device
|
||||
*/
|
||||
public static Device createDevice(SDRplay sdrPlay, IDeviceStruct deviceStruct)
|
||||
{
|
||||
switch(deviceStruct.getDeviceType())
|
||||
{
|
||||
case RSP1 -> {
|
||||
return new Rsp1Device(sdrPlay, deviceStruct);
|
||||
}
|
||||
case RSP1A -> {
|
||||
return new Rsp1aDevice(sdrPlay, deviceStruct);
|
||||
}
|
||||
case RSP2 -> {
|
||||
return new Rsp2Device(sdrPlay, deviceStruct);
|
||||
}
|
||||
case RSPduo -> {
|
||||
return new RspDuoDevice(sdrPlay, deviceStruct);
|
||||
}
|
||||
case RSPdx -> {
|
||||
return new RspDxDevice(sdrPlay, deviceStruct);
|
||||
}
|
||||
default -> {
|
||||
return new UnknownDevice(sdrPlay, deviceStruct);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a device structure parser for the specified API version
|
||||
* @param version to create
|
||||
* @param deviceMemorySegment for the device
|
||||
* @return device structure
|
||||
*/
|
||||
private static IDeviceStruct createDeviceStruct(Version version, MemorySegment deviceMemorySegment)
|
||||
{
|
||||
if(version == Version.V3_07)
|
||||
{
|
||||
return new DeviceStruct_v3_07(deviceMemorySegment);
|
||||
}
|
||||
else if(version.gte(Version.V3_08))
|
||||
{
|
||||
return new DeviceStruct_v3_08(deviceMemorySegment);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalArgumentException("Unsupported version: " + version);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.DeviceSelectionMode;
|
||||
import java.util.Objects;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
/**
|
||||
* RSP device information to support device selection.
|
||||
*/
|
||||
public class DeviceInfo
|
||||
{
|
||||
private DeviceSelectionMode mDeviceSelectionMode = DeviceSelectionMode.SINGLE_TUNER_1;
|
||||
private DeviceType mDeviceType;
|
||||
private String mSerialNumber;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param deviceType of the RSP device
|
||||
* @param serialNumber for the device
|
||||
*/
|
||||
public DeviceInfo(DeviceType deviceType, String serialNumber)
|
||||
{
|
||||
Validate.notNull(deviceType, "Device type cannot be null");
|
||||
Validate.notNull(serialNumber, "Device serial number cannot be null");
|
||||
|
||||
mDeviceType = deviceType;
|
||||
mSerialNumber = serialNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Alternate constructor where we get the parameters from a device structure.
|
||||
* @param deviceStruct containing device type and serial number values.
|
||||
*/
|
||||
public DeviceInfo(IDeviceStruct deviceStruct)
|
||||
{
|
||||
this(deviceStruct.getDeviceType(), deviceStruct.getSerialNumber());
|
||||
}
|
||||
|
||||
/**
|
||||
* Device type for this RSP device
|
||||
* @return type
|
||||
*/
|
||||
public DeviceType getDeviceType()
|
||||
{
|
||||
return mDeviceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serial number for this RSP device
|
||||
* @return serial number
|
||||
*/
|
||||
public String getSerialNumber()
|
||||
{
|
||||
return mSerialNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Device selection mode for this RSP device
|
||||
* @return device selection mode where single tuner 1 is default
|
||||
*/
|
||||
public DeviceSelectionMode getDeviceSelectionMode()
|
||||
{
|
||||
return mDeviceSelectionMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the device selection mode. This should be left as default of single tuner 1 unless this device is an RSPduo.
|
||||
* @param deviceSelectionMode to use for this device.
|
||||
*/
|
||||
public void setDeviceSelectionMode(DeviceSelectionMode deviceSelectionMode)
|
||||
{
|
||||
Validate.notNull(deviceSelectionMode, "Device selection mode cannot be null");
|
||||
mDeviceSelectionMode = deviceSelectionMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones this instance
|
||||
* @return deep copy.
|
||||
*/
|
||||
public DeviceInfo clone()
|
||||
{
|
||||
return new DeviceInfo(mDeviceType, mSerialNumber);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this device type and serial number matches the details of the device structure.
|
||||
* @param deviceStruct to compare
|
||||
* @return true if the device type and serial number match.
|
||||
*/
|
||||
public boolean matches(IDeviceStruct deviceStruct)
|
||||
{
|
||||
return deviceStruct != null && getDeviceType().equals(deviceStruct.getDeviceType()) && getSerialNumber().equals(deviceStruct.getSerialNumber());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Device: " + getDeviceType() + " Serial Number: " + getSerialNumber() + " Selection Mode: " + getDeviceSelectionMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
if(this == o)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if(o == null || getClass() != o.getClass())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
DeviceInfo that = (DeviceInfo) o;
|
||||
return mDeviceSelectionMode == that.mDeviceSelectionMode && mDeviceType == that.mDeviceType && mSerialNumber.equals(that.mSerialNumber);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(mDeviceSelectionMode, mDeviceType, mSerialNumber);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_DeviceT;
|
||||
import java.lang.foreign.MemoryAddress;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
|
||||
/**
|
||||
* sdrplay_api_DeviceT structure parser for API version 3.07
|
||||
*/
|
||||
public class DeviceStruct_v3_07 implements IDeviceStruct
|
||||
{
|
||||
private MemorySegment mDeviceMemorySegment;
|
||||
private DeviceType mDeviceType;
|
||||
private String mSerialNumber;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param deviceMemorySegment of foreign memory
|
||||
*/
|
||||
public DeviceStruct_v3_07(MemorySegment deviceMemorySegment)
|
||||
{
|
||||
mDeviceMemorySegment = deviceMemorySegment;
|
||||
mDeviceType = DeviceType.fromValue(0xFF & sdrplay_api_DeviceT.hwVer$get(mDeviceMemorySegment));
|
||||
MemorySegment serialSegment = sdrplay_api_DeviceT.SerNo$slice(mDeviceMemorySegment);
|
||||
mSerialNumber = serialSegment.getUtf8String(0);
|
||||
}
|
||||
|
||||
@Override public MemorySegment getDeviceMemorySegment()
|
||||
{
|
||||
return mDeviceMemorySegment;
|
||||
}
|
||||
|
||||
@Override public String getSerialNumber()
|
||||
{
|
||||
return mSerialNumber;
|
||||
}
|
||||
|
||||
@Override public DeviceType getDeviceType()
|
||||
{
|
||||
return mDeviceType;
|
||||
}
|
||||
|
||||
@Override public TunerSelect getTunerSelect()
|
||||
{
|
||||
return TunerSelect.fromValue(sdrplay_api_DeviceT.tuner$get(getDeviceMemorySegment()));
|
||||
}
|
||||
|
||||
@Override public RspDuoMode getRspDuoMode()
|
||||
{
|
||||
return RspDuoMode.fromValue(sdrplay_api_DeviceT.rspDuoMode$get(getDeviceMemorySegment()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRspDuoMode(RspDuoMode mode)
|
||||
{
|
||||
sdrplay_api_DeviceT.rspDuoMode$set(getDeviceMemorySegment(), mode.getValue());
|
||||
}
|
||||
|
||||
@Override public boolean isValid()
|
||||
{
|
||||
//Always returns true for version 3.07
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public double getRspDuoSampleFrequency()
|
||||
{
|
||||
return sdrplay_api_DeviceT.rspDuoSampleFreq$get(getDeviceMemorySegment());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRspDuoSampleFrequency(double frequency)
|
||||
{
|
||||
sdrplay_api_DeviceT.rspDuoSampleFreq$set(getDeviceMemorySegment(), frequency);
|
||||
}
|
||||
|
||||
@Override public MemoryAddress getDeviceHandle()
|
||||
{
|
||||
return sdrplay_api_DeviceT.dev$get(getDeviceMemorySegment());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_08.sdrplay_api_DeviceT;
|
||||
import java.lang.foreign.MemoryAddress;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
|
||||
/**
|
||||
* sdrplay_api_DeviceT structure parser for API version 3.07
|
||||
*/
|
||||
public class DeviceStruct_v3_08 implements IDeviceStruct
|
||||
{
|
||||
private MemorySegment mDeviceMemorySegment;
|
||||
private DeviceType mDeviceType;
|
||||
private String mSerialNumber;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param deviceMemorySegment of foreign memory
|
||||
*/
|
||||
public DeviceStruct_v3_08(MemorySegment deviceMemorySegment)
|
||||
{
|
||||
mDeviceMemorySegment = deviceMemorySegment;
|
||||
mDeviceType = DeviceType.fromValue(0xFF & sdrplay_api_DeviceT.hwVer$get(mDeviceMemorySegment));
|
||||
MemorySegment serialSegment = sdrplay_api_DeviceT.SerNo$slice(mDeviceMemorySegment);
|
||||
mSerialNumber = serialSegment.getUtf8String(0);
|
||||
}
|
||||
|
||||
@Override public MemorySegment getDeviceMemorySegment()
|
||||
{
|
||||
return mDeviceMemorySegment;
|
||||
}
|
||||
|
||||
@Override public String getSerialNumber()
|
||||
{
|
||||
return mSerialNumber;
|
||||
}
|
||||
|
||||
@Override public DeviceType getDeviceType()
|
||||
{
|
||||
return mDeviceType;
|
||||
}
|
||||
|
||||
@Override public TunerSelect getTunerSelect()
|
||||
{
|
||||
return TunerSelect.fromValue(sdrplay_api_DeviceT.tuner$get(getDeviceMemorySegment()));
|
||||
}
|
||||
|
||||
@Override public RspDuoMode getRspDuoMode()
|
||||
{
|
||||
return RspDuoMode.fromValue(sdrplay_api_DeviceT.rspDuoMode$get(getDeviceMemorySegment()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRspDuoMode(RspDuoMode mode)
|
||||
{
|
||||
sdrplay_api_DeviceT.rspDuoMode$set(getDeviceMemorySegment(), mode.getValue());
|
||||
}
|
||||
|
||||
@Override public boolean isValid()
|
||||
{
|
||||
//Always returns true for version 3.07
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public double getRspDuoSampleFrequency()
|
||||
{
|
||||
return sdrplay_api_DeviceT.rspDuoSampleFreq$get(getDeviceMemorySegment());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRspDuoSampleFrequency(double frequency)
|
||||
{
|
||||
sdrplay_api_DeviceT.rspDuoSampleFreq$set(getDeviceMemorySegment(), frequency);
|
||||
}
|
||||
|
||||
@Override public MemoryAddress getDeviceHandle()
|
||||
{
|
||||
return sdrplay_api_DeviceT.dev$get(getDeviceMemorySegment());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_h;
|
||||
|
||||
/**
|
||||
* RSP Device type
|
||||
*/
|
||||
public enum DeviceType
|
||||
{
|
||||
RSP1(sdrplay_api_h.SDRPLAY_RSP1_ID(), "RSP1"),
|
||||
RSP1A(sdrplay_api_h.SDRPLAY_RSP1A_ID(), "RSP1A"),
|
||||
RSP2(sdrplay_api_h.SDRPLAY_RSP2_ID(), "RSP2"),
|
||||
RSPduo(sdrplay_api_h.SDRPLAY_RSPduo_ID(), "RSPduo"),
|
||||
RSPdx(sdrplay_api_h.SDRPLAY_RSPdx_ID(), "RSPdx"),
|
||||
UNKNOWN(Integer.MIN_VALUE, "UNKNOWN");
|
||||
|
||||
private int mValue;
|
||||
private String mDescription;
|
||||
|
||||
DeviceType(int value, String description)
|
||||
{
|
||||
mValue = value;
|
||||
mDescription = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numeric value
|
||||
*/
|
||||
public int getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the entry from a return code
|
||||
* @param value to lookup
|
||||
* @return entry or UNKNOWN if the code is not recognized
|
||||
*/
|
||||
public static DeviceType fromValue(int value)
|
||||
{
|
||||
for(DeviceType status: DeviceType.values())
|
||||
{
|
||||
if(status.getValue() == value)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import java.lang.foreign.MemoryAddress;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
|
||||
/**
|
||||
* Interface for parsing and accessing the fields of the sdrplay_api_DeviceT structure across
|
||||
* various versions.
|
||||
*/
|
||||
public interface IDeviceStruct
|
||||
{
|
||||
/**
|
||||
* Foreign memory segment for this device structure
|
||||
*/
|
||||
MemorySegment getDeviceMemorySegment();
|
||||
|
||||
/**
|
||||
* Serial number of the device
|
||||
*/
|
||||
String getSerialNumber();
|
||||
|
||||
/**
|
||||
* Indicates the device type, or model of RSP
|
||||
*/
|
||||
DeviceType getDeviceType();
|
||||
|
||||
/**
|
||||
* Indicates single, dual, or master/slave mode for the tuner.
|
||||
*/
|
||||
TunerSelect getTunerSelect();
|
||||
|
||||
/**
|
||||
* RSPduo mode
|
||||
*/
|
||||
RspDuoMode getRspDuoMode();
|
||||
|
||||
/**
|
||||
* Sets the RSPduo mode
|
||||
* @param mode to set
|
||||
*/
|
||||
void setRspDuoMode(RspDuoMode mode);
|
||||
|
||||
/**
|
||||
* Indicates if the device is valid and ready for use (V3.08 and later)
|
||||
*/
|
||||
boolean isValid();
|
||||
|
||||
/**
|
||||
* Sample frequency/rate for the RSPduo when in master/slave mode
|
||||
*/
|
||||
double getRspDuoSampleFrequency();
|
||||
|
||||
/**
|
||||
* Sets the sample frequency/rate for the RSPduo when in master (only) mode.
|
||||
*/
|
||||
void setRspDuoSampleFrequency(double frequency);
|
||||
|
||||
/**
|
||||
* Device handle. Note this is only available if the device has been selected.
|
||||
*/
|
||||
MemoryAddress getDeviceHandle();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.composite.Rsp1CompositeParameters;
|
||||
|
||||
/**
|
||||
* RSP1 Device
|
||||
*/
|
||||
public class Rsp1Device extends Device<Rsp1CompositeParameters, Rsp1Tuner>
|
||||
{
|
||||
private Rsp1Tuner mTuner1;
|
||||
|
||||
/**
|
||||
* Constructs an SDRPlay RSP1 device from the foreign memory segment
|
||||
*
|
||||
* @param sdrPlay api instance that created this device
|
||||
* @param deviceStruct parser
|
||||
*/
|
||||
Rsp1Device(SDRplay sdrPlay, IDeviceStruct deviceStruct)
|
||||
{
|
||||
super(sdrPlay, deviceStruct);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rsp1Tuner getTuner() throws SDRPlayException
|
||||
{
|
||||
if(!isSelected())
|
||||
{
|
||||
throw new SDRPlayException("Device must be selected before accessing the tuner");
|
||||
}
|
||||
|
||||
if(mTuner1 == null)
|
||||
{
|
||||
mTuner1 = new Rsp1Tuner(Rsp1Device.this, getAPI(), getTunerSelect(),
|
||||
getCompositeParameters().getDeviceParameters(), getCompositeParameters().getTunerAParameters(),
|
||||
getCompositeParameters().getControlAParameters());
|
||||
}
|
||||
|
||||
return mTuner1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.ControlParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.device.Rsp1DeviceParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.Rsp1TunerParameters;
|
||||
|
||||
/**
|
||||
* RSP1 Tuner
|
||||
*/
|
||||
public class Rsp1Tuner extends RspTuner<Rsp1DeviceParameters, Rsp1TunerParameters>
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param device parent for this tuner
|
||||
* @param sdrplay api
|
||||
* @param tunerSelect to specify which tuner
|
||||
* @param deviceParameters for this device
|
||||
* @param tunerParameters for this tuner
|
||||
* @param controlParameters for this device
|
||||
*/
|
||||
public Rsp1Tuner(Device device, SDRplay sdrplay, TunerSelect tunerSelect, Rsp1DeviceParameters deviceParameters,
|
||||
Rsp1TunerParameters tunerParameters, ControlParameters controlParameters)
|
||||
{
|
||||
super(device, sdrplay, tunerSelect, deviceParameters, tunerParameters, controlParameters);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.composite.Rsp1aCompositeParameters;
|
||||
|
||||
/**
|
||||
* RSP1A Device
|
||||
*/
|
||||
public class Rsp1aDevice extends Device<Rsp1aCompositeParameters, Rsp1aTuner>
|
||||
{
|
||||
private Rsp1aTuner mTuner1;
|
||||
|
||||
/**
|
||||
* Constructs an SDRPlay RSP1A device from the foreign memory segment
|
||||
*
|
||||
* @param sdrPlay api instance that created this device
|
||||
* @param deviceStruct parser
|
||||
*/
|
||||
Rsp1aDevice(SDRplay sdrPlay, IDeviceStruct deviceStruct)
|
||||
{
|
||||
super(sdrPlay, deviceStruct);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rsp1aTuner getTuner() throws SDRPlayException
|
||||
{
|
||||
if(!isSelected())
|
||||
{
|
||||
throw new SDRPlayException("Device must be selected before accessing the tuner");
|
||||
}
|
||||
|
||||
if(mTuner1 == null)
|
||||
{
|
||||
mTuner1 = new Rsp1aTuner(Rsp1aDevice.this, getAPI(), getTunerSelect(),
|
||||
getCompositeParameters().getDeviceParameters(), getCompositeParameters().getTunerAParameters(),
|
||||
getCompositeParameters().getControlAParameters());
|
||||
}
|
||||
|
||||
return mTuner1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.UpdateReason;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.ControlParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.device.Rsp1aDeviceParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.Rsp1aTunerParameters;
|
||||
|
||||
/**
|
||||
* RSP1A Tuner
|
||||
*/
|
||||
public class Rsp1aTuner extends RspTuner<Rsp1aDeviceParameters, Rsp1aTunerParameters>
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param device parent for this tuner
|
||||
* @param sdrplay api
|
||||
* @param tunerSelect to specify which tuner
|
||||
* @param deviceParameters for this device
|
||||
* @param tunerParameters for this tuner
|
||||
* @param controlParameters for this device
|
||||
*/
|
||||
public Rsp1aTuner(Device device, SDRplay sdrplay, TunerSelect tunerSelect, Rsp1aDeviceParameters deviceParameters,
|
||||
Rsp1aTunerParameters tunerParameters, ControlParameters controlParameters)
|
||||
{
|
||||
super(device, sdrplay, tunerSelect, deviceParameters, tunerParameters, controlParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the RF notch is enabled
|
||||
*/
|
||||
public boolean isRfNotch()
|
||||
{
|
||||
return getDeviceParameters().isRFNotch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the RF notch
|
||||
* @param enable setting
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setRfNotch(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getDeviceParameters().setRFNotch(enable);
|
||||
update(UpdateReason.RSP1A_RF_NOTCH_CONTROL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the RF DAB notch is enabled
|
||||
*/
|
||||
public boolean isRfDabNotch()
|
||||
{
|
||||
return getDeviceParameters().isRfDabNotch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the RF DAB notch
|
||||
* @param enable value
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setRfDabNotch(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getDeviceParameters().setRfDabNotch(enable);
|
||||
update(UpdateReason.RSP1A_RF_DAB_NOTCH_CONTROL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the Bias-T is enabled
|
||||
*/
|
||||
public boolean isBiasT()
|
||||
{
|
||||
return getTunerParameters().isBiasT();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the Bias-T
|
||||
* @param enable value
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setBiasT(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().setBiasT(enable);
|
||||
update(UpdateReason.RSP1A_BIAS_T_CONTROL);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.composite.Rsp2CompositeParameters;
|
||||
|
||||
/**
|
||||
* RSP2 Device
|
||||
*/
|
||||
public class Rsp2Device extends Device<Rsp2CompositeParameters, Rsp2Tuner>
|
||||
{
|
||||
private Rsp2Tuner mTuner1;
|
||||
|
||||
/**
|
||||
* Constructs an SDRPlay RSP2 device from the foreign memory segment
|
||||
*
|
||||
* @param sdrPlay api instance that created this device
|
||||
* @param deviceStruct parser
|
||||
*/
|
||||
Rsp2Device(SDRplay sdrPlay, IDeviceStruct deviceStruct)
|
||||
{
|
||||
super(sdrPlay, deviceStruct);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rsp2Tuner getTuner() throws SDRPlayException
|
||||
{
|
||||
if(!isSelected())
|
||||
{
|
||||
throw new SDRPlayException("Device must be selected before accessing the tuner");
|
||||
}
|
||||
|
||||
if(mTuner1 == null)
|
||||
{
|
||||
mTuner1 = new Rsp2Tuner(Rsp2Device.this, getAPI(), getTunerSelect(),
|
||||
getCompositeParameters().getDeviceParameters(), getCompositeParameters().getTunerAParameters(),
|
||||
getCompositeParameters().getControlAParameters());
|
||||
}
|
||||
|
||||
return mTuner1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.UpdateReason;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.ControlParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.device.Rsp2DeviceParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.Rsp2AmPort;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.Rsp2Antenna;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.Rsp2TunerParameters;
|
||||
|
||||
/**
|
||||
* RSP2 Tuner
|
||||
*/
|
||||
public class Rsp2Tuner extends RspTuner<Rsp2DeviceParameters, Rsp2TunerParameters>
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param device parent for this tuner
|
||||
* @param sdrplay api
|
||||
* @param tunerSelect to specify which tuner
|
||||
* @param deviceParameters for this device
|
||||
* @param tunerParameters for this tuner
|
||||
* @param controlParameters for this device
|
||||
*/
|
||||
public Rsp2Tuner(Device device, SDRplay sdrplay, TunerSelect tunerSelect, Rsp2DeviceParameters deviceParameters,
|
||||
Rsp2TunerParameters tunerParameters, ControlParameters controlParameters)
|
||||
{
|
||||
super(device, sdrplay, tunerSelect, deviceParameters, tunerParameters, controlParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the external reference output is enabled.
|
||||
*/
|
||||
public boolean isExternalReferenceOutput()
|
||||
{
|
||||
return getDeviceParameters().isExternalReferenceOutput();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the external reference output
|
||||
* @param enable value
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setExternalReferenceOutput(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getDeviceParameters().setExternalReferenceOutput(enable);
|
||||
update(UpdateReason.RSP2_EXT_REF_CONTROL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the Bias-T is enabled
|
||||
*/
|
||||
public boolean isBiasT()
|
||||
{
|
||||
return getTunerParameters().isBiasT();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the Bias-T
|
||||
* @param enable value
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setBiasT(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().setBiasT(enable);
|
||||
update(UpdateReason.RSP2_BIAS_T_CONTROL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the RF notch is enabled
|
||||
*/
|
||||
public boolean isRfNotch()
|
||||
{
|
||||
return getTunerParameters().isRfNotch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the RF notch
|
||||
* @param enable setting
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setRfNotch(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().setRfNotch(enable);
|
||||
update(UpdateReason.RSP2_RF_NOTCH_CONTROL);
|
||||
}
|
||||
|
||||
/**
|
||||
* AM port selection
|
||||
*/
|
||||
public Rsp2AmPort getAmPort()
|
||||
{
|
||||
return getTunerParameters().getAmPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the AM port
|
||||
* @param port to select
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setAmPort(Rsp2AmPort port) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().setAmPort(port);
|
||||
update(UpdateReason.RSP2_AM_PORT_SELECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Antenna selection
|
||||
*/
|
||||
public Rsp2Antenna getAntenna()
|
||||
{
|
||||
return getTunerParameters().getAntenna();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the antenna
|
||||
* @param antenna to select
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setAntenna(Rsp2Antenna antenna) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().setAntenna(antenna);
|
||||
update(UpdateReason.RSP2_ANTENNA_CONTROL);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.UpdateReason;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.composite.RspDuoCompositeParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.IfMode;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.LoMode;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_DeviceT;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* RSPduo Device
|
||||
*/
|
||||
public class RspDuoDevice extends Device<RspDuoCompositeParameters, RspDuoTuner>
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(RspDuoDevice.class);
|
||||
|
||||
private RspDuoTuner mTuner;
|
||||
|
||||
/**
|
||||
* Constructs an SDRPlay RSPduo device from the foreign memory segment
|
||||
*
|
||||
* @param sdrPlay api instance that created this device
|
||||
* @param deviceStruct parser
|
||||
*/
|
||||
RspDuoDevice(SDRplay sdrPlay, IDeviceStruct deviceStruct)
|
||||
{
|
||||
super(sdrPlay, deviceStruct);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tuner
|
||||
* @return tuner
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
@Override
|
||||
public RspDuoTuner getTuner() throws SDRPlayException
|
||||
{
|
||||
if(!isSelected())
|
||||
{
|
||||
throw new SDRPlayException("Device must be selected before accessing the tuner");
|
||||
}
|
||||
|
||||
if(mTuner == null)
|
||||
{
|
||||
if(getTunerSelect().equals(TunerSelect.TUNER_1))
|
||||
{
|
||||
mTuner = new RspDuoTuner1(RspDuoDevice.this, getAPI(),
|
||||
getCompositeParameters().getDeviceParameters(), getCompositeParameters().getTunerAParameters(),
|
||||
getCompositeParameters().getControlAParameters());
|
||||
}
|
||||
else
|
||||
{
|
||||
mTuner = new RspDuoTuner2(RspDuoDevice.this, getAPI(),
|
||||
getCompositeParameters().getDeviceParameters(), getCompositeParameters().getTunerBParameters(),
|
||||
getCompositeParameters().getControlBParameters());
|
||||
}
|
||||
}
|
||||
|
||||
return mTuner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selected tuner(s).
|
||||
*/
|
||||
@Override
|
||||
public TunerSelect getTunerSelect()
|
||||
{
|
||||
return TunerSelect.fromValue(sdrplay_api_DeviceT.tuner$get(getDeviceMemorySegment()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the selected tuner(s)
|
||||
*/
|
||||
public void setTunerSelect(TunerSelect tunerSelect)
|
||||
{
|
||||
sdrplay_api_DeviceT.tuner$set(getDeviceMemorySegment(), tunerSelect.getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
* RSPduo mode
|
||||
*/
|
||||
public RspDuoMode getRspDuoMode()
|
||||
{
|
||||
return getDeviceStruct().getRspDuoMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets RSPduo mode. Note this must be set before selecting the device for use.
|
||||
* @param mode to set
|
||||
* @throws SDRPlayException if the device has already been selected
|
||||
*/
|
||||
public void setRspDuoMode(RspDuoMode mode) throws SDRPlayException
|
||||
{
|
||||
if(isSelected())
|
||||
{
|
||||
throw new SDRPlayException("RSPduo device is already selected. Mode can only be set/changed before the " +
|
||||
"device is selected for use.");
|
||||
}
|
||||
|
||||
getDeviceStruct().setRspDuoMode(mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sample rate when in master/slave mode
|
||||
*/
|
||||
public double getRspDuoSampleFrequency()
|
||||
{
|
||||
return getDeviceStruct().getRspDuoSampleFrequency();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the sample rate when the device is configured for master mode.
|
||||
* @param frequency
|
||||
*/
|
||||
public void setRspDuoSampleFrequency(double frequency) throws SDRPlayException
|
||||
{
|
||||
if(!getRspDuoMode().equals(RspDuoMode.MASTER))
|
||||
{
|
||||
throw new SDRPlayException("This method can only be used to set the overall sample rate when the RSPduo " +
|
||||
"device is configured for master mode.");
|
||||
}
|
||||
|
||||
getDeviceStruct().setRspDuoSampleFrequency(frequency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the decimation factor for the final sample rate.
|
||||
* @param decimation as an integer multiple of two (e.g. 1, 2, 4, 8)
|
||||
* @throws SDRPlayException if there is an error while setting decimation
|
||||
*/
|
||||
@Override
|
||||
public void setDecimation(Decimate decimation) throws SDRPlayException
|
||||
{
|
||||
if(getTunerSelect() == TunerSelect.TUNER_1)
|
||||
{
|
||||
getCompositeParameters().getControlAParameters().getDecimation().setDecimationFactor(decimation.getValue());
|
||||
getCompositeParameters().getControlAParameters().getDecimation().setEnabled(decimation.isEnabled());
|
||||
update(getTunerSelect(), UpdateReason.CONTROL_DECIMATION);
|
||||
}
|
||||
else if(getTunerSelect() == TunerSelect.TUNER_2)
|
||||
{
|
||||
getCompositeParameters().getControlBParameters().getDecimation().setDecimationFactor(decimation.getValue());
|
||||
getCompositeParameters().getControlBParameters().getDecimation().setEnabled(decimation.isEnabled());
|
||||
update(getTunerSelect(), UpdateReason.CONTROL_DECIMATION);
|
||||
}
|
||||
else if(getTunerSelect() == TunerSelect.TUNER_BOTH)
|
||||
{
|
||||
//Dual-synchronized tuner mode ... let the parent Device class set the value
|
||||
super.setDecimation(decimation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the IF mode when tuner 2 is selected in single-tuner mode.
|
||||
* @param ifMode to set
|
||||
*/
|
||||
public void setIfModeTuner2(IfMode ifMode)
|
||||
{
|
||||
getCompositeParameters().getTunerBParameters().setIfMode(ifMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the LO mode when tuner 2 is selected in single-tuner mode.
|
||||
* @param loMode to set
|
||||
*/
|
||||
public void setLoModeTuner2(LoMode loMode)
|
||||
{
|
||||
getCompositeParameters().getTunerBParameters().setLoMode(loMode);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("SDRPplay Device").append("\n");
|
||||
sb.append("\tType: " + getDeviceType()).append("\n");
|
||||
sb.append("\tSerial Number: " + getSerialNumber()).append("\n");
|
||||
sb.append("\tTuner: " + getTunerSelect()).append("\n");
|
||||
sb.append("\tRSP Duo: " + getRspDuoMode()).append("\n");
|
||||
sb.append("\tRSP Duo Sample Rate: " + getRspDuoSampleFrequency()).append("\n");
|
||||
sb.append("\tSelected: " + isSelected());
|
||||
if(hasCompositeParameters())
|
||||
{
|
||||
sb.append("\t").append(getCompositeParameters());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_h;
|
||||
|
||||
/**
|
||||
* RSP-Duo Mode
|
||||
*/
|
||||
public enum RspDuoMode
|
||||
{
|
||||
SINGLE_TUNER(sdrplay_api_h.sdrplay_api_RspDuoMode_Single_Tuner(), "SINGLE TUNER"),
|
||||
DUAL_TUNER(sdrplay_api_h.sdrplay_api_RspDuoMode_Dual_Tuner(), "DUAL TUNER"),
|
||||
MASTER(sdrplay_api_h.sdrplay_api_RspDuoMode_Master(), "MASTER"),
|
||||
SLAVE(sdrplay_api_h.sdrplay_api_RspDuoMode_Slave(), "SLAVE"),
|
||||
UNKNOWN(sdrplay_api_h.sdrplay_api_RspDuoMode_Unknown(), "UNKNOWN");
|
||||
|
||||
private int mValue;
|
||||
private String mDescription;
|
||||
|
||||
RspDuoMode(int value, String description)
|
||||
{
|
||||
mValue = value;
|
||||
mDescription = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numeric value
|
||||
*/
|
||||
public int getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the entry from a return code
|
||||
* @param value to lookup
|
||||
* @return entry or UKNOWN if the code is not recognized
|
||||
*/
|
||||
public static RspDuoMode fromValue(int value)
|
||||
{
|
||||
for(RspDuoMode status: RspDuoMode.values())
|
||||
{
|
||||
if(status.getValue() == value)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.UpdateReason;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.ControlParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.device.RspDuoDeviceParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.RspDuoTunerParameters;
|
||||
|
||||
/**
|
||||
* RSPduo Tuner
|
||||
*/
|
||||
public abstract class RspDuoTuner extends RspTuner<RspDuoDeviceParameters, RspDuoTunerParameters>
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param device parent for this tuner
|
||||
* @param sdrplay api
|
||||
* @param tunerSelect to specify which tuner
|
||||
* @param deviceParameters for this device
|
||||
* @param tunerParameters for this tuner
|
||||
* @param controlParameters for this device
|
||||
*/
|
||||
public RspDuoTuner(Device device, SDRplay sdrplay, TunerSelect tunerSelect, RspDuoDeviceParameters deviceParameters,
|
||||
RspDuoTunerParameters tunerParameters, ControlParameters controlParameters)
|
||||
{
|
||||
super(device, sdrplay, tunerSelect, deviceParameters, tunerParameters, controlParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the RF notch is enabled
|
||||
*/
|
||||
public boolean isRFNotch()
|
||||
{
|
||||
return getTunerParameters().isRfNotch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the RF notch
|
||||
* @param enable setting
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setRfNotch(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().setRfNotch(enable);
|
||||
update(UpdateReason.RSP_DUO_RF_NOTCH_CONTROL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the RF DAB notch is enabled
|
||||
*/
|
||||
public boolean isRfDabNotch()
|
||||
{
|
||||
return getTunerParameters().isRfDabNotch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the RF DAB notch
|
||||
* @param enable value
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setRfDabNotch(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().setRfDabNotch(enable);
|
||||
update(UpdateReason.RSP_DUO_RF_DAB_NOTCH_CONTROL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the external reference output is enabled.
|
||||
*/
|
||||
public boolean isExternalReferenceOutput()
|
||||
{
|
||||
return getDeviceParameters().isExternalReferenceOutput();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the external reference output
|
||||
* @param enable value
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setExternalReferenceOutput(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getDeviceParameters().setExternalReferenceOutput(enable);
|
||||
update(UpdateReason.RSP_DUO_EXT_REF_CONTROL);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.UpdateReason;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.ControlParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.device.RspDuoDeviceParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.RspDuoAmPort;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.RspDuoTunerParameters;
|
||||
|
||||
/**
|
||||
* RSPduo Tuner 1
|
||||
*/
|
||||
public class RspDuoTuner1 extends RspDuoTuner
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
*
|
||||
* @param device parent for this tuner
|
||||
* @param sdrplay api
|
||||
* @param deviceParameters for this device
|
||||
* @param tunerParameters for this tuner
|
||||
* @param controlParameters for this device
|
||||
*/
|
||||
public RspDuoTuner1(Device device, SDRplay sdrplay, RspDuoDeviceParameters deviceParameters,
|
||||
RspDuoTunerParameters tunerParameters, ControlParameters controlParameters)
|
||||
{
|
||||
super(device, sdrplay, TunerSelect.TUNER_1, deviceParameters, tunerParameters, controlParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates which AM port is selected
|
||||
*/
|
||||
public RspDuoAmPort getAmPort()
|
||||
{
|
||||
return getTunerParameters().getTuner1AmPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the AM port to use
|
||||
* @param port to use
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setAmPort(RspDuoAmPort port) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().setTuner1AmPort(port);
|
||||
update(UpdateReason.RSP_DUO_AM_PORT_SELECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the AM notch is enabled
|
||||
*/
|
||||
public boolean isAmNotch()
|
||||
{
|
||||
return getTunerParameters().isTuner1AmNotch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the AM notch
|
||||
* @param enable for the notch
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setAmNotch(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().setTuner1AmNotch(enable);
|
||||
update(UpdateReason.RSP_DUO_TUNER_1_AM_NOTCH_CONTROL);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.UpdateReason;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.ControlParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.device.RspDuoDeviceParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.RspDuoTunerParameters;
|
||||
|
||||
/**
|
||||
* RSPduo Tuner 2
|
||||
*/
|
||||
public class RspDuoTuner2 extends RspDuoTuner
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
*
|
||||
* @param device parent for this tuner
|
||||
* @param sdrplay api
|
||||
* @param deviceParameters for this device
|
||||
* @param tunerParameters for this tuner
|
||||
* @param controlParameters for this device
|
||||
*/
|
||||
public RspDuoTuner2(Device device, SDRplay sdrplay, RspDuoDeviceParameters deviceParameters,
|
||||
RspDuoTunerParameters tunerParameters, ControlParameters controlParameters)
|
||||
{
|
||||
super(device, sdrplay, TunerSelect.TUNER_2, deviceParameters, tunerParameters, controlParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the Bias-T is enabled
|
||||
*/
|
||||
public boolean isBiasT()
|
||||
{
|
||||
return getTunerParameters().isBiasT();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the Bias-T
|
||||
* @param enable value
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setBiasT(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().setBiasT(enable);
|
||||
update(UpdateReason.RSP_DUO_BIAS_T_CONTROL);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.composite.RspDxCompositeParameters;
|
||||
|
||||
/**
|
||||
* RSPdx Device
|
||||
*/
|
||||
public class RspDxDevice extends Device<RspDxCompositeParameters, RspDxTuner>
|
||||
{
|
||||
private RspDxTuner mTuner1;
|
||||
|
||||
/**
|
||||
* Constructs an SDRPlay RSPdx device from the foreign memory segment
|
||||
*
|
||||
* @param sdrPlay api instance that created this device
|
||||
* @param deviceStruct parser
|
||||
*/
|
||||
RspDxDevice(SDRplay sdrPlay, IDeviceStruct deviceStruct)
|
||||
{
|
||||
super(sdrPlay, deviceStruct);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public RspDxTuner getTuner() throws SDRPlayException
|
||||
{
|
||||
if(!isSelected())
|
||||
{
|
||||
throw new SDRPlayException("Device must be selected before accessing the tuner");
|
||||
}
|
||||
|
||||
if(mTuner1 == null)
|
||||
{
|
||||
mTuner1 = new RspDxTuner(RspDxDevice.this, getAPI(), getTunerSelect(),
|
||||
getCompositeParameters().getDeviceParameters(), getCompositeParameters().getTunerAParameters(),
|
||||
getCompositeParameters().getControlAParameters());
|
||||
}
|
||||
|
||||
return mTuner1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.UpdateReason;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.ControlParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.device.RspDxDeviceParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.HdrModeBandwidth;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.RspDxAntenna;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.RspDxTunerParameters;
|
||||
|
||||
/**
|
||||
* RSPdx Tuner
|
||||
*/
|
||||
public class RspDxTuner extends RspTuner<RspDxDeviceParameters, RspDxTunerParameters>
|
||||
{
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param device parent for this tuner
|
||||
* @param sdrplay api
|
||||
* @param tunerSelect to specify which tuner
|
||||
* @param deviceParameters for this device
|
||||
* @param tunerParameters for this tuner
|
||||
* @param controlParameters for this device
|
||||
*/
|
||||
public RspDxTuner(Device device, SDRplay sdrplay, TunerSelect tunerSelect, RspDxDeviceParameters deviceParameters,
|
||||
RspDxTunerParameters tunerParameters, ControlParameters controlParameters)
|
||||
{
|
||||
super(device, sdrplay, tunerSelect, deviceParameters, tunerParameters, controlParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if HDR mode is enabled
|
||||
*/
|
||||
public boolean isHdrMode()
|
||||
{
|
||||
return getDeviceParameters().isHdr();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables HDR mode
|
||||
* @param enable mode
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setHdrMode(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getDeviceParameters().setHdr(enable);
|
||||
update(UpdateReason.EXTENSION_RSP_DX_HDR_ENABLE);
|
||||
}
|
||||
|
||||
/**
|
||||
* HDR mode bandwidth
|
||||
*/
|
||||
public HdrModeBandwidth getHdrModeBandwidth()
|
||||
{
|
||||
return getTunerParameters().getHdrModeBandwidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets HDR mode bandwidth
|
||||
* @param bandwidth to select
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setHdrModeBandwidth(HdrModeBandwidth bandwidth) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().setHdrModeBandwidth(bandwidth);
|
||||
update(UpdateReason.EXTENSION_RSP_DX_HDR_BANDWIDTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the RF notch is enabled
|
||||
*/
|
||||
public boolean isRfNotch()
|
||||
{
|
||||
return getDeviceParameters().isRfNotch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the RF notch
|
||||
* @param enable setting
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setRfNotch(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getDeviceParameters().setRfNotch(enable);
|
||||
update(UpdateReason.EXTENSION_RSP_DX_RF_NOTCH_CONTROL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the RF DAB notch is enabled
|
||||
*/
|
||||
public boolean isRfDabNotch()
|
||||
{
|
||||
return getDeviceParameters().isRfDabNotch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the RF DAB notch
|
||||
* @param enable value
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setRfDabNotch(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getDeviceParameters().setRfDabNotch(enable);
|
||||
update(UpdateReason.EXTENSION_RSP_DX_RF_DAB_NOTCH_CONTROL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if the Bias-T is enabled
|
||||
*/
|
||||
public boolean isBiasT()
|
||||
{
|
||||
return getDeviceParameters().isBiasT();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables the Bias-T
|
||||
* @param enable value
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setBiasT(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getDeviceParameters().setBiasT(enable);
|
||||
update(UpdateReason.EXTENSION_RSP_DX_BIAS_T_CONTROL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Antenna selection
|
||||
*/
|
||||
public RspDxAntenna getAntenna()
|
||||
{
|
||||
return getDeviceParameters().getRspDxAntenna();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the antenna selection
|
||||
* @param antenna to select
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setAntenna(RspDxAntenna antenna) throws SDRPlayException
|
||||
{
|
||||
getDeviceParameters().setRspDxAntenna(antenna);
|
||||
update(UpdateReason.EXTENSION_RSP_DX_ANTENNA_CONTROL);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,419 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.UpdateReason;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.async.AsyncUpdateFuture;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.AgcMode;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.ControlParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.device.DeviceParameters;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.Bandwidth;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.Gain;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.GainReduction;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.IfMode;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.LoMode;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.TunerParameters;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Abstract RSP device tuner
|
||||
* @param <T> RSP device implementation
|
||||
*/
|
||||
public abstract class RspTuner<D extends DeviceParameters, T extends TunerParameters>
|
||||
{
|
||||
private static final Logger mLog = LoggerFactory.getLogger(RspTuner.class);
|
||||
private final SDRplay mSDRplay;
|
||||
private final Device mDevice;
|
||||
private final TunerSelect mTunerSelect;
|
||||
private final D mDeviceParameters;
|
||||
private final T mTunerParameters;
|
||||
private final ControlParameters mControlParameters;
|
||||
|
||||
private GainReduction mGainReduction;
|
||||
|
||||
RspTuner(Device device, SDRplay sdrplay, TunerSelect tunerSelect, D deviceParameters, T tunerParameters,
|
||||
ControlParameters controlParameters)
|
||||
{
|
||||
mDevice = device;
|
||||
mSDRplay = sdrplay;
|
||||
mTunerSelect = tunerSelect;
|
||||
mDeviceParameters = deviceParameters;
|
||||
mTunerParameters = tunerParameters;
|
||||
mControlParameters = controlParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* SDRplay API
|
||||
*/
|
||||
private SDRplay getSDRplay()
|
||||
{
|
||||
return mSDRplay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parent device for this tuner
|
||||
*/
|
||||
private Device getDevice()
|
||||
{
|
||||
return mDevice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selected tuner
|
||||
*/
|
||||
public TunerSelect getTunerSelect()
|
||||
{
|
||||
return mTunerSelect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Device parameters
|
||||
*/
|
||||
protected D getDeviceParameters()
|
||||
{
|
||||
return mDeviceParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tuner parameters for the selected tuner
|
||||
*/
|
||||
public T getTunerParameters()
|
||||
{
|
||||
return mTunerParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control parameters for the selected tuner
|
||||
*/
|
||||
protected ControlParameters getControlParameters()
|
||||
{
|
||||
return mControlParameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for notifying the API that parameters for the device have been updated, when the device is
|
||||
* initialized.
|
||||
*
|
||||
* @param updateReasons indicating what has been updated
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
protected void update(UpdateReason... updateReasons) throws SDRPlayException
|
||||
{
|
||||
getDevice().update(getTunerSelect(), updateReasons);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method for notifying the device that a parameter for this tuner have been updated.
|
||||
*
|
||||
* Note: the asynchronous device event responses are limited to Frequency, Gain and Sample Rate. For example,
|
||||
* if you update the RSPduo DAB Notch parameter, it will generate a Gain change notification, so we submit
|
||||
* an async update for the DAB Notch, but anticipate a Gain update response.
|
||||
*
|
||||
* @param updateReason indicating what has been updated
|
||||
* @param expectedResponse that will be received indicating that the async operation is completed.
|
||||
*/
|
||||
protected AsyncUpdateFuture updateAsync(UpdateReason updateReason, UpdateReason expectedResponse)
|
||||
{
|
||||
return getDevice().updateAsync(getTunerSelect(), updateReason, expectedResponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Current tuner bandwidth
|
||||
*/
|
||||
public Bandwidth getBandwidth()
|
||||
{
|
||||
return getTunerParameters().getBandwidth();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets tuner bandwidth
|
||||
* @param bandwidth to apply
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setBandwidth(Bandwidth bandwidth) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().setBandwidth(bandwidth);
|
||||
update(UpdateReason.TUNER_BANDWIDTH_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Center frequency for the tuner
|
||||
*/
|
||||
public long getFrequency()
|
||||
{
|
||||
return (long) getTunerParameters().getRfFrequency().getFrequency();
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests to set the center frequency for the tuner asynchronously.
|
||||
*
|
||||
* Note: the API supports the notion of synchronous frequency updates, but in testing I found that you cannot
|
||||
* submit a second frequency change update request until a previously submitted frequency change update
|
||||
* operation had completed, otherwise it would generate a fail status. Therefore, this is method is strictly
|
||||
* an async operation.
|
||||
*
|
||||
* @param frequency in Hertz
|
||||
* @return future that can be monitored for completion of the set frequency operation.
|
||||
*/
|
||||
public AsyncUpdateFuture setFrequency(long frequency)
|
||||
{
|
||||
try
|
||||
{
|
||||
getTunerParameters().getRfFrequency().setFrequency(frequency, false);
|
||||
updateGainReduction(frequency);
|
||||
return updateAsync(UpdateReason.TUNER_FREQUENCY_RF, UpdateReason.TUNER_FREQUENCY_RF);
|
||||
}
|
||||
catch(SDRPlayException se)
|
||||
{
|
||||
AsyncUpdateFuture future = new AsyncUpdateFuture(getTunerSelect(), UpdateReason.TUNER_FREQUENCY_RF,
|
||||
UpdateReason.TUNER_FREQUENCY_RF);
|
||||
future.setError(se);
|
||||
return future;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gain reduction in use for this device with the current RF frequency
|
||||
*/
|
||||
public GainReduction getGainReduction()
|
||||
{
|
||||
if(mGainReduction == null)
|
||||
{
|
||||
updateGainReduction(getFrequency());
|
||||
}
|
||||
|
||||
return mGainReduction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the gain reduction, if necessary, for the specified RF frequency
|
||||
*
|
||||
* @param frequency value
|
||||
*/
|
||||
private void updateGainReduction(long frequency)
|
||||
{
|
||||
if(mGainReduction == null || !mGainReduction.isValidFor(frequency))
|
||||
{
|
||||
mGainReduction = GainReduction.lookup(getDevice().getDeviceType(), frequency);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects a gain value index from the current gain reduction values
|
||||
*
|
||||
* @param index of the gain reduction values to use
|
||||
*/
|
||||
public void setGain(int index) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().getGain().setGain(getGainReduction(), index);
|
||||
update(UpdateReason.TUNER_GAIN_REDUCTION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the automatic gain contral (AGC) mode
|
||||
*
|
||||
* @param mode to set
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setAGC(AgcMode mode) throws SDRPlayException
|
||||
{
|
||||
getControlParameters().getAgc().setAgcMode(mode);
|
||||
update(UpdateReason.CONTROL_AGC);
|
||||
}
|
||||
|
||||
/**
|
||||
* AGC Mode
|
||||
*/
|
||||
public AgcMode getAGC()
|
||||
{
|
||||
return getControlParameters().getAgc().getAgcMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gain for the tuner.
|
||||
*/
|
||||
public Gain getGain()
|
||||
{
|
||||
return getTunerParameters().getGain();
|
||||
}
|
||||
|
||||
/**
|
||||
* Current gain index value.
|
||||
* @return current gain index value or -1 if the current gain setting does not match the possible gain reduction options.
|
||||
*/
|
||||
public int getGainIndex()
|
||||
{
|
||||
int gainDb = getGain().getGainReductionDb();
|
||||
return getGainReduction().getGainIndex(gainDb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables DC correction
|
||||
*
|
||||
* @param enable true or false
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setDCCorrection(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getControlParameters().getDcOffset().setDC(enable);
|
||||
update(UpdateReason.CONTROL_DC_OFFSET_IQ_IMBALANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables IQ imbalance correction
|
||||
*
|
||||
* @param enable true or false
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setIQCorrection(boolean enable) throws SDRPlayException
|
||||
{
|
||||
getControlParameters().getDcOffset().setIQ(enable);
|
||||
update(UpdateReason.CONTROL_DC_OFFSET_IQ_IMBALANCE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets or updates the parts per million (ppm) frequency correction
|
||||
*
|
||||
* @param ppm value
|
||||
* @throws SDRPlayException
|
||||
*/
|
||||
public AsyncUpdateFuture setPPM(double ppm) throws SDRPlayException
|
||||
{
|
||||
getDeviceParameters().setPPM(ppm);
|
||||
|
||||
//Note: async ppm updates effect both frequency and sample rate, so we expect the completion of the
|
||||
//operation will be first FREQUENCY and then SAMPLE RATE, so we watch for sample rate.
|
||||
return updateAsync(UpdateReason.DEVICE_PPM, UpdateReason.DEVICE_SAMPLE_RATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parts per million (PPM) frequency correction value
|
||||
*
|
||||
* @return ppm value
|
||||
*/
|
||||
public double getPPM()
|
||||
{
|
||||
return getDeviceParameters().getPPM();
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform synchronous update
|
||||
*
|
||||
* @param sampleNumber value
|
||||
* @param period value
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setSynchronousUpdate(int sampleNumber, int period) throws SDRPlayException
|
||||
{
|
||||
getDeviceParameters().getSynchronousUpdate().set(sampleNumber, period);
|
||||
update(UpdateReason.DEVICE_SYNC_UPDATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets device functions to default
|
||||
*
|
||||
* @param frequency to reset
|
||||
* @param sampleRate to reset
|
||||
* @param gain to reset
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void reset(boolean frequency, boolean sampleRate, boolean gain) throws SDRPlayException
|
||||
{
|
||||
getDeviceParameters().getResetFlags().resetGain(gain);
|
||||
getDeviceParameters().getResetFlags().resetFrequency(frequency);
|
||||
getDeviceParameters().getResetFlags().resetSampleRate(sampleRate);
|
||||
update(UpdateReason.DEVICE_RESET_FLAGS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the frequency.
|
||||
*
|
||||
* @param frequency true to reset
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void resetFrequency(boolean frequency) throws SDRPlayException
|
||||
{
|
||||
reset(frequency, false, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the sample rate.
|
||||
*
|
||||
* @param sampleRate true to reset
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void resetSampleRate(boolean sampleRate) throws SDRPlayException
|
||||
{
|
||||
reset(false, sampleRate, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the gain (reduction).
|
||||
*
|
||||
* @param gain true to reset
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void resetGain(boolean gain) throws SDRPlayException
|
||||
{
|
||||
reset(false, false, gain);
|
||||
}
|
||||
|
||||
/**
|
||||
* IF mode (type)
|
||||
*/
|
||||
public IfMode getIfMode()
|
||||
{
|
||||
return getTunerParameters().getIfMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the IF mode (type)
|
||||
* @param mode to set
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setIfMode(IfMode mode) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().setIfMode(mode);
|
||||
update(UpdateReason.TUNER_IF_TYPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Oscillator (LO) mode
|
||||
* @return mode
|
||||
*/
|
||||
public LoMode getLoMode()
|
||||
{
|
||||
return getTunerParameters().getLoMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Local Oscillator (LO) mode
|
||||
* @param mode to set
|
||||
* @throws SDRPlayException if there is an error
|
||||
*/
|
||||
public void setLoMode(LoMode mode) throws SDRPlayException
|
||||
{
|
||||
getTunerParameters().setLoMode(mode);
|
||||
update(UpdateReason.TUNER_LO_MODE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_h;
|
||||
|
||||
/**
|
||||
* Tuner Select
|
||||
*/
|
||||
public enum TunerSelect
|
||||
{
|
||||
TUNER_1(sdrplay_api_h.sdrplay_api_Tuner_A(), "TUNER 1"),
|
||||
TUNER_2(sdrplay_api_h.sdrplay_api_Tuner_B(), "TUNER 2"),
|
||||
TUNER_BOTH(sdrplay_api_h.sdrplay_api_Tuner_Both(), "TUNER 1 & 2"),
|
||||
NEITHER(sdrplay_api_h.sdrplay_api_Tuner_Neither(), "NEITHER");
|
||||
|
||||
private int mValue;
|
||||
private String mDescription;
|
||||
|
||||
TunerSelect(int value, String description)
|
||||
{
|
||||
mValue = value;
|
||||
mDescription = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numeric value
|
||||
*/
|
||||
public int getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the entry from a return code
|
||||
* @param value to lookup
|
||||
* @return entry or NEITHER if the code is not recognized
|
||||
*/
|
||||
public static TunerSelect fromValue(int value)
|
||||
{
|
||||
for(TunerSelect status: TunerSelect.values())
|
||||
{
|
||||
if(status.getValue() == value)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return NEITHER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.device;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.SDRplay;
|
||||
|
||||
/**
|
||||
* Unknown or Unrecognized SDRplay Device
|
||||
*/
|
||||
public class UnknownDevice extends Device
|
||||
{
|
||||
/**
|
||||
* Constructs an Unknown SDRPlay device from the foreign memory segment
|
||||
*
|
||||
* @param sdrPlay api instance that created this device
|
||||
* @param deviceStruct parser
|
||||
*/
|
||||
UnknownDevice(SDRplay sdrPlay, IDeviceStruct deviceStruct)
|
||||
{
|
||||
super(sdrPlay, deviceStruct);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RspTuner getTuner() throws SDRPlayException
|
||||
{
|
||||
throw new SDRPlayException("Unrecognized device type. Cannot construct tuner");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.error;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_h;
|
||||
|
||||
/**
|
||||
* Debug Level
|
||||
*/
|
||||
public enum DebugLevel
|
||||
{
|
||||
DISABLE(sdrplay_api_h.sdrplay_api_DbgLvl_Disable(), "DISABLE"),
|
||||
VERBOSE(sdrplay_api_h.sdrplay_api_DbgLvl_Verbose(), "VERBOSE"),
|
||||
WARNING(sdrplay_api_h.sdrplay_api_DbgLvl_Warning(), "WARNING"),
|
||||
ERROR(sdrplay_api_h.sdrplay_api_DbgLvl_Error(), "ERROR"),
|
||||
MESSAGE(sdrplay_api_h.sdrplay_api_DbgLvl_Message(), "MESSAGE"),
|
||||
UNKNOWN(-1, "UNKNOWN");
|
||||
|
||||
private int mValue;
|
||||
private String mDescription;
|
||||
|
||||
DebugLevel(int value, String description)
|
||||
{
|
||||
mValue = value;
|
||||
mDescription = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Numeric value
|
||||
*/
|
||||
public int getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the entry from a return code
|
||||
* @param value to lookup
|
||||
* @return entry or UNKNOWN if the code is not recognized
|
||||
*/
|
||||
public static DebugLevel fromValue(int value)
|
||||
{
|
||||
for(DebugLevel status: DebugLevel.values())
|
||||
{
|
||||
if(status.getValue() == value)
|
||||
{
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return mDescription;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2023 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
|
||||
package io.github.dsheirer.source.tuner.sdrplay.api.error;
|
||||
|
||||
import io.github.dsheirer.source.tuner.sdrplay.api.v3_07.sdrplay_api_ErrorInfoT;
|
||||
import java.lang.foreign.MemorySegment;
|
||||
|
||||
/**
|
||||
* Error Information structure (sdrplay_api_ErrorInfoT)
|
||||
*/
|
||||
public class ErrorInformation
|
||||
{
|
||||
private String mFile;
|
||||
private String mFunction;
|
||||
private int mLine;
|
||||
private String mMessage;
|
||||
|
||||
/**
|
||||
* Constructs an instance from the foreign memory segment
|
||||
*/
|
||||
public ErrorInformation(MemorySegment memorySegment)
|
||||
{
|
||||
mFile = sdrplay_api_ErrorInfoT.file$slice(memorySegment).getUtf8String(0);
|
||||
mFunction = sdrplay_api_ErrorInfoT.function$slice(memorySegment).getUtf8String(0);
|
||||
mLine = sdrplay_api_ErrorInfoT.line$get(memorySegment);
|
||||
mMessage = sdrplay_api_ErrorInfoT.message$slice(memorySegment).getUtf8String(0);
|
||||
}
|
||||
|
||||
public String getFile()
|
||||
{
|
||||
return mFile;
|
||||
}
|
||||
|
||||
public String getFunction()
|
||||
{
|
||||
return mFunction;
|
||||
}
|
||||
|
||||
public int getLine()
|
||||
{
|
||||
return mLine;
|
||||
}
|
||||
|
||||
public String getMessage()
|
||||
{
|
||||
return mMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Error Information:").append("\n");
|
||||
sb.append("\t File: ").append(getFile()).append("\n");
|
||||
sb.append("\tFunction: ").append(getFunction()).append("\n");
|
||||
sb.append("\t Line: ").append(getLine()).append("\n");
|
||||
sb.append("\t Message: ").append(getMessage()).append("\n");
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user