mirror of
				https://github.com/f4exb/sdrangel.git
				synced 2025-10-31 13:00:26 -04:00 
			
		
		
		
	Rough Wideband FM.
This commit is contained in:
		
							parent
							
								
									b41e83e0ad
								
							
						
					
					
						commit
						ff312a52a3
					
				| @ -4,5 +4,6 @@ add_subdirectory(nfm) | ||||
| add_subdirectory(ssb) | ||||
| add_subdirectory(tcpsrc) | ||||
| add_subdirectory(usb) | ||||
| add_subdirectory(wfm) | ||||
| 
 | ||||
| #add_subdirectory(tetra) | ||||
|  | ||||
							
								
								
									
										47
									
								
								plugins/channel/wfm/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								plugins/channel/wfm/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | ||||
| project(wfm) | ||||
| 
 | ||||
| set(wfm_SOURCES | ||||
| 	wfmdemod.cpp | ||||
| 	wfmdemodgui.cpp | ||||
| 	wfmplugin.cpp | ||||
| ) | ||||
| 
 | ||||
| set(wfm_HEADERS | ||||
| 	wfmdemod.h | ||||
| 	wfmdemodgui.h | ||||
| 	wfmplugin.h | ||||
| ) | ||||
| 
 | ||||
| set(wfm_FORMS | ||||
| 	wfmdemodgui.ui | ||||
| ) | ||||
| 
 | ||||
| include_directories( | ||||
| 	. | ||||
| 	${CMAKE_CURRENT_BINARY_DIR} | ||||
| 	${CMAKE_SOURCE_DIR}/include | ||||
| 	${CMAKE_SOURCE_DIR}/include-gpl | ||||
| 	${OPENGL_INCLUDE_DIR} | ||||
| ) | ||||
| 
 | ||||
| #include(${QT_USE_FILE}) | ||||
| add_definitions(${QT_DEFINITIONS}) | ||||
| add_definitions(-DQT_PLUGIN) | ||||
| add_definitions(-DQT_SHARED) | ||||
| 
 | ||||
| #qt5_wrap_cpp(wfm_HEADERS_MOC ${wfm_HEADERS}) | ||||
| qt5_wrap_ui(wfm_FORMS_HEADERS ${wfm_FORMS}) | ||||
| 
 | ||||
| add_library(demodwfm SHARED | ||||
| 	${wfm_SOURCES} | ||||
| 	${wfm_HEADERS_MOC} | ||||
| 	${wfm_FORMS_HEADERS} | ||||
| ) | ||||
| 
 | ||||
| target_link_libraries(demodwfm | ||||
| 	${QT_LIBRARIES} | ||||
| 	${OPENGL_LIBRARIES} | ||||
| 	sdrbase | ||||
| ) | ||||
| 
 | ||||
| qt5_use_modules(demodwfm Core Widgets OpenGL Multimedia) | ||||
							
								
								
									
										119
									
								
								plugins/channel/wfm/wfmdemod.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								plugins/channel/wfm/wfmdemod.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,119 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
 | ||||
| // written by Christian Daniel                                                   //
 | ||||
| //                                                                               //
 | ||||
| // 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                  //
 | ||||
| //                                                                               //
 | ||||
| // 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 <QTime> | ||||
| #include <stdio.h> | ||||
| #include "wfmdemod.h" | ||||
| #include "audio/audiooutput.h" | ||||
| #include "dsp/dspcommands.h" | ||||
| 
 | ||||
| MESSAGE_CLASS_DEFINITION(WFMDemod::MsgConfigureWFMDemod, Message) | ||||
| 
 | ||||
| WFMDemod::WFMDemod(AudioFifo* audioFifo, SampleSink* sampleSink) : | ||||
| 	m_sampleSink(sampleSink), | ||||
| 	m_audioFifo(audioFifo) | ||||
| { | ||||
| 	m_volume = 2.0; | ||||
| 	m_sampleRate = 250000; | ||||
| 	m_frequency = 0; | ||||
| 
 | ||||
| 	m_nco.setFreq(m_frequency, m_sampleRate); | ||||
| 	m_interpolator.create(16, m_sampleRate, 16000); | ||||
| 	m_sampleDistanceRemain = (Real)m_sampleRate / 48000.0; | ||||
| 
 | ||||
| 	m_audioBuffer.resize(256); | ||||
| 	m_audioBufferFill = 0; | ||||
| } | ||||
| 
 | ||||
