1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-09-05 14:47:50 -04:00

Deep redesign: move to SDRangel #6. New readme and cleanup

This commit is contained in:
f4exb 2015-08-30 21:46:27 +02:00
parent 4fdfcfe386
commit 3aa4dc710b
20 changed files with 39 additions and 1739 deletions

View File

@ -1,31 +1,35 @@
=============== ========
RTL-SDRangelove SDRangel
=============== ========
![Channel analyzer plugins](https://github.com/f4exb/rtl-sdrangelove/blob/f4exb/doc/img/sdrangelove_cover.png) ![Channel analyzer plugins](https://github.com/f4exb/sdrangel/blob/f4exb/doc/img/sdrangel_banner.png)
====================== SDRangel is a Qt5/OpenGL SDR frontend to various hardware
Cloning the repository
======================
- Clone as usual ===================
- Checkout the f4exb branch: `git checkout f4exb` Repository branches
===================
======================= - master: the "production" branch
GNURadio and libosmosdr - rtlsdrangelove: the master from hexameron rtl-sdrangelove
======================= - legacy: the modified rtl-sdrangelove before major redeisign
These plugins have a lot of bugs and they have been removed trom the build. Original sources still exist in the tree. So current version only supports the following hardware: ================================================
- RTL-SDR Plugins unsupported but still in the source tree
- Funcube ================================================
- BladeRF (standard and with XB-200 transverter)
- Channels:
- tetra
- Sample sources:
- gnuradio
- osmosdr
- v4l-msi
- v4l-rtl
============== ==============
Funcube Dongle Funcube Dongle
============== ==============
Funcube Dongle Pro+ support will need "libasound2-dev" installed. ("libhid" is built from source). Install the rules file "fcdpp.rules" in "/etc/udev/rules.d" to gain the "root access" needed to control the dongle. Only the original Funcube Dongle Pro is supported. Funcube Dongle Pro+ will come later
Funcube Dongle Pro+ USB drivers are broken on some hardware with recent kernels. It works well for me with an Atom Chipset, which has Full Speed USB ports, or a "Valleyview" Chromebook (kernel 3.10). A Desktop with the "same" chipset needs kernel 3.2, available with Debian 7 "wheezy". YMMV.
======= =======
BladeRF BladeRF
@ -65,30 +69,31 @@ For non standard installations of RTL-SDR library, the GNU Radio runtime and gr.
There is no installation procedure the executable is at the root of the build directory There is no installation procedure the executable is at the root of the build directory
============ ==========
For Debian 8 For Debian
============ ==========
For any version of Debian you will need Qt5.
Debian 7 "wheezy" uses Qt4. Qt5 is available from the "wheezy-backports" repo, but this will remove Qt4. Debian 8 "jessie" uses Qt5. Debian 7 "wheezy" uses Qt4. Qt5 is available from the "wheezy-backports" repo, but this will remove Qt4. Debian 8 "jessie" uses Qt5.
Assuming Debian Jessie is used:
`sudo apt-get install cmake g++ pkg-config libfftw3-dev libusb-1.0-0-dev libusb-dev qt5-default qtbase5-dev qtchooser libqt5multimedia5-plugins qtmultimedia5-dev qttools5-dev qttools5-dev-tools libqt5opengl5-dev qtbase5-dev librtlsdr-dev libboost-all-dev` `sudo apt-get install cmake g++ pkg-config libfftw3-dev libusb-1.0-0-dev libusb-dev qt5-default qtbase5-dev qtchooser libqt5multimedia5-plugins qtmultimedia5-dev qttools5-dev qttools5-dev-tools libqt5opengl5-dev qtbase5-dev librtlsdr-dev libboost-all-dev`
`mkdir build && cd build && cmake ../ && make` `mkdir build && cd build && cmake ../ && make`
The same remarks as for Ubuntu apply... Then the same remarks as for Ubuntu apply...
============ ============
Known Issues Known Issues
============ ============
- Actually NFM seems to be working pretty well - You will need to stop input before changing preset then start again
- RTL frontend will have bad aliasing in noisy environments. Considering the size of the hardware there is no place for proper filters. With good filtering and a good antenna up front these devices work remarkably well for the price!
- Aliasing can be annoying for broadcast FM. In this case try to shift the signal until you find a clear background for your station. This is a limitation of the RTL hardware so just use this workaround.
- GNU Radio plugin is not fully functional and has serious bugs (frequent segfaults). Trying to repair it is abandonned.
=================== ========================
Done since the fork Changes from SDRangelove
=================== ========================
- Added ppm correction for the LO of RTL-SDR. This uses the corresponding function in the librtlsdr interface (range -99..99 ppm) - Added ppm correction for the LO of RTL-SDR. This uses the corresponding function in the librtlsdr interface (range -99..99 ppm)
- Added a preset update button (the diskette with the yellow corner) to be able to save the current settings on an existing preset - Added a preset update button (the diskette with the yellow corner) to be able to save the current settings on an existing preset
@ -129,7 +134,7 @@ Done since the fork
- Coarse and fine trigger level sliders - Coarse and fine trigger level sliders
- Minimalist recording (no file choice) - Minimalist recording (no file choice)
- File sample source plugin (recording reader) not working - File sample source plugin (recording reader) not working
- Redesign: - Major redesign:
- Make the DSP engine global static - Make the DSP engine global static
- Fixed startup initialization sequence. New initialization phase in DSP engine and new ready state - Fixed startup initialization sequence. New initialization phase in DSP engine and new ready state
- Synchronous messaging class to push message to thread and wait for completion - Synchronous messaging class to push message to thread and wait for completion

BIN
doc/img/sdrangel_banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

View File

Before

Width:  |  Height:  |  Size: 496 KiB

After

Width:  |  Height:  |  Size: 496 KiB

View File

@ -1,47 +0,0 @@
project(nfm)
set(nfm_SOURCES
nfmdemod.cpp
nfmdemodgui.cpp
nfmplugin.cpp
)
set(nfm_HEADERS
nfmdemod.h
nfmdemodgui.h
nfmplugin.h
)
set(nfm_FORMS
nfmdemodgui.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(nfm_HEADERS_MOC ${nfm_HEADERS})
qt5_wrap_ui(nfm_FORMS_HEADERS ${nfm_FORMS})
add_library(demodnfm SHARED
${nfm_SOURCES}
${nfm_HEADERS_MOC}
${nfm_FORMS_HEADERS}
)
target_link_libraries(demodnfm
${QT_LIBRARIES}
${OPENGL_LIBRARIES}
sdrbase
)
qt5_use_modules(demodnfm Core Widgets OpenGL Multimedia)

View File

@ -1,156 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////
// 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 "nfmdemod.h"
#include "audio/audiooutput.h"
#include "dsp/dspcommands.h"
MESSAGE_CLASS_DEFINITION(NFMDemod::MsgConfigureNFMDemod, Message)
NFMDemod::NFMDemod(AudioFifo* audioFifo, SampleSink* sampleSink) :
m_sampleSink(sampleSink),
m_audioFifo(audioFifo)
{
m_rfBandwidth = 12500;
m_volume = 2.0;
m_squelchLevel = pow(10.0, -40.0 / 10.0);
m_sampleRate = 500000;
m_frequency = 0;
m_scale = 0;
m_framedrop = 0;
m_nco.setFreq(m_frequency, m_sampleRate);
m_interpolator.create(16, m_sampleRate, 12500);
m_sampleDistanceRemain = (Real)m_sampleRate / 48000.0;
m_lowpass.create(21, 48000, 3000);
m_audioBuffer.resize(256);
m_audioBufferFill = 0;
m_movingAverage.resize(16, 0);
}
NFMDemod::~NFMDemod()
{
}
void NFMDemod::configure(MessageQueue* messageQueue, Real rfBandwidth, Real afBandwidth, Real volume, Real squelch)
{
Message* cmd = MsgConfigureNFMDemod::create(rfBandwidth, afBandwidth, volume, squelch);
cmd->submit(messageQueue, this);
}
void NFMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
{
Complex ci;
qint16 sample;
Real a, b, s, demod;
double meansqr = 1.0;
for(SampleVector::const_iterator it = begin; it < end; ++it) {
Complex c(it->real() / 32768.0, it->imag() / 32768.0);
c *= m_nco.nextIQ();
if(m_interpolator.interpolate(&m_sampleDistanceRemain, c, &ci)) {
s = ci.real() * ci.real() + ci.imag() * ci.imag();
meansqr += s;
m_movingAverage.feed(s);
if(m_movingAverage.average() >= m_squelchLevel)
m_squelchState = m_sampleRate / 50;
a = m_scale * m_this.real() * (m_last.imag() - ci.imag());
b = m_scale * m_this.imag() * (m_last.real() - ci.real());
m_last = m_this;
m_this = Complex(ci.real(), ci.imag());
demod = m_volume * m_lowpass.filter(b - a);
sample = demod * 30000;
// Display audio spectrum to 12kHz
if (++m_framedrop & 1)
m_sampleBuffer.push_back(Sample(sample, sample));
if(m_squelchState > 0)
m_squelchState--;
else
sample = 0;
{
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();
// TODO: correct levels
m_scale = ( end - begin) * m_sampleRate / 48000 / meansqr;
}
void NFMDemod::start()
{
m_squelchState = 0;
}
void NFMDemod::stop()
{
}
bool NFMDemod::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_nco.setFreq(-signal->getFrequencyOffset(), m_sampleRate);
m_interpolator.create(16, m_sampleRate, m_rfBandwidth / 2.1);
m_sampleDistanceRemain = m_sampleRate / 48000.0;
m_squelchState = 0;
cmd->completed();
return true;
} else if(MsgConfigureNFMDemod::match(cmd)) {
MsgConfigureNFMDemod* cfg = (MsgConfigureNFMDemod*)cmd;
m_rfBandwidth = cfg->getRFBandwidth();
m_interpolator.create(16, m_sampleRate, m_rfBandwidth / 2.1);
m_lowpass.create(21, 48000, cfg->getAFBandwidth());
m_squelchLevel = pow(10.0, cfg->getSquelch() / 10.0);
m_volume = cfg->getVolume();
cmd->completed();
return true;
} else {
if(m_sampleSink != NULL)
return m_sampleSink->handleMessage(cmd);
else return false;
}
}

View File

@ -1,106 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////
// 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_NFMDEMOD_H
#define INCLUDE_NFMDEMOD_H
#include <vector>
#include "dsp/samplesink.h"
#include "dsp/nco.h"
#include "dsp/interpolator.h"
#include "dsp/lowpass.h"
#include "dsp/movingaverage.h"
#include "audio/audiofifo.h"
#include "util/message.h"
class AudioFifo;
class NFMDemod : public SampleSink {
public:
NFMDemod(AudioFifo* audioFifo, SampleSink* sampleSink);
~NFMDemod();
void configure(MessageQueue* messageQueue, Real rfBandwidth, Real afBandwidth, Real volume, Real squelch);
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
void start();
void stop();
bool handleMessage(Message* cmd);
private:
class MsgConfigureNFMDemod : public Message {
MESSAGE_CLASS_DECLARATION
public:
Real getRFBandwidth() const { return m_rfBandwidth; }
Real getAFBandwidth() const { return m_afBandwidth; }
Real getVolume() const { return m_volume; }
Real getSquelch() const { return m_squelch; }
static MsgConfigureNFMDemod* create(Real rfBandwidth, Real afBandwidth, Real volume, Real squelch)
{
return new MsgConfigureNFMDemod(rfBandwidth, afBandwidth, volume, squelch);
}
private:
Real m_rfBandwidth;
Real m_afBandwidth;
Real m_volume;
Real m_squelch;
MsgConfigureNFMDemod(Real rfBandwidth, Real afBandwidth, Real volume, Real squelch) :
Message(),
m_rfBandwidth(rfBandwidth),
m_afBandwidth(afBandwidth),
m_volume(volume),
m_squelch(squelch)
{ }
};
struct AudioSample {
qint16 l;
qint16 r;
};
typedef std::vector<AudioSample> AudioVector;
Real m_rfBandwidth;
Real m_volume;
Real m_squelchLevel;
int m_sampleRate;
int m_frequency;
NCO m_nco;
Interpolator m_interpolator;
Real m_sampleDistanceRemain;
Lowpass<Real> m_lowpass;
int m_squelchState;
int m_framedrop;
double m_scale;
Complex m_last, m_this;
MovingAverage m_movingAverage;
AudioVector m_audioBuffer;
uint m_audioBufferFill;
SampleSink* m_sampleSink;
SampleVector m_sampleBuffer;
AudioFifo* m_audioFifo;
};
#endif // INCLUDE_NFMDEMOD_H

View File

@ -1,210 +0,0 @@
#include <QDockWidget>
#include <QMainWindow>
#include "nfmdemodgui.h"
#include "ui_nfmdemodgui.h"
#include "nfmdemodgui.h"
#include "ui_nfmdemodgui.h"
#include "dsp/threadedsamplesink.h"
#include "dsp/channelizer.h"
#include "nfmdemod.h"
#include "dsp/spectrumvis.h"
#include "gui/glspectrum.h"
#include "plugin/pluginapi.h"
#include "util/simpleserializer.h"
#include "gui/basicchannelsettingswidget.h"
const int NFMDemodGUI::m_rfBW[] = {
5000, 6250, 8330, 10000, 12500, 15000, 20000, 25000, 40000
};
NFMDemodGUI* NFMDemodGUI::create(PluginAPI* pluginAPI)
{
NFMDemodGUI* gui = new NFMDemodGUI(pluginAPI);
return gui;
}
void NFMDemodGUI::destroy()
{
delete this;
}
void NFMDemodGUI::setName(const QString& name)
{
setObjectName(name);
}
void NFMDemodGUI::resetToDefaults()
{
ui->rfBW->setValue(4);
ui->afBW->setValue(3);
ui->volume->setValue(20);
ui->squelch->setValue(-40);
ui->spectrumGUI->resetToDefaults();
applySettings();
}
QByteArray NFMDemodGUI::serialize() const
{
SimpleSerializer s(1);
s.writeS32(1, m_channelMarker->getCenterFrequency());
s.writeS32(2, ui->rfBW->value());
s.writeS32(3, ui->afBW->value());
s.writeS32(4, ui->volume->value());
s.writeS32(5, ui->squelch->value());
s.writeBlob(6, ui->spectrumGUI->serialize());
s.writeU32(7, m_channelMarker->getColor().rgb());
return s.final();
}
bool NFMDemodGUI::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, 4);
ui->rfBW->setValue(tmp);
d.readS32(3, &tmp, 3);
ui->afBW->setValue(tmp);
d.readS32(4, &tmp, 20);
ui->volume->setValue(tmp);
d.readS32(5, &tmp, -40);
ui->squelch->setValue(tmp);
d.readBlob(6, &bytetmp);
ui->spectrumGUI->deserialize(bytetmp);
if(d.readU32(7, &u32tmp))
m_channelMarker->setColor(u32tmp);
applySettings();
return true;
} else {
resetToDefaults();
return false;
}
}
bool NFMDemodGUI::handleMessage(Message* message)
{
return false;
}
void NFMDemodGUI::viewChanged()
{
applySettings();
}
void NFMDemodGUI::on_rfBW_valueChanged(int value)
{
ui->rfBWText->setText(QString("%1 kHz").arg(m_rfBW[value] / 1000.0));
m_channelMarker->setBandwidth(m_rfBW[value]);
applySettings();
}
void NFMDemodGUI::on_afBW_valueChanged(int value)
{
ui->afBWText->setText(QString("%1 kHz").arg(value));
applySettings();
}
void NFMDemodGUI::on_volume_valueChanged(int value)
{
ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
applySettings();
}
void NFMDemodGUI::on_squelch_valueChanged(int value)
{
ui->squelchText->setText(QString("%1 dB").arg(value));
applySettings();
}
void NFMDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
/*
if((widget == ui->spectrumContainer) && (m_nfmDemod != NULL))
m_nfmDemod->setSpectrum(m_threadedSampleSink->getMessageQueue(), rollDown);
*/
}
void NFMDemodGUI::onMenuDoubleClicked()
{
if(!m_basicSettingsShown) {
m_basicSettingsShown = true;
BasicChannelSettingsWidget* bcsw = new BasicChannelSettingsWidget(m_channelMarker, this);
bcsw->show();
}
}
NFMDemodGUI::NFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
RollupWidget(parent),
ui(new Ui::NFMDemodGUI),
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_nfmDemod = new NFMDemod(m_audioFifo, m_spectrumVis);
m_channelizer = new Channelizer(m_nfmDemod);
m_threadedSampleSink = new ThreadedSampleSink(m_channelizer);
m_pluginAPI->addAudioSource(m_audioFifo);
m_pluginAPI->addSampleSink(m_threadedSampleSink);
ui->glSpectrum->setCenterFrequency(6000);
ui->glSpectrum->setSampleRate(12000);
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(12500);
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();
}
NFMDemodGUI::~NFMDemodGUI()
{
m_pluginAPI->removeChannelInstance(this);
m_pluginAPI->removeAudioSource(m_audioFifo);
m_pluginAPI->removeSampleSink(m_threadedSampleSink);
delete m_threadedSampleSink;
delete m_channelizer;
delete m_nfmDemod;
delete m_spectrumVis;
delete m_audioFifo;
delete m_channelMarker;
delete ui;
}
void NFMDemodGUI::applySettings()
{
setTitleColor(m_channelMarker->getColor());
m_channelizer->configure(m_threadedSampleSink->getMessageQueue(),
48000,
m_channelMarker->getCenterFrequency());
m_nfmDemod->configure(m_threadedSampleSink->getMessageQueue(),
m_rfBW[ui->rfBW->value()],
ui->afBW->value() * 1000.0,
ui->volume->value() / 10.0,
ui->squelch->value());
}

