diff --git a/ExtIO_NetSDR.sln b/ExtIO_NetSDR.sln new file mode 100644 index 0000000..3e06e9b --- /dev/null +++ b/ExtIO_NetSDR.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Express 2013 for Windows Desktop +VisualStudioVersion = 12.0.40629.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ExtIO_NetSDR", "ExtIO_NetSDR\ExtIO_NetSDR.vcxproj", "{F6D8A813-8B8D-46B5-B015-B5BE1BC467BE}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F6D8A813-8B8D-46B5-B015-B5BE1BC467BE}.Debug|Win32.ActiveCfg = Debug|Win32 + {F6D8A813-8B8D-46B5-B015-B5BE1BC467BE}.Debug|Win32.Build.0 = Debug|Win32 + {F6D8A813-8B8D-46B5-B015-B5BE1BC467BE}.Release|Win32.ActiveCfg = Release|Win32 + {F6D8A813-8B8D-46B5-B015-B5BE1BC467BE}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/ExtIO_NetSDR/ExtIO_NetSDR.vcxproj b/ExtIO_NetSDR/ExtIO_NetSDR.vcxproj new file mode 100644 index 0000000..d62e4e4 --- /dev/null +++ b/ExtIO_NetSDR/ExtIO_NetSDR.vcxproj @@ -0,0 +1,124 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {F6D8A813-8B8D-46B5-B015-B5BE1BC467BE} + Win32Proj + ExtIO_NetSDR + ExtIO_RFspaceNetSDR + + + + DynamicLibrary + true + v120_xp + Unicode + + + DynamicLibrary + false + v120_xp + true + Unicode + + + + + + + + + + + + + true + + + false + ../../clsocket/src;../../tinythreadpp/source;$(IncludePath) + + + + + + Level3 + Disabled + WIN32;_DEBUG;_WINDOWS;_USRDLL;EXTIO_NETSDR_EXPORTS;%(PreprocessorDefinitions) + + + Windows + true + Ws2_32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_WINDOWS;_USRDLL;EXTIO_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + false + Speed + MultiThreaded + false + true + + + Windows + false + true + true + 2018.0 + ..\src\ExtIO_RFspaceNetSDR.def + /PDBSTRIPPED + false + Ws2_32.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ExtIO_NetSDR/ExtIO_NetSDR.vcxproj.filters b/ExtIO_NetSDR/ExtIO_NetSDR.vcxproj.filters new file mode 100644 index 0000000..ffc63cc --- /dev/null +++ b/ExtIO_NetSDR/ExtIO_NetSDR.vcxproj.filters @@ -0,0 +1,95 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Source Files + + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + \ No newline at end of file diff --git a/README.md b/README.md index 2b18dee..b1aa7e2 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # ExtIO_RFspaceNetSDR Winrad/HDSDR plugin ExtIO for the RFspace NetSDR receiver + ## Software Defined Radio (SDR) receiver The hardware receiver was manufactured by RFspace. @@ -13,6 +14,7 @@ Network protocol specification for the interface is available at http://www.moetronix.com/svdownload.htm labeled 'NetSDR Interface Spec' + ## Origin of source code The ExtIO was developed at PROCITEC GmbH, @@ -24,3 +26,35 @@ They kindly gave permission to release the source code under LGPL (Lesser Genera Authors are Sebastian Balthasar and Hayati Ayguen. On questions, contact Hayati at h_ayguen@web.de + +## Step-by-step installation + +* install your favorite SDR software, e.g. HDSDR from http://www.hdsdr.de/ . +Other ExtIO compatible software like Winrad or Studio1 should also work. + +* download ExtIO_RFspaceNetSDR.DLL https://github.com/hayguen/ExtIO_RFspaceNetSDR/releases + +* copy downloaded file into your SDR software's installation directory (default=C:\Program Files (x86)\HDSDR). +Do NOT try to unzip directly into this directory! Because of Windows' user rights management this will fail. Unzip somewhere else first, then copy it to the installation directory. + +* exit and restart SDR software and select ExtIO_RFspaceNetSDR.DLL if demanded + + +## Compilation notes + +Besides cloning this repository, you also need to clone following libraries from same directory: + +* https://github.com/hayguen/tinythreadpp for threading + +* https://github.com/hayguen/clsocket for tcp/ip socket communication + +Microsoft Visual Studio Express 2013 (MSVC) IDE is used for compilation. +Other compiler should work, when adding suitable project files or fixing CMakeLists.txt. + + +## Status + +Compiles. In test. + +ExtIO control GUI for configuration is missing! To be implemented .. + diff --git a/src/ExtIO_Logging.cpp b/src/ExtIO_Logging.cpp new file mode 100644 index 0000000..25d8e3e --- /dev/null +++ b/src/ExtIO_Logging.cpp @@ -0,0 +1,12 @@ + +#include "ExtIO_Logging.h" + +// error message, with "const char*" in IQdata, +// intended for a log file AND a message box +// for messages extHw_MSG_* + +pfnExtIOCallback gpfnExtIOCallbackPtr = nullptr; + +char acExtioMsg[1024] = { 0 }; +bool SDRsupportsLogging = false; + diff --git a/src/ExtIO_Logging.h b/src/ExtIO_Logging.h new file mode 100644 index 0000000..4123a67 --- /dev/null +++ b/src/ExtIO_Logging.h @@ -0,0 +1,58 @@ +#pragma once + +#include "LC_ExtIO_Types.h" + +#ifdef _MSC_VER + #pragma warning(disable : 4996) + #define snprintf _snprintf +#endif + +/* ExtIO Callback */ +extern pfnExtIOCallback gpfnExtIOCallbackPtr; + +// error message, with "const char*" in IQdata, +// intended for a log file AND a message box +// for messages extHw_MSG_* + +extern char acExtioMsg[1024]; +extern bool SDRsupportsLogging; + + +#define SDRLOGTXT( A, TEXT ) \ + do { \ + if ( gpfnExtIOCallbackPtr && SDRsupportsLogging ) \ + gpfnExtIOCallbackPtr(-1, A, 0, TEXT ); \ + } while (0) + +// optional after calling gpfnExtIOCallbackPtr() .. +// if (extHw_MSG_ERRDLG == A) \ +// setStatusCB(TEXT, true); \ + + +#define SDRLOG( A, TEXTFMT, ... ) \ + do { \ + if ( gpfnExtIOCallbackPtr && SDRsupportsLogging ) \ + { \ + snprintf(acExtioMsg, 1023, TEXTFMT, ##__VA_ARGS__); \ + gpfnExtIOCallbackPtr(-1, A, 0, acExtioMsg ); \ + } \ + } while (0) + + +// for compatibility with PROCITEC code .. +// translate log level macros and implement LOG_PRO() macro .. similar to SDRLOG + +#define LOG_ERROR extHw_MSG_ERROR +#define LOG_PROTOCOL extHw_MSG_WARNING +#define LOG_NORMAL extHw_MSG_LOG +#define LOG_DEBUG extHw_MSG_DEBUG + +#define LOG_PRO( A, TEXTFMT, ... ) \ + do { \ + if ( gpfnExtIOCallbackPtr && SDRsupportsLogging ) \ + { \ + snprintf(acExtioMsg, 1023, TEXTFMT, ##__VA_ARGS__); \ + gpfnExtIOCallbackPtr(-1, A, 0, acExtioMsg ); \ + } \ + } while (0) + diff --git a/src/ExtIO_RFspaceNetSDR.cpp b/src/ExtIO_RFspaceNetSDR.cpp index 55a5555..3c93201 100644 --- a/src/ExtIO_RFspaceNetSDR.cpp +++ b/src/ExtIO_RFspaceNetSDR.cpp @@ -1,41 +1,32 @@ #define HWNAME "RFspace" #define HWMODEL "RFspace NetSDR" -#define SETTINGS_IDENTIFIER "RFspace NetSDR-0.1" - -#define IGNORE_CONF_DATA_DEST 0 - -#if IGNORE_CONF_DATA_DEST -// for test with "dump_tcp_forwarding.exe -v 58666" -#define DATA_DEST_IP "10.10.11.2" -#define DATA_DEST_PORT 50000 -#else -#define DATA_DEST_IP gacDataIP -#define DATA_DEST_PORT guDataPortNo -#endif +#define SETTINGS_IDENTIFIER "RFspace NetSDR-0.2" #include "ExtIO_RFspaceNetSDR.h" #include "rfspace_netsdr_receiver.h" -#include "common/base/baselib/base/ProLogging.h" -#include "foreign/extio/common/ExtIO_ProLogImpl.h" - +#include "ExtIO_Logging.h" //--------------------------------------------------------------------------- -#include "foreign/tinythread/tinythread.h" +#include "procitec_replacements.h" -#include "common/base/baselib/base/TimeMeasuring.h" -#include "common/base/baselib/base/ProStd.h" -#include "common/base/baselib/base/ProVersion.h" -#include "common/base/baselib/base/ProMakros.h" #if defined( WIN32 ) || defined( WIN64 ) -// #define WIN32_LEAN_AND_MEAN // Selten verwendete Teile der Windows-Header nicht einbinden. -#include + +#define WIN32_LEAN_AND_MEAN // Selten verwendete Teile der Windows-Header nicht einbinden. +#ifndef _WINSOCK2API_ +#define _WINSOCK2API_ +#define _WINSOCKAPI_ +#endif +#include #endif +#include "tinythread.h" + #include +#include #include #include #include @@ -205,36 +196,6 @@ static void ReceiverThreadProc( void* lpParameter ) } -//--------------------------------------------------------------------------- - -#if 0 -static void ReceptionStreamThreadProc( void* lpParameter ) -{ - (void)lpParameter; - - MonotonicClock oClock; - - uint64_t uTicksNew = 0; - uint64_t uLastReceivedPacket = oClock.msecs(); - - while ( 1 ) - { - if ( !gbDataStreamActivated ) - { - // wait for control - before binding UDP port, when using UDP protocol - tthread::this_thread::sleep_for( tthread::chrono::milliseconds( 1 ) ); - continue; - } - - gbBoundTcpDataPort = true; - while ( 1 ) - { - uLastReceivedPacket = oClock.msecs(); - } - } -} -#endif - //--------------------------------------------------------------------------- static void stopThread() @@ -669,6 +630,8 @@ enum class Setting { ID = 0 // enum values MUST be incremental without gaps! , CTRL_IP, CTRL_PORT // NetSDR IP/Port , DATA_IP, DATA_PORT // myPC Data IP/Port + , AVAIL_SRATES + , AVAIL_BWS , SAMPLERATE_IDX , RCV_FRQ , RCV_BW @@ -690,6 +653,8 @@ enum class Setting { int EXTIO_CALL ExtIoGetSetting( int idx, char* description, char* value ) { + int k; + size_t off; if (!gpoSettings) gpoSettings = new RFspaceNetReceiver::Settings(); @@ -710,7 +675,7 @@ int EXTIO_CALL ExtIoGetSetting( int idx, char* description, char* value ) return 0; case Setting::DATA_IP: - snprintf( description, 1024, "%s", "DATA IP: IP-Address of Client PC to receive streaming data" ); + snprintf( description, 1024, "%s", "DATA_IP: IP-Address of Client PC to receive streaming data" ); snprintf( value, 1024, "%s", gpoSettings->acDataIP ); return 0; case Setting::DATA_PORT: @@ -718,6 +683,32 @@ int EXTIO_CALL ExtIoGetSetting( int idx, char* description, char* value ) snprintf( value, 1024, "%d", gpoSettings->uDataPortNo ); return 0; + case Setting::AVAIL_SRATES: + snprintf(description, 1024, "info: %d available samplerates - per idx", RFspaceNetReceiver::miNumSamplerates ); + off = 0; + value[0] = 0; + for (k = 0; k < RFspaceNetReceiver::miNumSamplerates; ++k) + { + int w = snprintf(value + off, 1024 - off, "%s%d: %u", (k == 0 ? "":", "), k, unsigned(RFspaceNetReceiver::maiSamplerates[k]) ); + if (w < 0 || w >= (1024 - int(off))) + break; + off += w; + } + return 0; + + case Setting::AVAIL_BWS: + snprintf(description, 1024, "info: %d available bandwidths - per idx", RFspaceNetReceiver::miNumSamplerates); + off = 0; + value[0] = 0; + for (k = 0; k < RFspaceNetReceiver::miNumSamplerates; ++k) + { + int w = snprintf(value + off, 1024 - off, "%s%d: %u", (k == 0 ? "" : ", "), k, unsigned(RFspaceNetReceiver::maiBandwidths[k])); + if (w < 0 || w >= (1024 - int(off))) + break; + off += w; + } + return 0; + case Setting::SAMPLERATE_IDX: snprintf( description, 1024, "%s", "SampleRateIdx" ); snprintf( value, 1024, "%d", gpoSettings->iSampleRateIdx ); @@ -729,7 +720,7 @@ int EXTIO_CALL ExtIoGetSetting( int idx, char* description, char* value ) return 0; case Setting::RCV_BW: - snprintf( description, 1024, "%s", "bandwidth in Hz for Receiver: 10 / 25 / 50 / 80 / 100 / 200 / 400 / 500 / 800 / 1300 / 1600 kHz" ); + snprintf( description, 1024, "%s", "(last) bandwidth in Hz for Receiver" ); snprintf( value, 1024, "%d", gpoSettings->uiBandwidth ); return 0; @@ -739,7 +730,7 @@ int EXTIO_CALL ExtIoGetSetting( int idx, char* description, char* value ) return 0; case Setting::BITDEPTH_CHANGE_SMPRATE: - snprintf( description, 1024, "%s", "Samplerate at which bitdepth is being changed from 24 to 16 bit and vice verca." ); + snprintf( description, 1024, "%s", "Samplerate at which bitdepth is reduced from 24 to 16 bit. For samplerates <= value, you get 24 Bit, else 16 bit. From Specification: 1 333 333 Hz." ); snprintf( value, 1024, "%u", gpoSettings->iBitDepthThresSamplerate); return 0; @@ -754,12 +745,12 @@ int EXTIO_CALL ExtIoGetSetting( int idx, char* description, char* value ) return 0; case Setting::IS_VUHF_RANGE: - snprintf( description, 1024, "%s", "Is this reveiver in VUHG range ?" ); + snprintf( description, 1024, "%s", "Is this receiver in V/UHF range ?" ); snprintf( value, 1024, "%u", gpoSettings->bIsVUHFRange); return 0; case Setting::COMPATIBILITY_VALUE: - snprintf( description, 1024, "%s", "VUHF Compatibility Gain Level 0 ... 3" ); + snprintf( description, 1024, "%s", "V/UHF Compatibility Gain Level 0 ... 3" ); snprintf( value, 1024, "%u", gpoSettings->iCompatibilityValue); return 0; @@ -795,12 +786,55 @@ int EXTIO_CALL ExtIoGetSetting( int idx, char* description, char* value ) return -1; // ERROR } +static const char * trimmedIP(const char * value, const char * logText) +{ + static char acBuf[1024]; + char * pBlockStart[4] = { 0, 0, 0, 0 }; + int k = 0; + + // to first digit + while (value[0] && !isdigit(value[0])) + ++value; + if (!value[0]) + { + LOG_PRO(LOG_ERROR, "Error in %s or empty IP address", logText); + return ""; + } + + for (int j = 1; j <= 4; ++j) + { + pBlockStart[j - 1] = &acBuf[k]; + + // j.th numeric block + while (value[0] && isdigit(value[0])) + acBuf[k++] = *value++; + + // '.' ? + if (j < 4) + { + if (value[0] == '.') + ++value; + else + { + LOG_PRO(LOG_ERROR, "Error in %s for %d.th numeric block!", logText, j); + return ""; + } + } + } + + // zero termination + acBuf[k++] = 0; + + return acBuf; +} + void EXTIO_CALL ExtIoSetSetting( int idx, const char* value ) { if (!gpoSettings) gpoSettings = new RFspaceNetReceiver::Settings(); + int64_t tempI64; int tempInt; // now we know that there's no need to save our settings into some (.ini) file, // what won't be possible without admin rights!!!, @@ -819,19 +853,22 @@ void EXTIO_CALL ExtIoSetSetting( int idx, const char* value ) // make identifier version specific??? - or not ==> never change order of idx! break; case Setting::CTRL_IP: - snprintf( gpoSettings->acCtrlIP, 64, "%s", value ); + snprintf(gpoSettings->acCtrlIP, 64, "%s", trimmedIP(value, "CTRL_IP")); break; case Setting::CTRL_PORT: tempInt = atoi( value ); gpoSettings->uCtrlPortNo = (uint16_t)( tempInt & 0xffff ); break; case Setting::DATA_IP: - snprintf( gpoSettings->acDataIP, 64, "%s", value ); + snprintf(gpoSettings->acDataIP, 64, "%s", trimmedIP(value, "DATA_IP")); break; case Setting::DATA_PORT: tempInt = atoi( value ); gpoSettings->uDataPortNo = (uint16_t)( tempInt & 0xffff ); break; + case Setting::AVAIL_SRATES: + case Setting::AVAIL_BWS: + break; case Setting::SAMPLERATE_IDX: gpoSettings->iSampleRateIdx = atoi( value ); break; @@ -848,10 +885,12 @@ void EXTIO_CALL ExtIoSetSetting( int idx, const char* value ) gpoSettings->iBitDepthThresSamplerate = atoi( value ); break; case Setting::BAND1_RANGE_MINFREQ: - gpoSettings->iBand_minFreq = atoi( value ); + gpoSettings->iBand_minFreq = atol( value ); break; case Setting::BAND1_RANGE_MAXFREQ: - gpoSettings->iBand_maxFreq = atoi( value ); + tempI64 = atol(value); + if (gpoSettings->iBand_minFreq < tempI64) // reject when min > max + gpoSettings->iBand_maxFreq = tempI64; break; case Setting::IS_VUHF_RANGE: gpoSettings->bIsVUHFRange = atoi( value ) ? true : false; @@ -904,7 +943,7 @@ void EXTIO_CALL ExtIoSDRInfo( int extSDRInfo, int additionalValue, void * additi case extSDR_supports_SampleFormats: break; case extSDR_supports_Logging: - gbUseProcitecEnums = false; + SDRsupportsLogging = true; break; default: ; } diff --git a/src/ExtIO_RFspaceNetSDR.h b/src/ExtIO_RFspaceNetSDR.h index fd5e93e..9484a2e 100644 --- a/src/ExtIO_RFspaceNetSDR.h +++ b/src/ExtIO_RFspaceNetSDR.h @@ -55,7 +55,7 @@ -#include "common/functions/receiverlib/LC_ExtIO_Types.h" +#include "LC_ExtIO_Types.h" EXTIO_API const char * EXTIO_CALL GetBuildInfo(); EXTIO_API const char * EXTIO_CALL GetExtIOVersion(); diff --git a/src/LC_ExtIO_Types.h b/src/LC_ExtIO_Types.h new file mode 100644 index 0000000..69d765e --- /dev/null +++ b/src/LC_ExtIO_Types.h @@ -0,0 +1,546 @@ +//--------------------------------------------------------------------------- + +#ifndef LC_ExtIO_TypesH +#define LC_ExtIO_TypesH + +// last modification: 2017-04-26 + +// specification based on http://www.sdradio.eu/weaksignals/bin/Winrad_Extio.pdf +// linked referenced from http://www.weaksignals.com/ + +// for C99 compiler just #include +// MS VC++ 2008 Express does not have stdint.h Try http://msinttypes.googlecode.com/svn/trunk/stdint.h +#include +// for other compilers you may try http://www.azillionmonkeys.com/qed/pstdint.h +// or try boost: http://www.boost.org/doc/libs/1_36_0/boost/cstdint.hpp + +/* + * I. INITIALIZATION + OPEN SEQUENCE + * ================================= + * ExtIoSDRInfo() + * optional: inform ExtIO of SDR software's supported features + * ExtIoSetSetting() + * optional: previously saved settings are delivered to ExtIO + * call once with idx -1 to sign ExtIO that this functionality is supported, + * so that ExtIO may inhibit loading/storing any .ini + * InitHW() + * mandatory: initialize ExtIO. May do nothing! + * VersionInfo() + * optional: delivers SDR program name and version to ExtIO. Allows to check if some necessary + * functional extension is (not) supported by SDR program + * GetAttenuators() + * optional: show ExtIO, that SDR program supports controlling RF Gain/Attenuator(s) + * you should prefer this over determining SDR program's capabilities over VersionInfo() + * ExtIoGetMGCs() + * optional: show ExtIO, that SDR program supports controlling IF Gain/Attenuator(s) + * you should prefer this over determining SDR program's capabilities over VersionInfo() + * SetCallback() + * mandatory: callback function pointer is given to ExtIO. ExtIO may inform SDR program of events + * using this callback interface and the extHWstatusT enums + * OpenHW() + * mandatory: prepare ExtIO for start .. or fail for any reason! + * + * + * II. START SEQUENCE + * ================== + * StartHW() + * mandatory: start processing + * + * + * III. WORK + * ========= + * SetHWLO() and many other functions ... + * + * + * IV. STOP SEQUENCE (== 'undo' of Start sequence) + * ================= + * StopHW() + * mandatory: start processing + * + * + * V. CLOSE SEQUENCE (== 'undo' of init + stop sequence) + * ================= + * ExtIoGetSetting() + * optional: get and save settings for next time. + * call ExtIoGetSetting() before CloseHW() to get correct settings. + * do not call without súccessful OpenHW() + * CloseHW() + * mandatory: close hardware. Processing is not started again (with StartHW), + * unless OpenHW() is called again + * this function is called only when prior OpenHW() was successful + * take care not to free already freed or never allocated resources + * + */ + +// function implemented by Winrad / HDSDR; see enum extHWstatusT below +// IQoffs is no longer used (HDSDR >= 2.75), if ever used by any ExtIO! +// DC offset correction can be done inside HDSDR +typedef int(__cdecl * pfnExtIOCallback) (int cnt, int status, float IQoffs, void *IQdata); + +// mandatory functions, which have to be implemented by ExtIO DLL +#define EXTIO_MAX_NAME_LEN 16 /* name is displayed in Winrad/HDSDR's menu */ +#define EXTIO_MAX_MODEL_LEN 16 /* model is not used */ +typedef bool (__stdcall * pfnInitHW) (char *name, char *model, int& hwtype); + // name: descriptive name of the hardware. + // Preferably not longer than about 16 characters, + // as it will be used in a Winrad menu + // model: model code of the hardware, + // or its Serial Number. + // Keep also this field not too long, + // for the same reason of the previous one + // hwtype: see enum extHWtypeT below + // return: true if everything went well + +typedef bool (__stdcall * pfnOpenHW) (void); + // return: true if everything went well + +typedef void (__stdcall * pfnCloseHW) (void); +typedef int (__stdcall * pfnStartHW) (long extLOfreq); + // return: An integer specifying how many I/Q pairs are returned + // by the DLL each time the callback function is invoked (see later). + // This information is used of course only when the input data + // are not coming from the sound card, but through the callback device. + // If the number is negative, that means that an error has occurred, + // Winrad interrupts the starting process and returns to the + // idle status. + // The number of I/Q pairs must be at least 512, or an integer + // multiple of that value, + +typedef void (__stdcall * pfnStopHW) (void); +typedef void (__stdcall * pfnSetCallback) (pfnExtIOCallback funcptr); +typedef int (__stdcall * pfnSetHWLO) (long extLOfreq); // see also SetHWLO64 + // return values: + // == 0: The function did complete without errors. + // < 0 (a negative number N): + // The specified frequency is lower than the minimum that + // the hardware is capable to generate. The absolute value + // of N indicates what is the minimum supported by the HW. + // > 0 (a positive number N): + // The specified frequency is greater than the maximum + // that the hardware is capable to generate. The value + // of N indicates what is the maximum supported by the HW. + +typedef int (__stdcall * pfnGetStatus) (void); + // This entry point is meant to allow the DLL to return a status + // information to Winrad, upon request. + // Presently it is never called by Winrad, though its existence + // is checked when the DLL is loaded. So it must implemented, + // even if in a dummy way. + // It is meant for future expansions, for complex HW that implement + // e.g. a preselector or some other controls other than a simple + // LO frequency selection. + // The return value is an integer that is application dependent. + +// optional functions, which can be implemented by ExtIO DLL +// for performance reasons prefer not implementing rather then implementing empty functions +// especially for RawDataReady +typedef long (__stdcall * pfnGetHWLO) (void); // see also GetHWLO64 +typedef long (__stdcall * pfnGetHWSR) (void); +typedef void (__stdcall * pfnRawDataReady) (long samprate, void *Ldata, void *Rdata, int numsamples); +typedef void (__stdcall * pfnShowGUI) (void); +typedef void (__stdcall * pfnHideGUI) (void); +typedef void (__stdcall * pfnSwitchGUI) (void); // new: switch visibility of GUI +typedef void (__stdcall * pfnTuneChanged) (long tunefreq); // see also TuneChanged64 +typedef long (__stdcall * pfnGetTune) (void); // see also GetTune64 +typedef void (__stdcall * pfnModeChanged) (char mode); +typedef char (__stdcall * pfnGetMode) (void); +typedef void (__stdcall * pfnIFLimitsChanged)(long lowfreq, long highfreq); // see also IFLimitsChanged64 +typedef void (__stdcall * pfnFiltersChanged) (int loCut, int hiCut, int pitch); // lo/hiCut relative to tuneFreq +typedef void (__stdcall * pfnMuteChanged) (bool muted); +typedef void (__stdcall * pfnGetFilters) (int& loCut, int& hiCut, int& pitch); + +// optional functions - extended for receivers with frequency range over 2147 MHz - used from HDSDR +// these functions 64 bit functions are prefered rather than using the 32 bit ones +// for other Winrad derivations you should additionally implement the above "usual" 32 bit functions +typedef int (__stdcall * pfnStartHW64) (int64_t extLOfreq); // "StartHW64" with HDSDR >= 2.14 +typedef int64_t (__stdcall * pfnSetHWLO64) (int64_t extLOfreq); +typedef int64_t (__stdcall * pfnGetHWLO64) (void); +typedef void (__stdcall * pfnTuneChanged64) (int64_t tunefreq); +typedef int64_t (__stdcall * pfnGetTune64) (void); +typedef void (__stdcall * pfnIFLimitsChanged64) (int64_t lowfreq, int64_t highfreq); + +// optional functions - extended for high precision +typedef int (__stdcall * pfnStartHW_dbl) (double extLOfreq); +typedef double (__stdcall * pfnSetHWLO_dbl) (double extLOfreq); +typedef double (__stdcall * pfnGetHWLO_dbl) (void); +typedef void (__stdcall * pfnTuneChanged_dbl)(double tunefreq); +typedef double (__stdcall * pfnGetTune_dbl) (void); +typedef void (__stdcall * pfnIFLimitsChanged_dbl) (double lowfreq, double highfreq); + + +// optional functions, which can be implemented by ExtIO DLL +// following functions may get called from HDSDR 2.13 and above + +// "VersionInfo" is called - when existing - after successful InitHW() +// with this information an ExtIO may check which extHWstatusT enums are properly processed from application +// this call shall no longer be used to determine features of the SDR +// use "ExtIoSDRInfo" for this purpose +typedef void (__stdcall * pfnVersionInfo) (const char * progname, int ver_major, int ver_minor); + + +// "GetAttenuators" allows HDSDR to display a knob or slider for Attenuation / Amplification +// see & use extHw_Changed_ATT enum if ATT can get changed by ExtIO dialog window or from hardware +#define EXTIO_MAX_ATT_GAIN_VALUES 128 +typedef int (__stdcall * pfnGetAttenuators) (int idx, float * attenuation); // fill in attenuation + // use positive attenuation levels if signal is amplified (LNA) + // use negative attenuation levels if signal is attenuated + // sort by attenuation: use idx 0 for highest attenuation / most damping + // this functions is called with incrementing idx + // - until this functions returns != 0, which means that all attens are already delivered +typedef int (__stdcall * pfnGetActualAttIdx)(void); // returns -1 on error +typedef int (__stdcall * pfnSetAttenuator) (int idx); // returns != 0 on error + +// see extHw_TX_Request/extHw_RX_Request enums below if modechange can get triggered from user / hardware +typedef int (__stdcall * pfnSetModeRxTx) (int modeRxTx); // see enum extHw_ModeRxTxT + +// preliminary TX function - not really tested!: lack of test hw +// status: +// 0: Samples with numIQsamples > 0 (=512) and non-NULL pointer interleavedIQ +// 1: Reset (to suspend/stop TX thread of HDSDR) with numIQsamples == 0 and interleavedIQ == NULL +// 2: Pause/Stop (buffer underrun) with numIQsamples == 0 and interleavedIQ == NULL +// 3: Continue (after buffer underrun) with numIQsamples == 0 and interleavedIQ == NULL +typedef void (__stdcall * pfnTxSamples) (int status, int numIQsamples, const short * interleavedIQ); + + +// (de)activate all bandpass filter to allow "bandpass undersampling" (with external analog bandpass filter) +// intended for future use: it may get set automatically depending on LO frequency and the "ExtIO Frequency Options" +// deactivation of bp/lp-filters when real LO (in HDSDR) is > ADC_Samplerate/2 in undersampling mode +typedef int (__stdcall * pfnDeactivateBP) (int deactivate); + // deactivate == 1 to deactivate all bandpass and lowpass filters of hardware + // deactivate == 0 to reactivate automatic bandpass selection depending on frequency + +// optional "ExtIoGetSrates" is for replacing the Soundcard Samplerate values in the Samplerate selection dialog +// by these values supported from the SDR hardware. +// see & use extHw_Changed_SampleRate enum ... and "GetHWSR". Enumeration API as with "GetAttenuators" +// intended for future use - actually not implemented/called +#define EXTIO_MAX_SRATE_VALUES 32 +typedef int (__stdcall * pfnExtIoGetSrates) (int idx, double * samplerate); // fill in possible samplerates + // this functions is called with incrementing idx + // - until this functions returns != 0, which means that all srates are already delivered +typedef int (__stdcall * pfnExtIoGetActualSrateIdx) (void); // returns -1 on error +typedef int (__stdcall * pfnExtIoSetSrate) (int idx); // returns != 0 on error + +// optional function to get 3dB bandwidth from samplerate +typedef long (__stdcall * pfnExtIoGetBandwidth) (int srate_idx); // returns <= 0 on error + +// optional function to get center (= IF frequency) of 3dB band in Hz - for non I/Q receivers with 0 center +typedef long (__stdcall * pfnExtIoGetBwCenter) (int srate_idx); // returns 0 on error, which is default + +// optional function to get AGC Mode: AGC_OFF (always agc_index = 0), AGC_SLOW, AGC_MEDIUM, AGC_FAST, ... +// this functions is called with incrementing idx +// - until this functions returns != 0, which means that all agc modes are already delivered +#define EXTIO_MAX_AGC_VALUES 16 +typedef int (__stdcall * pfnExtIoGetAGCs) (int agc_idx, char * text); // text limited to max 16 char +typedef int (__stdcall * pfnExtIoGetActualAGCidx)(void); // returns -1 on error +typedef int (__stdcall * pfnExtIoSetAGC) (int agc_idx); // returns != 0 on error +// optional: HDSDR >= 2.62 +typedef int (__stdcall * pfnExtIoShowMGC)(int agc_idx); // return 1, to continue showing MGC slider on AGC + // return 0, is default for not showing MGC slider + +// for AGC in AGC_OFF (agc_idx == 0), which is (M)anual (G)ain (C)ontrol +// sometimes referred as "IFgain" - as in SDR-14/IP +#define EXTIO_MAX_MGC_VALUES 128 +typedef int (__stdcall * pfnExtIoGetMGCs)(int mgc_idx, float * gain); // fill in gain + // sort by ascending gain: use idx 0 for lowest gain + // this functions is called with incrementing idx + // - until this functions returns != 0, which means that all gains are already delivered +typedef int (__stdcall * pfnExtIoGetActualMgcIdx) (void); // returns -1 on error +typedef int (__stdcall * pfnExtIoSetMGC) (int mgc_idx); // returns != 0 on error + + +// not used in HDSDR - for now +// optional function to get 3dB band of Preselectors +// this functions is called with incrementing idx +// - until this functions returns != 0, which means that all preselectors are already delivered +// ExtIoSetPresel() with idx = -1 to activate automatic preselector selection +// ExtIoSetPresel() with valid idx (>=0) deactivates automatic preselection +typedef int (__stdcall * pfnExtIoGetPresels) ( int idx, int64_t * freq_low, int64_t * freq_high ); +typedef int (__stdcall * pfnExtIoGetActualPreselIdx) ( void ); // returns -1 on error +typedef int (__stdcall * pfnExtIoSetPresel) ( int idx ); // returns != 0 on error + +// not used in HDSDR - for now +// optional function to get frequency ranges usable with SetHWLO(), +// f.e. the FUNcube Dongle Pro+ should deliver idx 0: low=0.15 high=250 MHz and idx 1: low=420 high=1900 MHz +// with a gap from 250MHz to 420 MHz. see http://www.funcubedongle.com/?page_id=1073 +// if extIO is told to set a not-supported frequency with SetHWLO(), then the extIO should callback with extHw_Changed_LO +// and set a new frequency, which is supported +// this functions is called with incrementing idx +// - until this functions returns != 0, which means that all frequency ranges are already delivered +typedef int (__stdcall * pfnExtIoGetFreqRanges) ( int idx, int64_t * freq_low, int64_t * freq_high ); + +// not used in HDSDR - for now +// optional function to get full samplerate of A/D Converter +// useful to know with direct samplers in bandpass undersampling mode +// example: Perseus = 80 000 000 ; SDR-14 = 66 666 667 +// return <= 0 if undersampling not supported (when preselectors not deactivatable) +typedef double (__stdcall * pfnExtIoGetAdcSrate) ( void ); + +// HDSDR >= 2.51 +// optional functions to receive and set all special receiver settings (for save/restore in application) +// allows application and profile specific settings. +// easy to handle without problems with newer Windows versions saving a .ini file below programs as non-admin-user +// Settings shall be zero-terminated C-Strings. +// example settings: USB-Identifier(for opening specific device), IP/Port, AGC, Srate, .. +// idx in 0 .. 999 => NOT more than 1000 values storable! +// description max 1024 char +// value max 1024 char +// these functions are called with incrementing idx: 0, 1, ... +// until ExtIoGetSetting() returns != 0, which means that all settings are already delivered +typedef int (__stdcall * pfnExtIoGetSetting) ( int idx, char * description, char * value ); // will be called (at least) before exiting application +typedef void (__stdcall * pfnExtIoSetSetting) ( int idx, const char * value ); // before calling InitHW() !!! + // there will be an extra call with idx = -1, if theses functions are supported by the SDR app + // suggestion: use index 0 as ExtIO identifier (save/check ExtIO name) to allow fast skipping of all following SetSetting calls + // when this identifier does not match + +// not used in HDSDR - for now +// handling of VFOs - see also extHw_Changed_VFO +// VFOindex is in 0 .. numVFO-1 +typedef void (__stdcall * pfnExtIoVFOchanged) ( int VFOindex, int numVFO, int64_t extLOfreq, int64_t tunefreq, char mode ); +typedef int (__stdcall * pfnExtIoGetVFOindex)( void ); // returns new VFOindex + + +// HDSDR > 2.70 + +// inform ExtIO on the features supported by the SDR application +typedef void (__stdcall * pfnExtIoSDRInfo)( int extSDRInfo, int additionalValue, void * additionalPtr ); + +// HDSDR > 2.76 + +// inform ExtIO for unhandled keypress events. Encoding as in extHw_Unhandled_KeyPress. +typedef void (__stdcall * pfnExtKeyPressEvent)( int modifier, int keycode ); + + + +// hwtype codes to be set with pfnInitHW +// note: "exthwUSBdataNN" don't need to be from USB. The keyword "USB" is just for historical reasons, +// which may get removed later .. +typedef enum +{ + exthwNone = 0 + , exthwSDR14 = 1 + , exthwSDRX = 2 + , exthwUSBdata16 = 3 // the hardware does its own digitization and the audio data are returned to Winrad + // via the callback device. Data must be in 16-bit (short) format, little endian. + // each sample occupies 2 bytes (=16 bits) with values from -2^15 to +2^15 -1 + , exthwSCdata = 4 // The audio data are returned via the (S)ound (C)ard managed by Winrad. The external + // hardware just controls the LO, and possibly a preselector, under DLL control. + , exthwUSBdata24 = 5 // the hardware does its own digitization and the audio data are returned to Winrad + // via the callback device. Data are in 24-bit integer format, little endian. + // each sample just occupies 3 bytes (=24 bits) with values from -2^23 to +2^23 -1 + , exthwUSBdata32 = 6 // the hardware does its own digitization and the audio data are returned to Winrad + // via the callback device. Data are in 32-bit integer format, little endian. + // each sample occupies 4 bytes (=32 bits) but with values from -2^23 to +2^23 -1 + , exthwUSBfloat32 = 7 // the hardware does its own digitization and the audio data are returned to Winrad + // via the callback device. Data are in 32-bit float format, little endian. + , exthwHPSDR = 8 // for HPSDR only! + + // HDSDR > 2.70 + , exthwUSBdataU8 = 9 // the hardware does its own digitization and the audio data are returned to Winrad + // via the callback device. Data must be in 8-bit (unsigned) format, little endian. + // intended for RTL2832U based DVB-T USB sticks + // each sample occupies 1 byte (=8 bit) with values from 0 to 255 + , exthwUSBdataS8 = 10// the hardware does its own digitization and the audio data are returned to Winrad + // via the callback device. Data must be in 8-bit (signed) format, little endian. + // each sample occupies 1 byte (=8 bit) with values from -128 to 127 + , exthwFullPCM32 = 11 // the hardware does its own digitization and the audio data are returned to Winrad + // via the callback device. Data are in 32-bit integer format, little endian. + // each sample occupies 4 bytes (=32 bits) with full range: from -2^31 to +2^31 -1 +} extHWtypeT; + +// status codes for pfnExtIOCallback; used when cnt < 0 +typedef enum +{ + // only processed/understood for SDR14 + extHw_Disconnected = 0 // SDR-14/IQ not connected or powered off + , extHw_READY = 1 // IDLE / Ready + , extHw_RUNNING = 2 // RUNNING => not disconnected + , extHw_ERROR = 3 // ?? + , extHw_OVERLOAD = 4 // OVERLOAD => not disconnected + + // for all extIO's + , extHw_Changed_SampleRate = 100 // sampling speed has changed in the external HW + , extHw_Changed_LO = 101 // LO frequency has changed in the external HW + , extHw_Lock_LO = 102 + , extHw_Unlock_LO = 103 + , extHw_Changed_LO_Not_TUNE = 104 // CURRENTLY NOT YET IMPLEMENTED + // LO freq. has changed, Winrad must keep the Tune freq. unchanged + // (must immediately call GetHWLO() ) + , extHw_Changed_TUNE = 105 // a change of the Tune freq. is being requested. + // Winrad must call GetTune() to know which value is wanted + , extHw_Changed_MODE = 106 // a change of demod. mode is being requested. + // Winrad must call GetMode() to know the new mode + , extHw_Start = 107 // The DLL wants Winrad to Start + , extHw_Stop = 108 // The DLL wants Winrad to Stop + , extHw_Changed_FILTER = 109 // a change in the band limits is being requested + // Winrad must call GetFilters() + + // Above status codes are processed with Winrad 1.32. + // All Winrad derivation like WRplus, WinradF, WinradHD and HDSDR should understand them, + // but these do not provide version info with VersionInfo(progname, ver_major, ver_minor). + + , extHw_Mercury_DAC_ON = 110 // enable audio output on the Mercury DAC when using the HPSDR + , extHw_Mercury_DAC_OFF = 111 // disable audio output on the Mercury DAC when using the HPSDR + , extHw_PC_Audio_ON = 112 // enable audio output on the PC sound card when using the HPSDR + , extHw_PC_Audio_OFF = 113 // disable audio output on the PC sound card when using the HPSDR + + , extHw_Audio_MUTE_ON = 114 // the DLL is asking Winrad to mute the audio output. Also see 153 + , extHw_Audio_MUTE_OFF = 115 // the DLL is asking Winrad to unmute the audio output. Also see 154 + + // Above status codes are processed with Winrad 1.33 and HDSDR + // Winrad 1.33 and HDSDR still do not provide their version with VersionInfo() + + + // Following status codes are processed when VersionInfo delivers + // 0 == strcmp(progname, "HDSDR") && ( ver_major > 2 || ( ver_major == 2 && ver_minor >= 13 ) ) + + // all extHw_XX_SwapIQ_YYY callbacks shall be reported after each OpenHW() call + , extHw_RX_SwapIQ_ON = 116 // additionaly swap IQ - this does not modify the menu point / user selection + , extHw_RX_SwapIQ_OFF = 117 // the user selected swapIQ is additionally applied + , extHw_TX_SwapIQ_ON = 118 // additionaly swap IQ - this does not modify the menu point / user selection + , extHw_TX_SwapIQ_OFF = 119 // the user selected swapIQ is additionally applied + + + // Following status codes (for I/Q transceivers) are processed when VersionInfo delivers + // 0 == strcmp(progname, "HDSDR") && ( ver_major > 2 || ( ver_major == 2 && ver_minor >= 13 ) ) + + , extHw_TX_Request = 120 // DLL requests TX mode / User pressed PTT + // exciter/transmitter must wait until SetModeRxTx() is called! + , extHw_RX_Request = 121 // DLL wants to leave TX mode / User released PTT + // exciter/transmitter must wait until SetModeRxTx() is called! + + , extHw_CW_Pressed = 122 // User pressed CW key + , extHw_CW_Released = 123 // User released CW key + , extHw_PTT_as_CWkey = 124 // handle extHw_TX_Request as extHw_CW_Pressed in CW mode + // and extHw_RX_Request as extHw_CW_Released + // for further CW options see 155 .. 159 + + , extHw_Changed_ATT = 125 // Attenuator changed => call GetActualAttIdx() + + + // Following status codes are processed when ExtIoSDRInfo() was called with extSDR_supports_SampleFormats + // following status codes to change sampleformat at runtime + , extHw_SampleFormat_PCMU8 = 126 // as 'exthwUSBdataU8': each sample 1 byte: 0 to 255 (Realtek RTL2832U) + , extHw_SampleFormat_PCM16 = 127 // as 'exthwUSBdata16': each sample 2 bytes: -2^15 to +2^15 -1 + , extHw_SampleFormat_PCM24 = 128 // as 'exthwUSBdata24': each sample 3 bytes: -2^23 to +2^23 -1 + , extHw_SampleFormat_PCM2432 = 129 // as 'exthwUSBdata32': each sample 4 bytes: -2^23 to +2^23 -1 !!! + , extHw_SampleFormat_FLT32 = 130 // as 'exthwUSBfloat32': 32-bit float format, little endian + , extHw_SampleFormat_PCMS8 = 146 // as 'exthwUSBdataS8': each sample 1 byte: -128 to 127 + , extHw_SampleFormat_PCM32 = 147 // as 'exthwFullPCM32': each sample 4 bytes: -2^31 to +2^31 -1 + + // following status codes to change channel mode at runtime + , extHw_RX_ChanMode_LEFT = 131 // left channel only + , extHw_RX_ChanMode_RIGHT = 132 // right channel only + , extHw_RX_ChanMode_SUM_LR = 133 // sum of left + right channel + , extHw_RX_ChanMode_I_Q = 134 // I/Q with left channel = Inphase and right channel = Quadrature + // last option set I/Q and clear internal swap as with extHw_RX_SwapIQ_OFF + , extHw_RX_ChanMode_Q_I = 135 // I/Q with right channel = Inphase and left channel = Quadrature + // last option set I/Q and internal swap as with extHw_RX_SwapIQ_ON + + , extHw_Changed_RF_IF = 136 // refresh selectable attenuators and Gains + // => starts calling GetAttenuators(), GetAGCs() & GetMGCs() + , extHw_Changed_SRATES = 137 // refresh selectable samplerates => starts calling GetSamplerates() + + // Following status codes are for 3rd Party Software, currently not implemented in HDSDR + , extHw_Changed_PRESEL = 138 // Preselector changed => call ExtIoGetActualPreselIdx() + , extHw_Changed_PRESELS = 139 // refresh selectable preselectors => start calling ExtIoGetPresels() + , extHw_Changed_AGC = 140 // AGC changed => call ExtIoGetActualAGCidx() + , extHw_Changed_AGCS = 141 // refresh selectable AGCs => start calling ExtIoGetAGCs() + , extHw_Changed_SETTINGS = 142 // settings changed, call ExtIoGetSetting() + , extHw_Changed_FREQRANGES = 143 // refresh selectable frequency ranges, call ExtIoGetFreqRanges() + + , extHw_Changed_VFO = 144 // refresh selectable VFO => starts calling ExtIoGetVFOindex() + + // Following status codes are processed when ExtIoSDRInfo() was called with extSDR_supports_MGC + // Following status codes are processed when VersionInfo delivers + // 0 == strcmp(progname, "HDSDR") && ( ver_major > 2 || ( ver_major == 2 && ver_minor >= 60 ) ) + , extHw_Changed_MGC = 145 // MGC changed => call ExtIoGetMGC() + + // 146, 147 are used above: extHw_SampleFormat_PCMS8, extHw_SampleFormat_PCM32 + + // Following status codes are processed when ExtIoSDRInfo() was called with extSDR_supports_Logging + , extHw_MSG_ERRDLG = 148 // error message, with "const char*" in IQdata, + // intended for a log file AND a message box + , extHw_MSG_ERROR = 149 // error message, for a log file - NO error dialog + , extHw_MSG_WARNING = 150 // warning + , extHw_MSG_LOG = 151 // log message + , extHw_MSG_DEBUG = 152 // debug message for development + + , extHw_Unhandled_KeyPress = 153 // ExtIO can forward unhandleed keypress-events to the SDR application: + // the keycodes are pointed in void *IQdata as int * array: + // array[0] contains the modifiers as bitset: + // 1 : Ctrl + // 2 : Shift + // 4 : Alt + // array[1] contains the keycode + + , extHw_Get_TX_PowerLevel = 154 // SDR app shall write xx into void * IQdata as .. + , extHw_Set_TX_PowerLevel = 155 // SDR app shall read/use .. from void * IQdata as .. + + , extHw_Mic_MUTE_ON = 156 // the DLL is asking HDSDR to mute the Mic input (for TX). Also see 114 + , extHw_Mic_MUTE_OFF = 157 // the DLL is asking HDSDR to unmute the Mic input (for TX). Also see 115 + // these Mic_MUTE do muting before having switched to TX mode. + + + //, see extHw_CW_Pressed (=122) / extHw_CW_Released (=123) + , extHw_Get_CW_Speed_CPM = 158 // SDR app shall write xx into void * IQdata as .. + , extHw_Set_CW_Speed_CPM = 159 // SDR app shall read/use .. from void * IQdata as .. + , extHw_CW_Dit_Pressed = 160 // user pressed Dit. Request HDSDR to generate tone of that length. + , extHw_CW_Dit_Released = 161 // user released Dit + , extHw_CW_Dah_Pressed = 162 // user pressed Dah. Request HDSDR to generate tone of that length. + , extHw_CW_Dah_Released = 163 // user released Dah + , extHw_CW_Ext_Keying_ON = 164 // Request HDSDR to generate the I/Q-CW tone all the time + // for external keying in the hardware. + // This will let HDSDR generate I/Q tone - when in CW mode - also in RX + // - independent CW keys are pressed or released! + , extHw_CW_Ext_Keying_OFF = 165 // deactivate external keying + + , extHw_CW_TX_SideTone_ON = 166 // activate CW sidetone output to RX-Output Soundcard + , extHw_CW_TX_SideTone_OFF = 167 // deactivate CW sidetone output + + + + // reserved for Bonito's ECAS messages: + // 0x0100 - 0x03FF = 256 - 1023 -> from ExtIO to SDR-App + // 0x2000 = 8192 -> ECAS/Windows messages to + + +} extHWstatusT; + +// codes for pfnSetModeRxTx: +typedef enum +{ + extHw_modeRX = 0 + , extHw_modeTX = 1 +} extHw_ModeRxTxT; + + +// codes for pfnExtIoSDRInfo +typedef enum +{ + extSDR_NoInfo = 0 // sign SDR features would be signed with subsequent calls + , extSDR_supports_Settings = 1 + , extSDR_supports_Atten = 2 // RF Attenuation / Gain may be set via pfnSetAttenuator() + , extSDR_supports_TX = 3 // pfnSetModeRxTx() may be called + , extSDR_controls_BP = 4 // pfnDeactivateBP() may be called + , extSDR_supports_AGC = 5 // pfnExtIoSetAGC() may be called + , extSDR_supports_MGC = 6 // IF Attenuation / Gain may be set via pfnExtIoSetMGC() + , extSDR_supports_PCMU8 = 7 // exthwUSBdataU8 is supported + , extSDR_supports_PCMS8 = 8 // exthwUSBdataS8 is supported + , extSDR_supports_PCM32 = 9 // exthwFullPCM32 is supported + , extSDR_supports_Logging = 10 // extHw_MSG_* is supported + , extSDR_supports_SampleFormats = 11 // extHw_SampleFormat_* is supported + , extSDR_supports_Keys = 12 // + , extSDR_supports_PowerLevel = 13 // + , extSDR_supports_Mic_Mute = 14 // + , extSDR_supports_CW_Units = 15 // speed, Dit/Dah + , extSDR_supports_CW_SideTone = 16 // + , extSDR_supports_Ext_CW_Keying = 17 // + +} extSDR_InfoT; + + +// macro to call callback function with just status extHWstatusT +#define EXTIO_STATUS_CHANGE( CB, STATUS ) CB( -1, STATUS, 0, NULL ) + +#endif /* LC_ExtIO_TypesH */ + diff --git a/src/procitec_replacements.cpp b/src/procitec_replacements.cpp new file mode 100644 index 0000000..55aa70a --- /dev/null +++ b/src/procitec_replacements.cpp @@ -0,0 +1,35 @@ + +#include "procitec_replacements.h" + +#ifndef _WINSOCK2API_ +#define _WINSOCK2API_ +#define _WINSOCKAPI_ +#endif +#include + +uint64_t currentMSecsSinceEpoch() +{ + // mostly from http://www.frenk.com/2009/12/convert-filetime-to-unix-timestamp/ + + SYSTEMTIME st; + GetSystemTime(&st); + FILETIME ft; + SystemTimeToFileTime(&st, &ft); + + LARGE_INTEGER date; + date.HighPart = ft.dwHighDateTime; + date.LowPart = ft.dwLowDateTime; + + // Between Jan 1, 1601 and Jan 1, 1970 there are 11644473600 seconds + // 100-nanoseconds = milliseconds * 10000 + LARGE_INTEGER adjust; + adjust.QuadPart = 11644473600000LL * 10000LL; + + // removes the diff between 1970 and 1601 + date.QuadPart -= adjust.QuadPart; + + // converts back from 100-nanoseconds to milliseconds + uint64_t ret = uint64_t( date.QuadPart / 10000 ); + return ret; +} + diff --git a/src/procitec_replacements.h b/src/procitec_replacements.h new file mode 100644 index 0000000..fac2a8d --- /dev/null +++ b/src/procitec_replacements.h @@ -0,0 +1,153 @@ +#pragma once + +// missing definitions, macros and functions from following include files +//#include "common/base/baselib/base/ProLogging.h" +//#include "common/base/baselib/base/ByteOrder.h" +//#include "common/base/baselib/base/ProMakros.h" +//#include "common/base/baselib/base/ProStd.h" + +// hacked down all missing things +// - strictly assuming little endian platform! + +#include +#include + +#define NUMEL( ARR ) ( sizeof(ARR) / sizeof(ARR[0]) ) +#define ProAssert( COND ) assert( COND ) +#define PROASSERT( COND ) assert( COND ) + +#define STRINGIZE(s) STRINGIZEL(s) +#define STRINGIZEL(s) #s + +#define EXTIO_IFC_VER 2018 +#define EXTIO_VER_REV 0 +#define SCM_TAGNAME "" +#define SCM_DATE "" + +#define LITTLE_INT16_T int16_t + + +#pragma pack(push, 1) // exact fit - no padding +struct LITTLE_INT24_T +{ + uint8_t lo; + uint8_t mi; + int8_t hi; +}; +#pragma pack(pop) //back to whatever the previous packing mode was + + +extern uint64_t currentMSecsSinceEpoch(); + +static inline +const char * ProVersion() +{ + return "?"; +} + +static inline +void WRITE_LITTLE_INT8(uint8_t v, void * vp) +{ + uint8_t * tp = (uint8_t *)vp; + *tp = v; +} + +static inline +void WRITE_BIG_INT8(uint8_t v, void * vp) +{ + uint8_t * tp = (uint8_t *)vp; + *tp = v; +} + +static inline +void WRITE_LITTLE_INT16(uint16_t v, void * vp) +{ + uint16_t * tp = (uint16_t *)vp; + *tp = v; +} + +static inline +void WRITE_BIG_INT32(uint32_t v, void * vp) +{ + uint32_t * tp = (uint32_t *)vp; + uint32_t flipped = ((v & 0xFFU) << 24) + | ((v & 0xFF00U) << 8) + | ((v & 0xFF0000U) >> 8) + | ((v & 0xFF000000U) >> 24); + *tp = flipped; +} + +static inline +void WRITE_LITTLE_INT32(uint32_t v, void * vp) +{ + uint32_t * tp = (uint32_t *)vp; + *tp = v; +} + +static inline +void WRITE_LITTLE_INT64(uint64_t v, void * vp) +{ + uint64_t * tp = (uint64_t *)vp; + *tp = v; +} + + +static inline +uint8_t READ_LITTLE_INT8( const void * vp ) +{ + const uint8_t * tp = (const uint8_t *)vp; + return *tp; +} + +static inline +uint8_t READ_BIG_INT8(const void * vp) +{ + const uint8_t * tp = (const uint8_t *)vp; + return *tp; +} + +static inline +uint16_t READ_LITTLE_INT16(const void * vp) +{ + const uint16_t * tp = (const uint16_t *)vp; + return *tp; +} + +static inline +uint32_t READ_LITTLE_INT32(const void * vp) +{ + const uint32_t * tp = (const uint32_t *)vp; + return *tp; +} + +static inline +uint64_t READ_LITTLE_INT64(const void * vp) +{ + const uint64_t * tp = (const uint64_t *)vp; + return *tp; +} + +static inline +uint32_t READ_BIG_INT32(const void * vp) +{ + const uint32_t * tp = (const uint32_t *)vp; + const uint32_t v = *tp; + uint32_t flipped = ((v & 0xFFU) << 24) + | ((v & 0xFF00U) << 8) + | ((v & 0xFF0000U) >> 8) + | ((v & 0xFF000000U) >> 24); + return flipped; +} + + +template +T PROCLIP(T val, T minVal, T maxVal) +{ + if (val < minVal) + return minVal; + else if (val > maxVal) + return maxVal; + else + return val; +} + diff --git a/src/rfspace_netsdr_control.cpp b/src/rfspace_netsdr_control.cpp index 82fc0b3..e7253db 100644 --- a/src/rfspace_netsdr_control.cpp +++ b/src/rfspace_netsdr_control.cpp @@ -1,12 +1,11 @@ #include "rfspace_netsdr_control.h" -#include "foreign/clsocket/clsocket/src/SimpleSocket.h" +#include "ExtIO_Logging.h" -#include "common/base/baselib/base/ProLogging.h" -#include "common/base/baselib/base/ByteOrder.h" -#include "common/base/baselib/base/ProMakros.h" -#include "common/base/baselib/base/ProStd.h" +#include "SimpleSocket.h" + +#include "procitec_replacements.h" #include @@ -357,7 +356,7 @@ void RFspaceNetSDRControl::requestHwFwVersions(HwFw id) return; const unsigned int len = 5; - const char acBuf[len] = { 5, 0x20, 4, 0, 0 }; + char acBuf[len] = { 5, 0x20, 4, 0, 0 }; WRITE_LITTLE_INT8( uint8_t(id) , &acBuf[4] ); @@ -406,7 +405,7 @@ void RFspaceNetSDRControl::requestRcvFrequency() return; const unsigned int len = 5; - const char acBuf[len] = { 5, char(msgType), 0x20, 0, 0}; + char acBuf[len] = { 5, char(msgType), 0x20, 0, 0}; WRITE_LITTLE_INT8( channel , &acBuf[4] ); @@ -419,7 +418,7 @@ void RFspaceNetSDRControl::requestRcvFrequencyRanges() return; const unsigned int len = 5; - const char acBuf[len] = { 5, char(MsgType::REQ_CTRL_RANGE), 0x20, 0, 0}; + char acBuf[len] = { 5, char(MsgType::REQ_CTRL_RANGE), 0x20, 0, 0}; WRITE_LITTLE_INT8( channel , &acBuf[4] ); @@ -432,7 +431,7 @@ void RFspaceNetSDRControl::requestRcvADAmplScale() return; const unsigned int len = 5; - const char acBuf[len] = { 5, char(msgType), 0x23, 0, 0}; + char acBuf[len] = { 5, char(msgType), 0x23, 0, 0}; WRITE_LITTLE_INT8( channel , &acBuf[4] ); @@ -445,7 +444,7 @@ void RFspaceNetSDRControl::requestRFGain() return; const unsigned int len = 5; - const char acBuf[len] = { 5, char(msgType), 0x38, 0, 0}; + char acBuf[len] = { 5, char(msgType), 0x38, 0, 0}; WRITE_LITTLE_INT8( channel , &acBuf[4] ); @@ -469,7 +468,7 @@ void RFspaceNetSDRControl::requestRFFilterSelection() return; const unsigned int len = 5; - const char acBuf[len] = { 5, char(msgType), 0x44, 0, 0}; + char acBuf[len] = { 5, char(msgType), 0x44, 0, 0}; WRITE_LITTLE_INT8( channel , &acBuf[4] ); @@ -483,7 +482,7 @@ void RFspaceNetSDRControl::requestADMode() const unsigned int len = 5; - const uint8_t acBuf[len] = { 5, uint8_t(msgType), 0x8A, 0, 0 }; + uint8_t acBuf[len] = { 5, uint8_t(msgType), 0x8A, 0, 0 }; WRITE_LITTLE_INT8( channel , &acBuf[4] ); @@ -497,7 +496,7 @@ void RFspaceNetSDRControl::requestUDPInterface() const unsigned int len = 5; - const uint8_t acBuf[len] = { 5, uint8_t(msgType), 0xC5, 0, 0 }; + uint8_t acBuf[len] = { 5, uint8_t(msgType), 0xC5, 0, 0 }; WRITE_LITTLE_INT8( channel , &acBuf[4] ); @@ -908,18 +907,33 @@ void RFspaceNetSDRControl::setUDPInterface ( const char * ip, uint16_t portNum ) if ( mSocket.IsSocketInvalid() ) return; - uint32_t ipSend = inet_addr( ip ); + const uint32_t ipSend = CSimpleSocket::GetIPv4AddrInfoStatic(ip); - const unsigned int len = 10; - unsigned char acBuf[len] = { 0x0A, 0, 0xC5, 0, 0, 0, 0, 0, 0, 0 }; + if (ipSend) + { + const unsigned int len = 10; + unsigned char acBuf[len] = { 0x0A, 0, 0xC5, 0, 0, 0, 0, 0, 0, 0 }; - void * wp = &acBuf[4]; - WRITE_BIG_INT32( ipSend, wp ); //BIG ENDIAN because ip and portNum already are little endian format + void * wp = &acBuf[4]; + WRITE_BIG_INT32(ipSend, wp); //BIG ENDIAN because ip and portNum already are little endian format - wp = &acBuf[8]; - WRITE_LITTLE_INT16( portNum, wp ); + wp = &acBuf[8]; + WRITE_LITTLE_INT16(portNum, wp); - mSocket.Send(acBuf, len); + mSocket.Send(acBuf, len); + + LOG_PRO(LOG_DEBUG, "Commanded NetSDR to transmit it's UDP stream to %u.%u.%u.%u:%u" + , unsigned((ipSend >> 24) & 0xFF) + , unsigned((ipSend >> 16) & 0xFF) + , unsigned((ipSend >> 8) & 0xFF) + , unsigned(ipSend & 0xFF) + , unsigned(portNum) + ); + } + else + { + LOG_PRO(LOG_PROTOCOL, "Skipping NetSDR command to transmit it's UDP stream towards ??? without DATA_IP address"); + } } void RFspaceNetSDRControl::setCWStartup ( uint8_t wpm, CWFreq cwFreq, const char * asciiMessage) @@ -927,14 +941,13 @@ void RFspaceNetSDRControl::setCWStartup ( uint8_t wpm, CWFreq cwFreq, const char if ( mSocket.IsSocketInvalid() ) return; - int wpmMin = uint8_t(WpmMinMax::WPM_MIN); - int wpmMax = uint8_t(WpmMinMax::WPM_MAX); - + uint8_t wpmMin = uint8_t(WpmMinMax::WPM_MIN); + uint8_t wpmMax = uint8_t(WpmMinMax::WPM_MAX); if( (wpm < wpmMin) || (wpm > wpmMax) ) { wpm = PROCLIP(wpm, wpmMin, wpmMax); - LOG_PRO( LOG_ERROR,"WPM value out of bounds --> setting to value %u", wpm); + LOG_PRO( LOG_ERROR,"WPM value out of bounds --> setting to value %u", unsigned(wpm)); } uint8_t length = strlen(asciiMessage); @@ -1777,7 +1790,6 @@ const char * getText( RFspaceNetSDRControl::RfGain e ) const char * getFilterText( int e ) { - switch(RFspaceNetSDRControl::RfFilterSel(e)) { case RFspaceNetSDRControl::RfFilterSel::F_AUTO: return "Auto Selection"; @@ -1864,6 +1876,3 @@ const char * getText( uint8_t e ) } } - - - diff --git a/src/rfspace_netsdr_receiver.cpp b/src/rfspace_netsdr_receiver.cpp index b1391c6..cc996ec 100644 --- a/src/rfspace_netsdr_receiver.cpp +++ b/src/rfspace_netsdr_receiver.cpp @@ -1,21 +1,28 @@ #include "rfspace_netsdr_receiver.h" -#include "common/base/baselib/base/ProLogging.h" -#include "common/base/baselib/base/ProMakros.h" -#include "common/base/baselib/base/ProStd.h" +#include "ExtIO_Logging.h" +#include "procitec_replacements.h" #include #include #include -//#include - -const uint32_t RFspaceNetReceiver::maiSamplerates[] { 12500, 32000, 62500, 100*1000, 125*1000, 250*1000, 500*1000, 625*1000, 1000*1000, 1666666, 2000*1000 }; -const uint32_t RFspaceNetReceiver::maiBandwidths[] { 10*1000, 25*1000, 50*1000, 80*1000, 100*1000, 200*1000, 400*1000, 500*1000, 800*1000, 1300*1000, 1600*1000 }; -const float RFspaceNetReceiver::mafAttenuationATTs[] = { -30.0F, -30.0F, -20.0F, -20.0F, -10.0F, -10.0F, 0.0F, 0.0F }; -const float RFspaceNetReceiver::mafActualAttenuationATTs[] = { -30.0F, -26.5F, -20.0F, -16.5F, -10.0F, -6.5F, 0.0F, 3.5F }; -const float RFspaceNetReceiver::mafAttenuationADGains[] = { 1.0F, 1.5F, 1.0F, 1.5F, 1.0F, 1.5F, 1.0F, 1.5F }; -const float RFspaceNetReceiver::mafAttenuationADGainsdB[] = { 0.0F, 3.0F, 0.0F, 3.0F, 0.0F, 3.0F, 0.0F, 3.0F }; +#define KHZ *1000 +// from NetSDR specification: +// This parameter limited to frequencies that are integer divisions by 4 of the 80MHz A/D sample rate +// The maximum sample rate supported is 2,000,000 Hz in the 16 bits/sample mode.(80MHz/40) +// The maximum sample rate supported is 1,333,333 Hz in the 24 bits/sample mode.(80MHz/60) +// The minimum sample rate supported is 32,000 Hz in the 16 or 24 bits/sample mode.( 80MHz/250) +// +// decim from 80 MHz A/D clock: 6400 5000 2500 1280 1000 800 640 500 400 320 256 200 160 128 100 80 64 52 48 44 40 +const uint32_t RFspaceNetReceiver::maiSamplerates[] { 12500, 16 KHZ, 32 KHZ, 62500, 80 KHZ, 100 KHZ, 125 KHZ, 160 KHZ, 200 KHZ, 250 KHZ, 312500, 400 KHZ, 500 KHZ, 625 KHZ, 800 KHZ, 1000 KHZ, 1250 KHZ, 1538461, 1666666, 1818181, 2000 KHZ }; +const uint32_t RFspaceNetReceiver::maiBandwidths[] { 10 KHZ, 12 KHZ, 25 KHZ, 50 KHZ, 64 KHZ, 80 KHZ, 100 KHZ, 128 KHZ, 160 KHZ, 200 KHZ, 250 KHZ, 320 KHZ, 400 KHZ, 500 KHZ, 640 KHZ, 800 KHZ, 1000 KHZ, 1200 KHZ, 1300 KHZ, 1400 KHZ, 1600 KHZ }; +#undef KHZ + +const float RFspaceNetReceiver::mafAttenuationATTs[] = { -30.0F, -30.0F, -20.0F, -20.0F, -10.0F, -10.0F, 0.0F, 0.0F }; +const float RFspaceNetReceiver::mafActualAttenuationATTs[] = { -30.0F, -26.5F, -20.0F, -16.5F, -10.0F, -6.5F, 0.0F, 3.5F }; +const float RFspaceNetReceiver::mafAttenuationADGains[] = { 1.0F, 1.5F, 1.0F, 1.5F, 1.0F, 1.5F, 1.0F, 1.5F }; +const float RFspaceNetReceiver::mafAttenuationADGainsdB[] = { 0.0F, 3.0F, 0.0F, 3.0F, 0.0F, 3.0F, 0.0F, 3.0F }; const float RFspaceNetReceiver::mafVUHFCompatibilityGainValues[] = {0, 1, 2, 3 }; const float RFspaceNetReceiver::mafVUHFMultiGainValues[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; @@ -590,7 +597,7 @@ bool RFspaceNetReceiver::startHW(int64_t LOfreq) mpoSettings->iFrequency = LOfreq; mSampleBufferLenInFrames = 0; - mChangeBitRangeSmpRateIdx = getSmpRateIdx(mpoSettings->iBitDepthThresSamplerate); + mChangeBitRangeSmpRateIdx = getMaxSmpRateIdx(mpoSettings->iBitDepthThresSamplerate); if( mpoSettings->iSampleRateIdx <= mChangeBitRangeSmpRateIdx) { @@ -784,8 +791,6 @@ void RFspaceNetReceiver::setSamplerate( int idx ) //--> give samplerate change (and sometimes therefore bitdepth change) more time. mStartUDPTimer = 100; //in ms mStartData = true; - - } int64_t RFspaceNetReceiver::getHWLO( void ) @@ -811,7 +816,8 @@ int RFspaceNetReceiver::getSmpRateIdx( uint32_t smpRate ) int ret = -1; for(int idx = 0; idx < miNumSamplerates; ++idx) { - if(smpRate == maiSamplerates[idx]) + int32_t delta = smpRate - maiSamplerates[idx]; + if( -10 <= delta && delta <= 10 ) // +/- 10 Hz tolerance { LOG_PRO( LOG_DEBUG, "********* RFspaceNetReceiver::getSmpRateIdx(%u) --> idx: %d", smpRate, idx); ret = idx; @@ -820,12 +826,29 @@ int RFspaceNetReceiver::getSmpRateIdx( uint32_t smpRate ) } if(ret == -1) - LOG_PRO( LOG_DEBUG, "********* RFspaceNetReceiver::getSmpRateIdx(%u) --> idx: ERROR !", smpRate); + LOG_PRO(LOG_ERROR, "********* RFspaceNetReceiver::getSmpRateIdx(%u) --> idx: ERROR !", smpRate); return ret; +} + + +int RFspaceNetReceiver::getMaxSmpRateIdx(uint32_t smpRate) +{ + int ret = -1; + for (int idx = 0; idx < miNumSamplerates; ++idx) + { + if (smpRate >= maiSamplerates[idx]) + ret = idx; + } + if (ret == -1) + LOG_PRO(LOG_ERROR, "********* RFspaceNetReceiver::getMaxSmpRateIdx(%u) --> idx: ERROR !", smpRate); + else + LOG_PRO(LOG_DEBUG, "********* RFspaceNetReceiver::getMaxSmpRateIdx(%u) --> idx: %d", smpRate, ret); + return ret; } + const int64_t * RFspaceNetReceiver::getFrequencyRanges(int idx) { if(mHasRcvFrequencyRanges) diff --git a/src/rfspace_netsdr_receiver.h b/src/rfspace_netsdr_receiver.h index 5fde168..e22fdeb 100644 --- a/src/rfspace_netsdr_receiver.h +++ b/src/rfspace_netsdr_receiver.h @@ -3,10 +3,7 @@ #include "rfspace_netsdr_control.h" #include "rfspace_netsdr_udpdata.h" -#include "common/functions/receiverlib/LC_ExtIO_Types.h" - -#include "common/base/baselib/base/ByteOrder.h" -#include "common/base/baselib/base/ExtendedTypes.h" +#include "LC_ExtIO_Types.h" #include @@ -30,17 +27,16 @@ class RFspaceNetReceiver public: Settings() { - strcpy(acCtrlIP, "10.10.11.2"); - strcpy(acDataIP, ""); - uCtrlPortNo = uDataPortNo = 50000; - iSampleRateIdx = 0; + strcpy(acCtrlIP, "192.168.8.101"); // "10.10.11.2" + strcpy(acDataIP, "192.168.8.100"); // "" main PC: 192.168.8.100 PC2: 192.168.8.102 + uCtrlPortNo = uDataPortNo = 50002; // 50000 + iSampleRateIdx = 2; // 2: 32 kHz samplerate iAttenuationIdx = 0; - iBitDepthThresSamplerate = 0; - + iBitDepthThresSamplerate = 1333333; // 1333.333 kHz == 80 MHz / 60 iBand_minFreq = 0; - iBand_maxFreq = 0; + iBand_maxFreq = 34 * 1000L * 1000L; // 0 - 34 MHz uiBandwidth = 0; uiSamplerate = 0; @@ -138,6 +134,7 @@ class RFspaceNetReceiver int64_t getHWLO( void ); int getAttIdx( void ); int getSmpRateIdx( uint32_t ); + int getMaxSmpRateIdx(uint32_t); const int64_t * getFrequencyRanges( int idx ); void TimerProc(uint16_t waitMs); diff --git a/src/rfspace_netsdr_udpdata.cpp b/src/rfspace_netsdr_udpdata.cpp index 69c625f..7b18352 100644 --- a/src/rfspace_netsdr_udpdata.cpp +++ b/src/rfspace_netsdr_udpdata.cpp @@ -1,9 +1,8 @@ #include "rfspace_netsdr_udpdata.h" -#include "common/base/baselib/base/ByteOrder.h" -#include "common/base/baselib/base/ProStd.h" -#include "common/base/baselib/base/ProLogging.h" +#include "ExtIO_Logging.h" +#include "procitec_replacements.h" #define LENGTH_MASK 0x1FFF // mask for message length @@ -63,6 +62,24 @@ bool RFspaceNetSDRUdpData::bindIfc( const char * ifc, uint16_t portNo ) resetReceiverData(); + const uint32_t ipSend = CSimpleSocket::GetIPv4AddrInfoStatic(ifc); + if (!ipSend) + { + LOG_PRO(LOG_PROTOCOL, "Binding to all local interfaces without DATA_IP address '%s'", ifc); + ifc = ""; + } + else + { + LOG_PRO(LOG_DEBUG, "Binding will be on %u.%u.%u.%u for '%s'" + , unsigned((ipSend >> 24) & 0xFF) + , unsigned((ipSend >> 16) & 0xFF) + , unsigned((ipSend >> 8) & 0xFF) + , unsigned(ipSend & 0xFF) + , ifc + ); + } + + LOG_PRO(LOG_DEBUG, "Binding UDP to interface %s:%u ..", ifc, unsigned(portNo)); bool bConnected = mSocket.Bind(ifc, portNo); if ( bConnected ) { @@ -71,13 +88,15 @@ bool RFspaceNetSDRUdpData::bindIfc( const char * ifc, uint16_t portNo ) uint32_t resWinSize = mSocket.SetReceiveWindowSize( paramWinSize ); if ( resWinSize < paramWinSize ) { - LOG_PRO( LOG_DEBUG, "Error setting UDP windows size to %u - result is %u", paramWinSize, resWinSize); + LOG_PRO(LOG_ERROR, "Error setting UDP windows size to %u - result is %u", paramWinSize, resWinSize); } - + } + else + { + LOG_PRO(LOG_ERROR, "Error binding UDP to interface %s:%u", ifc, unsigned(portNo)); } return bConnected; - return true; } diff --git a/src/rfspace_netsdr_udpdata.h b/src/rfspace_netsdr_udpdata.h index 975250c..196d385 100644 --- a/src/rfspace_netsdr_udpdata.h +++ b/src/rfspace_netsdr_udpdata.h @@ -4,8 +4,8 @@ #include #include -#include "foreign/clsocket/clsocket/src/SimpleSocket.h" -#include "foreign/clsocket/clsocket/src/PassiveSocket.h" +#include "SimpleSocket.h" +#include "PassiveSocket.h" // forward declaration class CPassiveSocket;