| WFMDemod::~WFMDemod() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| void WFMDemod::configure(MessageQueue* messageQueue, Real afBandwidth, Real volume) | ||||
| { | ||||
| 	Message* cmd = MsgConfigureWFMDemod::create(afBandwidth, volume); | ||||
| 	cmd->submit(messageQueue, this); | ||||
| } | ||||
| 
 | ||||
| void WFMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly) | ||||
| { | ||||
| 	Complex ci; | ||||
| 	bool consumed; | ||||
| 	qint16 sample; | ||||
| 	Real demod; | ||||
| 
 | ||||
| 	for(SampleVector::const_iterator it = begin; it < end; ++it) { | ||||
| 		Complex c(it->real() , it->imag()); | ||||
| 		Complex d = c * conj(m_lastSample); | ||||
| 		m_lastSample = c; | ||||
| 		demod = atan2(d.imag(), d.real()) * (1 /M_PI); | ||||
| 		Complex e(demod, 0); | ||||
| 
 | ||||
| 		consumed = false; | ||||
| 		if(m_interpolator.interpolate(&m_sampleDistanceRemain, e, &consumed, &ci)) { | ||||
| 			sample = (qint16)(3000.0 * ci.real() * m_volume); | ||||
| 			m_sampleBuffer.push_back(Sample(sample, sample)); | ||||
| 			m_audioBuffer[m_audioBufferFill].l = sample; | ||||
| 			m_audioBuffer[m_audioBufferFill].r = sample; | ||||
| 			++m_audioBufferFill; | ||||
| 			if(m_audioBufferFill >= m_audioBuffer.size()) { | ||||
| 				uint res = m_audioFifo->write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 1); | ||||
| 				/*
 | ||||
| 				if(res != m_audioBufferFill) | ||||
| 					qDebug("lost %u samples", m_audioBufferFill - res); | ||||
| 				*/ | ||||
| 				m_audioBufferFill = 0; | ||||
| 			} | ||||
| 
 | ||||
| 			m_sampleDistanceRemain += (Real)m_sampleRate / 48000.0; | ||||
| 		} | ||||
| 	} | ||||
| 	if(m_audioFifo->write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 0) != m_audioBufferFill) | ||||
| 		;//qDebug("lost samples");
 | ||||
| 	m_audioBufferFill = 0; | ||||
| 
 | ||||
| 	if(m_sampleSink != NULL) | ||||
| 		m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), true); | ||||
| 	m_sampleBuffer.clear(); | ||||
| } | ||||
| 
 | ||||
| void WFMDemod::start() {} | ||||
| void WFMDemod::stop() {} | ||||
| 
 | ||||
