mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-26 02:20:26 -04:00 
			
		
		
		
	Add basic support for KiwiSDR receivers
This commit is contained in:
		
							parent
							
								
									ef32417245
								
							
						
					
					
						commit
						779f3fdb16
					
				| @ -291,6 +291,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON) | ||||
| set(_required_qt_version "5.6.0") | ||||
| find_package(Qt5 COMPONENTS Core REQUIRED) | ||||
| find_package(Qt5 COMPONENTS Widgets REQUIRED) | ||||
| find_package(Qt5 COMPONENTS WebSockets REQUIRED) | ||||
| find_package(Qt5 COMPONENTS Multimedia REQUIRED) | ||||
| find_package(Qt5 COMPONENTS MultimediaWidgets REQUIRED) | ||||
| 
 | ||||
|  | ||||
| @ -58,3 +58,4 @@ if(ENABLE_SOAPYSDR AND SOAPYSDR_FOUND) | ||||
|     add_subdirectory(soapysdrinput) | ||||
| endif() | ||||
| 
 | ||||
| add_subdirectory(kiwisdr) | ||||
							
								
								
									
										56
									
								
								plugins/samplesource/kiwisdr/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								plugins/samplesource/kiwisdr/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,56 @@ | ||||
| project(kiwisdr) | ||||
| 
 | ||||
| set(kiwisdr_SOURCES | ||||
| 	kiwisdrinput.cpp | ||||
| 	kiwisdrplugin.cpp | ||||
| 	kiwisdrworker.cpp | ||||
| 	kiwisdrsettings.cpp | ||||
| ) | ||||
| 
 | ||||
| set(kiwisdr_HEADERS | ||||
| 	kiwisdrinput.h | ||||
| 	kiwisdrplugin.h | ||||
| 	kiwisdrworker.h | ||||
| 	kiwisdrsettings.h | ||||
| ) | ||||
| 
 | ||||
| include_directories( | ||||
| 	${Boost_INCLUDE_DIRS} | ||||
| ) | ||||
| 
 | ||||
| if(NOT SERVER_MODE) | ||||
|     set(kiwisdr_SOURCES | ||||
|         ${kiwisdr_SOURCES} | ||||
|         kiwisdrgui.cpp | ||||
| 
 | ||||
|         kiwisdrgui.ui | ||||
|     ) | ||||
|     set(kiwisdr_HEADERS | ||||
|         ${kiwisdr_HEADERS} | ||||
|         kiwisdrgui.h | ||||
|     ) | ||||
| 
 | ||||
| 	set(TARGET_NAME inputkiwisdr) | ||||
| 	set(TARGET_LIB "Qt5::Widgets") | ||||
| 	set(TARGET_LIB_GUI "sdrgui") | ||||
| 	set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR}) | ||||
| else() | ||||
|     set(TARGET_NAME inputkiwisdrsrv) | ||||
|     set(TARGET_LIB "") | ||||
|     set(TARGET_LIB_GUI "") | ||||
|     set(INSTALL_FOLDER ${INSTALL_PLUGINSSRV_DIR}) | ||||
| endif() | ||||
| 
 | ||||
| add_library(${TARGET_NAME} SHARED | ||||
| 	${kiwisdr_SOURCES} | ||||
| ) | ||||
| 
 | ||||
| target_link_libraries(${TARGET_NAME} | ||||
| 	Qt5::Core | ||||
| 	Qt5::WebSockets | ||||
| 	${TARGET_LIB} | ||||
| 	sdrbase | ||||
| 	${TARGET_LIB_GUI} | ||||
| ) | ||||
| 
 | ||||
| install(TARGETS ${TARGET_NAME} DESTINATION ${INSTALL_FOLDER}) | ||||
							
								
								
									
										339
									
								
								plugins/samplesource/kiwisdr/kiwisdrgui.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										339
									
								
								plugins/samplesource/kiwisdr/kiwisdrgui.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,339 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2019 Vort                                                       //
 | ||||
| // Copyright (C) 2018 Edouard Griffiths, F4EXB                                   //
 | ||||
| //                                                                               //
 | ||||
| // 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.                                           //
 | ||||
| //                                                                               //
 | ||||
| // 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/>.          //
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #include <QDebug> | ||||
| 
 | ||||
| #include <QTime> | ||||
| #include <QDateTime> | ||||
| #include <QString> | ||||
| #include <QMessageBox> | ||||
| 
 | ||||
| #include "ui_kiwisdrgui.h" | ||||
| #include "plugin/pluginapi.h" | ||||
| #include "gui/colormapper.h" | ||||
| #include "gui/glspectrum.h" | ||||
| #include "gui/crightclickenabler.h" | ||||
| #include "gui/basicdevicesettingsdialog.h" | ||||
| #include "dsp/dspengine.h" | ||||
| #include "dsp/dspcommands.h" | ||||
| #include "util/db.h" | ||||
| 
 | ||||
| #include "mainwindow.h" | ||||
| 
 | ||||
| #include "kiwisdrgui.h" | ||||
| #include "device/deviceapi.h" | ||||
| #include "device/deviceuiset.h" | ||||
| 
 | ||||
| KiwiSDRGui::KiwiSDRGui(DeviceUISet *deviceUISet, QWidget* parent) : | ||||
|     QWidget(parent), | ||||
|     ui(new Ui::KiwiSDRGui), | ||||
|     m_deviceUISet(deviceUISet), | ||||
|     m_settings(), | ||||
|     m_doApplySettings(true), | ||||
|     m_forceSettings(true), | ||||
|     m_sampleSource(0), | ||||
|     m_tickCount(0), | ||||
|     m_lastEngineState(DeviceAPI::StNotStarted) | ||||
| { | ||||
|     qDebug("KiwiSDRGui::KiwiSDRGui"); | ||||
|     m_sampleSource = m_deviceUISet->m_deviceAPI->getSampleSource(); | ||||
| 
 | ||||
| 	m_statusTooltips.push_back("Idle"); | ||||
| 	m_statusTooltips.push_back("Connecting..."); | ||||
| 	m_statusTooltips.push_back("Connected"); | ||||
| 	m_statusTooltips.push_back("Error"); | ||||
| 
 | ||||
| 	m_statusColors.push_back("gray"); | ||||
| 	m_statusColors.push_back("rgb(232, 212, 35)"); | ||||
| 	m_statusColors.push_back("rgb(35, 138, 35)"); | ||||
| 	m_statusColors.push_back("rgb(232, 85, 85)"); | ||||
| 
 | ||||
|     ui->setupUi(this); | ||||
|     ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); | ||||
|     ui->centerFrequency->setValueRange(7, 0, 9999999); | ||||
| 
 | ||||
|     displaySettings(); | ||||
| 
 | ||||
|     connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); | ||||
|     connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); | ||||
|     m_statusTimer.start(500); | ||||
| 
 | ||||
|     connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection); | ||||
|     m_sampleSource->setMessageQueueToGUI(&m_inputMessageQueue); | ||||
| 
 | ||||
|     CRightClickEnabler *startStopRightClickEnabler = new CRightClickEnabler(ui->startStop); | ||||
|     connect(startStopRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(openDeviceSettingsDialog(const QPoint &))); | ||||
| } | ||||
| 
 | ||||
