22 #include <QMutexLocker> 24 #include <QNetworkReply> 49 m_deviceAPI(deviceAPI),
51 m_XTRXOutputThread(0),
56 m_deviceAPI->setNbSinkStreams(1);
57 m_networkManager =
new QNetworkAccessManager();
58 connect(m_networkManager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(networkManagerFinished(QNetworkReply*)));
85 qDebug(
"XTRXOutput::openDevice: look in Tx buddies");
90 if (deviceXTRXShared == 0)
92 qCritical(
"XTRXOutput::openDevice: the sink buddy shared pointer is null");
100 qCritical(
"XTRXOutput::openDevice: cannot get device pointer from Tx buddy");
109 qDebug(
"XTRXOutput::openDevice: look in Rx buddies");
114 if (deviceXTRXShared == 0)
116 qCritical(
"XTRXOutput::openDevice: the source buddy shared pointer is null");
124 qCritical(
"XTRXOutput::openDevice: cannot get device pointer from Rx buddy");
133 qDebug(
"XTRXOutput::openDevice: open device here");
141 qCritical(
"XTRXOutput::openDevice: cannot open BladeRF2 device");
192 std::vector<DeviceAPI*>::const_iterator it = sinkBuddies.begin();
194 for (; it != sinkBuddies.end(); ++it)
200 xtrxOutputThread = buddySink->
getThread();
202 if (xtrxOutputThread) {
208 return xtrxOutputThread;
219 std::vector<DeviceAPI*>::const_iterator it = sinkBuddies.begin();
221 for (; it != sinkBuddies.end(); ++it)
261 qDebug(
"XTRXOutput::start: no device object");
267 bool needsStart =
false;
269 if (xtrxOutputThread)
271 qDebug(
"XTRXOutput::start: thread is already allocated");
273 unsigned int nbOriginalChannels = xtrxOutputThread->
getNbChannels();
277 if (nbOriginalChannels != 0)
279 qDebug(
"XTRXOutput::start: expand channels. Re-allocate thread and take ownership");
282 unsigned int *log2Interps =
new unsigned int[2];
284 for (
int i = 0;
i < 2;
i++)
291 delete xtrxOutputThread;
296 for (
int i = 0;
i < 2;
i++)
304 std::vector<DeviceAPI*>::const_iterator it = sinkBuddies.begin();
306 for (; it != sinkBuddies.end(); ++it)
314 delete[] log2Interps;
320 qDebug(
"XTRXOutput::start: keep buddy thread");
325 qDebug(
"XTRXOutput::start: allocate thread and take ownership");
339 qDebug(
"XTRXOutput::start: (re)start thread");
343 qDebug(
"XTRXOutput::start: started");
365 int requestedChannel = removedChannel ^ 1;
368 if (xtrxOutputThread == 0) {
374 if (nbOriginalChannels == 1)
376 qDebug(
"XTRXOutput::stop: SO mode. Just stop and delete the thread");
378 delete xtrxOutputThread;
384 std::vector<DeviceAPI*>::const_iterator it = sinkBuddies.begin();
386 for (; it != sinkBuddies.end(); ++it)
392 else if (nbOriginalChannels == 2)
394 qDebug(
"XTRXOutput::stop: MO mode. Reduce by deleting and re-creating the thread");
396 delete xtrxOutputThread;
406 std::vector<DeviceAPI*>::const_iterator it = sinkBuddies.begin();
408 for (; it != sinkBuddies.end(); ++it)
424 std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
426 qDebug(
"XTRXOutput::suspendRxThread (%lu)", sourceBuddies.size());
428 for (; itSource != sourceBuddies.end(); ++itSource)
447 std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
449 qDebug(
"XTRXOutput::resumeRxThread (%lu)", sourceBuddies.size());
451 for (; itSource != sourceBuddies.end(); ++itSource)
512 return devSampleRate;
523 return log2HardInterp;
565 qDebug(
"XTRXOutput::getLORange: min: %f max: %f step: %f",
574 qDebug(
"XTRXOutput::getSRRange: min: %f max: %f step: %f",
583 qDebug(
"XTRXOutput::getLPRange: min: %f max: %f step: %f",
592 qDebug() <<
"XTRXOutput::handleMessage: MsgConfigureXTRX";
596 qDebug(
"XTRXOutput::handleMessage config error");
616 qDebug() <<
"XTRXOutput::handleMessage: MsgReportBuddyChange:" 684 double board_temp = 0.0;
685 bool gps_locked =
false;
688 qDebug(
"XTRXOutput::handleMessage: MsgGetDeviceInfo: cannot get board temperature");
692 qDebug(
"XTRXOutput::handleMessage: MsgGetDeviceInfo: cannot get GPS lock status");
706 std::vector<DeviceAPI*>::const_iterator itSink = sinkBuddies.begin();
708 for (; itSink != sinkBuddies.end(); ++itSink)
710 if ((*itSink)->getSamplingDeviceGUIMessageQueue())
713 (*itSink)->getSamplingDeviceGUIMessageQueue()->push(report);
719 std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
721 for (; itSource != sourceBuddies.end(); ++itSource)
723 if ((*itSource)->getSamplingDeviceGUIMessageQueue())
726 (*itSource)->getSamplingDeviceGUIMessageQueue()->push(report);
735 qDebug() <<
"XTRXOutput::handleMessage: MsgStartStop: " << (cmd.
getStartStop() ?
"start" :
"stop");
761 QList<QString> reverseAPIKeys;
763 bool forwardChangeOwnDSP =
false;
764 bool forwardChangeTxDSP =
false;
765 bool forwardChangeAllDSP =
false;
766 bool forwardClockSource =
false;
767 bool txThreadWasRunning =
false;
768 bool doLPCalibration =
false;
769 bool doChangeSampleRate =
false;
770 bool doChangeFreq =
false;
785 <<
" force: " << force;
789 reverseAPIKeys.append(
"pwrmode");
798 qCritical(
"XTRXOutput::applySettings: could not set power mode %d", settings.
m_pwrmode);
804 reverseAPIKeys.append(
"extClock");
807 reverseAPIKeys.append(
"extClockFreq");
817 (settings.
m_extClock) ? XTRX_CLKSRC_EXT : XTRX_CLKSRC_INT);
819 forwardClockSource =
true;
820 doChangeSampleRate =
true;
822 qDebug(
"XTRXOutput::applySettings: clock set to %s (Ext: %d Hz)",
823 settings.
m_extClock ?
"external" :
"internal",
830 reverseAPIKeys.append(
"devSampleRate");
833 reverseAPIKeys.append(
"log2HardInterp");
839 forwardChangeAllDSP =
true;
842 doChangeSampleRate =
true;
848 reverseAPIKeys.append(
"gain");
857 qDebug(
"XTRXOutput::applySettings: xtrx_set_gain(PAD) failed");
859 qDebug() <<
"XTRXOutput::applySettings: Gain (PAD) set to " << settings.
m_gain;
866 reverseAPIKeys.append(
"lpfBW");
869 doLPCalibration =
true;
874 if ((
m_settings.m_lpfFIRBW != settings.m_lpfFIRBW) ||
875 (
m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) || force)
877 if (
m_deviceShared.m_deviceParams->getDevice() != 0 && m_channelAcquired)
882 settings.m_lpfFIREnable,
883 settings.m_lpfFIRBW) < 0)
885 qCritical(
"XTRXOutput::applySettings: could %s and set LPF FIR to %f Hz",
886 settings.m_lpfFIREnable ?
"enable" :
"disable",
887 settings.m_lpfFIRBW);
892 qDebug(
"XTRXOutput::applySettings: %sd and set LPF FIR to %f Hz",
893 settings.m_lpfFIREnable ?
"enable" :
"disable",
894 settings.m_lpfFIRBW);
902 reverseAPIKeys.append(
"log2SoftInterp");
903 forwardChangeOwnDSP =
true;
905 if (outputThread != 0)
908 qDebug() <<
"XTRXOutput::applySettings: set soft interpolation to " << (1<<settings.
m_log2SoftInterp);
914 reverseAPIKeys.append(
"antennaPath");
919 qCritical(
"XTRXOutput::applySettings: could not set antenna path to %d", (
int) settings.
m_antennaPath);
921 qDebug(
"XTRXOutput::applySettings: set antenna path to %d", (
int) settings.
m_antennaPath);
928 reverseAPIKeys.append(
"centerFrequency");
933 reverseAPIKeys.append(
"ncoFrequency");
936 reverseAPIKeys.append(
"ncoEnable");
942 forceNCOFrequency =
true;
956 if (doChangeSampleRate)
963 txThreadWasRunning =
true;
974 qCritical(
"XTRXOutput::applySettings: could not set sample rate to %f with oversampling of %d",
981 forceNCOFrequency =
true;
982 forwardChangeAllDSP =
true;
984 qDebug(
"XTRXOutput::applySettings: sample rate set to %f with oversampling of %d",
991 if (txThreadWasRunning) {
1002 qCritical(
"XTRXOutput::applySettings: could not set LPF to %f Hz",
m_settings.
m_lpfBW);
1010 forwardChangeTxDSP =
true;
1018 qCritical(
"XTRXOutput::applySettings: could not set frequency to %lu", settings.
m_centerFrequency);
1021 qDebug(
"XTRXOutput::applySettings: frequency set to %lu", settings.
m_centerFrequency);
1026 if (forceNCOFrequency)
1036 qCritical(
"XTRXOutput::applySettings: could not %s and set NCO to %d Hz",
1042 forwardChangeOwnDSP =
true;
1043 qDebug(
"XTRXOutput::applySettings: %sd and set NCO to %d Hz",
1052 if (forwardChangeAllDSP)
1054 qDebug(
"XTRXOutput::applySettings: forward change to all buddies");
1070 std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
1072 for (; itSource != sourceBuddies.end(); ++itSource)
1076 (*itSource)->getSamplingDeviceInputMessageQueue()->push(report);
1081 std::vector<DeviceAPI*>::const_iterator itSink = sinkBuddies.begin();
1083 for (; itSink != sinkBuddies.end(); ++itSink)
1087 (*itSink)->getSamplingDeviceInputMessageQueue()->push(report);
1090 else if (forwardChangeTxDSP)
1092 qDebug(
"XTRXOutput::applySettings: forward change to Tx buddies");
1108 std::vector<DeviceAPI*>::const_iterator itSink = sinkBuddies.begin();
1110 for (; itSink != sinkBuddies.end(); ++itSink)
1114 (*itSink)->getSamplingDeviceInputMessageQueue()->push(report);
1117 else if (forwardChangeOwnDSP)
1119 qDebug(
"XTRXOutput::applySettings: forward change to self only");
1133 if (forwardClockSource)
1137 std::vector<DeviceAPI*>::const_iterator itSource = sourceBuddies.begin();
1139 for (; itSource != sourceBuddies.end(); ++itSource)
1143 (*itSource)->getSamplingDeviceInputMessageQueue()->push(report);
1148 std::vector<DeviceAPI*>::const_iterator itSink = sinkBuddies.begin();
1150 for (; itSink != sinkBuddies.end(); ++itSink)
1154 (*itSink)->getSamplingDeviceInputMessageQueue()->push(report);
1158 qDebug() <<
"XTRXOutput::applySettings:" 1160 <<
" sample rate with soft interpolation: " <<
getSampleRate() <<
"S/s" 1161 <<
" forceNCOFrequency: " << forceNCOFrequency
1162 <<
" doLPCalibration: " << doLPCalibration
1163 <<
" doChangeFreq: " << doChangeFreq
1164 <<
" doChangeSampleRate: " << doChangeSampleRate;
1171 QString& errorMessage)
1173 (void) errorMessage;
1182 const QStringList& deviceSettingsKeys,
1184 QString& errorMessage)
1186 (void) errorMessage;
1189 if (deviceSettingsKeys.contains(
"centerFrequency")) {
1192 if (deviceSettingsKeys.contains(
"devSampleRate")) {
1195 if (deviceSettingsKeys.contains(
"log2HardInterp")) {
1198 if (deviceSettingsKeys.contains(
"log2SoftInterp")) {
1201 if (deviceSettingsKeys.contains(
"lpfBW")) {
1204 if (deviceSettingsKeys.contains(
"gain")) {
1207 if (deviceSettingsKeys.contains(
"ncoEnable")) {
1210 if (deviceSettingsKeys.contains(
"ncoFrequency")) {
1213 if (deviceSettingsKeys.contains(
"antennaPath")) {
1216 if (deviceSettingsKeys.contains(
"extClock")) {
1219 if (deviceSettingsKeys.contains(
"extClockFreq")) {
1222 if (deviceSettingsKeys.contains(
"pwrmode")) {
1225 if (deviceSettingsKeys.contains(
"useReverseAPI")) {
1228 if (deviceSettingsKeys.contains(
"reverseAPIAddress")) {
1231 if (deviceSettingsKeys.contains(
"reverseAPIPort")) {
1234 if (deviceSettingsKeys.contains(
"reverseAPIDeviceIndex")) {
1279 QString& errorMessage)
1281 (void) errorMessage;
1290 QString& errorMessage)
1292 (void) errorMessage;
1300 QString& errorMessage)
1302 (void) errorMessage;
1319 bool success =
false;
1321 bool gpsStatus =
false;
1328 XTRX_TX, XTRX_CH_AB, XTRX_PERF_LLFIFO, &fifolevel);
1329 success = (ret >= 0);
1352 if (deviceSettingsKeys.contains(
"centerFrequency") || force) {
1355 if (deviceSettingsKeys.contains(
"devSampleRate") || force) {
1358 if (deviceSettingsKeys.contains(
"log2HardInterp") || force) {
1361 if (deviceSettingsKeys.contains(
"log2SoftInterp") || force) {
1364 if (deviceSettingsKeys.contains(
"ncoEnable") || force) {
1367 if (deviceSettingsKeys.contains(
"ncoFrequency") || force) {
1370 if (deviceSettingsKeys.contains(
"lpfBW") || force) {
1373 if (deviceSettingsKeys.contains(
"antennaPath") || force) {
1376 if (deviceSettingsKeys.contains(
"gain") || force) {
1379 if (deviceSettingsKeys.contains(
"extClock") || force) {
1382 if (deviceSettingsKeys.contains(
"extClockFreq") || force) {
1385 if (deviceSettingsKeys.contains(
"pwrmode") || force) {
1389 QString deviceSettingsURL = QString(
"http://%1:%2/sdrangel/deviceset/%3/device/settings")
1394 m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader,
"application/json");
1396 QBuffer *buffer=
new QBuffer();
1397 buffer->open((QBuffer::ReadWrite));
1398 buffer->write(swgDeviceSettings->
asJson().toUtf8());
1404 delete swgDeviceSettings;
1414 QString deviceSettingsURL = QString(
"http://%1:%2/sdrangel/deviceset/%3/device/run")
1419 m_networkRequest.setHeader(QNetworkRequest::ContentTypeHeader,
"application/json");
1421 QBuffer *buffer=
new QBuffer();
1422 buffer->open((QBuffer::ReadWrite));
1423 buffer->write(swgDeviceSettings->
asJson().toUtf8());
1432 delete swgDeviceSettings;
1437 QNetworkReply::NetworkError replyError = reply->error();
1441 qWarning() <<
"XTRXOutput::networkManagerFinished:" 1442 <<
" error(" << (int) replyError
1443 <<
"): " << replyError
1444 <<
": " << reply->errorString();
1448 QString answer = reply->readAll();
1450 qDebug(
"XTRXOutput::networkManagerFinished: reply:\n%s", answer.toStdString().c_str());
virtual QByteArray serialize() const
bool startDeviceEngine()
Start the device engine corresponding to the stream type.
qint32 getReverseApiPort()
double getClockGen() const
virtual bool isRunning()=0
uint32_t getLog2HardInterp() const
uint64_t getCenterFrequency() const
void webapiReverseSendSettings(QList< QString > &deviceSettingsKeys, const XTRXOutputSettings &settings, bool force)
qint32 getReverseApiDeviceIndex()
void push(Message *message, bool emitSignal=true)
Push message onto queue.
void stopDeviceEngine()
Stop the device engine corresponding to the stream type.
virtual bool deserialize(const QByteArray &data)
void setExtClockFreq(qint32 ext_clock_freq)
virtual int getSampleRate() const
Sample rate exposed by the sink.
void getLPRange(float &minF, float &maxF, float &stepF) const
void setUseReverseApi(qint32 use_reverse_api)
unsigned int getLog2Interpolation(unsigned int channel) const
void setFifoSize(qint32 fifo_size)
const std::vector< DeviceAPI * > & getSinkBuddies() const
static MsgReportClockSourceChange * create(bool extClock, uint32_t m_extClockFreq)
qint32 getLog2HardInterp()
virtual QString asJson() override
bool m_extClock
True if external clock source.
virtual int webapiRun(bool run, SWGSDRangel::SWGDeviceState &response, QString &errorMessage)
MessageQueue * getDeviceEngineInputMessageQueue()
Device engine message queue.
uint32_t m_log2SoftInterp
void setThread(XTRXOutputThread *thread)
uint32_t getExtClockFeq() const
uint32_t m_gain
Optimally distributed gain (dB)
double getClockGen() const
void setGain(qint32 gain)
int getDevSampleRate() const
int m_ncoFrequency
Actual NCO frequency (the resulting frequency with mixing is displayed)
double getActualOutputRate() const
virtual quint64 getCenterFrequency() const
Center frequency exposed by the sink.
uint32_t getDeviceItemIndex() const
uint32_t getDevSampleRate() const
xtrx_antenna_t m_antennaPath
void setReverseApiPort(qint32 reverse_api_port)
bool initDeviceEngine()
Init the device engine corresponding to the stream type.
double set_samplerate(double rate, double master, bool output)
XTRXOutputThread * getThread()
static MsgReportClockGenChange * create()
std::size_t getChannelIndex()
qint32 getUseReverseApi()
virtual int webapiSettingsGet(SWGSDRangel::SWGDeviceSettings &response, QString &errorMessage)
void setSuccess(qint32 success)
bool m_ncoEnable
Enable TSP NCO and mixing.
void setOriginatorIndex(qint32 originator_index)
DeviceXTRXShared m_deviceShared
uint32_t m_log2HardInterp
struct xtrx_dev * getDevice()
virtual void init()
initializations to be done when all collaborating objects are created and possibly connected ...
XTRXOutputThread * m_XTRXOutputThread
uint16_t m_reverseAPIPort
MessageQueue m_inputMessageQueue
Input queue to the sink.
qint64 getCenterFrequency()
SWGXtrxOutputReport * getXtrxOutputReport()
QByteArray serialize() const
QNetworkAccessManager * m_networkManager
int getDeviceSetIndex() const
bool m_threadWasRunning
flag to know if thread needs to be resumed after suspend
uint16_t m_reverseAPIDeviceIndex
void * getBuddySharedPtr() const
void setNcoFrequency(qint32 nco_frequency)
uint32_t m_extClockFreq
Frequency (Hz) of external clock source.
QString m_deviceDescription
#define MESSAGE_CLASS_DEFINITION(Name, BaseClass)
virtual int webapiReportGet(SWGSDRangel::SWGDeviceReport &response, QString &errorMessage)
SWGXtrxOutputSettings * getXtrxOutputSettings()
void setAntennaPath(qint32 antenna_path)
virtual bool handleMessage(const Message &message)
void setLog2SoftInterp(qint32 log2_soft_interp)
void setNcoEnable(qint32 nco_enable)
void setBuddySharedPtr(void *ptr)
void setLpfBw(qint32 lpf_bw)
void setGpsLock(qint32 gps_lock)
static MsgReportStreamInfo * create(bool success, bool active, uint32_t fifoFilledCount, uint32_t fifoSize)
XTRXOutputThread * findThread()
virtual int webapiSettingsPutPatch(bool force, const QStringList &deviceSettingsKeys, SWGSDRangel::SWGDeviceSettings &response, QString &errorMessage)
double get_board_temperature()
static bool match(const Message *message)
SampleSourceFifo * getFifo(unsigned int channel)
XTRXOutputSettings m_settings
void setFifo(unsigned int channel, SampleSourceFifo *sampleFifo)
QString * getReverseApiAddress()
void webapiReverseSendStartStop(bool start)
void setPwrmode(qint32 pwrmode)
virtual int webapiRunGet(SWGSDRangel::SWGDeviceState &response, QString &errorMessage)
qint32 getDevSampleRate()
virtual void startWork()=0
void setLog2HardInterp(qint32 log2_hard_interp)
int m_channel
allocated channel (-1 if none)
void setTemperature(float temperature)
unsigned getLog2HardDecimInterp() const
QString m_reverseAPIAddress
unsigned int getNbChannels() const
bool deserialize(const QByteArray &data)
void getDeviceEngineStateStr(QString &state)
void resize(uint32_t size)
void setXtrxOutputReport(SWGXtrxOutputReport *xtrx_output_report)
const QString & getSamplingDeviceSerial() const
void setFifoFill(qint32 fifo_fill)
bool getStartStop() const
void networkManagerFinished(QNetworkReply *reply)
static MsgReportBuddyChange * create(int devSampleRate, unsigned log2HardDecimInterp, uint64_t centerFrequency, bool rxElseTx)
void setDevSampleRate(qint32 dev_sample_rate)
void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings &response, const XTRXOutputSettings &settings)
bool applySettings(const XTRXOutputSettings &settings, bool force=false, bool forceNCOFrequency=false)
virtual void setCenterFrequency(qint64 centerFrequency)
void setExtClock(qint32 ext_clock)
void webapiFormatDeviceReport(SWGSDRangel::SWGDeviceReport &response)
SampleSourceFifo m_sampleSourceFifo
const std::vector< DeviceAPI * > & getSourceBuddies() const
qint32 getLog2SoftInterp()
static MsgStartStop * create(bool startStop)
ThreadInterface * m_thread
holds the thread address if started else 0
void getLORange(float &minF, float &maxF, float &stepF) const
void setReverseApiAddress(QString *reverse_api_address)
float m_lpfBW
LMS analog lowpass filter bandwidth (Hz)
void setCenterFrequency(qint64 center_frequency)
QNetworkRequest m_networkRequest
void getSRRange(float &minF, float &maxF, float &stepF) const
MessageQueue * getMessageQueueToGUI()
virtual void stopWork()=0
bool open(const char *deviceStr)
void setLog2Interpolation(unsigned int channel, unsigned int log2_interp)
void setDirection(qint32 direction)
MessageQueue * m_guiMessageQueue
Input message queue to the GUI.
uint64_t m_centerFrequency
virtual const QString & getDeviceDescription() const
static MsgReportDeviceInfo * create(float temperature, bool gpsLocked)
void setXtrxOutputSettings(SWGXtrxOutputSettings *xtrx_output_settings)
void setDeviceHwType(QString *device_hw_type)
void setReverseApiDeviceIndex(qint32 reverse_api_device_index)
MessageQueue * getSamplingDeviceGUIMessageQueue()
Sampling device (ex: single Tx) GUI input message queue.
unsigned __int64 uint64_t