| bool WFMDemod::handleMessage(Message* cmd) | ||||
| { | ||||
| 	if(DSPSignalNotification::match(cmd)) { | ||||
| 		DSPSignalNotification* signal = (DSPSignalNotification*)cmd; | ||||
| 		qDebug("%d samples/sec, %lld Hz offset", signal->getSampleRate(), signal->getFrequencyOffset()); | ||||
| 		m_sampleRate = signal->getSampleRate(); | ||||
| 		m_interpolator.create(16, m_sampleRate, m_afBandwidth); | ||||
| 		m_sampleDistanceRemain = m_sampleRate / 48000.0; | ||||
| 		cmd->completed(); | ||||
| 		return true; | ||||
| 	} else if(MsgConfigureWFMDemod::match(cmd)) { | ||||
| 		MsgConfigureWFMDemod* cfg = (MsgConfigureWFMDemod*)cmd; | ||||
| 		m_afBandwidth = cfg->getAFBandwidth(); | ||||
| 		m_interpolator.create(16, m_sampleRate, m_afBandwidth); | ||||
| 		m_volume = cfg->getVolume(); | ||||
| 		cmd->completed(); | ||||
| 		return true; | ||||
| 	} else { | ||||
| 		if(m_sampleSink != NULL) | ||||
| 		   return m_sampleSink->handleMessage(cmd); | ||||
| 		else return false; | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										92
									
								
								plugins/channel/wfm/wfmdemod.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								plugins/channel/wfm/wfmdemod.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,92 @@ | ||||
| ///////////////////////////////////////////////////////////////////////////////////
 | ||||
| // Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
 | ||||
| // written by Christian Daniel                                                   //
 | ||||
| //                                                                               //
 | ||||
| // 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                  //
 | ||||
| //                                                                               //
 | ||||
| // 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 INCLUDE_WFMDEMOD_H | ||||
| #define INCLUDE_WFMDEMOD_H | ||||
| 
 | ||||
| #include <vector> | ||||
| #include "dsp/samplesink.h" | ||||
| #include "dsp/nco.h" | ||||
| #include "dsp/interpolator.h" | ||||
| #include "dsp/lowpass.h" | ||||
| #include "audio/audiofifo.h" | ||||
| #include "util/message.h" | ||||
| 
 | ||||
| class AudioFifo; | ||||
| 
 | ||||
| class WFMDemod : public SampleSink { | ||||
| public: | ||||
| 	WFMDemod(AudioFifo* audioFifo, SampleSink* sampleSink); | ||||
| 	~WFMDemod(); | ||||
| 
 | ||||
| 	void configure(MessageQueue* messageQueue, Real afBandwidth, Real volume); | ||||
| 
 | ||||
| 	void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly); | ||||
| 	void start(); | ||||
| 	void stop(); | ||||
| 	bool handleMessage(Message* cmd); | ||||
| 
 | ||||
| private: | ||||
| 	class MsgConfigureWFMDemod : public Message { | ||||
| 		MESSAGE_CLASS_DECLARATION | ||||
| 
 | ||||
| 	public: | ||||
| 		Real getAFBandwidth() const { return m_afBandwidth; } | ||||
| 		Real getVolume() const { return m_volume; } | ||||
| 
 | ||||
| 		static MsgConfigureWFMDemod* create(Real afBandwidth, Real volume) | ||||
| 		{ | ||||
| 			return new MsgConfigureWFMDemod(afBandwidth, volume); | ||||
| 		} | ||||
| 
 | ||||
| 	private: | ||||
| 		Real m_afBandwidth; | ||||
| 		Real m_volume; | ||||
| 
 | ||||
| 		MsgConfigureWFMDemod(Real afBandwidth, Real volume) : | ||||
| 			Message(), | ||||
| 			m_afBandwidth(afBandwidth), | ||||
| 			m_volume(volume) | ||||
| 		{ } | ||||
| 	}; | ||||
| 
 | ||||
| 	struct AudioSample { | ||||
| 		qint16 l; | ||||
| 		qint16 r; | ||||
| 	}; | ||||
| 	typedef std::vector<AudioSample> AudioVector; | ||||
| 
 | ||||
| 	Real m_afBandwidth; | ||||
| 	Real m_volume; | ||||
| 	int m_sampleRate; | ||||
| 	int m_frequency; | ||||
| 
 | ||||
| 	NCO m_nco; | ||||
| 	Interpolator m_interpolator; | ||||
| 	Real m_sampleDistanceRemain; | ||||
| 
 | ||||
| 	Complex m_lastSample; | ||||
| 
 | ||||
| 	AudioVector m_audioBuffer; | ||||
| 	uint m_audioBufferFill; | ||||
| 	AudioFifo* m_audioFifo; | ||||
| 
 | ||||
| 	SampleSink* m_sampleSink; | ||||
| 	SampleVector m_sampleBuffer; | ||||
| }; | ||||
| 
 | ||||
| #endif // INCLUDE_WFMDEMOD_H
 | ||||
							
								
								
									
										182
									
								
								plugins/channel/wfm/wfmdemodgui.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										182
									
								
								plugins/channel/wfm/wfmdemodgui.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,182 @@ | ||||
| #include <QDockWidget> | ||||
| #include <QMainWindow> | ||||
| #include "wfmdemodgui.h" | ||||
| #include "ui_wfmdemodgui.h" | ||||
| #include "wfmdemodgui.h" | ||||
| #include "ui_wfmdemodgui.h" | ||||
| #include "dsp/threadedsamplesink.h" | ||||
| #include "dsp/channelizer.h" | ||||
| #include "wfmdemod.h" | ||||
| #include "dsp/spectrumvis.h" | ||||
| #include "gui/glspectrum.h" | ||||
| #include "plugin/pluginapi.h" | ||||
| #include "util/simpleserializer.h" | ||||
| #include "gui/basicchannelsettingswidget.h" | ||||
| 
 | ||||
| WFMDemodGUI* WFMDemodGUI::create(PluginAPI* pluginAPI) | ||||
| { | ||||
| 	WFMDemodGUI* gui = new WFMDemodGUI(pluginAPI); | ||||
| 	return gui; | ||||
| } | ||||
| 
 | ||||
| void WFMDemodGUI::destroy() | ||||
| { | ||||
| 	delete this; | ||||
| } | ||||
| 
 | ||||
| void WFMDemodGUI::setName(const QString& name) | ||||
| { | ||||
| 	setObjectName(name); | ||||
| } | ||||
| 
 | ||||
| void WFMDemodGUI::resetToDefaults() | ||||
| { | ||||
| 	ui->afBW->setValue(6); | ||||
| 	ui->volume->setValue(20); | ||||
| 	ui->spectrumGUI->resetToDefaults(); | ||||
| 	applySettings(); | ||||
| } | ||||
| 
 | ||||
| QByteArray WFMDemodGUI::serialize() const | ||||
| { | ||||
| 	SimpleSerializer s(1); | ||||
| 	s.writeS32(1, m_channelMarker->getCenterFrequency()); | ||||
| 	s.writeS32(2, ui->afBW->value()); | ||||
| 	s.writeS32(3, ui->volume->value()); | ||||
| 	s.writeBlob(4, ui->spectrumGUI->serialize()); | ||||
| 	s.writeU32(5, m_channelMarker->getColor().rgb()); | ||||
| 	return s.final(); | ||||
| } | ||||
| 
 | ||||
| bool WFMDemodGUI::deserialize(const QByteArray& data) | ||||
| { | ||||
| 	SimpleDeserializer d(data); | ||||
| 
 | ||||
| 	if(!d.isValid()) { | ||||
| 		resetToDefaults(); | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	if(d.getVersion() == 1) { | ||||
| 		QByteArray bytetmp; | ||||
| 		quint32 u32tmp; | ||||
| 		qint32 tmp; | ||||
| 		d.readS32(1, &tmp, 0); | ||||
| 		m_channelMarker->setCenterFrequency(tmp); | ||||
| 		d.readS32(2, &tmp, 6); | ||||
| 		ui->afBW->setValue(tmp); | ||||
| 		d.readS32(3, &tmp, 20); | ||||
| 		ui->volume->setValue(tmp); | ||||
| 		d.readBlob(4, &bytetmp); | ||||
| 		ui->spectrumGUI->deserialize(bytetmp); | ||||
| 		if(d.readU32(5, &u32tmp)) | ||||
| 			m_channelMarker->setColor(u32tmp); | ||||
| 		applySettings(); | ||||
| 		return true; | ||||
| 	} else { | ||||
| 		resetToDefaults(); | ||||
| 		return false; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| bool WFMDemodGUI::handleMessage(Message* message) | ||||
| { | ||||
| 	return false; | ||||
| } | ||||
| 
 | ||||
| void WFMDemodGUI::viewChanged() | ||||
| { | ||||
| 	applySettings(); | ||||
| } | ||||
| 
 | ||||
| void WFMDemodGUI::on_afBW_valueChanged(int value) | ||||
| { | ||||
| 	ui->afBWText->setText(QString("%1 kHz").arg(value)); | ||||
| 	applySettings(); | ||||
| } | ||||
| 
 | ||||
| void WFMDemodGUI::on_volume_valueChanged(int value) | ||||
| { | ||||
| 	ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1)); | ||||
| 	applySettings(); | ||||
| } | ||||
| 
 | ||||
| void WFMDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown) | ||||
| { | ||||
| 	/*
 | ||||
| 	if((widget == ui->spectrumContainer) && (m_wfmDemod != NULL)) | ||||
| 		m_wfmDemod->setSpectrum(m_threadedSampleSink->getMessageQueue(), rollDown); | ||||
| 	*/ | ||||
| } | ||||
| 
 | ||||
| void WFMDemodGUI::onMenuDoubleClicked() | ||||
| { | ||||
| 	if(!m_basicSettingsShown) { | ||||
| 		m_basicSettingsShown = true; | ||||
| 		BasicChannelSettingsWidget* bcsw = new BasicChannelSettingsWidget(m_channelMarker, this); | ||||
| 		bcsw->show(); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| WFMDemodGUI::WFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) : | ||||
| 	RollupWidget(parent), | ||||
| 	ui(new Ui::WFMDemodGUI), | ||||
| 	m_pluginAPI(pluginAPI), | ||||
| 	m_basicSettingsShown(false) | ||||
| { | ||||
| 	ui->setupUi(this); | ||||
| 	setAttribute(Qt::WA_DeleteOnClose, true); | ||||
| 	connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); | ||||
| 	connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked())); | ||||
| 
 | ||||
