Skip to content

Commit

Permalink
fixed setup: better handling of erroneous IP address or missing device
Browse files Browse the repository at this point in the history
* (windows) error dialog message, when connection fails
 added connection timeout, default: 1000 ms
* fixed changing samplerate
* fixed buffer space, when using WRITE_LITTLE_INT64() to write just 5 bytes

Signed-off-by: hayati ayguen <[email protected]>
hayguen committed May 7, 2018
1 parent 844e364 commit 1a9eb30
Showing 12 changed files with 264 additions and 215 deletions.
2 changes: 1 addition & 1 deletion ExtIO_NetSDR/ExtIO_NetSDR.vcxproj
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@
<GenerateDebugInformation>false</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<Version>2018.0</Version>
<Version>2018.1</Version>
<ModuleDefinitionFile>..\src\ExtIO_RFspaceNetSDR.def</ModuleDefinitionFile>
<StripPrivateSymbols>/PDBSTRIPPED</StripPrivateSymbols>
<AssemblyDebug>false</AssemblyDebug>
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# ExtIO_RFspaceNetSDR
Winrad/HDSDR plugin ExtIO for the RFspace NetSDR receiver

URL: https://github.com/hayguen/ExtIO_RFspaceNetSDR

## Software Defined Radio (SDR) receiver

@@ -37,6 +38,16 @@ Other ExtIO compatible software like Winrad or Studio1 should also work.
* 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.

* Edit one of config_Default-profile.reg (or config_NetSDR-profile.reg) with a Text-Editor,
e.g. Notepad++. Enter your IP address(es) and check if you need to modify the portnumber.
Use config_Default-profile.reg if you start HDSDR with it's installed shortcut.

* With a custom 'NetSDR' profile,
see https://sites.google.com/site/g4zfqradio/installing-and-using-hdsdr#Advanced ,
you might edit config_NetSDR-profile.reg

* Then doubleclick to import those settings, when HDSDR is closed

* exit and restart SDR software and select ExtIO_RFspaceNetSDR.DLL if demanded


@@ -49,7 +60,7 @@ Besides cloning this repository, you also need to clone following libraries from
* 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.
Other compilers (gcc/mingw) should work, when adding suitable project files or fixing CMakeLists.txt.


## Status
@@ -58,3 +69,6 @@ Compiles. In test.

ExtIO control GUI for configuration is missing! To be implemented ..

Workaround by editing Windows' registry directly with 'regedit.exe' for use with HDSDR.
Registry path: HKEY_CURRENT_USER\Software\HDSDR\ExtIO_RFspaceNetSDR.dll

Binary file added config_Default-profile.reg
Binary file not shown.
Binary file added config_NetSDR-profile.reg
Binary file not shown.
7 changes: 7 additions & 0 deletions docs/README.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

NetSDR Interface Specification from
http://www.moetronix.com/svdownload.htm

SDRNetSetup Utility Source Code Link
https://sourceforge.net/projects/sdrnetsetup/

73 changes: 46 additions & 27 deletions src/ExtIO_RFspaceNetSDR.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

#define HWNAME "RFspace"
#define HWMODEL "RFspace NetSDR"
#define SETTINGS_IDENTIFIER "RFspace NetSDR-0.2"
#define SETTINGS_IDENTIFIER "RFspace NetSDR-0.5"

#include "ExtIO_RFspaceNetSDR.h"
#include "rfspace_netsdr_receiver.h"
@@ -275,15 +275,19 @@ bool EXTIO_CALL InitHW( char* name, char* model, int& type )
gbInitHW = true;
}


return gbInitHW;
}

//---------------------------------------------------------------------------
bool EXTIO_CALL OpenHW( void )
bool EXTIO_CALL OpenHW(void)
{
LOG_PRO( LOG_DEBUG, "OpenHW() called" );
LOG_PRO(LOG_DEBUG, "OpenHW() called .. returning gbInitHw = %s", (gbInitHW ? "true" : "false"));
return gbInitHW; // open on demand!
}

//---------------------------------------------------------------------------
static bool InternalOpenHW(void)
{
bool bOpenOK = true;
if ( gbInitHW )
{
@@ -298,24 +302,26 @@ bool EXTIO_CALL OpenHW( void )
{
gpoReceiver->setExtIoCallback(gpfnExtIOCallbackPtr);
stopThread();
LOG_PRO(LOG_DEBUG, "InternalOpenHW(): trying to open/connect device ..");
bOpenOK = gpoReceiver->openHW(gpoSettings);
if (bOpenOK)
startThread();
else
{
delete gpoReceiver;
gpoReceiver = nullptr;

#if defined( WIN32 ) || defined( WIN64 )
char acMsg[1024];
snprintf(acMsg, 1023, "Error connecting to %s:%u", gpoSettings->acCtrlIP, unsigned(gpoSettings->uCtrlPortNo));
::MessageBoxA(0, acMsg, "Error", MB_OK);
#endif
}
LOG_PRO(LOG_DEBUG, "InternalOpenHW() returns gbInitHW && bOpenOK = %s && %s", (gbInitHW ? "true" : "false"), (bOpenOK ? "true" : "false"));
}
}
}

//EXTIO_STATUS_CHANGE( gpfnExtIOCallbackPtr, extHw_Changed_ATT );

LOG_PRO( LOG_DEBUG, "OpenHW() returns gbInitHW && bOpenOK = %s && %s", (gbInitHW ? "true":"false"), (bOpenOK ? "true":"false") );

// in the above statement, F->handle is the window handle of the panel displayed
// by the DLL, if such a panel exists
return gbInitHW && bOpenOK;
}