View File

@ -1,64 +0,0 @@
#ifndef INCLUDE_NFMDEMODGUI_H
#define INCLUDE_NFMDEMODGUI_H
#include "gui/rollupwidget.h"
#include "plugin/plugingui.h"
class PluginAPI;
class ChannelMarker;
class AudioFifo;
class ThreadedSampleSink;
class Channelizer;
class NFMDemod;
class SpectrumVis;
namespace Ui {
class NFMDemodGUI;
}
class NFMDemodGUI : public RollupWidget, public PluginGUI {
Q_OBJECT
public:
static NFMDemodGUI* 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_rfBW_valueChanged(int value);
void on_afBW_valueChanged(int value);
void on_volume_valueChanged(int value);
void on_squelch_valueChanged(int value);
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDoubleClicked();
private:
Ui::NFMDemodGUI* ui;
PluginAPI* m_pluginAPI;
ChannelMarker* m_channelMarker;
bool m_basicSettingsShown;
AudioFifo* m_audioFifo;
ThreadedSampleSink* m_threadedSampleSink;
Channelizer* m_channelizer;
NFMDemod* m_nfmDemod;
SpectrumVis* m_spectrumVis;
static const int m_rfBW[];
explicit NFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent = NULL);
~NFMDemodGUI();
void applySettings();
};
#endif // INCLUDE_NFMDEMODGUI_H