| 	m_audioFifo = new AudioFifo(4, 48000 / 4); | ||||
| 	m_spectrumVis = new SpectrumVis(ui->glSpectrum); | ||||
| 	m_wfmDemod = new WFMDemod(m_audioFifo, m_spectrumVis); | ||||
| 	m_channelizer = new Channelizer(m_wfmDemod); | ||||
| 	m_threadedSampleSink = new ThreadedSampleSink(m_channelizer); | ||||
| 	m_pluginAPI->addAudioSource(m_audioFifo); | ||||
| 	m_pluginAPI->addSampleSink(m_threadedSampleSink); | ||||
| 
 | ||||
| 	ui->glSpectrum->setCenterFrequency(12000); | ||||
| 	ui->glSpectrum->setSampleRate(24000); | ||||
| 	ui->glSpectrum->setDisplayWaterfall(true); | ||||
| 	ui->glSpectrum->setDisplayMaxHold(true); | ||||
| 	m_spectrumVis->configure(m_threadedSampleSink->getMessageQueue(), 64, 10, FFTWindow::BlackmanHarris); | ||||
| 
 | ||||
| 	m_channelMarker = new ChannelMarker(this); | ||||
| 	m_channelMarker->setColor(Qt::red); | ||||
| 	m_channelMarker->setBandwidth(16000); | ||||
| 	m_channelMarker->setCenterFrequency(0); | ||||
| 	m_channelMarker->setVisible(true); | ||||
| 	connect(m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged())); | ||||
| 	m_pluginAPI->addChannelMarker(m_channelMarker); | ||||
| 
 | ||||
