mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-26 09:48:45 -05:00
Deep redesign: Better support for FCD dongles #10: Proper support of FCD Pro+
This commit is contained in:
parent
7739db8fbe
commit
e784cf7f7f
@ -53,7 +53,7 @@ If you use your own location for libbladeRF install directory you need to specif
|
|||||||
|
|
||||||
<h2>FunCube Dongle</h2>
|
<h2>FunCube Dongle</h2>
|
||||||
|
|
||||||
Both Pro and Pro+ are supported with the plugins in fcdpro and fcdproplus respectively. This is a work in progress. Support of features is still limited for Pro+ (no IF gain, no filter settings) and inadapted for Pro which is just a copy from Pro+ apart from some constants to make it work with Pro.
|
Both Pro and Pro+ are supported with the plugins in fcdpro and fcdproplus respectively. This is a work in progress. For Pro+ the RF filter selection does not seem to be effective. Perhaps it is derived from the given center frequency internally. Support of features is still inadapted for Pro which is just a copy from Pro+ apart from some constants to make it work with Pro.
|
||||||
|
|
||||||
The control interface is based on qthid and has been built in the software in the fcdhid library. You don't need anything else than libusb support. Library fcdlib is used to store the constants for each dongle type.
|
The control interface is based on qthid and has been built in the software in the fcdhid library. You don't need anything else than libusb support. Library fcdlib is used to store the constants for each dongle type.
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <QDebug>
|
||||||
#include "ui_fcdproplusgui.h"
|
#include "ui_fcdproplusgui.h"
|
||||||
#include "plugin/pluginapi.h"
|
#include "plugin/pluginapi.h"
|
||||||
#include "gui/colormapper.h"
|
#include "gui/colormapper.h"
|
||||||
@ -15,7 +16,7 @@ FCDProPlusGui::FCDProPlusGui(PluginAPI* pluginAPI, QWidget* parent) :
|
|||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
|
|
||||||
ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold));
|
ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold));
|
||||||
ui->centerFrequency->setValueRange(7, 400000U, 2000000U);
|
ui->centerFrequency->setValueRange(7, 150U, 2000000U);
|
||||||
|
|
||||||
ui->filterIF->clear();
|
ui->filterIF->clear();
|
||||||
for (int i = 0; i < FCDProPlusConstants::fcdproplus_if_filter_nb_values(); i++)
|
for (int i = 0; i < FCDProPlusConstants::fcdproplus_if_filter_nb_values(); i++)
|
||||||
@ -96,9 +97,15 @@ bool FCDProPlusGui::handleMessage(const Message& message)
|
|||||||
void FCDProPlusGui::displaySettings()
|
void FCDProPlusGui::displaySettings()
|
||||||
{
|
{
|
||||||
ui->centerFrequency->setValue(m_settings.centerFrequency / 1000);
|
ui->centerFrequency->setValue(m_settings.centerFrequency / 1000);
|
||||||
ui->checkBoxR->setChecked(m_settings.rangeLow);
|
|
||||||
ui->checkBoxG->setChecked(m_settings.lnaGain);
|
ui->checkBoxG->setChecked(m_settings.lnaGain);
|
||||||
ui->checkBoxB->setChecked(m_settings.biasT);
|
ui->checkBoxB->setChecked(m_settings.biasT);
|
||||||
|
ui->mixGain->setChecked(m_settings.mixGain);
|
||||||
|
ui->ifGain->setValue(m_settings.ifGain);
|
||||||
|
ui->ifGainText->setText(QString("%1dB").arg(m_settings.ifGain));
|
||||||
|
ui->filterIF->setCurrentIndex(m_settings.ifFilterIndex);
|
||||||
|
ui->filterRF->setCurrentIndex(m_settings.rfFilterIndex);
|
||||||
|
ui->ppm->setValue(m_settings.LOppmTenths);
|
||||||
|
ui->ppmText->setText(QString("%1").arg(QString::number(m_settings.LOppmTenths/10.0, 'f', 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDProPlusGui::sendSettings()
|
void FCDProPlusGui::sendSettings()
|
||||||
@ -120,34 +127,6 @@ void FCDProPlusGui::updateHardware()
|
|||||||
m_updateTimer.stop();
|
m_updateTimer.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDProPlusGui::on_checkBoxR_stateChanged(int state)
|
|
||||||
{
|
|
||||||
if (state == Qt::Checked)
|
|
||||||
{
|
|
||||||
ui->centerFrequency->setValueRange(7, 150U, 240000U);
|
|
||||||
|
|
||||||
if ((ui->centerFrequency->getValue() < 150U) || (ui->centerFrequency->getValue() > 240000U))
|
|
||||||
{
|
|
||||||
ui->centerFrequency->setValue(7000);
|
|
||||||
m_settings.centerFrequency = 7000 * 1000;
|
|
||||||
m_settings.rangeLow = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ui->centerFrequency->setValueRange(7, 400000U, 2000000U);
|
|
||||||
|
|
||||||
if ((ui->centerFrequency->getValue() < 150U) || (ui->centerFrequency->getValue() > 240000U))
|
|
||||||
{
|
|
||||||
ui->centerFrequency->setValue(435000);
|
|
||||||
m_settings.centerFrequency = 435000 * 1000;
|
|
||||||
m_settings.rangeLow = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sendSettings();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FCDProPlusGui::on_checkBoxG_stateChanged(int state)
|
void FCDProPlusGui::on_checkBoxG_stateChanged(int state)
|
||||||
{
|
{
|
||||||
m_settings.lnaGain = (state == Qt::Checked);
|
m_settings.lnaGain = (state == Qt::Checked);
|
||||||
@ -181,6 +160,14 @@ void FCDProPlusGui::on_filterRF_currentIndexChanged(int index)
|
|||||||
void FCDProPlusGui::on_ifGain_valueChanged(int value)
|
void FCDProPlusGui::on_ifGain_valueChanged(int value)
|
||||||
{
|
{
|
||||||
m_settings.ifGain = value;
|
m_settings.ifGain = value;
|
||||||
|
displaySettings();
|
||||||
|
sendSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusGui::on_ppm_valueChanged(int value)
|
||||||
|
{
|
||||||
|
m_settings.LOppmTenths = value;
|
||||||
|
displaySettings();
|
||||||
sendSettings();
|
sendSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,13 +44,13 @@ private:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_centerFrequency_changed(quint64 value);
|
void on_centerFrequency_changed(quint64 value);
|
||||||
void on_checkBoxR_stateChanged(int state);
|
|
||||||
void on_checkBoxG_stateChanged(int state);
|
void on_checkBoxG_stateChanged(int state);
|
||||||
void on_checkBoxB_stateChanged(int state);
|
void on_checkBoxB_stateChanged(int state);
|
||||||
void on_mixGain_stateChanged(int state);
|
void on_mixGain_stateChanged(int state);
|
||||||
void on_ifGain_valueChanged(int value);
|
void on_ifGain_valueChanged(int value);
|
||||||
void on_filterRF_currentIndexChanged(int index);
|
void on_filterRF_currentIndexChanged(int index);
|
||||||
void on_filterIF_currentIndexChanged(int index);
|
void on_filterIF_currentIndexChanged(int index);
|
||||||
|
void on_ppm_valueChanged(int value);
|
||||||
void updateHardware();
|
void updateHardware();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,35 +100,33 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<layout class="QHBoxLayout" name="horizontalLayoutR">
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="mixGain">
|
|
||||||
<property name="text">
|
|
||||||
<string>Mix Gain</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="checkBoxR">
|
|
||||||
<property name="text">
|
|
||||||
<string>Low Range</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayoutG">
|
<layout class="QHBoxLayout" name="horizontalLayoutG">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="checkBoxG">
|
<widget class="QCheckBox" name="checkBoxG">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Activate LNA </string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>LNA Gain</string>
|
<string>LNA</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="mixGain">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Activate mixer gain</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Mix</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="checkBoxB">
|
<widget class="QCheckBox" name="checkBoxB">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Activate bias tee</string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Bias T</string>
|
<string>Bias T</string>
|
||||||
</property>
|
</property>
|
||||||
@ -147,6 +145,12 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSlider" name="ifGain">
|
<widget class="QSlider" name="ifGain">
|
||||||
|
<property name="maximum">
|
||||||
|
<number>59</number>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
@ -161,6 +165,43 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="ppmLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>LO ppm</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="ppm">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>LO ppm correction</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-100</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>100</number>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="ppmText">
|
||||||
|
<property name="text">
|
||||||
|
<string>0.0</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||||
<item>
|
<item>
|
||||||
|
@ -51,7 +51,8 @@ FCDProPlusInput::Settings::Settings() :
|
|||||||
biasT(false),
|
biasT(false),
|
||||||
ifGain(0),
|
ifGain(0),
|
||||||
ifFilterIndex(0),
|
ifFilterIndex(0),
|
||||||
rfFilterIndex(0)
|
rfFilterIndex(0),
|
||||||
|
LOppmTenths(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ void FCDProPlusInput::Settings::resetToDefaults()
|
|||||||
ifGain = 0;
|
ifGain = 0;
|
||||||
rfFilterIndex = 0;
|
rfFilterIndex = 0;
|
||||||
ifFilterIndex = 0;
|
ifFilterIndex = 0;
|
||||||
|
LOppmTenths = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray FCDProPlusInput::Settings::serialize() const
|
QByteArray FCDProPlusInput::Settings::serialize() const
|
||||||
@ -71,6 +73,7 @@ QByteArray FCDProPlusInput::Settings::serialize() const
|
|||||||
FCDProPlusSerializer::FCDData data;
|
FCDProPlusSerializer::FCDData data;
|
||||||
|
|
||||||
data.m_data.m_lnaGain = lnaGain;
|
data.m_data.m_lnaGain = lnaGain;
|
||||||
|
data.m_data.m_correction = LOppmTenths;
|
||||||
data.m_data.m_RxGain1 = ifGain;
|
data.m_data.m_RxGain1 = ifGain;
|
||||||
data.m_data.m_frequency = centerFrequency;
|
data.m_data.m_frequency = centerFrequency;
|
||||||
data.m_rangeLow = rangeLow;
|
data.m_rangeLow = rangeLow;
|
||||||
@ -98,6 +101,7 @@ bool FCDProPlusInput::Settings::deserialize(const QByteArray& serializedData)
|
|||||||
bool valid = FCDProPlusSerializer::readSerializedData(serializedData, data);
|
bool valid = FCDProPlusSerializer::readSerializedData(serializedData, data);
|
||||||
|
|
||||||
lnaGain = data.m_data.m_lnaGain;
|
lnaGain = data.m_data.m_lnaGain;
|
||||||
|
LOppmTenths = data.m_data.m_correction;
|
||||||
ifGain = data.m_data.m_RxGain1;
|
ifGain = data.m_data.m_RxGain1;
|
||||||
centerFrequency = data.m_data.m_frequency;
|
centerFrequency = data.m_data.m_frequency;
|
||||||
rangeLow = data.m_rangeLow;
|
rangeLow = data.m_rangeLow;
|
||||||
@ -255,7 +259,7 @@ void FCDProPlusInput::applySettings(const Settings& settings, bool force)
|
|||||||
|
|
||||||
if (m_dev != 0)
|
if (m_dev != 0)
|
||||||
{
|
{
|
||||||
set_lna_gain(settings.lnaGain > 0);
|
set_lna_gain(settings.lnaGain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,11 +269,61 @@ void FCDProPlusInput::applySettings(const Settings& settings, bool force)
|
|||||||
|
|
||||||
if (m_dev != 0)
|
if (m_dev != 0)
|
||||||
{
|
{
|
||||||
set_bias_t(settings.biasT > 0);
|
set_bias_t(settings.biasT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (signalChange)
|
if ((m_settings.mixGain != settings.mixGain) || force)
|
||||||
|
{
|
||||||
|
m_settings.mixGain = settings.mixGain;
|
||||||
|
|
||||||
|
if (m_dev != 0)
|
||||||
|
{
|
||||||
|
set_mixer_gain(settings.mixGain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_settings.ifGain != settings.ifGain) || force)
|
||||||
|
{
|
||||||
|
m_settings.ifGain = settings.ifGain;
|
||||||
|
|
||||||
|
if (m_dev != 0)
|
||||||
|
{
|
||||||
|
set_if_gain(settings.ifGain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_settings.ifFilterIndex != settings.ifFilterIndex) || force)
|
||||||
|
{
|
||||||
|
m_settings.ifFilterIndex = settings.ifFilterIndex;
|
||||||
|
|
||||||
|
if (m_dev != 0)
|
||||||
|
{
|
||||||
|
set_if_filter(settings.ifFilterIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_settings.rfFilterIndex != settings.rfFilterIndex) || force)
|
||||||
|
{
|
||||||
|
m_settings.rfFilterIndex = settings.rfFilterIndex;
|
||||||
|
|
||||||
|
if (m_dev != 0)
|
||||||
|
{
|
||||||
|
set_rf_filter(settings.rfFilterIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((m_settings.LOppmTenths != settings.LOppmTenths) || force)
|
||||||
|
{
|
||||||
|
m_settings.LOppmTenths = settings.LOppmTenths;
|
||||||
|
|
||||||
|
if (m_dev != 0)
|
||||||
|
{
|
||||||
|
set_lo_ppm();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (signalChange)
|
||||||
{
|
{
|
||||||
DSPSignalNotification *notif = new DSPSignalNotification(fcd_traits<ProPlus>::sampleRate, m_settings.centerFrequency);
|
DSPSignalNotification *notif = new DSPSignalNotification(fcd_traits<ProPlus>::sampleRate, m_settings.centerFrequency);
|
||||||
getOutputMessageQueue()->push(notif);
|
getOutputMessageQueue()->push(notif);
|
||||||
@ -278,6 +332,8 @@ void FCDProPlusInput::applySettings(const Settings& settings, bool force)
|
|||||||
|
|
||||||
void FCDProPlusInput::set_center_freq(double freq)
|
void FCDProPlusInput::set_center_freq(double freq)
|
||||||
{
|
{
|
||||||
|
freq += freq*(((double) m_settings.LOppmTenths)/10000000.0);
|
||||||
|
|
||||||
if (fcdAppSetFreq(m_dev, freq) == FCD_MODE_NONE)
|
if (fcdAppSetFreq(m_dev, freq) == FCD_MODE_NONE)
|
||||||
{
|
{
|
||||||
qDebug("No FCD HID found for frquency change");
|
qDebug("No FCD HID found for frquency change");
|
||||||
@ -314,7 +370,10 @@ void FCDProPlusInput::set_if_gain(int gain)
|
|||||||
|
|
||||||
quint8 cmd_value = gain;
|
quint8 cmd_value = gain;
|
||||||
|
|
||||||
fcdAppSetParam(m_dev, FCDPROPLUS_HID_CMD_SET_IF_GAIN, &cmd_value, 1);
|
if (fcdAppSetParam(m_dev, FCDPROPLUS_HID_CMD_SET_IF_GAIN, &cmd_value, 1) != FCD_MODE_APP)
|
||||||
|
{
|
||||||
|
qWarning() << "FCDProPlusInput::set_if_gain: failed to set at " << cmd_value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FCDProPlusInput::set_if_filter(int filterIndex)
|
void FCDProPlusInput::set_if_filter(int filterIndex)
|
||||||
@ -326,7 +385,10 @@ void FCDProPlusInput::set_if_filter(int filterIndex)
|
|||||||
|
|
||||||
quint8 cmd_value = FCDProPlusConstants::if_filters[filterIndex].value;
|
quint8 cmd_value = FCDProPlusConstants::if_filters[filterIndex].value;
|
||||||
|
|
||||||
fcdAppSetParam(m_dev, FCDPROPLUS_HID_CMD_SET_IF_FILTER, &cmd_value, 1);
|
if (fcdAppSetParam(m_dev, FCDPROPLUS_HID_CMD_SET_IF_FILTER, &cmd_value, 1) != FCD_MODE_APP)
|
||||||
|
{
|
||||||
|
qWarning() << "FCDProPlusInput::set_if_filter: failed to set at " << cmd_value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -339,8 +401,17 @@ void FCDProPlusInput::set_rf_filter(int filterIndex)
|
|||||||
|
|
||||||
quint8 cmd_value = FCDProPlusConstants::rf_filters[filterIndex].value;
|
quint8 cmd_value = FCDProPlusConstants::rf_filters[filterIndex].value;
|
||||||
|
|
||||||
fcdAppSetParam(m_dev, FCDPROPLUS_HID_CMD_SET_RF_FILTER, &cmd_value, 1);
|
if (fcdAppSetParam(m_dev, FCDPROPLUS_HID_CMD_SET_RF_FILTER, &cmd_value, 1) != FCD_MODE_APP)
|
||||||
|
{
|
||||||
|
qWarning() << "FCDProPlusInput::set_rf_filter: failed to set at " << cmd_value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FCDProPlusInput::set_lo_ppm()
|
||||||
|
{
|
||||||
|
set_center_freq((double) m_settings.centerFrequency);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ public:
|
|||||||
quint32 ifGain;
|
quint32 ifGain;
|
||||||
qint32 ifFilterIndex;
|
qint32 ifFilterIndex;
|
||||||
qint32 rfFilterIndex;
|
qint32 rfFilterIndex;
|
||||||
|
qint32 LOppmTenths;
|
||||||
void resetToDefaults();
|
void resetToDefaults();
|
||||||
QByteArray serialize() const;
|
QByteArray serialize() const;
|
||||||
bool deserialize(const QByteArray& data);
|
bool deserialize(const QByteArray& data);
|
||||||
@ -87,6 +88,7 @@ public:
|
|||||||
void set_if_gain(int gain);
|
void set_if_gain(int gain);
|
||||||
void set_rf_filter(int filterIndex);
|
void set_rf_filter(int filterIndex);
|
||||||
void set_if_filter(int filterIndex);
|
void set_if_filter(int filterIndex);
|
||||||
|
void set_lo_ppm();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void applySettings(const Settings& settings, bool force);
|
void applySettings(const Settings& settings, bool force);
|
||||||
|
Loading…
Reference in New Issue
Block a user