View File

@ -1,250 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>NFMDemodGUI</class>
<widget class="RollupWidget" name="NFMDemodGUI">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>302</width>
<height>410</height>
</rect>
</property>
<property name="windowTitle">
<string>NFM 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">
<property name="text">
<string>RF Bandwidth</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSlider" name="rfBW">
<property name="maximum">
<number>8</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="value">
<number>4</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="rfBWText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>12.5kHz</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_2">
<property name="text">
<string>AF Bandwidth</string>
</property>
</widget>
</item>
<item row="1" 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="1" column="2">
<widget class="QLabel" name="afBWText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>3 kHz</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Volume</string>
</property>
</widget>
</item>
<item row="2" 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="2" 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>
<item row="3" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Squelch</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QSlider" name="squelch">
<property name="minimum">
<number>-100</number>
</property>
<property name="maximum">
<number>0</number>
</property>
<property name="value">
<number>-40</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="squelchText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>-40dB</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>

View File

@ -1,53 +0,0 @@
#include <QtPlugin>
#include <QAction>
#include "plugin/pluginapi.h"
#include "nfmplugin.h"
#include "nfmdemodgui.h"
const PluginDescriptor NFMPlugin::m_pluginDescriptor = {
QString("NFM Demodulator"),
QString("---"),
QString("(c) maintech GmbH (written by Christian Daniel)"),
QString("http://www.maintech.de"),
true,
QString("http://www.maintech.de")
};
NFMPlugin::NFMPlugin(QObject* parent) :
QObject(parent)
{
}
const PluginDescriptor& NFMPlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void NFMPlugin::initPlugin(PluginAPI* pluginAPI)
{
m_pluginAPI = pluginAPI;
// register NFM demodulator
QAction* action = new QAction(tr("&NFM Demodulator"), this);
connect(action, SIGNAL(triggered()), this, SLOT(createInstanceNFM()));
m_pluginAPI->registerChannel("de.maintech.sdrangelove.channel.nfm", this, action);
}
PluginGUI* NFMPlugin::createChannel(const QString& channelName)
{
if(channelName == "de.maintech.sdrangelove.channel.nfm") {
NFMDemodGUI* gui = NFMDemodGUI::create(m_pluginAPI);
m_pluginAPI->registerChannelInstance("de.maintech.sdrangelove.channel.nfm", gui);
m_pluginAPI->addChannelRollup(gui);
return gui;
} else {
return NULL;
}
}
void NFMPlugin::createInstanceNFM()
{
NFMDemodGUI* gui = NFMDemodGUI::create(m_pluginAPI);
m_pluginAPI->registerChannelInstance("de.maintech.sdrangelove.channel.nfm", gui);
m_pluginAPI->addChannelRollup(gui);
}