| 	ui->spectrumGUI->setBuddies(m_threadedSampleSink->getMessageQueue(), m_spectrumVis, ui->glSpectrum); | ||||
| 
 | ||||
| 	applySettings(); | ||||
| } | ||||
| 
 | ||||
| WFMDemodGUI::~WFMDemodGUI() | ||||
| { | ||||
| 	m_pluginAPI->removeChannelInstance(this); | ||||
| 	m_pluginAPI->removeAudioSource(m_audioFifo); | ||||
| 	m_pluginAPI->removeSampleSink(m_threadedSampleSink); | ||||
| 	delete m_threadedSampleSink; | ||||
| 	delete m_channelizer; | ||||
| 	delete m_wfmDemod; | ||||
| 	delete m_spectrumVis; | ||||
| 	delete m_audioFifo; | ||||
| 	delete m_channelMarker; | ||||
| 	delete ui; | ||||
| } | ||||
| 
 | ||||
| void WFMDemodGUI::applySettings() | ||||
| { | ||||
| 	setTitleColor(m_channelMarker->getColor()); | ||||
| 	m_channelizer->configure(m_threadedSampleSink->getMessageQueue(), | ||||
| 		48000, | ||||
| 		m_channelMarker->getCenterFrequency()); | ||||
| 	m_wfmDemod->configure(m_threadedSampleSink->getMessageQueue(), | ||||
| 		ui->afBW->value() * 1000.0, | ||||
| 		ui->volume->value() * 0.1); | ||||
| } | ||||
							
								
								
									
										60
									
								
								plugins/channel/wfm/wfmdemodgui.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								plugins/channel/wfm/wfmdemodgui.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | ||||
| #ifndef INCLUDE_WFMDEMODGUI_H | ||||
| #define INCLUDE_WFMDEMODGUI_H | ||||
| 
 | ||||
| #include "gui/rollupwidget.h" | ||||
| #include "plugin/plugingui.h" | ||||
| 
 | ||||
| class PluginAPI; | ||||
| class ChannelMarker; | ||||
| 
 | ||||
