mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-22 16:08:39 -05:00
Deep redesign: Better support for FCD dongles #6: have two distinct plugins for Pro and Pro+. Only Pro+ is active at the moment
This commit is contained in:
parent
410b6d15c0
commit
5453d63431
@ -18,7 +18,7 @@ if(LIBUSB_FOUND AND UNIX)
|
|||||||
FIND_LIBRARY (LIBASOUND asound)
|
FIND_LIBRARY (LIBASOUND asound)
|
||||||
endif()
|
endif()
|
||||||
if(LIBASOUND AND ASOUNDH)
|
if(LIBASOUND AND ASOUNDH)
|
||||||
add_subdirectory(fcdpro)
|
add_subdirectory(fcdproplus)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(LibRTLSDR)
|
find_package(LibRTLSDR)
|
||||||
|
@ -206,8 +206,6 @@ void BladerfInput::stop()
|
|||||||
bladerf_close(m_dev);
|
bladerf_close(m_dev);
|
||||||
m_dev = 0;
|
m_dev = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_deviceDescription.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString& BladerfInput::getDeviceDescription() const
|
const QString& BladerfInput::getDeviceDescription() const
|
||||||
|
@ -1,23 +1,23 @@
|
|||||||
project(fcdpro)
|
project(fcdpro)
|
||||||
|
|
||||||
set(fcdpro_SOURCES
|
set(fcdpro_SOURCES
|
||||||
fcdgui.cpp
|
fcdprogui.cpp
|
||||||
fcdinput.cpp
|
fcdproinput.cpp
|
||||||
fcdplugin.cpp
|
fcdproplugin.cpp
|
||||||
fcdserializer.cpp
|
fcdproserializer.cpp
|
||||||
fcdthread.cpp
|
fcdprothread.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(fcdpro_HEADERS
|
set(fcdpro_HEADERS
|
||||||
fcdgui.h
|
fcdprogui.h
|
||||||
fcdinput.h
|
fcdproinput.h
|
||||||
fcdplugin.h
|
fcdproplugin.h
|
||||||
fcdserializer.h
|
fcdproserializer.h
|
||||||
fcdthread.h
|
fcdprothread.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(fcdpro_FORMS
|
set(fcdpro_FORMS
|
||||||
fcdgui.ui
|
fcdprogui.ui
|
||||||
)
|
)
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
#include "fcdgui.h"
|
#include "ui_fcdprogui.h"
|
||||||
#include "ui_fcdgui.h"
|
|
||||||
#include "plugin/pluginapi.h"
|
#include "plugin/pluginapi.h"
|
||||||
#include "gui/colormapper.h"
|
#include "gui/colormapper.h"
|
||||||
#include "dsp/dspengine.h"
|
#include "dsp/dspengine.h"
|
||||||
|
#include "fcdprogui.h"
|
||||||
|
|
||||||
FCDGui::FCDGui(PluginAPI* pluginAPI, QWidget* parent) :
|
FCDProGui::FCDProGui(PluginAPI* pluginAPI, QWidget* parent) :
|
||||||
QWidget(parent),
|
QWidget(parent),
|
||||||
ui(new Ui::FCDGui),
|
ui(new Ui::FCDProGui),
|
||||||
m_pluginAPI(pluginAPI),
|
m_pluginAPI(pluginAPI),
|
||||||
m_settings(),
|
m_settings(),
|
||||||
m_sampleSource(NULL)
|
m_sampleSource(NULL)
|
||||||
@ -17,48 +17,48 @@ FCDGui::FCDGui(PluginAPI* pluginAPI, QWidget* parent) :
|
|||||||
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
|
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
|
||||||
displaySettings();
|
displaySettings();
|
||||||
|
|
||||||
m_sampleSource = new FCDInput();
|
m_sampleSource = new FCDProInput();
|
||||||
DSPEngine::instance()->setSource(m_sampleSource);
|
DSPEngine::instance()->setSource(m_sampleSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
FCDGui::~FCDGui()
|
FCDProGui::~FCDProGui()
|
||||||
{
|
{
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDGui::destroy()
|
void FCDProGui::destroy()
|
||||||
{
|
{
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDGui::setName(const QString& name)
|
void FCDProGui::setName(const QString& name)
|
||||||
{
|
{
|
||||||
setObjectName(name);
|
setObjectName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString FCDGui::getName() const
|
QString FCDProGui::getName() const
|
||||||
{
|
{
|
||||||
return objectName();
|
return objectName();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDGui::resetToDefaults()
|
void FCDProGui::resetToDefaults()
|
||||||
{
|
{
|
||||||
m_settings.resetToDefaults();
|
m_settings.resetToDefaults();
|
||||||
displaySettings();
|
displaySettings();
|
||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 FCDGui::getCenterFrequency() const
|
qint64 FCDProGui::getCenterFrequency() const
|
||||||
{
|
{
|
||||||
return m_settings.centerFrequency;
|
return m_settings.centerFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray FCDGui::serialize() const
|
QByteArray FCDProGui::serialize() const
|
||||||
{
|
{
|
||||||
return m_settings.serialize();
|
return m_settings.serialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FCDGui::deserialize(const QByteArray& data)
|
bool FCDProGui::deserialize(const QByteArray& data)
|
||||||
{
|
{
|
||||||
if(m_settings.deserialize(data))
|
if(m_settings.deserialize(data))
|
||||||
{
|
{
|
||||||
@ -73,12 +73,12 @@ bool FCDGui::deserialize(const QByteArray& data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FCDGui::handleMessage(const Message& message)
|
bool FCDProGui::handleMessage(const Message& message)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDGui::displaySettings()
|
void FCDProGui::displaySettings()
|
||||||
{
|
{
|
||||||
ui->centerFrequency->setValue(m_settings.centerFrequency / 1000);
|
ui->centerFrequency->setValue(m_settings.centerFrequency / 1000);
|
||||||
ui->checkBoxR->setChecked(m_settings.range);
|
ui->checkBoxR->setChecked(m_settings.range);
|
||||||
@ -86,26 +86,26 @@ void FCDGui::displaySettings()
|
|||||||
ui->checkBoxB->setChecked(m_settings.bias);
|
ui->checkBoxB->setChecked(m_settings.bias);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDGui::sendSettings()
|
void FCDProGui::sendSettings()
|
||||||
{
|
{
|
||||||
if(!m_updateTimer.isActive())
|
if(!m_updateTimer.isActive())
|
||||||
m_updateTimer.start(100);
|
m_updateTimer.start(100);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDGui::on_centerFrequency_changed(quint64 value)
|
void FCDProGui::on_centerFrequency_changed(quint64 value)
|
||||||
{
|
{
|
||||||
m_settings.centerFrequency = value * 1000;
|
m_settings.centerFrequency = value * 1000;
|
||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDGui::updateHardware()
|
void FCDProGui::updateHardware()
|
||||||
{
|
{
|
||||||
FCDInput::MsgConfigureFCD* message = FCDInput::MsgConfigureFCD::create(m_settings);
|
FCDProInput::MsgConfigureFCD* message = FCDProInput::MsgConfigureFCD::create(m_settings);
|
||||||
m_sampleSource->getInputMessageQueue()->push(message);
|
m_sampleSource->getInputMessageQueue()->push(message);
|
||||||
m_updateTimer.stop();
|
m_updateTimer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDGui::on_checkBoxR_stateChanged(int state)
|
void FCDProGui::on_checkBoxR_stateChanged(int state)
|
||||||
{
|
{
|
||||||
if (state == Qt::Checked) // FIXME: this is for the Pro+ version only!
|
if (state == Qt::Checked) // FIXME: this is for the Pro+ version only!
|
||||||
{
|
{
|
||||||
@ -125,7 +125,7 @@ void FCDGui::on_checkBoxR_stateChanged(int state)
|
|||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDGui::on_checkBoxG_stateChanged(int state)
|
void FCDProGui::on_checkBoxG_stateChanged(int state)
|
||||||
{
|
{
|
||||||
if (state == Qt::Checked)
|
if (state == Qt::Checked)
|
||||||
{
|
{
|
||||||
@ -139,7 +139,7 @@ void FCDGui::on_checkBoxG_stateChanged(int state)
|
|||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDGui::on_checkBoxB_stateChanged(int state)
|
void FCDProGui::on_checkBoxB_stateChanged(int state)
|
||||||
{
|
{
|
||||||
if (state == Qt::Checked)
|
if (state == Qt::Checked)
|
||||||
{
|
{
|
53
plugins/samplesource/fcdpro/fcdprogui.h
Normal file
53
plugins/samplesource/fcdpro/fcdprogui.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#ifndef INCLUDE_FCDPROGUI_H
|
||||||
|
#define INCLUDE_FCDPROGUI_H
|
||||||
|
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "fcdproinput.h"
|
||||||
|
#include "plugin/plugingui.h"
|
||||||
|
|
||||||
|
class PluginAPI;
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class FCDProGui;
|
||||||
|
}
|
||||||
|
|
||||||
|
class FCDProGui : public QWidget, public PluginGUI {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FCDProGui(PluginAPI* pluginAPI, QWidget* parent = NULL);
|
||||||
|
virtual ~FCDProGui();
|
||||||
|
void destroy();
|
||||||
|
|
||||||
|
void setName(const QString& name);
|
||||||
|
QString getName() const;
|
||||||
|
|
||||||
|
void resetToDefaults();
|
||||||
|
qint64 getCenterFrequency() const;
|
||||||
|
QByteArray serialize() const;
|
||||||
|
bool deserialize(const QByteArray& data);
|
||||||
|
|
||||||
|
virtual bool handleMessage(const Message& message);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::FCDProGui* ui;
|
||||||
|
|
||||||
|
PluginAPI* m_pluginAPI;
|
||||||
|
FCDProInput::Settings m_settings;
|
||||||
|
QTimer m_updateTimer;
|
||||||
|
std::vector<int> m_gains;
|
||||||
|
SampleSource* m_sampleSource;
|
||||||
|
|
||||||
|
void displaySettings();
|
||||||
|
void sendSettings();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_centerFrequency_changed(quint64 value);
|
||||||
|
void on_checkBoxR_stateChanged(int state);
|
||||||
|
void on_checkBoxG_stateChanged(int state);
|
||||||
|
void on_checkBoxB_stateChanged(int state);
|
||||||
|
void updateHardware();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // INCLUDE_FCDPROGUI_H
|
@ -1,12 +1,12 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>FCDGui</class>
|
<class>FCDProGui</class>
|
||||||
<widget class="QWidget" name="FCDGui">
|
<widget class="QWidget" name="FCDProGui">
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>132</width>
|
<width>165</width>
|
||||||
<height>119</height>
|
<height>119</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
289
plugins/samplesource/fcdpro/fcdproinput.cpp
Normal file
289
plugins/samplesource/fcdpro/fcdproinput.cpp
Normal file
@ -0,0 +1,289 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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/>. //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
// FIXME: FCD is handled very badly!
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "dsp/dspcommands.h"
|
||||||
|
#include "fcdproinput.h"
|
||||||
|
|
||||||
|
#include "fcdprogui.h"
|
||||||
|
#include "fcdproserializer.h"
|
||||||
|
#include "fcdprothread.h"
|
||||||
|
|
||||||
|
MESSAGE_CLASS_DEFINITION(FCDProInput::MsgConfigureFCD, Message)
|
||||||
|
|
||||||
|
/*
|
||||||
|
const uint16_t FCDInput::m_vendorId = 0x04D8;
|
||||||
|
const uint16_t FCDInput::m_productId = 0xFB31;
|
||||||
|
const int FCDInput::m_sampleRate = 192000;
|
||||||
|
const std::string FCDInput::m_deviceName("hw:CARD=V20");
|
||||||
|
|
||||||
|
const uint16_t FCDInput::m_productId = 0xFB56;
|
||||||
|
const int FCDInput::m_sampleRate = 96000;
|
||||||
|
const std::string FCDInput::m_deviceName("hw:CARD=V10");
|
||||||
|
*/
|
||||||
|
|
||||||
|
FCDProInput::Settings::Settings() :
|
||||||
|
centerFrequency(435000000),
|
||||||
|
range(0),
|
||||||
|
gain(0),
|
||||||
|
bias(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProInput::Settings::resetToDefaults()
|
||||||
|
{
|
||||||
|
centerFrequency = 435000000;
|
||||||
|
range = 0;
|
||||||
|
gain = 0;
|
||||||
|
bias = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray FCDProInput::Settings::serialize() const
|
||||||
|
{
|
||||||
|
FCDProSerializer::FCDData data;
|
||||||
|
|
||||||
|
data.m_data.m_lnaGain = gain;
|
||||||
|
data.m_data.m_frequency = centerFrequency;
|
||||||
|
data.m_range = range;
|
||||||
|
data.m_bias = bias;
|
||||||
|
|
||||||
|
QByteArray byteArray;
|
||||||
|
|
||||||
|
FCDProSerializer::writeSerializedData(data, byteArray);
|
||||||
|
|
||||||
|
return byteArray;
|
||||||
|
|
||||||
|
/*
|
||||||
|
SimpleSerializer s(1);
|
||||||
|
s.writeU64(1, centerFrequency);
|
||||||
|
s.writeS32(2, range);
|
||||||
|
s.writeS32(3, gain);
|
||||||
|
s.writeS32(4, bias);
|
||||||
|
return s.final();*/
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FCDProInput::Settings::deserialize(const QByteArray& serializedData)
|
||||||
|
{
|
||||||
|
FCDProSerializer::FCDData data;
|
||||||
|
|
||||||
|
bool valid = FCDProSerializer::readSerializedData(serializedData, data);
|
||||||
|
|
||||||
|
gain = data.m_data.m_lnaGain;
|
||||||
|
centerFrequency = data.m_data.m_frequency;
|
||||||
|
range = data.m_range;
|
||||||
|
bias = data.m_bias;
|
||||||
|
|
||||||
|
return valid;
|
||||||
|
|
||||||
|
/*
|
||||||
|
SimpleDeserializer d(data);
|
||||||
|
|
||||||
|
if (d.isValid() && d.getVersion() == 1)
|
||||||
|
{
|
||||||
|
d.readU64(1, ¢erFrequency, 435000000);
|
||||||
|
d.readS32(2, &range, 0);
|
||||||
|
d.readS32(3, &gain, 0);
|
||||||
|
d.readS32(4, &bias, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
resetToDefaults();
|
||||||
|
return true;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
FCDProInput::FCDProInput() :
|
||||||
|
m_dev(0),
|
||||||
|
m_settings(),
|
||||||
|
m_FCDThread(0),
|
||||||
|
m_deviceDescription("Funcube Dongle Pro")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FCDProInput::~FCDProInput()
|
||||||
|
{
|
||||||
|
stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FCDProInput::init(const Message& cmd)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FCDProInput::start(int device)
|
||||||
|
{
|
||||||
|
qDebug() << "FCDProInput::start with device #" << device;
|
||||||
|
|
||||||
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
|
|
||||||
|
if (m_FCDThread)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_dev = fcdOpen(0x04D8, 0xFB56, device);
|
||||||
|
|
||||||
|
if (m_dev == 0)
|
||||||
|
{
|
||||||
|
qCritical("FCDProInput::start: could not open FCD");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Apply settings before streaming to avoid bus contention;
|
||||||
|
* there is very little spare bandwidth on a full speed USB device.
|
||||||
|
* Failure is harmless if no device is found
|
||||||
|
* ... This is rubbish...*/
|
||||||
|
|
||||||
|
//applySettings(m_settings, true);
|
||||||
|
|
||||||
|
if(!m_sampleFifo.setSize(96000*4))
|
||||||
|
{
|
||||||
|
qCritical("Could not allocate SampleFifo");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_FCDThread = new FCDProThread(&m_sampleFifo)) == NULL)
|
||||||
|
{
|
||||||
|
qFatal("out of memory");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_FCDThread->startWork();
|
||||||
|
|
||||||
|
mutexLocker.unlock();
|
||||||
|
applySettings(m_settings, true);
|
||||||
|
|
||||||
|
qDebug("FCDProInput::started");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProInput::stop()
|
||||||
|
{
|
||||||
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
|
|
||||||
|
if (m_FCDThread)
|
||||||
|
{
|
||||||
|
m_FCDThread->stopWork();
|
||||||
|
// wait for thread to quit ?
|
||||||
|
delete m_FCDThread;
|
||||||
|
m_FCDThread = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fcdClose(m_dev);
|
||||||
|
m_dev = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString& FCDProInput::getDeviceDescription() const
|
||||||
|
{
|
||||||
|
return m_deviceDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCDProInput::getSampleRate() const
|
||||||
|
{
|
||||||
|
return 96000;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint64 FCDProInput::getCenterFrequency() const
|
||||||
|
{
|
||||||
|
return m_settings.centerFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FCDProInput::handleMessage(const Message& message)
|
||||||
|
{
|
||||||
|
if(MsgConfigureFCD::match(message))
|
||||||
|
{
|
||||||
|
qDebug() << "FCDProInput::handleMessage: MsgConfigureFCD";
|
||||||
|
MsgConfigureFCD& conf = (MsgConfigureFCD&) message;
|
||||||
|
applySettings(conf.getSettings(), false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProInput::applySettings(const Settings& settings, bool force)
|
||||||
|
{
|
||||||
|
bool signalChange = false;
|
||||||
|
|
||||||
|
if ((m_settings.centerFrequency != settings.centerFrequency) || force)
|
||||||
|
{
|
||||||
|
qDebug() << "FCDProInput::applySettings: fc: " << settings.centerFrequency;
|
||||||
|
m_settings.centerFrequency = settings.centerFrequency;
|
||||||
|
|
||||||
|
if (m_dev != 0)
|
||||||
|
{
|
||||||
|
set_center_freq((double) m_settings.centerFrequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
signalChange = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_settings.gain != settings.gain) || force)
|
||||||
|
{
|
||||||
|
m_settings.gain = settings.gain;
|
||||||
|
|
||||||
|
if (m_dev != 0)
|
||||||
|
{
|
||||||
|
set_lna_gain(settings.gain > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_settings.bias != settings.bias) || force)
|
||||||
|
{
|
||||||
|
m_settings.bias = settings.bias;
|
||||||
|
|
||||||
|
if (m_dev != 0)
|
||||||
|
{
|
||||||
|
set_bias_t(settings.bias > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signalChange)
|
||||||
|
{
|
||||||
|
DSPSignalNotification *notif = new DSPSignalNotification(96000, m_settings.centerFrequency);
|
||||||
|
getOutputMessageQueue()->push(notif);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProInput::set_center_freq(double freq)
|
||||||
|
{
|
||||||
|
if (fcdAppSetFreq(m_dev, freq) == FCD_MODE_NONE)
|
||||||
|
{
|
||||||
|
qDebug("No FCD HID found for frquency change");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProInput::set_bias_t(bool on)
|
||||||
|
{
|
||||||
|
quint8 cmd = on ? 1 : 0;
|
||||||
|
|
||||||
|
fcdAppSetParam(m_dev, FCD_CMD_APP_SET_BIAS_TEE, &cmd, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProInput::set_lna_gain(bool on)
|
||||||
|
{
|
||||||
|
quint8 cmd = on ? 1 : 0;
|
||||||
|
|
||||||
|
fcdAppSetParam(m_dev, FCD_CMD_APP_SET_LNA_GAIN, &cmd, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
93
plugins/samplesource/fcdpro/fcdproinput.h
Normal file
93
plugins/samplesource/fcdpro/fcdproinput.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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_FCDPROINPUT_H
|
||||||
|
#define INCLUDE_FCDPROINPUT_H
|
||||||
|
|
||||||
|
#include "dsp/samplesource.h"
|
||||||
|
#include "fcdhid.h"
|
||||||
|
#include <QString>
|
||||||
|
#include <inttypes.h>
|
||||||
|
|
||||||
|
struct fcd_buffer {
|
||||||
|
void *start;
|
||||||
|
std::size_t length;
|
||||||
|
};
|
||||||
|
|
||||||
|
class FCDProThread;
|
||||||
|
|
||||||
|
class FCDProInput : public SampleSource {
|
||||||
|
public:
|
||||||
|
struct Settings {
|
||||||
|
Settings();
|
||||||
|
quint64 centerFrequency;
|
||||||
|
qint32 range;
|
||||||
|
qint32 gain;
|
||||||
|
qint32 bias;
|
||||||
|
void resetToDefaults();
|
||||||
|
QByteArray serialize() const;
|
||||||
|
bool deserialize(const QByteArray& data);
|
||||||
|
};
|
||||||
|
|
||||||
|
class MsgConfigureFCD : public Message {
|
||||||
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
|
public:
|
||||||
|
const Settings& getSettings() const { return m_settings; }
|
||||||
|
|
||||||
|
static MsgConfigureFCD* create(const Settings& settings)
|
||||||
|
{
|
||||||
|
return new MsgConfigureFCD(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
Settings m_settings;
|
||||||
|
|
||||||
|
MsgConfigureFCD(const Settings& settings) :
|
||||||
|
Message(),
|
||||||
|
m_settings(settings)
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
FCDProInput();
|
||||||
|
virtual ~FCDProInput();
|
||||||
|
|
||||||
|
virtual bool init(const Message& cmd);
|
||||||
|
virtual bool start(int device);
|
||||||
|
virtual void stop();
|
||||||
|
|
||||||
|
virtual const QString& getDeviceDescription() const;
|
||||||
|
virtual int getSampleRate() const;
|
||||||
|
virtual quint64 getCenterFrequency() const;
|
||||||
|
|
||||||
|
virtual bool handleMessage(const Message& message);
|
||||||
|
|
||||||
|
void set_center_freq(double freq);
|
||||||
|
void set_bias_t(bool on);
|
||||||
|
void set_lna_gain(bool on);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void applySettings(const Settings& settings, bool force);
|
||||||
|
|
||||||
|
hid_device *m_dev;
|
||||||
|
QMutex m_mutex;
|
||||||
|
Settings m_settings;
|
||||||
|
FCDProThread* m_FCDThread;
|
||||||
|
QString m_deviceDescription;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // INCLUDE_FCDPROINPUT_H
|
@ -18,10 +18,10 @@
|
|||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include "plugin/pluginapi.h"
|
#include "plugin/pluginapi.h"
|
||||||
#include "util/simpleserializer.h"
|
#include "util/simpleserializer.h"
|
||||||
#include "fcdplugin.h"
|
#include "fcdproplugin.h"
|
||||||
#include "fcdgui.h"
|
#include "fcdprogui.h"
|
||||||
|
|
||||||
const PluginDescriptor FCDPlugin::m_pluginDescriptor = {
|
const PluginDescriptor FCDProPlugin::m_pluginDescriptor = {
|
||||||
QString("FunCube Pro Input"),
|
QString("FunCube Pro Input"),
|
||||||
QString("---"),
|
QString("---"),
|
||||||
QString("(c) Edouard Griffiths, F4EXB"),
|
QString("(c) Edouard Griffiths, F4EXB"),
|
||||||
@ -30,24 +30,24 @@ const PluginDescriptor FCDPlugin::m_pluginDescriptor = {
|
|||||||
QString("https://github.com/f4exb/sdrangel")
|
QString("https://github.com/f4exb/sdrangel")
|
||||||
};
|
};
|
||||||
|
|
||||||
FCDPlugin::FCDPlugin(QObject* parent) :
|
FCDProPlugin::FCDProPlugin(QObject* parent) :
|
||||||
QObject(parent)
|
QObject(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const PluginDescriptor& FCDPlugin::getPluginDescriptor() const
|
const PluginDescriptor& FCDProPlugin::getPluginDescriptor() const
|
||||||
{
|
{
|
||||||
return m_pluginDescriptor;
|
return m_pluginDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDPlugin::initPlugin(PluginAPI* pluginAPI)
|
void FCDProPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||||
{
|
{
|
||||||
m_pluginAPI = pluginAPI;
|
m_pluginAPI = pluginAPI;
|
||||||
|
|
||||||
m_pluginAPI->registerSampleSource("org.osmocom.sdr.samplesource.fcdpro", this);
|
m_pluginAPI->registerSampleSource("org.osmocom.sdr.samplesource.fcdpro", this);
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginInterface::SampleSourceDevices FCDPlugin::enumSampleSources()
|
PluginInterface::SampleSourceDevices FCDProPlugin::enumSampleSources()
|
||||||
{
|
{
|
||||||
SampleSourceDevices result;
|
SampleSourceDevices result;
|
||||||
|
|
||||||
@ -59,11 +59,11 @@ PluginInterface::SampleSourceDevices FCDPlugin::enumSampleSources()
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
PluginGUI* FCDPlugin::createSampleSourcePluginGUI(const QString& sourceName, const QByteArray& address)
|
PluginGUI* FCDProPlugin::createSampleSourcePluginGUI(const QString& sourceName, const QByteArray& address)
|
||||||
{
|
{
|
||||||
if(sourceName == "org.osmocom.sdr.samplesource.fcdpro")
|
if(sourceName == "org.osmocom.sdr.samplesource.fcdpro")
|
||||||
{
|
{
|
||||||
FCDGui* gui = new FCDGui(m_pluginAPI);
|
FCDProGui* gui = new FCDProGui(m_pluginAPI);
|
||||||
m_pluginAPI->setInputGUI(gui);
|
m_pluginAPI->setInputGUI(gui);
|
||||||
return gui;
|
return gui;
|
||||||
}
|
}
|
@ -1,16 +1,16 @@
|
|||||||
#ifndef INCLUDE_FCDPLUGIN_H
|
#ifndef INCLUDE_FCDPROPLUGIN_H
|
||||||
#define INCLUDE_FCDPLUGIN_H
|
#define INCLUDE_FCDPROPLUGIN_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "plugin/plugininterface.h"
|
#include "plugin/plugininterface.h"
|
||||||
|
|
||||||
class FCDPlugin : public QObject, public PluginInterface {
|
class FCDProPlugin : public QObject, public PluginInterface {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_INTERFACES(PluginInterface)
|
Q_INTERFACES(PluginInterface)
|
||||||
Q_PLUGIN_METADATA(IID "org.osmocom.sdr.samplesource.fcdpro")
|
Q_PLUGIN_METADATA(IID "org.osmocom.sdr.samplesource.fcdpro")
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FCDPlugin(QObject* parent = NULL);
|
explicit FCDProPlugin(QObject* parent = NULL);
|
||||||
|
|
||||||
const PluginDescriptor& getPluginDescriptor() const;
|
const PluginDescriptor& getPluginDescriptor() const;
|
||||||
void initPlugin(PluginAPI* pluginAPI);
|
void initPlugin(PluginAPI* pluginAPI);
|
@ -14,9 +14,9 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "fcdserializer.h"
|
#include "fcdproserializer.h"
|
||||||
|
|
||||||
void FCDSerializer::writeSerializedData(const FCDData& data, QByteArray& serializedData)
|
void FCDProSerializer::writeSerializedData(const FCDData& data, QByteArray& serializedData)
|
||||||
{
|
{
|
||||||
QByteArray sampleSourceSerialized;
|
QByteArray sampleSourceSerialized;
|
||||||
SampleSourceSerializer::writeSerializedData(data.m_data, sampleSourceSerialized);
|
SampleSourceSerializer::writeSerializedData(data.m_data, sampleSourceSerialized);
|
||||||
@ -30,7 +30,7 @@ void FCDSerializer::writeSerializedData(const FCDData& data, QByteArray& seriali
|
|||||||
serializedData = s.final();
|
serializedData = s.final();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FCDSerializer::readSerializedData(const QByteArray& serializedData, FCDData& data)
|
bool FCDProSerializer::readSerializedData(const QByteArray& serializedData, FCDData& data)
|
||||||
{
|
{
|
||||||
bool valid = SampleSourceSerializer::readSerializedData(serializedData, data.m_data);
|
bool valid = SampleSourceSerializer::readSerializedData(serializedData, data.m_data);
|
||||||
|
|
||||||
@ -61,7 +61,7 @@ bool FCDSerializer::readSerializedData(const QByteArray& serializedData, FCDData
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDSerializer::setDefaults(FCDData& data)
|
void FCDProSerializer::setDefaults(FCDData& data)
|
||||||
{
|
{
|
||||||
data.m_range = 0;
|
data.m_range = 0;
|
||||||
data.m_bias = 0;
|
data.m_bias = 0;
|
@ -14,12 +14,12 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef PLUGINS_SAMPLESOURCE_FCD_FCDSERIALIZER_H_
|
#ifndef PLUGINS_SAMPLESOURCE_FCD_FCDPROSERIALIZER_H_
|
||||||
#define PLUGINS_SAMPLESOURCE_FCD_FCDSERIALIZER_H_
|
#define PLUGINS_SAMPLESOURCE_FCD_FCDPROSERIALIZER_H_
|
||||||
|
|
||||||
#include "util/samplesourceserializer.h"
|
#include "util/samplesourceserializer.h"
|
||||||
|
|
||||||
class FCDSerializer
|
class FCDProSerializer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct FCDData
|
struct FCDData
|
||||||
@ -36,4 +36,4 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /* PLUGINS_SAMPLESOURCE_FCD_FCDSERIALIZER_H_ */
|
#endif /* PLUGINS_SAMPLESOURCE_FCD_FCDPROSERIALIZER_H_ */
|
@ -18,11 +18,11 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "fcdthread.h"
|
|
||||||
#include "fcdinput.h"
|
|
||||||
#include "dsp/samplefifo.h"
|
#include "dsp/samplefifo.h"
|
||||||
|
#include "fcdprothread.h"
|
||||||
|
#include "fcdproinput.h"
|
||||||
|
|
||||||
FCDThread::FCDThread(SampleFifo* sampleFifo, QObject* parent) :
|
FCDProThread::FCDProThread(SampleFifo* sampleFifo, QObject* parent) :
|
||||||
QThread(parent),
|
QThread(parent),
|
||||||
fcd_handle(NULL),
|
fcd_handle(NULL),
|
||||||
m_running(false),
|
m_running(false),
|
||||||
@ -32,11 +32,11 @@ FCDThread::FCDThread(SampleFifo* sampleFifo, QObject* parent) :
|
|||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
FCDThread::~FCDThread()
|
FCDProThread::~FCDProThread()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDThread::startWork()
|
void FCDProThread::startWork()
|
||||||
{
|
{
|
||||||
m_startWaitMutex.lock();
|
m_startWaitMutex.lock();
|
||||||
|
|
||||||
@ -50,15 +50,15 @@ void FCDThread::startWork()
|
|||||||
m_startWaitMutex.unlock();
|
m_startWaitMutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDThread::stopWork()
|
void FCDProThread::stopWork()
|
||||||
{
|
{
|
||||||
m_running = false;
|
m_running = false;
|
||||||
wait();
|
wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDThread::run()
|
void FCDProThread::run()
|
||||||
{
|
{
|
||||||
if ( !OpenSource("hw:CARD=V20") )
|
if ( !OpenSource("hw:CARD=V10") )
|
||||||
{
|
{
|
||||||
qCritical() << "FCDThread::run: cannot open FCD sound card";
|
qCritical() << "FCDThread::run: cannot open FCD sound card";
|
||||||
return;
|
return;
|
||||||
@ -78,7 +78,7 @@ void FCDThread::run()
|
|||||||
CloseSource();
|
CloseSource();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FCDThread::OpenSource(const char* cardname)
|
bool FCDProThread::OpenSource(const char* cardname)
|
||||||
{
|
{
|
||||||
bool fail = false;
|
bool fail = false;
|
||||||
snd_pcm_hw_params_t* params;
|
snd_pcm_hw_params_t* params;
|
||||||
@ -133,7 +133,7 @@ bool FCDThread::OpenSource(const char* cardname)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDThread::CloseSource()
|
void FCDProThread::CloseSource()
|
||||||
{
|
{
|
||||||
if (fcd_handle)
|
if (fcd_handle)
|
||||||
{
|
{
|
||||||
@ -143,7 +143,7 @@ void FCDThread::CloseSource()
|
|||||||
fcd_handle = NULL;
|
fcd_handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FCDThread::work(int n_items)
|
int FCDProThread::work(int n_items)
|
||||||
{
|
{
|
||||||
int l;
|
int l;
|
||||||
SampleVector::iterator it;
|
SampleVector::iterator it;
|
55
plugins/samplesource/fcdpro/fcdprothread.h
Normal file
55
plugins/samplesource/fcdpro/fcdprothread.h
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
|
||||||
|
// //
|
||||||
|
// This program is free software; you can redistribute it and/or modify //
|
||||||
|
// it under the terms of the GNU General Public License as published by //
|
||||||
|
// the Free Software Foundation as version 3 of the License, or //
|
||||||
|
// //
|
||||||
|
// 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_FCDPROTHREAD_H
|
||||||
|
#define INCLUDE_FCDPROTHREAD_H
|
||||||
|
|
||||||
|
#include <QThread>
|
||||||
|
#include <QMutex>
|
||||||
|
#include <QWaitCondition>
|
||||||
|
#include "dsp/samplefifo.h"
|
||||||
|
#include "dsp/inthalfbandfilter.h"
|
||||||
|
#include <alsa/asoundlib.h>
|
||||||
|
|
||||||
|
#define FCDPP_RATE 192000
|
||||||
|
#define FCD_BLOCKSIZE (1<<11)
|
||||||
|
|
||||||
|
class FCDProThread : public QThread {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
FCDProThread(SampleFifo* sampleFifo, QObject* parent = NULL);
|
||||||
|
~FCDProThread();
|
||||||
|
|
||||||
|
void startWork();
|
||||||
|
void stopWork();
|
||||||
|
bool OpenSource(const char *filename);
|
||||||
|
void CloseSource();
|
||||||
|
|
||||||
|
private:
|
||||||
|
snd_pcm_t* fcd_handle;
|
||||||
|
|
||||||
|
QMutex m_startWaitMutex;
|
||||||
|
QWaitCondition m_startWaiter;
|
||||||
|
bool m_running;
|
||||||
|
|
||||||
|
SampleVector m_convertBuffer;
|
||||||
|
SampleFifo* m_sampleFifo;
|
||||||
|
|
||||||
|
void run();
|
||||||
|
int work(int n_items);
|
||||||
|
};
|
||||||
|
#endif // INCLUDE_FCDPROTHREAD_H
|
53
plugins/samplesource/fcdproplus/CMakeLists.txt
Normal file
53
plugins/samplesource/fcdproplus/CMakeLists.txt
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
project(fcdproplus)
|
||||||
|
|
||||||
|
set(fcdproplus_SOURCES
|
||||||
|
fcdproplusgui.cpp
|
||||||
|
fcdproplusinput.cpp
|
||||||
|
fcdproplusplugin.cpp
|
||||||
|
fcdproplusserializer.cpp
|
||||||
|
fcdproplusthread.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(fcdproplus_HEADERS
|
||||||
|
fcdproplusgui.h
|
||||||
|
fcdproplusinput.h
|
||||||
|
fcdproplusplugin.h
|
||||||
|
fcdproplusserializer.h
|
||||||
|
fcdproplusthread.h
|
||||||
|
)
|
||||||
|
|
||||||
|
set(fcdproplus_FORMS
|
||||||
|
fcdproplusgui.ui
|
||||||
|
)
|
||||||
|
|
||||||
|
include_directories(
|
||||||
|
.
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
${CMAKE_SOURCE_DIR}/include
|
||||||
|
${CMAKE_SOURCE_DIR}/include-gpl
|
||||||
|
${CMAKE_SOURCE_DIR}/fcdhid
|
||||||
|
)
|
||||||
|
|
||||||
|
#include(${QT_USE_FILE})
|
||||||
|
add_definitions(${QT_DEFINITIONS})
|
||||||
|
add_definitions(-DQT_PLUGIN)
|
||||||
|
add_definitions(-DQT_SHARED)
|
||||||
|
|
||||||
|
#qt4_wrap_cpp(fcdproplus_HEADERS_MOC ${fcdproplus_HEADERS})
|
||||||
|
qt5_wrap_ui(fcdproplus_FORMS_HEADERS ${fcdproplus_FORMS})
|
||||||
|
|
||||||
|
add_library(inputfcdproplus SHARED
|
||||||
|
${fcdproplus_SOURCES}
|
||||||
|
${fcdproplus_HEADERS_MOC}
|
||||||
|
${fcdproplus_FORMS_HEADERS}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(inputfcdproplus
|
||||||
|
${QT_LIBRARIES}
|
||||||
|
${LIBUSB_LIBRARIES}
|
||||||
|
asound
|
||||||
|
fcdhid
|
||||||
|
sdrbase
|
||||||
|
)
|
||||||
|
|
||||||
|
qt5_use_modules(inputfcdproplus Core Widgets OpenGL Multimedia)
|
154
plugins/samplesource/fcdproplus/fcdproplusgui.cpp
Normal file
154
plugins/samplesource/fcdproplus/fcdproplusgui.cpp
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
#include "ui_fcdproplusgui.h"
|
||||||
|
#include "plugin/pluginapi.h"
|
||||||
|
#include "gui/colormapper.h"
|
||||||
|
#include "dsp/dspengine.h"
|
||||||
|
#include "fcdproplusgui.h"
|
||||||
|
|
||||||
|
FCDProPlusGui::FCDProPlusGui(PluginAPI* pluginAPI, QWidget* parent) :
|
||||||
|
QWidget(parent),
|
||||||
|
ui(new Ui::FCDProPlusGui),
|
||||||
|
m_pluginAPI(pluginAPI),
|
||||||
|
m_settings(),
|
||||||
|
m_sampleSource(NULL)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold));
|
||||||
|
ui->centerFrequency->setValueRange(7, 64000U, 1700000U);
|
||||||
|
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
|
||||||
|
displaySettings();
|
||||||
|
|
||||||
|
m_sampleSource = new FCDProPlusInput();
|
||||||
|
DSPEngine::instance()->setSource(m_sampleSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
FCDProPlusGui::~FCDProPlusGui()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusGui::destroy()
|
||||||
|
{
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusGui::setName(const QString& name)
|
||||||
|
{
|
||||||
|
setObjectName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FCDProPlusGui::getName() const
|
||||||
|
{
|
||||||
|
return objectName();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusGui::resetToDefaults()
|
||||||
|
{
|
||||||
|
m_settings.resetToDefaults();
|
||||||
|
displaySettings();
|
||||||
|
sendSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 FCDProPlusGui::getCenterFrequency() const
|
||||||
|
{
|
||||||
|
return m_settings.centerFrequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray FCDProPlusGui::serialize() const
|
||||||
|
{
|
||||||
|
return m_settings.serialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FCDProPlusGui::deserialize(const QByteArray& data)
|
||||||
|
{
|
||||||
|
if(m_settings.deserialize(data))
|
||||||
|
{
|
||||||
|
displaySettings();
|
||||||
|
sendSettings();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resetToDefaults();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FCDProPlusGui::handleMessage(const Message& message)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusGui::displaySettings()
|
||||||
|
{
|
||||||
|
ui->centerFrequency->setValue(m_settings.centerFrequency / 1000);
|
||||||
|
ui->checkBoxR->setChecked(m_settings.range);
|
||||||
|
ui->checkBoxG->setChecked(m_settings.gain);
|
||||||
|
ui->checkBoxB->setChecked(m_settings.bias);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusGui::sendSettings()
|
||||||
|
{
|
||||||
|
if(!m_updateTimer.isActive())
|
||||||
|
m_updateTimer.start(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusGui::on_centerFrequency_changed(quint64 value)
|
||||||
|
{
|
||||||
|
m_settings.centerFrequency = value * 1000;
|
||||||
|
sendSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusGui::updateHardware()
|
||||||
|
{
|
||||||
|
FCDProPlusInput::MsgConfigureFCD* message = FCDProPlusInput::MsgConfigureFCD::create(m_settings);
|
||||||
|
m_sampleSource->getInputMessageQueue()->push(message);
|
||||||
|
m_updateTimer.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusGui::on_checkBoxR_stateChanged(int state)
|
||||||
|
{
|
||||||
|
if (state == Qt::Checked) // FIXME: this is for the Pro+ version only!
|
||||||
|
{
|
||||||
|
ui->centerFrequency->setValueRange(7, 150U, 240000U);
|
||||||
|
ui->centerFrequency->setValue(7000);
|
||||||
|
m_settings.centerFrequency = 7000 * 1000;
|
||||||
|
m_settings.range = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->centerFrequency->setValueRange(7, 64000U, 1900000U);
|
||||||
|
ui->centerFrequency->setValue(435000);
|
||||||
|
m_settings.centerFrequency = 435000 * 1000;
|
||||||
|
m_settings.range = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusGui::on_checkBoxG_stateChanged(int state)
|
||||||
|
{
|
||||||
|
if (state == Qt::Checked)
|
||||||
|
{
|
||||||
|
m_settings.gain = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_settings.gain = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusGui::on_checkBoxB_stateChanged(int state)
|
||||||
|
{
|
||||||
|
if (state == Qt::Checked)
|
||||||
|
{
|
||||||
|
m_settings.bias = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_settings.bias = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sendSettings();
|
||||||
|
}
|
@ -2,21 +2,22 @@
|
|||||||
#define INCLUDE_FCDGUI_H
|
#define INCLUDE_FCDGUI_H
|
||||||
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include "fcdproplusinput.h"
|
||||||
#include "plugin/plugingui.h"
|
#include "plugin/plugingui.h"
|
||||||
#include "fcdinput.h"
|
|
||||||
|
|
||||||
class PluginAPI;
|
class PluginAPI;
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
class FCDGui;
|
class FCDProPlusGui;
|
||||||
}
|
}
|
||||||
|
|
||||||
class FCDGui : public QWidget, public PluginGUI {
|
class FCDProPlusGui : public QWidget, public PluginGUI {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FCDGui(PluginAPI* pluginAPI, QWidget* parent = NULL);
|
explicit FCDProPlusGui(PluginAPI* pluginAPI, QWidget* parent = NULL);
|
||||||
virtual ~FCDGui();
|
virtual ~FCDProPlusGui();
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
void setName(const QString& name);
|
void setName(const QString& name);
|
||||||
@ -30,10 +31,10 @@ public:
|
|||||||
virtual bool handleMessage(const Message& message);
|
virtual bool handleMessage(const Message& message);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::FCDGui* ui;
|
Ui::FCDProPlusGui* ui;
|
||||||
|
|
||||||
PluginAPI* m_pluginAPI;
|
PluginAPI* m_pluginAPI;
|
||||||
FCDInput::Settings m_settings;
|
FCDProPlusInput::Settings m_settings;
|
||||||
QTimer m_updateTimer;
|
QTimer m_updateTimer;
|
||||||
std::vector<int> m_gains;
|
std::vector<int> m_gains;
|
||||||
SampleSource* m_sampleSource;
|
SampleSource* m_sampleSource;
|
144
plugins/samplesource/fcdproplus/fcdproplusgui.ui
Normal file
144
plugins/samplesource/fcdproplus/fcdproplusgui.ui
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>FCDProPlusGui</class>
|
||||||
|
<widget class="QWidget" name="FCDProPlusGui">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>165</width>
|
||||||
|
<height>119</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>FunCubeDongle</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="ValueDial" name="centerFrequency" native="true">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>32</width>
|
||||||
|
<height>16</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<family>Monospace</family>
|
||||||
|
<pointsize>20</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="focusPolicy">
|
||||||
|
<enum>Qt::StrongFocus</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Tuner center frequency in kHz</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Line" name="line_4">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayoutR">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkBoxR">
|
||||||
|
<property name="text">
|
||||||
|
<string>Low Range</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayoutG">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkBoxG">
|
||||||
|
<property name="text">
|
||||||
|
<string>LNA Gain</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="checkBoxB">
|
||||||
|
<property name="text">
|
||||||
|
<string>Bias T</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>ValueDial</class>
|
||||||
|
<extends>QWidget</extends>
|
||||||
|
<header>gui/valuedial.h</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
@ -20,13 +20,14 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "fcdinput.h"
|
|
||||||
#include "fcdthread.h"
|
|
||||||
#include "fcdgui.h"
|
|
||||||
#include "dsp/dspcommands.h"
|
#include "dsp/dspcommands.h"
|
||||||
#include "fcdserializer.h"
|
#include "fcdproplusinput.h"
|
||||||
|
|
||||||
MESSAGE_CLASS_DEFINITION(FCDInput::MsgConfigureFCD, Message)
|
#include "fcdproplusgui.h"
|
||||||
|
#include "fcdproplusserializer.h"
|
||||||
|
#include "fcdproplusthread.h"
|
||||||
|
|
||||||
|
MESSAGE_CLASS_DEFINITION(FCDProPlusInput::MsgConfigureFCD, Message)
|
||||||
//MESSAGE_CLASS_DEFINITION(FCDInput::MsgReportFCD, Message)
|
//MESSAGE_CLASS_DEFINITION(FCDInput::MsgReportFCD, Message)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -40,7 +41,7 @@ const int FCDInput::m_sampleRate = 96000;
|
|||||||
const std::string FCDInput::m_deviceName("hw:CARD=V10");
|
const std::string FCDInput::m_deviceName("hw:CARD=V10");
|
||||||
*/
|
*/
|
||||||
|
|
||||||
FCDInput::Settings::Settings() :
|
FCDProPlusInput::Settings::Settings() :
|
||||||
centerFrequency(435000000),
|
centerFrequency(435000000),
|
||||||
range(0),
|
range(0),
|
||||||
gain(0),
|
gain(0),
|
||||||
@ -48,7 +49,7 @@ FCDInput::Settings::Settings() :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDInput::Settings::resetToDefaults()
|
void FCDProPlusInput::Settings::resetToDefaults()
|
||||||
{
|
{
|
||||||
centerFrequency = 435000000;
|
centerFrequency = 435000000;
|
||||||
range = 0;
|
range = 0;
|
||||||
@ -56,9 +57,9 @@ void FCDInput::Settings::resetToDefaults()
|
|||||||
bias = 0;
|
bias = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray FCDInput::Settings::serialize() const
|
QByteArray FCDProPlusInput::Settings::serialize() const
|
||||||
{
|
{
|
||||||
FCDSerializer::FCDData data;
|
FCDProPlusSerializer::FCDData data;
|
||||||
|
|
||||||
data.m_data.m_lnaGain = gain;
|
data.m_data.m_lnaGain = gain;
|
||||||
data.m_data.m_frequency = centerFrequency;
|
data.m_data.m_frequency = centerFrequency;
|
||||||
@ -67,7 +68,7 @@ QByteArray FCDInput::Settings::serialize() const
|
|||||||
|
|
||||||
QByteArray byteArray;
|
QByteArray byteArray;
|
||||||
|
|
||||||
FCDSerializer::writeSerializedData(data, byteArray);
|
FCDProPlusSerializer::writeSerializedData(data, byteArray);
|
||||||
|
|
||||||
return byteArray;
|
return byteArray;
|
||||||
|
|
||||||
@ -80,11 +81,11 @@ QByteArray FCDInput::Settings::serialize() const
|
|||||||
return s.final();*/
|
return s.final();*/
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FCDInput::Settings::deserialize(const QByteArray& serializedData)
|
bool FCDProPlusInput::Settings::deserialize(const QByteArray& serializedData)
|
||||||
{
|
{
|
||||||
FCDSerializer::FCDData data;
|
FCDProPlusSerializer::FCDData data;
|
||||||
|
|
||||||
bool valid = FCDSerializer::readSerializedData(serializedData, data);
|
bool valid = FCDProPlusSerializer::readSerializedData(serializedData, data);
|
||||||
|
|
||||||
gain = data.m_data.m_lnaGain;
|
gain = data.m_data.m_lnaGain;
|
||||||
centerFrequency = data.m_data.m_frequency;
|
centerFrequency = data.m_data.m_frequency;
|
||||||
@ -109,27 +110,27 @@ bool FCDInput::Settings::deserialize(const QByteArray& serializedData)
|
|||||||
return true;*/
|
return true;*/
|
||||||
}
|
}
|
||||||
|
|
||||||
FCDInput::FCDInput() :
|
FCDProPlusInput::FCDProPlusInput() :
|
||||||
m_dev(0),
|
m_dev(0),
|
||||||
m_settings(),
|
m_settings(),
|
||||||
m_FCDThread(0),
|
m_FCDThread(0),
|
||||||
m_deviceDescription()
|
m_deviceDescription("Funcube Dongle Pro+")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
FCDInput::~FCDInput()
|
FCDProPlusInput::~FCDProPlusInput()
|
||||||
{
|
{
|
||||||
stop();
|
stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FCDInput::init(const Message& cmd)
|
bool FCDProPlusInput::init(const Message& cmd)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FCDInput::start(int device)
|
bool FCDProPlusInput::start(int device)
|
||||||
{
|
{
|
||||||
qDebug() << "FCDInput::start with device #" << device;
|
qDebug() << "FCDProPlusInput::start with device #" << device;
|
||||||
|
|
||||||
QMutexLocker mutexLocker(&m_mutex);
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
|
|
||||||
@ -142,12 +143,10 @@ bool FCDInput::start(int device)
|
|||||||
|
|
||||||
if (m_dev == 0)
|
if (m_dev == 0)
|
||||||
{
|
{
|
||||||
qCritical("FCDInput::start: could not open FCD");
|
qCritical("FCDProPlusInput::start: could not open FCD");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_deviceDescription = QString("Funcube Dongle");
|
|
||||||
|
|
||||||
/* Apply settings before streaming to avoid bus contention;
|
/* Apply settings before streaming to avoid bus contention;
|
||||||
* there is very little spare bandwidth on a full speed USB device.
|
* there is very little spare bandwidth on a full speed USB device.
|
||||||
* Failure is harmless if no device is found
|
* Failure is harmless if no device is found
|
||||||
@ -161,7 +160,7 @@ bool FCDInput::start(int device)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((m_FCDThread = new FCDThread(&m_sampleFifo)) == NULL)
|
if ((m_FCDThread = new FCDProPlusThread(&m_sampleFifo)) == NULL)
|
||||||
{
|
{
|
||||||
qFatal("out of memory");
|
qFatal("out of memory");
|
||||||
return false;
|
return false;
|
||||||
@ -172,11 +171,11 @@ bool FCDInput::start(int device)
|
|||||||
mutexLocker.unlock();
|
mutexLocker.unlock();
|
||||||
applySettings(m_settings, true);
|
applySettings(m_settings, true);
|
||||||
|
|
||||||
qDebug("FCDInput::started");
|
qDebug("FCDProPlusInput::started");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDInput::stop()
|
void FCDProPlusInput::stop()
|
||||||
{
|
{
|
||||||
QMutexLocker mutexLocker(&m_mutex);
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
|
|
||||||
@ -190,30 +189,28 @@ void FCDInput::stop()
|
|||||||
|
|
||||||
fcdClose(m_dev);
|
fcdClose(m_dev);
|
||||||
m_dev = 0;
|
m_dev = 0;
|
||||||
|
|
||||||
m_deviceDescription.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString& FCDInput::getDeviceDescription() const
|
const QString& FCDProPlusInput::getDeviceDescription() const
|
||||||
{
|
{
|
||||||
return m_deviceDescription;
|
return m_deviceDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FCDInput::getSampleRate() const
|
int FCDProPlusInput::getSampleRate() const
|
||||||
{
|
{
|
||||||
return 192000;
|
return 192000;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 FCDInput::getCenterFrequency() const
|
quint64 FCDProPlusInput::getCenterFrequency() const
|
||||||
{
|
{
|
||||||
return m_settings.centerFrequency;
|
return m_settings.centerFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FCDInput::handleMessage(const Message& message)
|
bool FCDProPlusInput::handleMessage(const Message& message)
|
||||||
{
|
{
|
||||||
if(MsgConfigureFCD::match(message))
|
if(MsgConfigureFCD::match(message))
|
||||||
{
|
{
|
||||||
qDebug() << "FCDInput::handleMessage: MsgConfigureFCD";
|
qDebug() << "FCDProPlusInput::handleMessage: MsgConfigureFCD";
|
||||||
MsgConfigureFCD& conf = (MsgConfigureFCD&) message;
|
MsgConfigureFCD& conf = (MsgConfigureFCD&) message;
|
||||||
applySettings(conf.getSettings(), false);
|
applySettings(conf.getSettings(), false);
|
||||||
return true;
|
return true;
|
||||||
@ -224,13 +221,13 @@ bool FCDInput::handleMessage(const Message& message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDInput::applySettings(const Settings& settings, bool force)
|
void FCDProPlusInput::applySettings(const Settings& settings, bool force)
|
||||||
{
|
{
|
||||||
bool signalChange = false;
|
bool signalChange = false;
|
||||||
|
|
||||||
if ((m_settings.centerFrequency != settings.centerFrequency) || force)
|
if ((m_settings.centerFrequency != settings.centerFrequency) || force)
|
||||||
{
|
{
|
||||||
qDebug() << "FCDInput::applySettings: fc: " << settings.centerFrequency;
|
qDebug() << "FCDProPlusInput::applySettings: fc: " << settings.centerFrequency;
|
||||||
m_settings.centerFrequency = settings.centerFrequency;
|
m_settings.centerFrequency = settings.centerFrequency;
|
||||||
|
|
||||||
if (m_dev != 0)
|
if (m_dev != 0)
|
||||||
@ -268,7 +265,7 @@ void FCDInput::applySettings(const Settings& settings, bool force)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDInput::set_center_freq(double freq)
|
void FCDProPlusInput::set_center_freq(double freq)
|
||||||
{
|
{
|
||||||
if (fcdAppSetFreq(m_dev, freq) == FCD_MODE_NONE)
|
if (fcdAppSetFreq(m_dev, freq) == FCD_MODE_NONE)
|
||||||
{
|
{
|
||||||
@ -276,14 +273,14 @@ void FCDInput::set_center_freq(double freq)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDInput::set_bias_t(bool on)
|
void FCDProPlusInput::set_bias_t(bool on)
|
||||||
{
|
{
|
||||||
quint8 cmd = on ? 1 : 0;
|
quint8 cmd = on ? 1 : 0;
|
||||||
|
|
||||||
fcdAppSetParam(m_dev, FCD_CMD_APP_SET_BIAS_TEE, &cmd, 1);
|
fcdAppSetParam(m_dev, FCD_CMD_APP_SET_BIAS_TEE, &cmd, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDInput::set_lna_gain(bool on)
|
void FCDProPlusInput::set_lna_gain(bool on)
|
||||||
{
|
{
|
||||||
quint8 cmd = on ? 1 : 0;
|
quint8 cmd = on ? 1 : 0;
|
||||||
|
|
@ -28,9 +28,9 @@ struct fcd_buffer {
|
|||||||
std::size_t length;
|
std::size_t length;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FCDThread;
|
class FCDProPlusThread;
|
||||||
|
|
||||||
class FCDInput : public SampleSource {
|
class FCDProPlusInput : public SampleSource {
|
||||||
public:
|
public:
|
||||||
struct Settings {
|
struct Settings {
|
||||||
Settings();
|
Settings();
|
||||||
@ -63,8 +63,8 @@ public:
|
|||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
|
|
||||||
FCDInput();
|
FCDProPlusInput();
|
||||||
virtual ~FCDInput();
|
virtual ~FCDProPlusInput();
|
||||||
|
|
||||||
virtual bool init(const Message& cmd);
|
virtual bool init(const Message& cmd);
|
||||||
virtual bool start(int device);
|
virtual bool start(int device);
|
||||||
@ -86,7 +86,7 @@ private:
|
|||||||
hid_device *m_dev;
|
hid_device *m_dev;
|
||||||
QMutex m_mutex;
|
QMutex m_mutex;
|
||||||
Settings m_settings;
|
Settings m_settings;
|
||||||
FCDThread* m_FCDThread;
|
FCDProPlusThread* m_FCDThread;
|
||||||
QString m_deviceDescription;
|
QString m_deviceDescription;
|
||||||
};
|
};
|
||||||
|
|
74
plugins/samplesource/fcdproplus/fcdproplusplugin.cpp
Normal file
74
plugins/samplesource/fcdproplus/fcdproplusplugin.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
|
||||||
|
// //
|
||||||
|
// This program is free software; you can redistribute it and/or modify //
|
||||||
|
// it under the terms of the GNU General Public License as published by //
|
||||||
|
// the Free Software Foundation as version 3 of the License, or //
|
||||||
|
// //
|
||||||
|
// This program is distributed in the hope that it will be useful, //
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||||
|
// GNU General Public License V3 for more details. //
|
||||||
|
// //
|
||||||
|
// You should have received a copy of the GNU General Public License //
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <QtPlugin>
|
||||||
|
#include <QAction>
|
||||||
|
#include "plugin/pluginapi.h"
|
||||||
|
#include "util/simpleserializer.h"
|
||||||
|
#include "fcdproplusplugin.h"
|
||||||
|
#include "fcdproplusgui.h"
|
||||||
|
|
||||||
|
const PluginDescriptor FCDProPlusPlugin::m_pluginDescriptor = {
|
||||||
|
QString("FunCube Pro+ Input"),
|
||||||
|
QString("---"),
|
||||||
|
QString("(c) Edouard Griffiths, F4EXB"),
|
||||||
|
QString("https://github.com/f4exb/sdrangel"),
|
||||||
|
true,
|
||||||
|
QString("https://github.com/f4exb/sdrangel")
|
||||||
|
};
|
||||||
|
|
||||||
|
FCDProPlusPlugin::FCDProPlusPlugin(QObject* parent) :
|
||||||
|
QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const PluginDescriptor& FCDProPlusPlugin::getPluginDescriptor() const
|
||||||
|
{
|
||||||
|
return m_pluginDescriptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||||
|
{
|
||||||
|
m_pluginAPI = pluginAPI;
|
||||||
|
|
||||||
|
m_pluginAPI->registerSampleSource("org.osmocom.sdr.samplesource.fcdproplus", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginInterface::SampleSourceDevices FCDProPlusPlugin::enumSampleSources()
|
||||||
|
{
|
||||||
|
SampleSourceDevices result;
|
||||||
|
|
||||||
|
QString displayedName(QString("FunCube Pro+ #1"));
|
||||||
|
SimpleSerializer s(1);
|
||||||
|
s.writeS32(1, 0);
|
||||||
|
result.append(SampleSourceDevice(displayedName, "org.osmocom.sdr.samplesource.fcdproplus", s.final()));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
PluginGUI* FCDProPlusPlugin::createSampleSourcePluginGUI(const QString& sourceName, const QByteArray& address)
|
||||||
|
{
|
||||||
|
if(sourceName == "org.osmocom.sdr.samplesource.fcdproplus")
|
||||||
|
{
|
||||||
|
FCDProPlusGui* gui = new FCDProPlusGui(m_pluginAPI);
|
||||||
|
m_pluginAPI->setInputGUI(gui);
|
||||||
|
return gui;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
27
plugins/samplesource/fcdproplus/fcdproplusplugin.h
Normal file
27
plugins/samplesource/fcdproplus/fcdproplusplugin.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#ifndef INCLUDE_FCDPROPLUSPLUGIN_H
|
||||||
|
#define INCLUDE_FCDPROPLUSPLUGIN_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include "plugin/plugininterface.h"
|
||||||
|
|
||||||
|
class FCDProPlusPlugin : public QObject, public PluginInterface {
|
||||||
|
Q_OBJECT
|
||||||
|
Q_INTERFACES(PluginInterface)
|
||||||
|
Q_PLUGIN_METADATA(IID "org.osmocom.sdr.samplesource.fcdproplus")
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FCDProPlusPlugin(QObject* parent = NULL);
|
||||||
|
|
||||||
|
const PluginDescriptor& getPluginDescriptor() const;
|
||||||
|
void initPlugin(PluginAPI* pluginAPI);
|
||||||
|
|
||||||
|
SampleSourceDevices enumSampleSources();
|
||||||
|
PluginGUI* createSampleSourcePluginGUI(const QString& sourceName, const QByteArray& address);
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const PluginDescriptor m_pluginDescriptor;
|
||||||
|
|
||||||
|
PluginAPI* m_pluginAPI;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // INCLUDE_FCDPROPLUSPLUGIN_H
|
68
plugins/samplesource/fcdproplus/fcdproplusserializer.cpp
Normal file
68
plugins/samplesource/fcdproplus/fcdproplusserializer.cpp
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
|
||||||
|
// //
|
||||||
|
// This program is free software; you can redistribute it and/or modify //
|
||||||
|
// it under the terms of the GNU General Public License as published by //
|
||||||
|
// the Free Software Foundation as version 3 of the License, or //
|
||||||
|
// //
|
||||||
|
// 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 "fcdproplusserializer.h"
|
||||||
|
|
||||||
|
void FCDProPlusSerializer::writeSerializedData(const FCDData& data, QByteArray& serializedData)
|
||||||
|
{
|
||||||
|
QByteArray sampleSourceSerialized;
|
||||||
|
SampleSourceSerializer::writeSerializedData(data.m_data, sampleSourceSerialized);
|
||||||
|
|
||||||
|
SimpleSerializer s(1);
|
||||||
|
|
||||||
|
s.writeBlob(1, sampleSourceSerialized);
|
||||||
|
s.writeS32(2, data.m_bias);
|
||||||
|
s.writeS32(3, data.m_range);
|
||||||
|
|
||||||
|
serializedData = s.final();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FCDProPlusSerializer::readSerializedData(const QByteArray& serializedData, FCDData& data)
|
||||||
|
{
|
||||||
|
bool valid = SampleSourceSerializer::readSerializedData(serializedData, data.m_data);
|
||||||
|
|
||||||
|
QByteArray sampleSourceSerialized;
|
||||||
|
|
||||||
|
SimpleDeserializer d(serializedData);
|
||||||
|
|
||||||
|
if (!d.isValid())
|
||||||
|
{
|
||||||
|
setDefaults(data);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d.getVersion() == SampleSourceSerializer::getSerializerVersion())
|
||||||
|
{
|
||||||
|
int intval;
|
||||||
|
|
||||||
|
d.readBlob(1, &sampleSourceSerialized);
|
||||||
|
d.readS32(2, &data.m_bias);
|
||||||
|
d.readS32(3, &data.m_range);
|
||||||
|
|
||||||
|
return SampleSourceSerializer::readSerializedData(sampleSourceSerialized, data.m_data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setDefaults(data);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusSerializer::setDefaults(FCDData& data)
|
||||||
|
{
|
||||||
|
data.m_range = 0;
|
||||||
|
data.m_bias = 0;
|
||||||
|
}
|
39
plugins/samplesource/fcdproplus/fcdproplusserializer.h
Normal file
39
plugins/samplesource/fcdproplus/fcdproplusserializer.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (C) 2015 Edouard Griffiths, F4EXB //
|
||||||
|
// //
|
||||||
|
// This program is free software; you can redistribute it and/or modify //
|
||||||
|
// it under the terms of the GNU General Public License as published by //
|
||||||
|
// the Free Software Foundation as version 3 of the License, or //
|
||||||
|
// //
|
||||||
|
// 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 PLUGINS_SAMPLESOURCE_FCD_FCDPROPLUSSERIALIZER_H_
|
||||||
|
#define PLUGINS_SAMPLESOURCE_FCD_FCDPROPLUSSERIALIZER_H_
|
||||||
|
|
||||||
|
#include "util/samplesourceserializer.h"
|
||||||
|
|
||||||
|
class FCDProPlusSerializer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct FCDData
|
||||||
|
{
|
||||||
|
SampleSourceSerializer::Data m_data;
|
||||||
|
qint32 m_bias;
|
||||||
|
qint32 m_range;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void writeSerializedData(const FCDData& data, QByteArray& serializedData);
|
||||||
|
static bool readSerializedData(const QByteArray& serializedData, FCDData& data);
|
||||||
|
static void setDefaults(FCDData& data);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* PLUGINS_SAMPLESOURCE_FCD_FCDPROPLUSSERIALIZER_H_ */
|
164
plugins/samplesource/fcdproplus/fcdproplusthread.cpp
Normal file
164
plugins/samplesource/fcdproplus/fcdproplusthread.cpp
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// 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 <QDebug>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include "dsp/samplefifo.h"
|
||||||
|
#include "fcdproplusthread.h"
|
||||||
|
#include "fcdproplusinput.h"
|
||||||
|
|
||||||
|
FCDProPlusThread::FCDProPlusThread(SampleFifo* sampleFifo, QObject* parent) :
|
||||||
|
QThread(parent),
|
||||||
|
fcd_handle(NULL),
|
||||||
|
m_running(false),
|
||||||
|
m_convertBuffer(FCD_BLOCKSIZE),
|
||||||
|
m_sampleFifo(sampleFifo)
|
||||||
|
{
|
||||||
|
start();
|
||||||
|
}
|
||||||
|
|
||||||
|
FCDProPlusThread::~FCDProPlusThread()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusThread::startWork()
|
||||||
|
{
|
||||||
|
m_startWaitMutex.lock();
|
||||||
|
|
||||||
|
start();
|
||||||
|
|
||||||
|
while(!m_running)
|
||||||
|
{
|
||||||
|
m_startWaiter.wait(&m_startWaitMutex, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_startWaitMutex.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusThread::stopWork()
|
||||||
|
{
|
||||||
|
m_running = false;
|
||||||
|
wait();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusThread::run()
|
||||||
|
{
|
||||||
|
if ( !OpenSource("hw:CARD=V20") )
|
||||||
|
{
|
||||||
|
qCritical() << "FCDThread::run: cannot open FCD sound card";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: fallback to original fcd
|
||||||
|
|
||||||
|
m_running = true;
|
||||||
|
|
||||||
|
while(m_running)
|
||||||
|
{
|
||||||
|
if (work(FCD_BLOCKSIZE) < 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FCDProPlusThread::OpenSource(const char* cardname)
|
||||||
|
{
|
||||||
|
bool fail = false;
|
||||||
|
snd_pcm_hw_params_t* params;
|
||||||
|
//fcd_rate = FCDPP_RATE;
|
||||||
|
//fcd_channels =2;
|
||||||
|
//fcd_format = SND_PCM_SFMT_U16_LE;
|
||||||
|
snd_pcm_stream_t fcd_stream = SND_PCM_STREAM_CAPTURE;
|
||||||
|
|
||||||
|
if (fcd_handle)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snd_pcm_open(&fcd_handle, cardname, fcd_stream, 0) < 0)
|
||||||
|
{
|
||||||
|
qCritical("FCDThread::OpenSource: cannot open %s", cardname);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
snd_pcm_hw_params_alloca(¶ms);
|
||||||
|
|
||||||
|
if (snd_pcm_hw_params_any(fcd_handle, params) < 0)
|
||||||
|
{
|
||||||
|
qCritical("FCDProPlusThread::OpenSource: snd_pcm_hw_params_any failed");
|
||||||
|
fail = true;
|
||||||
|
}
|
||||||
|
else if (snd_pcm_hw_params(fcd_handle, params) < 0)
|
||||||
|
{
|
||||||
|
qCritical("FCDProPlusThread::OpenSource: snd_pcm_hw_params failed");
|
||||||
|
fail = true;
|
||||||
|
// TODO: check actual samplerate, may be crippled firmware
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (snd_pcm_start(fcd_handle) < 0)
|
||||||
|
{
|
||||||
|
qCritical("FCDProPlusThread::OpenSource: snd_pcm_start failed");
|
||||||
|
fail = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fail)
|
||||||
|
{
|
||||||
|
snd_pcm_close( fcd_handle );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
qDebug("FCDProPlusThread::OpenSource: Funcube stream started");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusThread::CloseSource()
|
||||||
|
{
|
||||||
|
if (fcd_handle)
|
||||||
|
{
|
||||||
|
snd_pcm_close( fcd_handle );
|
||||||
|
}
|
||||||
|
|
||||||
|
fcd_handle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int FCDProPlusThread::work(int n_items)
|
||||||
|
{
|
||||||
|
int l;
|
||||||
|
SampleVector::iterator it;
|
||||||
|
void *out;
|
||||||
|
|
||||||
|
it = m_convertBuffer.begin();
|
||||||
|
out = (void *)&it[0];
|
||||||
|
l = snd_pcm_mmap_readi(fcd_handle, out, (snd_pcm_uframes_t)n_items);
|
||||||
|
if (l > 0)
|
||||||
|
m_sampleFifo->write(it, it + l);
|
||||||
|
if (l == -EPIPE) {
|
||||||
|
qDebug("FCDProPlusThread::work: Overrun detected");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -25,15 +25,15 @@
|
|||||||
#include "dsp/inthalfbandfilter.h"
|
#include "dsp/inthalfbandfilter.h"
|
||||||
#include <alsa/asoundlib.h>
|
#include <alsa/asoundlib.h>
|
||||||
|
|
||||||
#define FCDPP_RATE 192000 // FIXME: The Pro / Pro+ switch should be handled better than this!
|
#define FCDPP_RATE 192000
|
||||||
#define FCD_BLOCKSIZE (1<<11)
|
#define FCD_BLOCKSIZE (1<<11)
|
||||||
|
|
||||||
class FCDThread : public QThread {
|
class FCDProPlusThread : public QThread {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FCDThread(SampleFifo* sampleFifo, QObject* parent = NULL);
|
FCDProPlusThread(SampleFifo* sampleFifo, QObject* parent = NULL);
|
||||||
~FCDThread();
|
~FCDProPlusThread();
|
||||||
|
|
||||||
void startWork();
|
void startWork();
|
||||||
void stopWork();
|
void stopWork();
|
Loading…
Reference in New Issue
Block a user