View File

@ -1,29 +0,0 @@
#ifndef INCLUDE_NFMPLUGIN_H
#define INCLUDE_NFMPLUGIN_H
#include <QObject>
#include "plugin/plugininterface.h"
class NFMPlugin : public QObject, PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID "de.maintech.sdrangelove.channel.nfm")
public:
explicit NFMPlugin(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 createInstanceNFM();
};
#endif // INCLUDE_NFMPLUGIN_H

View File

@ -1,47 +0,0 @@
project(usb)
set(usb_SOURCES
usbdemod.cpp
usbdemodgui.cpp
usbplugin.cpp
)
set(usb_HEADERS
usbdemod.h
usbdemodgui.h
usbplugin.h
)
set(usb_FORMS
usbdemodgui.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(usb_HEADERS_MOC ${usb_HEADERS})
qt5_wrap_ui(usb_FORMS_HEADERS ${usb_FORMS})
add_library(demodusb SHARED
${usb_SOURCES}
${usb_HEADERS_MOC}
${usb_FORMS_HEADERS}
)
target_link_libraries(demodusb
${QT_LIBRARIES}
${OPENGL_LIBRARIES}
sdrbase
)
qt5_use_modules(demodusb Core Widgets OpenGL Multimedia)

View File

@ -1,158 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
// written by Christian Daniel //
// (c) 2014 Modified by John Greb
// //
// 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 "usbdemod.h"
#include "audio/audiooutput.h"
#include "dsp/dspcommands.h"
MESSAGE_CLASS_DEFINITION(USBDemod::MsgConfigureUSBDemod, Message)
USBDemod::USBDemod(AudioFifo* audioFifo, SampleSink* sampleSink) :
m_sampleSink(sampleSink),
m_audioFifo(audioFifo)
{
m_Bandwidth = 5000;
m_volume = 2.0;
m_sampleRate = 96000;
m_frequency = 0;
m_audioBuffer.resize(512);
m_audioBufferFill = 0;
m_undersampleCount = 0;
m_i = 0;
USBFilter = new fftfilt(0.01, m_Bandwidth / 96000.0, USBFFTLEN);
// if (!USBFilter) segfault;
}
USBDemod::~USBDemod()
{
if (USBFilter) delete USBFilter;
}
void USBDemod::configure(MessageQueue* messageQueue, Real Bandwidth, Real volume)
{
Message* cmd = MsgConfigureUSBDemod::create(Bandwidth, volume);
cmd->submit(messageQueue, this);
}
/* Fractional Downsample to 48 kHz.
* 192 1:4 (3072 / 16)
* 144 1:3 (1152 / 8)
* 96 1:2 (1536 / 16)
* 72 2:3 ( 288 / 4)
* 64 3:4 (1024 / 16)
* For Arbritrary resample use ssb demodulator */
double rerate(int rate)
{
switch (rate)
{
case 64000 : return (3.0 * 64000); break;
case 72000 : return (2.0 * 72000); break;
case 0 : return (1.0 ) ; break;
default : return (1.0 * rate ); break;
}
}
void USBDemod::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
{
Real a, b;
Complex c;
int i, n_out;
cmplx *sideband;
int samplestep = 2;
if ((m_sampleRate == 72000)||(m_sampleRate == 144000))
samplestep = 3;
if ((m_sampleRate == 64000)||(m_sampleRate == 192000))
samplestep = 4;
for(SampleVector::const_iterator it = begin; it < end; it ++) {
a = it->real();
b = it->imag();
c = Complex(a / 65536.0, b / 65536.0);
n_out = USBFilter->runSSB(c, &sideband, true);
if (m_sampleRate <= 72000)
n_out += USBFilter->runSSB(c, &sideband, true);
if (m_sampleRate == 64000)
n_out += USBFilter->runSSB(c, &sideband, true);
for (i = m_i ; i < n_out; i += samplestep) {
Real demod = (sideband[i].real() + sideband[i].imag()) * 32768.0;
// Downsample by 4x for audio display
if (!(m_undersampleCount++ & 3))
m_sampleBuffer.push_back(Sample(demod, 0.0));
qint16 sample = (qint16)(demod * m_volume);
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_i = i - n_out;
}
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 USBDemod::start()
{
}
void USBDemod::stop()
{
}
bool USBDemod::handleMessage(Message* cmd)
{
double rate;
if(DSPSignalNotification::match(cmd)) {
DSPSignalNotification* signal = (DSPSignalNotification*)cmd;
m_sampleRate = signal->getSampleRate();
rate = rerate(m_sampleRate);
USBFilter->create_filter(300.0 / rate, (double)m_Bandwidth / rate);
cmd->completed();
return true;
} else if(MsgConfigureUSBDemod::match(cmd)) {
MsgConfigureUSBDemod* cfg = (MsgConfigureUSBDemod*)cmd;
m_Bandwidth = cfg->getBandwidth();
rate = rerate(m_sampleRate);
USBFilter->create_filter(300.0 / rate, (double)m_Bandwidth / rate);
m_volume = cfg->getVolume();
m_volume *= m_volume * 0.1;
cmd->completed();
return true;
} else {
if(m_sampleSink != NULL)
return m_sampleSink->handleMessage(cmd);
else return false;
}
}

View File

@ -1,91 +0,0 @@
///////////////////////////////////////////////////////////////////////////////////
// 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_USBDEMOD_H
#define INCLUDE_USBDEMOD_H
#include <vector>
#include "dsp/samplesink.h"
#include "dsp/nco.h"
#include "dsp/interpolator.h"
#include "dsp/fftfilt.h"
#include "audio/audiofifo.h"
#include "util/message.h"
#define USBFFTLEN 2048
class AudioFifo;
class USBDemod : public SampleSink {
public:
USBDemod(AudioFifo* audioFifo, SampleSink* sampleSink);
~USBDemod();
void configure(MessageQueue* messageQueue, Real Bandwidth, Real volume);
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
void start();
void stop();
bool handleMessage(Message* cmd);
private:
class MsgConfigureUSBDemod : public Message {
MESSAGE_CLASS_DECLARATION
public:
Real getBandwidth() const { return m_Bandwidth; }
Real getVolume() const { return m_volume; }
static MsgConfigureUSBDemod* create(Real Bandwidth, Real volume)
{
return new MsgConfigureUSBDemod(Bandwidth, volume);
}
private:
Real m_Bandwidth;
Real m_volume;
MsgConfigureUSBDemod(Real Bandwidth, Real volume) :
Message(),
m_Bandwidth(Bandwidth),
m_volume(volume)
{ }
};
struct AudioSample {
qint16 l;
qint16 r;
};
typedef std::vector<AudioSample> AudioVector;
Real m_Bandwidth;
Real m_volume;
int m_undersampleCount;
int m_sampleRate;
int m_frequency;
int m_i;
AudioVector m_audioBuffer;
uint m_audioBufferFill;
fftfilt* USBFilter;
SampleSink* m_sampleSink;
SampleVector m_sampleBuffer;
AudioFifo* m_audioFifo;
};
#endif // INCLUDE_USBDEMOD_H

View File

@ -1,180 +0,0 @@
#include <QDockWidget>
#include <QMainWindow>
#include "usbdemodgui.h"
#include "ui_usbdemodgui.h"
#include "dsp/threadedsamplesink.h"
#include "dsp/channelizer.h"
#include "usbdemod.h"
#include "dsp/spectrumvis.h"
#include "gui/glspectrum.h"
#include "plugin/pluginapi.h"
#include "util/simpleserializer.h"
#include "gui/basicchannelsettingswidget.h"
USBDemodGUI* USBDemodGUI::create(PluginAPI* pluginAPI)
{
USBDemodGUI* gui = new USBDemodGUI(pluginAPI);
return gui;
}
void USBDemodGUI::destroy()
{
delete this;
}
void USBDemodGUI::setName(const QString& name)
{
setObjectName(name);
}
void USBDemodGUI::resetToDefaults()
{
ui->BW->setValue(3);
ui->volume->setValue(4);
applySettings();
}
QByteArray USBDemodGUI::serialize() const
{
SimpleSerializer s(1);
s.writeS32(1, m_channelMarker->getCenterFrequency());
s.writeS32(2, ui->BW->value());
s.writeS32(3, ui->volume->value());
s.writeBlob(4, ui->spectrumGUI->serialize());
s.writeU32(5, m_channelMarker->getColor().rgb());
return s.final();
}
bool USBDemodGUI::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, 3);
ui->BW->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 USBDemodGUI::handleMessage(Message* message)
{
return false;
}
void USBDemodGUI::viewChanged()
{
applySettings();
}
void USBDemodGUI::on_BW_valueChanged(int value)
{
ui->BWText->setText(QString("%1 kHz").arg(value));
m_channelMarker->setBandwidth(value * 1000);
m_channelMarker->setCenterFrequency(value * 500);
applySettings();
}
void USBDemodGUI::on_volume_valueChanged(int value)
{
ui->volumeText->setText(QString("%1").arg(value / 10.0, 0, 'f', 1));
applySettings();
}
void USBDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
/*
if((widget == ui->spectrumContainer) && (m_usbDemod != NULL))
m_usbDemod->setSpectrum(m_threadedSampleSink->getMessageQueue(), rollDown);
*/
}
void USBDemodGUI::onMenuDoubleClicked()
{
if(!m_basicSettingsShown) {
m_basicSettingsShown = true;
BasicChannelSettingsWidget* bcsw = new BasicChannelSettingsWidget(m_channelMarker, this);
bcsw->show();
}
}
USBDemodGUI::USBDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
RollupWidget(parent),
ui(new Ui::USBDemodGUI),
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_usbDemod = new USBDemod(m_audioFifo, m_spectrumVis);
m_channelizer = new Channelizer(m_usbDemod);
m_threadedSampleSink = new ThreadedSampleSink(m_channelizer);
m_pluginAPI->addAudioSource(m_audioFifo);
m_pluginAPI->addSampleSink(m_threadedSampleSink);
ui->glSpectrum->setCenterFrequency(3000);
ui->glSpectrum->setSampleRate(6000);
ui->glSpectrum->setDisplayWaterfall(true);
ui->glSpectrum->setDisplayMaxHold(true);
m_channelMarker = new ChannelMarker(this);
m_channelMarker->setColor(Qt::blue);
m_channelMarker->setBandwidth(5000);
m_channelMarker->setCenterFrequency(2500);
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();
}
USBDemodGUI::~USBDemodGUI()
{
m_pluginAPI->removeChannelInstance(this);
m_pluginAPI->removeAudioSource(m_audioFifo);
m_pluginAPI->removeSampleSink(m_threadedSampleSink);
delete m_threadedSampleSink;
delete m_channelizer;
delete m_usbDemod;
delete m_spectrumVis;
delete m_audioFifo;
delete m_channelMarker;
delete ui;
}
void USBDemodGUI::applySettings()
{
setTitleColor(m_channelMarker->getColor());
m_channelizer->configure(m_threadedSampleSink->getMessageQueue(),
48000,
m_channelMarker->getCenterFrequency());
m_usbDemod->configure(m_threadedSampleSink->getMessageQueue(),
ui->BW->value() * 1000.0,
ui->volume->value() / 10.0 );
}

