mirror of
https://github.com/f4exb/sdrangel.git
synced 2026-06-02 22:14:45 -04:00
git clone git://git.osmocom.org/sdrangelove.git
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
project(gnuradio)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules)
|
||||
|
||||
find_package(GnuradioRuntime)
|
||||
find_package(GnuradioOsmosdr)
|
||||
|
||||
if(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64")
|
||||
list(APPEND BOOST_LIBRARYDIR "/usr/lib64") #fedora 64-bit fix
|
||||
endif(UNIX AND NOT BOOST_ROOT AND EXISTS "/usr/lib64")
|
||||
|
||||
find_package(Boost COMPONENTS system)
|
||||
|
||||
if(NOT GNURADIO_RUNTIME_FOUND AND GNURADIO_OSMOSDR_FOUND)
|
||||
|
||||
message(STATUS "GNU Radio not found, assuming built-in gr-osmosdr runtime.")
|
||||
|
||||
set(GNURADIO_RUNTIME_FOUND TRUE)
|
||||
set(GNURADIO_RUNTIME_INCLUDE_DIRS "")
|
||||
set(GNURADIO_RUNTIME_LIBRARIES "")
|
||||
|
||||
FOREACH(inc ${GNURADIO_OSMOSDR_INCLUDE_DIRS})
|
||||
LIST(APPEND GNURADIO_RUNTIME_INCLUDE_DIRS "${inc}/osmosdr/runtime")
|
||||
ENDFOREACH(inc)
|
||||
|
||||
LIST(APPEND GNURADIO_RUNTIME_LIBRARIES ${GNURADIO_OSMOSDR_LIBRARIES})
|
||||
|
||||
endif(NOT GNURADIO_RUNTIME_FOUND AND GNURADIO_OSMOSDR_FOUND)
|
||||
|
||||
if(Boost_FOUND AND GNURADIO_RUNTIME_FOUND AND GNURADIO_OSMOSDR_FOUND)
|
||||
|
||||
set(gnuradio_SOURCES
|
||||
gnuradiogui.cpp
|
||||
gnuradioinput.cpp
|
||||
gnuradioplugin.cpp
|
||||
gnuradiothread.cpp
|
||||
)
|
||||
|
||||
set(gnuradio_HEADERS
|
||||
gnuradiogui.h
|
||||
gnuradioinput.h
|
||||
gnuradioplugin.h
|
||||
gnuradiothread.h
|
||||
)
|
||||
|
||||
set(gnuradio_FORMS
|
||||
gnuradiogui.ui
|
||||
)
|
||||
|
||||
include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_BINARY_DIR}
|
||||
${CMAKE_SOURCE_DIR}/include
|
||||
${CMAKE_SOURCE_DIR}/include-gpl
|
||||
${Boost_INCLUDE_DIRS}
|
||||
${GNURADIO_RUNTIME_INCLUDE_DIRS}
|
||||
${GNURADIO_OSMOSDR_INCLUDE_DIRS}
|
||||
)
|
||||
|
||||
add_definitions(${QT_DEFINITIONS})
|
||||
add_definitions(-DQT_PLUGIN)
|
||||
add_definitions(-DQT_SHARED)
|
||||
add_definitions(-DBOOST_ALL_NO_LIB)
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-DNOMINMAX)
|
||||
endif()
|
||||
|
||||
qt5_wrap_ui(gnuradio_FORMS_HEADERS ${gnuradio_FORMS})
|
||||
|
||||
add_library(inputgnuradio SHARED
|
||||
${gnuradio_SOURCES}
|
||||
${gnuradio_HEADERS_MOC}
|
||||
${gnuradio_FORMS_HEADERS}
|
||||
)
|
||||
|
||||
target_link_libraries(inputgnuradio
|
||||
${QT_LIBRARIES}
|
||||
${Boost_LIBRARIES}
|
||||
${GNURADIO_RUNTIME_LIBRARIES}
|
||||
${GNURADIO_OSMOSDR_LIBRARIES}
|
||||
sdrbase
|
||||
)
|
||||
|
||||
qt5_use_modules(inputgnuradio Core Widgets OpenGL Multimedia)
|
||||
|
||||
endif(Boost_FOUND AND GNURADIO_RUNTIME_FOUND AND GNURADIO_OSMOSDR_FOUND)
|
||||
@@ -0,0 +1,29 @@
|
||||
INCLUDE(FindPkgConfig)
|
||||
PKG_CHECK_MODULES(PC_GNURADIO_OSMOSDR gnuradio-osmosdr)
|
||||
|
||||
FIND_PATH(
|
||||
GNURADIO_OSMOSDR_INCLUDE_DIRS
|
||||
NAMES osmosdr/api.h
|
||||
HINTS $ENV{GNURADIO_OSMOSDR_DIR}/include
|
||||
${PC_GNURADIO_OSMOSDR_INCLUDEDIR}
|
||||
${CMAKE_INSTALL_PREFIX}/include
|
||||
PATHS /usr/local/include
|
||||
/usr/include
|
||||
)
|
||||
|
||||
FIND_LIBRARY(
|
||||
GNURADIO_OSMOSDR_LIBRARIES
|
||||
NAMES gnuradio-osmosdr
|
||||
HINTS $ENV{GNURADIO_OSMOSDR_DIR}/lib
|
||||
${PC_GNURADIO_OSMOSDR_LIBDIR}
|
||||
${CMAKE_INSTALL_PREFIX}/lib64
|
||||
${CMAKE_INSTALL_PREFIX}/lib
|
||||
PATHS /usr/local/lib
|
||||
/usr/local/lib64
|
||||
/usr/lib
|
||||
/usr/lib64
|
||||
)
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_OSMOSDR DEFAULT_MSG GNURADIO_OSMOSDR_LIBRARIES GNURADIO_OSMOSDR_INCLUDE_DIRS)
|
||||
MARK_AS_ADVANCED(GNURADIO_OSMOSDR_LIBRARIES GNURADIO_OSMOSDR_INCLUDE_DIRS)
|
||||
@@ -0,0 +1,29 @@
|
||||
INCLUDE(FindPkgConfig)
|
||||
PKG_CHECK_MODULES(PC_GNURADIO_RUNTIME gnuradio-runtime)
|
||||
|
||||
FIND_PATH(
|
||||
GNURADIO_RUNTIME_INCLUDE_DIRS
|
||||
NAMES gnuradio/api.h
|
||||
HINTS $ENV{GNURADIO_RUNTIME_DIR}/include
|
||||
${PC_GNURADIO_RUNTIME_INCLUDEDIR}
|
||||
${CMAKE_INSTALL_PREFIX}/include
|
||||
PATHS /usr/local/include
|
||||
/usr/include
|
||||
)
|
||||
|
||||
FIND_LIBRARY(
|
||||
GNURADIO_RUNTIME_LIBRARIES
|
||||
NAMES gnuradio-runtime
|
||||
HINTS $ENV{GNURADIO_RUNTIME_DIR}/lib
|
||||
${PC_GNURADIO_RUNTIME_LIBDIR}
|
||||
${CMAKE_INSTALL_PREFIX}/lib64
|
||||
${CMAKE_INSTALL_PREFIX}/lib
|
||||
PATHS /usr/local/lib
|
||||
/usr/local/lib64
|
||||
/usr/lib
|
||||
/usr/lib64
|
||||
)
|
||||
|
||||
INCLUDE(FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS(GNURADIO_RUNTIME DEFAULT_MSG GNURADIO_RUNTIME_LIBRARIES GNURADIO_RUNTIME_INCLUDE_DIRS)
|
||||
MARK_AS_ADVANCED(GNURADIO_RUNTIME_LIBRARIES GNURADIO_RUNTIME_INCLUDE_DIRS)
|
||||
@@ -0,0 +1,422 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
||||
// written by Christian Daniel //
|
||||
// Copyright (C) 2013 by Dimitri Stolnikov <horiz0n@gmx.net> //
|
||||
// //
|
||||
// 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 "gnuradiogui.h"
|
||||
#include "ui_gnuradiogui.h"
|
||||
|
||||
#include <osmosdr/device.h>
|
||||
#include <iostream>
|
||||
#include <plugin/pluginapi.h>
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QSlider>
|
||||
|
||||
GNURadioGui::GNURadioGui(PluginAPI* pluginAPI, QWidget* parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::GNURadioGui),
|
||||
m_pluginAPI(pluginAPI),
|
||||
m_settings(),
|
||||
m_sampleSource(NULL)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
|
||||
displaySettings();
|
||||
|
||||
m_sampleSource = new GNURadioInput(m_pluginAPI->getMainWindowMessageQueue());
|
||||
m_pluginAPI->setSampleSource(m_sampleSource);
|
||||
}
|
||||
|
||||
GNURadioGui::~GNURadioGui()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void GNURadioGui::destroy()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void GNURadioGui::setName(const QString& name)
|
||||
{
|
||||
setObjectName(name);
|
||||
}
|
||||
|
||||
void GNURadioGui::resetToDefaults()
|
||||
{
|
||||
m_generalSettings.resetToDefaults();
|
||||
m_settings.resetToDefaults();
|
||||
displaySettings();
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
QByteArray GNURadioGui::serializeGeneral() const
|
||||
{
|
||||
return m_generalSettings.serialize();
|
||||
}
|
||||
|
||||
bool GNURadioGui::deserializeGeneral(const QByteArray&data)
|
||||
{
|
||||
if(m_generalSettings.deserialize(data)) {
|
||||
displaySettings();
|
||||
sendSettings();
|
||||
return true;
|
||||
} else {
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
quint64 GNURadioGui::getCenterFrequency() const
|
||||
{
|
||||
return m_generalSettings.m_centerFrequency;
|
||||
}
|
||||
|
||||
QByteArray GNURadioGui::serialize() const
|
||||
{
|
||||
return m_settings.serialize();
|
||||
}
|
||||
|
||||
bool GNURadioGui::deserialize(const QByteArray& data)
|
||||
{
|
||||
if(m_settings.deserialize(data)) {
|
||||
displaySettings();
|
||||
sendSettings();
|
||||
return true;
|
||||
} else {
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool GNURadioGui::handleMessage(Message* message)
|
||||
{
|
||||
if(GNURadioInput::MsgReportGNURadio::match(message)) {
|
||||
GNURadioInput::MsgReportGNURadio* rep = (GNURadioInput::MsgReportGNURadio*)message;
|
||||
m_namedGains = rep->getNamedGains();
|
||||
m_freqMin = rep->getFreqMin();
|
||||
m_freqMax = rep->getFreqMax();
|
||||
m_freqCorr = rep->getFreqCorr();
|
||||
m_sampRates = rep->getSampRates();
|
||||
m_antennas = rep->getAntennas();
|
||||
m_dcoffs = rep->getDCOffs();
|
||||
m_iqbals = rep->getIQBals();
|
||||
m_bandwidths = rep->getBandwidths();
|
||||
/* insert 0 which will become "Auto" in the combo box */
|
||||
m_bandwidths.insert(m_bandwidths.begin(), 0);
|
||||
displaySettings();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void GNURadioGui::displaySettings()
|
||||
{
|
||||
int oldIndex = 0;
|
||||
|
||||
oldIndex = ui->cboDevices->currentIndex();
|
||||
ui->cboDevices->clear();
|
||||
|
||||
QString oldArgs = ui->txtDeviceArgs->text();
|
||||
|
||||
osmosdr::devices_t devices = osmosdr::device::find();
|
||||
|
||||
for ( int i = 0; i < devices.size(); i++ )
|
||||
{
|
||||
osmosdr::device_t dev = devices[i];
|
||||
|
||||
QString label;
|
||||
|
||||
if ( dev.count( "label" ) )
|
||||
{
|
||||
label = QString(dev[ "label" ].c_str());
|
||||
dev.erase("label");
|
||||
}
|
||||
|
||||
QPair< QString, QString > pair(label, dev.to_string().c_str());
|
||||
m_devs.append(pair);
|
||||
|
||||
ui->cboDevices->addItem(label);
|
||||
}
|
||||
|
||||
if ( ui->cboDevices->count() && oldIndex >= 0 )
|
||||
{
|
||||
if ( oldIndex > ui->cboDevices->count() - 1 )
|
||||
oldIndex = 0;
|
||||
|
||||
ui->cboDevices->setCurrentIndex(oldIndex);
|
||||
|
||||
if ( oldArgs.length() == 0 )
|
||||
ui->txtDeviceArgs->setText( m_devs[oldIndex].second );
|
||||
}
|
||||
|
||||
if ( oldArgs.length() )
|
||||
ui->txtDeviceArgs->setText( oldArgs );
|
||||
|
||||
ui->centerFrequency->setValueRange(7,
|
||||
unsigned(m_freqMin / 1000.0),
|
||||
unsigned(m_freqMax / 1000.0));
|
||||
|
||||
ui->centerFrequency->setValue(m_generalSettings.m_centerFrequency / 1000);
|
||||
|
||||
ui->sldFreqCorr->setRange(-100, +100);
|
||||
ui->sldFreqCorr->setValue( m_freqCorr );
|
||||
ui->lblFreqCorr->setText(tr("%1").arg(ui->sldFreqCorr->value()));
|
||||
|
||||
m_gainControls.clear();
|
||||
QVBoxLayout *layoutGains = ui->verticalLayoutGains;
|
||||
QLayoutItem *layoutItem;
|
||||
|
||||
while ( ( layoutItem = layoutGains->takeAt( 0 ) ) != NULL )
|
||||
{
|
||||
QLayout *layout = layoutItem->layout();
|
||||
|
||||
if ( !layout )
|
||||
continue;
|
||||
|
||||
while ( ( layoutItem = layout->takeAt( 0 ) ) != NULL )
|
||||
{
|
||||
delete layoutItem->widget();
|
||||
delete layoutItem;
|
||||
}
|
||||
|
||||
delete layout;
|
||||
}
|
||||
|
||||
for ( int i = 0; i < m_namedGains.size(); i++ )
|
||||
{
|
||||
std::pair< QString, std::vector<double> > pair = m_namedGains[i];
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout();
|
||||
QLabel *gainName = new QLabel( pair.first + " Gain" );
|
||||
QSlider *gainSlider = new QSlider(Qt::Horizontal);
|
||||
QLabel *gainLabel = new QLabel("0");
|
||||
gainLabel->setMinimumWidth(30);
|
||||
gainLabel->setAlignment(Qt::AlignHCenter | Qt::AlignHCenter);
|
||||
|
||||
QPair< QSlider*, QLabel* > pair2( gainSlider, gainLabel );
|
||||
m_gainControls.push_back( pair2 );
|
||||
|
||||
connect(gainSlider, SIGNAL(valueChanged(int)),
|
||||
this, SLOT(on_sldGain_valueChanged(int)));
|
||||
|
||||
layout->addWidget(gainName);
|
||||
layout->addWidget(gainSlider);
|
||||
layout->addWidget(gainLabel);
|
||||
|
||||
layoutGains->addLayout(layout);
|
||||
|
||||
std::vector<double> gain_values = pair.second;
|
||||
|
||||
if ( gain_values.size() ) {
|
||||
gainSlider->setRange(0, gain_values.size() - 1);
|
||||
gainSlider->setValue(gain_values.size() / 4);
|
||||
gainSlider->setEnabled(true);
|
||||
} else {
|
||||
gainSlider->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
oldIndex = ui->cboSampleRate->currentIndex();
|
||||
ui->cboSampleRate->clear();
|
||||
|
||||
for ( int i = 0; i < m_sampRates.size(); i++ )
|
||||
ui->cboSampleRate->addItem( QString::number(m_sampRates[i] / 1e6) );
|
||||
|
||||
if ( oldIndex > ui->cboSampleRate->count() - 1 )
|
||||
oldIndex = 0;
|
||||
|
||||
if ( ui->cboSampleRate->count() && oldIndex >= 0 )
|
||||
ui->cboSampleRate->setCurrentIndex(oldIndex);
|
||||
|
||||
if ( ui->cboSampleRate->count() ) {
|
||||
ui->cboSampleRate->setEnabled(true);
|
||||
} else {
|
||||
ui->cboSampleRate->setEnabled(false);
|
||||
}
|
||||
|
||||
oldIndex = ui->cboAntennas->currentIndex();
|
||||
ui->cboAntennas->clear();
|
||||
|
||||
if ( m_antennas.size() ) {
|
||||
for ( int i = 0; i < m_antennas.size(); i++ )
|
||||
ui->cboAntennas->addItem( m_antennas[i] );
|
||||
|
||||
if ( oldIndex > ui->cboAntennas->count() - 1 )
|
||||
oldIndex = 0;
|
||||
|
||||
if ( ui->cboAntennas->count() && oldIndex >= 0 )
|
||||
ui->cboAntennas->setCurrentIndex(oldIndex);
|
||||
|
||||
ui->cboAntennas->setEnabled(true);
|
||||
} else {
|
||||
ui->cboAntennas->setEnabled(false);
|
||||
}
|
||||
|
||||
oldIndex = ui->cboDCOffset->currentIndex();
|
||||
ui->cboDCOffset->clear();
|
||||
|
||||
if ( m_dcoffs.size() ) {
|
||||
for ( int i = 0; i < m_dcoffs.size(); i++ )
|
||||
ui->cboDCOffset->addItem( m_dcoffs[i] );
|
||||
|
||||
if ( ui->cboDCOffset->count() && oldIndex >= 0 )
|
||||
ui->cboDCOffset->setCurrentIndex(oldIndex);
|
||||
|
||||
ui->cboDCOffset->setEnabled(true);
|
||||
} else {
|
||||
ui->cboDCOffset->setEnabled(false);
|
||||
}
|
||||
|
||||
oldIndex = ui->cboIQBalance->currentIndex();
|
||||
ui->cboIQBalance->clear();
|
||||
|
||||
if ( m_iqbals.size() ) {
|
||||
for ( int i = 0; i < m_iqbals.size(); i++ )
|
||||
ui->cboIQBalance->addItem( m_iqbals[i] );
|
||||
|
||||
if ( ui->cboIQBalance->count() && oldIndex >= 0 )
|
||||
ui->cboIQBalance->setCurrentIndex(oldIndex);
|
||||
|
||||
ui->cboIQBalance->setEnabled(true);
|
||||
} else {
|
||||
ui->cboIQBalance->setEnabled(false);
|
||||
}
|
||||
|
||||
oldIndex = ui->cboBandwidth->currentIndex();
|
||||
ui->cboBandwidth->clear();
|
||||
|
||||
for ( int i = 0; i < m_bandwidths.size(); i++ )
|
||||
if ( 0.0 == m_bandwidths[i] )
|
||||
ui->cboBandwidth->addItem( "Auto" );
|
||||
else
|
||||
ui->cboBandwidth->addItem( QString::number(m_bandwidths[i] / 1e6) );
|
||||
|
||||
if ( oldIndex > ui->cboBandwidth->count() - 1 )
|
||||
oldIndex = 0;
|
||||
|
||||
if ( ui->cboBandwidth->count() && oldIndex >= 0 )
|
||||
ui->cboBandwidth->setCurrentIndex(oldIndex);
|
||||
|
||||
if ( ui->cboBandwidth->count() ) {
|
||||
ui->cboBandwidth->setEnabled(true);
|
||||
} else {
|
||||
ui->cboBandwidth->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void GNURadioGui::sendSettings()
|
||||
{
|
||||
if(!m_updateTimer.isActive())
|
||||
m_updateTimer.start(100);
|
||||
}
|
||||
|
||||
void GNURadioGui::updateHardware()
|
||||
{
|
||||
m_updateTimer.stop();
|
||||
GNURadioInput::MsgConfigureGNURadio* msg = GNURadioInput::MsgConfigureGNURadio::create(m_generalSettings, m_settings);
|
||||
msg->submit(m_pluginAPI->getDSPEngineMessageQueue());
|
||||
}
|
||||
|
||||
void GNURadioGui::on_cboDevices_currentIndexChanged(int index)
|
||||
{
|
||||
if ( index < 0 || index >= m_devs.count() )
|
||||
return;
|
||||
|
||||
ui->txtDeviceArgs->setText( m_devs[index].second );
|
||||
}
|
||||
|
||||
void GNURadioGui::on_txtDeviceArgs_textChanged(const QString &arg1)
|
||||
{
|
||||
m_settings.m_args = arg1;
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void GNURadioGui::on_centerFrequency_changed(quint64 value)
|
||||
{
|
||||
m_generalSettings.m_centerFrequency = value * 1000;
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void GNURadioGui::on_sldFreqCorr_valueChanged(int value)
|
||||
{
|
||||
ui->lblFreqCorr->setText(tr("%1").arg(value));
|
||||
m_settings.m_freqCorr = value;
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void GNURadioGui::on_sldGain_valueChanged(int value)
|
||||
{
|
||||
m_settings.m_namedGains.clear();
|
||||
|
||||
for ( int i = 0; i < m_gainControls.size(); i++ )
|
||||
{
|
||||
QPair< QSlider*, QLabel* > controls = m_gainControls[i];
|
||||
|
||||
QSlider *slider = controls.first;
|
||||
QLabel *label = controls.second;
|
||||
|
||||
std::pair< QString, std::vector<double> > named_gain = m_namedGains[ i ];
|
||||
|
||||
int index = slider->value();
|
||||
double gain = named_gain.second[index];
|
||||
label->setText(tr("%1").arg(gain));
|
||||
|
||||
QPair< QString, double > named_gain2( named_gain.first, gain );
|
||||
m_settings.m_namedGains.push_back( named_gain2 );
|
||||
}
|
||||
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void GNURadioGui::on_cboSampleRate_currentIndexChanged(int index)
|
||||
{
|
||||
if ( index < 0 || index >= m_sampRates.size() )
|
||||
return;
|
||||
|
||||
m_settings.m_sampRate = m_sampRates[index];
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void GNURadioGui::on_cboAntennas_currentIndexChanged(const QString &arg1)
|
||||
{
|
||||
m_settings.m_antenna = arg1;
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void GNURadioGui::on_cboDCOffset_currentIndexChanged(const QString &arg1)
|
||||
{
|
||||
m_settings.m_dcoff = arg1;
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void GNURadioGui::on_cboIQBalance_currentIndexChanged(const QString &arg1)
|
||||
{
|
||||
m_settings.m_iqbal = arg1;
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void GNURadioGui::on_cboBandwidth_currentIndexChanged(int index)
|
||||
{
|
||||
if ( index < 0 || index >= m_bandwidths.size() )
|
||||
return;
|
||||
|
||||
m_settings.m_bandwidth = m_bandwidths[index];
|
||||
sendSettings();
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
||||
// written by Christian Daniel //
|
||||
// Copyright (C) 2013 by Dimitri Stolnikov <horiz0n@gmx.net> //
|
||||
// //
|
||||
// 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_GNURADIOGUI_H
|
||||
#define INCLUDE_GNURADIOGUI_H
|
||||
|
||||
#include <QTimer>
|
||||
#include <QPair>
|
||||
#include <QList>
|
||||
#include <QString>
|
||||
#include <QSlider>
|
||||
#include <QLabel>
|
||||
#include "plugin/plugingui.h"
|
||||
#include "gnuradioinput.h"
|
||||
|
||||
namespace Ui {
|
||||
class GNURadioGui;
|
||||
}
|
||||
|
||||
class PluginAPI;
|
||||
|
||||
class GNURadioGui : public QWidget, public PluginGUI {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit GNURadioGui(PluginAPI* pluginAPI, QWidget* parent = NULL);
|
||||
~GNURadioGui();
|
||||
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::GNURadioGui* ui;
|
||||
PluginAPI* m_pluginAPI;
|
||||
SampleSource* m_sampleSource;
|
||||
QList< QPair<QString, QString> > m_devs;
|
||||
std::vector< std::pair< QString, std::vector<double> > > m_namedGains;
|
||||
double m_freqMin;
|
||||
double m_freqMax;
|
||||
double m_freqCorr;
|
||||
std::vector<double> m_sampRates;
|
||||
std::vector<QString> m_antennas;
|
||||
std::vector<QString> m_dcoffs;
|
||||
std::vector<QString> m_iqbals;
|
||||
std::vector<double> m_bandwidths;
|
||||
|
||||
std::vector< QSlider* > m_gainSliders;
|
||||
std::vector< QLabel* > m_gainLabels;
|
||||
|
||||
QList< QPair< QSlider*, QLabel* > > m_gainControls;
|
||||
|
||||
SampleSource::GeneralSettings m_generalSettings;
|
||||
GNURadioInput::Settings m_settings;
|
||||
QTimer m_updateTimer;
|
||||
|
||||
void displaySettings();
|
||||
void sendSettings();
|
||||
|
||||
private slots:
|
||||
void updateHardware();
|
||||
|
||||
void on_cboDevices_currentIndexChanged(int index);
|
||||
void on_txtDeviceArgs_textChanged(const QString &arg1);
|
||||
void on_centerFrequency_changed(quint64 value);
|
||||
void on_sldFreqCorr_valueChanged(int value);
|
||||
|
||||
void on_sldGain_valueChanged(int value);
|
||||
|
||||
void on_cboSampleRate_currentIndexChanged(int index);
|
||||
void on_cboAntennas_currentIndexChanged(const QString &arg1);
|
||||
void on_cboDCOffset_currentIndexChanged(const QString &arg1);
|
||||
void on_cboIQBalance_currentIndexChanged(const QString &arg1);
|
||||
void on_cboBandwidth_currentIndexChanged(int index);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_GNURADIOGUI_H
|
||||
@@ -0,0 +1,301 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>GNURadioGui</class>
|
||||
<widget class="QWidget" name="GNURadioGui">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>186</width>
|
||||
<height>261</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Gnuradio Source</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cboDevices">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="txtDeviceArgs">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_5">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<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">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Freq. Corr.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="sldFreqCorr">
|
||||
<property name="minimum">
|
||||
<number>-100</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="tracking">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblFreqCorr">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>30</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="layoutDirection">
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayoutGains"/>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Sample Rate (MHz)</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::AutoText</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cboSampleRate">
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::AdjustToMinimumContentsLength</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Selected Antenna</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cboAntennas">
|
||||
<property name="frame">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="text">
|
||||
<string>DC Offset Corr. </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cboDCOffset"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_8">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>IQ Imbalance Corr.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cboIQBalance"/>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Bandwidth (MHz)</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="cboBandwidth"/>
|
||||
</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,332 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
||||
// written by Christian Daniel //
|
||||
// Copyright (C) 2013 by Dimitri Stolnikov <horiz0n@gmx.net> //
|
||||
// //
|
||||
// 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 "util/simpleserializer.h"
|
||||
#include "gnuradioinput.h"
|
||||
#include "gnuradiothread.h"
|
||||
#include "gnuradiogui.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(GNURadioInput::MsgConfigureGNURadio, Message)
|
||||
MESSAGE_CLASS_DEFINITION(GNURadioInput::MsgReportGNURadio, Message)
|
||||
|
||||
GNURadioInput::Settings::Settings() :
|
||||
m_args(""),
|
||||
m_freqCorr(0),
|
||||
m_sampRate(0),
|
||||
m_antenna(""),
|
||||
m_dcoff(""),
|
||||
m_iqbal(""),
|
||||
m_bandwidth(0)
|
||||
{
|
||||
}
|
||||
|
||||
void GNURadioInput::Settings::resetToDefaults()
|
||||
{
|
||||
m_args = "";
|
||||
m_sampRate = 0;
|
||||
m_freqCorr = 0;
|
||||
m_antenna = "";
|
||||
m_dcoff = "";
|
||||
m_iqbal = "";
|
||||
m_bandwidth = 0;
|
||||
}
|
||||
|
||||
QByteArray GNURadioInput::Settings::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
// s.writeString(1, m_args);
|
||||
// s.writeDouble(2, m_freqCorr);
|
||||
// s.writeDouble(3, m_sampRate);
|
||||
// s.writeString(4, m_antenna);
|
||||
// s.writeString(5, m_dcoff);
|
||||
// s.writeString(5, m_iqbal);
|
||||
return s.final();
|
||||
}
|
||||
|
||||
bool GNURadioInput::Settings::deserialize(const QByteArray& data)
|
||||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if(!d.isValid()) {
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.getVersion() == 1) {
|
||||
// d.readString(1, &m_args, "");
|
||||
// d.readDouble(2, &m_freqCorr, 0);
|
||||
// d.readDouble(3, &m_sampRate, 0);
|
||||
// d.readString(4, &m_antenna, "");
|
||||
// d.readString(5, &m_dcoff, "");
|
||||
// d.readString(5, &m_iqbal, "");
|
||||
return true;
|
||||
} else {
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
GNURadioInput::GNURadioInput(MessageQueue* msgQueueToGUI) :
|
||||
SampleSource(msgQueueToGUI),
|
||||
m_settings(),
|
||||
m_GnuradioThread(NULL),
|
||||
m_deviceDescription()
|
||||
{
|
||||
}
|
||||
|
||||
GNURadioInput::~GNURadioInput()
|
||||
{
|
||||
stopInput();
|
||||
}
|
||||
|
||||
bool GNURadioInput::startInput(int device)
|
||||
{
|
||||
double freqMin = 0, freqMax = 0, freqCorr = 0;
|
||||
std::vector< std::pair< QString, std::vector<double> > > namedGains;
|
||||
std::vector< double > sampRates;
|
||||
std::vector< QString > antennas;
|
||||
std::vector< double > bandwidths;
|
||||
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if(m_GnuradioThread != NULL)
|
||||
stopInput();
|
||||
|
||||
if(!m_sampleFifo.setSize( 2 * 1024 * 1024 )) {
|
||||
qCritical("Could not allocate SampleFifo");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_deviceDescription = m_settings.m_args;
|
||||
|
||||
// pass device arguments from the gui
|
||||
m_GnuradioThread = new GnuradioThread(m_settings.m_args, &m_sampleFifo);
|
||||
if(m_GnuradioThread == NULL) {
|
||||
qFatal("out of memory");
|
||||
goto failed;
|
||||
}
|
||||
m_GnuradioThread->startWork();
|
||||
|
||||
mutexLocker.unlock();
|
||||
applySettings(m_generalSettings, m_settings, true);
|
||||
|
||||
if(m_GnuradioThread != NULL) {
|
||||
osmosdr::source::sptr radio = m_GnuradioThread->radio();
|
||||
|
||||
try {
|
||||
osmosdr::freq_range_t freq_rage = radio->get_freq_range();
|
||||
freqMin = freq_rage.start();
|
||||
freqMax = freq_rage.stop();
|
||||
} catch ( std::exception &ex ) {
|
||||
qDebug("%s", ex.what());
|
||||
}
|
||||
|
||||
freqCorr = radio->get_freq_corr();
|
||||
|
||||
namedGains.clear();
|
||||
m_settings.m_namedGains.clear();
|
||||
std::vector< std::string > gain_names = radio->get_gain_names();
|
||||
for ( int i = 0; i < gain_names.size(); i++ )
|
||||
{
|
||||
std::string gain_name = gain_names[i];
|
||||
|
||||
try {
|
||||
std::vector< double > gain_values = \
|
||||
radio->get_gain_range( gain_name ).values();
|
||||
|
||||
std::pair< QString, std::vector<double> > pair( gain_name.c_str(),
|
||||
gain_values );
|
||||
|
||||
namedGains.push_back( pair );
|
||||
|
||||
QPair< QString, double > pair2( gain_name.c_str(), 0 );
|
||||
|
||||
m_settings.m_namedGains.push_back( pair2 );
|
||||
} catch ( std::exception &ex ) {
|
||||
qDebug("%s", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
sampRates = radio->get_sample_rates().values();
|
||||
} catch ( std::exception &ex ) {
|
||||
qDebug("%s", ex.what());
|
||||
}
|
||||
|
||||
antennas.clear();
|
||||
std::vector< std::string > ant = radio->get_antennas();
|
||||
for ( int i = 0; i < ant.size(); i++ )
|
||||
antennas.push_back( QString( ant[i].c_str() ) );
|
||||
|
||||
m_dcoffs.clear();
|
||||
m_dcoffs.push_back( "Off" );
|
||||
m_dcoffs.push_back( "Keep" );
|
||||
m_dcoffs.push_back( "Auto" );
|
||||
|
||||
m_iqbals.clear();
|
||||
m_iqbals.push_back( "Off" );
|
||||
m_iqbals.push_back( "Keep" );
|
||||
m_iqbals.push_back( "Auto" );
|
||||
|
||||
try {
|
||||
bandwidths = radio->get_bandwidth_range().values();
|
||||
} catch ( std::exception &ex ) {
|
||||
qDebug("%s", ex.what());
|
||||
}
|
||||
}
|
||||
|
||||
qDebug("GnuradioInput: start");
|
||||
MsgReportGNURadio::create(freqMin, freqMax, freqCorr, namedGains,
|
||||
sampRates, antennas, m_dcoffs, m_iqbals,
|
||||
bandwidths)
|
||||
->submit(m_guiMessageQueue);
|
||||
|
||||
return true;
|
||||
|
||||
failed:
|
||||
stopInput();
|
||||
return false;
|
||||
}
|
||||
|
||||
void GNURadioInput::stopInput()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if(m_GnuradioThread != NULL) {
|
||||
m_GnuradioThread->stopWork();
|
||||
delete m_GnuradioThread;
|
||||
m_GnuradioThread = NULL;
|
||||
}
|
||||
|
||||
m_deviceDescription.clear();
|
||||
}
|
||||
|
||||
const QString& GNURadioInput::getDeviceDescription() const
|
||||
{
|
||||
return m_deviceDescription;
|
||||
}
|
||||
|
||||
int GNURadioInput::getSampleRate() const
|
||||
{
|
||||
return m_settings.m_sampRate;
|
||||
}
|
||||
|
||||
quint64 GNURadioInput::getCenterFrequency() const
|
||||
{
|
||||
return m_generalSettings.m_centerFrequency;
|
||||
}
|
||||
|
||||
bool GNURadioInput::handleMessage(Message* message)
|
||||
{
|
||||
if(MsgConfigureGNURadio::match(message)) {
|
||||
MsgConfigureGNURadio* conf = (MsgConfigureGNURadio*)message;
|
||||
if(!applySettings(conf->getGeneralSettings(), conf->getSettings(), false))
|
||||
qDebug("Gnuradio config error");
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool GNURadioInput::applySettings(const GeneralSettings& generalSettings,
|
||||
const Settings& settings,
|
||||
bool force)
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
m_settings.m_args = settings.m_args;
|
||||
|
||||
if ( NULL == m_GnuradioThread )
|
||||
return true;
|
||||
|
||||
osmosdr::source::sptr radio = m_GnuradioThread->radio();
|
||||
|
||||
try {
|
||||
|
||||
if((m_settings.m_freqCorr != settings.m_freqCorr) || force) {
|
||||
m_settings.m_freqCorr = settings.m_freqCorr;
|
||||
radio->set_freq_corr( m_settings.m_freqCorr );
|
||||
}
|
||||
|
||||
if((m_generalSettings.m_centerFrequency != generalSettings.m_centerFrequency) || force) {
|
||||
m_generalSettings.m_centerFrequency = generalSettings.m_centerFrequency;
|
||||
radio->set_center_freq( m_generalSettings.m_centerFrequency );
|
||||
}
|
||||
|
||||
for ( int i = 0; i < settings.m_namedGains.size(); i++ )
|
||||
{
|
||||
if((m_settings.m_namedGains[i].second != settings.m_namedGains[i].second) || force) {
|
||||
m_settings.m_namedGains[i].second = settings.m_namedGains[i].second;
|
||||
radio->set_gain( settings.m_namedGains[i].second,
|
||||
settings.m_namedGains[i].first.toStdString() );
|
||||
}
|
||||
}
|
||||
|
||||
if((m_settings.m_sampRate != settings.m_sampRate) || force) {
|
||||
m_settings.m_sampRate = settings.m_sampRate;
|
||||
radio->set_sample_rate( m_settings.m_sampRate );
|
||||
}
|
||||
|
||||
if((m_settings.m_antenna != settings.m_antenna) || force) {
|
||||
m_settings.m_antenna = settings.m_antenna;
|
||||
radio->set_antenna( m_settings.m_antenna.toStdString() );
|
||||
}
|
||||
|
||||
if((m_settings.m_dcoff != settings.m_dcoff) || force) {
|
||||
m_settings.m_dcoff = settings.m_dcoff;
|
||||
|
||||
for ( int i = 0; i < m_dcoffs.size(); i++ )
|
||||
{
|
||||
if ( m_dcoffs[i] != m_settings.m_dcoff )
|
||||
continue;
|
||||
|
||||
radio->set_dc_offset_mode( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if((m_settings.m_iqbal != settings.m_iqbal) || force) {
|
||||
m_settings.m_iqbal = settings.m_iqbal;
|
||||
|
||||
for ( int i = 0; i < m_iqbals.size(); i++ )
|
||||
{
|
||||
if ( m_iqbals[i] != m_settings.m_iqbal )
|
||||
continue;
|
||||
|
||||
radio->set_iq_balance_mode( i );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if((m_settings.m_bandwidth != settings.m_bandwidth) ||
|
||||
(0.0f == settings.m_bandwidth) || force) {
|
||||
m_settings.m_bandwidth = settings.m_bandwidth;
|
||||
/* setting the BW to 0.0 triggers automatic bandwidth
|
||||
* selection when supported by device */
|
||||
radio->set_bandwidth( m_settings.m_bandwidth );
|
||||
}
|
||||
|
||||
} catch ( std::exception &ex ) {
|
||||
qDebug("%s", ex.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
||||
// written by Christian Daniel //
|
||||
// Copyright (C) 2013 by Dimitri Stolnikov <horiz0n@gmx.net> //
|
||||
// //
|
||||
// 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_GNURADIOINPUT_H
|
||||
#define INCLUDE_GNURADIOINPUT_H
|
||||
|
||||
#include "dsp/samplesource/samplesource.h"
|
||||
#include <QString>
|
||||
#include <QPair>
|
||||
|
||||
class GnuradioThread;
|
||||
|
||||
class GNURadioInput : public SampleSource {
|
||||
public:
|
||||
struct Settings {
|
||||
QString m_args;
|
||||
double m_freqMin;
|
||||
double m_freqMax;
|
||||
double m_freqCorr;
|
||||
QList< QPair< QString, double > > m_namedGains;
|
||||
double m_sampRate;
|
||||
QString m_antenna;
|
||||
QString m_dcoff;
|
||||
QString m_iqbal;
|
||||
double m_bandwidth;
|
||||
|
||||
Settings();
|
||||
void resetToDefaults();
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
};
|
||||
|
||||
class MsgConfigureGNURadio : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
const GeneralSettings& getGeneralSettings() const { return m_generalSettings; }
|
||||
const Settings& getSettings() const { return m_settings; }
|
||||
|
||||
static MsgConfigureGNURadio* create(const GeneralSettings& generalSettings, const Settings& settings)
|
||||
{
|
||||
return new MsgConfigureGNURadio(generalSettings, settings);
|
||||
}
|
||||
|
||||
protected:
|
||||
GeneralSettings m_generalSettings;
|
||||
Settings m_settings;
|
||||
|
||||
MsgConfigureGNURadio(const GeneralSettings& generalSettings, const Settings& settings) :
|
||||
Message(),
|
||||
m_generalSettings(generalSettings),
|
||||
m_settings(settings)
|
||||
{ }
|
||||
};
|
||||
|
||||
class MsgReportGNURadio : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
const std::vector< std::pair< QString, std::vector<double> > >& getNamedGains() const { return m_namedGains; }
|
||||
const double getFreqMin() const { return m_freqMin; }
|
||||
const double getFreqMax() const { return m_freqMax; }
|
||||
const double getFreqCorr() const { return m_freqCorr; }
|
||||
const std::vector<double>& getSampRates() const { return m_sampRates; }
|
||||
const std::vector<QString>& getAntennas() const { return m_antennas; }
|
||||
const std::vector<QString>& getDCOffs() const { return m_dcoffs; }
|
||||
const std::vector<QString>& getIQBals() const { return m_iqbals; }
|
||||
const std::vector<double>& getBandwidths() const { return m_bandwidths; }
|
||||
|
||||
static MsgReportGNURadio* create(const double freqMin,
|
||||
const double freqMax,
|
||||
const double freqCorr,
|
||||
const std::vector< std::pair< QString, std::vector<double> > >& namedGains,
|
||||
const std::vector<double>& sampRates,
|
||||
const std::vector<QString>& antennas,
|
||||
const std::vector<QString>& dcoffs,
|
||||
const std::vector<QString>& iqbals,
|
||||
const std::vector<double>& bandwidths)
|
||||
{
|
||||
return new MsgReportGNURadio(freqMin, freqMax, freqCorr, namedGains, sampRates, antennas, dcoffs, iqbals, bandwidths);
|
||||
}
|
||||
|
||||
protected:
|
||||
double m_freqMin;
|
||||
double m_freqMax;
|
||||
double m_freqCorr;
|
||||
std::vector< std::pair< QString, std::vector<double> > > m_namedGains;
|
||||
std::vector<double> m_sampRates;
|
||||
std::vector<QString> m_antennas;
|
||||
std::vector<QString> m_dcoffs;
|
||||
std::vector<QString> m_iqbals;
|
||||
std::vector<double> m_bandwidths;
|
||||
|
||||
MsgReportGNURadio(const double freqMin,
|
||||
const double freqMax,
|
||||
const double freqCorr,
|
||||
const std::vector< std::pair< QString, std::vector<double> > >& namedGains,
|
||||
const std::vector<double>& sampRates,
|
||||
const std::vector<QString>& antennas,
|
||||
const std::vector<QString>& dcoffs,
|
||||
const std::vector<QString>& iqbals,
|
||||
const std::vector<double>& bandwidths) :
|
||||
Message(),
|
||||
m_freqMin(freqMin),
|
||||
m_freqMax(freqMax),
|
||||
m_freqCorr(freqCorr),
|
||||
m_namedGains(namedGains),
|
||||
m_sampRates(sampRates),
|
||||
m_antennas(antennas),
|
||||
m_dcoffs(dcoffs),
|
||||
m_iqbals(iqbals),
|
||||
m_bandwidths(bandwidths)
|
||||
{ }
|
||||
};
|
||||
|
||||
GNURadioInput(MessageQueue* msgQueueToGUI);
|
||||
~GNURadioInput();
|
||||
|
||||
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;
|
||||
GnuradioThread* m_GnuradioThread;
|
||||
QString m_deviceDescription;
|
||||
std::vector< QString > m_dcoffs;
|
||||
std::vector< QString > m_iqbals;
|
||||
|
||||
bool applySettings(const GeneralSettings& generalSettings,
|
||||
const Settings& settings,
|
||||
bool force);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_GNURADIOINPUT_H
|
||||
@@ -0,0 +1,52 @@
|
||||
#include <QtPlugin>
|
||||
#include <QAction>
|
||||
#include "plugin/pluginapi.h"
|
||||
#include "util/simpleserializer.h"
|
||||
#include "gnuradioplugin.h"
|
||||
#include "gnuradiogui.h"
|
||||
|
||||
const PluginDescriptor GNURadioPlugin::m_pluginDescriptor = {
|
||||
QString("GR-OsmoSDR Input"),
|
||||
QString("1.0"),
|
||||
QString("(c) Dimitri Stolnikov <horiz0n@gmx.net>"),
|
||||
QString("http://sdr.osmocom.org/trac/wiki/GrOsmoSDR"),
|
||||
true,
|
||||
QString("http://cgit.osmocom.org/cgit/gr-osmosdr")
|
||||
};
|
||||
|
||||
GNURadioPlugin::GNURadioPlugin(QObject* parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
}
|
||||
|
||||
const PluginDescriptor& GNURadioPlugin::getPluginDescriptor() const
|
||||
{
|
||||
return m_pluginDescriptor;
|
||||
}
|
||||
|
||||
void GNURadioPlugin::initPlugin(PluginAPI* pluginAPI)
|
||||
{
|
||||
m_pluginAPI = pluginAPI;
|
||||
|
||||
m_pluginAPI->registerSampleSource("org.osmocom.sdr.samplesource.gr-osmosdr", this);
|
||||
}
|
||||
|
||||
PluginInterface::SampleSourceDevices GNURadioPlugin::enumSampleSources()
|
||||
{
|
||||
SampleSourceDevices result;
|
||||
|
||||
result.append(SampleSourceDevice("GNURadio OsmoSDR Driver", "org.osmocom.sdr.samplesource.gr-osmosdr", QByteArray()));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
PluginGUI* GNURadioPlugin::createSampleSource(const QString& sourceName, const QByteArray& address)
|
||||
{
|
||||
if(sourceName == "org.osmocom.sdr.samplesource.gr-osmosdr") {
|
||||
GNURadioGui* gui = new GNURadioGui(m_pluginAPI);
|
||||
m_pluginAPI->setInputGUI(gui);
|
||||
return gui;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#ifndef INCLUDE_GNURADIOPLUGIN_H
|
||||
#define INCLUDE_GNURADIOPLUGIN_H
|
||||
|
||||
#include <QObject>
|
||||
#include "plugin/plugininterface.h"
|
||||
|
||||
class GNURadioPlugin : public QObject, PluginInterface {
|
||||
Q_OBJECT
|
||||
Q_INTERFACES(PluginInterface)
|
||||
Q_PLUGIN_METADATA(IID "org.osmocom.sdr.samplesource.gr-osmosdr")
|
||||
|
||||
public:
|
||||
explicit GNURadioPlugin(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_GNURADIOPLUGIN_H
|
||||
@@ -0,0 +1,144 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
||||
// written by Christian Daniel //
|
||||
// Copyright (C) 2013 by Dimitri Stolnikov <horiz0n@gmx.net> //
|
||||
// //
|
||||
// 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 "gnuradiothread.h"
|
||||
#include "dsp/samplefifo.h"
|
||||
|
||||
#include <gnuradio/sync_block.h>
|
||||
#include <gnuradio/io_signature.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class gr_adaptor;
|
||||
|
||||
typedef boost::shared_ptr< gr_adaptor > gr_adaptor_sptr;
|
||||
|
||||
gr_adaptor_sptr make_gr_adaptor (SampleFifo* sampleFifo);
|
||||
|
||||
class gr_adaptor : public gr::sync_block
|
||||
{
|
||||
public:
|
||||
gr_adaptor (SampleFifo* sampleFifo);
|
||||
~gr_adaptor ();
|
||||
|
||||
int work (int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items);
|
||||
|
||||
private:
|
||||
SampleFifo *m_sampleFifo;
|
||||
};
|
||||
|
||||
gr_adaptor_sptr
|
||||
make_gr_adaptor (SampleFifo *sampleFifo)
|
||||
{
|
||||
return gr_adaptor_sptr (new gr_adaptor (sampleFifo));
|
||||
}
|
||||
|
||||
gr_adaptor::gr_adaptor (SampleFifo *sampleFifo)
|
||||
: gr::sync_block("gr_adaptor",
|
||||
gr::io_signature::make(1, 1, sizeof (gr_complex)),
|
||||
gr::io_signature::make(0, 0, 0)),
|
||||
m_sampleFifo(sampleFifo)
|
||||
{
|
||||
}
|
||||
|
||||
gr_adaptor::~gr_adaptor ()
|
||||
{
|
||||
}
|
||||
|
||||
int
|
||||
gr_adaptor::work (int noutput_items,
|
||||
gr_vector_const_void_star &input_items,
|
||||
gr_vector_void_star &output_items)
|
||||
{
|
||||
const gr_complex *in = (const gr_complex *) input_items[0];
|
||||
|
||||
std::vector<qint16> buffer(noutput_items * 2, 0);
|
||||
std::vector<qint16>::iterator it = buffer.begin();
|
||||
|
||||
for (int i = 0; i < noutput_items; i++)
|
||||
{
|
||||
*it++ = in[i].real() * 32000;
|
||||
*it++ = in[i].imag() * 32000;
|
||||
}
|
||||
|
||||
// we must push at least 4 bytes into the fifo
|
||||
m_sampleFifo->write((const quint8*)buffer.data(),
|
||||
(it - buffer.begin()) * sizeof(qint16));
|
||||
|
||||
// Tell runtime system how many input items we consumed on
|
||||
// each input stream.
|
||||
consume_each(noutput_items);
|
||||
|
||||
// Tell runtime system how many output items we produced.
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
GnuradioThread::GnuradioThread(QString args, SampleFifo* sampleFifo, QObject* parent) :
|
||||
QThread(parent),
|
||||
m_running(false),
|
||||
m_args(args),
|
||||
m_sampleFifo(sampleFifo)
|
||||
{
|
||||
}
|
||||
|
||||
GnuradioThread::~GnuradioThread()
|
||||
{
|
||||
stopWork();
|
||||
}
|
||||
|
||||
void GnuradioThread::startWork()
|
||||
{
|
||||
m_startWaitMutex.lock();
|
||||
|
||||
start();
|
||||
while(!m_running)
|
||||
m_startWaiter.wait(&m_startWaitMutex, 100);
|
||||
|
||||
m_startWaitMutex.unlock();
|
||||
}
|
||||
|
||||
void GnuradioThread::stopWork()
|
||||
{
|
||||
m_running = false;
|
||||
|
||||
m_top->stop();
|
||||
|
||||
wait();
|
||||
}
|
||||
|
||||
void GnuradioThread::run()
|
||||
{
|
||||
m_top = gr::make_top_block( "flowgraph" );
|
||||
m_src = osmosdr::source::make( m_args.toStdString() );
|
||||
|
||||
/* now since we've constructed our shared objects, we allow the calling
|
||||
* thread to continue it's work and send some radio settings to us. */
|
||||
m_running = true;
|
||||
m_startWaiter.wakeAll();
|
||||
|
||||
gr_adaptor_sptr adaptor = make_gr_adaptor(m_sampleFifo);
|
||||
m_top->connect(m_src, 0, adaptor, 0);
|
||||
|
||||
m_top->run();
|
||||
|
||||
m_running = false;
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
|
||||
// written by Christian Daniel //
|
||||
// Copyright (C) 2013 by Dimitri Stolnikov <horiz0n@gmx.net> //
|
||||
// //
|
||||
// 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_GNURADIOTHREAD_H
|
||||
#define INCLUDE_GNURADIOTHREAD_H
|
||||
|
||||
#include <QThread>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
|
||||
#include <gnuradio/top_block.h>
|
||||
#include <osmosdr/source.h>
|
||||
|
||||
class SampleFifo;
|
||||
|
||||
class GnuradioThread : public QThread {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
GnuradioThread(QString args, SampleFifo* sampleFifo, QObject* parent = NULL);
|
||||
~GnuradioThread();
|
||||
|
||||
void startWork();
|
||||
void stopWork();
|
||||
|
||||
osmosdr::source::sptr radio() { return m_src; }
|
||||
|
||||
private:
|
||||
#pragma pack(push, 1)
|
||||
struct Sample {
|
||||
qint16 i;
|
||||
qint16 q;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
QMutex m_startWaitMutex;
|
||||
QWaitCondition m_startWaiter;
|
||||
bool m_running;
|
||||
|
||||
QString m_args;
|
||||
SampleFifo* m_sampleFifo;
|
||||
|
||||
gr::top_block_sptr m_top;
|
||||
osmosdr::source::sptr m_src;
|
||||
|
||||
void run();
|
||||
};
|
||||
|
||||
#endif // INCLUDE_GNURADIOTHREAD_H
|
||||
Reference in New Issue
Block a user