1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-25 01:18:38 -05:00

Compare commits

...

3 Commits

21 changed files with 285 additions and 51 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

View File

@ -53,7 +53,7 @@ void RemoteSourceSource::pull(SampleVector::iterator begin, unsigned int nbSampl
void RemoteSourceSource::pullOne(Sample& sample) void RemoteSourceSource::pullOne(Sample& sample)
{ {
m_dataReadQueue.readSample(sample, true); // true is scale for Tx m_dataReadQueue.readSample(sample, true);
} }
void RemoteSourceSource::start() void RemoteSourceSource::start()

View File

@ -279,7 +279,7 @@ void RemoteOutput::applySettings(const RemoteOutputSettings& settings, bool forc
if (force || (m_settings.m_dataAddress != settings.m_dataAddress) || (m_settings.m_dataPort != settings.m_dataPort)) if (force || (m_settings.m_dataAddress != settings.m_dataAddress) || (m_settings.m_dataPort != settings.m_dataPort))
{ {
if (m_remoteOutputWorker != 0) { if (m_remoteOutputWorker) {
m_remoteOutputWorker->setDataAddress(settings.m_dataAddress, settings.m_dataPort); m_remoteOutputWorker->setDataAddress(settings.m_dataAddress, settings.m_dataPort);
} }
} }
@ -288,15 +288,28 @@ void RemoteOutput::applySettings(const RemoteOutputSettings& settings, bool forc
{ {
reverseAPIKeys.append("nbFECBlocks"); reverseAPIKeys.append("nbFECBlocks");
if (m_remoteOutputWorker != 0) { if (m_remoteOutputWorker) {
m_remoteOutputWorker->setNbBlocksFEC(settings.m_nbFECBlocks); m_remoteOutputWorker->setNbBlocksFEC(settings.m_nbFECBlocks);
} }
} }
if (force || (m_settings.m_nbTxBytes != settings.m_nbTxBytes))
{
reverseAPIKeys.append("nbTxBytes");
if (m_remoteOutputWorker)
{
stopWorker();
m_remoteOutputWorker->setNbTxBytes(settings.m_nbTxBytes);
startWorker();
}
}
mutexLocker.unlock(); mutexLocker.unlock();
qDebug() << "RemoteOutput::applySettings:" qDebug() << "RemoteOutput::applySettings:"
<< " m_nbFECBlocks: " << settings.m_nbFECBlocks << " m_nbFECBlocks: " << settings.m_nbFECBlocks
<< " m_nbTxBytes: " << settings.m_nbTxBytes
<< " m_apiAddress: " << settings.m_apiAddress << " m_apiAddress: " << settings.m_apiAddress
<< " m_apiPort: " << settings.m_apiPort << " m_apiPort: " << settings.m_apiPort
<< " m_dataAddress: " << settings.m_dataAddress << " m_dataAddress: " << settings.m_dataAddress
@ -404,6 +417,9 @@ void RemoteOutput::webapiUpdateDeviceSettings(
if (deviceSettingsKeys.contains("nbFECBlocks")) { if (deviceSettingsKeys.contains("nbFECBlocks")) {
settings.m_nbFECBlocks = response.getRemoteOutputSettings()->getNbFecBlocks(); settings.m_nbFECBlocks = response.getRemoteOutputSettings()->getNbFecBlocks();
} }
if (deviceSettingsKeys.contains("nbTxBytes")) {
settings.m_nbTxBytes = response.getRemoteOutputSettings()->getNbTxBytes();
}
if (deviceSettingsKeys.contains("apiAddress")) { if (deviceSettingsKeys.contains("apiAddress")) {
settings.m_apiAddress = *response.getRemoteOutputSettings()->getApiAddress(); settings.m_apiAddress = *response.getRemoteOutputSettings()->getApiAddress();
} }
@ -450,6 +466,7 @@ int RemoteOutput::webapiReportGet(
void RemoteOutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const RemoteOutputSettings& settings) void RemoteOutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const RemoteOutputSettings& settings)
{ {
response.getRemoteOutputSettings()->setNbFecBlocks(settings.m_nbFECBlocks); response.getRemoteOutputSettings()->setNbFecBlocks(settings.m_nbFECBlocks);
response.getRemoteOutputSettings()->setNbTxBytes(settings.m_nbTxBytes);
response.getRemoteOutputSettings()->setApiAddress(new QString(settings.m_apiAddress)); response.getRemoteOutputSettings()->setApiAddress(new QString(settings.m_apiAddress));
response.getRemoteOutputSettings()->setApiPort(settings.m_apiPort); response.getRemoteOutputSettings()->setApiPort(settings.m_apiPort);
response.getRemoteOutputSettings()->setDataAddress(new QString(settings.m_dataAddress)); response.getRemoteOutputSettings()->setDataAddress(new QString(settings.m_dataAddress));
@ -657,6 +674,9 @@ void RemoteOutput::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys,
if (deviceSettingsKeys.contains("nbFECBlocks") || force) { if (deviceSettingsKeys.contains("nbFECBlocks") || force) {
swgRemoteOutputSettings->setNbFecBlocks(settings.m_nbFECBlocks); swgRemoteOutputSettings->setNbFecBlocks(settings.m_nbFECBlocks);
} }
if (deviceSettingsKeys.contains("nbTxBytes") || force) {
swgRemoteOutputSettings->setNbTxBytes(settings.m_nbTxBytes);
}
if (deviceSettingsKeys.contains("apiAddress") || force) { if (deviceSettingsKeys.contains("apiAddress") || force) {
swgRemoteOutputSettings->setApiAddress(new QString(settings.m_apiAddress)); swgRemoteOutputSettings->setApiAddress(new QString(settings.m_apiAddress));
} }

View File

@ -212,6 +212,7 @@ void RemoteOutputSinkGui::displaySettings()
blockApplySettings(true); blockApplySettings(true);
ui->centerFrequency->setText(QString("%L1").arg(m_deviceCenterFrequency)); ui->centerFrequency->setText(QString("%L1").arg(m_deviceCenterFrequency));
ui->nbFECBlocks->setValue(m_settings.m_nbFECBlocks); ui->nbFECBlocks->setValue(m_settings.m_nbFECBlocks);
ui->nbTxBytes->setCurrentIndex(log2(m_settings.m_nbTxBytes));
QString s0 = QString::number(128 + m_settings.m_nbFECBlocks, 'f', 0); QString s0 = 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);
@ -310,6 +311,12 @@ void RemoteOutputSinkGui::on_channelIndex_returnPressed()
sendSettings(); sendSettings();
} }
void RemoteOutputSinkGui::on_nbTxBytes_currentIndexChanged(int index)
{
m_settings.m_nbTxBytes = 1 << index;
sendSettings();
}
void RemoteOutputSinkGui::on_apiAddress_returnPressed() void RemoteOutputSinkGui::on_apiAddress_returnPressed()
{ {
m_settings.m_apiAddress = ui->apiAddress->text(); m_settings.m_apiAddress = ui->apiAddress->text();

View File

@ -129,6 +129,7 @@ private slots:
void on_nbFECBlocks_valueChanged(int value); void on_nbFECBlocks_valueChanged(int value);
void on_deviceIndex_returnPressed(); void on_deviceIndex_returnPressed();
void on_channelIndex_returnPressed(); void on_channelIndex_returnPressed();
void on_nbTxBytes_currentIndexChanged(int index);
void on_apiAddress_returnPressed(); void on_apiAddress_returnPressed();
void on_apiPort_returnPressed(); void on_apiPort_returnPressed();
void on_dataAddress_returnPressed(); void on_dataAddress_returnPressed();

View File

@ -239,6 +239,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"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">

View File

@ -26,6 +26,7 @@ RemoteOutputSettings::RemoteOutputSettings()
void RemoteOutputSettings::resetToDefaults() void RemoteOutputSettings::resetToDefaults()
{ {
m_nbFECBlocks = 0; m_nbFECBlocks = 0;
m_nbTxBytes = 2;
m_apiAddress = "127.0.0.1"; m_apiAddress = "127.0.0.1";
m_apiPort = 9091; m_apiPort = 9091;
m_dataAddress = "127.0.0.1"; m_dataAddress = "127.0.0.1";
@ -42,6 +43,7 @@ QByteArray RemoteOutputSettings::serialize() const
{ {
SimpleSerializer s(1); SimpleSerializer s(1);
s.writeU32(3, m_nbTxBytes);
s.writeU32(4, m_nbFECBlocks); s.writeU32(4, m_nbFECBlocks);
s.writeString(5, m_apiAddress); s.writeString(5, m_apiAddress);
s.writeU32(6, m_apiPort); s.writeU32(6, m_apiPort);
@ -71,6 +73,7 @@ bool RemoteOutputSettings::deserialize(const QByteArray& data)
{ {
quint32 uintval; quint32 uintval;
d.readU32(4, &m_nbTxBytes, 2);
d.readU32(4, &m_nbFECBlocks, 0); d.readU32(4, &m_nbFECBlocks, 0);
d.readString(5, &m_apiAddress, "127.0.0.1"); d.readString(5, &m_apiAddress, "127.0.0.1");
d.readU32(6, &uintval, 9090); d.readU32(6, &uintval, 9090);

View File

@ -23,6 +23,7 @@
struct RemoteOutputSettings { struct RemoteOutputSettings {
quint32 m_nbFECBlocks; quint32 m_nbFECBlocks;
quint32 m_nbTxBytes;
QString m_apiAddress; QString m_apiAddress;
quint16 m_apiPort; quint16 m_apiPort;
QString m_dataAddress; QString m_dataAddress;

View File

@ -48,6 +48,7 @@ RemoteOutputWorker::~RemoteOutputWorker()
void RemoteOutputWorker::startWork() void RemoteOutputWorker::startWork()
{ {
qDebug() << "RemoteOutputWorker::startWork: "; qDebug() << "RemoteOutputWorker::startWork: ";
m_udpSinkFEC.init();
m_udpSinkFEC.startSender(); m_udpSinkFEC.startSender();
m_maxThrottlems = 0; m_maxThrottlems = 0;
m_running = true; m_running = true;
@ -126,14 +127,14 @@ void RemoteOutputWorker::tick()
{ {
SampleVector::iterator beginRead = data.begin() + iPart1Begin; SampleVector::iterator beginRead = data.begin() + iPart1Begin;
unsigned int partSize = iPart1End - iPart1Begin; unsigned int partSize = iPart1End - iPart1Begin;
m_udpSinkFEC.write(beginRead, partSize); m_udpSinkFEC.write(beginRead, partSize, true);
} }
if (iPart2Begin != iPart2End) if (iPart2Begin != iPart2End)
{ {
SampleVector::iterator beginRead = data.begin() + iPart2Begin; SampleVector::iterator beginRead = data.begin() + iPart2Begin;
unsigned int partSize = iPart2End - iPart2Begin; unsigned int partSize = iPart2End - iPart2Begin;
m_udpSinkFEC.write(beginRead, partSize); m_udpSinkFEC.write(beginRead, partSize, true);
} }
} }
} }

View File

@ -49,6 +49,7 @@ public:
void setSamplerate(int samplerate); void setSamplerate(int samplerate);
void setNbBlocksFEC(uint32_t nbBlocksFEC) { m_udpSinkFEC.setNbBlocksFEC(nbBlocksFEC); }; void setNbBlocksFEC(uint32_t nbBlocksFEC) { m_udpSinkFEC.setNbBlocksFEC(nbBlocksFEC); };
void setNbTxBytes(uint32_t nbTxBytes) { m_udpSinkFEC.setNbTxBytes(nbTxBytes); };
void setDataAddress(const QString& address, uint16_t port) { m_udpSinkFEC.setRemoteAddress(address, port); } void setDataAddress(const QString& address, uint16_t port) { m_udpSinkFEC.setRemoteAddress(address, port); }
bool isRunning() const { return m_running; } bool isRunning() const { return m_running; }

View File

@ -31,6 +31,7 @@ UDPSinkFEC::UDPSinkFEC() :
m_sampleRate(48000), m_sampleRate(48000),
m_nbSamples(0), m_nbSamples(0),
m_nbBlocksFEC(0), m_nbBlocksFEC(0),
m_nbTxBytes(2),
m_txDelayRatio(0.0), m_txDelayRatio(0.0),
m_dataFrame(nullptr), m_dataFrame(nullptr),
m_txBlockIndex(0), m_txBlockIndex(0),
@ -56,6 +57,15 @@ UDPSinkFEC::~UDPSinkFEC()
delete m_senderThread; delete m_senderThread;
} }
void UDPSinkFEC::init()
{
m_dataFrame = nullptr;
m_txBlockIndex = 0;
m_txBlocksIndex = 0;
m_frameCount = 0;
m_sampleIndex = 0;
}
void UDPSinkFEC::startSender() void UDPSinkFEC::startSender()
{ {
qDebug("UDPSinkFEC::startSender"); qDebug("UDPSinkFEC::startSender");
@ -90,7 +100,7 @@ void UDPSinkFEC::setRemoteAddress(const QString& address, uint16_t port)
m_remoteOutputSender->setDestination(m_remoteAddress, m_remotePort); m_remoteOutputSender->setDestination(m_remoteAddress, m_remotePort);
} }
void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunkSize) void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunkSize, bool isTx)
{ {
const SampleVector::iterator end = begin + sampleChunkSize; const SampleVector::iterator end = begin + sampleChunkSize;
@ -108,8 +118,8 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk
metaData.m_centerFrequency = 0; // frequency not set by stream metaData.m_centerFrequency = 0; // frequency not set by stream
metaData.m_sampleRate = m_sampleRate; metaData.m_sampleRate = m_sampleRate;
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;
@ -126,8 +136,8 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk
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;
@ -151,27 +161,23 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk
} // 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 / (m_nbTxBytes * 2); // 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, isTx);
(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, isTx);
(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
@ -196,3 +202,15 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk
} }
} }
uint32_t UDPSinkFEC::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

@ -47,13 +47,14 @@ public:
/** Destroy UDP sink */ /** Destroy UDP sink */
~UDPSinkFEC(); ~UDPSinkFEC();
void init();
void startSender(); void startSender();
void stopSender(); void stopSender();
/** /**
* Write IQ samples * Write IQ samples
*/ */
void write(const SampleVector::iterator& begin, uint32_t sampleChunkSize); void write(const SampleVector::iterator& begin, uint32_t sampleChunkSize, bool isTx);
/** Return the last error, or return an empty string if there is no error. */ /** Return the last error, or return an empty string if there is no error. */
std::string error() std::string error()
@ -67,6 +68,7 @@ public:
void setSampleRate(uint32_t sampleRate); void setSampleRate(uint32_t sampleRate);
void setNbBlocksFEC(uint32_t nbBlocksFEC); void setNbBlocksFEC(uint32_t nbBlocksFEC);
void setNbTxBytes(uint32_t nbTxBytes) { m_nbTxBytes = nbTxBytes; }
void setRemoteAddress(const QString& address, uint16_t port); void setRemoteAddress(const QString& address, uint16_t port);
/** Return true if the stream is OK, return false if there is an error. */ /** Return true if the stream is OK, return false if there is an error. */
@ -85,6 +87,7 @@ private:
CRC64 m_crc64; CRC64 m_crc64;
RemoteMetaDataFEC m_currentMetaFEC; //!< Meta data for current frame RemoteMetaDataFEC m_currentMetaFEC; //!< Meta data for current frame
uint32_t m_nbBlocksFEC; //!< Variable number of FEC blocks uint32_t m_nbBlocksFEC; //!< Variable number of FEC blocks
uint32_t m_nbTxBytes;
float m_txDelayRatio; //!< Delay in ratio of nominal frame period float m_txDelayRatio; //!< Delay in ratio of nominal frame period
RemoteDataFrame *m_dataFrame; RemoteDataFrame *m_dataFrame;
RemoteSuperBlock m_superBlock; //!< current super block being built RemoteSuperBlock m_superBlock; //!< current super block being built
@ -97,6 +100,74 @@ private:
QThread *m_senderThread; QThread *m_senderThread;
QString m_remoteAddress; QString m_remoteAddress;
uint16_t m_remotePort; uint16_t m_remotePort;
uint32_t getNbSampleBits();
inline void convertSampleToData(const SampleVector::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 -> 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);
}
}
}
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 << 8;
*((int32_t*) &m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes]) = (begin+i)->m_imag << 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;
}
}
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 / (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);
}
}
}
}
}; };
#endif /* PLUGINS_SAMPLESINK_REMOTEOUTPUT_UDPSINKFEC_H_ */ #endif /* PLUGINS_SAMPLESINK_REMOTEOUTPUT_UDPSINKFEC_H_ */