@@ -331,6 +337,10 @@ int64_t EXTIO_CALL StartHW64( int64_t LOfreq )
{
LOG_PRO( LOG_DEBUG, "StartHW64() called" );

const bool bConnected = InternalOpenHW();
if (!bConnected && gpfnExtIOCallbackPtr)
EXTIO_STATUS_CHANGE(gpfnExtIOCallbackPtr, extHw_Stop);

if ( !gbInitHW || !gpoReceiver )
return 0;

@@ -427,12 +437,10 @@ long EXTIO_CALL GetHWLO( void )
long EXTIO_CALL GetHWSR( void )
{
LOG_PRO( LOG_DEBUG, "GetHWSR() called");
if ( !gpoReceiver )
return 0;
if (!gpoSettings)
gpoSettings = new RFspaceNetReceiver::Settings();
long srate = long(gpoSettings->uiSamplerate);
LOG_PRO( LOG_DEBUG, "GetHWSR(): %ld Hz", srate );
LOG_PRO(LOG_DEBUG, "GetHWSR(): %ld Hz", srate);
return long(srate);
}

@@ -574,7 +582,7 @@ int EXTIO_CALL ExtIoGetSrates( int srate_idx, double* samplerate )

if( srate_idx >= 0 && srate_idx < RFspaceNetReceiver::miNumSamplerates)
{
*samplerate = gpoReceiver->maiSamplerates[srate_idx];
*samplerate = RFspaceNetReceiver::srate_bws[srate_idx].srate;
return 0;
}
else
@@ -595,19 +603,20 @@ int EXTIO_CALL ExtIoGetActualSrateIdx( void )
int EXTIO_CALL ExtIoSetSrate( int srate_idx )
{
LOG_PRO( LOG_DEBUG, "************************************** ExtIoSetSrate(%d)*********************************", srate_idx);
int clippedIdx = PROCLIP(srate_idx, 0, RFspaceNetReceiver::miNumSamplerates - 1);
if ( gpoReceiver )
{
gpoReceiver->setSamplerate(srate_idx);
return 0;
gpoReceiver->setSamplerate(clippedIdx);
return (srate_idx == clippedIdx ? 0 : 1);
}
else
{
if (!gpoSettings)
gpoSettings = new RFspaceNetReceiver::Settings();
LOG_PRO( LOG_DEBUG, "************************************** ExtIoSetSrate(): receiver does not exist. set settings *********************************");

gpoSettings->iSampleRateIdx = srate_idx;
return 1;
gpoSettings->iSampleRateIdx = clippedIdx;
return (srate_idx == clippedIdx ? 0 : 1);
}
}

@@ -616,7 +625,7 @@ long EXTIO_CALL ExtIoGetBandwidth( int srate_idx )
long bandwidth;
if( srate_idx >= 0 && srate_idx < RFspaceNetReceiver::miNumSamplerates)
{
bandwidth = long(gpoReceiver->maiBandwidths[srate_idx]);
bandwidth = long(RFspaceNetReceiver::srate_bws[srate_idx].bw);
return bandwidth;
}
else
@@ -630,6 +639,7 @@ 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
, CONNECT_TIMEOUT_MILLIS
, AVAIL_SRATES
, AVAIL_BWS
, SAMPLERATE_IDX
@@ -675,21 +685,26 @@ 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 - or leave empty. As checked 'Use Alternative Data Destination UDP Address' in SpectraVue" );
snprintf( value, 1024, "%s", gpoSettings->acDataIP );
return 0;
case Setting::DATA_PORT:
snprintf( description, 1024, "%s", "DATA PortNo: port number of Client PC to receive streaming data (default: as CONTROL PortNo)" );
snprintf( value, 1024, "%d", gpoSettings->uDataPortNo );
return 0;

case Setting::CONNECT_TIMEOUT_MILLIS:
snprintf(description, 1024, "%s", "Connection timeout in milliseconds");
snprintf(value, 1024, "%d", gpoSettings->nConnectTimeoutMillis);
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]) );
int w = snprintf(value + off, 1024 - off, "%s%d: %u", (k == 0 ? "" : ", "), k, unsigned(RFspaceNetReceiver::srate_bws[k].srate));
if (w < 0 || w >= (1024 - int(off)))
break;
off += w;
@@ -702,7 +717,7 @@ int EXTIO_CALL ExtIoGetSetting( int idx, char* description, char* value )
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]));
int w = snprintf(value + off, 1024 - off, "%s%d: %u", (k == 0 ? "" : ", "), k, unsigned(RFspaceNetReceiver::srate_bws[k].bw));
if (w < 0 || w >= (1024 - int(off)))
break;
off += w;
@@ -760,7 +775,7 @@ int EXTIO_CALL ExtIoGetSetting( int idx, char* description, char* value )
return 0;

case Setting::GAIN_CONTROL_MODE:
snprintf( description, 1024, "%s", "Usage of AGC in VUHF Frequency Range" );
snprintf( description, 1024, "%s", "Usage of AGC in V/UHF Frequency Range" );
snprintf( value, 1024, "%u", gpoSettings->bUseVUHFAutoMode);
return 0;

@@ -778,6 +793,7 @@ int EXTIO_CALL ExtIoGetSetting( int idx, char* description, char* value )
snprintf( description, 1024, "%s", "IF Output Gain Level Value" );
snprintf( value, 1024, "%u", gpoSettings->iIFOutputValue);
return 0;

case Setting::NUM:
// no break
default:
@@ -813,7 +829,7 @@ static const char * trimmedIP(const char * value, const char * logText)
if (j < 4)
{
if (value[0] == '.')
++value;
acBuf[k++] = *value++;
else
{
LOG_PRO(LOG_ERROR, "Error in %s for %d.th numeric block!", logText, j);
@@ -866,6 +882,9 @@ void EXTIO_CALL ExtIoSetSetting( int idx, const char* value )
tempInt = atoi( value );
gpoSettings->uDataPortNo = (uint16_t)( tempInt & 0xffff );
break;
case Setting::CONNECT_TIMEOUT_MILLIS:
gpoSettings->nConnectTimeoutMillis = atoi(value);
break;
case Setting::AVAIL_SRATES:
case Setting::AVAIL_BWS:
break;
@@ -908,13 +927,13 @@ void EXTIO_CALL ExtIoSetSetting( int idx, const char* value )
break;*/
case Setting::LNA_VALUE:
gpoSettings->iLNAValue = atoi( value );
break;
break;
case Setting::MIXER_VALUE:
gpoSettings->iMixerValue = atoi( value );
break;
break;
case Setting::IFOUTPUT_VALUE:
gpoSettings->iIFOutputValue = atoi( value );
break;
break;
case Setting::NUM:
// no break
default:
6 changes: 3 additions & 3 deletions src/procitec_replacements.h
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@
#define STRINGIZEL(s) #s

#define EXTIO_IFC_VER 2018
#define EXTIO_VER_REV 0
#define EXTIO_VER_REV 1
#define SCM_TAGNAME ""
#define SCM_DATE ""

@@ -73,7 +73,7 @@ void WRITE_BIG_INT32(uint32_t v, void * vp)
uint32_t flipped = ((v & 0xFFU) << 24)
| ((v & 0xFF00U) << 8)
| ((v & 0xFF0000U) >> 8)
| ((v & 0xFF000000U) >> 24);
| (((v & 0xFF000000U) >> 24) & 0xFFU);
*tp = flipped;
}

@@ -135,7 +135,7 @@ uint32_t READ_BIG_INT32(const void * vp)
uint32_t flipped = ((v & 0xFFU) << 24)
| ((v & 0xFF00U) << 8)
| ((v & 0xFF0000U) >> 8)
| ((v & 0xFF000000U) >> 24);
| (((v & 0xFF000000U) >> 24) & 0xFFU);
return flipped;
}