View File

@ -1,60 +0,0 @@
#ifndef INCLUDE_USBDEMODGUI_H
#define INCLUDE_USBDEMODGUI_H
#include "gui/rollupwidget.h"
#include "plugin/plugingui.h"
class PluginAPI;
class ChannelMarker;
class AudioFifo;
class ThreadedSampleSink;
class Channelizer;
class USBDemod;
class SpectrumVis;
namespace Ui {
class USBDemodGUI;
}
class USBDemodGUI : public RollupWidget, public PluginGUI {
Q_OBJECT
public:
static USBDemodGUI* 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_BW_valueChanged(int value);
void on_volume_valueChanged(int value);
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDoubleClicked();
private:
Ui::USBDemodGUI* ui;
PluginAPI* m_pluginAPI;
ChannelMarker* m_channelMarker;
bool m_basicSettingsShown;
AudioFifo* m_audioFifo;
ThreadedSampleSink* m_threadedSampleSink;
Channelizer* m_channelizer;
USBDemod* m_usbDemod;
SpectrumVis* m_spectrumVis;
explicit USBDemodGUI(PluginAPI* pluginAPI, QWidget* parent = NULL);
~USBDemodGUI();
void applySettings();
};
#endif // INCLUDE_USBDEMODGUI_H

View File