| KiwiSDRGui::~KiwiSDRGui() | ||||
| { | ||||
|     delete ui; | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::destroy() | ||||
| { | ||||
|     delete this; | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::setName(const QString& name) | ||||
| { | ||||
|     setObjectName(name); | ||||
| } | ||||
| 
 | ||||
| QString KiwiSDRGui::getName() const | ||||
| { | ||||
|     return objectName(); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::resetToDefaults() | ||||
| { | ||||
|     m_settings.resetToDefaults(); | ||||
|     displaySettings(); | ||||
|     sendSettings(); | ||||
| } | ||||
| 
 | ||||
| qint64 KiwiSDRGui::getCenterFrequency() const | ||||
| { | ||||
|     return m_settings.m_centerFrequency; | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::setCenterFrequency(qint64 centerFrequency) | ||||
| { | ||||
|     m_settings.m_centerFrequency = centerFrequency; | ||||
|     displaySettings(); | ||||
|     sendSettings(); | ||||
| } | ||||
| 
 | ||||
| QByteArray KiwiSDRGui::serialize() const | ||||
| { | ||||
|     return m_settings.serialize(); | ||||
| } | ||||
| 
 | ||||
| bool KiwiSDRGui::deserialize(const QByteArray& data) | ||||
| { | ||||
|     if(m_settings.deserialize(data)) { | ||||
|         displaySettings(); | ||||
|         m_forceSettings = true; | ||||
|         sendSettings(); | ||||
|         return true; | ||||
|     } else { | ||||
|         resetToDefaults(); | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::on_startStop_toggled(bool checked) | ||||
| { | ||||
|     if (m_doApplySettings) | ||||
|     { | ||||
| 		KiwiSDRInput::MsgStartStop *message = KiwiSDRInput::MsgStartStop::create(checked); | ||||
|         m_sampleSource->getInputMessageQueue()->push(message); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::on_centerFrequency_changed(quint64 value) | ||||
| { | ||||
|     m_settings.m_centerFrequency = value * 1000; | ||||
|     sendSettings(); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::on_serverAddress_returnPressed() | ||||
| { | ||||
| 	on_serverAddressApplyButton_clicked(); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::on_serverAddressApplyButton_clicked() | ||||
| { | ||||
| 	m_settings.m_serverAddress = ui->serverAddress->text(); | ||||
| 	sendSettings(); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::on_record_toggled(bool checked) | ||||
| { | ||||
|     if (checked) { | ||||
|         ui->record->setStyleSheet("QToolButton { background-color : red; }"); | ||||
|     } else { | ||||
|         ui->record->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); | ||||
|     } | ||||
| 
 | ||||
| 	KiwiSDRInput::MsgFileRecord* message = KiwiSDRInput::MsgFileRecord::create(checked); | ||||
|     m_sampleSource->getInputMessageQueue()->push(message); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::on_agc_toggled(bool checked) | ||||
| { | ||||
| 	m_settings.m_useAGC = checked; | ||||
| 	sendSettings(); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::on_gain_valueChanged(int value) | ||||
| { | ||||
| 	m_settings.m_gain = value; | ||||
| 	ui->gainText->setText(QString::number(m_settings.m_gain) + " dB"); | ||||
| 	sendSettings(); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::displaySettings() | ||||
| { | ||||
|     blockApplySettings(true); | ||||
| 
 | ||||
|     ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); | ||||
| 	ui->serverAddress->setText(m_settings.m_serverAddress); | ||||
| 	ui->gain->setValue(m_settings.m_gain); | ||||
| 	ui->gainText->setText(QString::number(m_settings.m_gain) + " dB"); | ||||
| 	ui->agc->setChecked(m_settings.m_useAGC); | ||||
| 
 | ||||
|     blockApplySettings(false); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::sendSettings() | ||||
| { | ||||
|     if (!m_updateTimer.isActive()) { | ||||
|         m_updateTimer.start(100); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::updateHardware() | ||||
| { | ||||
|     if (m_doApplySettings) | ||||
|     { | ||||
| 		KiwiSDRInput::MsgConfigureKiwiSDR* message = KiwiSDRInput::MsgConfigureKiwiSDR::create(m_settings, m_forceSettings); | ||||
|         m_sampleSource->getInputMessageQueue()->push(message); | ||||
|         m_forceSettings = false; | ||||
|         m_updateTimer.stop(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::updateStatus() | ||||
| { | ||||
|     int state = m_deviceUISet->m_deviceAPI->state(); | ||||
| 
 | ||||
|     if (m_lastEngineState != state) | ||||
|     { | ||||
|         switch (state) | ||||
|         { | ||||
|             case DeviceAPI::StNotStarted: | ||||
|                 ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); | ||||
|                 break; | ||||
|             case DeviceAPI::StIdle: | ||||
|                 ui->startStop->setStyleSheet("QToolButton { background-color : blue; }"); | ||||
|                 break; | ||||
|             case DeviceAPI::StRunning: | ||||
|                 ui->startStop->setStyleSheet("QToolButton { background-color : green; }"); | ||||
|                 break; | ||||
|             case DeviceAPI::StError: | ||||
|                 ui->startStop->setStyleSheet("QToolButton { background-color : red; }"); | ||||
|                 QMessageBox::information(this, tr("Message"), m_deviceUISet->m_deviceAPI->errorMessage()); | ||||
|                 break; | ||||
|             default: | ||||
|                 break; | ||||
|         } | ||||
| 
 | ||||
|         m_lastEngineState = state; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool KiwiSDRGui::handleMessage(const Message& message) | ||||
| { | ||||
|     if (KiwiSDRInput::MsgConfigureKiwiSDR::match(message)) | ||||
|     { | ||||
|         qDebug("KiwiSDRGui::handleMessage: MsgConfigureKiwiSDR"); | ||||
|         const KiwiSDRInput::MsgConfigureKiwiSDR& cfg = (KiwiSDRInput::MsgConfigureKiwiSDR&) message; | ||||
|         m_settings = cfg.getSettings(); | ||||
|         displaySettings(); | ||||
|         return true; | ||||
|     } | ||||
|     else if (KiwiSDRInput::MsgStartStop::match(message)) | ||||
|     { | ||||
|         qDebug("KiwiSDRGui::handleMessage: MsgStartStop"); | ||||
| 		KiwiSDRInput::MsgStartStop& notif = (KiwiSDRInput::MsgStartStop&) message; | ||||
|         blockApplySettings(true); | ||||
|         ui->startStop->setChecked(notif.getStartStop()); | ||||
|         blockApplySettings(false); | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
| 	else if (KiwiSDRInput::MsgSetStatus::match(message)) | ||||
| 	{ | ||||
| 		qDebug("KiwiSDRGui::handleMessage: MsgSetStatus"); | ||||
| 		KiwiSDRInput::MsgSetStatus& notif = (KiwiSDRInput::MsgSetStatus&) message; | ||||
| 		int status = notif.getStatus(); | ||||
| 		ui->statusIndicator->setToolTip(m_statusTooltips[status]); | ||||
| 		ui->statusIndicator->setStyleSheet("QLabel { background-color: " + | ||||
| 			m_statusColors[status] + "; border-radius: 7px; }"); | ||||
| 		return true; | ||||
| 	} | ||||
|     else | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::handleInputMessages() | ||||
| { | ||||
|     Message* message; | ||||
| 
 | ||||
|     while ((message = m_inputMessageQueue.pop()) != 0) | ||||
|     { | ||||
|         if (DSPSignalNotification::match(*message)) | ||||
|         { | ||||
|             DSPSignalNotification* notif = (DSPSignalNotification*) message; | ||||
|             m_deviceSampleRate = notif->getSampleRate(); | ||||
|             m_deviceCenterFrequency = notif->getCenterFrequency(); | ||||
|             qDebug("KiwiSDRGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", | ||||
|                     notif->getSampleRate(), | ||||
|                     notif->getCenterFrequency()); | ||||
|             updateSampleRateAndFrequency(); | ||||
| 
 | ||||
|             delete message; | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             if (handleMessage(*message)) | ||||
|             { | ||||
|                 delete message; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::updateSampleRateAndFrequency() | ||||
| { | ||||
|     m_deviceUISet->getSpectrum()->setSampleRate(m_deviceSampleRate); | ||||
|     m_deviceUISet->getSpectrum()->setCenterFrequency(m_deviceCenterFrequency); | ||||
|     ui->deviceRateText->setText(tr("%1k").arg((float)m_deviceSampleRate / 1000)); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRGui::openDeviceSettingsDialog(const QPoint& p) | ||||
| { | ||||
|     BasicDeviceSettingsDialog dialog(this); | ||||
|     dialog.setUseReverseAPI(m_settings.m_useReverseAPI); | ||||
|     dialog.setReverseAPIAddress(m_settings.m_reverseAPIAddress); | ||||
|     dialog.setReverseAPIPort(m_settings.m_reverseAPIPort); | ||||
|     dialog.setReverseAPIDeviceIndex(m_settings.m_reverseAPIDeviceIndex); | ||||
| 
 | ||||
|     dialog.move(p); | ||||
|     dialog.exec(); | ||||
| 
 | ||||
|     m_settings.m_useReverseAPI = dialog.useReverseAPI(); | ||||
|     m_settings.m_reverseAPIAddress = dialog.getReverseAPIAddress(); | ||||
|     m_settings.m_reverseAPIPort = dialog.getReverseAPIPort(); | ||||
|     m_settings.m_reverseAPIDeviceIndex = dialog.getReverseAPIDeviceIndex(); | ||||
| 
 | ||||
|     sendSettings(); | ||||
| } | ||||
							
								
								
									
										93
									
								
								plugins/samplesource/kiwisdr/kiwisdrgui.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								plugins/samplesource/kiwisdr/kiwisdrgui.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,93 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2019 Vort                                                       //
 | ||||
| // Copyright (C) 2018 Edouard Griffiths, F4EXB                                   //
 | ||||
| //                                                                               //
 | ||||
| // 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.                                           //
 | ||||
| //                                                                               //
 | ||||
| // 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 _KIWISDR_KIWISDRGUI_H_ | ||||
| #define _KIWISDR_KIWISDRGUI_H_ | ||||
| 
 | ||||
| #include <plugin/plugininstancegui.h> | ||||
| #include <QTimer> | ||||
| #include <QWidget> | ||||
| 
 | ||||
| #include "util/messagequeue.h" | ||||
| 
 | ||||
| #include "kiwisdrsettings.h" | ||||
| #include "kiwisdrinput.h" | ||||
| 
 | ||||
| class DeviceUISet; | ||||
| 
 | ||||
| namespace Ui { | ||||
| 	class KiwiSDRGui; | ||||
| } | ||||
| 
 | ||||
| class KiwiSDRGui : public QWidget, public PluginInstanceGUI { | ||||
| 	Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
| 	explicit KiwiSDRGui(DeviceUISet *deviceUISet, QWidget* parent = 0); | ||||
| 	virtual ~KiwiSDRGui(); | ||||
| 	virtual void destroy(); | ||||
| 
 | ||||
| 	void setName(const QString& name); | ||||
| 	QString getName() const; | ||||
| 
 | ||||
| 	void resetToDefaults(); | ||||
| 	virtual qint64 getCenterFrequency() const; | ||||
| 	virtual void setCenterFrequency(qint64 centerFrequency); | ||||
| 	QByteArray serialize() const; | ||||
| 	bool deserialize(const QByteArray& data); | ||||
| 	virtual MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } | ||||
| 	virtual bool handleMessage(const Message& message); | ||||
| 
 | ||||
| private: | ||||
| 	Ui::KiwiSDRGui* ui; | ||||
| 
 | ||||
| 	DeviceUISet* m_deviceUISet; | ||||
| 	KiwiSDRSettings m_settings; | ||||
|     QTimer m_updateTimer; | ||||
|     QTimer m_statusTimer; | ||||
| 	bool m_doApplySettings; | ||||
|     bool m_forceSettings; | ||||
| 	DeviceSampleSource* m_sampleSource; | ||||
| 	std::size_t m_tickCount; | ||||
|     int m_deviceSampleRate; | ||||
|     quint64 m_deviceCenterFrequency; //!< Center frequency in device
 | ||||
| 	int m_lastEngineState; | ||||
| 	MessageQueue m_inputMessageQueue; | ||||
| 	std::vector<QString> m_statusColors; | ||||
| 	std::vector<QString> m_statusTooltips; | ||||
| 
 | ||||
| 	void blockApplySettings(bool block) { m_doApplySettings = !block; } | ||||
| 	void displaySettings(); | ||||
| 	void sendSettings(); | ||||
|     void updateSampleRateAndFrequency(); | ||||
| 
 | ||||
| private slots: | ||||
|     void handleInputMessages(); | ||||
| 	void on_startStop_toggled(bool checked); | ||||
|     void on_centerFrequency_changed(quint64 value); | ||||
| 	void on_record_toggled(bool checked); | ||||
| 	void on_gain_valueChanged(int value); | ||||
| 	void on_agc_toggled(bool checked); | ||||
| 	void on_serverAddress_returnPressed(); | ||||
| 	void on_serverAddressApplyButton_clicked(); | ||||
| 	void openDeviceSettingsDialog(const QPoint& p); | ||||
|     void updateStatus(); | ||||
|     void updateHardware(); | ||||
| }; | ||||
| 
 | ||||
| #endif // _KIWISDR_KIWISDRGUI_H_
 | ||||
							
								
								
									
										347
									
								
								plugins/samplesource/kiwisdr/kiwisdrgui.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										347
									
								
								plugins/samplesource/kiwisdr/kiwisdrgui.ui
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,347 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <ui version="4.0"> | ||||
|  <class>KiwiSDRGui</class> | ||||
|  <widget class="QWidget" name="KiwiSDRGui"> | ||||
|   <property name="geometry"> | ||||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>360</width> | ||||
|     <height>120</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="sizePolicy"> | ||||
|    <sizepolicy hsizetype="Minimum" vsizetype="Minimum"> | ||||
|     <horstretch>0</horstretch> | ||||
|     <verstretch>0</verstretch> | ||||
|    </sizepolicy> | ||||
|   </property> | ||||
|   <property name="minimumSize"> | ||||
|    <size> | ||||
|     <width>360</width> | ||||
|     <height>120</height> | ||||
|    </size> | ||||
|   </property> | ||||
|   <property name="font"> | ||||
|    <font> | ||||
|     <family>Liberation Sans</family> | ||||
|     <pointsize>9</pointsize> | ||||
|     <weight>50</weight> | ||||
|     <italic>false</italic> | ||||
|     <bold>false</bold> | ||||
|    </font> | ||||
|   </property> | ||||
|   <property name="windowTitle"> | ||||
|    <string>Test source</string> | ||||
|   </property> | ||||
|   <layout class="QVBoxLayout" name="verticalLayout"> | ||||
|    <property name="spacing"> | ||||
|     <number>3</number> | ||||
|    </property> | ||||
|    <property name="leftMargin"> | ||||
|     <number>2</number> | ||||
|    </property> | ||||
|    <property name="topMargin"> | ||||
|     <number>2</number> | ||||
|    </property> | ||||
|    <property name="rightMargin"> | ||||
|     <number>2</number> | ||||
|    </property> | ||||
|    <property name="bottomMargin"> | ||||
|     <number>2</number> | ||||
|    </property> | ||||
|    <item> | ||||
|     <layout class="QHBoxLayout" name="horizontalLayout_freq"> | ||||
|      <property name="topMargin"> | ||||
|       <number>4</number> | ||||
|      </property> | ||||
|      <item> | ||||
|       <layout class="QVBoxLayout" name="deviceUILayout"> | ||||
|        <item> | ||||
|         <layout class="QHBoxLayout" name="deviceButtonsLayout"> | ||||
|          <item> | ||||
|           <widget class="ButtonSwitch" name="startStop"> | ||||
|            <property name="toolTip"> | ||||
|             <string>start/stop acquisition</string> | ||||
|            </property> | ||||
|            <property name="text"> | ||||
|             <string/> | ||||
|            </property> | ||||
|            <property name="icon"> | ||||
|             <iconset resource="../../../sdrgui/resources/res.qrc"> | ||||
|              <normaloff>:/play.png</normaloff> | ||||
|              <normalon>:/stop.png</normalon>:/play.png</iconset> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|          <item> | ||||
|           <widget class="ButtonSwitch" name="record"> | ||||
|            <property name="toolTip"> | ||||
|             <string>Toggle record I/Q samples from device</string> | ||||
|            </property> | ||||
|            <property name="text"> | ||||
|             <string/> | ||||
|            </property> | ||||
|            <property name="icon"> | ||||
|             <iconset resource="../../../sdrgui/resources/res.qrc"> | ||||
|              <normaloff>:/record_off.png</normaloff>:/record_off.png</iconset> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|         </layout> | ||||
|        </item> | ||||
|        <item> | ||||
|         <layout class="QHBoxLayout" name="deviceRateLayout"> | ||||
|          <item> | ||||
|           <widget class="QLabel" name="deviceRateText"> | ||||
|            <property name="minimumSize"> | ||||
|             <size> | ||||
|              <width>58</width> | ||||
|              <height>0</height> | ||||
|             </size> | ||||
|            </property> | ||||
|            <property name="toolTip"> | ||||
|             <string>I/Q sample rate kS/s</string> | ||||
|            </property> | ||||
|            <property name="text"> | ||||
|             <string>0000.00k</string> | ||||
|            </property> | ||||
|            <property name="alignment"> | ||||
|             <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | ||||
|            </property> | ||||
|           </widget> | ||||
|          </item> | ||||
|         </layout> | ||||
|        </item> | ||||
|       </layout> | ||||
|      </item> | ||||
|      <item> | ||||
|       <spacer name="horizontalSpacer"> | ||||
|        <property name="orientation"> | ||||
|         <enum>Qt::Horizontal</enum> | ||||
|        </property> | ||||
|        <property name="sizeHint" stdset="0"> | ||||
|         <size> | ||||
|          <width>0</width> | ||||
|          <height>0</height> | ||||
|         </size> | ||||
|        </property> | ||||
|       </spacer> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="ValueDial" name="centerFrequency" native="true"> | ||||
|        <property name="sizePolicy"> | ||||
|         <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> | ||||
|          <horstretch>0</horstretch> | ||||
|          <verstretch>0</verstretch> | ||||
|         </sizepolicy> | ||||
|        </property> | ||||
|        <property name="minimumSize"> | ||||
|         <size> | ||||
|          <width>32</width> | ||||
|          <height>16</height> | ||||
|         </size> | ||||
|        </property> | ||||
|        <property name="font"> | ||||
|         <font> | ||||
|          <family>Liberation Mono</family> | ||||
|          <pointsize>20</pointsize> | ||||
|         </font> | ||||
|        </property> | ||||
|        <property name="cursor"> | ||||
|         <cursorShape>PointingHandCursor</cursorShape> | ||||
|        </property> | ||||
|        <property name="focusPolicy"> | ||||
|         <enum>Qt::StrongFocus</enum> | ||||
|        </property> | ||||
|        <property name="toolTip"> | ||||
|         <string>Tuner center frequency in kHz</string> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QLabel" name="freqUnits"> | ||||
|        <property name="text"> | ||||
|         <string> kHz</string> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <spacer name="horizontalSpacer_2"> | ||||
|        <property name="orientation"> | ||||
|         <enum>Qt::Horizontal</enum> | ||||
|        </property> | ||||
|        <property name="sizeHint" stdset="0"> | ||||
|         <size> | ||||
|          <width>0</width> | ||||
|          <height>0</height> | ||||
|         </size> | ||||
|        </property> | ||||
|       </spacer> | ||||
|      </item> | ||||
|     </layout> | ||||
|    </item> | ||||
|    <item> | ||||
|     <widget class="Line" name="line_2"> | ||||
|      <property name="orientation"> | ||||
|       <enum>Qt::Horizontal</enum> | ||||
|      </property> | ||||
|     </widget> | ||||
|    </item> | ||||
|    <item> | ||||
|     <layout class="QHBoxLayout" name="serverAddressLayout"> | ||||
|      <item> | ||||
|       <widget class="QLabel" name="serverAddressLabel"> | ||||
|        <property name="text"> | ||||
|         <string>Addr</string> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QLineEdit" name="serverAddress"> | ||||
|        <property name="toolTip"> | ||||
|         <string>Server address</string> | ||||
|        </property> | ||||
|        <property name="text"> | ||||
|         <string>127.0.0.1:8073</string> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QLabel" name="statusIndicator"> | ||||
|        <property name="sizePolicy"> | ||||
|         <sizepolicy hsizetype="Maximum" vsizetype="Maximum"> | ||||
|          <horstretch>0</horstretch> | ||||
|          <verstretch>0</verstretch> | ||||
|         </sizepolicy> | ||||
|        </property> | ||||
|        <property name="minimumSize"> | ||||
|         <size> | ||||
|          <width>14</width> | ||||
|          <height>14</height> | ||||
|         </size> | ||||
|        </property> | ||||
|        <property name="toolTip"> | ||||
|         <string>Idle</string> | ||||
|        </property> | ||||
|        <property name="styleSheet"> | ||||
|         <string notr="true">QLabel { background-color: gray; border-radius: 7px; }</string> | ||||
|        </property> | ||||
|        <property name="text"> | ||||
|         <string/> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QPushButton" name="serverAddressApplyButton"> | ||||
|        <property name="maximumSize"> | ||||
|         <size> | ||||
|          <width>30</width> | ||||
|          <height>16777215</height> | ||||
|         </size> | ||||
|        </property> | ||||
|        <property name="text"> | ||||
|         <string>Set</string> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|     </layout> | ||||
|    </item> | ||||
|    <item> | ||||
|     <layout class="QHBoxLayout" name="gainLayout"> | ||||
|      <item> | ||||
|       <widget class="QLabel" name="gainLabel"> | ||||
|        <property name="text"> | ||||
|         <string>Gain</string> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QSlider" name="gain"> | ||||
|        <property name="toolTip"> | ||||
|         <string>Manual gain</string> | ||||
|        </property> | ||||
|        <property name="maximum"> | ||||
|         <number>120</number> | ||||
|        </property> | ||||
|        <property name="pageStep"> | ||||
|         <number>1</number> | ||||
|        </property> | ||||
|        <property name="value"> | ||||
|         <number>20</number> | ||||
|        </property> | ||||
|        <property name="orientation"> | ||||
|         <enum>Qt::Horizontal</enum> | ||||
|        </property> | ||||
|        <property name="tickPosition"> | ||||
|         <enum>QSlider::NoTicks</enum> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QLabel" name="gainText"> | ||||
|        <property name="minimumSize"> | ||||
|         <size> | ||||
|          <width>40</width> | ||||
|          <height>0</height> | ||||
|         </size> | ||||
|        </property> | ||||
|        <property name="text"> | ||||
|         <string>20 dB</string> | ||||
|        </property> | ||||
|        <property name="alignment"> | ||||
|         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|      <item> | ||||
|       <widget class="QToolButton" name="agc"> | ||||
|        <property name="toolTip"> | ||||
|         <string>Automatic gain control</string> | ||||
|        </property> | ||||
|        <property name="text"> | ||||
|         <string>AGC</string> | ||||
|        </property> | ||||
|        <property name="checkable"> | ||||
|         <bool>true</bool> | ||||
|        </property> | ||||
|        <property name="checked"> | ||||
|         <bool>true</bool> | ||||
|        </property> | ||||
|       </widget> | ||||
|      </item> | ||||
|     </layout> | ||||
|    </item> | ||||
|    <item> | ||||
|     <spacer name="verticalSpacer"> | ||||
|      <property name="orientation"> | ||||
|       <enum>Qt::Vertical</enum> | ||||
|      </property> | ||||
|      <property name="sizeHint" stdset="0"> | ||||
|       <size> | ||||
|        <width>20</width> | ||||
|        <height>40</height> | ||||
|       </size> | ||||
|      </property> | ||||
|     </spacer> | ||||
|    </item> | ||||
|   </layout> | ||||
|  </widget> | ||||
|  <customwidgets> | ||||
|   <customwidget> | ||||
|    <class>ValueDial</class> | ||||
|    <extends>QWidget</extends> | ||||
|    <header>gui/valuedial.h</header> | ||||
|    <container>1</container> | ||||
|   </customwidget> | ||||
|   <customwidget> | ||||
|    <class>ButtonSwitch</class> | ||||
|    <extends>QToolButton</extends> | ||||
|    <header>gui/buttonswitch.h</header> | ||||
|   </customwidget> | ||||
|  </customwidgets> | ||||
|  <resources> | ||||
|   <include location="../../../sdrgui/resources/res.qrc"/> | ||||
|  </resources> | ||||
|  <connections/> | ||||
| </ui> | ||||
							
								
								
									
										348
									
								
								plugins/samplesource/kiwisdr/kiwisdrinput.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										348
									
								
								plugins/samplesource/kiwisdr/kiwisdrinput.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,348 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2019 Vort                                                       //
 | ||||
| // Copyright (C) 2018 Edouard Griffiths, F4EXB                                   //
 | ||||
| //                                                                               //
 | ||||
| // 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.                                           //
 | ||||
| //                                                                               //
 | ||||
| // 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/>.          //
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #include <string.h> | ||||
| #include <errno.h> | ||||
| 
 | ||||
| #include <QDebug> | ||||
| #include <QNetworkReply> | ||||
| #include <QNetworkAccessManager> | ||||
| #include <QBuffer> | ||||
| 
 | ||||
| #include "kiwisdrinput.h" | ||||
| #include "device/deviceapi.h" | ||||
| #include "kiwisdrworker.h" | ||||
| #include "dsp/dspcommands.h" | ||||
| #include "dsp/dspengine.h" | ||||
| #include "dsp/filerecord.h" | ||||
| 
 | ||||
| MESSAGE_CLASS_DEFINITION(KiwiSDRInput::MsgConfigureKiwiSDR, Message) | ||||
| MESSAGE_CLASS_DEFINITION(KiwiSDRInput::MsgFileRecord, Message) | ||||
| MESSAGE_CLASS_DEFINITION(KiwiSDRInput::MsgStartStop, Message) | ||||
| MESSAGE_CLASS_DEFINITION(KiwiSDRInput::MsgSetStatus, Message) | ||||
| 
 | ||||
| 
 | ||||
| KiwiSDRInput::KiwiSDRInput(DeviceAPI *deviceAPI) : | ||||
|     m_deviceAPI(deviceAPI), | ||||
| 	m_settings(), | ||||
| 	m_kiwiSDRWorker(nullptr), | ||||
| 	m_deviceDescription(), | ||||
| 	m_running(false), | ||||
| 	m_masterTimer(deviceAPI->getMasterTimer()) | ||||
| { | ||||
| 	m_kiwiSDRWorkerThread.start(); | ||||
| 
 | ||||
|     m_fileSink = new FileRecord(); | ||||
|     m_deviceAPI->setNbSourceStreams(1); | ||||
|     m_deviceAPI->addAncillarySink(m_fileSink); | ||||
| 
 | ||||
|     if (!m_sampleFifo.setSize(getSampleRate() * 2)) { | ||||
|         qCritical("KiwiSDRInput::KiwiSDRInput: Could not allocate SampleFifo"); | ||||
|     } | ||||
| 
 | ||||
|     m_networkManager = new QNetworkAccessManager(); | ||||
|     connect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); | ||||
| } | ||||
| 
 | ||||
| KiwiSDRInput::~KiwiSDRInput() | ||||
| { | ||||
|     disconnect(m_networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(networkManagerFinished(QNetworkReply*))); | ||||
|     delete m_networkManager; | ||||
| 
 | ||||
|     if (m_running) { | ||||
|         stop(); | ||||
|     } | ||||
| 
 | ||||
| 	m_kiwiSDRWorkerThread.quit(); | ||||
| 	m_kiwiSDRWorkerThread.wait(); | ||||
| 
 | ||||
|     m_deviceAPI->removeAncillarySink(m_fileSink); | ||||
|     delete m_fileSink; | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRInput::destroy() | ||||
| { | ||||
|     delete this; | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRInput::init() | ||||
| { | ||||
|     applySettings(m_settings, true); | ||||
| } | ||||
| 
 | ||||
| bool KiwiSDRInput::start() | ||||
| { | ||||
| 	QMutexLocker mutexLocker(&m_mutex); | ||||
| 
 | ||||
|     if (m_running) stop(); | ||||
| 
 | ||||
| 	m_kiwiSDRWorker = new KiwiSDRWorker(&m_sampleFifo); | ||||
| 	m_kiwiSDRWorker->moveToThread(&m_kiwiSDRWorkerThread); | ||||
| 
 | ||||
| 	connect(this, &KiwiSDRInput::setWorkerCenterFrequency, m_kiwiSDRWorker, &KiwiSDRWorker::onCenterFrequencyChanged); | ||||
| 	connect(this, &KiwiSDRInput::setWorkerServerAddress, m_kiwiSDRWorker, &KiwiSDRWorker::onServerAddressChanged); | ||||
| 	connect(this, &KiwiSDRInput::setWorkerGain, m_kiwiSDRWorker, &KiwiSDRWorker::onGainChanged); | ||||
| 	connect(m_kiwiSDRWorker, &KiwiSDRWorker::updateStatus, this, &KiwiSDRInput::setWorkerStatus); | ||||
| 
 | ||||
| 	mutexLocker.unlock(); | ||||
| 
 | ||||
| 	applySettings(m_settings, true); | ||||
| 	m_running = true; | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRInput::stop() | ||||
| { | ||||
| 	QMutexLocker mutexLocker(&m_mutex); | ||||
| 
 | ||||
| 	setWorkerStatus(0); | ||||
| 
 | ||||
| 	if (m_kiwiSDRWorker != 0) | ||||
| 	{ | ||||
| 		m_kiwiSDRWorker->deleteLater(); | ||||
| 		m_kiwiSDRWorker = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	m_running = false; | ||||
| } | ||||
| 
 | ||||
| QByteArray KiwiSDRInput::serialize() const | ||||
| { | ||||
|     return m_settings.serialize(); | ||||
| } | ||||
| 
 | ||||
| bool KiwiSDRInput::deserialize(const QByteArray& data) | ||||
| { | ||||
|     bool success = true; | ||||
| 
 | ||||
|     if (!m_settings.deserialize(data)) | ||||
|     { | ||||
|         m_settings.resetToDefaults(); | ||||
|         success = false; | ||||
|     } | ||||
| 
 | ||||
|     MsgConfigureKiwiSDR* message = MsgConfigureKiwiSDR::create(m_settings, true); | ||||
|     m_inputMessageQueue.push(message); | ||||
| 
 | ||||
|     if (m_guiMessageQueue) | ||||
|     { | ||||
|         MsgConfigureKiwiSDR* messageToGUI = MsgConfigureKiwiSDR::create(m_settings, true); | ||||
|         m_guiMessageQueue->push(messageToGUI); | ||||
|     } | ||||
| 
 | ||||
|     return success; | ||||
| } | ||||
| 
 | ||||
| const QString& KiwiSDRInput::getDeviceDescription() const | ||||
| { | ||||
| 	return m_deviceDescription; | ||||
| } | ||||
| 
 | ||||
| int KiwiSDRInput::getSampleRate() const | ||||
| { | ||||
| 	return 12000; | ||||
| } | ||||
| 
 | ||||
| quint64 KiwiSDRInput::getCenterFrequency() const | ||||
| { | ||||
| 	return m_settings.m_centerFrequency; | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRInput::setCenterFrequency(qint64 centerFrequency) | ||||
| { | ||||
| 	KiwiSDRSettings settings = m_settings; | ||||
|     settings.m_centerFrequency = centerFrequency; | ||||
| 
 | ||||
|     MsgConfigureKiwiSDR* message = MsgConfigureKiwiSDR::create(settings, false); | ||||
|     m_inputMessageQueue.push(message); | ||||
| 
 | ||||
|     if (m_guiMessageQueue) | ||||
|     { | ||||
|         MsgConfigureKiwiSDR* messageToGUI = MsgConfigureKiwiSDR::create(settings, false); | ||||
|         m_guiMessageQueue->push(messageToGUI); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRInput::setWorkerStatus(int status) | ||||
| { | ||||
| 	if (m_guiMessageQueue) | ||||
| 		m_guiMessageQueue->push(MsgSetStatus::create(status)); | ||||
| } | ||||
| 
 | ||||
| bool KiwiSDRInput::handleMessage(const Message& message) | ||||
| { | ||||
|     if (MsgConfigureKiwiSDR::match(message)) | ||||
|     { | ||||
|         MsgConfigureKiwiSDR& conf = (MsgConfigureKiwiSDR&) message; | ||||
|         qDebug() << "KiwiSDRInput::handleMessage: MsgConfigureKiwiSDR"; | ||||
| 
 | ||||
|         bool success = applySettings(conf.getSettings(), conf.getForce()); | ||||
| 
 | ||||
|         if (!success) | ||||
|         { | ||||
|             qDebug("KiwiSDRInput::handleMessage: config error"); | ||||
|         } | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
|     else if (MsgFileRecord::match(message)) | ||||
|     { | ||||
|         MsgFileRecord& conf = (MsgFileRecord&) message; | ||||
|         qDebug() << "KiwiSDRInput::handleMessage: MsgFileRecord: " << conf.getStartStop(); | ||||
| 
 | ||||
|         if (conf.getStartStop()) | ||||
|         { | ||||
|             m_fileSink->genUniqueFileName(m_deviceAPI->getDeviceUID()); | ||||
|             m_fileSink->startRecording(); | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             m_fileSink->stopRecording(); | ||||
|         } | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
|     else if (MsgStartStop::match(message)) | ||||
|     { | ||||
|         MsgStartStop& cmd = (MsgStartStop&) message; | ||||
|         qDebug() << "KiwiSDRInput::handleMessage: MsgStartStop: " << (cmd.getStartStop() ? "start" : "stop"); | ||||
| 
 | ||||
|         if (cmd.getStartStop()) | ||||
|         { | ||||
|             if (m_deviceAPI->initDeviceEngine()) | ||||
|             { | ||||
|                 m_deviceAPI->startDeviceEngine(); | ||||
|             } | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             m_deviceAPI->stopDeviceEngine(); | ||||
|         } | ||||
| 
 | ||||
|         if (m_settings.m_useReverseAPI) { | ||||
|             webapiReverseSendStartStop(cmd.getStartStop()); | ||||
|         } | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool KiwiSDRInput::applySettings(const KiwiSDRSettings& settings, bool force) | ||||
| { | ||||
|     QList<QString> reverseAPIKeys; | ||||
| 
 | ||||
| 	if (m_settings.m_serverAddress != settings.m_serverAddress || force) | ||||
| 		emit setWorkerServerAddress(settings.m_serverAddress); | ||||
| 
 | ||||
| 	if (m_settings.m_gain != settings.m_gain || | ||||
| 		m_settings.m_useAGC != settings.m_useAGC || force) | ||||
| 	{ | ||||
| 		emit setWorkerGain(settings.m_gain, settings.m_useAGC); | ||||
| 	} | ||||
| 
 | ||||
|     if (m_settings.m_centerFrequency != settings.m_centerFrequency || force) | ||||
|     { | ||||
|         reverseAPIKeys.append("centerFrequency"); | ||||
| 
 | ||||
|         emit setWorkerCenterFrequency(settings.m_centerFrequency); | ||||
| 
 | ||||
| 		DSPSignalNotification *notif = new DSPSignalNotification( | ||||
| 			getSampleRate(), settings.m_centerFrequency); | ||||
| 		m_fileSink->handleMessage(*notif); // forward to file sink
 | ||||
| 		m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif); | ||||
| 	} | ||||
| 
 | ||||
|     if (settings.m_useReverseAPI) | ||||
|     { | ||||
|         qDebug("KiwiSDRInput::applySettings: call webapiReverseSendSettings"); | ||||
|         bool fullUpdate = ((m_settings.m_useReverseAPI != settings.m_useReverseAPI) && settings.m_useReverseAPI) || | ||||
|                 (m_settings.m_reverseAPIAddress != settings.m_reverseAPIAddress) || | ||||
|                 (m_settings.m_reverseAPIPort != settings.m_reverseAPIPort) || | ||||
|                 (m_settings.m_reverseAPIDeviceIndex != settings.m_reverseAPIDeviceIndex); | ||||
|         webapiReverseSendSettings(reverseAPIKeys, settings, fullUpdate || force); | ||||
|     } | ||||
| 
 | ||||
|     m_settings = settings; | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| int KiwiSDRInput::webapiRunGet( | ||||
|         SWGSDRangel::SWGDeviceState& response, | ||||
|         QString& errorMessage) | ||||
| { | ||||
|     return 404; | ||||
| } | ||||
| 
 | ||||
| int KiwiSDRInput::webapiRun( | ||||
|         bool run, | ||||
|         SWGSDRangel::SWGDeviceState& response, | ||||
|         QString& errorMessage) | ||||
| { | ||||
| 	return 404; | ||||
| } | ||||
| 
 | ||||
| int KiwiSDRInput::webapiSettingsGet( | ||||
|                 SWGSDRangel::SWGDeviceSettings& response, | ||||
|                 QString& errorMessage) | ||||
| { | ||||
|     return 404; | ||||
| } | ||||
| 
 | ||||
| int KiwiSDRInput::webapiSettingsPutPatch( | ||||
|                 bool force, | ||||
|                 const QStringList& deviceSettingsKeys, | ||||
|                 SWGSDRangel::SWGDeviceSettings& response, // query + response
 | ||||
|                 QString& errorMessage) | ||||
| { | ||||
|     return 404; | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRInput::webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const KiwiSDRSettings& settings) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRInput::webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const KiwiSDRSettings& settings, bool force) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRInput::webapiReverseSendStartStop(bool start) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRInput::networkManagerFinished(QNetworkReply *reply) | ||||
| { | ||||
|     QNetworkReply::NetworkError replyError = reply->error(); | ||||
| 
 | ||||
|     if (replyError) | ||||
|     { | ||||
|         qWarning() << "KiwiSDRInput::networkManagerFinished:" | ||||
|                 << " error(" << (int) replyError | ||||
|                 << "): " << replyError | ||||
|                 << ": " << reply->errorString(); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     QString answer = reply->readAll(); | ||||
|     answer.chop(1); // remove last \n
 | ||||
|     qDebug("KiwiSDRInput::networkManagerFinished: reply:\n%s", answer.toStdString().c_str()); | ||||
| } | ||||
							
								
								
									
										189
									
								
								plugins/samplesource/kiwisdr/kiwisdrinput.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										189
									
								
								plugins/samplesource/kiwisdr/kiwisdrinput.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,189 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2019 Vort                                                       //
 | ||||
| // Copyright (C) 2018 Edouard Griffiths, F4EXB                                   //
 | ||||
| //                                                                               //
 | ||||
| // 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.                                           //
 | ||||
| //                                                                               //
 | ||||
| // 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 _KIWISDR_KIWISDRINPUT_H_ | ||||
| #define _KIWISDR_KIWISDRINPUT_H_ | ||||
| 
 | ||||
| #include <QString> | ||||
| #include <QByteArray> | ||||
| #include <QTimer> | ||||
| #include <QThread> | ||||
| #include <QNetworkRequest> | ||||
| 
 | ||||
| #include <dsp/devicesamplesource.h> | ||||
| #include "kiwisdrsettings.h" | ||||
| 
 | ||||
| class DeviceAPI; | ||||
| class KiwiSDRWorker; | ||||
| class FileRecord; | ||||
| class QNetworkAccessManager; | ||||
| class QNetworkReply; | ||||
| 
 | ||||
| class KiwiSDRInput : public DeviceSampleSource { | ||||
|     Q_OBJECT | ||||
| public: | ||||
| 	class MsgConfigureKiwiSDR : public Message { | ||||
| 		MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
| 	public: | ||||
| 		const KiwiSDRSettings& getSettings() const { return m_settings; } | ||||
| 		bool getForce() const { return m_force; } | ||||
| 
 | ||||
| 		static MsgConfigureKiwiSDR* create(const KiwiSDRSettings& settings, bool force) | ||||
| 		{ | ||||
| 			return new MsgConfigureKiwiSDR(settings, force); | ||||
| 		} | ||||
| 
 | ||||
| 	private: | ||||
| 		KiwiSDRSettings m_settings; | ||||
| 		bool m_force; | ||||
| 
 | ||||
| 		MsgConfigureKiwiSDR(const KiwiSDRSettings& settings, bool force) : | ||||
| 			Message(), | ||||
| 			m_settings(settings), | ||||
| 			m_force(force) | ||||
| 		{ } | ||||
| 	}; | ||||
| 
 | ||||
|     class MsgFileRecord : public Message { | ||||
|         MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
|     public: | ||||
|         bool getStartStop() const { return m_startStop; } | ||||
| 
 | ||||
|         static MsgFileRecord* create(bool startStop) { | ||||
|             return new MsgFileRecord(startStop); | ||||
|         } | ||||
| 
 | ||||
|     protected: | ||||
|         bool m_startStop; | ||||
| 
 | ||||
|         MsgFileRecord(bool startStop) : | ||||
|             Message(), | ||||
|             m_startStop(startStop) | ||||
|         { } | ||||
|     }; | ||||
| 
 | ||||
|     class MsgStartStop : public Message { | ||||
|         MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
|     public: | ||||
|         bool getStartStop() const { return m_startStop; } | ||||
| 
 | ||||
|         static MsgStartStop* create(bool startStop) { | ||||
|             return new MsgStartStop(startStop); | ||||
|         } | ||||
| 
 | ||||
|     protected: | ||||
|         bool m_startStop; | ||||
| 
 | ||||
|         MsgStartStop(bool startStop) : | ||||
|             Message(), | ||||
|             m_startStop(startStop) | ||||
|         { } | ||||
|     }; | ||||
| 
 | ||||
| 	class MsgSetStatus : public Message { | ||||
| 		MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
| 	public: | ||||
| 		int getStatus() const { return m_status; } | ||||
| 
 | ||||
| 		static MsgSetStatus* create(int status) { | ||||
| 			return new MsgSetStatus(status); | ||||
| 		} | ||||
| 
 | ||||
| 	protected: | ||||
| 		int m_status; | ||||
| 
 | ||||
| 		MsgSetStatus(int status) : | ||||
| 			Message(), | ||||
| 			m_status(status) | ||||
| 		{ } | ||||
| 	}; | ||||
| 
 | ||||
| 	KiwiSDRInput(DeviceAPI *deviceAPI); | ||||
| 	virtual ~KiwiSDRInput(); | ||||
| 	virtual void destroy(); | ||||
| 
 | ||||
| 	virtual void init(); | ||||
| 	virtual bool start(); | ||||
| 	virtual void stop(); | ||||
| 
 | ||||
|     virtual QByteArray serialize() const; | ||||
|     virtual bool deserialize(const QByteArray& data); | ||||
| 
 | ||||
|     virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; } | ||||
| 	virtual const QString& getDeviceDescription() const; | ||||
| 	virtual int getSampleRate() const; | ||||
|     virtual void setSampleRate(int sampleRate) { (void) sampleRate; } | ||||
| 	virtual quint64 getCenterFrequency() const; | ||||
|     virtual void setCenterFrequency(qint64 centerFrequency); | ||||
| 
 | ||||
| 	virtual bool handleMessage(const Message& message); | ||||
| 
 | ||||
|     virtual int webapiSettingsGet( | ||||
|                 SWGSDRangel::SWGDeviceSettings& response, | ||||
|                 QString& errorMessage); | ||||
| 
 | ||||
|     virtual int webapiSettingsPutPatch( | ||||
|                 bool force, | ||||
|                 const QStringList& deviceSettingsKeys, | ||||
|                 SWGSDRangel::SWGDeviceSettings& response, // query + response
 | ||||
|                 QString& errorMessage); | ||||
| 
 | ||||
|     virtual int webapiRunGet( | ||||
|             SWGSDRangel::SWGDeviceState& response, | ||||
|             QString& errorMessage); | ||||
| 
 | ||||
|     virtual int webapiRun( | ||||
|             bool run, | ||||
|             SWGSDRangel::SWGDeviceState& response, | ||||
|             QString& errorMessage); | ||||
| 
 | ||||
| private: | ||||
| 	DeviceAPI *m_deviceAPI; | ||||
|     FileRecord *m_fileSink; //!< File sink to record device I/Q output
 | ||||
| 	QMutex m_mutex; | ||||
| 	KiwiSDRSettings m_settings; | ||||
| 	KiwiSDRWorker* m_kiwiSDRWorker; | ||||
| 	QThread m_kiwiSDRWorkerThread; | ||||
| 	QString m_deviceDescription; | ||||
| 	bool m_running; | ||||
|     const QTimer& m_masterTimer; | ||||
|     QNetworkAccessManager *m_networkManager; | ||||
|     QNetworkRequest m_networkRequest; | ||||
| 
 | ||||
| 	bool applySettings(const KiwiSDRSettings& settings, bool force); | ||||
|     void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const KiwiSDRSettings& settings); | ||||
|     void webapiReverseSendSettings(QList<QString>& deviceSettingsKeys, const KiwiSDRSettings& settings, bool force); | ||||
|     void webapiReverseSendStartStop(bool start); | ||||
| 
 | ||||
| signals: | ||||
| 	void startWorker(); | ||||
| 	void stopWorker(); | ||||
| 	void setWorkerCenterFrequency(quint64 centerFrequency); | ||||
| 	void setWorkerServerAddress(QString serverAddress); | ||||
| 	void setWorkerGain(quint32 gain, bool useAGC); | ||||
| 
 | ||||
| private slots: | ||||
| 	void setWorkerStatus(int status); | ||||
|     void networkManagerFinished(QNetworkReply *reply); | ||||
| }; | ||||
| 
 | ||||
| #endif // _KIWISDR_KIWISDRINPUT_H_
 | ||||
							
								
								
									
										111
									
								
								plugins/samplesource/kiwisdr/kiwisdrplugin.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								plugins/samplesource/kiwisdr/kiwisdrplugin.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,111 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2018 Edouard Griffiths, F4EXB                                   //
 | ||||
| //                                                                               //
 | ||||
| // 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.                                           //
 | ||||
| //                                                                               //
 | ||||
| // 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/>.          //
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #include <QtPlugin> | ||||
| 
 | ||||
| #include "plugin/pluginapi.h" | ||||
| #include "util/simpleserializer.h" | ||||
| 
 | ||||
| #ifdef SERVER_MODE | ||||
| #include "kiwisdrinput.h" | ||||
| #else | ||||
| #include "kiwisdrgui.h" | ||||
| #endif | ||||
| #include "kiwisdrplugin.h" | ||||
| 
 | ||||
| const PluginDescriptor KiwiSDRPlugin::m_pluginDescriptor = { | ||||
| 	QString("KiwiSDR input"), | ||||
| 	QString("0.0.1"), | ||||
| 	QString("(c) Vort (c) Edouard Griffiths, F4EXB"), | ||||
| 	QString("https://github.com/f4exb/sdrangel"), | ||||
| 	true, | ||||
| 	QString("https://github.com/f4exb/sdrangel") | ||||
| }; | ||||
| 
 | ||||
| const QString KiwiSDRPlugin::m_hardwareID = "KiwiSDR"; | ||||
| const QString KiwiSDRPlugin::m_deviceTypeID = KIWISDR_DEVICE_TYPE_ID; | ||||
| 
 | ||||
| KiwiSDRPlugin::KiwiSDRPlugin(QObject* parent) : | ||||
| 	QObject(parent) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| const PluginDescriptor& KiwiSDRPlugin::getPluginDescriptor() const | ||||
| { | ||||
| 	return m_pluginDescriptor; | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRPlugin::initPlugin(PluginAPI* pluginAPI) | ||||
| { | ||||
| 	pluginAPI->registerSampleSource(m_deviceTypeID, this); | ||||
| } | ||||
| 
 | ||||
| PluginInterface::SamplingDevices KiwiSDRPlugin::enumSampleSources() | ||||
| { | ||||
| 	SamplingDevices result; | ||||
| 
 | ||||
|     result.append(SamplingDevice( | ||||
|             "KiwiSDR", | ||||
|             m_hardwareID, | ||||
|             m_deviceTypeID, | ||||
|             QString::null, | ||||
|             0, | ||||
|             PluginInterface::SamplingDevice::BuiltInDevice, | ||||
|             PluginInterface::SamplingDevice::StreamSingleRx, | ||||
|             1, | ||||
|             0)); | ||||
| 
 | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| #ifdef SERVER_MODE | ||||
| PluginInstanceGUI* KiwiSDRPlugin::createSampleSourcePluginInstanceGUI( | ||||
|         const QString& sourceId, | ||||
|         QWidget **widget, | ||||
|         DeviceUISet *deviceUISet) | ||||
| { | ||||
|     return 0; | ||||
| } | ||||
| #else | ||||
| PluginInstanceGUI* KiwiSDRPlugin::createSampleSourcePluginInstanceGUI( | ||||
|         const QString& sourceId, | ||||
|         QWidget **widget, | ||||
|         DeviceUISet *deviceUISet) | ||||
| { | ||||
| 	if(sourceId == m_deviceTypeID) { | ||||
| 		KiwiSDRGui* gui = new KiwiSDRGui(deviceUISet); | ||||
| 		*widget = gui; | ||||
| 		return gui; | ||||
| 	} else { | ||||
| 		return 0; | ||||
| 	} | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| DeviceSampleSource *KiwiSDRPlugin::createSampleSourcePluginInstance(const QString& sourceId, DeviceAPI *deviceAPI) | ||||
| { | ||||
|     if (sourceId == m_deviceTypeID) | ||||
|     { | ||||
| 		KiwiSDRInput* input = new KiwiSDRInput(deviceAPI); | ||||
|         return input; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         return 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
							
								
								
									
										53
									
								
								plugins/samplesource/kiwisdr/kiwisdrplugin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								plugins/samplesource/kiwisdr/kiwisdrplugin.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2018 Edouard Griffiths, F4EXB                                   //
 | ||||
| //                                                                               //
 | ||||
| // 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.                                           //
 | ||||
| //                                                                               //
 | ||||
| // 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 _KIWISDR_KIWISDRPLUGIN_H | ||||
| #define _KIWISDR_KIWISDRPLUGIN_H | ||||
| 
 | ||||
| #include <QObject> | ||||
| #include "plugin/plugininterface.h" | ||||
| 
 | ||||
| class PluginAPI; | ||||
| 
 | ||||
| #define KIWISDR_DEVICE_TYPE_ID "sdrangel.samplesource.kiwisdrsource" | ||||
| 
 | ||||
| class KiwiSDRPlugin : public QObject, public PluginInterface { | ||||
| 	Q_OBJECT | ||||
| 	Q_INTERFACES(PluginInterface) | ||||
| 	Q_PLUGIN_METADATA(IID KIWISDR_DEVICE_TYPE_ID) | ||||
| 
 | ||||
| public: | ||||
| 	explicit KiwiSDRPlugin(QObject* parent = NULL); | ||||
| 
 | ||||
| 	const PluginDescriptor& getPluginDescriptor() const; | ||||
| 	void initPlugin(PluginAPI* pluginAPI); | ||||
| 
 | ||||
| 	virtual SamplingDevices enumSampleSources(); | ||||
| 	virtual PluginInstanceGUI* createSampleSourcePluginInstanceGUI( | ||||
| 	        const QString& sourceId, | ||||
| 	        QWidget **widget, | ||||
| 	        DeviceUISet *deviceUISet); | ||||
| 	virtual DeviceSampleSource* createSampleSourcePluginInstance(const QString& sourceId, DeviceAPI *deviceAPI); | ||||
| 
 | ||||
| 	static const QString m_hardwareID; | ||||
|     static const QString m_deviceTypeID; | ||||
| 
 | ||||
| private: | ||||
| 	static const PluginDescriptor m_pluginDescriptor; | ||||
| }; | ||||
| 
 | ||||
| #endif // _KIWISDR_KIWISDRPLUGIN_H
 | ||||
							
								
								
									
										103
									
								
								plugins/samplesource/kiwisdr/kiwisdrsettings.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								plugins/samplesource/kiwisdr/kiwisdrsettings.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2019 Vort                                                       //
 | ||||
| // Copyright (C) 2018 Edouard Griffiths, F4EXB                                   //
 | ||||
| //                                                                               //
 | ||||
| // 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.                                           //
 | ||||
| //                                                                               //
 | ||||
| // 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/>.          //
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #include "util/simpleserializer.h" | ||||
| #include "kiwisdrsettings.h" | ||||
| 
 | ||||
| KiwiSDRSettings::KiwiSDRSettings() | ||||
| { | ||||
|     resetToDefaults(); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRSettings::resetToDefaults() | ||||
| { | ||||
|     m_centerFrequency = 1450000; | ||||
| 
 | ||||
| 	m_gain = 20; | ||||
| 	m_useAGC = true; | ||||
| 
 | ||||
| 	m_serverAddress = "127.0.0.1:8073"; | ||||
| 
 | ||||
|     m_useReverseAPI = false; | ||||
|     m_reverseAPIAddress = "127.0.0.1"; | ||||
|     m_reverseAPIPort = 8888; | ||||
|     m_reverseAPIDeviceIndex = 0; | ||||
| } | ||||
| 
 | ||||
| QByteArray KiwiSDRSettings::serialize() const | ||||
| { | ||||
|     SimpleSerializer s(2); | ||||
| 
 | ||||
| 	s.writeString(2, m_serverAddress); | ||||
| 	s.writeU32(3, m_gain); | ||||
| 	s.writeBool(4, m_useAGC); | ||||
| 
 | ||||
|     s.writeBool(100, m_useReverseAPI); | ||||
|     s.writeString(101, m_reverseAPIAddress); | ||||
|     s.writeU32(102, m_reverseAPIPort); | ||||
|     s.writeU32(103, m_reverseAPIDeviceIndex); | ||||
| 
 | ||||
| 	return s.final(); | ||||
| } | ||||
| 
 | ||||
| bool KiwiSDRSettings::deserialize(const QByteArray& data) | ||||
| { | ||||
|     SimpleDeserializer d(data); | ||||
| 
 | ||||
|     if (!d.isValid()) | ||||
|     { | ||||
|         resetToDefaults(); | ||||
|         return false; | ||||
|     } | ||||
| 
 | ||||
|     if (d.getVersion() == 2) | ||||
|     { | ||||
| 		uint32_t utmp; | ||||
| 
 | ||||
| 		d.readString(2, &m_serverAddress, "127.0.0.1:8073"); | ||||
| 		d.readU32(3, &m_gain, 20); | ||||
| 		d.readBool(4, &m_useAGC, true); | ||||
| 
 | ||||
| 		d.readBool(100, &m_useReverseAPI, false); | ||||
| 		d.readString(101, &m_reverseAPIAddress, "127.0.0.1"); | ||||
| 		d.readU32(102, &utmp, 0); | ||||
| 
 | ||||
| 		if ((utmp > 1023) && (utmp < 65535)) { | ||||
| 			m_reverseAPIPort = utmp; | ||||
| 		} | ||||
| 		else { | ||||
| 			m_reverseAPIPort = 8888; | ||||
| 		} | ||||
| 
 | ||||
| 		d.readU32(103, &utmp, 0); | ||||
| 		m_reverseAPIDeviceIndex = utmp > 99 ? 99 : utmp; | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         resetToDefaults(); | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
							
								
								
									
										43
									
								
								plugins/samplesource/kiwisdr/kiwisdrsettings.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								plugins/samplesource/kiwisdr/kiwisdrsettings.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2019 Vort                                                       //
 | ||||
| // Copyright (C) 2018 Edouard Griffiths, F4EXB                                   //
 | ||||
| //                                                                               //
 | ||||
| // 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.                                           //
 | ||||
| //                                                                               //
 | ||||
| // 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 _KIWISDR_KIWISDRSETTINGS_H_ | ||||
| #define _KIWISDR_KIWISDRSETTINGS_H_ | ||||
| 
 | ||||
| #include <QString> | ||||
| #include <QByteArray> | ||||
| 
 | ||||
| struct KiwiSDRSettings { | ||||
| 	uint32_t m_gain; | ||||
| 	bool m_useAGC; | ||||
| 
 | ||||
|     quint64 m_centerFrequency; | ||||
| 	QString m_serverAddress; | ||||
| 
 | ||||
| 	bool m_useReverseAPI; | ||||
|     QString m_reverseAPIAddress; | ||||
|     uint16_t m_reverseAPIPort; | ||||
|     uint16_t m_reverseAPIDeviceIndex; | ||||
| 
 | ||||
| 	KiwiSDRSettings(); | ||||
| 	void resetToDefaults(); | ||||
| 	QByteArray serialize() const; | ||||
| 	bool deserialize(const QByteArray& data); | ||||
| }; | ||||
| 
 | ||||
| #endif /* _KIWISDR_KIWISDRSETTINGS_H_ */ | ||||
							
								
								
									
										147
									
								
								plugins/samplesource/kiwisdr/kiwisdrworker.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								plugins/samplesource/kiwisdr/kiwisdrworker.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,147 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2019 Vort                                                       //
 | ||||
| //                                                                               //
 | ||||
| // 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.                                           //
 | ||||
| //                                                                               //
 | ||||
| // 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/>.          //
 | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| #include <boost/endian/conversion.hpp> | ||||
| #include "kiwisdrworker.h" | ||||
| 
 | ||||
| KiwiSDRWorker::KiwiSDRWorker(SampleSinkFifo* sampleFifo) | ||||
| 	: QObject(), | ||||
| 	m_timer(this), | ||||
| 	m_sampleFifo(sampleFifo), | ||||
| 	m_samplesBuf(), | ||||
| 	m_centerFrequency(1450000), | ||||
| 	m_gain(20), | ||||
| 	m_useAGC(true) | ||||
| { | ||||
| 	connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick())); | ||||
| 
 | ||||
| 	m_webSocket.setParent(this); | ||||
| 	connect(&m_webSocket, &QWebSocket::connected, | ||||
| 		this, &KiwiSDRWorker::onConnected); | ||||
| 	connect(&m_webSocket, &QWebSocket::binaryMessageReceived, | ||||
| 		this, &KiwiSDRWorker::onBinaryMessageReceived); | ||||
| 	connect(&m_webSocket, QOverload<QAbstractSocket::SocketError>::of(&QWebSocket::error), | ||||
| 		this, &KiwiSDRWorker::onSocketError); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRWorker::onConnected() | ||||
| { | ||||
| 	m_webSocket.sendTextMessage("SET auth t=kiwi p=#"); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRWorker::onSocketError(QAbstractSocket::SocketError error) | ||||
| { | ||||
| 	emit updateStatus(3); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRWorker::sendCenterFrequency() | ||||
| { | ||||
| 	if (!m_webSocket.isValid()) | ||||
| 		return; | ||||
| 
 | ||||
| 	QString freq = QString::number(m_centerFrequency / 1000.0, 'f', 3); | ||||
| 	QString msg = "SET mod=iq low_cut=-5980 high_cut=5980 freq=" + freq; | ||||
| 	m_webSocket.sendTextMessage(msg); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRWorker::sendGain() | ||||
| { | ||||
| 	if (!m_webSocket.isValid()) | ||||
| 		return; | ||||
| 
 | ||||
| 	QString msg("SET agc="); | ||||
| 	msg.append(m_useAGC ? "1" : "0"); | ||||
| 	msg.append(" hang=0 thresh=-130 slope=6 decay=1000 manGain="); | ||||
| 	msg.append(QString::number(m_gain)); | ||||
| 	m_webSocket.sendTextMessage(msg); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRWorker::onBinaryMessageReceived(const QByteArray &message) | ||||
| { | ||||
| 	if (message[0] == 'M' && message[1] == 'S' && message[2] == 'G') | ||||
| 	{ | ||||
| 		QStringList al = QString::fromUtf8(message).split(' '); | ||||
| 		if (al[1] == "audio_init=0" && | ||||
| 			al[2] == "audio_rate=12000") | ||||
| 		{ | ||||
| 			m_webSocket.sendTextMessage("SET AR OK in=12000 out=48000"); | ||||
| 			m_webSocket.sendTextMessage("SERVER DE CLIENT KiwiAngel SND"); | ||||
| 			sendGain(); | ||||
| 			sendCenterFrequency(); | ||||
| 			m_timer.start(5000); | ||||
| 			emit updateStatus(2); | ||||
| 		} | ||||
| 	} | ||||
| 	else if (message[0] == 'S' && message[1] == 'N' && message[2] == 'D') | ||||
| 	{ | ||||
| 		int dataOffset = 20; | ||||
| 		int sampleCount = 512; | ||||
| 		const int16_t* messageSamples = (const int16_t*)(message.constData() + dataOffset); | ||||
| 
 | ||||
| 		m_samplesBuf.clear(); | ||||
| 		for (int i = 0; i < sampleCount; i++) | ||||
| 		{ | ||||
| 			m_samplesBuf.push_back(Sample( | ||||
| 				boost::endian::endian_reverse(messageSamples[i * 2]) << (SDR_RX_SAMP_SZ - 16), | ||||
| 				boost::endian::endian_reverse(messageSamples[i * 2 + 1]) << (SDR_RX_SAMP_SZ - 16) | ||||
| 			)); | ||||
| 		} | ||||
| 
 | ||||
| 		m_sampleFifo->write(m_samplesBuf.begin(), m_samplesBuf.end()); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRWorker::onCenterFrequencyChanged(quint64 centerFrequency) | ||||
| { | ||||
| 	if (m_centerFrequency == centerFrequency) | ||||
| 		return; | ||||
| 
 | ||||
| 	m_centerFrequency = centerFrequency; | ||||
| 	sendCenterFrequency(); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRWorker::onGainChanged(quint32 gain, bool useAGC) | ||||
| { | ||||
| 	if (m_gain == gain && m_useAGC == useAGC) | ||||
| 		return; | ||||
| 
 | ||||
| 	m_gain = gain; | ||||
| 	m_useAGC = useAGC; | ||||
| 
 | ||||
| 	sendGain(); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRWorker::onServerAddressChanged(QString serverAddress) | ||||
| { | ||||
| 	if (m_serverAddress == serverAddress) | ||||
| 		return; | ||||
| 	m_serverAddress = serverAddress; | ||||
| 
 | ||||
| 	emit updateStatus(1); | ||||
| 
 | ||||
| 	QString url("ws://"); | ||||
| 	url.append(m_serverAddress); | ||||
| 	url.append("/kiwi/"); | ||||
| 	url.append(QString::number(QDateTime::currentMSecsSinceEpoch())); | ||||
| 	url.append("/SND"); | ||||
| 	m_webSocket.open(QUrl(url)); | ||||
| } | ||||
| 
 | ||||
| void KiwiSDRWorker::tick() | ||||
| { | ||||
| 	m_webSocket.sendTextMessage("SET keepalive"); | ||||
| } | ||||
							
								
								
									
										64
									
								
								plugins/samplesource/kiwisdr/kiwisdrworker.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								plugins/samplesource/kiwisdr/kiwisdrworker.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,64 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2019 Vort                                                       //
 | ||||
| //                                                                               //
 | ||||
| // 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.                                           //
 | ||||
| //                                                                               //
 | ||||
| // 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 _KIWISDR_KIWISDRWORKER_H_ | ||||
| #define _KIWISDR_KIWISDRWORKER_H_ | ||||
| 
 | ||||
| #include <QTimer> | ||||
| #include <QtWebSockets/QtWebSockets> | ||||
| 
 | ||||
| #include "dsp/samplesinkfifo.h" | ||||
| 
 | ||||
| class KiwiSDRWorker : public QObject { | ||||
| 	Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
| 	KiwiSDRWorker(SampleSinkFifo* sampleFifo); | ||||
| 
 | ||||
| private: | ||||
| 	QTimer m_timer; | ||||
| 	QWebSocket m_webSocket; | ||||
| 
 | ||||
| 	SampleVector m_samplesBuf; | ||||
| 	SampleSinkFifo* m_sampleFifo; | ||||
| 
 | ||||
| 	QString m_serverAddress; | ||||
| 	uint64_t m_centerFrequency; | ||||
| 
 | ||||
| 	uint32_t m_gain; | ||||
| 	bool m_useAGC; | ||||
| 
 | ||||
| 	void sendCenterFrequency(); | ||||
| 	void sendGain(); | ||||
| 
 | ||||
| signals: | ||||
| 	void updateStatus(int status); | ||||
| 
 | ||||
| public slots: | ||||
| 	void onCenterFrequencyChanged(quint64 centerFrequency); | ||||
| 	void onServerAddressChanged(QString serverAddress); | ||||
| 	void onGainChanged(quint32 gain, bool useAGC); | ||||
| 
 | ||||
| private slots: | ||||
| 	void onConnected(); | ||||
| 	void onBinaryMessageReceived(const QByteArray &message); | ||||
| 	void onSocketError(QAbstractSocket::SocketError error); | ||||
| 
 | ||||
|     void tick(); | ||||
| }; | ||||
| 
 | ||||
| #endif // _KIWISDR_KIWISDRWORKER_H_
 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user