145 changes: 54 additions & 91 deletions src/rfspace_netsdr_control.cpp
Original file line number Diff line number Diff line change
@@ -246,13 +246,11 @@ void RFspaceNetSDRControl::resetReceiverData()
if(i<=4)
mRcvFrequencyRanges[i] = 0;
}


}



bool RFspaceNetSDRControl::connect( const char * ip, unsigned portNo )
bool RFspaceNetSDRControl::connect(const char * ip, unsigned portNo, int nConnectTimeoutMillis)
{

if ( mSocket.IsSocketPeerOpen() )
@@ -270,21 +268,22 @@ bool RFspaceNetSDRControl::connect( const char * ip, unsigned portNo )

resetReceiverData();

if (nConnectTimeoutMillis > 0)
mSocket.SetConnectTimeoutMillis(nConnectTimeoutMillis);

mSocket.SetNonblocking();
bool bConnected = mSocket.Open( ip, portNo );
if ( bConnected )
{

mSocket.SetNonblocking();

//request information about General Control at initial connection
mSocket.WaitUntilWritable(500);
requestOptions();
requestTargetName();
requestTargetSerialNum();
requestInterfaceVersion();
requestHwFwVersions(RFspaceNetSDRControl::HwFw::BOOT_CODE);
requestProductId();
requestStatus();

}

return bConnected;
@@ -756,12 +755,12 @@ void RFspaceNetSDRControl::setRcvFreq( int64_t rcvFreqHz)
if ( mSocket.IsSocketInvalid() )
return;


const unsigned int len = 10;
unsigned char acBuf[len] = { 0x0A, 0, 0x20, 0, 0, 0, 0, 0, 0, 0 };
// 0 1 2 3 4 5
unsigned char acBuf[len+8] = { 0x0A, 0, 0x20, 0, 0, 0, 0, 0, 0, 0 };
void * wp = &acBuf[4];
WRITE_LITTLE_INT8( channel , wp ); //write channel information to byte #5
wp = &acBuf[len-5];
wp = &acBuf[5];
WRITE_LITTLE_INT64( rcvFreqHz , wp ); //write frequency to last 5 bytes of buffer

mSocket.Send(acBuf, len);
@@ -915,7 +914,7 @@ void RFspaceNetSDRControl::setUDPInterface ( const char * ip, uint16_t portNum )
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
WRITE_LITTLE_INT32(ipSend, wp); // spec 4.4.6 writes "little endian"!

wp = &acBuf[8];
WRITE_LITTLE_INT16(portNum, wp);
@@ -1530,36 +1529,34 @@ void RFspaceNetSDRControl::parseVUHFGains( )
/////////////////////////////////////////////////////////////////////////////////////////////////
//********************************** PRINT FUNCTIONS ********************************************

void RFspaceNetSDRControl::printText( const Options & opt )
void RFspaceNetSDRControl::printText(const Options & opt, const char * pacPreText)
{
LOG_PRO( LOG_DEBUG, "Receiver Options Information : ");
LOG_PRO( LOG_DEBUG, "Sound Enabled : %s ", opt.Sound_Enabled ? "Yes" : "No" );
LOG_PRO( LOG_DEBUG, "ReflockBoard Present : %s ", opt.ReflockBoard_Present ? "Yes" : "No" );
LOG_PRO( LOG_DEBUG, "DownConverterBoard Present : %s ", opt.DownConverterBoard_Present ? "Yes" : "No" );
LOG_PRO( LOG_DEBUG, "UpConverterBoard Present : %s ", opt.UpConverterBoard_Present ? "Yes" : "No" );
LOG_PRO( LOG_DEBUG, "X2Board Present : %s ", opt.X2Board_Present ? "Yes" : "No" );
LOG_PRO( LOG_DEBUG, "MainBoardVariant : %u ", opt.MainBoardVariant);
LOG_PRO( LOG_DEBUG, "ReflockBoardVariant : %u ", opt.ReflockBoardVariant);
LOG_PRO( LOG_DEBUG, "DownConverterBoardVariant : %u ", opt.DownConverterBoardVariant);
LOG_PRO( LOG_DEBUG, "UpConverterBoardVariant : %u ", opt.UpConverterBoardVariant);
LOG_PRO(LOG_DEBUG, "%s Receiver Options Information :", pacPreText);
LOG_PRO( LOG_DEBUG, " Sound Enabled : %s", opt.Sound_Enabled ? "Yes" : "No" );
LOG_PRO( LOG_DEBUG, " ReflockBoard Present : %s", opt.ReflockBoard_Present ? "Yes" : "No" );
LOG_PRO( LOG_DEBUG, " DownConverterBoard Present : %s", opt.DownConverterBoard_Present ? "Yes" : "No" );
LOG_PRO( LOG_DEBUG, " UpConverterBoard Present : %s", opt.UpConverterBoard_Present ? "Yes" : "No" );
LOG_PRO( LOG_DEBUG, " X2Board Present : %s", opt.X2Board_Present ? "Yes" : "No" );
LOG_PRO( LOG_DEBUG, " MainBoardVariant : %u", opt.MainBoardVariant);
LOG_PRO( LOG_DEBUG, " ReflockBoardVariant : %u", opt.ReflockBoardVariant);
LOG_PRO( LOG_DEBUG, " DownConverterBoardVariant : %u", opt.DownConverterBoardVariant);
LOG_PRO( LOG_DEBUG, " UpConverterBoardVariant : %u", opt.UpConverterBoardVariant);
}

void RFspaceNetSDRControl::printUDPStateText( const bool & state )
void RFspaceNetSDRControl::printUDPStateText(const bool & state, const char * pacPreText)
{
LOG_PRO( LOG_DEBUG, "UDP State Information : ");
LOG_PRO( LOG_DEBUG, "UDP State : %s", state ? "RUNNING" : "IDLE" );
LOG_PRO(LOG_DEBUG, "%s UDP State '%s'", pacPreText, state ? "RUNNING" : "IDLE");
}

void RFspaceNetSDRControl::printBitDepthText( const int & bitDepth )
void RFspaceNetSDRControl::printBitDepthText(const int & bitDepth, const char * pacPreText)
{
LOG_PRO( LOG_DEBUG, "UDP Bit Depth Information : ");
LOG_PRO( LOG_DEBUG, "UDP Bit Depth : %uBit ", bitDepth);
LOG_PRO(LOG_DEBUG, "%s UDP Bit Depth: %u Bit", pacPreText, bitDepth);
}

/*
void RFspaceNetSDRControl::printText( const RcvFrequencies & rcvFreq)
void RFspaceNetSDRControl::printText(const RcvFrequencies & rcvFreq, const char * pacPreText)
{
LOG_PRO( LOG_DEBUG, "Receiver Frequency Information : ");
LOG_PRO( LOG_DEBUG, "%s Receiver Frequency Information : ", pacPreText);
LOG_PRO( LOG_DEBUG, "Channel 1 NCO-Frequency : %lu Hz", rcvFreq.Chn1_Freq );
LOG_PRO( LOG_DEBUG, "Channel 2 NCO-Frequency : %lu Hz", rcvFreq.Chn2_Freq );
LOG_PRO( LOG_DEBUG, "****************************************************************************************** ");
@@ -1574,77 +1571,64 @@ void RFspaceNetSDRControl::printText( const RcvFrequencies & rcvFreq)
LOG_PRO( LOG_DEBUG, "Range: Channel 2, Band 2 VCO- Frequency : %lu Hz", rcvFreq.Chn2_Bnd2_VCO_DwnConvFreq );
}
*/
void RFspaceNetSDRControl::printRcvFreqText( const uint64_t & rcvFreq)
void RFspaceNetSDRControl::printRcvFreqText(const uint64_t & rcvFreq, const char * pacPreText)
{
LOG_PRO( LOG_DEBUG, "Receiver Frequency Information :");
LOG_PRO( LOG_DEBUG, "Frequency: %luHz", rcvFreq );
LOG_PRO(LOG_DEBUG, "%s Frequency: %lu Hz", pacPreText, (unsigned long)(rcvFreq));
}

void RFspaceNetSDRControl::printFilterText( const int & filtSel)
void RFspaceNetSDRControl::printFilterText(const int & filtSel, const char * pacPreText)
{
LOG_PRO( LOG_DEBUG, "RF FilterSelect Information : ");
LOG_PRO( LOG_DEBUG, "Filter Select: %s", getFilterText(filtSel) );
LOG_PRO(LOG_DEBUG, "%s Filter Select: %s", pacPreText, getFilterText(filtSel));
}

void RFspaceNetSDRControl::printText( const bool & dithering)
void RFspaceNetSDRControl::printText(const bool & dithering, const char * pacPreText)
{
LOG_PRO( LOG_DEBUG, "AD Dither Information : ");
LOG_PRO( LOG_DEBUG, "Dithering: %s", dithering ? "ON" : "OFF" );
LOG_PRO(LOG_DEBUG, "%s A/D Dithering: %s", pacPreText, dithering ? "ON" : "OFF");
}

void RFspaceNetSDRControl::printText( const float & gain)
void RFspaceNetSDRControl::printText(const float & gain, const char * pacPreText)
{
LOG_PRO( LOG_DEBUG, "AD Gain Information : ");
if(gain != -1)
LOG_PRO( LOG_DEBUG, "Gain: %.1f", gain );
if (gain != -1)
LOG_PRO(LOG_DEBUG, "%s A/D Gain: %.1f", pacPreText, gain);
else
LOG_PRO( LOG_ERROR, "ERROR! Passed invalid channel argument. Please choose < 1 > or < 2 > in the get function");
LOG_PRO(LOG_ERROR, "%s A/D Gain: ERROR!", pacPreText);
}

void RFspaceNetSDRControl::printText( const RfGain & gain )
void RFspaceNetSDRControl::printText(const RfGain & gain, const char * pacPreText)
{
{
LOG_PRO( LOG_DEBUG, "RF Gain Information :");
LOG_PRO( LOG_DEBUG, "RFGain: %s", getText(gain) );
}
LOG_PRO(LOG_DEBUG, "%s RF Gain: %s", pacPreText, getText(gain));
}

void RFspaceNetSDRControl::printText( const VUHFGains & vuhfGains )
void RFspaceNetSDRControl::printText(const VUHFGains & vuhfGains, const char * pacPreText)
{
{
LOG_PRO( LOG_DEBUG, "VUHF Gain Information :");
LOG_PRO( LOG_DEBUG, "VUHF AutoMode: %s", vuhfGains.isAGCMode ? "ON" : "OFF" );
LOG_PRO( LOG_DEBUG, "VUHF LNA Gain: %u", vuhfGains.LNAGainLevel );
LOG_PRO( LOG_DEBUG, "VUHF Mix Gain: %u", vuhfGains.MixerGainLevel );
LOG_PRO( LOG_DEBUG, "VUHF IF Gain: %u", vuhfGains.IFOutputGainLevel );
}
LOG_PRO(LOG_DEBUG, "%s V/UHF Gain Information :", pacPreText);
LOG_PRO( LOG_DEBUG, " V/UHF AutoMode: %s", vuhfGains.isAGCMode ? "ON" : "OFF" );
LOG_PRO( LOG_DEBUG, " V/UHF LNA Gain: %u", vuhfGains.LNAGainLevel );
LOG_PRO( LOG_DEBUG, " V/UHF Mix Gain: %u", vuhfGains.MixerGainLevel );
LOG_PRO( LOG_DEBUG, " V/UHF IF Gain: %u", vuhfGains.IFOutputGainLevel );
}

void RFspaceNetSDRControl::printText( const IQOutSmpRate & smpRate )
void RFspaceNetSDRControl::printText(const IQOutSmpRate & smpRate, const char * pacPreText)
{
LOG_PRO( LOG_DEBUG, "IQ Output Sample Rate Information :");
LOG_PRO( LOG_DEBUG, "IQ Output Sample Rate: %s", getText(smpRate) );
LOG_PRO(LOG_DEBUG, "%s IQ Sample Rate: %u Hz", pacPreText, unsigned(smpRate));
}

void RFspaceNetSDRControl::printText( const UDPPacketSize & packetSize )
void RFspaceNetSDRControl::printText(const UDPPacketSize & packetSize, const char * pacPreText)
{
LOG_PRO( LOG_DEBUG, "IQ UDP Packet Size Information : ");
LOG_PRO( LOG_DEBUG, "UDP Packet Size: %s", getText(packetSize) );
LOG_PRO(LOG_DEBUG, "%s UDP Packet Size: %s", pacPreText, getText(packetSize));
}

void RFspaceNetSDRControl::printUDPIPText( const char * ip )
void RFspaceNetSDRControl::printUDPIPText(const char * ip, const char * pacPreText)
{
LOG_PRO( LOG_DEBUG, "UDP IP Information : ");
LOG_PRO( LOG_DEBUG, "UDP IP : %s", ip);
LOG_PRO(LOG_DEBUG, "%s UDP IP : %s", pacPreText, ip);
}

void RFspaceNetSDRControl::printUDPPortNumText( const unsigned portNum )
void RFspaceNetSDRControl::printUDPPortNumText(const unsigned portNum, const char * pacPreText)
{
LOG_PRO( LOG_DEBUG, "UDP Port Number Information : ");
LOG_PRO( LOG_DEBUG, "UDP Port Number : %u", portNum);
}

void RFspaceNetSDRControl::printText( const CWStartup & cwStartup)
void RFspaceNetSDRControl::printText(const CWStartup & cwStartup, const char * pacPreText)
{

uint8_t len = sizeof(cwStartup.asciiMessage);
@@ -1658,12 +1642,10 @@ void RFspaceNetSDRControl::printText( const CWStartup & cwStartup)
LOG_PRO( LOG_DEBUG, "CW wpm: %u", cwStartup.cw_wpm);
LOG_PRO( LOG_DEBUG, "CW Frequency: %s", getText(cwStartup.eCwFreq));
LOG_PRO( LOG_DEBUG, "CW Message: '%s'", stringMessage.c_str());

}

void RFspaceNetSDRControl::printText( const uint8_t & chnMode)
void RFspaceNetSDRControl::printText(const uint8_t & chnMode, const char * pacPreText)
{
LOG_PRO( LOG_DEBUG, "Receiver Channel Setup Information : ");
LOG_PRO( LOG_DEBUG, "Receiver Channel Setup: %s", getText(chnMode));
}

@@ -1820,25 +1802,6 @@ const char * getText( RFspaceNetSDRControl::ADGain e)
}
}