View File

@ -77,7 +77,7 @@ void RemoteDataReadQueue::setSize(uint32_t size)
} }
} }
void RemoteDataReadQueue::readSample(Sample& s, bool scaleForTx) void RemoteDataReadQueue::readSample(Sample& s, bool isTx)
{ {
// depletion/repletion state // depletion/repletion state
if (m_dataFrame == nullptr) if (m_dataFrame == nullptr)
@ -89,7 +89,7 @@ void RemoteDataReadQueue::readSample(Sample& s, bool scaleForTx)
qDebug("RemoteDataReadQueue::readSample: initial pop new frame: queue size: %u", length()); qDebug("RemoteDataReadQueue::readSample: initial pop new frame: queue size: %u", length());
m_blockIndex = 1; m_blockIndex = 1;
m_sampleIndex = 0; m_sampleIndex = 0;
convertDataToSample(s, m_blockIndex, m_sampleIndex, scaleForTx); convertDataToSample(s, m_blockIndex, m_sampleIndex, isTx);
m_sampleIndex++; m_sampleIndex++;
} }
else else
@ -107,7 +107,7 @@ void RemoteDataReadQueue::readSample(Sample& s, bool scaleForTx)
if (m_sampleIndex < samplesPerBlock) if (m_sampleIndex < samplesPerBlock)
{ {
convertDataToSample(s, m_blockIndex, m_sampleIndex, scaleForTx); convertDataToSample(s, m_blockIndex, m_sampleIndex, isTx);
m_sampleIndex++; m_sampleIndex++;
m_sampleCount++; m_sampleCount++;
} }
@ -118,7 +118,7 @@ void RemoteDataReadQueue::readSample(Sample& s, bool scaleForTx)
if (m_blockIndex < RemoteNbOrginalBlocks) if (m_blockIndex < RemoteNbOrginalBlocks)
{ {
convertDataToSample(s, m_blockIndex, m_sampleIndex, scaleForTx); convertDataToSample(s, m_blockIndex, m_sampleIndex, isTx);
m_sampleIndex++; m_sampleIndex++;
m_sampleCount++; m_sampleCount++;
} }
@ -133,7 +133,7 @@ void RemoteDataReadQueue::readSample(Sample& s, bool scaleForTx)
{ {
m_blockIndex = 1; m_blockIndex = 1;
m_sampleIndex = 0; m_sampleIndex = 0;
convertDataToSample(s, m_blockIndex, m_sampleIndex, scaleForTx); convertDataToSample(s, m_blockIndex, m_sampleIndex, isTx);
m_sampleIndex++; m_sampleIndex++;
m_sampleCount++; m_sampleCount++;
} }

