| 
									
										
										
										
											2019-06-07 10:33:33 +03:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // 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>
 | 
					
						
							| 
									
										
										
										
											2022-11-27 00:28:55 +01:00
										 |  |  | #include "util/messagequeue.h"
 | 
					
						
							| 
									
										
										
										
											2019-06-07 10:33:33 +03:00
										 |  |  | #include "kiwisdrworker.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-11-27 00:28:55 +01:00
										 |  |  | MESSAGE_CLASS_DEFINITION(KiwiSDRWorker::MsgReportSampleRate, Message) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-14 05:51:19 +01:00
										 |  |  | KiwiSDRWorker::KiwiSDRWorker(SampleSinkFifo* sampleFifo) : | 
					
						
							|  |  |  | 	QObject(), | 
					
						
							| 
									
										
										
										
											2019-06-07 10:33:33 +03:00
										 |  |  | 	m_timer(this), | 
					
						
							|  |  |  | 	m_samplesBuf(), | 
					
						
							| 
									
										
										
										
											2020-11-14 05:51:19 +01:00
										 |  |  | 	m_sampleFifo(sampleFifo), | 
					
						
							| 
									
										
										
										
											2019-06-07 10:33:33 +03:00
										 |  |  | 	m_centerFrequency(1450000), | 
					
						
							| 
									
										
										
										
											2022-11-27 00:28:55 +01:00
										 |  |  |     m_sampleRate(12000), | 
					
						
							|  |  |  |     m_inputMessageQueue(nullptr), | 
					
						
							| 
									
										
										
										
											2019-06-07 10:33:33 +03:00
										 |  |  | 	m_gain(20), | 
					
						
							| 
									
										
										
										
											2019-06-09 00:56:31 +02:00
										 |  |  | 	m_useAGC(true), | 
					
						
							|  |  |  |     m_status(0) | 
					
						
							| 
									
										
										
										
											2019-06-07 10:33:33 +03:00
										 |  |  | { | 
					
						
							|  |  |  | 	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); | 
					
						
							| 
									
										
										
										
											2019-06-08 22:28:06 +02:00
										 |  |  |     connect(&m_webSocket, &QWebSocket::disconnected, | 
					
						
							|  |  |  |         this, &KiwiSDRWorker::onDisconnected); | 
					
						
							| 
									
										
										
										
											2019-06-07 10:33:33 +03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void KiwiSDRWorker::onConnected() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_webSocket.sendTextMessage("SET auth t=kiwi p=#"); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-08 22:28:06 +02:00
										 |  |  | void KiwiSDRWorker::onDisconnected() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     qDebug("KiwiSDRWorker::onDisconnected"); | 
					
						
							| 
									
										
										
										
											2019-06-09 00:56:31 +02:00
										 |  |  |     m_status = 4; | 
					
						
							| 
									
										
										
										
											2019-06-08 22:28:06 +02:00
										 |  |  | 	emit updateStatus(4); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 10:33:33 +03:00
										 |  |  | void KiwiSDRWorker::onSocketError(QAbstractSocket::SocketError error) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-11-14 11:13:32 +01:00
										 |  |  | 	(void) error; | 
					
						
							| 
									
										
										
										
											2019-06-09 00:56:31 +02:00
										 |  |  |     m_status = 3; | 
					
						
							| 
									
										
										
										
											2019-06-07 10:33:33 +03:00
										 |  |  | 	emit updateStatus(3); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void KiwiSDRWorker::sendCenterFrequency() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!m_webSocket.isValid()) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	QString freq = QString::number(m_centerFrequency / 1000.0, 'f', 3); | 
					
						
							| 
									
										
										
										
											2022-11-27 00:28:55 +01:00
										 |  |  |     int bw = (m_sampleRate/2) - 20; | 
					
						
							|  |  |  | 	QString msg = QString("SET mod=iq low_cut=-%1 high_cut=%2 freq=%3").arg(bw).arg(bw).arg(freq); | 
					
						
							| 
									
										
										
										
											2019-06-07 10:33:33 +03:00
										 |  |  | 	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(' '); | 
					
						
							| 
									
										
										
										
											2022-11-27 00:28:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if ((al.size() > 2) && al[2].startsWith("audio_rate=")) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             QStringList rateKeyVal = al[2].split('='); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (rateKeyVal.size() > 1) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 bool ok; | 
					
						
							|  |  |  |                 int sampleRate = rateKeyVal[1].toInt(&ok); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (ok) { | 
					
						
							|  |  |  |                     m_sampleRate = sampleRate; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 qDebug("KiwiSDRWorker::onBinaryMessageReceived: sample rate: %d", m_sampleRate); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (m_inputMessageQueue) { | 
					
						
							|  |  |  |                     m_inputMessageQueue->push(MsgReportSampleRate::create(m_sampleRate)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 QString msg = QString("SET AR OK in=%1 out=48000").arg(m_sampleRate); | 
					
						
							|  |  |  |                 m_webSocket.sendTextMessage(msg); | 
					
						
							|  |  |  |                 m_webSocket.sendTextMessage("SERVER DE CLIENT KiwiAngel SND"); | 
					
						
							|  |  |  |                 sendGain(); | 
					
						
							|  |  |  |                 sendCenterFrequency(); | 
					
						
							|  |  |  |                 m_timer.start(5000); | 
					
						
							|  |  |  |                 m_status = 2; | 
					
						
							|  |  |  |                 emit updateStatus(2); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2019-06-07 10:33:33 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	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) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-10-08 12:45:37 +02:00
										 |  |  | 	if (m_serverAddress == serverAddress) { | 
					
						
							| 
									
										
										
										
											2019-06-07 10:33:33 +03:00
										 |  |  | 		return; | 
					
						
							| 
									
										
										
										
											2022-10-08 12:45:37 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-07 10:33:33 +03:00
										 |  |  | 	m_serverAddress = serverAddress; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-06-09 00:56:31 +02:00
										 |  |  |     m_status = 1; | 
					
						
							| 
									
										
										
										
											2019-06-07 10:33:33 +03:00
										 |  |  | 	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"); | 
					
						
							| 
									
										
										
										
											2020-11-03 22:11:19 +01:00
										 |  |  | } |