const char * getText( RFspaceNetSDRControl::IQOutSmpRate e)
{
switch (e)
{
case RFspaceNetSDRControl::IQOutSmpRate::SR_12_5kHz: return "12.5 kHz";
case RFspaceNetSDRControl::IQOutSmpRate::SR_32kHz: return "32 kHz";
case RFspaceNetSDRControl::IQOutSmpRate::SR_62_5kHz: return "62.5 kHz";
case RFspaceNetSDRControl::IQOutSmpRate::SR_100kHz: return "100 kHz";
case RFspaceNetSDRControl::IQOutSmpRate::SR_125kHz: return "125 kHz";
case RFspaceNetSDRControl::IQOutSmpRate::SR_250kHz: return "250 kHz";
case RFspaceNetSDRControl::IQOutSmpRate::SR_500kHz: return "500 kHz";
case RFspaceNetSDRControl::IQOutSmpRate::SR_625kHz: return "625 kHz";
case RFspaceNetSDRControl::IQOutSmpRate::SR_1000kHz: return "1 MHz";
case RFspaceNetSDRControl::IQOutSmpRate::SR_1666kHz: return "1.66 MHz";
case RFspaceNetSDRControl::IQOutSmpRate::SR_2000kHz: return "2 MHz";
default : return "ERROR";
}
}