@ -1,172 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>USBDemodGUI</class>
<widget class="RollupWidget" name="USBDemodGUI">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>302</width>
<height>410</height>
</rect>
</property>
<property name="windowTitle">
<string>USB 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">
<property name="text">
<string>Bandwidth</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QSlider" name="BW">
<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="BWText">
<property name="minimumSize">
<size>
<width>50</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>3 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_2">
<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>

View File

@ -1,53 +0,0 @@
#include <QtPlugin>
#include <QAction>
#include "plugin/pluginapi.h"
#include "usbplugin.h"
#include "usbdemodgui.h"
const PluginDescriptor USBPlugin::m_pluginDescriptor = {
QString("USB Demodulator"),
QString("0.1"),
QString("(c) 2014 John Greb"),
QString("http://www.maintech.de"),
true,
QString("github.com/hexameron/rtl-sdrangelove")
};
USBPlugin::USBPlugin(QObject* parent) :
QObject(parent)
{
}
const PluginDescriptor& USBPlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void USBPlugin::initPlugin(PluginAPI* pluginAPI)
{
m_pluginAPI = pluginAPI;
// register demodulator
QAction* action = new QAction(tr("&USB Demodulator"), this);
connect(action, SIGNAL(triggered()), this, SLOT(createInstanceUSB()));
m_pluginAPI->registerChannel("de.maintech.sdrangelove.channel.usb", this, action);
}
PluginGUI* USBPlugin::createChannel(const QString& channelName)
{
if(channelName == "de.maintech.sdrangelove.channel.usb") {
USBDemodGUI* gui = USBDemodGUI::create(m_pluginAPI);
m_pluginAPI->registerChannelInstance("de.maintech.sdrangelove.channel.usb", gui);
m_pluginAPI->addChannelRollup(gui);
return gui;
} else {
return NULL;
}
}
void USBPlugin::createInstanceUSB()
{
USBDemodGUI* gui = USBDemodGUI::create(m_pluginAPI);
m_pluginAPI->registerChannelInstance("de.maintech.sdrangelove.channel.usb", gui);
m_pluginAPI->addChannelRollup(gui);
}

