mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-25 09:18:54 -05:00
Compare commits
2 Commits
9278b12e25
...
7c8cb7a85a
Author | SHA1 | Date | |
---|---|---|---|
|
7c8cb7a85a | ||
|
ab9f316737 |
Binary file not shown.
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
Binary file not shown.
@ -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 (/).
|
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.
|
Number of bytes per I or Q sample in transmission.
|
||||||
|
|
||||||
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 ✕ 126 ✕ _d_) / _SR_) / (128 + _F_)
|
|
||||||
|
|
||||||
The percentage appears first at the right of the dial button and then the actual delay value in microseconds.
|
|
||||||
|
@ -209,6 +209,14 @@ void RemoteSink::applySettings(const RemoteSinkSettings& settings, bool force)
|
|||||||
frequencyOffsetChange = true;
|
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_settings.m_streamIndex != settings.m_streamIndex)
|
||||||
{
|
{
|
||||||
if (m_deviceAPI->getSampleMIMO()) // change of stream is possible for MIMO devices only
|
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")) {
|
if (channelSettingsKeys.contains("dataAddress")) {
|
||||||
settings.m_dataAddress = *response.getRemoteSinkSettings()->getDataAddress();
|
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()->setDataAddress(new QString(settings.m_dataAddress));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
response.getRemoteSinkSettings()->setNbTxBytes(settings.m_nbTxBytes);
|
||||||
response.getRemoteSinkSettings()->setDataPort(settings.m_dataPort);
|
response.getRemoteSinkSettings()->setDataPort(settings.m_dataPort);
|
||||||
response.getRemoteSinkSettings()->setRgbColor(settings.m_rgbColor);
|
response.getRemoteSinkSettings()->setRgbColor(settings.m_rgbColor);
|
||||||
|
|
||||||
@ -488,6 +501,9 @@ void RemoteSink::webapiFormatChannelSettings(
|
|||||||
if (channelSettingsKeys.contains("nbFECBlocks") || force) {
|
if (channelSettingsKeys.contains("nbFECBlocks") || force) {
|
||||||
swgRemoteSinkSettings->setNbFecBlocks(settings.m_nbFECBlocks);
|
swgRemoteSinkSettings->setNbFecBlocks(settings.m_nbFECBlocks);
|
||||||
}
|
}
|
||||||
|
if (channelSettingsKeys.contains("nbTxBytes") || force) {
|
||||||
|
swgRemoteSinkSettings->setNbTxBytes(settings.m_nbTxBytes);
|
||||||
|
}
|
||||||
if (channelSettingsKeys.contains("dataAddress") || force) {
|
if (channelSettingsKeys.contains("dataAddress") || force) {
|
||||||
swgRemoteSinkSettings->setDataAddress(new QString(settings.m_dataAddress));
|
swgRemoteSinkSettings->setDataAddress(new QString(settings.m_dataAddress));
|
||||||
}
|
}
|
||||||
|
@ -52,6 +52,7 @@ void RemoteSinkBaseband::reset()
|
|||||||
{
|
{
|
||||||
QMutexLocker mutexLocker(&m_mutex);
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
m_sampleFifo.reset();
|
m_sampleFifo.reset();
|
||||||
|
m_sink.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteSinkBaseband::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
|
void RemoteSinkBaseband::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end)
|
||||||
|
@ -64,6 +64,7 @@ public:
|
|||||||
void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
|
void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end);
|
||||||
void startSender() { m_sink.startSender(); }
|
void startSender() { m_sink.startSender(); }
|
||||||
void stopSender() { m_sink.stopSender(); }
|
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
|
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
||||||
int getChannelSampleRate() const;
|
int getChannelSampleRate() const;
|
||||||
|
@ -168,6 +168,7 @@ void RemoteSinkGUI::displaySettings()
|
|||||||
QString s = QString::number(128 + m_settings.m_nbFECBlocks, 'f', 0);
|
QString s = QString::number(128 + m_settings.m_nbFECBlocks, 'f', 0);
|
||||||
QString s1 = QString::number(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->nominalNbBlocksText->setText(tr("%1/%2").arg(s).arg(s1));
|
||||||
|
ui->nbTxBytes->setCurrentIndex(log2(m_settings.m_nbTxBytes));
|
||||||
applyDecimation();
|
applyDecimation();
|
||||||
displayStreamIndex();
|
displayStreamIndex();
|
||||||
restoreState(m_settings.m_rollupState);
|
restoreState(m_settings.m_rollupState);
|
||||||
@ -333,6 +334,12 @@ void RemoteSinkGUI::on_nbFECBlocks_valueChanged(int value)
|
|||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoteSinkGUI::on_nbTxBytes_currentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
m_settings.m_nbTxBytes = 1 << index;
|
||||||
|
applySettings();
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteSinkGUI::applyDecimation()
|
void RemoteSinkGUI::applyDecimation()
|
||||||
{
|
{
|
||||||
uint32_t maxHash = 1;
|
uint32_t maxHash = 1;
|
||||||
|
@ -88,6 +88,7 @@ private slots:
|
|||||||
void on_dataPort_returnPressed();
|
void on_dataPort_returnPressed();
|
||||||
void on_dataApplyButton_clicked(bool checked);
|
void on_dataApplyButton_clicked(bool checked);
|
||||||
void on_nbFECBlocks_valueChanged(int value);
|
void on_nbFECBlocks_valueChanged(int value);
|
||||||
|
void on_nbTxBytes_currentIndexChanged(int index);
|
||||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||||
void onMenuDialogCalled(const QPoint& p);
|
void onMenuDialogCalled(const QPoint& p);
|
||||||
void tick();
|
void tick();
|
||||||
|
@ -395,6 +395,41 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</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>
|
<item>
|
||||||
<spacer name="horizontalSpacer_3">
|
<spacer name="horizontalSpacer_3">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
@ -37,6 +37,7 @@ RemoteSinkSettings::RemoteSinkSettings()
|
|||||||
void RemoteSinkSettings::resetToDefaults()
|
void RemoteSinkSettings::resetToDefaults()
|
||||||
{
|
{
|
||||||
m_nbFECBlocks = 0;
|
m_nbFECBlocks = 0;
|
||||||
|
m_nbTxBytes = 2;
|
||||||
m_dataAddress = "127.0.0.1";
|
m_dataAddress = "127.0.0.1";
|
||||||
m_dataPort = 9090;
|
m_dataPort = 9090;
|
||||||
m_rgbColor = QColor(140, 4, 4).rgb();
|
m_rgbColor = QColor(140, 4, 4).rgb();
|
||||||
@ -56,6 +57,7 @@ QByteArray RemoteSinkSettings::serialize() const
|
|||||||
{
|
{
|
||||||
SimpleSerializer s(1);
|
SimpleSerializer s(1);
|
||||||
s.writeU32(1, m_nbFECBlocks);
|
s.writeU32(1, m_nbFECBlocks);
|
||||||
|
s.writeU32(2, m_nbTxBytes);
|
||||||
s.writeString(3, m_dataAddress);
|
s.writeString(3, m_dataAddress);
|
||||||
s.writeU32(4, m_dataPort);
|
s.writeU32(4, m_dataPort);
|
||||||
s.writeU32(5, m_rgbColor);
|
s.writeU32(5, m_rgbColor);
|
||||||
@ -96,6 +98,7 @@ bool RemoteSinkSettings::deserialize(const QByteArray& data)
|
|||||||
m_nbFECBlocks = 0;
|
m_nbFECBlocks = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.readU32(2, &m_nbTxBytes, 2);
|
||||||
d.readString(3, &m_dataAddress, "127.0.0.1");
|
d.readString(3, &m_dataAddress, "127.0.0.1");
|
||||||
d.readU32(4, &tmp, 0);
|
d.readU32(4, &tmp, 0);
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ class Serializable;
|
|||||||
struct RemoteSinkSettings
|
struct RemoteSinkSettings
|
||||||
{
|
{
|
||||||
uint16_t m_nbFECBlocks;
|
uint16_t m_nbFECBlocks;
|
||||||
|
uint32_t m_nbTxBytes;
|
||||||
QString m_dataAddress;
|
QString m_dataAddress;
|
||||||
uint16_t m_dataPort;
|
uint16_t m_dataPort;
|
||||||
quint32 m_rgbColor;
|
quint32 m_rgbColor;
|
||||||
|
@ -36,6 +36,7 @@ RemoteSinkSink::RemoteSinkSink() :
|
|||||||
m_frequencyOffset(0),
|
m_frequencyOffset(0),
|
||||||
m_basebandSampleRate(48000),
|
m_basebandSampleRate(48000),
|
||||||
m_nbBlocksFEC(0),
|
m_nbBlocksFEC(0),
|
||||||
|
m_nbTxBytes(SDR_RX_SAMP_SZ <= 16 ? 2 : 4),
|
||||||
m_dataAddress("127.0.0.1"),
|
m_dataAddress("127.0.0.1"),
|
||||||
m_dataPort(9090)
|
m_dataPort(9090)
|
||||||
{
|
{
|
||||||
@ -68,6 +69,14 @@ void RemoteSinkSink::stopSender()
|
|||||||
m_senderThread->wait();
|
m_senderThread->wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoteSinkSink::init()
|
||||||
|
{
|
||||||
|
m_dataFrame = nullptr;
|
||||||
|
m_txBlockIndex = 0;
|
||||||
|
m_frameCount = 0;
|
||||||
|
m_sampleIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteSinkSink::setNbBlocksFEC(int nbBlocksFEC)
|
void RemoteSinkSink::setNbBlocksFEC(int nbBlocksFEC)
|
||||||
{
|
{
|
||||||
qDebug() << "RemoteSinkSink::setNbBlocksFEC: nbBlocksFEC: " << 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_centerFrequency = m_deviceCenterFrequency + m_frequencyOffset;
|
||||||
metaData.m_sampleRate = m_basebandSampleRate / (1<<m_settings.m_log2Decim);
|
metaData.m_sampleRate = m_basebandSampleRate / (1<<m_settings.m_log2Decim);
|
||||||
metaData.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
metaData.m_sampleBytes = m_nbTxBytes;
|
||||||
metaData.m_sampleBits = SDR_RX_SAMP_SZ;
|
metaData.m_sampleBits = getNbSampleBits();
|
||||||
metaData.m_nbOriginalBlocks = RemoteNbOrginalBlocks;
|
metaData.m_nbOriginalBlocks = RemoteNbOrginalBlocks;
|
||||||
metaData.m_nbFECBlocks = m_nbBlocksFEC;
|
metaData.m_nbFECBlocks = m_nbBlocksFEC;
|
||||||
metaData.m_tv_sec = nowus / 1000000UL; // tv.tv_sec;
|
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.init();
|
||||||
superBlock.m_header.m_frameIndex = m_frameCount;
|
superBlock.m_header.m_frameIndex = m_frameCount;
|
||||||
superBlock.m_header.m_blockIndex = m_txBlockIndex;
|
superBlock.m_header.m_blockIndex = m_txBlockIndex;
|
||||||
superBlock.m_header.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4);
|
superBlock.m_header.m_sampleBytes = m_nbTxBytes;
|
||||||
superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
superBlock.m_header.m_sampleBits = getNbSampleBits();
|
||||||
|
|
||||||
RemoteMetaDataFEC *destMeta = (RemoteMetaDataFEC *) &superBlock.m_protectedBlock;
|
RemoteMetaDataFEC *destMeta = (RemoteMetaDataFEC *) &superBlock.m_protectedBlock;
|
||||||
*destMeta = metaData;
|
*destMeta = metaData;
|
||||||
@ -135,27 +144,29 @@ void RemoteSinkSink::feed(const SampleVector::const_iterator& begin, const Sampl
|
|||||||
} // block zero
|
} // block zero
|
||||||
|
|
||||||
// handle different sample sizes...
|
// 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
|
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)],
|
convertSampleToData(begin + inSamplesIndex, inRemainingSamples, false);
|
||||||
(const void *) &(*(begin+inSamplesIndex)),
|
// memcpy((void *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
|
||||||
inRemainingSamples * sizeof(Sample));
|
// (const void *) &(*(begin+inSamplesIndex)),
|
||||||
|
// inRemainingSamples * sizeof(Sample));
|
||||||
m_sampleIndex += inRemainingSamples;
|
m_sampleIndex += inRemainingSamples;
|
||||||
it = end; // all input samples are consumed
|
it = end; // all input samples are consumed
|
||||||
}
|
}
|
||||||
else // complete super block and initiate the next if not end of frame
|
else // complete super block and initiate the next if not end of frame
|
||||||
{
|
{
|
||||||
memcpy((void *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
|
convertSampleToData(begin + inSamplesIndex, samplesPerBlock - m_sampleIndex, false);
|
||||||
(const void *) &(*(begin+inSamplesIndex)),
|
// memcpy((void *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)],
|
||||||
(samplesPerBlock - m_sampleIndex) * sizeof(Sample));
|
// (const void *) &(*(begin+inSamplesIndex)),
|
||||||
|
// (samplesPerBlock - m_sampleIndex) * sizeof(Sample));
|
||||||
it += samplesPerBlock - m_sampleIndex;
|
it += samplesPerBlock - m_sampleIndex;
|
||||||
m_sampleIndex = 0;
|
m_sampleIndex = 0;
|
||||||
|
|
||||||
m_superBlock.m_header.m_frameIndex = m_frameCount;
|
m_superBlock.m_header.m_frameIndex = m_frameCount;
|
||||||
m_superBlock.m_header.m_blockIndex = m_txBlockIndex;
|
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_sampleBytes = m_nbTxBytes;
|
||||||
m_superBlock.m_header.m_sampleBits = SDR_RX_SAMP_SZ;
|
m_superBlock.m_header.m_sampleBits = getNbSampleBits();
|
||||||
m_dataFrame->m_superBlocks[m_txBlockIndex] = m_superBlock;
|
m_dataFrame->m_superBlocks[m_txBlockIndex] = m_superBlock;
|
||||||
|
|
||||||
if (m_txBlockIndex == RemoteNbOrginalBlocks - 1) // frame complete
|
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);
|
double shiftFactor = HBFilterChainConverter::getShiftFactor(m_settings.m_log2Decim, m_settings.m_filterChainHash);
|
||||||
m_frequencyOffset = round(shiftFactor*m_basebandSampleRate);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -40,7 +40,9 @@ public:
|
|||||||
|
|
||||||
void startSender();
|
void startSender();
|
||||||
void stopSender();
|
void stopSender();
|
||||||
|
void init();
|
||||||
|
|
||||||
|
void setNbTxBytes(uint32_t nbTxBytes) { m_nbTxBytes = nbTxBytes; }
|
||||||
void applySettings(const RemoteSinkSettings& settings, bool force = false);
|
void applySettings(const RemoteSinkSettings& settings, bool force = false);
|
||||||
void applyBasebandSampleRate(uint32_t sampleRate);
|
void applyBasebandSampleRate(uint32_t sampleRate);
|
||||||
void setDeviceCenterFrequency(uint64_t frequency) { m_deviceCenterFrequency = frequency; }
|
void setDeviceCenterFrequency(uint64_t frequency) { m_deviceCenterFrequency = frequency; }
|
||||||
@ -61,10 +63,84 @@ private:
|
|||||||
int64_t m_frequencyOffset;
|
int64_t m_frequencyOffset;
|
||||||
uint32_t m_basebandSampleRate;
|
uint32_t m_basebandSampleRate;
|
||||||
int m_nbBlocksFEC;
|
int m_nbBlocksFEC;
|
||||||
|
uint32_t m_nbTxBytes;
|
||||||
QString m_dataAddress;
|
QString m_dataAddress;
|
||||||
uint16_t m_dataPort;
|
uint16_t m_dataPort;
|
||||||
|
|
||||||
void setNbBlocksFEC(int nbBlocksFEC);
|
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_
|
#endif // INCLUDE_REMOTESINKSINK_H_
|
||||||
|
@ -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.
|
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>
|
<h3>7: Forward Error Correction setting and status</h3>
|
||||||
|
|
||||||
![SDR Remote output FEC GUI](../../../doc/img/RemoteOutput_plugin_06.png)
|
![SDR Remote output FEC GUI](../../../doc/img/RemoteOutput_plugin_06.png)
|
||||||
|
@ -35,7 +35,6 @@ UDPSinkFEC::UDPSinkFEC() :
|
|||||||
m_txDelayRatio(0.0),
|
m_txDelayRatio(0.0),
|
||||||
m_dataFrame(nullptr),
|
m_dataFrame(nullptr),
|
||||||
m_txBlockIndex(0),
|
m_txBlockIndex(0),
|
||||||
m_txBlocksIndex(0),
|
|
||||||
m_frameCount(0),
|
m_frameCount(0),
|
||||||
m_sampleIndex(0),
|
m_sampleIndex(0),
|
||||||
m_remoteOutputSender(nullptr),
|
m_remoteOutputSender(nullptr),
|
||||||
@ -61,7 +60,6 @@ void UDPSinkFEC::init()
|
|||||||
{
|
{
|
||||||
m_dataFrame = nullptr;
|
m_dataFrame = nullptr;
|
||||||
m_txBlockIndex = 0;
|
m_txBlockIndex = 0;
|
||||||
m_txBlocksIndex = 0;
|
|
||||||
m_frameCount = 0;
|
m_frameCount = 0;
|
||||||
m_sampleIndex = 0;
|
m_sampleIndex = 0;
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,6 @@ private:
|
|||||||
RemoteDataFrame *m_dataFrame;
|
RemoteDataFrame *m_dataFrame;
|
||||||
RemoteSuperBlock m_superBlock; //!< current super block being built
|
RemoteSuperBlock m_superBlock; //!< current super block being built
|
||||||
int m_txBlockIndex; //!< Current index in blocks to transmit in the Tx row
|
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
|
uint16_t m_frameCount; //!< transmission frame count
|
||||||
int m_sampleIndex; //!< Current sample index in protected block data
|
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;
|
*((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++)
|
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);
|
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (int8_t) ((begin+i)->m_real / (1<<8));
|
||||||
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 + m_nbTxBytes]) = (int8_t) ((begin+i)->m_imag / (1<<8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,26 +143,32 @@ private:
|
|||||||
{
|
{
|
||||||
for (int i = 0; i < nbSamples; i++)
|
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]) = (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 << 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
|
else if (m_nbTxBytes == 2) // 24 -> 16
|
||||||
{
|
{
|
||||||
for (int i = 0; i < nbSamples; i++)
|
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]) = (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 >> 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++)
|
for (int i = 0; i < nbSamples; i++)
|
||||||
{
|
{
|
||||||
m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2] =
|
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2]) = (int8_t) ((begin+i)->m_real / (1<<8));
|
||||||
(uint8_t) (((begin+i)->m_real / (1<<sizeof(Sample)*2)) & 0xFF);
|
*((int8_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (int8_t) ((begin+i)->m_imag / (1<<8));
|
||||||
m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes] =
|
}
|
||||||
(uint8_t) (((begin+i)->m_imag / (1<<sizeof(Sample)*2)) & 0xFF);
|
}
|
||||||
|
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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -326,27 +326,13 @@ void RemoteInputUDPHandler::tick()
|
|||||||
const RemoteMetaDataFEC& metaData = m_remoteInputBuffer.getCurrentMeta();
|
const RemoteMetaDataFEC& metaData = m_remoteInputBuffer.getCurrentMeta();
|
||||||
m_readLength = m_readLengthSamples * (metaData.m_sampleBytes & 0xF) * 2;
|
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)
|
// read samples directly feeding the SampleFifo (no callback)
|
||||||
{
|
m_sampleFifo->write(reinterpret_cast<quint8*>(m_remoteInputBuffer.readData(m_readLength)), m_readLength);
|
||||||
if (m_converterBuffer) { delete[] m_converterBuffer; }
|
m_samplesCount += m_readLengthSamples;
|
||||||
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
|
else if ((metaData.m_sampleBits == 8) && (SDR_RX_SAMP_SZ == 16)) // 8 -> 16
|
||||||
{
|
{
|
||||||
if (m_readLengthSamples > (int) m_converterBufferNbSamples)
|
if (m_readLengthSamples > (int) m_converterBufferNbSamples)
|
||||||
{
|
{
|
||||||
@ -354,28 +340,125 @@ void RemoteInputUDPHandler::tick()
|
|||||||
m_converterBuffer = new int32_t[m_readLengthSamples];
|
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++)
|
for (int is = 0; is < m_readLengthSamples; is++)
|
||||||
{
|
{
|
||||||
m_converterBuffer[is] = ((int32_t *)buf)[2*is+1]>>8; // Q -> MSB
|
m_converterBuffer[is] = buf[2*is+1] * (1<<8); // Q -> MSB
|
||||||
m_converterBuffer[is] <<=16;
|
m_converterBuffer[is] <<= 16;
|
||||||
m_converterBuffer[is] += ((int32_t *)buf)[2*is]>>8; // I -> LSB
|
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));
|
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)
|
if (m_readLengthSamples > (int) m_converterBufferNbSamples)
|
||||||
m_sampleFifo->write(reinterpret_cast<quint8*>(m_remoteInputBuffer.readData(m_readLength)), m_readLength);
|
{
|
||||||
m_samplesCount += m_readLengthSamples;
|
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
|
else // invalid size
|
||||||
{
|
{
|
||||||
qWarning("RemoteInputUDPHandler::tick: unexpected sample size in stream: %d bits", (int) metaData.m_sampleBits);
|
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)
|
if (m_tickCount < m_rateDivider)
|
||||||
{
|
{
|
||||||
m_tickCount++;
|
m_tickCount++;
|
||||||
|
@ -70,24 +70,23 @@ private:
|
|||||||
{
|
{
|
||||||
if (sampleSize == 2) // 8 -> 16 bits
|
if (sampleSize == 2) // 8 -> 16 bits
|
||||||
{
|
{
|
||||||
int8_t iu = m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize];
|
int8_t *buf = (int8_t*) m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf;
|
||||||
int8_t qu = m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+1];
|
iconv = buf[sampleIndex*sampleSize] * (1<<8);
|
||||||
iconv = iu * (1 << 8);
|
qconv = buf[sampleIndex*sampleSize+1] * (1<<8);
|
||||||
qconv = qu * (1 << 8);
|
|
||||||
s.setReal(iconv);
|
s.setReal(iconv);
|
||||||
s.setImag(qconv);
|
s.setImag(qconv);
|
||||||
}
|
}
|
||||||
else if (sampleSize == 4) // just convert types (always 16 bits wide)
|
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];
|
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]))[0];
|
qconv = *((int16_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+2]));
|
||||||
s.setReal(iconv);
|
s.setReal(iconv);
|
||||||
s.setImag(qconv);
|
s.setImag(qconv);
|
||||||
}
|
}
|
||||||
else if (sampleSize == 8) // just convert types (always 16 bits wide)
|
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];
|
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]))[0];
|
qconv = *((int32_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+4]));
|
||||||
s.setReal(iconv);
|
s.setReal(iconv);
|
||||||
s.setImag(qconv);
|
s.setImag(qconv);
|
||||||
}
|
}
|
||||||
@ -98,26 +97,33 @@ private:
|
|||||||
}
|
}
|
||||||
else
|
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 *buf = (int8_t*) m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf;
|
||||||
int8_t qu = m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+1];
|
iconv = buf[sampleIndex*sampleSize] * (1<<8);
|
||||||
iconv = iu * (1 << sizeof(Sample)*2);
|
qconv = buf[sampleIndex*sampleSize+1] * (1<<8);
|
||||||
qconv = qu * (1 << sizeof(Sample)*2);
|
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.setReal(iconv);
|
||||||
s.setImag(qconv);
|
s.setImag(qconv);
|
||||||
}
|
}
|
||||||
else if (sampleSize == 4) // 16 -> 24 bits
|
else if (sampleSize == 4) // 16 -> 24 bits
|
||||||
{
|
{
|
||||||
iconv = ((int16_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize]))[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]))[0] << 8;
|
qconv = *((int16_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+2])) * (1<<8);
|
||||||
s.setReal(iconv);
|
s.setReal(iconv);
|
||||||
s.setImag(qconv);
|
s.setImag(qconv);
|
||||||
}
|
}
|
||||||
else if (sampleSize == 8) // 24 -> 16 bits
|
else if (sampleSize == 8) // 24 -> 16 bits
|
||||||
{
|
{
|
||||||
iconv = ((int32_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize]))[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]))[0] >> 8;
|
qconv = *((int32_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+4])) / (1<<8);
|
||||||
s.setReal(iconv);
|
s.setReal(iconv);
|
||||||
s.setImag(qconv);
|
s.setImag(qconv);
|
||||||
}
|
}
|
||||||
|
@ -9864,7 +9864,8 @@ margin-bottom: 20px;
|
|||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
"nbTxBytes" : {
|
"nbTxBytes" : {
|
||||||
"type" : "integer"
|
"type" : "integer",
|
||||||
|
"description" : "Number of bytes in a transmited I or Q sample\n * 1\n * 2\n * 4\n"
|
||||||
},
|
},
|
||||||
"apiAddress" : {
|
"apiAddress" : {
|
||||||
"type" : "string"
|
"type" : "string"
|
||||||
@ -9906,6 +9907,10 @@ margin-bottom: 20px;
|
|||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"description" : "Number of FEC blocks per frame"
|
"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" : {
|
"dataAddress" : {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"description" : "Receiving USB data address"
|
"description" : "Receiving USB data address"
|
||||||
@ -51625,7 +51630,7 @@ except ApiException as e:
|
|||||||
</div>
|
</div>
|
||||||
<div id="generator">
|
<div id="generator">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
Generated 2021-12-18T22:54:13.645+01:00
|
Generated 2021-12-19T12:04:51.409+01:00
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,6 +5,11 @@ RemoteOutputSettings:
|
|||||||
type: integer
|
type: integer
|
||||||
nbTxBytes:
|
nbTxBytes:
|
||||||
type: integer
|
type: integer
|
||||||
|
description: >
|
||||||
|
Number of bytes in a transmited I or Q sample
|
||||||
|
* 1
|
||||||
|
* 2
|
||||||
|
* 4
|
||||||
apiAddress:
|
apiAddress:
|
||||||
type: string
|
type: string
|
||||||
apiPort:
|
apiPort:
|
||||||
|
@ -4,6 +4,13 @@ RemoteSinkSettings:
|
|||||||
nbFECBlocks:
|
nbFECBlocks:
|
||||||
description: "Number of FEC blocks per frame"
|
description: "Number of FEC blocks per frame"
|
||||||
type: integer
|
type: integer
|
||||||
|
nbTxBytes:
|
||||||
|
type: integer
|
||||||
|
description: >
|
||||||
|
Number of bytes in a transmited I or Q sample
|
||||||
|
* 1
|
||||||
|
* 2
|
||||||
|
* 4
|
||||||
dataAddress:
|
dataAddress:
|
||||||
description: "Receiving USB data address"
|
description: "Receiving USB data address"
|
||||||
type: string
|
type: string
|
||||||
|
@ -5,6 +5,11 @@ RemoteOutputSettings:
|
|||||||
type: integer
|
type: integer
|
||||||
nbTxBytes:
|
nbTxBytes:
|
||||||
type: integer
|
type: integer
|
||||||
|
description: >
|
||||||
|
Number of bytes in a transmited I or Q sample
|
||||||
|
* 1
|
||||||
|
* 2
|
||||||
|
* 4
|
||||||
apiAddress:
|
apiAddress:
|
||||||
type: string
|
type: string
|
||||||
apiPort:
|
apiPort:
|
||||||
|
@ -4,6 +4,13 @@ RemoteSinkSettings:
|
|||||||
nbFECBlocks:
|
nbFECBlocks:
|
||||||
description: "Number of FEC blocks per frame"
|
description: "Number of FEC blocks per frame"
|
||||||
type: integer
|
type: integer
|
||||||
|
nbTxBytes:
|
||||||
|
type: integer
|
||||||
|
description: >
|
||||||
|
Number of bytes in a transmited I or Q sample
|
||||||
|
* 1
|
||||||
|
* 2
|
||||||
|
* 4
|
||||||
dataAddress:
|
dataAddress:
|
||||||
description: "Receiving USB data address"
|
description: "Receiving USB data address"
|
||||||
type: string
|
type: string
|
||||||
|
@ -9864,7 +9864,8 @@ margin-bottom: 20px;
|
|||||||
"type" : "integer"
|
"type" : "integer"
|
||||||
},
|
},
|
||||||
"nbTxBytes" : {
|
"nbTxBytes" : {
|
||||||
"type" : "integer"
|
"type" : "integer",
|
||||||
|
"description" : "Number of bytes in a transmited I or Q sample\n * 1\n * 2\n * 4\n"
|
||||||
},
|
},
|
||||||
"apiAddress" : {
|
"apiAddress" : {
|
||||||
"type" : "string"
|
"type" : "string"
|
||||||
@ -9906,6 +9907,10 @@ margin-bottom: 20px;
|
|||||||
"type" : "integer",
|
"type" : "integer",
|
||||||
"description" : "Number of FEC blocks per frame"
|
"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" : {
|
"dataAddress" : {
|
||||||
"type" : "string",
|
"type" : "string",
|
||||||
"description" : "Receiving USB data address"
|
"description" : "Receiving USB data address"
|
||||||
@ -51625,7 +51630,7 @@ except ApiException as e:
|
|||||||
</div>
|
</div>
|
||||||
<div id="generator">
|
<div id="generator">
|
||||||
<div class="content">
|
<div class="content">
|
||||||
Generated 2021-12-18T22:54:13.645+01:00
|
Generated 2021-12-19T12:04:51.409+01:00
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -30,6 +30,8 @@ SWGRemoteSinkSettings::SWGRemoteSinkSettings(QString* json) {
|
|||||||
SWGRemoteSinkSettings::SWGRemoteSinkSettings() {
|
SWGRemoteSinkSettings::SWGRemoteSinkSettings() {
|
||||||
nb_fec_blocks = 0;
|
nb_fec_blocks = 0;
|
||||||
m_nb_fec_blocks_isSet = false;
|
m_nb_fec_blocks_isSet = false;
|
||||||
|
nb_tx_bytes = 0;
|
||||||
|
m_nb_tx_bytes_isSet = false;
|
||||||
data_address = nullptr;
|
data_address = nullptr;
|
||||||
m_data_address_isSet = false;
|
m_data_address_isSet = false;
|
||||||
data_port = 0;
|
data_port = 0;
|
||||||
@ -66,6 +68,8 @@ void
|
|||||||
SWGRemoteSinkSettings::init() {
|
SWGRemoteSinkSettings::init() {
|
||||||
nb_fec_blocks = 0;
|
nb_fec_blocks = 0;
|
||||||
m_nb_fec_blocks_isSet = false;
|
m_nb_fec_blocks_isSet = false;
|
||||||
|
nb_tx_bytes = 0;
|
||||||
|
m_nb_tx_bytes_isSet = false;
|
||||||
data_address = new QString("");
|
data_address = new QString("");
|
||||||
m_data_address_isSet = false;
|
m_data_address_isSet = false;
|
||||||
data_port = 0;
|
data_port = 0;
|
||||||
@ -97,6 +101,7 @@ SWGRemoteSinkSettings::init() {
|
|||||||
void
|
void
|
||||||
SWGRemoteSinkSettings::cleanup() {
|
SWGRemoteSinkSettings::cleanup() {
|
||||||
|
|
||||||
|
|
||||||
if(data_address != nullptr) {
|
if(data_address != nullptr) {
|
||||||
delete data_address;
|
delete data_address;
|
||||||
}
|
}
|
||||||
@ -133,6 +138,8 @@ void
|
|||||||
SWGRemoteSinkSettings::fromJsonObject(QJsonObject &pJson) {
|
SWGRemoteSinkSettings::fromJsonObject(QJsonObject &pJson) {
|
||||||
::SWGSDRangel::setValue(&nb_fec_blocks, pJson["nbFECBlocks"], "qint32", "");
|
::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_address, pJson["dataAddress"], "QString", "QString");
|
||||||
|
|
||||||
::SWGSDRangel::setValue(&data_port, pJson["dataPort"], "qint32", "");
|
::SWGSDRangel::setValue(&data_port, pJson["dataPort"], "qint32", "");
|
||||||
@ -178,6 +185,9 @@ SWGRemoteSinkSettings::asJsonObject() {
|
|||||||
if(m_nb_fec_blocks_isSet){
|
if(m_nb_fec_blocks_isSet){
|
||||||
obj->insert("nbFECBlocks", QJsonValue(nb_fec_blocks));
|
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("")){
|
if(data_address != nullptr && *data_address != QString("")){
|
||||||
toJsonValue(QString("dataAddress"), data_address, obj, QString("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;
|
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*
|
QString*
|
||||||
SWGRemoteSinkSettings::getDataAddress() {
|
SWGRemoteSinkSettings::getDataAddress() {
|
||||||
return data_address;
|
return data_address;
|
||||||
@ -369,6 +389,9 @@ SWGRemoteSinkSettings::isSet(){
|
|||||||
if(m_nb_fec_blocks_isSet){
|
if(m_nb_fec_blocks_isSet){
|
||||||
isObjectUpdated = true; break;
|
isObjectUpdated = true; break;
|
||||||
}
|
}
|
||||||
|
if(m_nb_tx_bytes_isSet){
|
||||||
|
isObjectUpdated = true; break;
|
||||||
|
}
|
||||||
if(data_address && *data_address != QString("")){
|
if(data_address && *data_address != QString("")){
|
||||||
isObjectUpdated = true; break;
|
isObjectUpdated = true; break;
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,9 @@ public:
|
|||||||
qint32 getNbFecBlocks();
|
qint32 getNbFecBlocks();
|
||||||
void setNbFecBlocks(qint32 nb_fec_blocks);
|
void setNbFecBlocks(qint32 nb_fec_blocks);
|
||||||
|
|
||||||
|
qint32 getNbTxBytes();
|
||||||
|
void setNbTxBytes(qint32 nb_tx_bytes);
|
||||||
|
|
||||||
QString* getDataAddress();
|
QString* getDataAddress();
|
||||||
void setDataAddress(QString* data_address);
|
void setDataAddress(QString* data_address);
|
||||||
|
|
||||||
@ -92,6 +95,9 @@ private:
|
|||||||
qint32 nb_fec_blocks;
|
qint32 nb_fec_blocks;
|
||||||
bool m_nb_fec_blocks_isSet;
|
bool m_nb_fec_blocks_isSet;
|
||||||
|
|
||||||
|
qint32 nb_tx_bytes;
|
||||||
|
bool m_nb_tx_bytes_isSet;
|
||||||
|
|
||||||
QString* data_address;
|
QString* data_address;
|
||||||
bool m_data_address_isSet;
|
bool m_data_address_isSet;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user