const char * getText( RFspaceNetSDRControl::UDPPacketSize e)
{
switch (e)
70 changes: 43 additions & 27 deletions src/rfspace_netsdr_control.h
Original file line number Diff line number Diff line change
@@ -61,20 +61,33 @@ class RFspaceNetSDRControl
// 4.2.8 A/D Modes ***************
enum class ADGain : uint8_t { ADGain_1_5 = 0x02, ADGain_1 = 0x00 };

// A/D Converter frequency = 80 MHz
static const uint32_t ADC_FREQ = 80 * 1000 * 1000;

// 4.2.9I/Q Output Data Sample Rate ***************
// this enum has to be in sync with RFspaceNetReceiver::srate_bws[]
enum class IQOutSmpRate : uint32_t {
SR_12_5kHz = 80*1000*1000/6400
, SR_32kHz = 80*1000*1000/2500
, SR_62_5kHz = 80*1000*1000/1280
, SR_100kHz = 80*1000*1000/800
, SR_125kHz = 80*1000*1000/640
, SR_250kHz = 80*1000*1000/320
, SR_500kHz = 80*1000*1000/160
, SR_625kHz = 80*1000*1000/128
, SR_1000kHz = 80*1000*1000/80
, SR_1666kHz = 80*1000*1000/48
, SR_2000kHz = 80*1000*1000/40
SR_12kHz = ADC_FREQ / 6400
, SR_16kHz = ADC_FREQ / 5000
, SR_32kHz = ADC_FREQ / 2500
, SR_62kHz = ADC_FREQ / 1280
, SR_80kHz = ADC_FREQ / 1000
, SR_100kHz = ADC_FREQ / 800
, SR_125kHz = ADC_FREQ / 640
, SR_160kHz = ADC_FREQ / 500
, SR_200kHz = ADC_FREQ / 400
, SR_250kHz = ADC_FREQ / 320
, SR_312kHz = ADC_FREQ / 256
, SR_400kHz = ADC_FREQ / 200
, SR_500kHz = ADC_FREQ / 160
, SR_625kHz = ADC_FREQ / 128
, SR_800kHz = ADC_FREQ / 100
, SR_1000kHz = ADC_FREQ / 80
, SR_1250kHz = ADC_FREQ / 64
, SR_1538kHz = ADC_FREQ / 52
, SR_1666kHz = ADC_FREQ / 48
, SR_1818kHz = ADC_FREQ / 44
, SR_2000kHz = ADC_FREQ / 40
};

// 4.4.2 Data Output Packet Size ***************
@@ -94,7 +107,7 @@ class RFspaceNetSDRControl
RFspaceNetSDRControl(RFspaceNetSDRControl::CallbackIfc * pCB = nullptr);
~RFspaceNetSDRControl();

bool connect( const char * ip, unsigned portNo );
bool connect(const char * ip, unsigned portNo, int nConnectTimeoutMillis = -1 );
bool close();
bool connected() const;

@@ -158,23 +171,26 @@ class RFspaceNetSDRControl
const char * getRcvChannelSetupText( uint8_t setup ) const;
const char * getRcvChannelText( uint8_t chn ) const;

private:

// PRINT-TEXT FUNCTIONS
static void printText( const Options & );
static void printUDPStateText( const bool & );
static void printBitDepthText( const int & );
static void printRcvFreqText( const uint64_t & );
static void printFilterText( const int & ); // hätte man auch "PrintText" belassen können, da Datentyp int bisher einmalig
static void printText( const bool & );
static void printText( const float & );
static void printText( const IQOutSmpRate & );
static void printText( const UDPPacketSize & );
static void printText( const RfGain & );
static void printUDPIPText( const char * ip );
static void printUDPPortNumText( const unsigned );
static void printText( const CWStartup & );
static void printText( const uint8_t & );
static void printText( const VUHFGains &);
static void printText(const Options &, const char * pacPreText = "received from device:");
static void printUDPStateText(const bool &, const char * pacPreText = "received from device:");
static void printBitDepthText(const int &, const char * pacPreText = "received from device:");
static void printRcvFreqText(const uint64_t &, const char * pacPreText = "received from device:");
static void printFilterText(const int &, const char * pacPreText = "received from device:");
static void printText(const bool &, const char * pacPreText = "received from device:");
static void printText(const float &, const char * pacPreText = "received from device:");
static void printText(const IQOutSmpRate &, const char * pacPreText = "received from device:");
static void printText(const UDPPacketSize &, const char * pacPreText = "received from device:");
static void printText(const RfGain &, const char * pacPreText = "received from device:");
static void printUDPIPText(const char * ip, const char * pacPreText = "received from device:");
static void printUDPPortNumText(const unsigned, const char * pacPreText = "received from device:");
static void printText(const CWStartup &, const char * pacPreText = "received from device:");
static void printText(const uint8_t &, const char * pacPreText = "received from device:");
static void printText(const VUHFGains &, const char * pacPreText = "received from device:");

public:

// STRUCT-DECLARATIONS
//**************************************************************
118 changes: 68 additions & 50 deletions src/rfspace_netsdr_receiver.cpp
Original file line number Diff line number Diff line change
@@ -7,18 +7,44 @@
#include <cstring>
#include <assert.h>

#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 };
// these tables have to be in sync with RFspaceNetSDRControl::IQOutSmpRate !!!

#define KHZ *1000

const RFspaceNetReceiver::srate_bw RFspaceNetReceiver::srate_bws[] =
{
{ 6400, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_12kHz ), 12500, 10 KHZ, "12.5 kHz" } // 0
, { 5000, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_16kHz ), 16 KHZ, 12 KHZ, "16 kHz" }
, { 2500, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_32kHz ), 32 KHZ, 25 KHZ, "32 kHz" }
, { 1280, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_62kHz ), 62500, 50 KHZ, "62.5 kHz" }
, { 1000, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_80kHz ), 80 KHZ, 64 KHZ, "80 kHz" }
, { 800, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_100kHz ), 100 KHZ, 80 KHZ, "100 kHz" } // 5
, { 640, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_125kHz ), 125 KHZ, 100 KHZ, "125 kHz" }
, { 500, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_160kHz ), 160 KHZ, 128 KHZ, "160 kHz" }
, { 400, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_200kHz ), 200 KHZ, 160 KHZ, "200 kHz" }
, { 320, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_250kHz ), 250 KHZ, 200 KHZ, "250 kHz" }
, { 256, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_312kHz ), 312500, 250 KHZ, "312.5 kHz" } // 10
, { 200, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_400kHz ), 400 KHZ, 320 KHZ, "400 kHz" }
, { 160, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_500kHz ), 500 KHZ, 400 KHZ, "500 kHz" }
, { 128, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_625kHz ), 625 KHZ, 500 KHZ, "625 kHz" }
, { 100, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_800kHz ), 800 KHZ, 640 KHZ, "800 kHz" }
, { 80, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_1000kHz), 1000 KHZ, 800 KHZ, "1 MHz" } // 15
, { 64, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_1250kHz), 1250 KHZ, 1000 KHZ, "1.25 MHz" }
, { 52, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_1538kHz), 1538461, 1200 KHZ, "1.538 MHz" }
, { 48, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_1666kHz), 1666666, 1300 KHZ, "1.666 MHz" }
, { 44, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_1818kHz), 1818181, 1400 KHZ, "1.818 MHz" }
, { 40, uint32_t(RFspaceNetSDRControl::IQOutSmpRate::SR_2000kHz), 2000 KHZ, 1600 KHZ, "2 MHz" } // 20
};