| class AudioFifo; | ||||
| class ThreadedSampleSink; | ||||
| class Channelizer; | ||||
| class WFMDemod; | ||||
| class SpectrumVis; | ||||
| 
 | ||||
| namespace Ui { | ||||
| 	class WFMDemodGUI; | ||||
| } | ||||
| 
 | ||||
| class WFMDemodGUI : public RollupWidget, public PluginGUI { | ||||
| 	Q_OBJECT | ||||
| 
 | ||||
| public: | ||||
| 	static WFMDemodGUI* create(PluginAPI* pluginAPI); | ||||
| 	void destroy(); | ||||
| 
 | ||||
| 	void setName(const QString& name); | ||||
| 
 | ||||
| 	void resetToDefaults(); | ||||
| 	QByteArray serialize() const; | ||||
| 	bool deserialize(const QByteArray& data); | ||||
| 
 | ||||
| 	bool handleMessage(Message* message); | ||||
| 
 | ||||
| private slots: | ||||
| 	void viewChanged(); | ||||
| 	void on_afBW_valueChanged(int value); | ||||
| 	void on_volume_valueChanged(int value); | ||||
| 	void onWidgetRolled(QWidget* widget, bool rollDown); | ||||
| 	void onMenuDoubleClicked(); | ||||
| 
 | ||||
| private: | ||||
| 	Ui::WFMDemodGUI* ui; | ||||
| 	PluginAPI* m_pluginAPI; | ||||
| 	ChannelMarker* m_channelMarker; | ||||
| 	bool m_basicSettingsShown; | ||||
| 
 | ||||
| 	AudioFifo* m_audioFifo; | ||||
| 	ThreadedSampleSink* m_threadedSampleSink; | ||||
| 	Channelizer* m_channelizer; | ||||
| 	WFMDemod* m_wfmDemod; | ||||
| 	SpectrumVis* m_spectrumVis; | ||||
| 
 | ||||
| 	explicit WFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent = NULL); | ||||
| 	~WFMDemodGUI(); | ||||
| 
 | ||||
| 	void applySettings(); | ||||
| }; | ||||
| 
 | ||||
