1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-21 15:51:47 -05:00

Compare commits

...

2 Commits

Author SHA1 Message Date
f4exb
7c8cb7a85a Remote: more fixes in conversion routines 2021-12-20 22:30:43 +01:00
f4exb
ab9f316737 Remote sink/input: implemented choice of sample size in transmission. 2021-12-19 13:15:17 +01:00
26 changed files with 403 additions and 90 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

View File

@ -56,17 +56,6 @@ When the return key is hit within the address (1) or port (2) the changes are ef
This sets the number of FEC blocks per frame. A frame consists of 128 data blocks (1 meta data block followed by 127 I/Q data blocks) and a variable number of FEC blocks used to protect the UDP transmission with a Cauchy MDS block erasure correction. The two numbers next are the total number of blocks and the number of FEC blocks separated by a slash (/).
<h3>10: Delay between UDP blocks transmission</h3>
<h3>10: Transmission sample size</h3>
This sets the minimum delay between transmission of an UDP block (send datagram) and the next. This allows throttling of the UDP transmission that is otherwise uncontrolled and causes network congestion.
The value is a percentage of the nominal time it takes to process a block of samples corresponding to one UDP block (512 bytes). This is calculated as follows:
- Sample rate on the network: _SR_
- Delay percentage: _d_
- Number of FEC blocks: _F_
- There are 127 blocks of I/Q data per frame (1 meta block for 128 blocks) and each I/Q data block of 512 bytes (128 samples) has a 8 bytes header (2 samples) thus there are 126 samples remaining effectively. This gives the constant 127*126 = 16002 samples per frame in the formula
Formula: ((127 &#x2715; 126 &#x2715; _d_) / _SR_) / (128 + _F_)
The percentage appears first at the right of the dial button and then the actual delay value in microseconds.
Number of bytes per I or Q sample in transmission.

View File

@ -209,6 +209,14 @@ void RemoteSink::applySettings(const RemoteSinkSettings& settings, bool force)
frequencyOffsetChange = true;
}
if ((m_settings.m_nbTxBytes != settings.m_nbTxBytes) || force)
{
reverseAPIKeys.append("nbTxBytes");
stop();
m_basebandSink->setNbTxBytes(settings.m_nbTxBytes);
start();
}
if (m_settings.m_streamIndex != settings.m_streamIndex)
{
if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only
@ -318,6 +326,10 @@ void RemoteSink::webapiUpdateChannelSettings(
}
}
if (channelSettingsKeys.contains("nbTxBytes")) {
settings.m_nbTxBytes = response.getRemoteSinkSettings()->getNbTxBytes();
}
if (channelSettingsKeys.contains("dataAddress")) {
settings.m_dataAddress = *response.getRemoteSinkSettings()->getDataAddress();
}
@ -383,6 +395,7 @@ void RemoteSink::webapiFormatChannelSettings(SWGSDRangel::SWGChannelSettings& re
response.getRemoteSinkSettings()->setDataAddress(new QString(settings.m_dataAddress));
}
response.getRemoteSinkSettings()->setNbTxBytes(settings.m_nbTxBytes);
response.getRemoteSinkSettings()->setDataPort(settings.m_dataPort);
response.getRemoteSinkSettings()->setRgbColor(settings.m_rgbColor);
@ -488,6 +501,9 @@ void RemoteSink::webapiFormatChannelSettings(
if (channelSettingsKeys.contains("nbFECBlocks") || force) {
swgRemoteSinkSettings->setNbFecBlocks(settings.m_nbFECBlocks);
}
if (channelSettingsKeys.contains("nbTxBytes") || force) {
swgRemoteSinkSettings->setNbTxBytes(settings.m_nbTxBytes);
}
if (channelSettingsKeys.contains("dataAddress") || force) {
swgRemoteSinkSettings->setDataAddress(new QString(settings.m_dataAddress));
}

View File

@ -52,6 +52,7 @@ void RemoteSinkBaseband::reset()
{
QMutexLocker mutexLocker(&m_mutex);
m_sampleFifo.reset();
m_sink.init();
}
void RemoteSinkBaseband::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
@ -155,4 +156,4 @@ void RemoteSinkBaseband::setBasebandSampleRate(int sampleRate)
m_basebandSampleRate = sampleRate;
m_channelizer->setBasebandSampleRate(m_basebandSampleRate);
m_sink.applyBasebandSampleRate(m_basebandSampleRate);
}
}

View File

@ -64,6 +64,7 @@ public:
void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
void startSender() { m_sink.startSender(); }
void stopSender() { m_sink.stopSender(); }
void setNbTxBytes(uint32_t nbTxBytes) { m_sink.setNbTxBytes(nbTxBytes); }
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
int getChannelSampleRate() const;

