Perseus support (4)

This commit is contained in:
f4exb 2018-02-07 09:12:34 +01:00
parent becbe0f96e
commit 65174d7044
5 changed files with 561 additions and 0 deletions

View File

@ -0,0 +1,78 @@
project(perseus)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(perseus_SOURCES
# perseusgui.cpp
# perseusinput.cpp
# perseusplugin.cpp
perseussettings.cpp
# perseusthread.cpp
)
set(perseus_HEADERS
# perseusgui.h
# perseusinput.h
# perseusplugin.h
perseussettings.h
# perseusthread.h
)
set(perseus_FORMS
perseusgui.ui
)
if (BUILD_DEBIAN)
include_directories(
.
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
${LIBAIRSPYHFSRC}
${LIBAIRSPYHFSRC}/libperseus/src
)
else (BUILD_DEBIAN)
include_directories(
.
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_SOURCE_DIR}/swagger/sdrangel/code/qt5/client
${LIBAIRSPYHF_INCLUDE_DIR}
)
endif (BUILD_DEBIAN)
#include(${QT_USE_FILE})
#add_definitions(${QT_DEFINITIONS})
add_definitions("${QT_DEFINITIONS} -DLIBAIRSPY_DYN_RATES")
add_definitions(-DQT_PLUGIN)
add_definitions(-DQT_SHARED)
#qt4_wrap_cpp(perseus_HEADERS_MOC ${perseus_HEADERS})
qt5_wrap_ui(perseus_FORMS_HEADERS ${perseus_FORMS})
add_library(inputperseus SHARED
${perseus_SOURCES}
${perseus_HEADERS_MOC}
${perseus_FORMS_HEADERS}
)
if (BUILD_DEBIAN)
target_link_libraries(inputperseus
${QT_LIBRARIES}
perseus
sdrbase
sdrgui
swagger
)
else (BUILD_DEBIAN)
target_link_libraries(inputperseus
${QT_LIBRARIES}
${LIBAIRSPYHF_LIBRARIES}
sdrbase
sdrgui
swagger
)
endif (BUILD_DEBIAN)
qt5_use_modules(inputperseus Core Widgets)
install(TARGETS inputperseus DESTINATION lib/plugins/samplesource)

View File