| #endif // INCLUDE_WFMDEMODGUI_H
 | ||||
							
								
								
									
										172
									
								
								plugins/channel/wfm/wfmdemodgui.ui
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										172
									
								
								plugins/channel/wfm/wfmdemodgui.ui
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,172 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <ui version="4.0"> | ||||
|  <class>WFMDemodGUI</class> | ||||
|  <widget class="RollupWidget" name="WFMDemodGUI"> | ||||
|   <property name="geometry"> | ||||
|    <rect> | ||||
|     <x>0</x> | ||||
|     <y>0</y> | ||||
|     <width>302</width> | ||||
|     <height>410</height> | ||||
|    </rect> | ||||
|   </property> | ||||
|   <property name="windowTitle"> | ||||
|    <string>WBFM Demodulator</string> | ||||
|   </property> | ||||
|   <widget class="QWidget" name="settingsContainer" native="true"> | ||||
|    <property name="geometry"> | ||||
|     <rect> | ||||
|      <x>35</x> | ||||
|      <y>35</y> | ||||
|      <width>242</width> | ||||
|      <height>96</height> | ||||
|     </rect> | ||||
|    </property> | ||||
|    <property name="windowTitle"> | ||||
|     <string>Settings</string> | ||||
|    </property> | ||||
|    <layout class="QGridLayout" name="gridLayout"> | ||||
|     <property name="margin"> | ||||
|      <number>2</number> | ||||
|     </property> | ||||
|     <property name="spacing"> | ||||
|      <number>3</number> | ||||
|     </property> | ||||
|     <item row="0" column="0"> | ||||
|      <widget class="QLabel" name="label_2"> | ||||
|       <property name="text"> | ||||
|        <string>AF Bandwidth</string> | ||||
|       </property> | ||||
|      </widget> | ||||
|     </item> | ||||
|     <item row="0" column="1"> | ||||
|      <widget class="QSlider" name="afBW"> | ||||
|       <property name="minimum"> | ||||
|        <number>1</number> | ||||
|       </property> | ||||
|       <property name="maximum"> | ||||
|        <number>20</number> | ||||
|       </property> | ||||
|       <property name="pageStep"> | ||||
|        <number>1</number> | ||||
|       </property> | ||||
|       <property name="value"> | ||||
|        <number>3</number> | ||||
|       </property> | ||||
|       <property name="orientation"> | ||||
|        <enum>Qt::Horizontal</enum> | ||||
|       </property> | ||||
|      </widget> | ||||
|     </item> | ||||
|     <item row="0" column="2"> | ||||
|      <widget class="QLabel" name="afBWText"> | ||||
|       <property name="minimumSize"> | ||||
|        <size> | ||||
|         <width>50</width> | ||||
|         <height>0</height> | ||||
|        </size> | ||||
|       </property> | ||||
|       <property name="text"> | ||||
|        <string>6 kHz</string> | ||||
|       </property> | ||||
|       <property name="alignment"> | ||||
|        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | ||||
|       </property> | ||||
|      </widget> | ||||
|     </item> | ||||
|     <item row="1" column="0"> | ||||
|      <widget class="QLabel" name="label_3"> | ||||
|       <property name="text"> | ||||
|        <string>Volume</string> | ||||
|       </property> | ||||
|      </widget> | ||||
|     </item> | ||||
|     <item row="1" column="1"> | ||||
|      <widget class="QSlider" name="volume"> | ||||
|       <property name="maximum"> | ||||
|        <number>100</number> | ||||
|       </property> | ||||
|       <property name="value"> | ||||
|        <number>20</number> | ||||
|       </property> | ||||
|       <property name="orientation"> | ||||
|        <enum>Qt::Horizontal</enum> | ||||
|       </property> | ||||
|      </widget> | ||||
|     </item> | ||||
|     <item row="1" column="2"> | ||||
|      <widget class="QLabel" name="volumeText"> | ||||
|       <property name="minimumSize"> | ||||
|        <size> | ||||
|         <width>50</width> | ||||
|         <height>0</height> | ||||
|        </size> | ||||
|       </property> | ||||
|       <property name="text"> | ||||
|        <string>2.0</string> | ||||
|       </property> | ||||
|       <property name="alignment"> | ||||
|        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | ||||
|       </property> | ||||
|      </widget> | ||||
|     </item> | ||||
|    </layout> | ||||
|   </widget> | ||||
|   <widget class="QWidget" name="spectrumContainer" native="true"> | ||||
|    <property name="geometry"> | ||||
|     <rect> | ||||
|      <x>40</x> | ||||
|      <y>140</y> | ||||
|      <width>218</width> | ||||
|      <height>184</height> | ||||
|     </rect> | ||||
|    </property> | ||||
|    <property name="windowTitle"> | ||||
|     <string>Channel Spectrum</string> | ||||
|    </property> | ||||
|    <layout class="QVBoxLayout" name="verticalLayout"> | ||||
|     <property name="spacing"> | ||||
|      <number>2</number> | ||||
|     </property> | ||||
|     <property name="margin"> | ||||
|      <number>3</number> | ||||
|     </property> | ||||
|     <item> | ||||
|      <widget class="GLSpectrum" name="glSpectrum" native="true"> | ||||
|       <property name="minimumSize"> | ||||
|        <size> | ||||
|         <width>200</width> | ||||
|         <height>150</height> | ||||
|        </size> | ||||
|       </property> | ||||
|      </widget> | ||||
|     </item> | ||||
|     <item> | ||||
|      <widget class="GLSpectrumGUI" name="spectrumGUI" native="true"/> | ||||
|     </item> | ||||
|    </layout> | ||||
|   </widget> | ||||
|  </widget> | ||||
|  <customwidgets> | ||||
|   <customwidget> | ||||
|    <class>GLSpectrum</class> | ||||
|    <extends>QWidget</extends> | ||||
|    <header>gui/glspectrum.h</header> | ||||
|    <container>1</container> | ||||
|   </customwidget> | ||||
|   <customwidget> | ||||
|    <class>GLSpectrumGUI</class> | ||||
|    <extends>QWidget</extends> | ||||
|    <header>gui/glspectrumgui.h</header> | ||||
|    <container>1</container> | ||||
|   </customwidget> | ||||
|   <customwidget> | ||||
|    <class>RollupWidget</class> | ||||
|    <extends>QWidget</extends> | ||||
|    <header>gui/rollupwidget.h</header> | ||||
|    <container>1</container> | ||||
|   </customwidget> | ||||
|  </customwidgets> | ||||
|  <resources/> | ||||
|  <connections/> | ||||
| </ui> | ||||
							
								
								
									
										53
									
								
								plugins/channel/wfm/wfmplugin.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								plugins/channel/wfm/wfmplugin.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | ||||