View File

@ -168,6 +168,7 @@ void RemoteSinkGUI::displaySettings()
QString s = QString::number(128 + m_settings.m_nbFECBlocks, 'f', 0);
QString s1 = QString::number(m_settings.m_nbFECBlocks, 'f', 0);
ui->nominalNbBlocksText->setText(tr("%1/%2").arg(s).arg(s1));
ui->nbTxBytes->setCurrentIndex(log2(m_settings.m_nbTxBytes));
applyDecimation();
displayStreamIndex();
restoreState(m_settings.m_rollupState);
@ -333,6 +334,12 @@ void RemoteSinkGUI::on_nbFECBlocks_valueChanged(int value)
applySettings();
}
void RemoteSinkGUI::on_nbTxBytes_currentIndexChanged(int index)
{
m_settings.m_nbTxBytes = 1 << index;
applySettings();
}
void RemoteSinkGUI::applyDecimation()
{
uint32_t maxHash = 1;

View File

@ -88,6 +88,7 @@ private slots:
void on_dataPort_returnPressed();
void on_dataApplyButton_clicked(bool checked);
void on_nbFECBlocks_valueChanged(int value);
void on_nbTxBytes_currentIndexChanged(int index);
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDialogCalled(const QPoint& p);
void tick();

View File

@ -395,6 +395,41 @@
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="nbTxBytesLabel">
<property name="text">
<string>Tx bytes</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="nbTxBytes">
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Number of transmitted bytes per I or Q sample</string>
</property>
<item>
<property name="text">
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>2</string>
</property>
</item>
<item>
<property name="text">
<string>4</string>
</property>
</item>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_3">
<property name="orientation">

View File

@ -37,6 +37,7 @@ RemoteSinkSettings::RemoteSinkSettings()
void RemoteSinkSettings::resetToDefaults()
{
m_nbFECBlocks = 0;
m_nbTxBytes = 2;
m_dataAddress = "127.0.0.1";
m_dataPort = 9090;
m_rgbColor = QColor(140, 4, 4).rgb();
@ -56,6 +57,7 @@ QByteArray RemoteSinkSettings::serialize() const
{
SimpleSerializer s(1);
s.writeU32(1, m_nbFECBlocks);
s.writeU32(2, m_nbTxBytes);
s.writeString(3, m_dataAddress);
s.writeU32(4, m_dataPort);
s.writeU32(5, m_rgbColor);
@ -96,6 +98,7 @@ bool RemoteSinkSettings::deserialize(const QByteArray& data)
m_nbFECBlocks = 0;
}
d.readU32(2, &m_nbTxBytes, 2);
d.readString(3, &m_dataAddress, "127.0.0.1");
d.readU32(4, &tmp, 0);

View File

@ -32,6 +32,7 @@ class Serializable;
struct RemoteSinkSettings
{
uint16_t m_nbFECBlocks;
uint32_t m_nbTxBytes;
QString m_dataAddress;
uint16_t m_dataPort;
quint32 m_rgbColor;

View File

@ -36,6 +36,7 @@ RemoteSinkSink::RemoteSinkSink() :
m_frequencyOffset(0),
m_basebandSampleRate(48000),
m_nbBlocksFEC(0),
m_nbTxBytes(SDR_RX_SAMP_SZ <= 16 ? 2 : 4),
m_dataAddress("127.0.0.1"),
m_dataPort(9090)
{
@ -68,6 +69,14 @@ void RemoteSinkSink::stopSender()
m_senderThread->wait();
}
void RemoteSinkSink::init()
{
m_dataFrame = nullptr;
m_txBlockIndex = 0;
m_frameCount = 0;
m_sampleIndex = 0;
}
void RemoteSinkSink::setNbBlocksFEC(int nbBlocksFEC)
{
qDebug() << "RemoteSinkSink::setNbBlocksFEC: nbBlocksFEC: " << nbBlocksFEC;
@ -92,8 +101,8 @@ void RemoteSinkSink::feed(const SampleVector::const_iterator& begin, const Sampl
metaData.m_centerFrequency = m_deviceCenterFrequency + m_frequencyOffset;
metaData.m_sampleRate = m_basebandSampleRate / (1<<m_settings.m_log2Decim);
metaData.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
metaData.m_sampleBits = SDR_RX_SAMP_SZ;
metaData.m_sampleBytes = m_nbTxBytes;
metaData.m_sampleBits = getNbSampleBits();
metaData.m_nbOriginalBlocks = RemoteNbOrginalBlocks;
metaData.m_nbFECBlocks = m_nbBlocksFEC;
metaData.m_tv_sec = nowus / 1000000UL; // tv.tv_sec;
@ -110,8 +119,8 @@ void RemoteSinkSink::feed(const SampleVector::const_iterator& begin, const Sampl
superBlock.init();
superBlock.m_header.m_frameIndex = m_frameCount;
superBlock.m_header.m_blockIndex = m_txBlockIndex;
superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
superBlock.m_header.m_sampleBytes = m_nbTxBytes;
superBlock.m_header.m_sampleBits = getNbSampleBits();
RemoteMetaDataFEC *destMeta = (RemoteMetaDataFEC *) &superBlock.m_protectedBlock;
*destMeta = metaData;
@ -135,27 +144,29 @@ void RemoteSinkSink::feed(const SampleVector::const_iterator& begin, const Sampl
} // block zero
// handle different sample sizes...
int samplesPerBlock = RemoteNbBytesPerBlock / (SDR_RX_SAMP_SZ <= 16 ? 4 : 8); // two I or Q samples
int samplesPerBlock = RemoteNbBytesPerBlock / (2 * m_nbTxBytes); // two I or Q samples
if (m_sampleIndex + inRemainingSamples < samplesPerBlock) // there is still room in the current super block
{
memcpy((void *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
(const void *) &(*(begin+inSamplesIndex)),
inRemainingSamples * sizeof(Sample));
convertSampleToData(begin + inSamplesIndex, inRemainingSamples, false);
// memcpy((void *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
// (const void *) &(*(begin+inSamplesIndex)),
// inRemainingSamples * sizeof(Sample));
m_sampleIndex += inRemainingSamples;
it = end; // all input samples are consumed
}
else // complete super block and initiate the next if not end of frame
{
memcpy((void *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
(const void *) &(*(begin+inSamplesIndex)),
(samplesPerBlock - m_sampleIndex) * sizeof(Sample));
convertSampleToData(begin + inSamplesIndex, samplesPerBlock - m_sampleIndex, false);
// memcpy((void *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
// (const void *) &(*(begin+inSamplesIndex)),
// (samplesPerBlock - m_sampleIndex) * sizeof(Sample));
it += samplesPerBlock - m_sampleIndex;
m_sampleIndex = 0;
m_superBlock.m_header.m_frameIndex = m_frameCount;
m_superBlock.m_header.m_blockIndex = m_txBlockIndex;
m_superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
m_superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
m_superBlock.m_header.m_sampleBytes = m_nbTxBytes;
m_superBlock.m_header.m_sampleBits = getNbSampleBits();
m_dataFrame->m_superBlocks[m_txBlockIndex] = m_superBlock;
if (m_txBlockIndex == RemoteNbOrginalBlocks - 1) // frame complete
@ -215,3 +226,16 @@ void RemoteSinkSink::applyBasebandSampleRate(uint32_t sampleRate)
double shiftFactor = HBFilterChainConverter::getShiftFactor(m_settings.m_log2Decim, m_settings.m_filterChainHash);
m_frequencyOffset = round(shiftFactor*m_basebandSampleRate);
}
uint32_t RemoteSinkSink::getNbSampleBits()
{
if (m_nbTxBytes == 1) {
return 8;
} else if (m_nbTxBytes == 2) {
return 16;
} else if (m_nbTxBytes == 4) {
return 24;
} else {
return 16;
}
}

View File

@ -40,7 +40,9 @@ public:
void startSender();
void stopSender();
void init();
void setNbTxBytes(uint32_t nbTxBytes) { m_nbTxBytes = nbTxBytes; }
void applySettings(const RemoteSinkSettings& settings, bool force = false);
void applyBasebandSampleRate(uint32_t sampleRate);
void setDeviceCenterFrequency(uint64_t frequency) { m_deviceCenterFrequency = frequency; }
@ -61,10 +63,84 @@ private:
int64_t m_frequencyOffset;
uint32_t m_basebandSampleRate;
int m_nbBlocksFEC;
uint32_t m_nbTxBytes;
QString m_dataAddress;
uint16_t m_dataPort;
void setNbBlocksFEC(int nbBlocksFEC);
uint32_t getNbSampleBits();
inline void convertSampleToData(const SampleVector::const_iterator& begin, int nbSamples, bool isTx)
{
if (sizeof(Sample) == m_nbTxBytes * 2) // 16 -> 16 or 24 ->24: direct copy
{
memcpy((void *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*m_nbTxBytes*2],
(const void *) &(*(begin)),
nbSamples * sizeof(Sample));
}
else if (isTx)
{
if (m_nbTxBytes == 4) // just convert type int16_t -> int32_t (always 16 bit wide)
{
for (int i = 0; i < nbSamples; i++)
{
*((int32_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (begin+i)->m_real;
*((int32_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (begin+i)->m_imag;
}
}
else if (m_nbTxBytes == 2) //just convert type int32_t -> int16_t (always 16 bit wide)
{
for (int i = 0; i < nbSamples; i++)
{
*((int16_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (begin+i)->m_real;
*((int16_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (begin+i)->m_imag;
}
}
else if (m_nbTxBytes == 1) // 16 or 24 -> 8
{
for (int i = 0; i < nbSamples; i++)
{
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (int8_t) ((begin+i)->m_real / (1<<8));
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (int8_t) ((begin+i)->m_imag / (1<<8));
}
}
}
else
{
if (m_nbTxBytes == 4) // 16 -> 24
{
for (int i = 0; i < nbSamples; i++)
{
*((int32_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (begin+i)->m_real * (1<<8);
*((int32_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (begin+i)->m_imag * (1<<8);
}
}
else if (m_nbTxBytes == 2) // 24 -> 16
{
for (int i = 0; i < nbSamples; i++)
{
*((int16_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (begin+i)->m_real / (1<<8);
*((int16_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (begin+i)->m_imag / (1<<8);
}
}
else if ((m_nbTxBytes == 1) && (sizeof(Sample) == 4)) // 16 -> 8
{
for (int i = 0; i < nbSamples; i++)
{
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (int8_t) ((begin+i)->m_real / (1<<8));
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (int8_t) ((begin+i)->m_imag / (1<<8));
}
}
else if ((m_nbTxBytes == 1) && (sizeof(Sample) == 8)) // 24 -> 8
{
for (int i = 0; i < nbSamples; i++)
{
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (int8_t) ((begin+i)->m_real / (1<<16));
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (int8_t) ((begin+i)->m_imag / (1<<16));
}
}
}
}
};
#endif // INCLUDE_REMOTESINKSINK_H_

View File

@ -45,6 +45,10 @@ This is the device set index in the remote instance to which the stream is conne
This is the channel index of the Remote source in the remote instance to which the stream is connected to. Use this value to properly address the API to get status.
<h3>6a: transmission sample size</h3>
This is the size in bytes of a transmitted I or Q sample. The choice is between 1, 2 and 4 bytes. Conversion takes place if the size is different from the built-in sample size.
<h3>7: Forward Error Correction setting and status</h3>
![SDR Remote output FEC GUI](../../../doc/img/RemoteOutput_plugin_06.png)

View File

@ -35,7 +35,6 @@ UDPSinkFEC::UDPSinkFEC() :
m_txDelayRatio(0.0),
m_dataFrame(nullptr),
m_txBlockIndex(0),
m_txBlocksIndex(0),
m_frameCount(0),
m_sampleIndex(0),
m_remoteOutputSender(nullptr),
@ -61,7 +60,6 @@ void UDPSinkFEC::init()
{
m_dataFrame = nullptr;
m_txBlockIndex = 0;
m_txBlocksIndex = 0;
m_frameCount = 0;
m_sampleIndex = 0;
}

View File

@ -92,7 +92,6 @@ private:
RemoteDataFrame *m_dataFrame;
RemoteSuperBlock m_superBlock; //!< current super block being built
int m_txBlockIndex; //!< Current index in blocks to transmit in the Tx row
int m_txBlocksIndex; //!< Current index of Tx blocks row
uint16_t m_frameCount; //!< transmission frame count
int m_sampleIndex; //!< Current sample index in protected block data
@ -129,12 +128,12 @@ private:
*((int16_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (begin+i)->m_imag;
}
}
else if (m_nbTxBytes == 1) // 16 -> 8
else if (m_nbTxBytes == 1) // 16 or 24 -> 8
{
for (int i = 0; i < nbSamples; i++)
{
m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2] = (uint8_t) ((begin+i)->m_real / 256);
m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes] = (uint8_t) ((begin+i)->m_imag / 256);
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (int8_t) ((begin+i)->m_real / (1<<8));
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (int8_t) ((begin+i)->m_imag / (1<<8));
}
}
}
@ -144,26 +143,32 @@ private:
{
for (int i = 0; i < nbSamples; i++)
{
*((int32_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (begin+i)->m_real << 8;
*((int32_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (begin+i)->m_imag << 8;
*((int32_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (begin+i)->m_real * (1<<8);
*((int32_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (begin+i)->m_imag * (1<<8);
}
}
else if (m_nbTxBytes == 2) // 24 -> 16
{
for (int i = 0; i < nbSamples; i++)
{
*((int16_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (begin+i)->m_real >> 8;
*((int16_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (begin+i)->m_imag >> 8;
*((int16_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (begin+i)->m_real / (1<<8);
*((int16_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (begin+i)->m_imag / (1<<8);
}
}
else if (m_nbTxBytes == 1) // 16 or 24 -> 8
else if ((m_nbTxBytes == 1) && (sizeof(Sample) == 4)) // 16 -> 8
{
for (int i = 0; i < nbSamples; i++)
{
m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2] =
(uint8_t) (((begin+i)->m_real / (1<<sizeof(Sample)*2)) & 0xFF);
m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes] =
(uint8_t) (((begin+i)->m_imag / (1<<sizeof(Sample)*2)) & 0xFF);
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (int8_t) ((begin+i)->m_real / (1<<8));
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (int8_t) ((begin+i)->m_imag / (1<<8));
}
}
else if ((m_nbTxBytes == 1) && (sizeof(Sample) == 4)) // 24 -> 8
{
for (int i = 0; i < nbSamples; i++)
{
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (int8_t) ((begin+i)->m_real / (1<<16));
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (int8_t) ((begin+i)->m_imag / (1<<16));
}
}
}

View File

@ -326,27 +326,13 @@ void RemoteInputUDPHandler::tick()
const RemoteMetaDataFEC& metaData = m_remoteInputBuffer.getCurrentMeta();
m_readLength = m_readLengthSamples * (metaData.m_sampleBytes & 0xF) * 2;
if ((metaData.m_sampleBits == 16) && (SDR_RX_SAMP_SZ == 24)) // 16 -> 24 bits
if (metaData.m_sampleBits == SDR_RX_SAMP_SZ) // no conversion
{
if (m_readLengthSamples > (int) m_converterBufferNbSamples)
{
if (m_converterBuffer) { delete[] m_converterBuffer; }
m_converterBuffer = new int32_t[m_readLengthSamples*2];
}
uint8_t *buf = m_remoteInputBuffer.readData(m_readLength);
for (int is = 0; is < m_readLengthSamples; is++)
{
m_converterBuffer[2*is] = ((int16_t*)buf)[2*is]; // I
m_converterBuffer[2*is]<<=8;
m_converterBuffer[2*is+1] = ((int16_t*)buf)[2*is+1]; // Q
m_converterBuffer[2*is+1]<<=8;
}
m_sampleFifo->write(reinterpret_cast<quint8*>(m_converterBuffer), m_readLengthSamples*sizeof(Sample));
// read samples directly feeding the SampleFifo (no callback)
m_sampleFifo->write(reinterpret_cast<quint8*>(m_remoteInputBuffer.readData(m_readLength)), m_readLength);
m_samplesCount += m_readLengthSamples;
}
else if ((metaData.m_sampleBits == 24) && (SDR_RX_SAMP_SZ == 16)) // 24 -> 16 bits
else if ((metaData.m_sampleBits == 8) && (SDR_RX_SAMP_SZ == 16)) // 8 -> 16
{
if (m_readLengthSamples > (int) m_converterBufferNbSamples)
{
@ -354,28 +340,125 @@ void RemoteInputUDPHandler::tick()
m_converterBuffer = new int32_t[m_readLengthSamples];
}
uint8_t *buf = m_remoteInputBuffer.readData(m_readLength);
int8_t *buf = (int8_t*) m_remoteInputBuffer.readData(m_readLength);
for (int is = 0; is < m_readLengthSamples; is++)
{
m_converterBuffer[is] = ((int32_t *)buf)[2*is+1]>>8; // Q -> MSB
m_converterBuffer[is] <<=16;
m_converterBuffer[is] += ((int32_t *)buf)[2*is]>>8; // I -> LSB
m_converterBuffer[is] = buf[2*is+1] * (1<<8); // Q -> MSB
m_converterBuffer[is] <<= 16;
m_converterBuffer[is] += buf[2*is] * (1<<8); // I -> LSB
}
}
else if ((metaData.m_sampleBits == 8) && (SDR_RX_SAMP_SZ == 24)) // 8 -> 24
{
if (m_readLengthSamples > (int) m_converterBufferNbSamples)
{
if (m_converterBuffer) { delete[] m_converterBuffer; }
m_converterBuffer = new int32_t[m_readLengthSamples*2];
}
int8_t *buf = (int8_t*) m_remoteInputBuffer.readData(m_readLength);
for (int is = 0; is < m_readLengthSamples; is++)
{
m_converterBuffer[2*is] = buf[2*is] * (1<<16); // I
m_converterBuffer[2*is+1] = buf[2*is+1] * (1<<16); // Q
}
m_sampleFifo->write(reinterpret_cast<quint8*>(m_converterBuffer), m_readLengthSamples*sizeof(Sample));
}
else if ((metaData.m_sampleBits == 16) || (metaData.m_sampleBits == 24)) // same sample size and valid size
else if (metaData.m_sampleBits == 16) // 16 -> 24
{
// read samples directly feeding the SampleFifo (no callback)
m_sampleFifo->write(reinterpret_cast<quint8*>(m_remoteInputBuffer.readData(m_readLength)), m_readLength);
m_samplesCount += m_readLengthSamples;
if (m_readLengthSamples > (int) m_converterBufferNbSamples)
{
if (m_converterBuffer) { delete[] m_converterBuffer; }
m_converterBuffer = new int32_t[m_readLengthSamples*2];
}
int16_t *buf = (int16_t*) m_remoteInputBuffer.readData(m_readLength);
for (int is = 0; is < m_readLengthSamples; is++)
{
m_converterBuffer[2*is] = buf[2*is] * (1<<8); // I
m_converterBuffer[2*is+1] = buf[2*is+1] * (1<<8); // Q
}
m_sampleFifo->write(reinterpret_cast<quint8*>(m_converterBuffer), m_readLengthSamples*sizeof(Sample));
}
else if (metaData.m_sampleBits == 24) // 24 -> 16
{
if (m_readLengthSamples > (int) m_converterBufferNbSamples)
{
if (m_converterBuffer) { delete[] m_converterBuffer; }
m_converterBuffer = new int32_t[m_readLengthSamples];
}
int32_t *buf = (int32_t*) m_remoteInputBuffer.readData(m_readLength);
for (int is = 0; is < m_readLengthSamples; is++)
{
m_converterBuffer[is] = buf[2*is+1] / (1<<8); // Q -> MSB
m_converterBuffer[is] <<= 16;
m_converterBuffer[is] += buf[2*is] / (1<<8); // I -> LSB
}
m_sampleFifo->write(reinterpret_cast<quint8*>(m_converterBuffer), m_readLengthSamples*sizeof(Sample));
}
else // invalid size
{
qWarning("RemoteInputUDPHandler::tick: unexpected sample size in stream: %d bits", (int) metaData.m_sampleBits);
}
// if ((metaData.m_sampleBits == 16) && (SDR_RX_SAMP_SZ == 24)) // 16 -> 24 bits
// {
// if (m_readLengthSamples > (int) m_converterBufferNbSamples)
// {
// if (m_converterBuffer) { delete[] m_converterBuffer; }
// m_converterBuffer = new int32_t[m_readLengthSamples*2];
// }
// uint8_t *buf = m_remoteInputBuffer.readData(m_readLength);
// for (int is = 0; is < m_readLengthSamples; is++)
// {
// m_converterBuffer[2*is] = ((int16_t*)buf)[2*is]; // I
// m_converterBuffer[2*is]<<=8;
// m_converterBuffer[2*is+1] = ((int16_t*)buf)[2*is+1]; // Q
// m_converterBuffer[2*is+1]<<=8;
// }
// m_sampleFifo->write(reinterpret_cast<quint8*>(m_converterBuffer), m_readLengthSamples*sizeof(Sample));
// }
// else if ((metaData.m_sampleBits == 24) && (SDR_RX_SAMP_SZ == 16)) // 24 -> 16 bits
// {
// if (m_readLengthSamples > (int) m_converterBufferNbSamples)
// {
// if (m_converterBuffer) { delete[] m_converterBuffer; }
// m_converterBuffer = new int32_t[m_readLengthSamples];
// }
// uint8_t *buf = m_remoteInputBuffer.readData(m_readLength);
// for (int is = 0; is < m_readLengthSamples; is++)
// {
// m_converterBuffer[is] = ((int32_t *)buf)[2*is+1]>>8; // Q -> MSB
// m_converterBuffer[is] <<=16;
// m_converterBuffer[is] += ((int32_t *)buf)[2*is]>>8; // I -> LSB
// }
// m_sampleFifo->write(reinterpret_cast<quint8*>(m_converterBuffer), m_readLengthSamples*sizeof(Sample));
// }
// else if ((metaData.m_sampleBits == 16) || (metaData.m_sampleBits == 24)) // same sample size and valid size
// {
// // read samples directly feeding the SampleFifo (no callback)
// m_sampleFifo->write(reinterpret_cast<quint8*>(m_remoteInputBuffer.readData(m_readLength)), m_readLength);
// m_samplesCount += m_readLengthSamples;
// }
// else // invalid size
// {
// qWarning("RemoteInputUDPHandler::tick: unexpected sample size in stream: %d bits", (int) metaData.m_sampleBits);
// }
if (m_tickCount < m_rateDivider)
{
m_tickCount++;

View File

@ -70,24 +70,23 @@ private:
{
if (sampleSize == 2) // 8 -> 16 bits
{
int8_t iu = m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize];
int8_t qu = m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+1];
iconv = iu * (1 << 8);
qconv = qu * (1 << 8);
int8_t *buf = (int8_t*) m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf;
iconv = buf[sampleIndex*sampleSize] * (1<<8);
qconv = buf[sampleIndex*sampleSize+1] * (1<<8);
s.setReal(iconv);
s.setImag(qconv);
}
else if (sampleSize == 4) // just convert types (always 16 bits wide)
{
iconv = ((int16_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize]))[0];
qconv = ((int16_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+2]))[0];
iconv = *((int16_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize]));
qconv = *((int16_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+2]));
s.setReal(iconv);
s.setImag(qconv);
}
else if (sampleSize == 8) // just convert types (always 16 bits wide)
{
iconv = ((int32_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize]))[0];
qconv = ((int32_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+4]))[0];
iconv = *((int32_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize]));
qconv = *((int32_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+4]));
s.setReal(iconv);
s.setImag(qconv);
}
@ -98,26 +97,33 @@ private:
}
else
{
if (sampleSize == 2) // 8 -> 16 or 24 bits
if ((sampleSize == 2) && (sizeof(Sample) == 2)) // 8 -> 16 bits
{
int8_t iu = m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize];
int8_t qu = m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+1];
iconv = iu * (1 << sizeof(Sample)*2);
qconv = qu * (1 << sizeof(Sample)*2);
int8_t *buf = (int8_t*) m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf;
iconv = buf[sampleIndex*sampleSize] * (1<<8);
qconv = buf[sampleIndex*sampleSize+1] * (1<<8);
s.setReal(iconv);
s.setImag(qconv);
}
else if ((sampleSize == 2) && (sizeof(Sample) == 4)) // 8 -> 24 bits
{
int8_t *buf = (int8_t*) m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf;
iconv = buf[sampleIndex*sampleSize] * (1<<16);
qconv = buf[sampleIndex*sampleSize+1] * (1<<16);
s.setReal(iconv);
s.setImag(qconv);
}
else if (sampleSize == 4) // 16 -> 24 bits
{
iconv = ((int16_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize]))[0] << 8;
qconv = ((int16_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+2]))[0] << 8;
iconv = *((int16_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize])) * (1<<8);
qconv = *((int16_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+2])) * (1<<8);
s.setReal(iconv);
s.setImag(qconv);
}
else if (sampleSize == 8) // 24 -> 16 bits
{
iconv = ((int32_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize]))[0] >> 8;
qconv = ((int32_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+4]))[0] >> 8;
iconv = *((int32_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize])) / (1<<8);
qconv = *((int32_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+4])) / (1<<8);
s.setReal(iconv);
s.setImag(qconv);
}

View File

@ -9864,7 +9864,8 @@ margin-bottom: 20px;
"type" : "integer"
},
"nbTxBytes" : {
"type" : "integer"
"type" : "integer",
"description" : "Number of bytes in a transmited I or Q sample\n * 1\n * 2\n * 4\n"
},
"apiAddress" : {
"type" : "string"
@ -9906,6 +9907,10 @@ margin-bottom: 20px;
"type" : "integer",
"description" : "Number of FEC blocks per frame"
},
"nbTxBytes" : {
"type" : "integer",
"description" : "Number of bytes in a transmited I or Q sample\n * 1\n * 2\n * 4\n"
},
"dataAddress" : {
"type" : "string",
"description" : "Receiving USB data address"
@ -51625,7 +51630,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2021-12-18T22:54:13.645+01:00
Generated 2021-12-19T12:04:51.409+01:00
</div>
</div>
</div>

View File

@ -5,6 +5,11 @@ RemoteOutputSettings:
type: integer
nbTxBytes:
type: integer
description: >
Number of bytes in a transmited I or Q sample
* 1
* 2
* 4
apiAddress:
type: string
apiPort:

View File

@ -4,6 +4,13 @@ RemoteSinkSettings:
nbFECBlocks:
description: "Number of FEC blocks per frame"
type: integer
nbTxBytes:
type: integer
description: >
Number of bytes in a transmited I or Q sample
* 1
* 2
* 4
dataAddress:
description: "Receiving USB data address"
type: string

View File

@ -5,6 +5,11 @@ RemoteOutputSettings:
type: integer
nbTxBytes:
type: integer
description: >
Number of bytes in a transmited I or Q sample
* 1
* 2
* 4
apiAddress:
type: string
apiPort:

View File

@ -4,6 +4,13 @@ RemoteSinkSettings:
nbFECBlocks:
description: "Number of FEC blocks per frame"
type: integer
nbTxBytes:
type: integer
description: >
Number of bytes in a transmited I or Q sample
* 1
* 2
* 4
dataAddress:
description: "Receiving USB data address"
type: string

View File

@ -9864,7 +9864,8 @@ margin-bottom: 20px;
"type" : "integer"
},
"nbTxBytes" : {
"type" : "integer"
"type" : "integer",
"description" : "Number of bytes in a transmited I or Q sample\n * 1\n * 2\n * 4\n"
},
"apiAddress" : {
"type" : "string"
@ -9906,6 +9907,10 @@ margin-bottom: 20px;
"type" : "integer",
"description" : "Number of FEC blocks per frame"
},
"nbTxBytes" : {
"type" : "integer",
"description" : "Number of bytes in a transmited I or Q sample\n * 1\n * 2\n * 4\n"
},
"dataAddress" : {
"type" : "string",
"description" : "Receiving USB data address"
@ -51625,7 +51630,7 @@ except ApiException as e:
</div>
<div id="generator">
<div class="content">
Generated 2021-12-18T22:54:13.645+01:00
Generated 2021-12-19T12:04:51.409+01:00
</div>
</div>
</div>

View File

@ -30,6 +30,8 @@ SWGRemoteSinkSettings::SWGRemoteSinkSettings(QString* json) {
SWGRemoteSinkSettings::SWGRemoteSinkSettings() {
nb_fec_blocks = 0;
m_nb_fec_blocks_isSet = false;
nb_tx_bytes = 0;
m_nb_tx_bytes_isSet = false;
data_address = nullptr;
m_data_address_isSet = false;
data_port = 0;
@ -66,6 +68,8 @@ void
SWGRemoteSinkSettings::init() {
nb_fec_blocks = 0;
m_nb_fec_blocks_isSet = false;
nb_tx_bytes = 0;
m_nb_tx_bytes_isSet = false;
data_address = new QString("");
m_data_address_isSet = false;
data_port = 0;
@ -97,6 +101,7 @@ SWGRemoteSinkSettings::init() {
void
SWGRemoteSinkSettings::cleanup() {
if(data_address != nullptr) {
delete data_address;
}
@ -133,6 +138,8 @@ void
SWGRemoteSinkSettings::fromJsonObject(QJsonObject &pJson) {
::SWGSDRangel::setValue(&nb_fec_blocks, pJson["nbFECBlocks"], "qint32", "");
::SWGSDRangel::setValue(&nb_tx_bytes, pJson["nbTxBytes"], "qint32", "");
::SWGSDRangel::setValue(&data_address, pJson["dataAddress"], "QString", "QString");
::SWGSDRangel::setValue(&data_port, pJson["dataPort"], "qint32", "");
@ -178,6 +185,9 @@ SWGRemoteSinkSettings::asJsonObject() {
if(m_nb_fec_blocks_isSet){
obj->insert("nbFECBlocks", QJsonValue(nb_fec_blocks));
}
if(m_nb_tx_bytes_isSet){
obj->insert("nbTxBytes", QJsonValue(nb_tx_bytes));
}
if(data_address != nullptr && *data_address != QString("")){
toJsonValue(QString("dataAddress"), data_address, obj, QString("QString"));
}
@ -231,6 +241,16 @@ SWGRemoteSinkSettings::setNbFecBlocks(qint32 nb_fec_blocks) {
this->m_nb_fec_blocks_isSet = true;
}
qint32
SWGRemoteSinkSettings::getNbTxBytes() {
return nb_tx_bytes;
}
void
SWGRemoteSinkSettings::setNbTxBytes(qint32 nb_tx_bytes) {
this->nb_tx_bytes = nb_tx_bytes;
this->m_nb_tx_bytes_isSet = true;
}
QString*
SWGRemoteSinkSettings::getDataAddress() {
return data_address;
@ -369,6 +389,9 @@ SWGRemoteSinkSettings::isSet(){
if(m_nb_fec_blocks_isSet){
isObjectUpdated = true; break;
}
if(m_nb_tx_bytes_isSet){
isObjectUpdated = true; break;
}
if(data_address && *data_address != QString("")){
isObjectUpdated = true; break;
}

View File

@ -46,6 +46,9 @@ public:
qint32 getNbFecBlocks();
void setNbFecBlocks(qint32 nb_fec_blocks);
qint32 getNbTxBytes();
void setNbTxBytes(qint32 nb_tx_bytes);
QString* getDataAddress();
void setDataAddress(QString* data_address);
@ -92,6 +95,9 @@ private:
qint32 nb_fec_blocks;
bool m_nb_fec_blocks_isSet;
qint32 nb_tx_bytes;
bool m_nb_tx_bytes_isSet;
QString* data_address;
bool m_data_address_isSet;