From 9278b12e2523ff04f98fd295f85bbab3ec554a8d Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 19 Dec 2021 11:30:48 +0100 Subject: [PATCH] Remote output/source: implemented choice of sample size in transmission. Fixes in the size conversion routines --- doc/img/RemoteOutput_plugin.png | Bin 34589 -> 36424 bytes doc/img/RemoteOutput_plugin.xcf | Bin 113415 -> 120391 bytes .../remotesource/remotesourcesource.cpp | 2 +- .../samplesink/remoteoutput/remoteoutput.cpp | 24 ++++++++- .../remoteoutput/remoteoutputgui.cpp | 7 +++ .../samplesink/remoteoutput/remoteoutputgui.h | 1 + .../remoteoutput/remoteoutputgui.ui | 35 +++++++++++++ .../remoteoutput/remoteoutputsettings.cpp | 3 ++ .../remoteoutput/remoteoutputsettings.h | 1 + .../remoteoutput/remoteoutputworker.cpp | 5 +- .../remoteoutput/remoteoutputworker.h | 1 + .../samplesink/remoteoutput/udpsinkfec.cpp | 22 ++++---- plugins/samplesink/remoteoutput/udpsinkfec.h | 47 +++++++++++++++--- sdrbase/channel/remotedatareadqueue.cpp | 10 ++-- sdrbase/channel/remotedatareadqueue.h | 40 +++++++++++++-- sdrbase/resources/webapi/doc/html2/index.html | 5 +- .../doc/swagger/include/RemoteOutput.yaml | 2 + .../api/swagger/include/RemoteOutput.yaml | 2 + swagger/sdrangel/code/html2/index.html | 5 +- .../qt5/client/SWGRemoteOutputSettings.cpp | 23 +++++++++ .../code/qt5/client/SWGRemoteOutputSettings.h | 6 +++ 21 files changed, 207 insertions(+), 34 deletions(-) diff --git a/doc/img/RemoteOutput_plugin.png b/doc/img/RemoteOutput_plugin.png index e7a01975d0a44cd752fc4af535acbc91f9096724..c29389ca0b6203752401b02c5e790e24aa69e89a 100644 GIT binary patch literal 36424 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 literal 34589 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 diff --git a/doc/img/RemoteOutput_plugin.xcf b/doc/img/RemoteOutput_plugin.xcf index f02f5f490db53a3231405a9a16fd7aa5961880b0..41c84086bd96f5802c879101c3906d24e1269900 100644 GIT binary patch delta 10216 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 delta 5641 zcmZ|T3shBA8o=?p&qc1@vMdP$6g3IWQqz=5GnqiNeB_LeNQW5`?SWR7y_9iXMh!>N zM31jYy@I07AR=-|=o+GkEZQlS3>3>t#UsPS z8gB5TFC=cdN&Gxc+uhZAMt@Ozxg)vkQYAUgH?weBXonc*o8d$%F3TF?enF{CW_r(X zBdF9o7}Q18S`9(B1*x;*x&IuGg9Ezu5}hSRSli)&uPPmOa2wqw@}{ zpz}qyTCGReg(>YGDouC41N-X{hD|X)>r&y1AafD*azzltpeU_QG_Wrx~o-tCZ|3jv?PsT6ymvuDRn$B+PPnwrw*8O7t+5R3@M3elt40z&mQRl#beJeik3& zeUuq`Y@Hc7^8d|2vi0wTP9D|X>@+??Md_}`KV-#^-yLLr5f>3YF;beFmX6DDgYI-v zff+M#W!O(rIEBhnVu>@%&n8BPCr*?wkz*(En8Z^jn30pNpBHC7PE5YyQ3v#VBsJEK?FhvSy7MdX`G2Ulb4$o$olTr$< zOGmc9lhtu%tVbo71DA#yv!|O+T?#d3&$kxNP6|>Dy4#m-losDOkKc>)T)NwrHSRv+n(e8JL01`99apAs)= zr#niwv+2v|yYMS1UDOX>#WHbmJMqnNW{t1rx`8+wZPy>)^r*Y+fkdd0dK^oWteH!% z8Y)qbV>#(wyH#3RTYv#Qj<>p+xyv&KW$}Djb+=qyH5d1btKCQj*4%3TcE$A*<7A-U z%KTvS>)b8v^6WpEV;)K!W}VnRK^YqiJy{zf^&mIISd({-3NkkN^e8v6;kHLeKihlb zeav+nA4S)1-XcEKI{p+=#nyKOVy-yohaL?hTGUmn%1dg1d1Tj=^a-3)3(YH{veb zkH@eHFJhax{RUezsyFu593K}!SBQ( zH+IHecpt{$L`=cCw*QmQ5Ucll?|6*ja=kf=n{+~pztairbL1|!Q94*BwDei|`|>rI zjrlsE@ACE#;4LITVgh}nT7V4~7)_jrG#hw>_)oY2|AM9Xf%smuShiT}bCof!GB##e zF%^#BDLjMUiwA-*1fy^;#^WTMfv@0VM?0Yh)=-d(#driy;Tim1EDypEjKaYfkCSi) zzJiNwe@>{Cbu`Ii9IDmHJaoxPruT0_QqivUR7r?6;=`_Pw>{uD2XM~SPr<*Kn#emn*fv_98y#&!H@F1&^r zxDI#VKCHlcJd0Pv>R=4TXpF%GM?0z2Qz&>EU&9PshdXc|R$x7z#VcY>Fot3@#$bZ2 z6;+?v!KhuWlUZA!lUZ9K6(pJFhz~=pE~hUT#>q1}p{H(_%Z(S1{+bM(&^mTg9lNQH z-Bi~g)$7jVk79j$q}lpD5`X-p*su)WM(2@le;NWJ>PucSs&d_ z{pfaGXkFhkScOHnE_Ty3)ZW!7Kfcx8Jf}iud(5tjyh&au(p6kPj2C}Ol|SKRP#xub zS0Qpls5`dH^+C(Uq4GRXzmgTFM#~|p9;e>#evo>p_2L}+(0$ncs?yS>Anmlc%vqXt z`D*7uV*6(~mDQGeB+fl5=FKj-)1#^?jG}kfe^af(!;0iiRLKIVP$ECARf(Bpzp|@h zii=ms<>Jk_8_Td7n~`RVuSxt)N9>0Ea5#>`Bz)e{=Th%1pkM`V#@$$k)!2-e@tU}= zBX+}nI2^}e5K*0*!jJvT6tFaj`<2A9QBX+}nI2^}e5;5b zedz9A`g?mUC+&aEtDur9rKT8YK{*Umpv^v8Zu6-?FUsY2mzx!o_PDC0*i17X5vcxc>>lGZ^SLO pb{i_Nje?!H3-_RfCAc5U@i126F+71M@ndYl&t0zdNpsetDataAddress(settings.m_dataAddress, settings.m_dataPort); } } @@ -288,15 +288,28 @@ void RemoteOutput::applySettings(const RemoteOutputSettings& settings, bool forc { reverseAPIKeys.append("nbFECBlocks"); - if (m_remoteOutputWorker != 0) { + if (m_remoteOutputWorker) { 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(); qDebug() << "RemoteOutput::applySettings:" << " m_nbFECBlocks: " << settings.m_nbFECBlocks + << " m_nbTxBytes: " << settings.m_nbTxBytes << " m_apiAddress: " << settings.m_apiAddress << " m_apiPort: " << settings.m_apiPort << " m_dataAddress: " << settings.m_dataAddress @@ -404,6 +417,9 @@ void RemoteOutput::webapiUpdateDeviceSettings( if (deviceSettingsKeys.contains("nbFECBlocks")) { settings.m_nbFECBlocks = response.getRemoteOutputSettings()->getNbFecBlocks(); } + if (deviceSettingsKeys.contains("nbTxBytes")) { + settings.m_nbTxBytes = response.getRemoteOutputSettings()->getNbTxBytes(); + } if (deviceSettingsKeys.contains("apiAddress")) { settings.m_apiAddress = *response.getRemoteOutputSettings()->getApiAddress(); } @@ -450,6 +466,7 @@ int RemoteOutput::webapiReportGet( void RemoteOutput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const RemoteOutputSettings& settings) { response.getRemoteOutputSettings()->setNbFecBlocks(settings.m_nbFECBlocks); + response.getRemoteOutputSettings()->setNbTxBytes(settings.m_nbTxBytes); response.getRemoteOutputSettings()->setApiAddress(new QString(settings.m_apiAddress)); response.getRemoteOutputSettings()->setApiPort(settings.m_apiPort); response.getRemoteOutputSettings()->setDataAddress(new QString(settings.m_dataAddress)); @@ -657,6 +674,9 @@ void RemoteOutput::webapiReverseSendSettings(QList& deviceSettingsKeys, if (deviceSettingsKeys.contains("nbFECBlocks") || force) { swgRemoteOutputSettings->setNbFecBlocks(settings.m_nbFECBlocks); } + if (deviceSettingsKeys.contains("nbTxBytes") || force) { + swgRemoteOutputSettings->setNbTxBytes(settings.m_nbTxBytes); + } if (deviceSettingsKeys.contains("apiAddress") || force) { swgRemoteOutputSettings->setApiAddress(new QString(settings.m_apiAddress)); } diff --git a/plugins/samplesink/remoteoutput/remoteoutputgui.cpp b/plugins/samplesink/remoteoutput/remoteoutputgui.cpp index 0e011c194..790604b9f 100644 --- a/plugins/samplesink/remoteoutput/remoteoutputgui.cpp +++ b/plugins/samplesink/remoteoutput/remoteoutputgui.cpp @@ -212,6 +212,7 @@ void RemoteOutputSinkGui::displaySettings() blockApplySettings(true); ui->centerFrequency->setText(QString("%L1").arg(m_deviceCenterFrequency)); 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 s1 = QString::number(m_settings.m_nbFECBlocks, 'f', 0); @@ -310,6 +311,12 @@ void RemoteOutputSinkGui::on_channelIndex_returnPressed() sendSettings(); } +void RemoteOutputSinkGui::on_nbTxBytes_currentIndexChanged(int index) +{ + m_settings.m_nbTxBytes = 1 << index; + sendSettings(); +} + void RemoteOutputSinkGui::on_apiAddress_returnPressed() { m_settings.m_apiAddress = ui->apiAddress->text(); diff --git a/plugins/samplesink/remoteoutput/remoteoutputgui.h b/plugins/samplesink/remoteoutput/remoteoutputgui.h index af1bd8c78..7b1964440 100644 --- a/plugins/samplesink/remoteoutput/remoteoutputgui.h +++ b/plugins/samplesink/remoteoutput/remoteoutputgui.h @@ -129,6 +129,7 @@ private slots: void on_nbFECBlocks_valueChanged(int value); void on_deviceIndex_returnPressed(); void on_channelIndex_returnPressed(); + void on_nbTxBytes_currentIndexChanged(int index); void on_apiAddress_returnPressed(); void on_apiPort_returnPressed(); void on_dataAddress_returnPressed(); diff --git a/plugins/samplesink/remoteoutput/remoteoutputgui.ui b/plugins/samplesink/remoteoutput/remoteoutputgui.ui index 2935a78f9..84a293ac8 100644 --- a/plugins/samplesink/remoteoutput/remoteoutputgui.ui +++ b/plugins/samplesink/remoteoutput/remoteoutputgui.ui @@ -239,6 +239,41 @@ + + + + Tx bytes + + + + + + + + 50 + 16777215 + + + + Number of transmitted bytes per I or Q sample + + + + 1 + + + + + 2 + + + + + 4 + + + + diff --git a/plugins/samplesink/remoteoutput/remoteoutputsettings.cpp b/plugins/samplesink/remoteoutput/remoteoutputsettings.cpp index e615e8672..cbff6e6f0 100644 --- a/plugins/samplesink/remoteoutput/remoteoutputsettings.cpp +++ b/plugins/samplesink/remoteoutput/remoteoutputsettings.cpp @@ -26,6 +26,7 @@ RemoteOutputSettings::RemoteOutputSettings() void RemoteOutputSettings::resetToDefaults() { m_nbFECBlocks = 0; + m_nbTxBytes = 2; m_apiAddress = "127.0.0.1"; m_apiPort = 9091; m_dataAddress = "127.0.0.1"; @@ -42,6 +43,7 @@ QByteArray RemoteOutputSettings::serialize() const { SimpleSerializer s(1); + s.writeU32(3, m_nbTxBytes); s.writeU32(4, m_nbFECBlocks); s.writeString(5, m_apiAddress); s.writeU32(6, m_apiPort); @@ -71,6 +73,7 @@ bool RemoteOutputSettings::deserialize(const QByteArray& data) { quint32 uintval; + d.readU32(4, &m_nbTxBytes, 2); d.readU32(4, &m_nbFECBlocks, 0); d.readString(5, &m_apiAddress, "127.0.0.1"); d.readU32(6, &uintval, 9090); diff --git a/plugins/samplesink/remoteoutput/remoteoutputsettings.h b/plugins/samplesink/remoteoutput/remoteoutputsettings.h index cf61d20c0..830e056dd 100644 --- a/plugins/samplesink/remoteoutput/remoteoutputsettings.h +++ b/plugins/samplesink/remoteoutput/remoteoutputsettings.h @@ -23,6 +23,7 @@ struct RemoteOutputSettings { quint32 m_nbFECBlocks; + quint32 m_nbTxBytes; QString m_apiAddress; quint16 m_apiPort; QString m_dataAddress; diff --git a/plugins/samplesink/remoteoutput/remoteoutputworker.cpp b/plugins/samplesink/remoteoutput/remoteoutputworker.cpp index 7c54fee62..173c9630c 100644 --- a/plugins/samplesink/remoteoutput/remoteoutputworker.cpp +++ b/plugins/samplesink/remoteoutput/remoteoutputworker.cpp @@ -48,6 +48,7 @@ RemoteOutputWorker::~RemoteOutputWorker() void RemoteOutputWorker::startWork() { qDebug() << "RemoteOutputWorker::startWork: "; + m_udpSinkFEC.init(); m_udpSinkFEC.startSender(); m_maxThrottlems = 0; m_running = true; @@ -126,14 +127,14 @@ void RemoteOutputWorker::tick() { SampleVector::iterator beginRead = data.begin() + iPart1Begin; unsigned int partSize = iPart1End - iPart1Begin; - m_udpSinkFEC.write(beginRead, partSize); + m_udpSinkFEC.write(beginRead, partSize, true); } if (iPart2Begin != iPart2End) { SampleVector::iterator beginRead = data.begin() + iPart2Begin; unsigned int partSize = iPart2End - iPart2Begin; - m_udpSinkFEC.write(beginRead, partSize); + m_udpSinkFEC.write(beginRead, partSize, true); } } } diff --git a/plugins/samplesink/remoteoutput/remoteoutputworker.h b/plugins/samplesink/remoteoutput/remoteoutputworker.h index 8a20ab52b..4fcbbd8f5 100644 --- a/plugins/samplesink/remoteoutput/remoteoutputworker.h +++ b/plugins/samplesink/remoteoutput/remoteoutputworker.h @@ -49,6 +49,7 @@ public: void setSamplerate(int samplerate); 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); } bool isRunning() const { return m_running; } diff --git a/plugins/samplesink/remoteoutput/udpsinkfec.cpp b/plugins/samplesink/remoteoutput/udpsinkfec.cpp index b53684571..0ba66ed57 100644 --- a/plugins/samplesink/remoteoutput/udpsinkfec.cpp +++ b/plugins/samplesink/remoteoutput/udpsinkfec.cpp @@ -31,7 +31,6 @@ UDPSinkFEC::UDPSinkFEC() : m_sampleRate(48000), m_nbSamples(0), m_nbBlocksFEC(0), - //m_nbTxBytes(SDR_RX_SAMP_SZ <= 16 ? 2 : 4), m_nbTxBytes(2), m_txDelayRatio(0.0), m_dataFrame(nullptr), @@ -58,6 +57,15 @@ UDPSinkFEC::~UDPSinkFEC() delete m_senderThread; } +void UDPSinkFEC::init() +{ + m_dataFrame = nullptr; + m_txBlockIndex = 0; + m_txBlocksIndex = 0; + m_frameCount = 0; + m_sampleIndex = 0; +} + void UDPSinkFEC::startSender() { qDebug("UDPSinkFEC::startSender"); @@ -92,7 +100,7 @@ void UDPSinkFEC::setRemoteAddress(const QString& address, uint16_t port) 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; @@ -156,19 +164,13 @@ void UDPSinkFEC::write(const SampleVector::iterator& begin, uint32_t sampleChunk 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 { - convertSampleToData(begin + inSamplesIndex, inRemainingSamples); - // memcpy((void *) &m_superBlock.m_protectedBlock.buf[m_sampleIndex*sizeof(Sample)], - // (const void *) &(*(begin+inSamplesIndex)), - // inRemainingSamples * sizeof(Sample)); + convertSampleToData(begin + inSamplesIndex, inRemainingSamples, isTx); m_sampleIndex += inRemainingSamples; it = end; // all input samples are consumed } else // complete super block and initiate the next if not end of frame { - convertSampleToData(begin + inSamplesIndex, samplesPerBlock - m_sampleIndex); - // 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, isTx); it += samplesPerBlock - m_sampleIndex; m_sampleIndex = 0; diff --git a/plugins/samplesink/remoteoutput/udpsinkfec.h b/plugins/samplesink/remoteoutput/udpsinkfec.h index 82d48a58a..00e06090d 100644 --- a/plugins/samplesink/remoteoutput/udpsinkfec.h +++ b/plugins/samplesink/remoteoutput/udpsinkfec.h @@ -47,13 +47,14 @@ public: /** Destroy UDP sink */ ~UDPSinkFEC(); + void init(); void startSender(); void stopSender(); /** * 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. */ std::string error() @@ -67,6 +68,7 @@ public: void setSampleRate(uint32_t sampleRate); void setNbBlocksFEC(uint32_t nbBlocksFEC); + void setNbTxBytes(uint32_t nbTxBytes) { m_nbTxBytes = nbTxBytes; } void setRemoteAddress(const QString& address, uint16_t port); /** Return true if the stream is OK, return false if there is an error. */ @@ -101,7 +103,7 @@ private: uint32_t getNbSampleBits(); - inline void convertSampleToData(const SampleVector::iterator& begin, int nbSamples) + inline void convertSampleToData(const SampleVector::iterator& begin, int nbSamples, bool isTx) { if (sizeof(Sample) == m_nbTxBytes * 2) // 16 -> 16 or 24 ->24: direct copy { @@ -109,30 +111,59 @@ private: (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++) { - m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2] = (begin+i)->m_real << 8; - 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 << 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++) { - m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2] = (begin+i)->m_real >> 8; - 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 >> 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] = (begin+i)->m_real >> sizeof(Sample)*2; - m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2 + m_nbTxBytes] = (begin+i)->m_imag >> sizeof(Sample)*2; + m_superBlock.m_protectedBlock.buf[(m_sampleIndex+ i)*m_nbTxBytes*2] = + (uint8_t) (((begin+i)->m_real / (1<m_imag / (1<m_superBlocks[blockIndex].m_header.m_sampleBytes * 2; // I/Q sample size in data block int32_t iconv, qconv; @@ -66,12 +66,44 @@ private: { s = *((Sample*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize])); } + else if (isTx) + { + 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 { - iconv = ((int32_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize]))[0] << sizeof(Sample)*2; - qconv = ((int32_t*) &(m_dataFrame->m_superBlocks[blockIndex].m_protectedBlock.buf[sampleIndex*sampleSize+sampleSize]))[0] << sizeof(Sample)*2; + 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); } diff --git a/sdrbase/resources/webapi/doc/html2/index.html b/sdrbase/resources/webapi/doc/html2/index.html index bac167a93..18dacf153 100644 --- a/sdrbase/resources/webapi/doc/html2/index.html +++ b/sdrbase/resources/webapi/doc/html2/index.html @@ -9863,6 +9863,9 @@ margin-bottom: 20px; "nbFECBlocks" : { "type" : "integer" }, + "nbTxBytes" : { + "type" : "integer" + }, "apiAddress" : { "type" : "string" }, @@ -51622,7 +51625,7 @@ except ApiException as e:
- Generated 2021-12-15T21:39:08.842+01:00 + Generated 2021-12-18T22:54:13.645+01:00
diff --git a/sdrbase/resources/webapi/doc/swagger/include/RemoteOutput.yaml b/sdrbase/resources/webapi/doc/swagger/include/RemoteOutput.yaml index dad91083b..9db40eab8 100644 --- a/sdrbase/resources/webapi/doc/swagger/include/RemoteOutput.yaml +++ b/sdrbase/resources/webapi/doc/swagger/include/RemoteOutput.yaml @@ -3,6 +3,8 @@ RemoteOutputSettings: properties: nbFECBlocks: type: integer + nbTxBytes: + type: integer apiAddress: type: string apiPort: diff --git a/swagger/sdrangel/api/swagger/include/RemoteOutput.yaml b/swagger/sdrangel/api/swagger/include/RemoteOutput.yaml index dad91083b..9db40eab8 100644 --- a/swagger/sdrangel/api/swagger/include/RemoteOutput.yaml +++ b/swagger/sdrangel/api/swagger/include/RemoteOutput.yaml @@ -3,6 +3,8 @@ RemoteOutputSettings: properties: nbFECBlocks: type: integer + nbTxBytes: + type: integer apiAddress: type: string apiPort: diff --git a/swagger/sdrangel/code/html2/index.html b/swagger/sdrangel/code/html2/index.html index bac167a93..18dacf153 100644 --- a/swagger/sdrangel/code/html2/index.html +++ b/swagger/sdrangel/code/html2/index.html @@ -9863,6 +9863,9 @@ margin-bottom: 20px; "nbFECBlocks" : { "type" : "integer" }, + "nbTxBytes" : { + "type" : "integer" + }, "apiAddress" : { "type" : "string" }, @@ -51622,7 +51625,7 @@ except ApiException as e:
- Generated 2021-12-15T21:39:08.842+01:00 + Generated 2021-12-18T22:54:13.645+01:00
diff --git a/swagger/sdrangel/code/qt5/client/SWGRemoteOutputSettings.cpp b/swagger/sdrangel/code/qt5/client/SWGRemoteOutputSettings.cpp index 64a4143a1..827f50054 100644 --- a/swagger/sdrangel/code/qt5/client/SWGRemoteOutputSettings.cpp +++ b/swagger/sdrangel/code/qt5/client/SWGRemoteOutputSettings.cpp @@ -30,6 +30,8 @@ SWGRemoteOutputSettings::SWGRemoteOutputSettings(QString* json) { SWGRemoteOutputSettings::SWGRemoteOutputSettings() { nb_fec_blocks = 0; m_nb_fec_blocks_isSet = false; + nb_tx_bytes = 0; + m_nb_tx_bytes_isSet = false; api_address = nullptr; m_api_address_isSet = false; api_port = 0; @@ -60,6 +62,8 @@ void SWGRemoteOutputSettings::init() { nb_fec_blocks = 0; m_nb_fec_blocks_isSet = false; + nb_tx_bytes = 0; + m_nb_tx_bytes_isSet = false; api_address = new QString(""); m_api_address_isSet = false; api_port = 0; @@ -85,6 +89,7 @@ SWGRemoteOutputSettings::init() { void SWGRemoteOutputSettings::cleanup() { + if(api_address != nullptr) { delete api_address; } @@ -116,6 +121,8 @@ void SWGRemoteOutputSettings::fromJsonObject(QJsonObject &pJson) { ::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_port, pJson["apiPort"], "qint32", ""); @@ -155,6 +162,9 @@ SWGRemoteOutputSettings::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(api_address != nullptr && *api_address != 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; } +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* SWGRemoteOutputSettings::getApiAddress() { return api_address; @@ -307,6 +327,9 @@ SWGRemoteOutputSettings::isSet(){ if(m_nb_fec_blocks_isSet){ isObjectUpdated = true; break; } + if(m_nb_tx_bytes_isSet){ + isObjectUpdated = true; break; + } if(api_address && *api_address != QString("")){ isObjectUpdated = true; break; } diff --git a/swagger/sdrangel/code/qt5/client/SWGRemoteOutputSettings.h b/swagger/sdrangel/code/qt5/client/SWGRemoteOutputSettings.h index f29c094bf..e647abde8 100644 --- a/swagger/sdrangel/code/qt5/client/SWGRemoteOutputSettings.h +++ b/swagger/sdrangel/code/qt5/client/SWGRemoteOutputSettings.h @@ -45,6 +45,9 @@ public: qint32 getNbFecBlocks(); void setNbFecBlocks(qint32 nb_fec_blocks); + qint32 getNbTxBytes(); + void setNbTxBytes(qint32 nb_tx_bytes); + QString* getApiAddress(); void setApiAddress(QString* api_address); @@ -82,6 +85,9 @@ private: qint32 nb_fec_blocks; bool m_nb_fec_blocks_isSet; + qint32 nb_tx_bytes; + bool m_nb_tx_bytes_isSet; + QString* api_address; bool m_api_address_isSet;