@ -0,0 +1,199 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "SWGDeviceSettings.h"
#include "SWGDeviceState.h"
#include "dsp/filerecord.h"
#include "dsp/dspcommands.h"
#include "dsp/dspengine.h"
#include "device/devicesourceapi.h"
#include "perseusinput.h"
#include "perseusthread.h"
MESSAGE_CLASS_DEFINITION(PerseusInput::MsgConfigurePerseus, Message)
MESSAGE_CLASS_DEFINITION(PerseusInput::MsgFileRecord, Message)
MESSAGE_CLASS_DEFINITION(PerseusInput::MsgStartStop, Message)
PerseusInput::PerseusInput(DeviceSourceAPI *deviceAPI) :
m_deviceAPI(deviceAPI),
m_fileSink(0),
m_deviceDescription("PerseusInput"),
m_running(false),
m_perseusThread(0),
m_perseusDescriptor(0)
{
openDevice();
char recFileNameCStr[30];
sprintf(recFileNameCStr, "test_%d.sdriq", m_deviceAPI->getDeviceUID());
m_fileSink = new FileRecord(std::string(recFileNameCStr));
m_deviceAPI->addSink(m_fileSink);
}
PerseusInput::~PerseusInput()
{
m_deviceAPI->removeSink(m_fileSink);
delete m_fileSink;
closeDevice();
}
void PerseusInput::destroy()
{
delete this;
}
void PerseusInput::init()
{
applySettings(m_settings, true);
}
bool PerseusInput::start()
{
if (m_running) stop();
applySettings(m_settings, true);
// start / stop streaming is done in the thread.
if ((m_plutoSDRInputThread = new PlutoSDRInputThread(PLUTOSDR_BLOCKSIZE_SAMPLES, m_deviceShared.m_deviceParams->getBox(), &m_sampleFifo)) == 0)
{
qFatal("PlutoSDRInput::start: cannot create thread");
stop();
return false;
}
else
{
qDebug("PlutoSDRInput::start: thread created");
}
m_perseusThread->setLog2Decimation(m_settings.m_log2Decim);
m_perseusThread->startWork();
m_running = true;
return true;
}
void PerseusInput::stop()
{
if (m_perseusThread != 0)
{
m_perseusThread->stopWork();
delete m_perseusThread;
m_perseusThread = 0;
}
m_running = false;
}
QByteArray PerseusInput::serialize() const
{
return m_settings.serialize();
}
bool PerseusInput::deserialize(const QByteArray& data)
{
bool success = true;
if (!m_settings.deserialize(data))
{
m_settings.resetToDefaults();
success = false;
}
MsgConfigurePerseus* message = MsgConfigurePerseus::create(m_settings, true);
m_inputMessageQueue.push(message);
if (m_guiMessageQueue)
{
MsgConfigurePerseus* messageToGUI = MsgConfigurePerseus::create(m_settings, true);
m_guiMessageQueue->push(messageToGUI);
}
return success;
}
const QString& PerseusInput::getDeviceDescription() const
{
return m_deviceDescription;
}
int PerseusInput::getSampleRate() const
{
return (m_settings.m_devSampleRate / (1<<m_settings.m_log2Decim));
}
quint64 PerseusInput::getCenterFrequency() const
{
return m_settings.m_centerFrequency;
}
void PerseusInput::setCenterFrequency(qint64 centerFrequency)
{
PerseusSettings settings = m_settings;
settings.m_centerFrequency = centerFrequency;
MsgConfigurePerseus* message = MsgConfigurePerseus::create(settings, false);
m_inputMessageQueue.push(message);
if (m_guiMessageQueue)
{
MsgConfigurePerseus* messageToGUI = MsgConfigurePerseus::create(settings, false);
m_guiMessageQueue->push(messageToGUI);
}
}
bool PerseusInput::openDevice()
{
m_deviceAPI->getSampleSourceSerial();
int deviceSequence = DevicePerseus::instance().getSequenceFromSerial(m_deviceAPI->getSampleSourceSerial().toStdString());
if ((m_perseusDescriptor = perseus_open(deviceSequence)) == 0)
{
qCritical("PerseusInput::openDevice: cannot open device: %s", perseus_errorstr());
return false;
}
int buf[32];
m_sampleRates.clear();
if (perseus_get_sampling_rates(m_perseusDescriptor, buf, sizeof(buf)/sizeof(buf[0])) < 0)
{
qCritical("PerseusInput::openDevice: cannot get sampling rates: %s", perseus_errorstr());
perseus_close(m_perseusDescriptor);
return false;
}
else
{
for (int i = 0; (i < 32) && (buf[i] != 0); i++)
{
qDebug("PerseusInput::openDevice: sample rate: %d", buf[i]);
m_sampleRates.push_back(buf[i]);
}
}
return true;
}
void PerseusInput::closeDevice()
{
if (m_perseusDescriptor)
{
perseus_stop_async_input(m_perseusDescriptor);
perseus_close(m_perseusDescriptor);
}
}

View File

@ -0,0 +1,137 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_SAMPLESOURCE_PERSEUS_PERSEUSINPUT_H_
#define PLUGINS_SAMPLESOURCE_PERSEUS_PERSEUSINPUT_H_
#include <vector>
#include "dsp/devicesamplesource.h"
#include "util/message.h"
#include "perseussettings.h"
class DeviceSourceAPI;
class FileRecord;
class PerseusThread;
struct perseus_descr;
class PerseusInput : public DeviceSampleSource {
public:
class MsgConfigurePerseus : public Message {
MESSAGE_CLASS_DECLARATION
public:
const PerseusSettings& getSettings() const { return m_settings; }
bool getForce() const { return m_force; }
static MsgConfigurePerseus* create(const PerseusSettings& settings, bool force)
{
return new MsgConfigurePerseus(settings, force);
}
private:
PerseusSettings m_settings;
bool m_force;
MsgConfigurePerseus(const PerseusSettings& settings, bool force) :
Message(),
m_settings(settings),
m_force(force)
{ }
};
class MsgFileRecord : public Message {
MESSAGE_CLASS_DECLARATION
public:
bool getStartStop() const { return m_startStop; }
static MsgFileRecord* create(bool startStop) {
return new MsgFileRecord(startStop);
}
protected:
bool m_startStop;
MsgFileRecord(bool startStop) :
Message(),
m_startStop(startStop)
{ }
};
class MsgStartStop : public Message {
MESSAGE_CLASS_DECLARATION
public:
bool getStartStop() const { return m_startStop; }
static MsgStartStop* create(bool startStop) {
return new MsgStartStop(startStop);
}
protected:
bool m_startStop;
MsgStartStop(bool startStop) :
Message(),
m_startStop(startStop)
{ }
};
PerseusInput(DeviceSourceAPI *deviceAPI);
~PerseusInput();
virtual void destroy();
virtual void init();
virtual bool start();
virtual void stop();
virtual QByteArray serialize() const;
virtual bool deserialize(const QByteArray& data);
virtual void setMessageQueueToGUI(MessageQueue *queue) { m_guiMessageQueue = queue; }
virtual const QString& getDeviceDescription() const;
virtual int getSampleRate() const;
virtual quint64 getCenterFrequency() const;
virtual void setCenterFrequency(qint64 centerFrequency);
virtual bool handleMessage(const Message& message);
virtual int webapiRunGet(
SWGSDRangel::SWGDeviceState& response,
QString& errorMessage);
virtual int webapiRun(
bool run,
SWGSDRangel::SWGDeviceState& response,
QString& errorMessage);
private:
DeviceSourceAPI *m_deviceAPI;
FileRecord *m_fileSink;
QString m_deviceDescription;
PerseusSettings m_settings;
bool m_running;
PerseusThread *m_perseusThread;
perseus_descr *m_perseusDescriptor;
std::vector<uint32_t> m_sampleRates;
QMutex m_mutex;
bool openDevice();
void closeDevice();
bool applySettings(const PerseusSettings& settings, bool force = false);
};
#endif /* PLUGINS_SAMPLESOURCE_PERSEUS_PERSEUSINPUT_H_ */