#undef KHZ

// 0 1 2 3 4 5 6 7
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 };
@@ -38,7 +64,7 @@ const RFspaceNetSDRControl::RfGain RFspaceNetReceiver::mVUHF_RFGainAttenuations[
const int RFspaceNetReceiver::miNumAttenuations = (int)( NUMEL(mafAttenuationATTs) );
const int RFspaceNetReceiver::miNumCompatibilityGains = (int)( sizeof(mafVUHFCompatibilityGainValues) / sizeof(mafVUHFCompatibilityGainValues[0]) );
const int RFspaceNetReceiver::miNumMultiGains = (int)( sizeof(mafVUHFMultiGainValues) / sizeof(mafVUHFMultiGainValues[0]) );
const int RFspaceNetReceiver::miNumSamplerates = (int)( sizeof(maiSamplerates) / sizeof(maiSamplerates[0]) );
const int RFspaceNetReceiver::miNumSamplerates = (int)(sizeof(srate_bws) / sizeof(srate_bws[0]));

#define NORMALIZE_DATA 0

@@ -223,7 +249,7 @@ void RFspaceNetReceiver::receiveRfspaceNetSDRUdpData( const int fmt, const void
{
if ( mLastReportedBitDepth != extHw_SampleFormat_PCM16 )
{
LOG_PRO( LOG_DEBUG, "SEND STATUS CHANGE OF 16 BIT DATA TO RCM !" );
LOG_PRO( LOG_DEBUG, "SEND STATUS CHANGE OF 16 BIT DATA TO SDR !" );
EXTIO_STATUS_CHANGE(mExtIOCallbackPtr , extHw_SampleFormat_PCM16 );
mLastReportedBitDepth = extHw_SampleFormat_PCM16;
mSampleBufferLenInFrames = 0;
@@ -260,7 +286,7 @@ void RFspaceNetReceiver::receiveRfspaceNetSDRUdpData( const int fmt, const void

if ( mLastReportedBitDepth != extHw_SampleFormat_PCM24 )
{
LOG_PRO( LOG_DEBUG, "SEND STATUS CHANGE OF 24 BIT DATA TO RCM !" );
LOG_PRO( LOG_DEBUG, "SEND STATUS CHANGE OF 24 BIT DATA TO SDR !" );
EXTIO_STATUS_CHANGE(mExtIOCallbackPtr , extHw_SampleFormat_PCM24 );
mLastReportedBitDepth = extHw_SampleFormat_PCM24;
mSampleBufferLenInFrames = 0;
@@ -448,7 +474,7 @@ void RFspaceNetReceiver::receiveRFspaceNetSDRControlInfo(Info info)
mpoSettings->uiSamplerate = actualIQSmpRate;
mpoSettings->uiLastReportedSamplerate = mpoSettings->uiSamplerate;
mpoSettings->iSampleRateIdx = getSmpRateIdx(actualIQSmpRate);
mpoSettings->uiBandwidth = maiBandwidths[mpoSettings->iSampleRateIdx];
mpoSettings->uiBandwidth = srate_bws[mpoSettings->iSampleRateIdx].bw;
LOG_PRO( LOG_ERROR, " RECEIVED CALLBACK WITH UNEXPECTED IQ_OUT_SAMPLERATE : %u Hz", actualIQSmpRate);
EXTIO_STATUS_CHANGE(mExtIOCallbackPtr , extHw_Changed_SampleRate );
}
@@ -506,7 +532,7 @@ bool RFspaceNetReceiver::openHW(Settings * poSettings)

mpoSettings = poSettings;

bool bTCPConnOK = rcv.connect( mpoSettings->acCtrlIP, mpoSettings->uCtrlPortNo );
bool bTCPConnOK = rcv.connect( mpoSettings->acCtrlIP, mpoSettings->uCtrlPortNo, mpoSettings->nConnectTimeoutMillis );
if ( !bTCPConnOK )
{
LOG_PRO( LOG_ERROR, "Error connecting to receiver %s:%u for control", mpoSettings->acCtrlIP, mpoSettings->uCtrlPortNo );
@@ -516,9 +542,9 @@ bool RFspaceNetReceiver::openHW(Settings * poSettings)
poSettings->bIsTCPConnected = true;

int samplerateIdx = poSettings->iSampleRateIdx;
samplerateIdx = PROCLIP(samplerateIdx, 0, int(NUMEL(maiSamplerates)));
samplerateIdx = PROCLIP(samplerateIdx, 0, int(NUMEL(srate_bws)));

poSettings->uiSamplerate = maiSamplerates[samplerateIdx];
poSettings->uiSamplerate = srate_bws[samplerateIdx].srate;
LOG_PRO( LOG_DEBUG, "********************************** RFspaceNetReceiver::openHW() : SENDING SAMPLERATE FREQUENCY TO NETSDR: %dHz (idx: %d)", poSettings->uiSamplerate, poSettings->iSampleRateIdx);

poSettings->iSampleRateIdx = samplerateIdx;
@@ -592,36 +618,27 @@ bool RFspaceNetReceiver::startHW(int64_t LOfreq)
}
rcv.setUDPInterface( mpoSettings->acDataIP, mpoSettings->uDataPortNo );

rcv.setRcvFreq( LOfreq );
mpoSettings->bIsSocketBound = true;
}

mpoSettings->iFrequency = LOfreq;
mSampleBufferLenInFrames = 0;

mSampleBufferLenInFrames = 0;
mChangeBitRangeSmpRateIdx = getMaxSmpRateIdx(mpoSettings->iBitDepthThresSamplerate);
mChangeBitRangeSmpRateIdx = getMaxSmpRateIdx(mpoSettings->iBitDepthThresSamplerate);

if( mpoSettings->iSampleRateIdx <= mChangeBitRangeSmpRateIdx)
{
//24 Bit
mOutBitSize = 8 * sizeof(LITTLE_INT24_T);
rcv.start24BitDataStream();
LOG_PRO( LOG_DEBUG, "****************RFspaceNetReceiver::startHW(%dHz): START 24 BIT DATA STREAM *********************************", LOfreq);
}
else
{
//16 Bit
mOutBitSize = 8 * sizeof(LITTLE_INT16_T);
rcv.start16BitDataStream();
LOG_PRO( LOG_DEBUG, "****************RFspaceNetReceiver::startHW(%dHz): START 16 BIT DATA STREAM *********************************", LOfreq);
}
rcv.setRcvFreq(LOfreq);
mpoSettings->iFrequency = LOfreq;

mpoSettings->bIsSocketBound = true;
return true;
setSamplerate(mpoSettings->iSampleRateIdx);

if (!mStartData)
{
//restart udp data (24bit/16bit) after "mStartUDPTimer" ms in "TimerProc" --> NetSDR sometimes streams wrong bitrate (although claiming it would stream the right bitrate).
//--> give samplerate change (and sometimes therefore bitdepth change) more time.
mStartUDPTimer = 100; //in ms
mStartData = true;
}
else
setSamplerate( mpoSettings->iSampleRateIdx);

return true;

}


@@ -757,7 +774,7 @@ void RFspaceNetReceiver::setGain( int idx )

void RFspaceNetReceiver::setSamplerate( int idx )
{
int numSamplerates = int(NUMEL(maiSamplerates));
int numSamplerates = int(NUMEL(srate_bws));

if ( idx < 0 || idx > numSamplerates )
{
@@ -766,31 +783,33 @@ void RFspaceNetReceiver::setSamplerate( int idx )
idx = newIdx;
}

mpoSettings->iSampleRateIdx = idx;
mpoSettings->uiSamplerate = srate_bws[idx].srate;
mpoSettings->uiBandwidth = srate_bws[idx].bw;

bool bOk = false;

bool bIsStreaming = rcv.isUDPDataStreamRunning(&bOk);

if (bIsStreaming && bOk)
{
mpoSettings->iSampleRateIdx = idx;
mpoSettings->uiSamplerate = maiSamplerates[idx];
mpoSettings->uiBandwidth = maiBandwidths[idx];

LOG_PRO( LOG_DEBUG, "************************************** RFspaceNetReceiver::setSamplerate(): send ChangedSamplerate-Callback *********************************");
EXTIO_STATUS_CHANGE(mExtIOCallbackPtr , extHw_Changed_SampleRate );
mpoSettings->uiLastReportedSamplerate = mpoSettings->uiSamplerate;

return;
}

LOG_PRO( LOG_DEBUG, "************************************** RFspaceNetReceiver::setSamplerate(): ready to set Samplerate and Bitdepth! *********************************");
// currently not streaming:
LOG_PRO(LOG_DEBUG, "************************************** RFspaceNetReceiver::setSamplerate(%u): set Samplerate ************************", mpoSettings->uiSamplerate);
rcv.setIQOutSmpRate(RFspaceNetSDRControl::IQOutSmpRate(mpoSettings->uiSamplerate));
LOG_PRO( LOG_DEBUG, " Report new Samplerate %u Hz", mpoSettings->uiSamplerate);

//restart udp data (24bit/16bit) after "mStartUDPTimer" ms in "TimerProc" --> NetSDR sometimes streams wrong bitrate (although claiming it would stream the right bitrate).
//--> give samplerate change (and sometimes therefore bitdepth change) more time.
mStartUDPTimer = 100; //in ms
mStartData = true;
if (0) // next startHW() should do
{
//restart udp data (24bit/16bit) after "mStartUDPTimer" ms in "TimerProc" --> NetSDR sometimes streams wrong bitrate (although claiming it would stream the right bitrate).
//--> give samplerate change (and sometimes therefore bitdepth change) more time.
mStartUDPTimer = 100; //in ms
mStartData = true;
}
}

int64_t RFspaceNetReceiver::getHWLO( void )
@@ -816,7 +835,7 @@ int RFspaceNetReceiver::getSmpRateIdx( uint32_t smpRate )
int ret = -1;
for(int idx = 0; idx < miNumSamplerates; ++idx)
{
int32_t delta = smpRate - maiSamplerates[idx];
int32_t delta = smpRate - srate_bws[idx].srate;
if( -10 <= delta && delta <= 10 ) // +/- 10 Hz tolerance
{
LOG_PRO( LOG_DEBUG, "********* RFspaceNetReceiver::getSmpRateIdx(%u) --> idx: %d", smpRate, idx);
@@ -837,7 +856,7 @@ int RFspaceNetReceiver::getMaxSmpRateIdx(uint32_t smpRate)
int ret = -1;
for (int idx = 0; idx < miNumSamplerates; ++idx)
{
if (smpRate >= maiSamplerates[idx])
if (smpRate >= srate_bws[idx].srate)
ret = idx;
}
if (ret == -1)
@@ -875,9 +894,8 @@ void RFspaceNetReceiver::TimerProc(uint16_t waitMs)

if(mStartUDPTimer <= 0)
{

setGain(mpoSettings->iControlValue);
mStartData = false;
setGain(mpoSettings->iControlValue);
if( mpoSettings->iSampleRateIdx <= mChangeBitRangeSmpRateIdx )
{
rcv.start24BitDataStream();
25 changes: 16 additions & 9 deletions src/rfspace_netsdr_receiver.h
Original file line number Diff line number Diff line change
@@ -28,20 +28,20 @@ class RFspaceNetReceiver
Settings()
{
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
strcpy(acDataIP, ""); // "" main PC: 192.168.8.100 PC2: 192.168.8.102
uCtrlPortNo = uDataPortNo = 50000; // 50000 / 50002
iSampleRateIdx = 2; // 2: 32 kHz samplerate
iAttenuationIdx = 0;
iAttenuationIdx = 6; // 6: 0 dB - no ATT & no ADC Gain

iBitDepthThresSamplerate = 1333333; // 1333.333 kHz == 80 MHz / 60

iBand_minFreq = 0;
iBand_maxFreq = 34 * 1000L * 1000L; // 0 - 34 MHz

uiBandwidth = 0;
uiSamplerate = 0;
uiBandwidth = 10000;
uiSamplerate = 12500;
uiLastReportedSamplerate = 0;
iFrequency = 0;
iFrequency = 7 * 1000 * 1000;
iLNAValue = 0;
iMixerValue = 0;
iIFOutputValue = 0;
@@ -54,7 +54,7 @@ class RFspaceNetReceiver
bUseVUHFAutoMode = true;
mfGainCompensationFactor = 1.0F;


nConnectTimeoutMillis = 1000;
}

char acCtrlIP[64];
@@ -92,10 +92,17 @@ class RFspaceNetReceiver

float mfGainCompensationFactor;

int nConnectTimeoutMillis;
};

static const uint32_t maiSamplerates[];
static const uint32_t maiBandwidths[];
static const struct srate_bw {
uint32_t decim;
uint32_t srate;
uint32_t srateval;
uint32_t bw;
const char * srateTxt;
} srate_bws[];

static const int miNumSamplerates;

static const float mafAttenuationATTs[];
17 changes: 11 additions & 6 deletions src/rfspace_netsdr_udpdata.cpp
Original file line number Diff line number Diff line change
@@ -108,7 +108,7 @@ bool RFspaceNetSDRUdpData::poll( )

while (1)
{
int rx = mSocket.Receive( MAX_UDP_LEN, &mRxBuffer[0] );
int rx = mSocket.Receive( MAX_UDP_LEN, &mRxBuffer[0] );

if ( rx > 0 )
{
@@ -122,20 +122,24 @@ bool RFspaceNetSDRUdpData::poll( )
}

return true;

}
}


bool RFspaceNetSDRUdpData::processReceivedDataMessage(unsigned rxLen)
{
if ( rxLen < 2 + 2 + 384 )
return false;

void * wp = &mRxBuffer[0];
const void * wp = &mRxBuffer[0];
const uint16_t uControlItemCode = READ_LITTLE_INT16( wp );
wp = &mRxBuffer[2];
const uint16_t uSequenceNum = READ_LITTLE_INT16( wp );

if (rxLen < 2 + 2 + 384)
{
LOG_PRO(LOG_PROTOCOL, "received too small UDP packet of length %u with %s control item 0x%x"
, rxLen, (rxLen >= 2 ? "valid" : "invalid"), unsigned(uControlItemCode));
return false;
}

bool bProcessed = true; // assume so

if ( uSequenceNum != uExpectedSequenceNum )
@@ -228,6 +232,7 @@ bool RFspaceNetSDRUdpData::processReceivedDataMessage(unsigned rxLen)
break;

default:
LOG_PRO(LOG_PROTOCOL, "received UDP packet with unknown control item 0x%x length %u", unsigned(uControlItemCode), rxLen);
bProcessed = false;
}

0 comments on commit 1a9eb30

Please sign in to comment.