View File

@ -39,7 +39,7 @@ public:
~RemoteDataReadQueue(); ~RemoteDataReadQueue();
void push(RemoteDataFrame* dataFrame); //!< push frame on the queue void push(RemoteDataFrame* dataFrame); //!< push frame on the queue
void readSample(Sample& s, bool scaleForTx = false); //!< Read sample from queue possibly scaling to Tx size void readSample(Sample& s, bool isTx); //!< Read sample from queue
uint32_t length() const { return m_dataReadQueue.size(); } //!< Returns queue length uint32_t length() const { return m_dataReadQueue.size(); } //!< Returns queue length
uint32_t size() const { return m_maxSize; } //!< Returns queue size (max length) uint32_t size() const { return m_maxSize; } //!< Returns queue size (max length)
void setSize(uint32_t size); //!< Sets the queue size (max length) void setSize(uint32_t size); //!< Sets the queue size (max length)
@ -57,37 +57,74 @@ private:
RemoteDataFrame* pop(); //!< Pop frame from the queue RemoteDataFrame* pop(); //!< Pop frame from the queue
inline void convertDataToSample(Sample& s, uint32_t blockIndex, uint32_t sampleIndex, bool scaleForTx) inline void convertDataToSample(Sample& s, uint32_t blockIndex, uint32_t sampleIndex, bool isTx)
{ {
int sampleSize = m_dataFrame->m_superBlocks[blockIndex].m_header.m_sampleBytes * 2; // I/Q sample size in data block int sampleSize = m_dataFrame->m_superBlocks[blockIndex].m_header.m_sampleBytes * 2; // I/Q sample size in data block
int samplebits = m_dataFrame->m_superBlocks[blockIndex].m_header.m_sampleBits; // I or Q sample size in bits
int32_t iconv, qconv; int32_t iconv, qconv;
if ((sizeof(Sample) == 4) && (sampleSize == 8)) // generally 24->16 bits if (sizeof(Sample) == sampleSize) // no conversion
{
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 >>= scaleForTx ? (SDR_TX_SAMP_SZ-SDR_RX_SAMP_SZ) : (samplebits-SDR_RX_SAMP_SZ);
qconv >>= scaleForTx ? (SDR_TX_SAMP_SZ-SDR_RX_SAMP_SZ) : (samplebits-SDR_RX_SAMP_SZ);
s.setReal(iconv);
s.setImag(qconv);
}
else if ((sizeof(Sample) == 8) && (sampleSize == 4)) // generally 16->24 bits
{
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 <<= scaleForTx ? (SDR_TX_SAMP_SZ-samplebits) : (SDR_RX_SAMP_SZ-samplebits);
qconv <<= scaleForTx ? (SDR_TX_SAMP_SZ-samplebits) : (SDR_RX_SAMP_SZ-samplebits);
s.setReal(iconv);
s.setImag(qconv);
}
else if ((sampleSize == 4) || (sampleSize == 8)) // generally 16->16 or 24->24 bits
{ {
s = *((Sample*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize])); s = *((Sample*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize]));
} }
else // invalid size else if (isTx)
{ {
s = Sample{0, 0}; 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);
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];
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];
s.setReal(iconv);
s.setImag(qconv);
}
else // invalid
{
s = Sample{0, 0};
}
}
else
{
if (sampleSize == 2) // 8 -> 16 or 24 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);
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;
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;
s.setReal(iconv);
s.setImag(qconv);
}
else // invalid
{
s = Sample{0, 0};
}
} }
} }
}; };