| #include <QtPlugin> | ||||
| #include <QAction> | ||||
| #include "plugin/pluginapi.h" | ||||
| #include "wfmplugin.h" | ||||
| #include "wfmdemodgui.h" | ||||
| 
 | ||||
| const PluginDescriptor WFMPlugin::m_pluginDescriptor = { | ||||
| 	QString("WFM Demodulator"), | ||||
| 	QString("---"), | ||||
| 	QString("(c) maintech GmbH (written by Christian Daniel)"), | ||||
| 	QString("http://www.maintech.de"), | ||||
| 	true, | ||||
| 	QString("http://www.maintech.de") | ||||
| }; | ||||
| 
 | ||||
| WFMPlugin::WFMPlugin(QObject* parent) : | ||||
| 	QObject(parent) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| const PluginDescriptor& WFMPlugin::getPluginDescriptor() const | ||||
| { | ||||
| 	return m_pluginDescriptor; | ||||
| } | ||||
| 
 | ||||
| void WFMPlugin::initPlugin(PluginAPI* pluginAPI) | ||||
| { | ||||
| 	m_pluginAPI = pluginAPI; | ||||
| 
 | ||||
| 	// register WFM demodulator
 | ||||
| 	QAction* action = new QAction(tr("&WFM Demodulator"), this); | ||||
| 	connect(action, SIGNAL(triggered()), this, SLOT(createInstanceWFM())); | ||||
| 	m_pluginAPI->registerChannel("de.maintech.sdrangelove.channel.wfm", this, action); | ||||
| } | ||||
| 
 | ||||
| PluginGUI* WFMPlugin::createChannel(const QString& channelName) | ||||
| { | ||||
| 	if(channelName == "de.maintech.sdrangelove.channel.wfm") { | ||||
| 		WFMDemodGUI* gui = WFMDemodGUI::create(m_pluginAPI); | ||||
| 		m_pluginAPI->registerChannelInstance("de.maintech.sdrangelove.channel.wfm", gui); | ||||
| 		m_pluginAPI->addChannelRollup(gui); | ||||
| 		return gui; | ||||
| 	} else { | ||||
| 		return NULL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void WFMPlugin::createInstanceWFM() | ||||
| { | ||||
| 	WFMDemodGUI* gui = WFMDemodGUI::create(m_pluginAPI); | ||||
| 	m_pluginAPI->registerChannelInstance("de.maintech.sdrangelove.channel.wfm", gui); | ||||
| 	m_pluginAPI->addChannelRollup(gui); | ||||
| } | ||||
							
								
								
									
										29
									
								
								plugins/channel/wfm/wfmplugin.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								plugins/channel/wfm/wfmplugin.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| #ifndef INCLUDE_WFMPLUGIN_H | ||||
| #define INCLUDE_WFMPLUGIN_H | ||||
| 
 | ||||
| #include <QObject> | ||||
| #include "plugin/plugininterface.h" | ||||
| 
 | ||||
| class WFMPlugin : public QObject, PluginInterface { | ||||
| 	Q_OBJECT | ||||
| 	Q_INTERFACES(PluginInterface) | ||||
| 	Q_PLUGIN_METADATA(IID "de.maintech.sdrangelove.channel.wfm") | ||||
| 
 | ||||
| public: | ||||
| 	explicit WFMPlugin(QObject* parent = NULL); | ||||
| 
 | ||||
| 	const PluginDescriptor& getPluginDescriptor() const; | ||||
| 	void initPlugin(PluginAPI* pluginAPI); | ||||
| 
 | ||||
| 	PluginGUI* createChannel(const QString& channelName); | ||||
| 
 | ||||
| private: | ||||
| 	static const PluginDescriptor m_pluginDescriptor; | ||||
| 
 | ||||
| 	PluginAPI* m_pluginAPI; | ||||
| 
 | ||||
| private slots: | ||||
| 	void createInstanceWFM(); | ||||
| }; | ||||
| 
 | ||||
| #endif // INCLUDE_WFMPLUGIN_H
 | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user