View File

@ -0,0 +1,95 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "perseussettings.h"
#include "util/simpleserializer.h"
PerseusSettings::PerseusSettings()
{
resetToDefaults();
}
void PerseusSettings::resetToDefaults()
{
m_centerFrequency = 7150*1000;
m_LOppmTenths = 0;
m_devSampleRateIndex = 0;
m_log2Decim = 0;
m_transverterMode = false;
m_transverterDeltaFrequency = 0;
m_adcDither = false;
m_adcPreamp = false;
m_wideBand = false;
m_attenuator = Attenuator_None;
}
QByteArray PerseusSettings::serialize() const
{
SimpleSerializer s(1);
s.writeU32(1, m_devSampleRateIndex);
s.writeS32(2, m_LOppmTenths);
s.writeU32(3, m_log2Decim);
s.writeBool(4, m_transverterMode);
s.writeS64(5, m_transverterDeltaFrequency);
s.writeBool(6, m_adcDither);
s.writeBool(7, m_adcPreamp);
s.writeBool(8, m_wideBand);
s.writeS32(9, (int) m_attenuator);
return s.final();
}
bool PerseusSettings::deserialize(const QByteArray& data)
{
SimpleDeserializer d(data);
if (!d.isValid())
{
resetToDefaults();
return false;
}
if (d.getVersion() == 1)
{
int intval;
d.readU32(1, &m_devSampleRateIndex, 0);
d.readS32(2, &m_LOppmTenths, 0);
d.readU32(3, &m_log2Decim, 0);
d.readBool(4, &m_transverterMode, false);
d.readS64(5, &m_transverterDeltaFrequency, 0);
d.readBool(6, &m_adcDither, false);
d.readBool(7, &m_adcPreamp, false);
d.readBool(8, &m_wideBand, false);
d.readS32(9, &intval, 0);
if ((intval >= 0) && (intval < (int) Attenuator_last)) {
m_attenuator = (Attenuator) intval;
} else {
m_attenuator = Attenuator_None;
}
return true;
}
else
{
resetToDefaults();
return false;
}
}

View File

@ -0,0 +1,52 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef PLUGINS_SAMPLESOURCE_PERSEUS_PERSEUSSETTINGS_H_
#define PLUGINS_SAMPLESOURCE_PERSEUS_PERSEUSSETTINGS_H_
#include <QtGlobal>
struct PerseusSettings
{
typedef enum
{
Attenuator_None,
Attenuator_10dB,
Attenuator_20dB,
Attenuator_30dB,
Attenuator_last
} Attenuator;
quint64 m_centerFrequency;
qint32 m_LOppmTenths;
quint32 m_devSampleRateIndex;
quint32 m_log2Decim;
bool m_transverterMode;
qint64 m_transverterDeltaFrequency;
bool m_adcDither;
bool m_adcPreamp;
bool m_wideBand;
Attenuator m_attenuator;
PerseusSettings();
void resetToDefaults();
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
};
#endif /* PLUGINS_SAMPLESOURCE_PERSEUS_PERSEUSSETTINGS_H_ */