View File

@ -1,29 +0,0 @@
#ifndef INCLUDE_USBPLUGIN_H
#define INCLUDE_USBPLUGIN_H
#include <QObject>
#include "plugin/plugininterface.h"
class USBPlugin : public QObject, PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID "de.maintech.sdrangelove.channel.usb")
public:
explicit USBPlugin(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 createInstanceUSB();
};
#endif // INCLUDE_USBPLUGIN_H

View File

@ -5,12 +5,12 @@ find_package(LibUSB)
if(V4L-RTL) if(V4L-RTL)
FIND_LIBRARY (LIBV4L2 v4l2) FIND_LIBRARY (LIBV4L2 v4l2)
FIND_PATH (LIBV4L2H libv4l2.h) FIND_PATH (LIBV4L2H libv4l2.h)
add_subdirectory(v4l-rtl) # add_subdirectory(v4l-rtl)
endif() endif()
if(V4L-MSI) if(V4L-MSI)
FIND_LIBRARY (LIBV4L2 v4l2) FIND_LIBRARY (LIBV4L2 v4l2)
FIND_PATH (LIBV4L2H libv4l2.h) FIND_PATH (LIBV4L2H libv4l2.h)
add_subdirectory(v4l-msi) # add_subdirectory(v4l-msi)
endif() endif()
if(LIBUSB_FOUND AND UNIX) if(LIBUSB_FOUND AND UNIX)