1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2026-06-02 14:04:46 -04:00

git clone git://git.osmocom.org/sdrangelove.git

This commit is contained in:
Hexameron
2014-05-18 16:52:39 +01:00
commit 7d3bfb26fc
203 changed files with 27958 additions and 0 deletions
@@ -0,0 +1,54 @@
project(osmosdr)
set(osmosdr_SOURCES
osmosdrgui.cpp
osmosdrinput.cpp
osmosdrplugin.cpp
osmosdrthread.cpp
)
set(osmosdr_HEADERS
osmosdrgui.h
osmosdrinput.h
osmosdrplugin.h
osmosdrthread.h
)
set(osmosdr_FORMS
osmosdrgui.ui
)
include_directories(
.
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/include-gpl
${LIBOSMOSDR_INCLUDE_DIR}
)
#include(${QT_USE_FILE})
add_definitions(${QT_DEFINITIONS})
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_SHARED)
if(MSVC)
add_definitions(-DNOMINMAX)
endif()
#qt4_wrap_cpp(osmosdr_HEADERS_MOC ${osmosdr_HEADERS})
qt5_wrap_ui(osmosdr_FORMS_HEADERS ${osmosdr_FORMS})
add_library(inputosmosdr SHARED
${osmosdr_SOURCES}
${osmosdr_HEADERS_MOC}
${osmosdr_FORMS_HEADERS}
)
target_link_libraries(inputosmosdr
${QT_LIBRARIES}
${LIBOSMOSDR_LIBRARIES}
${LIBUSB_LIBRARIES}
sdrbase
)
qt5_use_modules(inputosmosdr Core Widgets OpenGL Multimedia)
+310
View File
@@ -0,0 +1,310 @@
#include "osmosdrgui.h"
#include "ui_osmosdrgui.h"
#include "plugin/pluginapi.h"
OsmoSDRGui::OsmoSDRGui(PluginAPI* pluginAPI, QWidget* parent) :
QWidget(parent),
ui(new Ui::OsmoSDRGui),
m_pluginAPI(pluginAPI),
m_settings(),
m_sampleSource(NULL)
{
ui->setupUi(this);
ui->centerFrequency->setValueRange(7, 20000U, 2200000U);
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
displaySettings();
m_sampleSource = new OsmoSDRInput(m_pluginAPI->getMainWindowMessageQueue());
m_pluginAPI->setSampleSource(m_sampleSource);
}
OsmoSDRGui::~OsmoSDRGui()
{
delete ui;
}
void OsmoSDRGui::destroy()
{
delete this;
}
void OsmoSDRGui::setName(const QString& name)
{
setObjectName(name);
}
void OsmoSDRGui::resetToDefaults()
{
m_generalSettings.resetToDefaults();
m_settings.resetToDefaults();
displaySettings();
sendSettings();
}
QByteArray OsmoSDRGui::serializeGeneral() const
{
return m_generalSettings.serialize();
}
bool OsmoSDRGui::deserializeGeneral(const QByteArray&data)
{
if(m_generalSettings.deserialize(data)) {
displaySettings();
sendSettings();
return true;
} else {
resetToDefaults();
return false;
}
}
quint64 OsmoSDRGui::getCenterFrequency() const
{
return m_generalSettings.m_centerFrequency;
}
QByteArray OsmoSDRGui::serialize() const
{
return m_settings.serialize();
}
bool OsmoSDRGui::deserialize(const QByteArray& data)
{
if(m_settings.deserialize(data)) {
displaySettings();
sendSettings();
return true;
} else {
resetToDefaults();
return false;
}
}
bool OsmoSDRGui::handleMessage(Message* message)
{
return false;
/*
if(message->id() == OsmoSDRInput::MsgReportOsmoSDR::ID()) {
m_gains = ((RTLSDRInput::MsgReportRTLSDR*)message)->getGains();
displaySettings();
message->completed();
return true;
} else {
return false;
}*/
}
#if 0
OsmoSDRGui::OsmoSDRGui(MessageQueue* msgQueue, QWidget* parent) :
SampleSourceGUI(parent),
ui(new Ui::OsmoSDRGui),
m_msgQueue(msgQueue),
m_settings()
{
ui->setupUi(this);
ui->centerFrequency->setValueRange(7, 20000U, 2200000U);
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
displaySettings();
}
OsmoSDRGui::~OsmoSDRGui()
{
delete ui;
}
QString OsmoSDRGui::serializeSettings() const
{
return m_settings.serialize();
}
bool OsmoSDRGui::deserializeSettings(const QString& settings)
{
if(m_settings.deserialize(settings)) {
displaySettings();
sendSettings();
return true;
} else {
return false;
}
}
bool OsmoSDRGui::handleSourceMessage(DSPCmdSourceToGUI* cmd)
{
return false;
}
#endif
void OsmoSDRGui::displaySettings()
{
ui->centerFrequency->setValue(m_generalSettings.m_centerFrequency / 1000);
ui->iqSwap->setChecked(m_settings.m_swapIQ);
ui->decimation->setValue(m_settings.m_decimation);
ui->e4000LNAGain->setValue(e4kLNAGainToIdx(m_settings.m_lnaGain));
ui->e4000MixerGain->setCurrentIndex((m_settings.m_mixerGain - 40) / 80);
if(m_settings.m_mixerEnhancement == 0)
ui->e4000MixerEnh->setCurrentIndex(0);
else ui->e4000MixerEnh->setCurrentIndex((m_settings.m_mixerEnhancement + 10) / 20);
ui->e4000if1->setCurrentIndex((m_settings.m_if1gain + 30) / 90);
ui->e4000if2->setCurrentIndex(m_settings.m_if2gain / 30);
ui->e4000if3->setCurrentIndex(m_settings.m_if3gain / 30);
ui->e4000if4->setCurrentIndex(m_settings.m_if4gain / 10);
ui->e4000if5->setCurrentIndex(m_settings.m_if5gain / 30 - 1);
ui->e4000if6->setCurrentIndex(m_settings.m_if6gain / 30 - 1);
ui->filterI1->setValue(m_settings.m_opAmpI1);
ui->filterI2->setValue(m_settings.m_opAmpI2);
ui->filterQ1->setValue(m_settings.m_opAmpQ1);
ui->filterQ2->setValue(m_settings.m_opAmpQ2);
ui->e4kI->setValue(m_settings.m_dcOfsI);
ui->e4kQ->setValue(m_settings.m_dcOfsQ);
}
void OsmoSDRGui::sendSettings()
{
if(!m_updateTimer.isActive())
m_updateTimer.start(100);
}
int OsmoSDRGui::e4kLNAGainToIdx(int gain) const
{
static const quint32 gainList[13] = {
-50, -25, 0, 25, 50, 75, 100, 125, 150, 175, 200, 250, 300
};
for(int i = 0; i < 13; i++) {
if(gainList[i] == gain)
return i;
}
return 0;
}
int OsmoSDRGui::e4kIdxToLNAGain(int idx) const
{
static const quint32 gainList[13] = {
-50, -25, 0, 25, 50, 75, 100, 125, 150, 175, 200, 250, 300
};
if((idx < 0) || (idx >= 13))
return -50;
else return gainList[idx];
}
void OsmoSDRGui::on_iqSwap_toggled(bool checked)
{
m_settings.m_swapIQ = checked;
sendSettings();
}
void OsmoSDRGui::on_e4000MixerGain_currentIndexChanged(int index)
{
m_settings.m_mixerGain = index * 80 + 40;
sendSettings();
}
void OsmoSDRGui::on_e4000MixerEnh_currentIndexChanged(int index)
{
if(index == 0)
m_settings.m_mixerEnhancement = 0;
else m_settings.m_mixerEnhancement = index * 20 - 10;
sendSettings();
}
void OsmoSDRGui::on_e4000if1_currentIndexChanged(int index)
{
m_settings.m_if1gain = index * 90 - 30;
sendSettings();
}
void OsmoSDRGui::on_e4000if2_currentIndexChanged(int index)
{
m_settings.m_if2gain = index * 30;
sendSettings();
}
void OsmoSDRGui::on_e4000if3_currentIndexChanged(int index)
{
m_settings.m_if3gain = index * 30;
sendSettings();
}
void OsmoSDRGui::on_e4000if4_currentIndexChanged(int index)
{
m_settings.m_if4gain = index * 10;
sendSettings();
}
void OsmoSDRGui::on_e4000if5_currentIndexChanged(int index)
{
m_settings.m_if5gain = (index + 1) * 30;
sendSettings();
}
void OsmoSDRGui::on_e4000if6_currentIndexChanged(int index)
{
m_settings.m_if6gain = (index + 1) * 30;
sendSettings();
}
void OsmoSDRGui::on_centerFrequency_changed(quint64 value)
{
m_generalSettings.m_centerFrequency = value * 1000;
sendSettings();
}
void OsmoSDRGui::on_filterI1_valueChanged(int value)
{
m_settings.m_opAmpI1 = value;
sendSettings();
}
void OsmoSDRGui::on_filterI2_valueChanged(int value)
{
m_settings.m_opAmpI2 = value;
sendSettings();
}
void OsmoSDRGui::on_filterQ1_valueChanged(int value)
{
m_settings.m_opAmpQ1 = value;
sendSettings();
}
void OsmoSDRGui::on_filterQ2_valueChanged(int value)
{
m_settings.m_opAmpQ2 = value;
sendSettings();
}
void OsmoSDRGui::on_decimation_valueChanged(int value)
{
ui->decimationDisplay->setText(tr("1:%1").arg(1 << value));
m_settings.m_decimation = value;
sendSettings();
}
void OsmoSDRGui::on_e4000LNAGain_valueChanged(int value)
{
int gain = e4kIdxToLNAGain(value);
ui->e4000LNAGainDisplay->setText(tr("%1.%2").arg(gain / 10).arg(abs(gain % 10)));
m_settings.m_lnaGain = gain;
sendSettings();
}
void OsmoSDRGui::on_e4kI_valueChanged(int value)
{
m_settings.m_dcOfsI = value;
sendSettings();
}
void OsmoSDRGui::on_e4kQ_valueChanged(int value)
{
m_settings.m_dcOfsQ = value;
sendSettings();
}
void OsmoSDRGui::updateHardware()
{
m_updateTimer.stop();
Message* msg = OsmoSDRInput::MsgConfigureOsmoSDR::create(m_generalSettings, m_settings);
msg->submit(m_pluginAPI->getDSPEngineMessageQueue());
}
+70
View File
@@ -0,0 +1,70 @@
#ifndef INCLUDE_OSMOSDRGUI_H
#define INCLUDE_OSMOSDRGUI_H
#include <QTimer>
#include "plugin/plugingui.h"
#include "osmosdrinput.h"
class PluginAPI;
namespace Ui {
class OsmoSDRGui;
}
class OsmoSDRGui : public QWidget, public PluginGUI {
Q_OBJECT
public:
explicit OsmoSDRGui(PluginAPI* pluginAPI, QWidget* parent = NULL);
~OsmoSDRGui();
void destroy();
void setName(const QString& name);
void resetToDefaults();
QByteArray serializeGeneral() const;
bool deserializeGeneral(const QByteArray&data);
quint64 getCenterFrequency() const;
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
bool handleMessage(Message* message);
private:
Ui::OsmoSDRGui* ui;
PluginAPI* m_pluginAPI;
SampleSource::GeneralSettings m_generalSettings;
OsmoSDRInput::Settings m_settings;
QTimer m_updateTimer;
std::vector<int> m_gains;
SampleSource* m_sampleSource;
void displaySettings();
void sendSettings();
int e4kLNAGainToIdx(int gain) const;
int e4kIdxToLNAGain(int idx) const;
private slots:
void on_iqSwap_toggled(bool checked);
void on_e4000MixerGain_currentIndexChanged(int index);
void on_e4000MixerEnh_currentIndexChanged(int index);
void on_e4000if1_currentIndexChanged(int index);
void on_e4000if2_currentIndexChanged(int index);
void on_e4000if3_currentIndexChanged(int index);
void on_e4000if4_currentIndexChanged(int index);
void on_e4000if5_currentIndexChanged(int index);
void on_e4000if6_currentIndexChanged(int index);
void on_centerFrequency_changed(quint64 value);
void on_filterI1_valueChanged(int value);
void on_filterI2_valueChanged(int value);
void on_filterQ1_valueChanged(int value);
void on_filterQ2_valueChanged(int value);
void on_decimation_valueChanged(int value);
void on_e4000LNAGain_valueChanged(int value);
void on_e4kI_valueChanged(int value);
void on_e4kQ_valueChanged(int value);
void updateHardware();
};
#endif // INCLUDE_OSMOSDRGUI_H
+770
View File
@@ -0,0 +1,770 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OsmoSDRGui</class>
<widget class="QWidget" name="OsmoSDRGui">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>253</width>
<height>229</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>OsmoSDR</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>3</number>
</property>
<property name="margin">
<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="horizontalLayout">
<property name="spacing">
<number>3</number>
</property>
<item>
<widget class="QLabel" name="label_13">
<property name="text">
<string>Decimation</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="decimation">
<property name="toolTip">
<string>Signal decimation factor</string>
</property>
<property name="maximum">
<number>5</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="decimationDisplay">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>1:1</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>3</number>
</property>
<item>
<widget class="QLabel" name="label_11">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>LNA</string>
</property>
</widget>
</item>
<item>
<widget class="QSlider" name="e4000LNAGain">
<property name="toolTip">
<string>LNA amplification</string>
</property>
<property name="maximum">
<number>12</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="e4000LNAGainDisplay">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="text">
<string>-5.0</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="leftMargin">
<number>10</number>
</property>
<item>
<widget class="QLabel" name="label_19">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Mix</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="e4000MixerGain">
<property name="toolTip">
<string>Tuner mixer amplification</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
</property>
<item>
<property name="text">
<string>4</string>
</property>
</item>
<item>
<property name="text">
<string>12</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="label_20">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Enh.</string>
</property>
</widget>
</item>
<item>
<widget class="QComboBox" name="e4000MixerEnh">
<property name="toolTip">
<string>Tuner LNA amplification enhancement</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
</property>
<item>
<property name="text">
<string>off</string>
</property>
</item>
<item>
<property name="text">
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>3</string>
</property>
</item>
<item>
<property name="text">
<string>5</string>
</property>
</item>
<item>
<property name="text">
<string>7</string>
</property>
</item>
</widget>
</item>
<item>
<widget class="Line" name="line_5">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="iqSwap">
<property name="text">
<string>Swap IQ</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout_4">
<property name="topMargin">
<number>0</number>
</property>
<property name="spacing">
<number>3</number>
</property>
<item row="1" column="1">
<widget class="QComboBox" name="e4000if2">
<property name="toolTip">
<string>Tuner IF 2 amplification</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
<item>
<property name="text">
<string>0</string>
</property>
</item>
<item>
<property name="text">
<string>3</string>
</property>
</item>
<item>
<property name="text">
<string>6</string>
</property>
</item>
<item>
<property name="text">
<string>9</string>
</property>
</item>
</widget>
</item>
<item row="1" column="3">
<widget class="QComboBox" name="e4000if4">
<property name="toolTip">
<string>Tuner IF 4 amplification</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
<item>
<property name="text">
<string>0</string>
</property>
</item>
<item>
<property name="text">
<string>1</string>
</property>
</item>
<item>
<property name="text">
<string>2</string>
</property>
</item>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="label_18">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>IF4</string>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QLabel" name="label_25">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>IF5</string>
</property>
</widget>
</item>
<item row="0" column="5">
<widget class="QComboBox" name="e4000if5">
<property name="toolTip">
<string>Tuner IF 5 amplification</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
<item>
<property name="text">
<string>3</string>
</property>
</item>
<item>
<property name="text">
<string>6</string>
</property>
</item>
<item>
<property name="text">
<string>9</string>
</property>
</item>
<item>
<property name="text">
<string>12</string>
</property>
</item>
<item>
<property name="text">
<string>15</string>
</property>
</item>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="label_26">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>IF6</string>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QComboBox" name="e4000if3">
<property name="toolTip">
<string>Tuner IF 3 amplification</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
<item>
<property name="text">
<string>0</string>
</property>
</item>
<item>
<property name="text">
<string>3</string>
</property>
</item>
<item>
<property name="text">
<string>6</string>
</property>
</item>
<item>
<property name="text">
<string>9</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_23">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>IF2</string>
</property>
</widget>
</item>
<item row="1" column="5">
<widget class="QComboBox" name="e4000if6">
<property name="toolTip">
<string>Tuner IF 6 amplification</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
<item>
<property name="text">
<string>3</string>
</property>
</item>
<item>
<property name="text">
<string>6</string>
</property>
</item>
<item>
<property name="text">
<string>9</string>
</property>
</item>
<item>
<property name="text">
<string>12</string>
</property>
</item>
<item>
<property name="text">
<string>15</string>
</property>
</item>
</widget>
</item>
<item row="0" column="2">
<widget class="QLabel" name="label_24">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>IF3</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="e4000if1">
<property name="toolTip">
<string>Tuner IF 1 amplification</string>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
<item>
<property name="text">
<string>-3</string>
</property>
</item>
<item>
<property name="text">
<string>6</string>
</property>
</item>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="label_12">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>IF1</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<property name="spacing">
<number>3</number>
</property>
<item row="0" column="2">
<widget class="QLabel" name="label_6">
<property name="text">
<string>Poti 2</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>I</string>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QSlider" name="filterI2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>I DC offset adjustment</string>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QSlider" name="filterI1">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>I path amplification</string>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSlider" name="filterQ1">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Q path amplification</string>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QSlider" name="filterQ2">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Q DC offset adjustment</string>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QSlider" name="e4kQ">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Q DC offset adjustment</string>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="label_7">
<property name="text">
<string>E4000</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Q</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Poti 1</string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QSlider" name="e4kI">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="toolTip">
<string>Q path amplification</string>
</property>
<property name="maximum">
<number>255</number>
</property>
<property name="pageStep">
<number>1</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</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>
@@ -0,0 +1,479 @@
///////////////////////////////////////////////////////////////////////////////////
// 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 <string.h>
#include <errno.h>
#include "osmosdrinput.h"
#include "osmosdrthread.h"
#include "osmosdrgui.h"
#include "util/simpleserializer.h"
MESSAGE_CLASS_DEFINITION(OsmoSDRInput::MsgConfigureOsmoSDR, Message)
OsmoSDRInput::Settings::Settings() :
m_swapIQ(false),
m_decimation(3),
m_lnaGain(-50),
m_mixerGain(40),
m_mixerEnhancement(0),
m_if1gain(-30),
m_if2gain(0),
m_if3gain(0),
m_if4gain(0),
m_if5gain(30),
m_if6gain(30),
m_opAmpI1(0),
m_opAmpI2(0),
m_opAmpQ1(0),
m_opAmpQ2(0),
m_dcOfsI(0),
m_dcOfsQ(0)
{
}
void OsmoSDRInput::Settings::resetToDefaults()
{
m_swapIQ = false;
m_decimation = 3;
m_lnaGain = -50;
m_mixerGain = 40;
m_mixerEnhancement = 0;
m_if1gain = -30;
m_if2gain = 0;
m_if3gain = 0;
m_if4gain = 0;
m_if5gain = 30;
m_if6gain = 30;
m_opAmpI1 = 0;
m_opAmpI2 = 0;
m_opAmpQ1 = 0;
m_opAmpQ2 = 0;
m_dcOfsI = 0;
m_dcOfsQ = 0;
}
QByteArray OsmoSDRInput::Settings::serialize() const
{
SimpleSerializer s(1);
s.writeBool(1, m_swapIQ);
s.writeS32(2, m_decimation);
s.writeS32(3, m_lnaGain);
s.writeS32(4, m_mixerGain);
s.writeS32(5, m_mixerEnhancement);
s.writeS32(6, m_if1gain);
s.writeS32(7, m_if2gain);
s.writeS32(8, m_if3gain);
s.writeS32(9, m_if4gain);
s.writeS32(10, m_if5gain);
s.writeS32(11, m_if6gain);
s.writeS32(12, m_opAmpI1);
s.writeS32(13, m_opAmpI2);
s.writeS32(14, m_opAmpQ1);
s.writeS32(15, m_opAmpQ2);
s.writeS32(16, m_dcOfsI);
s.writeS32(17, m_dcOfsQ);
return s.final();
}
bool OsmoSDRInput::Settings::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if(!d.isValid()) {
resetToDefaults();
return false;
}
if(d.getVersion() == 1) {
d.readBool(1, &m_swapIQ, false);
d.readS32(2, &m_decimation, 3);
d.readS32(3, &m_lnaGain, -50);
d.readS32(4, &m_mixerGain, 40);
d.readS32(5, &m_mixerEnhancement, 0);
d.readS32(6, &m_if1gain, -30);
d.readS32(7, &m_if2gain, 0);
d.readS32(8, &m_if3gain, 0);
d.readS32(9, &m_if4gain, 0);
d.readS32(10, &m_if5gain, 30);
d.readS32(11, &m_if6gain, 30);
d.readS32(12, &m_opAmpI1, 0);
d.readS32(13, &m_opAmpI2, 0);
d.readS32(14, &m_opAmpQ1, 0);
d.readS32(15, &m_opAmpQ2, 0);
d.readS32(16, &m_dcOfsI, 0);
d.readS32(17, &m_dcOfsQ, 0);
return true;
} else {
resetToDefaults();
return false;
}
}
#if 0
OsmoSDRInput::Settings::Settings() :
{
}
QString OsmoSDRInput::Settings::serialize() const
{
return QString("osmosdr:a:%1:%2:%3:%4:%5:%6:%7:%8:%9:%10:%11:%12:%13:%14:%15:%16:%17:%18")
.arg(centerFrequency)
.arg(swapIQ ? 1 : 0)
.arg(decimation)
.arg(lnaGain)
.arg(mixerGain)
.arg(mixerEnhancement)
.arg(if1gain)
.arg(if2gain)
.arg(if3gain)
.arg(if4gain)
.arg(if5gain)
.arg(if6gain)
.arg(opAmpI1)
.arg(opAmpI2)
.arg(opAmpQ1)
.arg(opAmpQ2)
.arg(dcOfsI)
.arg(dcOfsQ);
}
bool OsmoSDRInput::Settings::deserialize(const QString& settings)
{
QStringList list = settings.split(":");
if(list.size() < 2)
return false;
if(list[0] != "osmosdr")
return false;
if(list[1] == "a") {
bool ok;
if(list.size() != 20)
return false;
centerFrequency = list[2].toLongLong(&ok);
if(!ok)
return false;
swapIQ = (list[3].toInt(&ok) != 0) ? true : false;
if(!ok)
return false;
decimation = list[4].toInt(&ok);
if(!ok)
return false;
lnaGain = list[5].toInt(&ok);
if(!ok)
return false;
mixerGain = list[6].toInt(&ok);
if(!ok)
return false;
mixerEnhancement = list[7].toInt(&ok);
if(!ok)
return false;
if1gain = list[8].toInt(&ok);
if(!ok)
return false;
if2gain = list[9].toInt(&ok);
if(!ok)
return false;
if3gain = list[10].toInt(&ok);
if(!ok)
return false;
if4gain = list[11].toInt(&ok);
if(!ok)
return false;
if5gain = list[12].toInt(&ok);
if(!ok)
return false;
if6gain = list[13].toInt(&ok);
if(!ok)
return false;
opAmpI1 = list[14].toInt(&ok);
if(!ok)
return false;
opAmpI2 = list[15].toInt(&ok);
if(!ok)
return false;
opAmpQ1 = list[16].toInt(&ok);
if(!ok)
return false;
opAmpQ2 = list[17].toInt(&ok);
if(!ok)
return false;
dcOfsI = list[18].toInt(&ok);
if(!ok)
return false;
dcOfsQ = list[19].toInt(&ok);
if(!ok)
return false;
return true;
} else {
return false;
}
}
MessageRegistrator OsmoSDRInput::MsgConfigureSourceOsmoSDR::ID("MsgConfigureSourceOsmoSDR");
#endif
OsmoSDRInput::OsmoSDRInput(MessageQueue* msgQueueToGUI) :
SampleSource(msgQueueToGUI),
m_settings(),
m_dev(NULL),
m_osmoSDRThread(NULL),
m_deviceDescription()
{
}
OsmoSDRInput::~OsmoSDRInput()
{
stopInput();
}
bool OsmoSDRInput::startInput(int device)
{
QMutexLocker mutexLocker(&m_mutex);
if(m_dev != NULL)
stopInput();
char vendor[256];
char product[256];
char serial[256];
int res;
if(!m_sampleFifo.setSize(524288)) {
qCritical("Could not allocate SampleFifo");
return false;
}
if((res = osmosdr_open(&m_dev, device)) < 0) {
qCritical("could not open OsmoSDR #%d: %s", device, strerror(errno));
return false;
}
vendor[0] = '\0';
product[0] = '\0';
serial[0] = '\0';
if((res = osmosdr_get_usb_strings(m_dev, vendor, product, serial)) < 0) {
qCritical("error accessing USB device");
goto failed;
}
qDebug("OsmoSDRInput open: %s %s, SN: %s", vendor, product, serial);
m_deviceDescription = QString("%1 (SN %2)").arg(product).arg(serial);
if((res = osmosdr_set_tuner_gain_mode(m_dev, 1)) < 0) {
qCritical("error setting tuner gain mode");
goto failed;
}
if((res = osmosdr_reset_buffer(m_dev)) < 0) {
qCritical("could not reset USB EP buffers: %s", strerror(errno));
goto failed;
}
if((m_osmoSDRThread = new OsmoSDRThread(m_dev, &m_sampleFifo)) == NULL) {
qFatal("out of memory");
goto failed;
}
m_osmoSDRThread->startWork();
mutexLocker.unlock();
applySettings(m_generalSettings, m_settings, true);
qDebug("OsmoSDRInput: start");
return true;
failed:
stopInput();
return false;
}
void OsmoSDRInput::stopInput()
{
QMutexLocker mutexLocker(&m_mutex);
if(m_osmoSDRThread != NULL) {
m_osmoSDRThread->stopWork();
delete m_osmoSDRThread;
m_osmoSDRThread = NULL;
}
if(m_dev != NULL) {
osmosdr_close(m_dev);
m_dev = NULL;
}
m_deviceDescription.clear();
}
const QString& OsmoSDRInput::getDeviceDescription() const
{
return m_deviceDescription;
}
int OsmoSDRInput::getSampleRate() const
{
return 4000000 / (1 << m_settings.m_decimation);
}
quint64 OsmoSDRInput::getCenterFrequency() const
{
return m_generalSettings.m_centerFrequency;
}
bool OsmoSDRInput::handleMessage(Message* message)
{
if(MsgConfigureOsmoSDR::match(message)) {
MsgConfigureOsmoSDR* conf = (MsgConfigureOsmoSDR*)message;
if(!applySettings(conf->getGeneralSettings(), conf->getSettings(), false))
qDebug("OsmoSDR config error");
message->completed();
return true;
} else {
return false;
}
/*
if(cmd->sourceType() != DSPCmdConfigureSourceOsmoSDR::SourceType)
return false;
if(!applySettings(((DSPCmdConfigureSourceOsmoSDR*)cmd)->getSettings(), false))
qDebug("OsmoSDR config error");
cmd->completed();
return true;
*/
return false;
}
bool OsmoSDRInput::applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force)
{
QMutexLocker mutexLocker(&m_mutex);
if((m_generalSettings.m_centerFrequency != generalSettings.m_centerFrequency) || force) {
m_generalSettings.m_centerFrequency = generalSettings.m_centerFrequency;
if(m_dev != NULL) {
if(osmosdr_set_center_freq(m_dev, m_generalSettings.m_centerFrequency) != 0)
qDebug("osmosdr_set_center_freq(%lld) failed", m_generalSettings.m_centerFrequency);
}
}
if((m_settings.m_swapIQ != settings.m_swapIQ) || force) {
m_settings.m_swapIQ = settings.m_swapIQ;
if(m_dev != NULL) {
if(osmosdr_set_fpga_iq_swap(m_dev, m_settings.m_swapIQ ? 1 : 0) == 0)
qDebug("osmosdr_set_fpga_iq_swap() failed");
}
}
if((m_settings.m_decimation != settings.m_decimation) || force) {
m_settings.m_decimation = settings.m_decimation;
if(m_dev != NULL) {
if(!osmosdr_set_fpga_decimation(m_dev, m_settings.m_decimation))
qDebug("osmosdr_set_fpga_decimation() failed");
}
}
if((m_settings.m_lnaGain != settings.m_lnaGain) || force) {
m_settings.m_lnaGain = settings.m_lnaGain;
if(m_dev != NULL) {
if(!osmosdr_set_tuner_lna_gain(m_dev, m_settings.m_lnaGain))
qDebug("osmosdr_set_tuner_lna_gain() failed");
}
}
if((m_settings.m_mixerGain != settings.m_mixerGain) || force) {
m_settings.m_mixerGain = settings.m_mixerGain;
if(m_dev != NULL) {
if(!osmosdr_set_tuner_mixer_gain(m_dev, m_settings.m_mixerGain))
qDebug("osmosdr_set_tuner_mixer_gain() failed");
}
}
if((m_settings.m_mixerEnhancement != settings.m_mixerEnhancement) || force) {
m_settings.m_mixerEnhancement = settings.m_mixerEnhancement;
if(m_dev != NULL) {
if(!osmosdr_set_tuner_mixer_enh(m_dev, m_settings.m_mixerEnhancement))
qDebug("osmosdr_set_tuner_mixer_enh() failed");
}
}
if((m_settings.m_if1gain != settings.m_if1gain) || force) {
m_settings.m_if1gain = settings.m_if1gain;
if(m_dev != NULL) {
if(!osmosdr_set_tuner_if_gain(m_dev, 1, m_settings.m_if1gain))
qDebug("osmosdr_set_tuner_if_gain(1) failed");
}
}
if((m_settings.m_if2gain != settings.m_if2gain) || force) {
m_settings.m_if2gain = settings.m_if2gain;
if(m_dev != NULL) {
if(!osmosdr_set_tuner_if_gain(m_dev, 2, m_settings.m_if2gain))
qDebug("osmosdr_set_tuner_if_gain(2) failed");
}
}
if((m_settings.m_if3gain != settings.m_if3gain) || force) {
m_settings.m_if3gain = settings.m_if3gain;
if(m_dev != NULL) {
if(!osmosdr_set_tuner_if_gain(m_dev, 3, m_settings.m_if3gain))
qDebug("osmosdr_set_tuner_if_gain(3) failed");
}
}
if((m_settings.m_if4gain != settings.m_if4gain) || force) {
m_settings.m_if4gain = settings.m_if4gain;
if(m_dev != NULL) {
if(!osmosdr_set_tuner_if_gain(m_dev, 4, m_settings.m_if4gain))
qDebug("osmosdr_set_tuner_if_gain(4) failed");
}
}
if((m_settings.m_if5gain != settings.m_if5gain) || force) {
m_settings.m_if5gain = settings.m_if5gain;
if(m_dev != NULL) {
if(!osmosdr_set_tuner_if_gain(m_dev, 5, m_settings.m_if5gain))
qDebug("osmosdr_set_tuner_if_gain(5) failed");
}
}
if((m_settings.m_if6gain != settings.m_if6gain) || force) {
m_settings.m_if6gain = settings.m_if6gain;
if(m_dev != NULL) {
if(!osmosdr_set_tuner_if_gain(m_dev, 6, m_settings.m_if6gain))
qDebug("osmosdr_set_tuner_if_gain(6) failed");
}
}
if((m_settings.m_opAmpI1 != settings.m_opAmpI1) || (m_settings.m_opAmpI2 != settings.m_opAmpI2) ||
(m_settings.m_opAmpQ1 != settings.m_opAmpQ1) || (m_settings.m_opAmpQ2 != settings.m_opAmpQ2) ||
force) {
m_settings.m_opAmpI1 = settings.m_opAmpI1;
m_settings.m_opAmpI2 = settings.m_opAmpI2;
m_settings.m_opAmpQ1 = settings.m_opAmpQ1;
m_settings.m_opAmpQ2 = settings.m_opAmpQ2;
if(m_dev != NULL) {
if(!osmosdr_set_iq_amp(m_dev, m_settings.m_opAmpI1, m_settings.m_opAmpI2, m_settings.m_opAmpQ1, m_settings.m_opAmpQ2))
qDebug("osmosdr_set_iq_amp(1) failed");
}
}
if((m_settings.m_dcOfsI != settings.m_dcOfsI) || (m_settings.m_dcOfsQ != settings.m_dcOfsQ) ||
force) {
m_settings.m_dcOfsI = settings.m_dcOfsI;
m_settings.m_dcOfsQ = settings.m_dcOfsQ;
if(m_dev != NULL) {
if(!osmosdr_set_tuner_dc_offset(m_dev, m_settings.m_dcOfsI, m_settings.m_dcOfsQ))
qDebug("osmosdr_set_tuner_dc_offset() failed");
}
}
return true;
}
@@ -0,0 +1,99 @@
///////////////////////////////////////////////////////////////////////////////////
// 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_OSMOSDRINPUT_H
#define INCLUDE_OSMOSDRINPUT_H
#include "dsp/samplesource/samplesource.h"
#include <osmosdr.h>
#include <QString>
class OsmoSDRThread;
class OsmoSDRInput : public SampleSource {
public:
struct Settings {
bool m_swapIQ;
qint32 m_decimation;
qint32 m_lnaGain;
qint32 m_mixerGain;
qint32 m_mixerEnhancement;
qint32 m_if1gain;
qint32 m_if2gain;
qint32 m_if3gain;
qint32 m_if4gain;
qint32 m_if5gain;
qint32 m_if6gain;
qint32 m_opAmpI1;
qint32 m_opAmpI2;
qint32 m_opAmpQ1;
qint32 m_opAmpQ2;
qint32 m_dcOfsI;
qint32 m_dcOfsQ;
Settings();
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
};
class MsgConfigureOsmoSDR : public Message {
MESSAGE_CLASS_DECLARATION
public:
const GeneralSettings& getGeneralSettings() const { return m_generalSettings; }
const Settings& getSettings() const { return m_settings; }
static MsgConfigureOsmoSDR* create(const GeneralSettings& generalSettings, const Settings& settings)
{
return new MsgConfigureOsmoSDR(generalSettings, settings);
}
protected:
GeneralSettings m_generalSettings;
Settings m_settings;
MsgConfigureOsmoSDR(const GeneralSettings& generalSettings, const Settings& settings) :
Message(),
m_generalSettings(generalSettings),
m_settings(settings)
{ }
};
OsmoSDRInput(MessageQueue* msgQueueToGUI);
~OsmoSDRInput();
bool startInput(int device);
void stopInput();
const QString& getDeviceDescription() const;
int getSampleRate() const;
quint64 getCenterFrequency() const;
bool handleMessage(Message* message);
private:
QMutex m_mutex;
Settings m_settings;
osmosdr_dev_t* m_dev;
OsmoSDRThread* m_osmoSDRThread;
QString m_deviceDescription;
bool applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force);
};
#endif // INCLUDE_OSMOSDRINPUT_H
@@ -0,0 +1,69 @@
#include <QtPlugin>
#include <QAction>
#include <osmosdr.h>
#include "plugin/pluginapi.h"
#include "util/simpleserializer.h"
#include "osmosdrplugin.h"
#include "osmosdrgui.h"
const PluginDescriptor OsmoSDRPlugin::m_pluginDescriptor = {
QString("OsmoSDR Input"),
QString("---"),
QString("(c) Christian Daniel"),
QString("http://sdr.osmocom.org/trac/wiki/osmo-sdr"),
true,
QString("http://cgit.osmocom.org/cgit/osmo-sdr")
};
OsmoSDRPlugin::OsmoSDRPlugin(QObject* parent) :
QObject(parent)
{
}
const PluginDescriptor& OsmoSDRPlugin::getPluginDescriptor() const
{
return m_pluginDescriptor;
}
void OsmoSDRPlugin::initPlugin(PluginAPI* pluginAPI)
{
m_pluginAPI = pluginAPI;
m_pluginAPI->registerSampleSource("org.osmocom.sdr.samplesource.osmo-sdr", this);
}
PluginInterface::SampleSourceDevices OsmoSDRPlugin::enumSampleSources()
{
SampleSourceDevices result;
int count = osmosdr_get_device_count();
char vendor[256];
char product[256];
char serial[256];
for(int i = 0; i < count; i++) {
vendor[0] = '\0';
product[0] = '\0';
serial[0] = '\0';
if(osmosdr_get_device_usb_strings(i, vendor, product, serial) != 0)
continue;
QString displayedName(QString("OsmoSDR #%1 (#%2)").arg(i + 1).arg(serial));
qDebug("found %s", qPrintable(displayedName));
SimpleSerializer s(1);
s.writeS32(1, i);
result.append(SampleSourceDevice(displayedName, "org.osmocom.sdr.samplesource.osmo-sdr", s.final()));
}
return result;
}
PluginGUI* OsmoSDRPlugin::createSampleSource(const QString& sourceName, const QByteArray& address)
{
if(sourceName == "org.osmocom.sdr.samplesource.osmo-sdr") {
OsmoSDRGui* gui = new OsmoSDRGui(m_pluginAPI);
m_pluginAPI->setInputGUI(gui);
return gui;
} else {
return NULL;
}
}
@@ -0,0 +1,27 @@
#ifndef INCLUDE_OSMOSDRPLUGIN_H
#define INCLUDE_OSMOSDRPLUGIN_H
#include <QObject>
#include "plugin/plugininterface.h"
class OsmoSDRPlugin : public QObject, PluginInterface {
Q_OBJECT
Q_INTERFACES(PluginInterface)
Q_PLUGIN_METADATA(IID "org.osmocom.sdr.samplesource.osmo-sdr")
public:
explicit OsmoSDRPlugin(QObject* parent = NULL);
const PluginDescriptor& getPluginDescriptor() const;
void initPlugin(PluginAPI* pluginAPI);
SampleSourceDevices enumSampleSources();
PluginGUI* createSampleSource(const QString& sourceName, const QByteArray& address);
private:
static const PluginDescriptor m_pluginDescriptor;
PluginAPI* m_pluginAPI;
};
#endif // INCLUDE_OSMOSDRPLUGIN_H
@@ -0,0 +1,116 @@
///////////////////////////////////////////////////////////////////////////////////
// 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 <stdio.h>
#include <errno.h>
#include "osmosdrthread.h"
#include "dsp/samplefifo.h"
OsmoSDRThread::OsmoSDRThread(osmosdr_dev_t* dev, SampleFifo* sampleFifo, QObject* parent) :
QThread(parent),
m_running(false),
m_dev(dev),
m_sampleFifo(sampleFifo)
{
}
OsmoSDRThread::~OsmoSDRThread()
{
stopWork();
}
void OsmoSDRThread::startWork()
{
m_startWaitMutex.lock();
start();
while(!m_running)
m_startWaiter.wait(&m_startWaitMutex, 100);
m_startWaitMutex.unlock();
}
void OsmoSDRThread::stopWork()
{
m_running = false;
wait();
}
void OsmoSDRThread::run()
{
int res;
m_running = true;
m_startWaiter.wakeAll();
//m_f = fopen("/tmp/samples.bin", "wb");
while(m_running) {
if((res = osmosdr_read_async(m_dev, &OsmoSDRThread::callbackHelper, this, 16, sizeof(Sample) * 8192 * 2)) < 0) {
qCritical("OsmoSDRThread: async error: %s", strerror(errno));
break;
}
}
m_running = false;
}
void OsmoSDRThread::checkData(const quint8* buf, qint32 len)
{
const Sample* s = (const Sample*)buf;
len /= sizeof(Sample);
while(len) {
if((s->i != m_nextI) || (s->q != m_nextQ)) {
qDebug("continuity error after %llu samples", m_samplePos);
m_samplePos = 0;
m_nextI = s->i - 1;
m_nextQ = s->q + 1;
} else {
m_nextI--;
m_nextQ++;
m_samplePos++;
}
len--;
s++;
}
}
void OsmoSDRThread::callback(const quint8* buf, qint32 len)
{
/*
qDebug("%d", len);
*/
/*
for(int i = 0; i < len / 2; i += 2) {
((qint16*)buf)[i] = sin((float)(cntr) * 1024* 2.0 * M_PI / 65536.0) * 32000.0;
((qint16*)buf)[i + 1] = -cos((float)(cntr++) * 1024*2.0 * M_PI / 65536.0) * 32000.0;
}
*/
//m_sampleFifo->write((SampleVector::const_iterator)((Sample*)buf), (SampleVector::const_iterator)((Sample*)(buf + len)));
//fwrite(buf, 1, len, m_f);
//checkData(buf, len);
m_sampleFifo->write(buf, len);
if(!m_running)
osmosdr_cancel_async(m_dev);
}
void OsmoSDRThread::callbackHelper(unsigned char* buf, uint32_t len, void* ctx)
{
OsmoSDRThread* thread = (OsmoSDRThread*)ctx;
thread->callback(buf, len);
}
@@ -0,0 +1,66 @@
///////////////////////////////////////////////////////////////////////////////////
// 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_OSMOSDRTHREAD_H
#define INCLUDE_OSMOSDRTHREAD_H
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
#include <osmosdr.h>
class SampleFifo;
class OsmoSDRThread : public QThread {
Q_OBJECT
public:
OsmoSDRThread(osmosdr_dev_t* dev, SampleFifo* sampleFifo, QObject* parent = NULL);
~OsmoSDRThread();
void startWork();
void stopWork();
private:
#pragma pack(push, 1)
struct Sample {
qint16 i;
qint16 q;
};
#pragma pack(pop)
qint16 m_nextI;
qint16 m_nextQ;
quint64 m_samplePos;
QMutex m_startWaitMutex;
QWaitCondition m_startWaiter;
bool m_running;
FILE* m_f;
osmosdr_dev_t* m_dev;
SampleFifo* m_sampleFifo;
void run();
void checkData(const quint8* buf, qint32 len);
void callback(const quint8* buf, qint32 len);
static void callbackHelper(unsigned char* buf, uint32_t len, void* ctx);
};
#endif // INCLUDE_OSMOSDRTHREAD_H
@@ -0,0 +1,518 @@
#include <QFileDialog>
#include <QMessageBox>
#include <QCursor>
#include <QThread>
#include <libusb.h>
#include "osmosdrupgrade.h"
#include "ui_osmosdrupgrade.h"
#define OSMOSDR_USB_VID 0x16c0
#define OSMOSDR_USB_PID 0x0763
// DFU commands
#define DFU_DETACH 0x00
#define DFU_DNLOAD 0x01
#define DFU_UPLOAD 0x02
#define DFU_GETSTATUS 0x03
#define DFU_CLRSTATUS 0x04
#define DFU_GETSTATE 0x05
#define DFU_ABORT 0x06
// DFU states
#define ST_appIDLE 0
#define ST_appDETACH 1
#define ST_dfuIDLE 2
#define ST_dfuDNLOAD_SYNC 3
#define ST_dfuDNBUSY 4
#define ST_dfuDNLOAD_IDLE 5
#define ST_dfuMANIFEST_SYNC 6
#define ST_dfuMANIFEST 7
#define ST_dfuMANIFEST_WAIT_RST 8
#define ST_dfuUPLOAD_IDLE 9
#define ST_dfuERROR 10
#define DFU_PACKETSIZE 512
#pragma pack(push, 1)
struct dfu_getstatus {
quint8 bStatus;
quint8 bwPollTimeout[3];
quint8 bState;
quint8 iString;
};
#pragma pack(pop)
OsmoSDRUpgrade::OsmoSDRUpgrade(QWidget* parent) :
QDialog(parent),
ui(new Ui::OsmoSDRUpgrade),
m_usb(NULL)
{
ui->setupUi(this);
connect(&m_searchDeviceTimer, SIGNAL(timeout()), this, SLOT(searchDeviceTick()));
}
OsmoSDRUpgrade::~OsmoSDRUpgrade()
{
delete ui;
}
void OsmoSDRUpgrade::on_browse_clicked()
{
QString filename = QFileDialog::getOpenFileName(this, tr("OsmoSDR Firmware File"), QString(), tr("OsmoSDR Firmware (*.ofw);;All Files (*)"));
if(filename.isEmpty())
return;
QFile file(filename);
if(file.size() > 10 * 1024 * 1024) {
QMessageBox::critical(this, tr("File Open Error"), tr("File is too big to be a firmware update for OsmoSDR."));
return;
}
QByteArray dfuApp;
QByteArray radioApp;
QByteArray fpgaBin;
mz_zip_archive zip;
memset(&zip, 0x00, sizeof(zip));
if(!mz_zip_reader_init_file(&zip, qPrintable(filename), 0)) {
mz_zip_reader_end(&zip);
QMessageBox::critical(this, tr("File Open Error"), tr("File is not a valid OsmoSDR update."));
return;
}
int dfuAppIndex = mz_zip_reader_locate_file(&zip, "dfuapp.bin", NULL, 0);
int radioAppIndex = mz_zip_reader_locate_file(&zip, "radioapp.bin", NULL, 0);
int fpgaIndex = mz_zip_reader_locate_file(&zip, "fpga.bin", NULL, 0);
if((dfuAppIndex < 0) && (radioAppIndex < 0) && (fpgaIndex < 0)) {
mz_zip_reader_end(&zip);
QMessageBox::critical(this, tr("File Open Error"), tr("File is not a valid OsmoSDR update."));
return;
}
if(!mz_zip_reader_extract_to_callback(&zip, dfuAppIndex, zipHelper, &dfuApp, 0)) {
mz_zip_reader_end(&zip);
QMessageBox::critical(this, tr("File Open Error"), tr("File is not a valid OsmoSDR update."));
return;
}
if(!mz_zip_reader_extract_to_callback(&zip, radioAppIndex, zipHelper, &radioApp, 0)) {
mz_zip_reader_end(&zip);
QMessageBox::critical(this, tr("File Open Error"), tr("File is not a valid OsmoSDR update."));
return;
}
if(!mz_zip_reader_extract_to_callback(&zip, fpgaIndex, zipHelper, &fpgaBin, 0)) {
mz_zip_reader_end(&zip);
QMessageBox::critical(this, tr("File Open Error"), tr("File is not a valid OsmoSDR update."));
return;
}
mz_zip_reader_end(&zip);
m_dfuApp = dfuApp;
m_radioApp = radioApp;
m_fpgaBin = fpgaBin;
if(dfuAppIndex >= 0) {
ui->dfu->setEnabled(true);
ui->dfuSize->setText(tr("%1").arg(m_dfuApp.size()));
} else {
ui->dfu->setEnabled(false);
ui->dfuSize->setText(tr("-"));
}
if(radioAppIndex >= 0) {
ui->radio->setEnabled(true);
ui->radioSize->setText(tr("%1").arg(m_radioApp.size()));
} else {
ui->radio->setEnabled(false);
ui->dfuSize->setText(tr("-"));
}
if(fpgaIndex >= 0) {
ui->fpga->setEnabled(true);
ui->fpgaSize->setText(tr("%1").arg(m_fpgaBin.size()));
} else {
ui->fpga->setEnabled(false);
ui->fpgaSize->setText(tr("-"));
}
if((dfuAppIndex >= 0) && (radioAppIndex < 0) && (fpgaIndex < 0)) {
ui->dfu->setChecked(true);
ui->radio->setChecked(false);
ui->fpga->setChecked(false);
} else {
ui->dfu->setChecked(false);
ui->radio->setChecked(radioAppIndex >= 0);
ui->fpga->setChecked(fpgaIndex >= 0);
}
ui->fwBox->setEnabled(true);
ui->progressBox->setEnabled(true);
QFileInfo fi(file.fileName());
ui->filename->setText(fi.fileName());
}
void OsmoSDRUpgrade::on_dfu_toggled(bool checked)
{
updateFlashButton();
}
void OsmoSDRUpgrade::on_radio_toggled(bool checked)
{
updateFlashButton();
}
void OsmoSDRUpgrade::on_fpga_toggled(bool checked)
{
updateFlashButton();
}
void OsmoSDRUpgrade::updateFlashButton()
{
if(ui->dfu->isChecked() || ui->radio->isChecked() || ui->fpga->isChecked())
ui->progressBox->setEnabled(true);
else ui->progressBox->setEnabled(false);
}
void OsmoSDRUpgrade::on_start_clicked()
{
ui->close->setEnabled(false);
ui->start->setEnabled(false);
QApplication::setOverrideCursor(Qt::WaitCursor);
ui->log->clear();
log(tr("Starting flash operation..."));
if(libusb_init(&m_usb) < 0) {
fail(tr("Could not initialize libusb."));
return;
}
switchToDFU();
m_searchTries = 0;
m_searchDeviceTimer.start(250);
}
void OsmoSDRUpgrade::searchDeviceTick()
{
m_searchTries++;
log(tr("Searching device (try %1)").arg(m_searchTries));
libusb_device_handle* device = libusb_open_device_with_vid_pid(m_usb, OSMOSDR_USB_VID, OSMOSDR_USB_PID);
if(device == NULL) {
if(m_searchTries >= 10) {
m_searchDeviceTimer.stop();
finish();
}
return;
}
m_searchDeviceTimer.stop();
libusb_device_descriptor deviceDescriptor;
if(libusb_get_descriptor(device, LIBUSB_DT_DEVICE, 0, (unsigned char*)&deviceDescriptor, sizeof(deviceDescriptor)) < 0) {
libusb_close(device);
fail(tr("Could not read device descriptor."));
return;
}
char sn[64];
memset(sn, 0x00, sizeof(sn));
libusb_get_string_descriptor_ascii(device, deviceDescriptor.iSerialNumber, (unsigned char*)sn, sizeof(sn));
sn[sizeof(sn) - 1] = '\0';
log(tr("OsmoSDR found (SN %1)").arg(sn));
quint8 buffer[255];
if(libusb_get_descriptor(device, LIBUSB_DT_CONFIG, 0, buffer, sizeof(buffer)) < 16) {
libusb_close(device);
fail(tr("Could not get a configuration descriptor"));
return;
}
if(buffer[15] != 1) {
libusb_close(device);
fail(tr("Device not in DFU mode as it should be"));
return;
}
quint8 state;
if(dfuGetState(device, &state) < 0) {
libusb_reset_device(device);
if(dfuGetState(device, &state) < 0) {
libusb_close(device);
fail(tr("Cannot get device DFU state"));
return;
}
}
if((state != ST_dfuIDLE) && (state != ST_dfuDNLOAD_IDLE)) {
dfuGetStatus(device);
libusb_close(device);
fail(tr("Device is not in dfuIDLE or dfuDNLOAD_IDLE state"));
return;
}
if(libusb_claim_interface(device, 0) < 0) {
libusb_close(device);
fail(tr("Could not claim interface"));
return;
}
QByteArray* image;
int altSetting;
while(true) {
if(ui->dfu->isChecked()) {
log(tr("Starting download of DFU application"));
image = &m_dfuApp;
altSetting = 1;
} else if(ui->radio->isChecked()) {
log(tr("Starting download of radio application"));
image = &m_radioApp;
altSetting = 0;
} else if(ui->fpga->isChecked()) {
log(tr("Starting download of FPGA image"));
image = &m_fpgaBin;
altSetting = 2;
} else {
log(tr("Switching back to radio application mode"));
dfuDetach(device);
break;
}
if(libusb_set_interface_alt_setting(device, 0, altSetting) < 0) {
libusb_close(device);
fail(tr("Could not set alternate interface setting to %1").arg(altSetting));
return;
}
ui->progress->setMaximum((image->size() / DFU_PACKETSIZE) + ((image->size() % DFU_PACKETSIZE) ? 1 : 0));
int blocknum = 0;
while((state == ST_dfuIDLE) || (state == ST_dfuDNLOAD_IDLE)) {
int offset = blocknum * DFU_PACKETSIZE;
int blocklen = (int)image->size() - offset;
if(blocklen < 0)
blocklen = 0;
if(blocklen > DFU_PACKETSIZE)
blocklen = DFU_PACKETSIZE;
if(dfuDownloadBlock(device, blocknum, (const quint8*)(image->data() + offset), blocklen) < 0) {
if(dfuGetState(device, &state) < 0) {
if(ui->dfu->isChecked())
break;
libusb_close(device);
fail(tr("Cannot get device DFU state"));
return;
}
dfuGetStatus(device);
libusb_close(device);
fail(tr("Error downloading block %1").arg(blocknum));
return;
}
dfuGetStatus(device);
if(blocklen == 0)
break;
blocknum++;
ui->progress->setValue(blocknum);
QApplication::processEvents();
}
log(tr("Download complete (state %1)").arg(state));
do {
if(dfuGetState(device, &state) < 0) {
if(ui->dfu->isChecked()) {
break;
} else {
libusb_close(device);
fail(tr("Cannot get device DFU state"));
return;
}
}
dfuGetStatus(device);
} while(state == ST_dfuMANIFEST);
if(ui->dfu->isChecked()) {
ui->dfu->setChecked(false);
m_searchTries = 0;
m_searchDeviceTimer.start(250);
libusb_close(device);
return;
} else if(ui->radio->isChecked()) {
ui->radio->setChecked(false);
} else if(ui->fpga->isChecked()) {
ui->fpga->setChecked(false);
}
QApplication::processEvents();
}
log(tr("Upgrade finished successfully"));
libusb_close(device);
finish();
}
void OsmoSDRUpgrade::switchToDFU()
{
libusb_device_handle* device = libusb_open_device_with_vid_pid(m_usb, OSMOSDR_USB_VID, OSMOSDR_USB_PID);
if(device == NULL) {
log(tr("No OsmoSDR VID:PID %1:%2 found").arg(OSMOSDR_USB_VID, 4, 16, QChar('0')).arg(OSMOSDR_USB_PID, 4, 16, QChar('0')));
return;
}
quint8 buffer[255];
if(libusb_get_descriptor(device, LIBUSB_DT_CONFIG, 0, buffer, sizeof(buffer)) < 16) {
log(tr("Could not get a valid configuration descriptor"));
libusb_close(device);
return;
}
if(buffer[15] != 1) {
if(libusb_claim_interface(device, 0) < 0) {
log(tr("Could not claim interface"));
libusb_close(device);
return;
}
log(tr("Switching device to DFU mode"));
libusb_control_transfer(device, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT, 0x07, 0x0003, 0, NULL, 0, 50);
libusb_release_interface(device, 0);
} else {
log(tr("Device is already in DFU mode"));
}
libusb_close(device);
}
int OsmoSDRUpgrade::dfuGetState(libusb_device_handle* device, quint8* state)
{
int res;
res = libusb_control_transfer(
device,
0xa1,
DFU_GETSTATE,
0,
0,
(unsigned char*)state,
1,
1000);
return res;
}
int OsmoSDRUpgrade::dfuGetStatus(libusb_device_handle* device)
{
int res;
struct dfu_getstatus getstatus;
/*
static const char* statedesc[] = {
"appIDLE",
"appDETACH",
"dfuIDLE",
"dfuDNLOAD-SYNC",
"dfuDNBUSY",
"dfuDNLOAD-IDLE",
"dfuMANIFEST-SYNC",
"dfuMANIFEST",
"dfuMANIFEST-WAIT-RESET",
"dfuUPLOAD-IDLE",
"dfuERROR"
};
*/
res = libusb_control_transfer(
device,
0xa1,
DFU_GETSTATUS,
0,
0,
(unsigned char*)&getstatus,
sizeof(getstatus),
1000);
/*
if(res >= 0)
log(tr("OsmoSDR bStatus: %1, bState: %2 (%3)").arg(getstatus.bStatus).arg(statedesc[getstatus.bState]).arg(getstatus.bState));
*/
return res;
}
int OsmoSDRUpgrade::dfuClrStatus(libusb_device_handle* device)
{
return libusb_control_transfer(
device,
0x21,
DFU_CLRSTATUS,
0,
0,
NULL,
0,
1000);
}
int OsmoSDRUpgrade::dfuDownloadBlock(libusb_device_handle* device, quint16 block, const quint8* data, quint16 len)
{
return libusb_control_transfer(
device,
0x21,
DFU_DNLOAD,
block,
0,
(unsigned char*)data,
len,
10000);
}
int OsmoSDRUpgrade::dfuDetach(libusb_device_handle* device)
{
return libusb_control_transfer(
device,
0x21,
DFU_DETACH,
0,
0,
NULL,
0,
1000);
}
void OsmoSDRUpgrade::fail(const QString& msg)
{
log(tr("Fatal error: %1").arg(msg));
QMessageBox::critical(this, tr("OsmoSDR Upgrade Failed"), msg);
finish();
}
void OsmoSDRUpgrade::finish()
{
if(m_usb != NULL) {
libusb_exit(m_usb);
m_usb = NULL;
}
QApplication::restoreOverrideCursor();
ui->start->setEnabled(true);
ui->close->setEnabled(true);
}
void OsmoSDRUpgrade::log(const QString& msg)
{
ui->log->appendPlainText(msg);
ui->log->moveCursor(QTextCursor::End);
}
void OsmoSDRUpgrade::reject()
{
if(ui->close->isEnabled())
return QDialog::reject();
}
size_t OsmoSDRUpgrade::zipHelper(void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n)
{
QByteArray* bytes = (QByteArray*)pOpaque;
bytes->append((const char*)pBuf, n);
return n;
}
@@ -0,0 +1,60 @@
#ifndef INCLUDE_OSMOSDRUPGRADE_H
#define INCLUDE_OSMOSDRUPGRADE_H
#include <QDialog>
#include <QTimer>
#include "util/miniz.h"
typedef struct libusb_context libusb_context;
typedef struct libusb_device_handle libusb_device_handle;
namespace Ui {
class OsmoSDRUpgrade;
}
class OsmoSDRUpgrade : public QDialog {
Q_OBJECT
public:
explicit OsmoSDRUpgrade(QWidget* parent = NULL);
~OsmoSDRUpgrade();
private slots:
void on_browse_clicked();
void on_dfu_toggled(bool checked);
void on_radio_toggled(bool checked);
void on_fpga_toggled(bool checked);
void on_start_clicked();
void searchDeviceTick();
private:
Ui::OsmoSDRUpgrade* ui;
libusb_context* m_usb;
QByteArray m_dfuApp;
QByteArray m_radioApp;
QByteArray m_fpgaBin;
int m_searchTries;
QTimer m_searchDeviceTimer;
void updateFlashButton();
void switchToDFU();
int dfuGetState(libusb_device_handle* device, quint8* state);
int dfuGetStatus(libusb_device_handle* device);
int dfuClrStatus(libusb_device_handle* device);
int dfuDownloadBlock(libusb_device_handle* device, quint16 block, const quint8* data, quint16 len);
int dfuDetach(libusb_device_handle* device);
void fail(const QString& msg);
void finish();
void log(const QString& msg);
void reject();
static size_t zipHelper(void* pOpaque, mz_uint64 file_ofs, const void* pBuf, size_t n);
};
#endif // INCLUDE_OSMOSDRUPGRADE_H
@@ -0,0 +1,213 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OsmoSDRUpgrade</class>
<widget class="QDialog" name="OsmoSDRUpgrade">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>382</width>
<height>503</height>
</rect>
</property>
<property name="windowTitle">
<string>OsmoSDR Firmware Upgrade</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Firmware Archive</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="filename">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>256</width>
<height>0</height>
</size>
</property>
<property name="text">
<string/>
</property>
<property name="textFormat">
<enum>Qt::PlainText</enum>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="browse">
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="fwBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="title">
<string>Firmware</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="2" column="1">
<widget class="QLabel" name="radioSize">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLabel" name="fpgaSize">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_4">
<property name="text">
<string>Size (Bytes)</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="dfu">
<property name="text">
<string>DFU Application</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QCheckBox" name="radio">
<property name="text">
<string>Radio Application</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="fpga">
<property name="text">
<string>FPGA Image</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="dfuSize">
<property name="text">
<string/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="progressBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="title">
<string>Progress</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<item>
<widget class="QProgressBar" name="progress">
<property name="value">
<number>0</number>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="start">
<property name="text">
<string>Flash!</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QPlainTextEdit" name="log">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="close">
<property name="text">
<string>Close</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<resources/>
<connections>
<connection>
<sender>close</sender>
<signal>clicked()</signal>
<receiver>OsmoSDRUpgrade</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>331</x>
<y>247</y>
</hint>
<hint type="destinationlabel">
<x>190</x>
<y>134</y>
</hint>
</hints>
</connection>
</connections>
</ui>