20 #include <SoapySDR/Formats.hpp> 21 #include <SoapySDR/Errors.hpp> 32 m_nbChannels(nbTxChannels),
33 m_interpolatorType(InterpolatorFloat)
35 qDebug(
"SoapySDROutputThread::SoapySDROutputThread");
41 qDebug(
"SoapySDROutputThread::~SoapySDROutputThread");
87 std::iota(channels.begin(), channels.end(), 0);
90 qDebug(
"SoapySDROutputThread::run: m_sampleRate: %u",
m_sampleRate);
91 for (
const auto &it : channels) {
96 double fullScale(0.0);
97 std::string format =
m_dev->getNativeStreamFormat(SOAPY_SDR_TX, channels.front(), fullScale);
99 qDebug(
"SoapySDROutputThread::run: format: %s fullScale: %f", format.c_str(), fullScale);
101 if ((format ==
"CS8") && (fullScale == 128.0)) {
103 }
else if ((format ==
"CS16") && (fullScale == 2048.0)) {
105 }
else if ((format ==
"CS16") && (fullScale == 32768.0)) {
112 unsigned int elemSize = SoapySDR::formatToSize(format);
113 SoapySDR::Stream *stream =
m_dev->setupStream(SOAPY_SDR_TX, format, channels);
116 const unsigned int numElems =
m_dev->getStreamMTU(stream);
117 std::vector<std::vector<char>> buffMem(
m_nbChannels, std::vector<char>(elemSize*numElems));
121 buffs[
i] = buffMem[
i].data();
124 m_dev->activateStream(stream);
128 long initialTtimeoutUs = 10000000 * blockTime;
129 long timeoutUs = initialTtimeoutUs < 250000 ? 250000 : initialTtimeoutUs;
131 qDebug(
"SoapySDROutputThread::run: numElems: %u elemSize: %u initialTtimeoutUs: %ld timeoutUs: %ld",
132 numElems, elemSize, initialTtimeoutUs, timeoutUs);
133 qDebug(
"SoapySDROutputThread::run: start running loop");
137 int ret =
m_dev->writeStream(stream, buffs.data(), numElems, flags, timeNs, timeoutUs);
139 if (ret == SOAPY_SDR_TIMEOUT)
141 qWarning(
"SoapySDROutputThread::run: timeout: flags: %d timeNs: %lld timeoutUs: %ld", flags, timeNs, timeoutUs);
143 else if (ret == SOAPY_SDR_OVERFLOW)
145 qWarning(
"SoapySDROutputThread::run: overflow: flags: %d timeNs: %lld timeoutUs: %ld", flags, timeNs, timeoutUs);
149 qCritical(
"SoapySDROutputThread::run: Unexpected write stream error: %s", SoapySDR::errToStr(ret));
153 if (m_nbChannels > 1)
178 qDebug(
"SoapySDROutputThread::run: stop running loop");
179 m_dev->deactivateStream(stream);
180 m_dev->closeStream(stream);
185 qWarning(
"SoapySDROutputThread::run: no channels or FIFO allocated. Aborting");
193 unsigned int fifoCount = 0;
239 for(
unsigned int ichan = 0; ichan <
m_nbChannels; ichan++)
246 callbackSO8((qint8*) buffs[ichan], samplesPerChannel, ichan);
249 callbackSO12((qint16*) buffs[ichan], samplesPerChannel, ichan);
252 callbackSO16((qint16*) buffs[ichan], samplesPerChannel, ichan);
265 std::fill((qint8*) buffs[ichan], (qint8*) buffs[ichan] + 2*samplesPerChannel, 0);
269 std::fill((qint16*) buffs[ichan], (qint16*) buffs[ichan] + 2*samplesPerChannel, 0);
273 std::fill((
float*) buffs[ichan], (
float*) buffs[ichan] + 2*samplesPerChannel, 0.0f);
289 qDebug(
"SoapySDROutputThread::callbackSO8: read lags: %f", bal);
290 }
else if (bal > 0.25) {
291 qDebug(
"SoapySDROutputThread::callbackSO8: read leads: %f", bal);
294 SampleVector::iterator beginRead;
331 std::fill(buf, buf+2*len, 0);
342 qDebug(
"SoapySDROutputThread::callbackSO12: read lags: %f", bal);
343 }
else if (bal > 0.25) {
344 qDebug(
"SoapySDROutputThread::callbackSO12: read leads: %f", bal);
347 SampleVector::iterator beginRead;
384 std::fill(buf, buf+2*len, 0);
395 qDebug(
"SoapySDROutputThread::callbackSO16: read lags: %f", bal);
396 }
else if (bal > 0.25) {
397 qDebug(
"SoapySDROutputThread::callbackSO16: read leads: %f", bal);
400 SampleVector::iterator beginRead;
437 std::fill(buf, buf+2*len, 0);
449 qDebug(
"SoapySDROutputThread::callbackSO16: read lags: %f", bal);
450 }
else if (bal > 0.25) {
451 qDebug(
"SoapySDROutputThread::callbackSO16: read leads: %f", bal);
454 SampleVector::iterator beginRead;
491 std::fill(buf, buf+2*len, 0.0f);
void interpolate16_cen(SampleVector::iterator *it, float *buf, qint32 len, bool invertIQ=false)
unsigned int m_sampleRate
unsigned int getLog2Interpolation(unsigned int channel) const
void callbackSO16(qint16 *buf, qint32 len, unsigned int channel=0)
SampleSourceFifo * m_sampleFifo
void interpolate8_cen(SampleVector::iterator *it, float *buf, qint32 len, bool invertIQ=false)
void interpolate64_cen(SampleVector::iterator *it, T *buf, qint32 len, bool invertIQ=false)
float getRWBalance() const
Interpolators< qint16, SDR_TX_SAMP_SZ, 12 > m_interpolators12
void interpolate4_cen(SampleVector::iterator *it, float *buf, qint32 len, bool invertIQ=false)
void interpolate64_cen(SampleVector::iterator *it, float *buf, qint32 len, bool invertIQ=false)
void interpolate32_cen(SampleVector::iterator *it, T *buf, qint32 len, bool invertIQ=false)
QWaitCondition m_startWaiter
void interpolate8_cen(SampleVector::iterator *it, T *buf, qint32 len, bool invertIQ=false)
void callbackSOIF(float *buf, qint32 len, unsigned int channel=0)
unsigned int getNbFifos()
unsigned int m_nbChannels
InterpolatorType m_interpolatorType
void interpolate2_cen(SampleVector::iterator *it, T *buf, qint32 len, bool invertIQ=false)
Interpolators< qint8, SDR_TX_SAMP_SZ, 8 > m_interpolators8
InterpolatorsIF< SDR_TX_SAMP_SZ, SDR_TX_SAMP_SZ > m_interpolatorsIF
void readAdvance(SampleVector::iterator &readUntil, unsigned int nbSamples)
SoapySDROutputThread(SoapySDR::Device *dev, unsigned int nbTxChannels, QObject *parent=0)
Interpolators< qint16, SDR_TX_SAMP_SZ, 16 > m_interpolators16
void setFifo(unsigned int channel, SampleSourceFifo *sampleFifo)
void interpolate2_cen(SampleVector::iterator *it, float *buf, qint32 len, bool invertIQ=false)
void interpolate32_cen(SampleVector::iterator *it, float *buf, qint32 len, bool invertIQ=false)
void callbackMO(std::vector< void *> &buffs, qint32 samplesPerChannel)
void interpolate1(SampleVector::iterator *it, float *buf, qint32 len, bool invertIQ=false)
void interpolate1(SampleVector::iterator *it, T *buf, qint32 len, bool invertIQ=false)
void interpolate16_cen(SampleVector::iterator *it, T *buf, qint32 len, bool invertIQ=false)
void interpolate4_cen(SampleVector::iterator *it, T *buf, qint32 len, bool invertIQ=false)
void callbackSO8(qint8 *buf, qint32 len, unsigned int channel=0)
Channel * m_channels
Array of channels dynamically allocated for the given number of Tx channels.
SampleSourceFifo * getFifo(unsigned int channel)
unsigned int m_log2Interp
void callbackSO12(qint16 *buf, qint32 len, unsigned int channel=0)
void setLog2Interpolation(unsigned int channel, unsigned int log2_interp)