View File

@ -9863,6 +9863,9 @@ margin-bottom: 20px;
"nbFECBlocks" : { "nbFECBlocks" : {
"type" : "integer" "type" : "integer"
}, },
"nbTxBytes" : {
"type" : "integer"
},
"apiAddress" : { "apiAddress" : {
"type" : "string" "type" : "string"
}, },
@ -51622,7 +51625,7 @@ except ApiException as e:
</div> </div>
<div id="generator"> <div id="generator">
<div class="content"> <div class="content">
Generated 2021-12-15T21:39:08.842+01:00 Generated 2021-12-18T22:54:13.645+01:00
</div> </div>
</div> </div>
</div> </div>

View File

@ -3,6 +3,8 @@ RemoteOutputSettings:
properties: properties:
nbFECBlocks: nbFECBlocks:
type: integer type: integer
nbTxBytes:
type: integer
apiAddress: apiAddress:
type: string type: string
apiPort: apiPort:

View File

@ -3,6 +3,8 @@ RemoteOutputSettings:
properties: properties:
nbFECBlocks: nbFECBlocks:
type: integer type: integer
nbTxBytes:
type: integer
apiAddress: apiAddress:
type: string type: string
apiPort: apiPort:

View File

@ -9863,6 +9863,9 @@ margin-bottom: 20px;
"nbFECBlocks" : { "nbFECBlocks" : {
"type" : "integer" "type" : "integer"
}, },
"nbTxBytes" : {
"type" : "integer"
},
"apiAddress" : { "apiAddress" : {
"type" : "string" "type" : "string"
}, },
@ -51622,7 +51625,7 @@ except ApiException as e:
</div> </div>
<div id="generator"> <div id="generator">
<div class="content"> <div class="content">
Generated 2021-12-15T21:39:08.842+01:00 Generated 2021-12-18T22:54:13.645+01:00
</div> </div>
</div> </div>
</div> </div>

