diff --git a/fcdlib/fcdtraits.cpp b/fcdlib/fcdtraits.cpp index 40592dd80..ac008da78 100644 --- a/fcdlib/fcdtraits.cpp +++ b/fcdlib/fcdtraits.cpp @@ -34,7 +34,7 @@ const char *fcd_traits::displayedName = "FunCube Dongle Pro+"; const char *fcd_traits::pluginDisplayedName = "FunCube Pro Input"; const char *fcd_traits::pluginDisplayedName = "FunCube Pro+ Input"; -const char *fcd_traits::pluginVersion = "4.0.0"; +const char *fcd_traits::pluginVersion = "4.3.0"; const char *fcd_traits::pluginVersion = "4.3.0"; const int64_t fcd_traits::loLowLimitFreq = 64000000L; diff --git a/plugins/samplesource/fcdpro/fcdprogui.ui b/plugins/samplesource/fcdpro/fcdprogui.ui index 5e3d747d7..ad9e7c918 100644 --- a/plugins/samplesource/fcdpro/fcdprogui.ui +++ b/plugins/samplesource/fcdpro/fcdprogui.ui @@ -31,9 +31,6 @@ FunCubeDongle - - start/stop acquisition - 3 @@ -61,6 +58,9 @@ + + start/stop acquisition + @@ -287,7 +287,11 @@ - + + + LNA enhancement + + @@ -297,7 +301,11 @@ - + + + Band optimizations + + @@ -311,7 +319,11 @@ - + + + Band bias + + @@ -321,7 +333,11 @@ - + + + Mode ? + + @@ -335,7 +351,11 @@ - + + + LNA gain + + @@ -345,7 +365,11 @@ - + + + RF filter selection + + @@ -359,7 +383,11 @@ - + + + Mixer gain + + @@ -369,7 +397,11 @@ - + + + Mixer filter selection + + @@ -383,7 +415,11 @@ - + + + Gain block #1 + + @@ -393,7 +429,11 @@ - + + + Baseband RC filter selection + + @@ -407,7 +447,11 @@ - + + + Gain block #2 + + @@ -417,7 +461,11 @@ - + + + Gain block #3 + + @@ -431,7 +479,11 @@ - + + + Gain block #4 + + @@ -441,7 +493,11 @@ - + + + IF filter selection + + @@ -455,7 +511,11 @@ - + + + Gain block #5 + + @@ -465,7 +525,11 @@ - + + + Gain block #6 + + diff --git a/plugins/samplesource/fcdpro/fcdproinput.cpp b/plugins/samplesource/fcdpro/fcdproinput.cpp index 03f1ec662..2ba8b52c0 100644 --- a/plugins/samplesource/fcdpro/fcdproinput.cpp +++ b/plugins/samplesource/fcdpro/fcdproinput.cpp @@ -1,6 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // -// written by Christian Daniel // +// Copyright (C) 2015-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 // @@ -15,8 +14,6 @@ // along with this program. If not, see . // /////////////////////////////////////////////////////////////////////////////////// -// FIXME: FCD is handled very badly! - #include #include #include @@ -27,10 +24,9 @@ #include "dsp/dspcommands.h" #include "dsp/dspengine.h" #include "dsp/filerecord.h" +#include "device/devicesourceapi.h" + #include "fcdproinput.h" - -#include - #include "fcdprothread.h" #include "fcdtraits.h" #include "fcdproconst.h" @@ -47,6 +43,7 @@ FCDProInput::FCDProInput(DeviceSourceAPI *deviceAPI) : m_deviceDescription(fcd_traits::displayedName), m_running(false) { + m_fcdFIFO.setSize(20*fcd_traits::convBufSize); openDevice(); m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID())); m_deviceAPI->addSink(m_fileSink); @@ -54,9 +51,13 @@ FCDProInput::FCDProInput(DeviceSourceAPI *deviceAPI) : FCDProInput::~FCDProInput() { - if (m_running) stop(); + if (m_running) { + stop(); + } + m_deviceAPI->removeSink(m_fileSink); delete m_fileSink; + closeDevice(); } @@ -67,15 +68,12 @@ void FCDProInput::destroy() bool FCDProInput::openDevice() { - int device = m_deviceAPI->getSampleSourceSequence(); - - if (m_dev != 0) - { + if (m_dev != 0) { closeDevice(); } + int device = m_deviceAPI->getSampleSourceSequence(); qDebug() << "FCDProInput::openDevice with device #" << device; - m_dev = fcdOpen(fcd_traits::vendorId, fcd_traits::productId, device); if (m_dev == 0) @@ -117,7 +115,17 @@ bool FCDProInput::start() return false; } - m_FCDThread = new FCDProThread(&m_sampleFifo); + if (!openFCDAudio(fcd_traits::qtDeviceName)) + { + qCritical("FCDProInput::start: could not open FCD audio source"); + return false; + } + else + { + qDebug("FCDProInput::start: FCD audio source opened"); + } + + m_FCDThread = new FCDProThread(&m_sampleFifo, &m_fcdFIFO); m_FCDThread->startWork(); // mutexLocker.unlock(); @@ -139,6 +147,35 @@ void FCDProInput::closeDevice() m_dev = 0; } +bool FCDProInput::openFCDAudio(const char* cardname) +{ + AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager(); + const QList& audioList = audioDeviceManager->getInputDevices(); + + for (const auto &itAudio : audioList) + { + if (itAudio.deviceName().contains(QString(cardname))) + { + int fcdDeviceIndex = audioDeviceManager->getInputDeviceIndex(itAudio.deviceName()); + m_fcdAudioInput.start(fcdDeviceIndex, fcd_traits::sampleRate); + int fcdSampleRate = m_fcdAudioInput.getRate(); + qDebug("FCDProPlusInput::openFCDAudio: %s index %d at %d S/s", + itAudio.deviceName().toStdString().c_str(), fcdDeviceIndex, fcdSampleRate); + m_fcdAudioInput.addFifo(&m_fcdFIFO); + return true; + } + } + + qCritical("FCDProInput::openFCDAudio: device with name %s not found", cardname); + return false; +} + +void FCDProInput::closeFCDAudio() +{ + m_fcdAudioInput.removeFifo(&m_fcdFIFO); + m_fcdAudioInput.stop(); +} + void FCDProInput::stop() { // QMutexLocker mutexLocker(&m_mutex); @@ -148,7 +185,8 @@ void FCDProInput::stop() m_FCDThread->stopWork(); // wait for thread to quit ? delete m_FCDThread; - m_FCDThread = 0; + m_FCDThread = nullptr; + closeFCDAudio(); } m_running = false; diff --git a/plugins/samplesource/fcdpro/fcdproinput.h b/plugins/samplesource/fcdpro/fcdproinput.h index dfdbabe0d..aa0c7240f 100644 --- a/plugins/samplesource/fcdpro/fcdproinput.h +++ b/plugins/samplesource/fcdpro/fcdproinput.h @@ -1,6 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany // -// written by Christian Daniel // +// Copyright (C) 2015-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 // @@ -22,7 +21,10 @@ #include #include -#include +#include "dsp/devicesamplesource.h" +#include "audio/audioinput.h" +#include "audio/audiofifo.h" + #include "fcdprosettings.h" #include "fcdhid.h" @@ -158,6 +160,8 @@ public: private: bool openDevice(); void closeDevice(); + bool openFCDAudio(const char *filename); + void closeFCDAudio(); void applySettings(const FCDProSettings& settings, bool force); void set_lo_ppm(); @@ -165,6 +169,8 @@ private: DeviceSourceAPI *m_deviceAPI; hid_device *m_dev; + AudioInput m_fcdAudioInput; + AudioFifo m_fcdFIFO; QMutex m_mutex; FCDProSettings m_settings; FCDProThread* m_FCDThread; diff --git a/plugins/samplesource/fcdpro/fcdprothread.cpp b/plugins/samplesource/fcdpro/fcdprothread.cpp index e1fbbb721..7b4152b2e 100644 --- a/plugins/samplesource/fcdpro/fcdprothread.cpp +++ b/plugins/samplesource/fcdpro/fcdprothread.cpp @@ -18,16 +18,19 @@ #include #include #include -#include "fcdprothread.h" +#include +#include #include "dsp/samplesinkfifo.h" -#include "fcdtraits.h" +#include "audio/audiofifo.h" -FCDProThread::FCDProThread(SampleSinkFifo* sampleFifo, QObject* parent) : +#include "fcdprothread.h" + +FCDProThread::FCDProThread(SampleSinkFifo* sampleFifo, AudioFifo *fcdFIFO, QObject* parent) : QThread(parent), - fcd_handle(NULL), + m_fcdFIFO(fcdFIFO), m_running(false), - m_convertBuffer(fcd_traits::convBufSize), + m_convertBuffer(fcd_traits::convBufSize), // nb samples m_sampleFifo(sampleFifo) { start(); @@ -59,107 +62,23 @@ void FCDProThread::stopWork() void FCDProThread::run() { - if ( !OpenSource(fcd_traits::alsaDeviceName) ) - { - qCritical() << "FCDThread::run: cannot open FCD sound card"; - return; - } - // TODO: fallback to original fcd + m_running = true; + qDebug("FCDProThread::run: start running loop"); - m_running = true; + while (m_running) + { + work(fcd_traits::convBufSize); + std::this_thread::sleep_for(std::chrono::microseconds(200)); + } - while(m_running) - { - if (work(fcd_traits::convBufSize) < 0) - { - break; - } - } - - CloseSource(); + qDebug("FCDProThread::run: running loop stopped"); + m_running = false; } -bool FCDProThread::OpenSource(const char* cardname) +void FCDProThread::work(unsigned int n_items) { - bool fail = false; - snd_pcm_hw_params_t* params; - //fcd_rate = FCDPP_RATE; - //fcd_channels =2; - //fcd_format = SND_PCM_SFMT_U16_LE; - snd_pcm_stream_t fcd_stream = SND_PCM_STREAM_CAPTURE; - - if (fcd_handle) - { - return false; - } - - if (snd_pcm_open(&fcd_handle, cardname, fcd_stream, 0) < 0) - { - qCritical("FCDThread::OpenSource: cannot open %s", cardname); - return false; - } - - snd_pcm_hw_params_alloca(¶ms); - - if (snd_pcm_hw_params_any(fcd_handle, params) < 0) - { - qCritical("FCDThread::OpenSource: snd_pcm_hw_params_any failed"); - fail = true; - } - else if (snd_pcm_hw_params(fcd_handle, params) < 0) - { - qCritical("FCDThread::OpenSource: snd_pcm_hw_params failed"); - fail = true; - // TODO: check actual samplerate, may be crippled firmware - } - else - { - if (snd_pcm_start(fcd_handle) < 0) - { - qCritical("FCDThread::OpenSource: snd_pcm_start failed"); - fail = true; - } - } - - if (fail) - { - snd_pcm_close( fcd_handle ); - return false; - } - else - { - qDebug("FCDThread::OpenSource: Funcube stream started"); - } - - return true; + uint32_t nbRead = m_fcdFIFO->read((unsigned char *) m_buf, n_items); // number of samples + SampleVector::iterator it = m_convertBuffer.begin(); + m_decimators.decimate1(&it, m_buf, 2*nbRead); + m_sampleFifo->write(m_convertBuffer.begin(), it); } - -void FCDProThread::CloseSource() -{ - if (fcd_handle) - { - snd_pcm_close( fcd_handle ); - } - - fcd_handle = NULL; -} - -int FCDProThread::work(int n_items) -{ - int l; - SampleVector::iterator it; - void *out; - - it = m_convertBuffer.begin(); - out = (void *)&it[0]; - l = snd_pcm_mmap_readi(fcd_handle, out, (snd_pcm_uframes_t)n_items); - if (l > 0) - m_sampleFifo->write(it, it + l); - if (l == -EPIPE) { - qDebug("FCD: Overrun detected"); - return 0; - } - return l; -} - - diff --git a/plugins/samplesource/fcdpro/fcdprothread.h b/plugins/samplesource/fcdpro/fcdprothread.h index ce3e47da5..05891cd92 100644 --- a/plugins/samplesource/fcdpro/fcdprothread.h +++ b/plugins/samplesource/fcdpro/fcdprothread.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2015 Edouard Griffiths, F4EXB // +// Copyright (C) 2015-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 // @@ -20,33 +20,37 @@ #include #include #include -#include "dsp/inthalfbandfilter.h" -#include + #include "dsp/samplesinkfifo.h" +#include "dsp/decimators.h" +#include "fcdtraits.h" + +class AudioFifo; class FCDProThread : public QThread { Q_OBJECT public: - FCDProThread(SampleSinkFifo* sampleFifo, QObject* parent = NULL); + FCDProThread(SampleSinkFifo* sampleFifo, AudioFifo *fcdFIFO, QObject* parent = nullptr); ~FCDProThread(); void startWork(); void stopWork(); - bool OpenSource(const char *filename); - void CloseSource(); private: - snd_pcm_t* fcd_handle; + AudioFifo* m_fcdFIFO; QMutex m_startWaitMutex; QWaitCondition m_startWaiter; bool m_running; + qint16 m_buf[fcd_traits::convBufSize*2]; // stereo (I, Q) SampleVector m_convertBuffer; SampleSinkFifo* m_sampleFifo; + Decimators m_decimators; void run(); - int work(int n_items); + void work(unsigned int n_items); }; + #endif // INCLUDE_FCDPROTHREAD_H diff --git a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp index 30d77a5e8..4c9776e13 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp @@ -23,11 +23,10 @@ #include "dsp/dspcommands.h" #include "dsp/dspengine.h" -#include +#include "dsp/filerecord.h" +#include "device/devicesourceapi.h" + #include "fcdproplusinput.h" - -#include - #include "fcdproplusthread.h" #include "fcdtraits.h" #include "fcdproplusconst.h" @@ -39,7 +38,6 @@ MESSAGE_CLASS_DEFINITION(FCDProPlusInput::MsgFileRecord, Message) FCDProPlusInput::FCDProPlusInput(DeviceSourceAPI *deviceAPI) : m_deviceAPI(deviceAPI), m_dev(0), - fcd_handle(0), m_settings(), m_FCDThread(0), m_deviceDescription(fcd_traits::displayedName), @@ -53,9 +51,13 @@ FCDProPlusInput::FCDProPlusInput(DeviceSourceAPI *deviceAPI) : FCDProPlusInput::~FCDProPlusInput() { - if (m_running) stop(); + if (m_running) { + stop(); + } + m_deviceAPI->removeSink(m_fileSink); delete m_fileSink; + closeDevice(); } @@ -66,9 +68,12 @@ void FCDProPlusInput::destroy() bool FCDProPlusInput::openDevice() { + if (m_dev != 0) { + closeDevice(); + } + int device = m_deviceAPI->getSampleSourceSequence(); qDebug() << "FCDProPlusInput::openDevice with device #" << device; - m_dev = fcdOpen(fcd_traits::vendorId, fcd_traits::productId, device); if (m_dev == 0) diff --git a/plugins/samplesource/fcdproplus/fcdproplusinput.h b/plugins/samplesource/fcdproplus/fcdproplusinput.h index 99a139dff..94206cd61 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusinput.h +++ b/plugins/samplesource/fcdproplus/fcdproplusinput.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////////////// -// Copyright (C) 2016 Edouard Griffiths, F4EXB // +// Copyright (C) 2016-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 // @@ -21,8 +21,6 @@ #include #include -#include - #include "dsp/devicesamplesource.h" #include "audio/audioinput.h" #include "audio/audiofifo.h" @@ -161,7 +159,6 @@ private: hid_device *m_dev; AudioInput m_fcdAudioInput; AudioFifo m_fcdFIFO; - snd_pcm_t* fcd_handle; QMutex m_mutex; FCDProPlusSettings m_settings; FCDProPlusThread* m_FCDThread; diff --git a/plugins/samplesource/fcdproplus/fcdproplusthread.cpp b/plugins/samplesource/fcdproplus/fcdproplusthread.cpp index 0f742bde7..4a6f27f2a 100644 --- a/plugins/samplesource/fcdproplus/fcdproplusthread.cpp +++ b/plugins/samplesource/fcdproplus/fcdproplusthread.cpp @@ -17,11 +17,14 @@ #include #include #include -#include "fcdproplusthread.h" +#include +#include #include "dsp/samplesinkfifo.h" #include "audio/audiofifo.h" +#include "fcdproplusthread.h" + FCDProPlusThread::FCDProPlusThread(SampleSinkFifo* sampleFifo, AudioFifo *fcdFIFO, QObject* parent) : QThread(parent), m_fcdFIFO(fcdFIFO), @@ -61,8 +64,10 @@ void FCDProPlusThread::run() m_running = true; qDebug("FCDThread::run: start running loop"); - while (m_running) { + while (m_running) + { work(fcd_traits::convBufSize); + std::this_thread::sleep_for(std::chrono::microseconds(100)); } qDebug("FCDThread::run: running loop stopped");