sdrangel/plugins/samplesource/testsource/testsourceworker.h

366 lines
12 KiB
C
Raw Normal View History

2018-01-13 20:25:24 -05:00
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018-2020 Edouard Griffiths, F4EXB <f4exb06@gmail.com> //
// Copyright (C) 2022 Jiří Pinkava <jiri.pinkava@rossum.ai> //
2018-01-13 20:25:24 -05:00
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// (at your option) any later version. //
2018-01-13 20:25:24 -05:00
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef _TESTSOURCE_TESTSOURCEWORKER_H_
#define _TESTSOURCE_TESTSOURCEWORKER_H_
2018-01-13 20:25:24 -05:00
2019-05-21 15:18:49 -04:00
#include <map>
#include <QObject>
2018-01-13 20:25:24 -05:00
#include <QTimer>
#include <QElapsedTimer>
#include <QDebug>
#include "dsp/samplesinkfifo.h"
#include "dsp/decimators.h"
#include "dsp/ncof.h"
2018-09-06 08:29:14 -04:00
#include "util/messagequeue.h"
2018-01-13 20:25:24 -05:00
#include "testsourcesettings.h"
2018-01-13 20:25:24 -05:00
#define TESTSOURCE_THROTTLE_MS 50
class TestSourceWorker : public QObject {
2018-01-13 20:25:24 -05:00
Q_OBJECT
public:
TestSourceWorker(SampleSinkFifo* sampleFifo, QObject* parent = 0);
~TestSourceWorker();
2018-09-06 08:29:14 -04:00
void startWork();
void stopWork();
2018-01-13 20:25:24 -05:00
void setSamplerate(int samplerate);
void setLog2Decimation(unsigned int log2_decim);
void setFcPos(int fcPos);
void setBitSize(uint32_t bitSizeIndex);
void setAmplitudeBits(int32_t amplitudeBits);
void setDCFactor(float iFactor);
void setIFactor(float iFactor);
void setQFactor(float qFactor);
void setPhaseImbalance(float phaseImbalance);
2018-01-13 20:25:24 -05:00
void setFrequencyShift(int shift);
void setToneFrequency(int toneFrequency);
void setModulation(TestSourceSettings::Modulation modulation);
void setAMModulation(float amModulation);
void setFMDeviation(float deviation);
2018-10-23 18:10:12 -04:00
void setPattern0();
void setPattern1();
2018-10-25 07:53:58 -04:00
void setPattern2();
2018-01-13 20:25:24 -05:00
private:
volatile bool m_running;
2018-01-13 20:25:24 -05:00
2018-01-13 22:43:24 -05:00
qint16 *m_buf;
2018-01-13 20:25:24 -05:00
quint32 m_bufsize;
quint32 m_chunksize;
SampleVector m_convertBuffer;
SampleSinkFifo* m_sampleFifo;
NCOF m_nco;
NCOF m_toneNco;
2018-01-13 22:43:24 -05:00
int m_frequencyShift;
int m_toneFrequency;
TestSourceSettings::Modulation m_modulation;
float m_amModulation;
float m_fmDeviationUnit;
float m_fmPhasor;
2018-10-23 08:34:56 -04:00
uint32_t m_pulseWidth; //!< pulse width in number of samples
uint32_t m_pulseSampleCount;
uint32_t m_pulsePatternCount;
uint32_t m_pulsePatternCycle;
uint32_t m_pulsePatternPlaces;
2018-01-13 20:25:24 -05:00
int m_samplerate;
unsigned int m_log2Decim;
int m_fcPos;
uint32_t m_bitSizeIndex;
uint32_t m_bitShift;
int32_t m_amplitudeBits;
float m_dcBias;
float m_iBias;
float m_qBias;
float m_phaseImbalance;
int32_t m_amplitudeBitsDC;
int32_t m_amplitudeBitsI;
int32_t m_amplitudeBitsQ;
2018-01-13 20:25:24 -05:00
uint64_t m_frequency;
int m_fcPosShift;
int m_throttlems;
2018-09-06 08:29:14 -04:00
QTimer m_timer;
2018-01-13 20:25:24 -05:00
QElapsedTimer m_elapsedTimer;
bool m_throttleToggle;
QRecursiveMutex m_mutex;
2018-01-13 20:25:24 -05:00
2018-09-06 08:29:14 -04:00
MessageQueue m_inputMessageQueue;
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 8, true> m_decimators_8;
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12, true> m_decimators_12;
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 16, true> m_decimators_16;
2018-01-13 20:25:24 -05:00
2019-05-21 15:18:49 -04:00
std::map<int, int> m_timerHistogram;
uint32_t m_histoCounter;
2018-01-13 22:43:24 -05:00
void callback(const qint16* buf, qint32 len);
2018-01-13 20:25:24 -05:00
void setBuffers(quint32 chunksize);
void generate(quint32 chunksize);
void pullAF(Real& afSample);
2018-01-13 20:25:24 -05:00
// Decimate according to specified log2 (ex: log2=4 => decim=16)
2018-01-13 22:43:24 -05:00
inline void convert_8(SampleVector::iterator* it, const qint16* buf, qint32 len)
2018-01-13 20:25:24 -05:00
{
if (m_log2Decim == 0) {
m_decimators_8.decimate1(it, buf, len);
} else {
if (m_fcPos == 0) { // Infradyne
switch (m_log2Decim) {
case 1:
m_decimators_8.decimate2_inf(it, buf, len);
break;
case 2:
m_decimators_8.decimate4_inf(it, buf, len);
break;
case 3:
m_decimators_8.decimate8_inf(it, buf, len);
break;
case 4:
m_decimators_8.decimate16_inf(it, buf, len);
break;
case 5:
m_decimators_8.decimate32_inf(it, buf, len);
break;
case 6:
m_decimators_8.decimate64_inf(it, buf, len);
break;
default:
break;
}
} else if (m_fcPos == 1) {// Supradyne
switch (m_log2Decim) {
case 1:
m_decimators_8.decimate2_sup(it, buf, len);
break;
case 2:
m_decimators_8.decimate4_sup(it, buf, len);
break;
case 3:
m_decimators_8.decimate8_sup(it, buf, len);
break;
case 4:
m_decimators_8.decimate16_sup(it, buf, len);
break;
case 5:
m_decimators_8.decimate32_sup(it, buf, len);
break;
case 6:
m_decimators_8.decimate64_sup(it, buf, len);
break;
default:
break;
}
} else { // Centered
switch (m_log2Decim) {
case 1:
m_decimators_8.decimate2_cen(it, buf, len);
break;
case 2:
m_decimators_8.decimate4_cen(it, buf, len);
break;
case 3:
m_decimators_8.decimate8_cen(it, buf, len);
break;
case 4:
m_decimators_8.decimate16_cen(it, buf, len);
break;
case 5:
m_decimators_8.decimate32_cen(it, buf, len);
break;
case 6:
m_decimators_8.decimate64_cen(it, buf, len);
break;
default:
break;
}
}
}
}
2018-01-13 22:43:24 -05:00
void convert_12(SampleVector::iterator* it, const qint16* buf, qint32 len)
2018-01-13 20:25:24 -05:00
{
if (m_log2Decim == 0) {
m_decimators_12.decimate1(it, buf, len);
} else {
if (m_fcPos == 0) { // Infradyne
switch (m_log2Decim) {
case 1:
m_decimators_12.decimate2_inf(it, buf, len);
break;
case 2:
m_decimators_12.decimate4_inf(it, buf, len);
break;
case 3:
m_decimators_12.decimate8_inf(it, buf, len);
break;
case 4:
m_decimators_12.decimate16_inf(it, buf, len);
break;
case 5:
m_decimators_12.decimate32_inf(it, buf, len);
break;
case 6:
m_decimators_12.decimate64_inf(it, buf, len);
break;
default:
break;
}
} else if (m_fcPos == 1) {// Supradyne
switch (m_log2Decim) {
case 1:
m_decimators_12.decimate2_sup(it, buf, len);
break;
case 2:
m_decimators_12.decimate4_sup(it, buf, len);
break;
case 3:
m_decimators_12.decimate8_sup(it, buf, len);
break;
case 4:
m_decimators_12.decimate16_sup(it, buf, len);
break;
case 5:
m_decimators_12.decimate32_sup(it, buf, len);
break;
case 6:
m_decimators_12.decimate64_sup(it, buf, len);
break;
default:
break;
}
} else { // Centered
switch (m_log2Decim) {
case 1:
m_decimators_12.decimate2_cen(it, buf, len);
break;
case 2:
m_decimators_12.decimate4_cen(it, buf, len);
break;
case 3:
m_decimators_12.decimate8_cen(it, buf, len);
break;
case 4:
m_decimators_12.decimate16_cen(it, buf, len);
break;
case 5:
m_decimators_12.decimate32_cen(it, buf, len);
break;
case 6:
m_decimators_12.decimate64_cen(it, buf, len);
break;
default:
break;
}
}
}
}
2018-01-13 22:43:24 -05:00
void convert_16(SampleVector::iterator* it, const qint16* buf, qint32 len)
2018-01-13 20:25:24 -05:00
{
if (m_log2Decim == 0) {
m_decimators_16.decimate1(it, buf, len);
} else {
if (m_fcPos == 0) { // Infradyne
switch (m_log2Decim) {
case 1:
m_decimators_16.decimate2_inf(it, buf, len);
break;
case 2:
m_decimators_16.decimate4_inf(it, buf, len);
break;
case 3:
m_decimators_16.decimate8_inf(it, buf, len);
break;
case 4:
m_decimators_16.decimate16_inf(it, buf, len);
break;
case 5:
m_decimators_16.decimate32_inf(it, buf, len);
break;
case 6:
m_decimators_16.decimate64_inf(it, buf, len);
break;
default:
break;
}
} else if (m_fcPos == 1) {// Supradyne
switch (m_log2Decim) {
case 1:
m_decimators_16.decimate2_sup(it, buf, len);
break;
case 2:
m_decimators_16.decimate4_sup(it, buf, len);
break;
case 3:
m_decimators_16.decimate8_sup(it, buf, len);
break;
case 4:
m_decimators_16.decimate16_sup(it, buf, len);
break;
case 5:
m_decimators_16.decimate32_sup(it, buf, len);
break;
case 6:
m_decimators_16.decimate64_sup(it, buf, len);
break;
default:
break;
}
} else { // Centered
switch (m_log2Decim) {
case 1:
m_decimators_16.decimate2_cen(it, buf, len);
break;
case 2:
m_decimators_16.decimate4_cen(it, buf, len);
break;
case 3:
m_decimators_16.decimate8_cen(it, buf, len);
break;
case 4:
m_decimators_16.decimate16_cen(it, buf, len);
break;
case 5:
m_decimators_16.decimate32_cen(it, buf, len);
break;
case 6:
m_decimators_16.decimate64_cen(it, buf, len);
break;
default:
break;
}
}
}
}
private slots:
void tick();
2018-09-06 08:29:14 -04:00
void handleInputMessages();
2018-01-13 20:25:24 -05:00
};
#endif // _TESTSOURCE_TESTSOURCEWORKER_H_