View File

@ -30,6 +30,8 @@ SWGRemoteOutputSettings::SWGRemoteOutputSettings(QString* json) {
SWGRemoteOutputSettings::SWGRemoteOutputSettings() { SWGRemoteOutputSettings::SWGRemoteOutputSettings() {
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;
api_address = nullptr; api_address = nullptr;
m_api_address_isSet = false; m_api_address_isSet = false;
api_port = 0; api_port = 0;
@ -60,6 +62,8 @@ void
SWGRemoteOutputSettings::init() { SWGRemoteOutputSettings::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;
api_address = new QString(""); api_address = new QString("");
m_api_address_isSet = false; m_api_address_isSet = false;
api_port = 0; api_port = 0;
@ -85,6 +89,7 @@ SWGRemoteOutputSettings::init() {
void void
SWGRemoteOutputSettings::cleanup() { SWGRemoteOutputSettings::cleanup() {
if(api_address != nullptr) { if(api_address != nullptr) {
delete api_address; delete api_address;
} }
@ -116,6 +121,8 @@ void
SWGRemoteOutputSettings::fromJsonObject(QJsonObject &pJson) { SWGRemoteOutputSettings::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(&api_address, pJson["apiAddress"], "QString", "QString"); ::SWGSDRangel::setValue(&api_address, pJson["apiAddress"], "QString", "QString");
::SWGSDRangel::setValue(&api_port, pJson["apiPort"], "qint32", ""); ::SWGSDRangel::setValue(&api_port, pJson["apiPort"], "qint32", "");
@ -155,6 +162,9 @@ SWGRemoteOutputSettings::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(api_address != nullptr && *api_address != QString("")){ if(api_address != nullptr && *api_address != QString("")){
toJsonValue(QString("apiAddress"), api_address, obj, QString("QString")); toJsonValue(QString("apiAddress"), api_address, obj, QString("QString"));
} }
@ -199,6 +209,16 @@ SWGRemoteOutputSettings::setNbFecBlocks(qint32 nb_fec_blocks) {
this->m_nb_fec_blocks_isSet = true; this->m_nb_fec_blocks_isSet = true;
} }
qint32
SWGRemoteOutputSettings::getNbTxBytes() {
return nb_tx_bytes;
}
void
SWGRemoteOutputSettings::setNbTxBytes(qint32 nb_tx_bytes) {
this->nb_tx_bytes = nb_tx_bytes;
this->m_nb_tx_bytes_isSet = true;
}
QString* QString*
SWGRemoteOutputSettings::getApiAddress() { SWGRemoteOutputSettings::getApiAddress() {
return api_address; return api_address;
@ -307,6 +327,9 @@ SWGRemoteOutputSettings::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(api_address && *api_address != QString("")){ if(api_address && *api_address != QString("")){
isObjectUpdated = true; break; isObjectUpdated = true; break;
} }

View File

@ -45,6 +45,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* getApiAddress(); QString* getApiAddress();
void setApiAddress(QString* api_address); void setApiAddress(QString* api_address);
@ -82,6 +85,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* api_address; QString* api_address;
bool m_api_address_isSet; bool m_api_address_isSet;