mirror of https://github.com/f4exb/sdrangel.git
Deep redesign: phase #4. Compiles
This commit is contained in:
parent
b5f2475fbf
commit
a6a7145f3d
|
@ -129,9 +129,12 @@ Done since the fork
|
|||
- Coarse and fine trigger level sliders
|
||||
- Minimalist recording (no file choice)
|
||||
- File sample source plugin (recording reader) not working
|
||||
- Make the DSP engine global static
|
||||
- Fixed startup initialization sequence. New initialization phase in DSP engine and new ready state
|
||||
- Message queuing and handling redesign
|
||||
- Redesign:
|
||||
- Make the DSP engine global static
|
||||
- Fixed startup initialization sequence. New initialization phase in DSP engine and new ready state
|
||||
- Synchronous messaging class to push message to thread and wait for completion
|
||||
- Message queuing and handling redesign
|
||||
- Many other little things...
|
||||
|
||||
=====
|
||||
To Do
|
||||
|
|
|
@ -17,10 +17,9 @@ public:
|
|||
void configure(MessageQueue* messageQueue, int sampleRate, int centerFrequency);
|
||||
int getInputSampleRate() const { return m_inputSampleRate; }
|
||||
|
||||
virtual bool init(const Message& cmd);
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
|
||||
protected:
|
||||
|
|
|
@ -105,6 +105,30 @@ private:
|
|||
SampleSink* m_sampleSink;
|
||||
};
|
||||
|
||||
class SDRANGELOVE_API DSPAddThreadedSink : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
DSPAddThreadedSink(SampleSink* sampleSink) : Message(), m_sampleSink(sampleSink) { }
|
||||
|
||||
SampleSink* getSampleSink() const { return m_sampleSink; }
|
||||
|
||||
private:
|
||||
SampleSink* m_sampleSink;
|
||||
};
|
||||
|
||||
class SDRANGELOVE_API DSPRemoveThreadedSink : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
DSPRemoveThreadedSink(SampleSink* sampleSink) : Message(), m_sampleSink(sampleSink) { }
|
||||
|
||||
SampleSink* getSampleSink() const { return m_sampleSink; }
|
||||
|
||||
private:
|
||||
SampleSink* m_sampleSink;
|
||||
};
|
||||
|
||||
class SDRANGELOVE_API DSPAddAudioSink : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
class SampleSource;
|
||||
class SampleSink;
|
||||
class ThreadedSampleSink;
|
||||
class AudioFifo;
|
||||
|
||||
class SDRANGELOVE_API DSPEngine : public QThread {
|
||||
|
@ -66,6 +67,9 @@ public:
|
|||
void addSink(SampleSink* sink); //!< Add a sample sink
|
||||
void removeSink(SampleSink* sink); //!< Remove a sample sink
|
||||
|
||||
void addThreadedSink(SampleSink* sink); //!< Add a sample sink that will run on its own thread
|
||||
void removeThreadedSink(SampleSink* sink); //!< Remove a sample sink that runs on its own thread
|
||||
|
||||
void addAudioSink(AudioFifo* audioFifo); //!< Add the audio sink
|
||||
void removeAudioSink(AudioFifo* audioFifo); //!< Remove the audio sink
|
||||
|
||||
|
@ -89,7 +93,10 @@ private:
|
|||
SampleSource* m_sampleSource;
|
||||
|
||||
typedef std::list<SampleSink*> SampleSinks;
|
||||
SampleSinks m_sampleSinks;
|
||||
SampleSinks m_sampleSinks; //!< sample sinks within main thread (usually spectrum, file output)
|
||||
|
||||
typedef std::list<ThreadedSampleSink*> ThreadedSampleSinks;
|
||||
ThreadedSampleSinks m_threadedSampleSinks; //!< sample sinks on their own threads (usually channels)
|
||||
|
||||
AudioOutput m_audioSink;
|
||||
|
||||
|
@ -120,7 +127,7 @@ private slots:
|
|||
void handleData(); //!< Handle data when samples from source FIFO are ready to be processed
|
||||
void handleSourceMessages(); //!< Handle source message output
|
||||
void handleInputMessages(); //!< Handle input message queue
|
||||
void handleSynchronousMessages(Message *message); //!< Handle synchronous messages with the thread
|
||||
void handleSynchronousMessages(const Message& message); //!< Handle synchronous messages with the thread
|
||||
};
|
||||
|
||||
#endif // INCLUDE_DSPENGINE_H
|
||||
|
|
|
@ -28,7 +28,6 @@ public:
|
|||
|
||||
void configure(MessageQueue* msgQueue, const std::string& filename);
|
||||
|
||||
virtual bool init(const Message& cmd);
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
|
|
|
@ -35,7 +35,6 @@ public:
|
|||
uint traceSize);
|
||||
void setOneShot(bool oneShot);
|
||||
|
||||
virtual bool init(const Message& cmd);
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
|
|
|
@ -14,7 +14,6 @@ public:
|
|||
SpectrumScopeComboVis(SpectrumVis* spectrumVis, ScopeVis* scopeVis);
|
||||
virtual ~SpectrumScopeComboVis();
|
||||
|
||||
virtual bool init(const Message& cmd);
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
|
|
|
@ -16,7 +16,6 @@ public:
|
|||
|
||||
void configure(MessageQueue* msgQueue, int fftSize, int overlapPercent, FFTWindow::Function window);
|
||||
|
||||
virtual bool init(const Message& cmd);
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||
void feedTriggered(SampleVector::const_iterator triggerPoint, SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||
virtual void start();
|
||||
|
|
|
@ -52,7 +52,7 @@ public:
|
|||
|
||||
void freeAll();
|
||||
|
||||
bool handleMessage(Message* message);
|
||||
bool handleMessage(const Message& message);
|
||||
|
||||
void updateSampleSourceDevices();
|
||||
void fillSampleSourceSelector(QComboBox* comboBox);
|
||||
|
|
|
@ -13,18 +13,18 @@ public:
|
|||
SampleSink();
|
||||
virtual ~SampleSink();
|
||||
|
||||
virtual bool init(const Message& cmd) = 0;
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly) = 0;
|
||||
virtual void start() = 0;
|
||||
virtual void stop() = 0;
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly) = 0;
|
||||
virtual bool handleMessage(const Message& cmd) = 0; //!< Processing of a message. Returns true if message has actually been processed
|
||||
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
MessageQueue *getOutputMessageQueue() { return &m_outputMessageQueue; }
|
||||
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
||||
MessageQueue *getOutputMessageQueue() { return &m_outputMessageQueue; } //!< Get the queue for asynchronous outbound communication
|
||||
|
||||
protected:
|
||||
MessageQueue m_inputMessageQueue;
|
||||
MessageQueue m_outputMessageQueue;
|
||||
void handleInputMessages();
|
||||
MessageQueue m_inputMessageQueue; //!< Queue for asynchronous inbound communication
|
||||
MessageQueue m_outputMessageQueue; //!< Queue for asynchronous outbound communication
|
||||
};
|
||||
|
||||
#endif // INCLUDE_SAMPLESINK_H
|
||||
|
|
|
@ -29,13 +29,13 @@ public:
|
|||
SampleSource();
|
||||
virtual ~SampleSource();
|
||||
|
||||
virtual void init(const Message& cmd) = 0;
|
||||
virtual bool init(const Message& cmd) = 0;
|
||||
virtual bool start(int device) = 0;
|
||||
virtual void stop() = 0;
|
||||
|
||||
virtual const QString& getDeviceDescription() const = 0;
|
||||
virtual int getSampleRate() const { return m_sampleRate; };
|
||||
virtual quint64 getCenterFrequency() const { return m_centerFrequency; };
|
||||
virtual int getSampleRate() const = 0; //!< Sample rate exposed by the source
|
||||
virtual quint64 getCenterFrequency() const = 0; //!< Center frequency exposed by the source
|
||||
|
||||
virtual bool handleMessage(const Message& message) = 0;
|
||||
|
||||
|
@ -44,15 +44,9 @@ public:
|
|||
SampleFifo* getSampleFifo() { return &m_sampleFifo; }
|
||||
|
||||
protected:
|
||||
void setSampleRate(int sampleRate);
|
||||
void setCenterFrequency(quint64 centerFrequency);
|
||||
void sendNewData();
|
||||
|
||||
SampleFifo m_sampleFifo;
|
||||
MessageQueue m_inputMessageQueue;
|
||||
MessageQueue m_outputMessageQueue;
|
||||
int m_sampleRate;
|
||||
quint64 m_centerFrequency;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_SAMPLESOURCE_H
|
||||
|
|
|
@ -1,41 +1,62 @@
|
|||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2015 F4EXB //
|
||||
// written by Edouard Griffiths //
|
||||
// //
|
||||
// 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_THREADEDSAMPLESINK_H
|
||||
#define INCLUDE_THREADEDSAMPLESINK_H
|
||||
|
||||
#include <QMutex>
|
||||
#include <QThread>
|
||||
#include "samplesink.h"
|
||||
#include "dsp/samplefifo.h"
|
||||
#include "util/messagequeue.h"
|
||||
#include "util/export.h"
|
||||
#include "util/syncmessenger.h"
|
||||
|
||||
class QThread;
|
||||
class SampleSink;
|
||||
|
||||
class SDRANGELOVE_API ThreadedSampleSink : public SampleSink {
|
||||
/**
|
||||
* This class is a wrapper for SampleSink that runs the SampleSink object in its own thread
|
||||
*/
|
||||
class SDRANGELOVE_API ThreadedSampleSink : public QThread {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ThreadedSampleSink(SampleSink* sampleSink);
|
||||
virtual ~ThreadedSampleSink();
|
||||
~ThreadedSampleSink();
|
||||
|
||||
MessageQueue* getMessageQueue() { return &m_messageQueue; }
|
||||
const SampleSink *getSink() const { return m_sampleSink; }
|
||||
MessageQueue* getInputMessageQueue() { return m_sampleSink->getInputMessageQueue(); } //!< Return pointer to sample sink's input message queue
|
||||
MessageQueue* getOutputMessageQueue() { return m_sampleSink->getOutputMessageQueue(); } //!< Return pointer to sample sink's output message queue
|
||||
|
||||
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||
void start();
|
||||
void stop();
|
||||
bool handleMessage(Message* cmd);
|
||||
void start(); //!< this thread start()
|
||||
void stop(); //!< this thread exit() and wait()
|
||||
|
||||
bool sendWaitSink(const Message& cmd); //!< Send message to sink synchronously
|
||||
void feed(SampleVector::const_iterator& begin, SampleVector::const_iterator& end, bool positiveOnly); //!< Feed sink with samples
|
||||
|
||||
QString getSampleSinkObjectName() const;
|
||||
|
||||
protected:
|
||||
QMutex m_mutex;
|
||||
QThread* m_thread;
|
||||
MessageQueue m_messageQueue;
|
||||
SampleFifo m_sampleFifo;
|
||||
SyncMessenger m_syncMessenger; //!< Used to process messages synchronously with the thread
|
||||
SampleSink* m_sampleSink;
|
||||
|
||||
protected slots:
|
||||
void handleData();
|
||||
void handleMessages();
|
||||
void threadStarted();
|
||||
void threadFinished();
|
||||
private:
|
||||
void run(); //!< this thread run() method
|
||||
void handleSynchronousMessages(const Message& message); //!< Handle synchronous messages with the thread
|
||||
};
|
||||
|
||||
#endif // INCLUDE_THREADEDSAMPLESINK_H
|
||||
|
|
|
@ -37,12 +37,14 @@ public:
|
|||
void removeChannelMarker(ChannelMarker* channelMarker);
|
||||
|
||||
// DSPEngine access
|
||||
/* Direct access with DSP engine singleton
|
||||
void setSampleSource(SampleSource* sampleSource);
|
||||
void addSampleSink(SampleSink* sampleSink);
|
||||
void removeSampleSink(SampleSink* sampleSink);
|
||||
MessageQueue* getDSPEngineMessageQueue();
|
||||
void addAudioSource(AudioFifo* audioFifo);
|
||||
void removeAudioSource(AudioFifo* audioFifo);
|
||||
*/
|
||||
|
||||
// Sample Source stuff
|
||||
void registerSampleSource(const QString& sourceName, PluginInterface* plugin);
|
||||
|
|
|
@ -9,6 +9,8 @@ class Message;
|
|||
class SDRANGELOVE_API PluginGUI {
|
||||
public:
|
||||
PluginGUI() { };
|
||||
virtual ~PluginGUI() { };
|
||||
|
||||
virtual void destroy() = 0;
|
||||
|
||||
virtual void setName(const QString& name) = 0;
|
||||
|
@ -23,7 +25,7 @@ public:
|
|||
virtual QByteArray serialize() const = 0;
|
||||
virtual bool deserialize(const QByteArray& data) = 0;
|
||||
|
||||
virtual bool handleMessage(Message* message) = 0;
|
||||
virtual bool handleMessage(const Message& message) = 0;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_PLUGINGUI_H
|
||||
|
|
|
@ -43,7 +43,7 @@ protected:
|
|||
public: \
|
||||
const char* getIdentifier() const; \
|
||||
bool matchIdentifier(const char* identifier) const; \
|
||||
static bool match(const Message* message); \
|
||||
static bool match(const Message& message); \
|
||||
protected: \
|
||||
static const char* m_identifier; \
|
||||
private:
|
||||
|
@ -54,6 +54,6 @@ protected:
|
|||
bool Name::matchIdentifier(const char* identifier) const {\
|
||||
return (m_identifier == identifier) ? true : BaseClass::matchIdentifier(identifier); \
|
||||
} \
|
||||
bool Name::match(const Message* message) { return message->matchIdentifier(m_identifier); }
|
||||
bool Name::match(const Message& message) { return message.matchIdentifier(m_identifier); }
|
||||
|
||||
#endif // INCLUDE_MESSAGE_H
|
||||
|
|
|
@ -36,11 +36,11 @@ public:
|
|||
SyncMessenger();
|
||||
~SyncMessenger();
|
||||
|
||||
int sendWait(Message *message, unsigned long msPollTime = 100); //!< Send message and waits for its process completion
|
||||
int sendWait(const Message& message, unsigned long msPollTime = 100); //!< Send message and waits for its process completion
|
||||
void done(int result = 0); //!< Processing of the message is complete
|
||||
|
||||
signals:
|
||||
void messageSent(Message *message);
|
||||
void messageSent(const Message& message);
|
||||
|
||||
protected:
|
||||
QWaitCondition m_waitCondition;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "amdemod.h"
|
||||
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <stdio.h>
|
||||
#include <complex.h>
|
||||
#include "audio/audiooutput.h"
|
||||
|
@ -55,93 +56,53 @@ AMDemod::~AMDemod()
|
|||
void AMDemod::configure(MessageQueue* messageQueue, Real rfBandwidth, Real afBandwidth, Real volume, Real squelch)
|
||||
{
|
||||
Message* cmd = MsgConfigureAMDemod::create(rfBandwidth, afBandwidth, volume, squelch);
|
||||
cmd->submit(messageQueue, this);
|
||||
messageQueue->push(cmd);
|
||||
}
|
||||
|
||||
/*
|
||||
float arctan2(Real y, Real x)
|
||||
{
|
||||
Real coeff_1 = M_PI / 4;
|
||||
Real coeff_2 = 3 * coeff_1;
|
||||
Real abs_y = fabs(y) + 1e-10; // kludge to prevent 0/0 condition
|
||||
Real angle;
|
||||
if( x>= 0) {
|
||||
Real r = (x - abs_y) / (x + abs_y);
|
||||
angle = coeff_1 - coeff_1 * r;
|
||||
} else {
|
||||
Real r = (x + abs_y) / (abs_y - x);
|
||||
angle = coeff_2 - coeff_1 * r;
|
||||
}
|
||||
if(y < 0)
|
||||
return(-angle);
|
||||
else return(angle);
|
||||
}
|
||||
|
||||
Real angleDist(Real a, Real b)
|
||||
{
|
||||
Real dist = b - a;
|
||||
|
||||
while(dist <= M_PI)
|
||||
dist += 2 * M_PI;
|
||||
while(dist >= M_PI)
|
||||
dist -= 2 * M_PI;
|
||||
|
||||
return dist;
|
||||
}
|
||||
*/
|
||||
|
||||
void AMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool firstOfBurst)
|
||||
{
|
||||
Complex ci;
|
||||
|
||||
if(m_audioFifo->size() <= 0)
|
||||
if (m_audioFifo->size() <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for(SampleVector::const_iterator it = begin; it != end; ++it) {
|
||||
for (SampleVector::const_iterator it = begin; it != end; ++it)
|
||||
{
|
||||
Complex c(it->real() / 32768.0, it->imag() / 32768.0);
|
||||
c *= m_nco.nextIQ();
|
||||
|
||||
{
|
||||
if(m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci)) {
|
||||
if (m_interpolator.interpolate(&m_interpolatorDistanceRemain, c, &ci))
|
||||
{
|
||||
m_sampleBuffer.push_back(Sample(ci.real() * 32767.0, ci.imag() * 32767.0));
|
||||
|
||||
Real magsq = ci.real() * ci.real() + ci.imag() * ci.imag();
|
||||
m_movingAverage.feed(magsq);
|
||||
if(m_movingAverage.average() >= m_squelchLevel)
|
||||
|
||||
if (m_movingAverage.average() >= m_squelchLevel)
|
||||
{
|
||||
m_squelchState = m_running.m_audioSampleRate/ 20;
|
||||
}
|
||||
|
||||
qint16 sample;
|
||||
if(m_squelchState > 0) {
|
||||
|
||||
if (m_squelchState > 0)
|
||||
{
|
||||
m_squelchState--;
|
||||
/*
|
||||
Real argument = arg(ci);
|
||||
Real demod = argument - m_lastArgument;
|
||||
m_lastArgument = argument;
|
||||
*/
|
||||
|
||||
/* NFM demod:
|
||||
Complex d = conj(m_lastSample) * ci;
|
||||
m_lastSample = ci;
|
||||
Real demod = atan2(d.imag(), d.real());
|
||||
//Real demod = arctan2(d.imag(), d.real());
|
||||
*/
|
||||
|
||||
/*
|
||||
Real argument1 = arg(ci);//atan2(ci.imag(), ci.real());
|
||||
Real argument2 = m_lastSample.real();
|
||||
Real demod = angleDist(argument2, argument1);
|
||||
m_lastSample = Complex(argument1, 0);
|
||||
*/
|
||||
Real demod = sqrt(magsq);
|
||||
|
||||
//demod /= M_PI;
|
||||
|
||||
demod = m_lowpass.filter(demod);
|
||||
|
||||
if(demod < -1)
|
||||
if (demod < -1)
|
||||
{
|
||||
demod = -1;
|
||||
else if(demod > 1)
|
||||
}
|
||||
else if (demod > 1)
|
||||
{
|
||||
demod = 1;
|
||||
}
|
||||
|
||||
m_volumeAGC.feed(demod);
|
||||
|
||||
|
@ -149,7 +110,9 @@ void AMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_itera
|
|||
demod *= m_running.m_volume;
|
||||
sample = demod * 32700 * 16;
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_volumeAGC.close();
|
||||
sample = 0;
|
||||
}
|
||||
|
@ -157,10 +120,16 @@ void AMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_itera
|
|||
m_audioBuffer[m_audioBufferFill].l = sample;
|
||||
m_audioBuffer[m_audioBufferFill].r = sample;
|
||||
++m_audioBufferFill;
|
||||
if(m_audioBufferFill >= m_audioBuffer.size()) {
|
||||
|
||||
if (m_audioBufferFill >= m_audioBuffer.size())
|
||||
{
|
||||
uint res = m_audioFifo->write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 1);
|
||||
if(res != m_audioBufferFill)
|
||||
|
||||
if (res != m_audioBufferFill)
|
||||
{
|
||||
qDebug("lost %u audio samples", m_audioBufferFill - res);
|
||||
}
|
||||
|
||||
m_audioBufferFill = 0;
|
||||
}
|
||||
|
||||
|
@ -168,15 +137,24 @@ void AMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_itera
|
|||
}
|
||||
}
|
||||
}
|
||||
if(m_audioBufferFill > 0) {
|
||||
|
||||
if (m_audioBufferFill > 0)
|
||||
{
|
||||
uint res = m_audioFifo->write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 1);
|
||||
if(res != m_audioBufferFill)
|
||||
|
||||
if (res != m_audioBufferFill)
|
||||
{
|
||||
qDebug("lost %u samples", m_audioBufferFill - res);
|
||||
}
|
||||
|
||||
m_audioBufferFill = 0;
|
||||
}
|
||||
|
||||
if(m_sampleSink != NULL)
|
||||
if(m_sampleSink != 0)
|
||||
{
|
||||
m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), false);
|
||||
}
|
||||
|
||||
m_sampleBuffer.clear();
|
||||
}
|
||||
|
||||
|
@ -194,28 +172,54 @@ void AMDemod::stop()
|
|||
{
|
||||
}
|
||||
|
||||
bool AMDemod::handleMessage(Message* cmd)
|
||||
bool AMDemod::handleMessage(const Message& cmd)
|
||||
{
|
||||
if(DSPSignalNotification::match(cmd)) {
|
||||
DSPSignalNotification* signal = (DSPSignalNotification*)cmd;
|
||||
qDebug() << "AMDemod::handleMessage";
|
||||
|
||||
if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
|
||||
m_config.m_inputSampleRate = notif.getSampleRate();
|
||||
m_config.m_inputFrequencyOffset = notif.getFrequencyOffset();
|
||||
|
||||
m_config.m_inputSampleRate = signal->getSampleRate();
|
||||
m_config.m_inputFrequencyOffset = signal->getFrequencyOffset();
|
||||
apply();
|
||||
cmd->completed();
|
||||
|
||||
qDebug() << " - DSPSignalNotification:"
|
||||
<< " m_inputSampleRate: " << m_config.m_inputSampleRate
|
||||
<< " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset;
|
||||
|
||||
return true;
|
||||
} else if(MsgConfigureAMDemod::match(cmd)) {
|
||||
MsgConfigureAMDemod* cfg = (MsgConfigureAMDemod*)cmd;
|
||||
m_config.m_rfBandwidth = cfg->getRFBandwidth();
|
||||
m_config.m_afBandwidth = cfg->getAFBandwidth();
|
||||
m_config.m_volume = cfg->getVolume();
|
||||
m_config.m_squelch = cfg->getSquelch();
|
||||
}
|
||||
else if (MsgConfigureAMDemod::match(cmd))
|
||||
{
|
||||
MsgConfigureAMDemod& cfg = (MsgConfigureAMDemod&) cmd;
|
||||
|
||||
m_config.m_rfBandwidth = cfg.getRFBandwidth();
|
||||
m_config.m_afBandwidth = cfg.getAFBandwidth();
|
||||
m_config.m_volume = cfg.getVolume();
|
||||
m_config.m_squelch = cfg.getSquelch();
|
||||
|
||||
apply();
|
||||
|
||||
qDebug() << " - MsgConfigureAMDemod:"
|
||||
<< " m_rfBandwidth: " << m_config.m_rfBandwidth
|
||||
<< " m_afBandwidth: " << m_config.m_afBandwidth
|
||||
<< " m_volume: " << m_config.m_volume
|
||||
<< " m_squelch: " << m_config.m_squelch;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
if(m_sampleSink != NULL)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_sampleSink != 0)
|
||||
{
|
||||
return m_sampleSink->handleMessage(cmd);
|
||||
else return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,23 +227,27 @@ void AMDemod::apply()
|
|||
{
|
||||
|
||||
if((m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) ||
|
||||
(m_config.m_inputSampleRate != m_running.m_inputSampleRate)) {
|
||||
(m_config.m_inputSampleRate != m_running.m_inputSampleRate))
|
||||
{
|
||||
m_nco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_inputSampleRate);
|
||||
}
|
||||
|
||||
if((m_config.m_inputSampleRate != m_running.m_inputSampleRate) ||
|
||||
(m_config.m_rfBandwidth != m_running.m_rfBandwidth)) {
|
||||
(m_config.m_rfBandwidth != m_running.m_rfBandwidth))
|
||||
{
|
||||
m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_rfBandwidth / 2.2);
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
m_interpolatorDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_audioSampleRate;
|
||||
}
|
||||
|
||||
if((m_config.m_afBandwidth != m_running.m_afBandwidth) ||
|
||||
(m_config.m_audioSampleRate != m_running.m_audioSampleRate)) {
|
||||
(m_config.m_audioSampleRate != m_running.m_audioSampleRate))
|
||||
{
|
||||
m_lowpass.create(21, m_config.m_audioSampleRate, m_config.m_afBandwidth);
|
||||
}
|
||||
|
||||
if(m_config.m_squelch != m_running.m_squelch) {
|
||||
if(m_config.m_squelch != m_running.m_squelch)
|
||||
{
|
||||
m_squelchLevel = pow(10.0, m_config.m_squelch / 20.0);
|
||||
m_squelchLevel *= m_squelchLevel;
|
||||
}
|
||||
|
|
|
@ -36,10 +36,10 @@ public:
|
|||
|
||||
void configure(MessageQueue* messageQueue, Real rfBandwidth, Real afBandwidth, Real volume, Real squelch);
|
||||
|
||||
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool po);
|
||||
void start();
|
||||
void stop();
|
||||
bool handleMessage(Message* cmd);
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool po);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
|
||||
private:
|
||||
class MsgConfigureAMDemod : public Message {
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
#include "ui_amdemodgui.h"
|
||||
#include "dsp/threadedsamplesink.h"
|
||||
#include "dsp/channelizer.h"
|
||||
#include "dsp/nullsink.h"
|
||||
#include "gui/glspectrum.h"
|
||||
#include "plugin/pluginapi.h"
|
||||
#include "util/simpleserializer.h"
|
||||
#include "gui/basicchannelsettingswidget.h"
|
||||
#include "dsp/dspengine.h"
|
||||
|
||||
#include "amdemod.h"
|
||||
|
||||
|
@ -100,7 +100,7 @@ bool AMDemodGUI::deserialize(const QByteArray& data)
|
|||
}
|
||||
}
|
||||
|
||||
bool AMDemodGUI::handleMessage(Message* message)
|
||||
bool AMDemodGUI::handleMessage(const Message& message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -185,12 +185,10 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked()));
|
||||
|
||||
m_audioFifo = new AudioFifo(4, 48000);
|
||||
m_nullSink = new NullSink();
|
||||
m_amDemod = new AMDemod(m_audioFifo, m_nullSink);
|
||||
m_amDemod = new AMDemod(m_audioFifo, 0);
|
||||
m_channelizer = new Channelizer(m_amDemod);
|
||||
m_threadedSampleSink = new ThreadedSampleSink(m_channelizer);
|
||||
m_pluginAPI->addAudioSource(m_audioFifo);
|
||||
m_pluginAPI->addSampleSink(m_threadedSampleSink);
|
||||
DSPEngine::instance()->addAudioSink(m_audioFifo);
|
||||
DSPEngine::instance()->addThreadedSink(m_channelizer);
|
||||
|
||||
m_channelMarker = new ChannelMarker(this);
|
||||
m_channelMarker->setColor(Qt::yellow);
|
||||
|
@ -206,12 +204,10 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
AMDemodGUI::~AMDemodGUI()
|
||||
{
|
||||
m_pluginAPI->removeChannelInstance(this);
|
||||
m_pluginAPI->removeAudioSource(m_audioFifo);
|
||||
m_pluginAPI->removeSampleSink(m_threadedSampleSink);
|
||||
delete m_threadedSampleSink;
|
||||
DSPEngine::instance()->removeAudioSink(m_audioFifo);
|
||||
DSPEngine::instance()->removeThreadedSink(m_channelizer);
|
||||
delete m_channelizer;
|
||||
delete m_amDemod;
|
||||
delete m_nullSink;
|
||||
delete m_audioFifo;
|
||||
delete m_channelMarker;
|
||||
delete ui;
|
||||
|
@ -220,12 +216,15 @@ AMDemodGUI::~AMDemodGUI()
|
|||
void AMDemodGUI::applySettings()
|
||||
{
|
||||
setTitleColor(m_channelMarker->getColor());
|
||||
m_channelizer->configure(m_threadedSampleSink->getMessageQueue(),
|
||||
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
48000,
|
||||
m_channelMarker->getCenterFrequency());
|
||||
|
||||
ui->deltaFrequency->setValue(abs(m_channelMarker->getCenterFrequency()));
|
||||
ui->deltaMinus->setChecked(m_channelMarker->getCenterFrequency() < 0);
|
||||
m_amDemod->configure(m_threadedSampleSink->getMessageQueue(),
|
||||
|
||||
m_amDemod->configure(m_amDemod->getInputMessageQueue(),
|
||||
m_rfBW[ui->rfBW->value()],
|
||||
ui->afBW->value() * 1000.0,
|
||||
ui->volume->value() / 10.0,
|
||||
|
|
|
@ -8,10 +8,8 @@ class PluginAPI;
|
|||
class ChannelMarker;
|
||||
|
||||
class AudioFifo;
|
||||
class ThreadedSampleSink;
|
||||
class Channelizer;
|
||||
class AMDemod;
|
||||
class NullSink;
|
||||
|
||||
namespace Ui {
|
||||
class AMDemodGUI;
|
||||
|
@ -32,7 +30,7 @@ public:
|
|||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
|
||||
bool handleMessage(Message* message);
|
||||
virtual bool handleMessage(const Message& message);
|
||||
|
||||
private slots:
|
||||
void viewChanged();
|
||||
|
@ -52,10 +50,8 @@ private:
|
|||
bool m_basicSettingsShown;
|
||||
|
||||
AudioFifo* m_audioFifo;
|
||||
ThreadedSampleSink* m_threadedSampleSink;
|
||||
Channelizer* m_channelizer;
|
||||
AMDemod* m_amDemod;
|
||||
NullSink *m_nullSink;
|
||||
|
||||
static const int m_rfBW[];
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <stdio.h>
|
||||
#include "audio/audiooutput.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
|
@ -55,7 +56,7 @@ void ChannelAnalyzer::configure(MessageQueue* messageQueue,
|
|||
bool ssb)
|
||||
{
|
||||
Message* cmd = MsgConfigureChannelAnalyzer::create(Bandwidth, LowCutoff, spanLog2, ssb);
|
||||
cmd->submit(messageQueue, this);
|
||||
messageQueue->push(cmd);
|
||||
}
|
||||
|
||||
void ChannelAnalyzer::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
|
||||
|
@ -65,13 +66,17 @@ void ChannelAnalyzer::feed(SampleVector::const_iterator begin, SampleVector::con
|
|||
int decim = 1<<m_spanLog2;
|
||||
unsigned char decim_mask = decim - 1; // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1)
|
||||
|
||||
for(SampleVector::const_iterator it = begin; it < end; ++it) {
|
||||
for(SampleVector::const_iterator it = begin; it < end; ++it)
|
||||
{
|
||||
Complex c(it->real() / 32768.0, it->imag() / 32768.0);
|
||||
c *= m_nco.nextIQ();
|
||||
|
||||
if (m_ssb) {
|
||||
if (m_ssb)
|
||||
{
|
||||
n_out = SSBFilter->runSSB(c, &sideband, m_usb);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
n_out = DSBFilter->runDSB(c, &sideband);
|
||||
}
|
||||
|
||||
|
@ -116,29 +121,41 @@ void ChannelAnalyzer::stop()
|
|||
{
|
||||
}
|
||||
|
||||
bool ChannelAnalyzer::handleMessage(Message* cmd)
|
||||
bool ChannelAnalyzer::handleMessage(const Message& cmd)
|
||||
{
|
||||
float band, lowCutoff;
|
||||
|
||||
if(DSPSignalNotification::match(cmd)) {
|
||||
DSPSignalNotification* signal = (DSPSignalNotification*)cmd;
|
||||
fprintf(stderr, "ChannelAnalyzer::handleMessage: %d samples/sec, %lld Hz offset\n", signal->getSampleRate(), signal->getFrequencyOffset());
|
||||
m_sampleRate = signal->getSampleRate();
|
||||
m_nco.setFreq(-signal->getFrequencyOffset(), m_sampleRate);
|
||||
cmd->completed();
|
||||
qDebug() << "ChannelAnalyzer::handleMessage";
|
||||
|
||||
if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
|
||||
m_sampleRate = notif.getSampleRate();
|
||||
m_nco.setFreq(-notif.getFrequencyOffset(), m_sampleRate);
|
||||
|
||||
qDebug() << " - DSPSignalNotification: m_sampleRate: " << m_sampleRate
|
||||
<< " frequencyOffset: " << notif.getFrequencyOffset();
|
||||
|
||||
return true;
|
||||
} else if(MsgConfigureChannelAnalyzer::match(cmd)) {
|
||||
MsgConfigureChannelAnalyzer* cfg = (MsgConfigureChannelAnalyzer*)cmd;
|
||||
}
|
||||
else if (MsgConfigureChannelAnalyzer::match(cmd))
|
||||
{
|
||||
MsgConfigureChannelAnalyzer& cfg = (MsgConfigureChannelAnalyzer&) cmd;
|
||||
|
||||
band = cfg->getBandwidth();
|
||||
lowCutoff = cfg->getLoCutoff();
|
||||
band = cfg.getBandwidth();
|
||||
lowCutoff = cfg.getLoCutoff();
|
||||
|
||||
if (band < 0) {
|
||||
if (band < 0)
|
||||
{
|
||||
band = -band;
|
||||
lowCutoff = -lowCutoff;
|
||||
m_usb = false;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
m_usb = true;
|
||||
}
|
||||
|
||||
if (band < 100.0f)
|
||||
{
|
||||
|
@ -153,14 +170,25 @@ bool ChannelAnalyzer::handleMessage(Message* cmd)
|
|||
SSBFilter->create_filter(m_LowCutoff / m_sampleRate, m_Bandwidth / m_sampleRate);
|
||||
DSBFilter->create_dsb_filter(m_Bandwidth / m_sampleRate);
|
||||
|
||||
m_spanLog2 = cfg->getSpanLog2();
|
||||
m_ssb = cfg->getSSB();
|
||||
m_spanLog2 = cfg.getSpanLog2();
|
||||
m_ssb = cfg.getSSB();
|
||||
|
||||
qDebug() << " - MsgConfigureChannelAnalyzer: m_Bandwidth: " << m_Bandwidth
|
||||
<< " m_LowCutoff: " << m_LowCutoff
|
||||
<< " m_spanLog2: " << m_spanLog2
|
||||
<< " m_ssb: " << m_ssb;
|
||||
|
||||
cmd->completed();
|
||||
return true;
|
||||
} else {
|
||||
if(m_sampleSink != NULL)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_sampleSink != 0)
|
||||
{
|
||||
return m_sampleSink->handleMessage(cmd);
|
||||
else return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
class ChannelAnalyzer : public SampleSink {
|
||||
public:
|
||||
ChannelAnalyzer(SampleSink* m_sampleSink);
|
||||
~ChannelAnalyzer();
|
||||
virtual ~ChannelAnalyzer();
|
||||
|
||||
void configure(MessageQueue* messageQueue,
|
||||
Real Bandwidth,
|
||||
|
@ -45,10 +45,10 @@ public:
|
|||
return m_sampleRate;
|
||||
}
|
||||
|
||||
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||
void start();
|
||||
void stop();
|
||||
bool handleMessage(Message* cmd);
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
|
||||
private:
|
||||
class MsgConfigureChannelAnalyzer : public Message {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include <QDockWidget>
|
||||
#include <QMainWindow>
|
||||
#include "ui_chanalyzergui.h"
|
||||
#include "dsp/threadedsamplesink.h"
|
||||
#include "dsp/channelizer.h"
|
||||
#include "dsp/spectrumscopecombovis.h"
|
||||
#include "dsp/spectrumvis.h"
|
||||
|
@ -11,6 +10,7 @@
|
|||
#include "plugin/pluginapi.h"
|
||||
#include "util/simpleserializer.h"
|
||||
#include "gui/basicchannelsettingswidget.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "chanalyzer.h"
|
||||
|
@ -103,7 +103,7 @@ bool ChannelAnalyzerGUI::deserialize(const QByteArray& data)
|
|||
}
|
||||
}
|
||||
|
||||
bool ChannelAnalyzerGUI::handleMessage(Message* message)
|
||||
bool ChannelAnalyzerGUI::handleMessage(const Message& message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -267,8 +267,7 @@ ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
m_channelAnalyzer = new ChannelAnalyzer(m_spectrumScopeComboVis);
|
||||
m_channelizer = new Channelizer(m_channelAnalyzer);
|
||||
connect(m_channelizer, SIGNAL(inputSampleRateChanged()), this, SLOT(channelSampleRateChanged()));
|
||||
m_threadedSampleSink = new ThreadedSampleSink(m_channelizer);
|
||||
m_pluginAPI->addSampleSink(m_threadedSampleSink);
|
||||
DSPEngine::instance()->addThreadedSink(m_channelizer);
|
||||
|
||||
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold));
|
||||
|
||||
|
@ -290,8 +289,8 @@ ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
connect(m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged()));
|
||||
m_pluginAPI->addChannelMarker(m_channelMarker);
|
||||
|
||||
ui->spectrumGUI->setBuddies(m_threadedSampleSink->getMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||
ui->scopeGUI->setBuddies(m_threadedSampleSink->getMessageQueue(), m_scopeVis, ui->glScope);
|
||||
ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||
ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope);
|
||||
|
||||
applySettings();
|
||||
}
|
||||
|
@ -299,8 +298,7 @@ ChannelAnalyzerGUI::ChannelAnalyzerGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
ChannelAnalyzerGUI::~ChannelAnalyzerGUI()
|
||||
{
|
||||
m_pluginAPI->removeChannelInstance(this);
|
||||
m_pluginAPI->removeSampleSink(m_threadedSampleSink);
|
||||
delete m_threadedSampleSink;
|
||||
DSPEngine::instance()->removeThreadedSink(m_channelizer);
|
||||
delete m_channelizer;
|
||||
delete m_channelAnalyzer;
|
||||
delete m_spectrumVis;
|
||||
|
@ -376,10 +374,12 @@ void ChannelAnalyzerGUI::applySettings()
|
|||
setTitleColor(m_channelMarker->getColor());
|
||||
ui->deltaFrequency->setValue(abs(m_channelMarker->getCenterFrequency()));
|
||||
ui->deltaMinus->setChecked(m_channelMarker->getCenterFrequency() < 0);
|
||||
m_channelizer->configure(m_threadedSampleSink->getMessageQueue(),
|
||||
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
m_channelizer->getInputSampleRate(),
|
||||
m_channelMarker->getCenterFrequency());
|
||||
m_channelAnalyzer->configure(m_threadedSampleSink->getMessageQueue(),
|
||||
|
||||
m_channelAnalyzer->configure(m_channelAnalyzer->getInputMessageQueue(),
|
||||
ui->BW->value() * 100.0,
|
||||
ui->lowCut->value() * 100.0,
|
||||
m_spanLog2,
|
||||
|
|
|
@ -8,7 +8,6 @@ class PluginAPI;
|
|||
class ChannelMarker;
|
||||
|
||||
//class AudioFifo;
|
||||
class ThreadedSampleSink;
|
||||
class Channelizer;
|
||||
class ChannelAnalyzer;
|
||||
class SpectrumScopeComboVis;
|
||||
|
@ -34,7 +33,7 @@ public:
|
|||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
|
||||
bool handleMessage(Message* message);
|
||||
virtual bool handleMessage(const Message& message);
|
||||
|
||||
private slots:
|
||||
void viewChanged();
|
||||
|
@ -56,7 +55,6 @@ private:
|
|||
int m_rate;
|
||||
int m_spanLog2;
|
||||
|
||||
ThreadedSampleSink* m_threadedSampleSink;
|
||||
Channelizer* m_channelizer;
|
||||
ChannelAnalyzer* m_channelAnalyzer;
|
||||
SpectrumScopeComboVis* m_spectrumScopeComboVis;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <stdio.h>
|
||||
#include "lorademod.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
|
@ -44,6 +45,7 @@ LoRaDemod::LoRaDemod(SampleSink* sampleSink) :
|
|||
m_count = 0;
|
||||
m_header = 0;
|
||||
m_time = 0;
|
||||
m_tune = 0;
|
||||
|
||||
loraFilter = new sfft(LORA_SFFT_LEN);
|
||||
negaFilter = new sfft(LORA_SFFT_LEN);
|
||||
|
@ -70,7 +72,7 @@ LoRaDemod::~LoRaDemod()
|
|||
void LoRaDemod::configure(MessageQueue* messageQueue, Real Bandwidth)
|
||||
{
|
||||
Message* cmd = MsgConfigureLoRaDemod::create(Bandwidth);
|
||||
cmd->submit(messageQueue, this);
|
||||
messageQueue->push(cmd);
|
||||
}
|
||||
|
||||
void LoRaDemod::dumpRaw()
|
||||
|
@ -79,13 +81,18 @@ void LoRaDemod::dumpRaw()
|
|||
char text[256];
|
||||
|
||||
max = m_time / 4 - 3;
|
||||
if (max > 140)
|
||||
max = 140; // about 2 symbols to each char
|
||||
|
||||
for ( j=0; j < max; j++) {
|
||||
if (max > 140)
|
||||
{
|
||||
max = 140; // about 2 symbols to each char
|
||||
}
|
||||
|
||||
for ( j=0; j < max; j++)
|
||||
{
|
||||
bin = (history[(j + 1) * 4] + m_tune ) & (LORA_SFFT_LEN - 1);
|
||||
text[j] = toGray(bin >> 1);
|
||||
}
|
||||
|
||||
prng6(text, max);
|
||||
// First block is always 8 symbols
|
||||
interleave6(text, 6);
|
||||
|
@ -93,46 +100,75 @@ void LoRaDemod::dumpRaw()
|
|||
hamming6(text, 6);
|
||||
hamming6(&text[8], max);
|
||||
|
||||
for ( j=0; j < max / 2; j++) {
|
||||
for ( j=0; j < max / 2; j++)
|
||||
{
|
||||
text[j] = (text[j * 2 + 1] << 4) | (0xf & text[j * 2 + 0]);
|
||||
|
||||
if ((text[j] < 32 )||( text[j] > 126))
|
||||
{
|
||||
text[j] = 0x5f;
|
||||
}
|
||||
}
|
||||
|
||||
text[3] = text[2];
|
||||
text[2] = text[1];
|
||||
text[1] = text[0];
|
||||
text[j] = 0;
|
||||
|
||||
printf("%s\n", &text[1]);
|
||||
}
|
||||
|
||||
short LoRaDemod::synch(short bin)
|
||||
{
|
||||
short i, j;
|
||||
if (bin < 0) {
|
||||
|
||||
if (bin < 0)
|
||||
{
|
||||
if (m_time > 70)
|
||||
{
|
||||
dumpRaw();
|
||||
}
|
||||
|
||||
m_time = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
history[m_time] = bin;
|
||||
|
||||
if (m_time > 12)
|
||||
{
|
||||
if (bin == history[m_time - 6])
|
||||
if (bin == history[m_time - 12]) {
|
||||
{
|
||||
if (bin == history[m_time - 12])
|
||||
{
|
||||
m_tune = LORA_SFFT_LEN - bin;
|
||||
j = 0;
|
||||
|
||||
for (i=0; i<12; i++)
|
||||
{
|
||||
j += finetune[15 & (m_time - i)];
|
||||
}
|
||||
|
||||
if (j < 0)
|
||||
{
|
||||
m_tune += 1;
|
||||
}
|
||||
|
||||
m_tune &= (LORA_SFFT_LEN - 1);
|
||||
m_time = 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_time++;
|
||||
m_time &= 1023;
|
||||
|
||||
if (m_time & 3)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return (bin + m_tune) & (LORA_SFFT_LEN - 1);
|
||||
}
|
||||
|
||||
|
@ -149,24 +185,34 @@ int LoRaDemod::detect(Complex c, Complex a)
|
|||
|
||||
// process spectrum twice in FFTLEN
|
||||
if (++m_count & ((1 << DATA_BITS) - 1))
|
||||
{
|
||||
return m_result;
|
||||
}
|
||||
|
||||
movpoint = 3 & (m_count >> DATA_BITS);
|
||||
|
||||
loraFilter->fetch(mag);
|
||||
negaFilter->fetch(rev);
|
||||
peak = negpeak = 0.0f;
|
||||
result = negresult = 0;
|
||||
for (i = 0; i < LORA_SFFT_LEN; i++) {
|
||||
if (rev[i] > negpeak) {
|
||||
|
||||
for (i = 0; i < LORA_SFFT_LEN; i++)
|
||||
{
|
||||
if (rev[i] > negpeak)
|
||||
{
|
||||
negpeak = rev[i];
|
||||
negresult = i;
|
||||
}
|
||||
|
||||
tfloat = mov[i] + mov[LORA_SFFT_LEN + i] +mov[2 * LORA_SFFT_LEN + i]
|
||||
+ mov[3 * LORA_SFFT_LEN + i] + mag[i];
|
||||
if (tfloat > peak) {
|
||||
|
||||
if (tfloat > peak)
|
||||
{
|
||||
peak = tfloat;
|
||||
result = i;
|
||||
}
|
||||
|
||||
mov[movpoint * LORA_SFFT_LEN + i] = mag[i];
|
||||
}
|
||||
|
||||
|
@ -175,10 +221,17 @@ int LoRaDemod::detect(Complex c, Complex a)
|
|||
finetune[15 & m_time] = (mag[p] > mag[q]) ? -1 : 1;
|
||||
|
||||
if (peak < negpeak * LORA_SQUELCH)
|
||||
{
|
||||
result = -1;
|
||||
}
|
||||
|
||||
result = synch(result);
|
||||
|
||||
if (result >= 0)
|
||||
{
|
||||
m_result = result;
|
||||
}
|
||||
|
||||
return m_result;
|
||||
}
|
||||
|
||||
|
@ -188,11 +241,14 @@ void LoRaDemod::feed(SampleVector::const_iterator begin, SampleVector::const_ite
|
|||
Complex ci;
|
||||
|
||||
m_sampleBuffer.clear();
|
||||
for(SampleVector::const_iterator it = begin; it < end; ++it) {
|
||||
|
||||
for(SampleVector::const_iterator it = begin; it < end; ++it)
|
||||
{
|
||||
Complex c(it->real() / 32768.0, it->imag() / 32768.0);
|
||||
c *= m_nco.nextIQ();
|
||||
|
||||
if(m_interpolator.interpolate(&m_sampleDistanceRemain, c, &ci)) {
|
||||
if(m_interpolator.interpolate(&m_sampleDistanceRemain, c, &ci))
|
||||
{
|
||||
m_chirp = (m_chirp + 1) & (SPREADFACTOR - 1);
|
||||
m_angle = (m_angle + m_chirp) & (SPREADFACTOR - 1);
|
||||
Complex cangle(cos(M_PI*2*m_angle/SPREADFACTOR),-sin(M_PI*2*m_angle/SPREADFACTOR));
|
||||
|
@ -204,8 +260,11 @@ void LoRaDemod::feed(SampleVector::const_iterator begin, SampleVector::const_ite
|
|||
m_sampleDistanceRemain += (Real)m_sampleRate / m_Bandwidth;
|
||||
}
|
||||
}
|
||||
if(m_sampleSink != NULL)
|
||||
|
||||
if(m_sampleSink != 0)
|
||||
{
|
||||
m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), false);
|
||||
}
|
||||
}
|
||||
|
||||
void LoRaDemod::start()
|
||||
|
@ -216,26 +275,43 @@ void LoRaDemod::stop()
|
|||
{
|
||||
}
|
||||
|
||||
bool LoRaDemod::handleMessage(Message* cmd)
|
||||
bool LoRaDemod::handleMessage(const Message& cmd)
|
||||
{
|
||||
if(DSPSignalNotification::match(cmd)) {
|
||||
DSPSignalNotification* signal = (DSPSignalNotification*)cmd;
|
||||
m_sampleRate = signal->getSampleRate();
|
||||
m_nco.setFreq(-signal->getFrequencyOffset(), m_sampleRate);
|
||||
qDebug() << "LoRaDemod::handleMessage";
|
||||
|
||||
if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
|
||||
m_sampleRate = notif.getSampleRate();
|
||||
m_nco.setFreq(-notif.getFrequencyOffset(), m_sampleRate);
|
||||
m_interpolator.create(16, m_sampleRate, m_Bandwidth/1.9);
|
||||
m_sampleDistanceRemain = m_sampleRate / m_Bandwidth;
|
||||
cmd->completed();
|
||||
|
||||
qDebug() << " DSPSignalNotification: m_sampleRate: " << m_sampleRate;
|
||||
|
||||
return true;
|
||||
} else if(MsgConfigureLoRaDemod::match(cmd)) {
|
||||
MsgConfigureLoRaDemod* cfg = (MsgConfigureLoRaDemod*)cmd;
|
||||
m_Bandwidth = cfg->getBandwidth();
|
||||
}
|
||||
else if (MsgConfigureLoRaDemod::match(cmd))
|
||||
{
|
||||
MsgConfigureLoRaDemod& cfg = (MsgConfigureLoRaDemod&) cmd;
|
||||
|
||||
m_Bandwidth = cfg.getBandwidth();
|
||||
m_interpolator.create(16, m_sampleRate, m_Bandwidth/1.9);
|
||||
cmd->completed();
|
||||
|
||||
qDebug() << " MsgConfigureLoRaDemod: m_Bandwidth: " << m_Bandwidth;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
if(m_sampleSink != NULL)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_sampleSink != 0)
|
||||
{
|
||||
return m_sampleSink->handleMessage(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,14 +34,14 @@
|
|||
class LoRaDemod : public SampleSink {
|
||||
public:
|
||||
LoRaDemod(SampleSink* sampleSink);
|
||||
~LoRaDemod();
|
||||
virtual ~LoRaDemod();
|
||||
|
||||
void configure(MessageQueue* messageQueue, Real Bandwidth);
|
||||
|
||||
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool pO);
|
||||
void start();
|
||||
void stop();
|
||||
bool handleMessage(Message* cmd);
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool pO);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
|
||||
private:
|
||||
int detect(Complex sample, Complex angle);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "plugin/pluginapi.h"
|
||||
#include "util/simpleserializer.h"
|
||||
#include "gui/basicchannelsettingswidget.h"
|
||||
#include "dsp/dspengine.h"
|
||||
|
||||
LoRaDemodGUI* LoRaDemodGUI::create(PluginAPI* pluginAPI)
|
||||
{
|
||||
|
@ -83,7 +84,7 @@ bool LoRaDemodGUI::deserialize(const QByteArray& data)
|
|||
}
|
||||
}
|
||||
|
||||
bool LoRaDemodGUI::handleMessage(Message* message)
|
||||
bool LoRaDemodGUI::handleMessage(const Message& message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -137,8 +138,7 @@ LoRaDemodGUI::LoRaDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
m_spectrumVis = new SpectrumVis(ui->glSpectrum);
|
||||
m_LoRaDemod = new LoRaDemod(m_spectrumVis);
|
||||
m_channelizer = new Channelizer(m_LoRaDemod);
|
||||
m_threadedSampleSink = new ThreadedSampleSink(m_channelizer);
|
||||
m_pluginAPI->addSampleSink(m_threadedSampleSink);
|
||||
DSPEngine::instance()->addThreadedSink(m_channelizer);
|
||||
|
||||
ui->glSpectrum->setCenterFrequency(16000);
|
||||
ui->glSpectrum->setSampleRate(32000);
|
||||
|
@ -155,7 +155,7 @@ LoRaDemodGUI::LoRaDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
connect(m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged()));
|
||||
m_pluginAPI->addChannelMarker(m_channelMarker);
|
||||
|
||||
ui->spectrumGUI->setBuddies(m_threadedSampleSink->getMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||
ui->spectrumGUI->setBuddies(m_channelizer->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||
|
||||
applySettings();
|
||||
}
|
||||
|
@ -163,8 +163,7 @@ LoRaDemodGUI::LoRaDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
LoRaDemodGUI::~LoRaDemodGUI()
|
||||
{
|
||||
m_pluginAPI->removeChannelInstance(this);
|
||||
m_pluginAPI->removeSampleSink(m_threadedSampleSink);
|
||||
delete m_threadedSampleSink;
|
||||
DSPEngine::instance()->removeThreadedSink(m_channelizer);
|
||||
delete m_channelizer;
|
||||
delete m_LoRaDemod;
|
||||
delete m_spectrumVis;
|
||||
|
@ -176,8 +175,10 @@ void LoRaDemodGUI::applySettings()
|
|||
{
|
||||
const int loraBW[] = BANDWIDTHSTRING;
|
||||
int thisBW = loraBW[ui->BW->value()];
|
||||
m_channelizer->configure(m_threadedSampleSink->getMessageQueue(),
|
||||
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
thisBW,
|
||||
m_channelMarker->getCenterFrequency());
|
||||
m_LoRaDemod->configure(m_threadedSampleSink->getMessageQueue(), thisBW);
|
||||
|
||||
m_LoRaDemod->configure(m_LoRaDemod->getInputMessageQueue(), thisBW);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
class PluginAPI;
|
||||
class ChannelMarker;
|
||||
class ThreadedSampleSink;
|
||||
class Channelizer;
|
||||
class LoRaDemod;
|
||||
class SpectrumVis;
|
||||
|
@ -32,7 +31,7 @@ public:
|
|||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
|
||||
bool handleMessage(Message* message);
|
||||
virtual bool handleMessage(const Message& message);
|
||||
|
||||
private slots:
|
||||
void viewChanged();
|
||||
|
@ -47,7 +46,6 @@ private:
|
|||
ChannelMarker* m_channelMarker;
|
||||
bool m_basicSettingsShown;
|
||||
|
||||
ThreadedSampleSink* m_threadedSampleSink;
|
||||
Channelizer* m_channelizer;
|
||||
LoRaDemod* m_LoRaDemod;
|
||||
SpectrumVis* m_spectrumVis;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <stdio.h>
|
||||
#include <complex.h>
|
||||
#include "nfmdemod.h"
|
||||
|
@ -23,6 +24,7 @@
|
|||
#include "audio/audiooutput.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
#include "dsp/pidcontroller.h"
|
||||
#include "dsp/dspengine.h"
|
||||
|
||||
static const Real afSqTones[2] = {1200.0, 8000.0};
|
||||
|
||||
|
@ -68,7 +70,7 @@ NFMDemod::~NFMDemod()
|
|||
void NFMDemod::configure(MessageQueue* messageQueue, Real rfBandwidth, Real afBandwidth, Real volume, Real squelch)
|
||||
{
|
||||
Message* cmd = MsgConfigureNFMDemod::create(rfBandwidth, afBandwidth, volume, squelch);
|
||||
cmd->submit(messageQueue, this);
|
||||
messageQueue->push(cmd);
|
||||
}
|
||||
|
||||
float arctan2(Real y, Real x)
|
||||
|
@ -250,52 +252,80 @@ void NFMDemod::stop()
|
|||
{
|
||||
}
|
||||
|
||||
bool NFMDemod::handleMessage(Message* cmd)
|
||||
bool NFMDemod::handleMessage(const Message& cmd)
|
||||
{
|
||||
if(DSPSignalNotification::match(cmd)) {
|
||||
DSPSignalNotification* signal = (DSPSignalNotification*)cmd;
|
||||
qDebug() << "NFMDemod::handleMessage";
|
||||
|
||||
if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
|
||||
m_config.m_inputSampleRate = notif.getSampleRate();
|
||||
m_config.m_inputFrequencyOffset = notif.getFrequencyOffset();
|
||||
|
||||
m_config.m_inputSampleRate = signal->getSampleRate();
|
||||
m_config.m_inputFrequencyOffset = signal->getFrequencyOffset();
|
||||
apply();
|
||||
cmd->completed();
|
||||
|
||||
qDebug() << " - DSPSignalNotification: m_inputSampleRate: " << m_config.m_inputSampleRate
|
||||
<< " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset;
|
||||
|
||||
return true;
|
||||
} else if(MsgConfigureNFMDemod::match(cmd)) {
|
||||
MsgConfigureNFMDemod* cfg = (MsgConfigureNFMDemod*)cmd;
|
||||
m_config.m_rfBandwidth = cfg->getRFBandwidth();
|
||||
m_config.m_afBandwidth = cfg->getAFBandwidth();
|
||||
m_config.m_volume = cfg->getVolume();
|
||||
m_config.m_squelch = cfg->getSquelch();
|
||||
}
|
||||
else if (MsgConfigureNFMDemod::match(cmd))
|
||||
{
|
||||
MsgConfigureNFMDemod& cfg = (MsgConfigureNFMDemod&) cmd;
|
||||
|
||||
m_config.m_rfBandwidth = cfg.getRFBandwidth();
|
||||
m_config.m_afBandwidth = cfg.getAFBandwidth();
|
||||
m_config.m_volume = cfg.getVolume();
|
||||
m_config.m_squelch = cfg.getSquelch();
|
||||
|
||||
apply();
|
||||
|
||||
qDebug() << " - MsgConfigureNFMDemod: m_rfBandwidth: " << m_config.m_rfBandwidth
|
||||
<< " m_afBandwidth: " << m_config.m_afBandwidth
|
||||
<< " m_volume: " << m_config.m_volume
|
||||
<< " m_squelch: " << m_config.m_squelch;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
if(m_sampleSink != NULL)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_sampleSink != 0)
|
||||
{
|
||||
return m_sampleSink->handleMessage(cmd);
|
||||
else return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NFMDemod::apply()
|
||||
{
|
||||
if((m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) ||
|
||||
(m_config.m_inputSampleRate != m_running.m_inputSampleRate)) {
|
||||
(m_config.m_inputSampleRate != m_running.m_inputSampleRate))
|
||||
{
|
||||
m_nco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_inputSampleRate);
|
||||
}
|
||||
|
||||
if((m_config.m_inputSampleRate != m_running.m_inputSampleRate) ||
|
||||
(m_config.m_rfBandwidth != m_running.m_rfBandwidth)) {
|
||||
(m_config.m_rfBandwidth != m_running.m_rfBandwidth))
|
||||
{
|
||||
m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_rfBandwidth / 2.2);
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
m_interpolatorDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_audioSampleRate;
|
||||
}
|
||||
|
||||
if((m_config.m_afBandwidth != m_running.m_afBandwidth) ||
|
||||
(m_config.m_audioSampleRate != m_running.m_audioSampleRate)) {
|
||||
(m_config.m_audioSampleRate != m_running.m_audioSampleRate))
|
||||
{
|
||||
m_lowpass.create(301, m_config.m_audioSampleRate, 250.0);
|
||||
m_bandpass.create(301, m_config.m_audioSampleRate, 300.0, m_config.m_afBandwidth);
|
||||
}
|
||||
|
||||
if(m_config.m_squelch != m_running.m_squelch) {
|
||||
if(m_config.m_squelch != m_running.m_squelch)
|
||||
{
|
||||
m_squelchLevel = pow(10.0, m_config.m_squelch / 10.0);
|
||||
m_squelchLevel *= m_squelchLevel;
|
||||
m_afSquelch.setThreshold(m_squelchLevel);
|
||||
|
|
|
@ -41,10 +41,10 @@ public:
|
|||
|
||||
void configure(MessageQueue* messageQueue, Real rfBandwidth, Real afBandwidth, Real volume, Real squelch);
|
||||
|
||||
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool po);
|
||||
void start();
|
||||
void stop();
|
||||
bool handleMessage(Message* cmd);
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool po);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
|
||||
void registerGUI(NFMDemodGUI *nfmDemodGUI) {
|
||||
m_nfmDemodGUI = nfmDemodGUI;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include "plugin/pluginapi.h"
|
||||
#include "util/simpleserializer.h"
|
||||
#include "gui/basicchannelsettingswidget.h"
|
||||
#include "dsp/dspengine.h"
|
||||
|
||||
const int NFMDemodGUI::m_rfBW[] = {
|
||||
5000, 6250, 8330, 10000, 12500, 15000, 20000, 25000, 40000
|
||||
|
@ -69,12 +70,14 @@ bool NFMDemodGUI::deserialize(const QByteArray& data)
|
|||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if(!d.isValid()) {
|
||||
if (!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.getVersion() == 1) {
|
||||
if (d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
quint32 u32tmp;
|
||||
qint32 tmp;
|
||||
|
@ -96,13 +99,15 @@ bool NFMDemodGUI::deserialize(const QByteArray& data)
|
|||
ui->ctcss->setCurrentIndex(tmp);
|
||||
applySettings();
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool NFMDemodGUI::handleMessage(Message* message)
|
||||
bool NFMDemodGUI::handleMessage(const Message& message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -125,9 +130,12 @@ void NFMDemodGUI::on_deltaMinus_clicked(bool minus)
|
|||
|
||||
void NFMDemodGUI::on_deltaFrequency_changed(quint64 value)
|
||||
{
|
||||
if (ui->deltaMinus->isChecked()) {
|
||||
if (ui->deltaMinus->isChecked())
|
||||
{
|
||||
m_channelMarker->setCenterFrequency(-value);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_channelMarker->setCenterFrequency(value);
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +167,8 @@ void NFMDemodGUI::on_squelch_valueChanged(int value)
|
|||
|
||||
void NFMDemodGUI::on_ctcss_currentIndexChanged(int index)
|
||||
{
|
||||
if (m_nfmDemod != NULL) {
|
||||
if (m_nfmDemod != 0)
|
||||
{
|
||||
m_nfmDemod->setSelectedCtcssIndex(index);
|
||||
}
|
||||
}
|
||||
|
@ -174,7 +183,8 @@ void NFMDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
|||
|
||||
void NFMDemodGUI::onMenuDoubleClicked()
|
||||
{
|
||||
if(!m_basicSettingsShown) {
|
||||
if (!m_basicSettingsShown)
|
||||
{
|
||||
m_basicSettingsShown = true;
|
||||
BasicChannelSettingsWidget* bcsw = new BasicChannelSettingsWidget(m_channelMarker, this);
|
||||
bcsw->show();
|
||||
|
@ -193,9 +203,8 @@ NFMDemodGUI::NFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked()));
|
||||
|
||||
m_audioFifo = new AudioFifo(4, 48000);
|
||||
m_nullSink = new NullSink();
|
||||
|
||||
m_nfmDemod = new NFMDemod(m_audioFifo, m_nullSink);
|
||||
m_nfmDemod = new NFMDemod(m_audioFifo, 0);
|
||||
m_nfmDemod->registerGUI(this);
|
||||
|
||||
int ctcss_nbTones;
|
||||
|
@ -203,7 +212,8 @@ NFMDemodGUI::NFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
|
||||
ui->ctcss->addItem("--");
|
||||
|
||||
for (int i=0; i<ctcss_nbTones; i++) {
|
||||
for (int i=0; i<ctcss_nbTones; i++)
|
||||
{
|
||||
ui->ctcss->addItem(QString("%1").arg(ctcss_tones[i]));
|
||||
}
|
||||
|
||||
|
@ -211,9 +221,8 @@ NFMDemodGUI::NFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
//ui->deltaFrequency->setBold(true);
|
||||
|
||||
m_channelizer = new Channelizer(m_nfmDemod);
|
||||
m_threadedSampleSink = new ThreadedSampleSink(m_channelizer);
|
||||
m_pluginAPI->addAudioSource(m_audioFifo);
|
||||
m_pluginAPI->addSampleSink(m_threadedSampleSink);
|
||||
DSPEngine::instance()->addAudioSink(m_audioFifo);
|
||||
DSPEngine::instance()->addThreadedSink(m_channelizer);
|
||||
|
||||
m_channelMarker = new ChannelMarker(this);
|
||||
m_channelMarker->setColor(Qt::red);
|
||||
|
@ -229,12 +238,10 @@ NFMDemodGUI::NFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
NFMDemodGUI::~NFMDemodGUI()
|
||||
{
|
||||
m_pluginAPI->removeChannelInstance(this);
|
||||
m_pluginAPI->removeAudioSource(m_audioFifo);
|
||||
m_pluginAPI->removeSampleSink(m_threadedSampleSink);
|
||||
delete m_threadedSampleSink;
|
||||
DSPEngine::instance()->removeAudioSink(m_audioFifo);
|
||||
DSPEngine::instance()->removeThreadedSink(m_channelizer);
|
||||
delete m_channelizer;
|
||||
delete m_nfmDemod;
|
||||
delete m_nullSink;
|
||||
delete m_audioFifo;
|
||||
delete m_channelMarker;
|
||||
delete ui;
|
||||
|
@ -243,12 +250,15 @@ NFMDemodGUI::~NFMDemodGUI()
|
|||
void NFMDemodGUI::applySettings()
|
||||
{
|
||||
setTitleColor(m_channelMarker->getColor());
|
||||
m_channelizer->configure(m_threadedSampleSink->getMessageQueue(),
|
||||
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
48000,
|
||||
m_channelMarker->getCenterFrequency());
|
||||
|
||||
ui->deltaFrequency->setValue(abs(m_channelMarker->getCenterFrequency()));
|
||||
ui->deltaMinus->setChecked(m_channelMarker->getCenterFrequency() < 0);
|
||||
m_nfmDemod->configure(m_threadedSampleSink->getMessageQueue(),
|
||||
|
||||
m_nfmDemod->configure(m_nfmDemod->getInputMessageQueue(),
|
||||
m_rfBW[ui->rfBW->value()],
|
||||
ui->afBW->value() * 1000.0,
|
||||
ui->volume->value() / 10.0,
|
||||
|
|
|
@ -9,10 +9,8 @@ class PluginAPI;
|
|||
class ChannelMarker;
|
||||
|
||||
class AudioFifo;
|
||||
class ThreadedSampleSink;
|
||||
class Channelizer;
|
||||
class NFMDemod;
|
||||
class NullSink;
|
||||
|
||||
namespace Ui {
|
||||
class NFMDemodGUI;
|
||||
|
@ -33,7 +31,7 @@ public:
|
|||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
|
||||
bool handleMessage(Message* message);
|
||||
virtual bool handleMessage(const Message& message);
|
||||
void setCtcssFreq(Real ctcssFreq);
|
||||
|
||||
private slots:
|
||||
|
@ -55,10 +53,8 @@ private:
|
|||
bool m_basicSettingsShown;
|
||||
|
||||
AudioFifo* m_audioFifo;
|
||||
ThreadedSampleSink* m_threadedSampleSink;
|
||||
Channelizer* m_channelizer;
|
||||
NFMDemod* m_nfmDemod;
|
||||
NullSink *m_nullSink;
|
||||
|
||||
static const int m_rfBW[];
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <stdio.h>
|
||||
#include "ssbdemod.h"
|
||||
#include "audio/audiooutput.h"
|
||||
|
@ -57,7 +58,7 @@ SSBDemod::~SSBDemod()
|
|||
void SSBDemod::configure(MessageQueue* messageQueue, Real Bandwidth, Real LowCutoff, Real volume, int spanLog2)
|
||||
{
|
||||
Message* cmd = MsgConfigureSSBDemod::create(Bandwidth, LowCutoff, volume, spanLog2);
|
||||
cmd->submit(messageQueue, this);
|
||||
messageQueue->push(cmd);
|
||||
}
|
||||
|
||||
void SSBDemod::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
|
||||
|
@ -69,17 +70,23 @@ void SSBDemod::feed(SampleVector::const_iterator begin, SampleVector::const_iter
|
|||
int decim = 1<<(m_spanLog2 - 1);
|
||||
unsigned char decim_mask = decim - 1; // counter LSB bit mask for decimation by 2^(m_scaleLog2 - 1)
|
||||
|
||||
for(SampleVector::const_iterator it = begin; it < end; ++it) {
|
||||
for(SampleVector::const_iterator it = begin; it < end; ++it)
|
||||
{
|
||||
Complex c(it->real() / 32768.0, it->imag() / 32768.0);
|
||||
c *= m_nco.nextIQ();
|
||||
|
||||
if(m_interpolator.interpolate(&m_sampleDistanceRemain, c, &ci)) {
|
||||
if(m_interpolator.interpolate(&m_sampleDistanceRemain, c, &ci))
|
||||
{
|
||||
n_out = SSBFilter->runSSB(ci, &sideband, m_usb);
|
||||
m_sampleDistanceRemain += (Real)m_sampleRate / 48000.0;
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
n_out = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < n_out; i++) {
|
||||
for (int i = 0; i < n_out; i++)
|
||||
{
|
||||
Real demod = (sideband[i].real() + sideband[i].imag()) * 0.7 * 32768.0;
|
||||
|
||||
// Downsample by 2^(m_scaleLog2 - 1) for SSB band spectrum display
|
||||
|
@ -87,7 +94,8 @@ void SSBDemod::feed(SampleVector::const_iterator begin, SampleVector::const_iter
|
|||
|
||||
sum += sideband[i];
|
||||
|
||||
if (!(m_undersampleCount++ & decim_mask)) {
|
||||
if (!(m_undersampleCount++ & decim_mask))
|
||||
{
|
||||
avg = (sum.real() + sum.imag()) * 0.7 * 32768.0 / decim;
|
||||
m_sampleBuffer.push_back(Sample(avg, 0.0));
|
||||
sum.real() = 0.0;
|
||||
|
@ -98,20 +106,32 @@ void SSBDemod::feed(SampleVector::const_iterator begin, SampleVector::const_iter
|
|||
m_audioBuffer[m_audioBufferFill].l = sample;
|
||||
m_audioBuffer[m_audioBufferFill].r = sample;
|
||||
++m_audioBufferFill;
|
||||
if(m_audioBufferFill >= m_audioBuffer.size()) {
|
||||
|
||||
if (m_audioBufferFill >= m_audioBuffer.size())
|
||||
{
|
||||
uint res = m_audioFifo->write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 1);
|
||||
|
||||
if (res != m_audioBufferFill)
|
||||
{
|
||||
qDebug("lost %u samples", m_audioBufferFill - res);
|
||||
}
|
||||
|
||||
m_audioBufferFill = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(m_audioFifo->write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 0) != m_audioBufferFill)
|
||||
;//qDebug("lost samples");
|
||||
|
||||
if (m_audioFifo->write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 0) != m_audioBufferFill)
|
||||
{
|
||||
qDebug("SSBDemod::feed: lost samples");
|
||||
}
|
||||
m_audioBufferFill = 0;
|
||||
|
||||
if(m_sampleSink != NULL)
|
||||
if(m_sampleSink != 0)
|
||||
{
|
||||
m_sampleSink->feed(m_sampleBuffer.begin(), m_sampleBuffer.end(), true);
|
||||
}
|
||||
|
||||
m_sampleBuffer.clear();
|
||||
}
|
||||
|
||||
|
@ -123,24 +143,32 @@ void SSBDemod::stop()
|
|||
{
|
||||
}
|
||||
|
||||
bool SSBDemod::handleMessage(Message* cmd)
|
||||
bool SSBDemod::handleMessage(const Message& cmd)
|
||||
{
|
||||
float band, lowCutoff;
|
||||
|
||||
if(DSPSignalNotification::match(cmd)) {
|
||||
DSPSignalNotification* signal = (DSPSignalNotification*)cmd;
|
||||
//fprintf(stderr, "%d samples/sec, %lld Hz offset", signal->getSampleRate(), signal->getFrequencyOffset());
|
||||
m_sampleRate = signal->getSampleRate();
|
||||
m_nco.setFreq(-signal->getFrequencyOffset(), m_sampleRate);
|
||||
qDebug() << "SSBDemod::handleMessage";
|
||||
|
||||
if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
|
||||
m_sampleRate = notif.getSampleRate();
|
||||
m_nco.setFreq(-notif.getFrequencyOffset(), m_sampleRate);
|
||||
m_interpolator.create(16, m_sampleRate, m_Bandwidth);
|
||||
m_sampleDistanceRemain = m_sampleRate / 48000.0;
|
||||
cmd->completed();
|
||||
return true;
|
||||
} else if(MsgConfigureSSBDemod::match(cmd)) {
|
||||
MsgConfigureSSBDemod* cfg = (MsgConfigureSSBDemod*)cmd;
|
||||
|
||||
band = cfg->getBandwidth();
|
||||
lowCutoff = cfg->getLoCutoff();
|
||||
qDebug() << " - DSPSignalNotification: m_sampleRate: " << m_sampleRate
|
||||
<< " frequencyOffset" << notif.getFrequencyOffset();
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureSSBDemod::match(cmd))
|
||||
{
|
||||
MsgConfigureSSBDemod& cfg = (MsgConfigureSSBDemod&) cmd;
|
||||
|
||||
band = cfg.getBandwidth();
|
||||
lowCutoff = cfg.getLoCutoff();
|
||||
|
||||
if (band < 0) {
|
||||
band = -band;
|
||||
|
@ -161,16 +189,27 @@ bool SSBDemod::handleMessage(Message* cmd)
|
|||
m_interpolator.create(16, m_sampleRate, band * 2.0f);
|
||||
SSBFilter->create_filter(m_LowCutoff / 48000.0f, m_Bandwidth / 48000.0f);
|
||||
|
||||
m_volume = cfg->getVolume();
|
||||
m_volume = cfg.getVolume();
|
||||
m_volume *= m_volume * 0.1;
|
||||
|
||||
m_spanLog2 = cfg->getSpanLog2();
|
||||
m_spanLog2 = cfg.getSpanLog2();
|
||||
|
||||
qDebug() << " - MsgConfigureSSBDemod: m_Bandwidth: " << m_Bandwidth
|
||||
<< " m_LowCutoff: " << m_LowCutoff
|
||||
<< " m_volume: " << m_volume
|
||||
<< " m_spanLog2: " << m_spanLog2;
|
||||
|
||||
cmd->completed();
|
||||
return true;
|
||||
} else {
|
||||
if(m_sampleSink != NULL)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_sampleSink != 0)
|
||||
{
|
||||
return m_sampleSink->handleMessage(cmd);
|
||||
else return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,14 +33,14 @@ class AudioFifo;
|
|||
class SSBDemod : public SampleSink {
|
||||
public:
|
||||
SSBDemod(AudioFifo* audioFifo, SampleSink* sampleSink);
|
||||
~SSBDemod();
|
||||
virtual ~SSBDemod();
|
||||
|
||||
void configure(MessageQueue* messageQueue, Real Bandwidth, Real LowCutoff, Real volume, int spanLog2);
|
||||
|
||||
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||
void start();
|
||||
void stop();
|
||||
bool handleMessage(Message* cmd);
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
|
||||
private:
|
||||
class MsgConfigureSSBDemod : public Message {
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "plugin/pluginapi.h"
|
||||
#include "util/simpleserializer.h"
|
||||
#include "gui/basicchannelsettingswidget.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
SSBDemodGUI* SSBDemodGUI::create(PluginAPI* pluginAPI)
|
||||
|
@ -66,12 +67,14 @@ bool SSBDemodGUI::deserialize(const QByteArray& data)
|
|||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if(!d.isValid()) {
|
||||
if (!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.getVersion() == 1) {
|
||||
if (d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
quint32 u32tmp;
|
||||
qint32 tmp;
|
||||
|
@ -92,13 +95,15 @@ bool SSBDemodGUI::deserialize(const QByteArray& data)
|
|||
setNewRate(tmp);
|
||||
applySettings();
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SSBDemodGUI::handleMessage(Message* message)
|
||||
bool SSBDemodGUI::handleMessage(const Message& message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -121,9 +126,12 @@ void SSBDemodGUI::on_deltaMinus_clicked(bool minus)
|
|||
|
||||
void SSBDemodGUI::on_deltaFrequency_changed(quint64 value)
|
||||
{
|
||||
if (ui->deltaMinus->isChecked()) {
|
||||
if (ui->deltaMinus->isChecked())
|
||||
{
|
||||
m_channelMarker->setCenterFrequency(-value);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_channelMarker->setCenterFrequency(value);
|
||||
}
|
||||
}
|
||||
|
@ -134,9 +142,12 @@ void SSBDemodGUI::on_BW_valueChanged(int value)
|
|||
ui->BWText->setText(tr("%1k").arg(s));
|
||||
m_channelMarker->setBandwidth(value * 100 * 2);
|
||||
|
||||
if (value < 0) {
|
||||
if (value < 0)
|
||||
{
|
||||
m_channelMarker->setSidebands(ChannelMarker::lsb);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_channelMarker->setSidebands(ChannelMarker::usb);
|
||||
}
|
||||
|
||||
|
@ -149,18 +160,25 @@ int SSBDemodGUI::getEffectiveLowCutoff(int lowCutoff)
|
|||
int effectiveLowCutoff = lowCutoff;
|
||||
const int guard = 100;
|
||||
|
||||
if (ssbBW < 0) {
|
||||
if (effectiveLowCutoff < ssbBW + guard) {
|
||||
if (ssbBW < 0)
|
||||
{
|
||||
if (effectiveLowCutoff < ssbBW + guard)
|
||||
{
|
||||
effectiveLowCutoff = ssbBW + guard;
|
||||
}
|
||||
if (effectiveLowCutoff > 0) {
|
||||
if (effectiveLowCutoff > 0)
|
||||
{
|
||||
effectiveLowCutoff = 0;
|
||||
}
|
||||
} else {
|
||||
if (effectiveLowCutoff > ssbBW - guard) {
|
||||
}
|
||||
else
|
||||
{
|
||||
if (effectiveLowCutoff > ssbBW - guard)
|
||||
{
|
||||
effectiveLowCutoff = ssbBW - guard;
|
||||
}
|
||||
if (effectiveLowCutoff < 0) {
|
||||
if (effectiveLowCutoff < 0)
|
||||
{
|
||||
effectiveLowCutoff = 0;
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +204,8 @@ void SSBDemodGUI::on_volume_valueChanged(int value)
|
|||
|
||||
void SSBDemodGUI::on_spanLog2_valueChanged(int value)
|
||||
{
|
||||
if (setNewRate(value)) {
|
||||
if (setNewRate(value))
|
||||
{
|
||||
applySettings();
|
||||
}
|
||||
|
||||
|
@ -202,7 +221,8 @@ void SSBDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
|||
|
||||
void SSBDemodGUI::onMenuDoubleClicked()
|
||||
{
|
||||
if(!m_basicSettingsShown) {
|
||||
if(!m_basicSettingsShown)
|
||||
{
|
||||
m_basicSettingsShown = true;
|
||||
BasicChannelSettingsWidget* bcsw = new BasicChannelSettingsWidget(m_channelMarker, this);
|
||||
bcsw->show();
|
||||
|
@ -226,9 +246,8 @@ SSBDemodGUI::SSBDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
m_spectrumVis = new SpectrumVis(ui->glSpectrum);
|
||||
m_ssbDemod = new SSBDemod(m_audioFifo, m_spectrumVis);
|
||||
m_channelizer = new Channelizer(m_ssbDemod);
|
||||
m_threadedSampleSink = new ThreadedSampleSink(m_channelizer);
|
||||
m_pluginAPI->addAudioSource(m_audioFifo);
|
||||
m_pluginAPI->addSampleSink(m_threadedSampleSink);
|
||||
DSPEngine::instance()->addAudioSink(m_audioFifo);
|
||||
DSPEngine::instance()->addThreadedSink(m_channelizer);
|
||||
|
||||
ui->deltaFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold));
|
||||
|
||||
|
@ -248,7 +267,7 @@ SSBDemodGUI::SSBDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
connect(m_channelMarker, SIGNAL(changed()), this, SLOT(viewChanged()));
|
||||
m_pluginAPI->addChannelMarker(m_channelMarker);
|
||||
|
||||
ui->spectrumGUI->setBuddies(m_threadedSampleSink->getMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||
ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||
|
||||
applySettings();
|
||||
}
|
||||
|
@ -256,9 +275,8 @@ SSBDemodGUI::SSBDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
SSBDemodGUI::~SSBDemodGUI()
|
||||
{
|
||||
m_pluginAPI->removeChannelInstance(this);
|
||||
m_pluginAPI->removeAudioSource(m_audioFifo);
|
||||
m_pluginAPI->removeSampleSink(m_threadedSampleSink);
|
||||
delete m_threadedSampleSink;
|
||||
DSPEngine::instance()->removeAudioSink(m_audioFifo);
|
||||
DSPEngine::instance()->removeThreadedSink(m_channelizer);
|
||||
delete m_channelizer;
|
||||
delete m_ssbDemod;
|
||||
delete m_spectrumVis;
|
||||
|
@ -269,25 +287,32 @@ SSBDemodGUI::~SSBDemodGUI()
|
|||
|
||||
bool SSBDemodGUI::setNewRate(int spanLog2)
|
||||
{
|
||||
if ((spanLog2 < 1) || (spanLog2 > 5)) {
|
||||
if ((spanLog2 < 1) || (spanLog2 > 5))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_spanLog2 = spanLog2;
|
||||
m_rate = 48000 / (1<<spanLog2);
|
||||
|
||||
if (ui->BW->value() < -m_rate/100) {
|
||||
if (ui->BW->value() < -m_rate/100)
|
||||
{
|
||||
ui->BW->setValue(-m_rate/100);
|
||||
m_channelMarker->setBandwidth(-m_rate*2);
|
||||
} else if (ui->BW->value() > m_rate/100) {
|
||||
}
|
||||
else if (ui->BW->value() > m_rate/100)
|
||||
{
|
||||
ui->BW->setValue(m_rate/100);
|
||||
m_channelMarker->setBandwidth(m_rate*2);
|
||||
}
|
||||
|
||||
if (ui->lowCut->value() < -m_rate/100) {
|
||||
if (ui->lowCut->value() < -m_rate/100)
|
||||
{
|
||||
ui->lowCut->setValue(-m_rate/100);
|
||||
m_channelMarker->setLowCutoff(-m_rate);
|
||||
} else if (ui->lowCut->value() > m_rate/100) {
|
||||
}
|
||||
else if (ui->lowCut->value() > m_rate/100)
|
||||
{
|
||||
ui->lowCut->setValue(m_rate/100);
|
||||
m_channelMarker->setLowCutoff(m_rate);
|
||||
}
|
||||
|
@ -311,10 +336,12 @@ void SSBDemodGUI::applySettings()
|
|||
setTitleColor(m_channelMarker->getColor());
|
||||
ui->deltaFrequency->setValue(abs(m_channelMarker->getCenterFrequency()));
|
||||
ui->deltaMinus->setChecked(m_channelMarker->getCenterFrequency() < 0);
|
||||
m_channelizer->configure(m_threadedSampleSink->getMessageQueue(),
|
||||
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
48000,
|
||||
m_channelMarker->getCenterFrequency());
|
||||
m_ssbDemod->configure(m_threadedSampleSink->getMessageQueue(),
|
||||
|
||||
m_ssbDemod->configure(m_ssbDemod->getInputMessageQueue(),
|
||||
ui->BW->value() * 100.0,
|
||||
ui->lowCut->value() * 100.0,
|
||||
ui->volume->value() / 10.0,
|
||||
|
|
|
@ -8,7 +8,6 @@ class PluginAPI;
|
|||
class ChannelMarker;
|
||||
|
||||
class AudioFifo;
|
||||
class ThreadedSampleSink;
|
||||
class Channelizer;
|
||||
class SSBDemod;
|
||||
class SpectrumVis;
|
||||
|
@ -32,7 +31,7 @@ public:
|
|||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
|
||||
bool handleMessage(Message* message);
|
||||
virtual bool handleMessage(const Message& message);
|
||||
|
||||
private slots:
|
||||
void viewChanged();
|
||||
|
@ -54,7 +53,6 @@ private:
|
|||
int m_spanLog2;
|
||||
|
||||
AudioFifo* m_audioFifo;
|
||||
ThreadedSampleSink* m_threadedSampleSink;
|
||||
Channelizer* m_channelizer;
|
||||
SSBDemod* m_ssbDemod;
|
||||
SpectrumVis* m_spectrumVis;
|
||||
|
|
|
@ -47,6 +47,7 @@ TCPSrc::TCPSrc(MessageQueue* uiMessageQueue, TCPSrcGUI* tcpSrcGUI, SampleSink* s
|
|||
m_last = 0;
|
||||
m_this = 0;
|
||||
m_scale = 0;
|
||||
m_boost = 0;
|
||||
m_sampleBufferSSB.resize(tcpFftLen);
|
||||
TCPFilter = new fftfilt(0.3 / 48.0, 16.0 / 48.0, tcpFftLen);
|
||||
// if (!TCPFilter) segfault;
|
||||
|
@ -60,13 +61,13 @@ TCPSrc::~TCPSrc()
|
|||
void TCPSrc::configure(MessageQueue* messageQueue, SampleFormat sampleFormat, Real outputSampleRate, Real rfBandwidth, int tcpPort, int boost)
|
||||
{
|
||||
Message* cmd = MsgTCPSrcConfigure::create(sampleFormat, outputSampleRate, rfBandwidth, tcpPort, boost);
|
||||
cmd->submit(messageQueue, this);
|
||||
messageQueue->push(cmd);
|
||||
}
|
||||
|
||||
void TCPSrc::setSpectrum(MessageQueue* messageQueue, bool enabled)
|
||||
{
|
||||
Message* cmd = MsgTCPSrcSpectrum::create(enabled);
|
||||
cmd->submit(messageQueue, this);
|
||||
messageQueue->push(cmd);
|
||||
}
|
||||
|
||||
void TCPSrc::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
|
||||
|
@ -157,61 +158,101 @@ void TCPSrc::stop()
|
|||
delete m_tcpServer;
|
||||
}
|
||||
|
||||
bool TCPSrc::handleMessage(Message* cmd)
|
||||
bool TCPSrc::handleMessage(const Message& cmd)
|
||||
{
|
||||
if(DSPSignalNotification::match(cmd)) {
|
||||
DSPSignalNotification* signal = (DSPSignalNotification*)cmd;
|
||||
qDebug("%d samples/sec, %lld Hz offset", signal->getSampleRate(), signal->getFrequencyOffset());
|
||||
m_inputSampleRate = signal->getSampleRate();
|
||||
m_nco.setFreq(-signal->getFrequencyOffset(), m_inputSampleRate);
|
||||
qDebug() << "TCPSrc::handleMessage";
|
||||
|
||||
if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
|
||||
m_inputSampleRate = notif.getSampleRate();
|
||||
m_nco.setFreq(-notif.getFrequencyOffset(), m_inputSampleRate);
|
||||
m_interpolator.create(16, m_inputSampleRate, m_rfBandwidth / 2.0);
|
||||
m_sampleDistanceRemain = m_inputSampleRate / m_outputSampleRate;
|
||||
cmd->completed();
|
||||
|
||||
qDebug() << " - DSPSignalNotification: m_inputSampleRate: " << m_inputSampleRate
|
||||
<< " frequencyOffset: " << notif.getFrequencyOffset();
|
||||
|
||||
return true;
|
||||
} else if(MsgTCPSrcConfigure::match(cmd)) {
|
||||
MsgTCPSrcConfigure* cfg = (MsgTCPSrcConfigure*)cmd;
|
||||
m_sampleFormat = cfg->getSampleFormat();
|
||||
m_outputSampleRate = cfg->getOutputSampleRate();
|
||||
m_rfBandwidth = cfg->getRFBandwidth();
|
||||
if(cfg->getTCPPort() != m_tcpPort) {
|
||||
m_tcpPort = cfg->getTCPPort();
|
||||
}
|
||||
else if (MsgTCPSrcConfigure::match(cmd))
|
||||
{
|
||||
MsgTCPSrcConfigure& cfg = (MsgTCPSrcConfigure&) cmd;
|
||||
|
||||
m_sampleFormat = cfg.getSampleFormat();
|
||||
m_outputSampleRate = cfg.getOutputSampleRate();
|
||||
m_rfBandwidth = cfg.getRFBandwidth();
|
||||
|
||||
if (cfg.getTCPPort() != m_tcpPort)
|
||||
{
|
||||
m_tcpPort = cfg.getTCPPort();
|
||||
|
||||
if(m_tcpServer->isListening())
|
||||
{
|
||||
m_tcpServer->close();
|
||||
}
|
||||
|
||||
m_tcpServer->listen(QHostAddress::Any, m_tcpPort);
|
||||
}
|
||||
m_boost = cfg->getBoost();
|
||||
|
||||
m_boost = cfg.getBoost();
|
||||
m_interpolator.create(16, m_inputSampleRate, m_rfBandwidth / 2.0);
|
||||
m_sampleDistanceRemain = m_inputSampleRate / m_outputSampleRate;
|
||||
|
||||
if (m_sampleFormat == FormatSSB)
|
||||
{
|
||||
TCPFilter->create_filter(0.3 / 48.0, m_rfBandwidth / 2.0 / m_outputSampleRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
TCPFilter->create_filter(0.0, m_rfBandwidth / 2.0 / m_outputSampleRate);
|
||||
cmd->completed();
|
||||
}
|
||||
|
||||
qDebug() << " - MsgTCPSrcConfigure: m_sampleFormat: " << m_sampleFormat
|
||||
<< " m_outputSampleRate: " << m_outputSampleRate
|
||||
<< " m_rfBandwidth: " << m_rfBandwidth
|
||||
<< " m_boost: " << m_boost;
|
||||
|
||||
return true;
|
||||
} else if(MsgTCPSrcSpectrum::match(cmd)) {
|
||||
MsgTCPSrcSpectrum* spc = (MsgTCPSrcSpectrum*)cmd;
|
||||
m_spectrumEnabled = spc->getEnabled();
|
||||
cmd->completed();
|
||||
}
|
||||
else if (MsgTCPSrcSpectrum::match(cmd))
|
||||
{
|
||||
MsgTCPSrcSpectrum& spc = (MsgTCPSrcSpectrum&) cmd;
|
||||
|
||||
m_spectrumEnabled = spc.getEnabled();
|
||||
|
||||
qDebug() << " - MsgTCPSrcSpectrum: m_spectrumEnabled: " << m_spectrumEnabled;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
if(m_spectrum != NULL)
|
||||
}
|
||||
else
|
||||
{
|
||||
if(m_spectrum != 0)
|
||||
{
|
||||
return m_spectrum->handleMessage(cmd);
|
||||
else return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TCPSrc::closeAllSockets(Sockets* sockets)
|
||||
{
|
||||
for(int i = 0; i < sockets->count(); ++i) {
|
||||
for(int i = 0; i < sockets->count(); ++i)
|
||||
{
|
||||
MsgTCPSrcConnection* msg = MsgTCPSrcConnection::create(false, sockets->at(i).id, QHostAddress(), 0);
|
||||
msg->submit(m_uiMessageQueue, (PluginGUI*)m_tcpSrcGUI);
|
||||
m_uiMessageQueue->push(msg);
|
||||
sockets->at(i).socket->close();
|
||||
}
|
||||
}
|
||||
|
||||
void TCPSrc::onNewConnection()
|
||||
{
|
||||
while(m_tcpServer->hasPendingConnections()) {
|
||||
while(m_tcpServer->hasPendingConnections())
|
||||
{
|
||||
QTcpSocket* connection = m_tcpServer->nextPendingConnection();
|
||||
connect(connection, SIGNAL(disconnected()), this, SLOT(onDisconnected()));
|
||||
|
||||
|
@ -223,7 +264,7 @@ void TCPSrc::onNewConnection()
|
|||
MsgTCPSrcConnection* msg = MsgTCPSrcConnection::create(true, id, connection->peerAddress(), connection->peerPort());
|
||||
m_nextSSBId = (m_nextSSBId + 1) & 0xffffff;
|
||||
m_ssbSockets.push_back(Socket(id, connection));
|
||||
msg->submit(m_uiMessageQueue, (PluginGUI*)m_tcpSrcGUI);
|
||||
m_uiMessageQueue->push(msg);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -232,7 +273,7 @@ void TCPSrc::onNewConnection()
|
|||
MsgTCPSrcConnection* msg = MsgTCPSrcConnection::create(true, id, connection->peerAddress(), connection->peerPort());
|
||||
m_nextS16leId = (m_nextS16leId + 1) & 0xffffff;
|
||||
m_s16leSockets.push_back(Socket(id, connection));
|
||||
msg->submit(m_uiMessageQueue, (PluginGUI*)m_tcpSrcGUI);
|
||||
m_uiMessageQueue->push(msg);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -246,19 +287,25 @@ void TCPSrc::onNewConnection()
|
|||
void TCPSrc::onDisconnected()
|
||||
{
|
||||
quint32 id;
|
||||
QTcpSocket* socket = NULL;
|
||||
QTcpSocket* socket = 0;
|
||||
|
||||
for(int i = 0; i < m_ssbSockets.count(); i++) {
|
||||
if(m_ssbSockets[i].socket == sender()) {
|
||||
for(int i = 0; i < m_ssbSockets.count(); i++)
|
||||
{
|
||||
if(m_ssbSockets[i].socket == sender())
|
||||
{
|
||||
id = m_ssbSockets[i].id;
|
||||
socket = m_ssbSockets[i].socket;
|
||||
m_ssbSockets.removeAt(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(socket == NULL) {
|
||||
for(int i = 0; i < m_s16leSockets.count(); i++) {
|
||||
if(m_s16leSockets[i].socket == sender()) {
|
||||
|
||||
if(socket == 0)
|
||||
{
|
||||
for(int i = 0; i < m_s16leSockets.count(); i++)
|
||||
{
|
||||
if(m_s16leSockets[i].socket == sender())
|
||||
{
|
||||
id = m_s16leSockets[i].id;
|
||||
socket = m_s16leSockets[i].socket;
|
||||
m_s16leSockets.removeAt(i);
|
||||
|
@ -266,9 +313,11 @@ void TCPSrc::onDisconnected()
|
|||
}
|
||||
}
|
||||
}
|
||||
if(socket != NULL) {
|
||||
|
||||
if(socket != 0)
|
||||
{
|
||||
MsgTCPSrcConnection* msg = MsgTCPSrcConnection::create(false, id, QHostAddress(), 0);
|
||||
msg->submit(m_uiMessageQueue, (PluginGUI*)m_tcpSrcGUI);
|
||||
m_uiMessageQueue->push(msg);
|
||||
socket->deleteLater();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,15 +26,15 @@ public:
|
|||
};
|
||||
|
||||
TCPSrc(MessageQueue* uiMessageQueue, TCPSrcGUI* tcpSrcGUI, SampleSink* spectrum);
|
||||
~TCPSrc();
|
||||
virtual ~TCPSrc();
|
||||
|
||||
void configure(MessageQueue* messageQueue, SampleFormat sampleFormat, Real outputSampleRate, Real rfBandwidth, int tcpPort, int boost);
|
||||
void setSpectrum(MessageQueue* messageQueue, bool enabled);
|
||||
|
||||
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||
void start();
|
||||
void stop();
|
||||
bool handleMessage(Message* cmd);
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
|
||||
class MsgTCPSrcConnection : public Message {
|
||||
MESSAGE_CLASS_DECLARATION
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include "tcpsrc.h"
|
||||
#include "dsp/channelizer.h"
|
||||
#include "dsp/spectrumvis.h"
|
||||
#include "dsp/threadedsamplesink.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "util/simpleserializer.h"
|
||||
#include "gui/basicchannelsettingswidget.h"
|
||||
#include "ui_tcpsrcgui.h"
|
||||
|
@ -64,12 +64,14 @@ bool TCPSrcGUI::deserialize(const QByteArray& data)
|
|||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if(!d.isValid()) {
|
||||
if (!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.getVersion() == 1) {
|
||||
if (d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
qint32 s32tmp;
|
||||
Real realtmp;
|
||||
|
@ -104,22 +106,39 @@ bool TCPSrcGUI::deserialize(const QByteArray& data)
|
|||
ui->boost->setValue(s32tmp);
|
||||
applySettings();
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool TCPSrcGUI::handleMessage(Message* message)
|
||||
bool TCPSrcGUI::handleMessage(const Message& message)
|
||||
{
|
||||
if(TCPSrc::MsgTCPSrcConnection::match(message)) {
|
||||
TCPSrc::MsgTCPSrcConnection* con = (TCPSrc::MsgTCPSrcConnection*)message;
|
||||
if(con->getConnect())
|
||||
addConnection(con->getID(), con->getPeerAddress(), con->getPeerPort());
|
||||
else delConnection(con->getID());
|
||||
message->completed();
|
||||
qDebug() << "TCPSrcGUI::handleMessage";
|
||||
|
||||
if (TCPSrc::MsgTCPSrcConnection::match(message))
|
||||
{
|
||||
TCPSrc::MsgTCPSrcConnection& con = (TCPSrc::MsgTCPSrcConnection&) message;
|
||||
|
||||
if(con.getConnect())
|
||||
{
|
||||
addConnection(con.getID(), con.getPeerAddress(), con.getPeerPort());
|
||||
}
|
||||
else
|
||||
{
|
||||
delConnection(con.getID());
|
||||
}
|
||||
|
||||
qDebug() << " - TCPSrc::MsgTCPSrcConnection: ID: " << con.getID()
|
||||
<< " peerAddress: " << con.getPeerAddress()
|
||||
<< " peerPort: " << con.getPeerPort();
|
||||
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -145,14 +164,13 @@ TCPSrcGUI::TCPSrcGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
m_spectrumVis = new SpectrumVis(ui->glSpectrum);
|
||||
m_tcpSrc = new TCPSrc(m_pluginAPI->getMainWindowMessageQueue(), this, m_spectrumVis);
|
||||
m_channelizer = new Channelizer(m_tcpSrc);
|
||||
m_threadedSampleSink = new ThreadedSampleSink(m_channelizer);
|
||||
m_pluginAPI->addSampleSink(m_threadedSampleSink);
|
||||
DSPEngine::instance()->addThreadedSink(m_channelizer);
|
||||
|
||||
ui->glSpectrum->setCenterFrequency(0);
|
||||
ui->glSpectrum->setSampleRate(ui->sampleRate->text().toInt());
|
||||
ui->glSpectrum->setDisplayWaterfall(true);
|
||||
ui->glSpectrum->setDisplayMaxHold(true);
|
||||
m_spectrumVis->configure(m_threadedSampleSink->getMessageQueue(), 64, 10, FFTWindow::BlackmanHarris);
|
||||
m_spectrumVis->configure(m_spectrumVis->getInputMessageQueue(), 64, 10, FFTWindow::BlackmanHarris);
|
||||
|
||||
m_channelMarker = new ChannelMarker(this);
|
||||
m_channelMarker->setBandwidth(16000);
|
||||
|
@ -162,7 +180,7 @@ TCPSrcGUI::TCPSrcGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
connect(m_channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged()));
|
||||
m_pluginAPI->addChannelMarker(m_channelMarker);
|
||||
|
||||
ui->spectrumGUI->setBuddies(m_threadedSampleSink->getMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||
ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||
|
||||
applySettings();
|
||||
}
|
||||
|
@ -170,8 +188,7 @@ TCPSrcGUI::TCPSrcGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
TCPSrcGUI::~TCPSrcGUI()
|
||||
{
|
||||
m_pluginAPI->removeChannelInstance(this);
|
||||
m_pluginAPI->removeSampleSink(m_threadedSampleSink);
|
||||
delete m_threadedSampleSink;
|
||||
DSPEngine::instance()->removeThreadedSink(m_channelizer);
|
||||
delete m_channelizer;
|
||||
delete m_tcpSrc;
|
||||
delete m_spectrumVis;
|
||||
|
@ -184,14 +201,26 @@ void TCPSrcGUI::applySettings()
|
|||
bool ok;
|
||||
|
||||
Real outputSampleRate = ui->sampleRate->text().toDouble(&ok);
|
||||
|
||||
if((!ok) || (outputSampleRate < 1000))
|
||||
{
|
||||
outputSampleRate = 48000;
|
||||
}
|
||||
|
||||
Real rfBandwidth = ui->rfBandwidth->text().toDouble(&ok);
|
||||
|
||||
if((!ok) || (rfBandwidth > outputSampleRate))
|
||||
{
|
||||
rfBandwidth = outputSampleRate;
|
||||
}
|
||||
|
||||
int tcpPort = ui->tcpPort->text().toInt(&ok);
|
||||
|
||||
if((!ok) || (tcpPort < 1) || (tcpPort > 65535))
|
||||
{
|
||||
tcpPort = 9999;
|
||||
}
|
||||
|
||||
int boost = ui->boost->value();
|
||||
|
||||
setTitleColor(m_channelMarker->getColor());
|
||||
|
@ -204,12 +233,14 @@ void TCPSrcGUI::applySettings()
|
|||
connect(m_channelMarker, SIGNAL(changed()), this, SLOT(channelMarkerChanged()));
|
||||
ui->glSpectrum->setSampleRate(outputSampleRate);
|
||||
|
||||
m_channelizer->configure(m_threadedSampleSink->getMessageQueue(),
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
outputSampleRate,
|
||||
m_channelMarker->getCenterFrequency());
|
||||
|
||||
TCPSrc::SampleFormat sampleFormat;
|
||||
switch(ui->sampleFormat->currentIndex()) {
|
||||
|
||||
switch(ui->sampleFormat->currentIndex())
|
||||
{
|
||||
case 0:
|
||||
sampleFormat = TCPSrc::FormatSSB;
|
||||
break;
|
||||
|
@ -230,7 +261,7 @@ void TCPSrcGUI::applySettings()
|
|||
m_tcpPort = tcpPort;
|
||||
m_boost = boost;
|
||||
|
||||
m_tcpSrc->configure(m_threadedSampleSink->getMessageQueue(),
|
||||
m_tcpSrc->configure(m_tcpSrc->getInputMessageQueue(),
|
||||
sampleFormat,
|
||||
outputSampleRate,
|
||||
rfBandwidth,
|
||||
|
@ -273,13 +304,16 @@ void TCPSrcGUI::on_boost_valueChanged(int value)
|
|||
|
||||
void TCPSrcGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||||
{
|
||||
if((widget == ui->spectrumBox) && (m_tcpSrc != NULL))
|
||||
m_tcpSrc->setSpectrum(m_threadedSampleSink->getMessageQueue(), rollDown);
|
||||
if ((widget == ui->spectrumBox) && (m_tcpSrc != 0))
|
||||
{
|
||||
m_tcpSrc->setSpectrum(m_tcpSrc->getInputMessageQueue(), rollDown);
|
||||
}
|
||||
}
|
||||
|
||||
void TCPSrcGUI::onMenuDoubleClicked()
|
||||
{
|
||||
if(!m_basicSettingsShown) {
|
||||
if (!m_basicSettingsShown)
|
||||
{
|
||||
m_basicSettingsShown = true;
|
||||
BasicChannelSettingsWidget* bcsw = new BasicChannelSettingsWidget(m_channelMarker, this);
|
||||
bcsw->show();
|
||||
|
@ -296,8 +330,10 @@ void TCPSrcGUI::addConnection(quint32 id, const QHostAddress& peerAddress, int p
|
|||
|
||||
void TCPSrcGUI::delConnection(quint32 id)
|
||||
{
|
||||
for(int i = 0; i < ui->connections->topLevelItemCount(); i++) {
|
||||
if(ui->connections->topLevelItem(i)->type() == (int)id) {
|
||||
for(int i = 0; i < ui->connections->topLevelItemCount(); i++)
|
||||
{
|
||||
if(ui->connections->topLevelItem(i)->type() == (int)id)
|
||||
{
|
||||
delete ui->connections->topLevelItem(i);
|
||||
ui->connectedClientsBox->setWindowTitle(tr("Connected Clients (%1)").arg(ui->connections->topLevelItemCount()));
|
||||
return;
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
class PluginAPI;
|
||||
class ChannelMarker;
|
||||
class ThreadedSampleSink;
|
||||
class Channelizer;
|
||||
class TCPSrc;
|
||||
class SpectrumVis;
|
||||
|
@ -32,7 +31,7 @@ public:
|
|||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
|
||||
bool handleMessage(Message* message);
|
||||
virtual bool handleMessage(const Message& message);
|
||||
|
||||
private slots:
|
||||
void channelMarkerChanged();
|
||||
|
@ -59,12 +58,11 @@ private:
|
|||
bool m_basicSettingsShown;
|
||||
|
||||
// RF path
|
||||
ThreadedSampleSink* m_threadedSampleSink;
|
||||
Channelizer* m_channelizer;
|
||||
SpectrumVis* m_spectrumVis;
|
||||
|
||||
explicit TCPSrcGUI(PluginAPI* pluginAPI, QWidget* parent = NULL);
|
||||
~TCPSrcGUI();
|
||||
virtual ~TCPSrcGUI();
|
||||
|
||||
void applySettings();
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QTime>
|
||||
#include <QDebug>
|
||||
#include <stdio.h>
|
||||
#include <complex.h>
|
||||
#include "audio/audiooutput.h"
|
||||
|
@ -51,13 +52,15 @@ WFMDemod::WFMDemod(AudioFifo* audioFifo, SampleSink* sampleSink) :
|
|||
WFMDemod::~WFMDemod()
|
||||
{
|
||||
if (m_rfFilter)
|
||||
{
|
||||
delete m_rfFilter;
|
||||
}
|
||||
}
|
||||
|
||||
void WFMDemod::configure(MessageQueue* messageQueue, Real rfBandwidth, Real afBandwidth, Real volume, Real squelch)
|
||||
{
|
||||
Message* cmd = MsgConfigureWFMDemod::create(rfBandwidth, afBandwidth, volume, squelch);
|
||||
cmd->submit(messageQueue, this);
|
||||
messageQueue->push(cmd);
|
||||
}
|
||||
|
||||
void WFMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool firstOfBurst)
|
||||
|
@ -79,13 +82,6 @@ void WFMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_iter
|
|||
|
||||
for (int i =0 ; i <rf_out; i++)
|
||||
{
|
||||
/*
|
||||
// atan2 version
|
||||
Real x = rf[i].real() * m_lastSample.real() + rf[i].imag() * m_lastSample.imag();
|
||||
Real y = rf[i].real() * m_m1Sample.imag() - rf[i].imag() * m_m1Sample.real();
|
||||
Real demod = atan2(x,y) / M_PI;
|
||||
*/
|
||||
|
||||
msq = rf[i].real()*rf[i].real() + rf[i].imag()*rf[i].imag();
|
||||
|
||||
m_movingAverage.feed(msq);
|
||||
|
@ -135,89 +131,6 @@ void WFMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_iter
|
|||
m_interpolatorDistanceRemain += m_interpolatorDistance;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
{
|
||||
if(m_interpolator.interpolate(&m_interpolatorDistanceRemain, e, &ci))
|
||||
{
|
||||
m_sampleBuffer.push_back(Sample(ci.real() * 32767.0, ci.imag() * 32767.0));
|
||||
|
||||
m_movingAverage.feed(ci.real() * ci.real() + ci.imag() * ci.imag());
|
||||
if(m_movingAverage.average() >= m_squelchLevel)
|
||||
m_squelchState = m_running.m_audioSampleRate/ 20;
|
||||
|
||||
qint16 sample;
|
||||
if(m_squelchState > 0) {
|
||||
m_squelchState--;
|
||||
|
||||
/*
|
||||
Real argument = arg(ci);
|
||||
argument /= M_PI;
|
||||
Real demod = argument - m_lastArgument;
|
||||
m_lastArgument = argument;
|
||||
*/
|
||||
|
||||
|
||||
//ci *= 32768.0;
|
||||
|
||||
/*
|
||||
Complex d = conj(m_lastSample) * ci;
|
||||
m_lastSample = ci;
|
||||
Real demod = atan2(d.imag(), d.real());
|
||||
*/
|
||||
|
||||
|
||||
//m_lastSample = ci;
|
||||
|
||||
/*
|
||||
Real argument = atan2(ci.real()*m_lastSample.imag() - m_lastSample.real()*ci.imag(),
|
||||
ci.real()*m_lastSample.real() + ci.imag()*m_lastSample.imag());
|
||||
argument /= M_PI;
|
||||
Real demod = argument - m_lastArgument;
|
||||
m_lastArgument = argument;
|
||||
m_lastSample = ci;
|
||||
*/
|
||||
|
||||
//Real demod = arctan2(d.imag(), d.real());
|
||||
/*
|
||||
Real argument1 = arg(ci);//atan2(ci.imag(), ci.real());
|
||||
Real argument2 = m_lastSample.real();
|
||||
Real demod = angleDist(argument2, argument1);
|
||||
m_lastSample = Complex(argument1, 0);
|
||||
*/
|
||||
//demod /= M_PI;
|
||||
|
||||
demod = m_lowpass.filter(demod);
|
||||
|
||||
/*
|
||||
if(demod < -1)
|
||||
demod = -1;
|
||||
else if(demod > 1)
|
||||
demod = 1;
|
||||
*/
|
||||
|
||||
demod *= m_running.m_volume;
|
||||
sample = demod * 64;
|
||||
|
||||
} else {
|
||||
sample = 0;
|
||||
}
|
||||
|
||||
m_audioBuffer[m_audioBufferFill].l = sample;
|
||||
m_audioBuffer[m_audioBufferFill].r = sample;
|
||||
++m_audioBufferFill;
|
||||
if(m_audioBufferFill >= m_audioBuffer.size()) {
|
||||
uint res = m_audioFifo->write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 1);
|
||||
if(res != m_audioBufferFill)
|
||||
qDebug("lost %u audio samples", m_audioBufferFill - res);
|
||||
m_audioBufferFill = 0;
|
||||
}
|
||||
|
||||
m_interpolatorDistanceRemain += m_interpolatorDistance;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if(m_audioBufferFill > 0) {
|
||||
|
@ -246,28 +159,50 @@ void WFMDemod::stop()
|
|||
{
|
||||
}
|
||||
|
||||
bool WFMDemod::handleMessage(Message* cmd)
|
||||
bool WFMDemod::handleMessage(const Message& cmd)
|
||||
{
|
||||
if(DSPSignalNotification::match(cmd)) {
|
||||
DSPSignalNotification* signal = (DSPSignalNotification*)cmd;
|
||||
qDebug() << "WFMDemod::handleMessage";
|
||||
|
||||
m_config.m_inputSampleRate = signal->getSampleRate();
|
||||
m_config.m_inputFrequencyOffset = signal->getFrequencyOffset();
|
||||
if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
|
||||
m_config.m_inputSampleRate = notif.getSampleRate();
|
||||
m_config.m_inputFrequencyOffset = notif.getFrequencyOffset();
|
||||
apply();
|
||||
cmd->completed();
|
||||
|
||||
qDebug() << " - DSPSignalNotification: m_inputSampleRate: " << m_config.m_inputSampleRate
|
||||
<< " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset;
|
||||
|
||||
return true;
|
||||
} else if(MsgConfigureWFMDemod::match(cmd)) {
|
||||
MsgConfigureWFMDemod* cfg = (MsgConfigureWFMDemod*)cmd;
|
||||
m_config.m_rfBandwidth = cfg->getRFBandwidth();
|
||||
m_config.m_afBandwidth = cfg->getAFBandwidth();
|
||||
m_config.m_volume = cfg->getVolume();
|
||||
m_config.m_squelch = cfg->getSquelch();
|
||||
}
|
||||
else if (MsgConfigureWFMDemod::match(cmd))
|
||||
{
|
||||
MsgConfigureWFMDemod& cfg = (MsgConfigureWFMDemod&) cmd;
|
||||
|
||||
m_config.m_rfBandwidth = cfg.getRFBandwidth();
|
||||
m_config.m_afBandwidth = cfg.getAFBandwidth();
|
||||
m_config.m_volume = cfg.getVolume();
|
||||
m_config.m_squelch = cfg.getSquelch();
|
||||
apply();
|
||||
|
||||
qDebug() << " - MsgConfigureWFMDemod: m_rfBandwidth: " << m_config.m_rfBandwidth
|
||||
<< " m_afBandwidth: " << m_config.m_afBandwidth
|
||||
<< " m_volume: " << m_config.m_volume
|
||||
<< " m_squelch: " << m_config.m_squelch;
|
||||
|
||||
return true;
|
||||
} else {
|
||||
if(m_sampleSink != NULL)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_sampleSink != 0)
|
||||
{
|
||||
return m_sampleSink->handleMessage(cmd);
|
||||
else return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,14 +35,14 @@ class AudioFifo;
|
|||
class WFMDemod : public SampleSink {
|
||||
public:
|
||||
WFMDemod(AudioFifo* audioFifo, SampleSink* sampleSink);
|
||||
~WFMDemod();
|
||||
virtual ~WFMDemod();
|
||||
|
||||
void configure(MessageQueue* messageQueue, Real rfBandwidth, Real afBandwidth, Real volume, Real squelch);
|
||||
|
||||
void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool po);
|
||||
void start();
|
||||
void stop();
|
||||
bool handleMessage(Message* cmd);
|
||||
virtual void feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool po);
|
||||
virtual void start();
|
||||
virtual void stop();
|
||||
virtual bool handleMessage(const Message& cmd);
|
||||
|
||||
private:
|
||||
class MsgConfigureWFMDemod : public Message {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#include <QDockWidget>
|
||||
#include <QMainWindow>
|
||||
#include <QDebug>
|
||||
#include "ui_wfmdemodgui.h"
|
||||
#include "dsp/threadedsamplesink.h"
|
||||
#include "dsp/channelizer.h"
|
||||
#include "dsp/nullsink.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "gui/glspectrum.h"
|
||||
#include "plugin/pluginapi.h"
|
||||
#include "util/simpleserializer.h"
|
||||
|
@ -79,12 +80,14 @@ bool WFMDemodGUI::deserialize(const QByteArray& data)
|
|||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if(!d.isValid()) {
|
||||
if (!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.getVersion() == 1) {
|
||||
if (d.getVersion() == 1)
|
||||
{
|
||||
QByteArray bytetmp;
|
||||
quint32 u32tmp;
|
||||
qint32 tmp;
|
||||
|
@ -104,13 +107,15 @@ bool WFMDemodGUI::deserialize(const QByteArray& data)
|
|||
m_channelMarker->setColor(u32tmp);
|
||||
applySettings();
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool WFMDemodGUI::handleMessage(Message* message)
|
||||
bool WFMDemodGUI::handleMessage(const Message& message)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -133,9 +138,12 @@ void WFMDemodGUI::on_deltaMinus_clicked(bool minus)
|
|||
|
||||
void WFMDemodGUI::on_deltaFrequency_changed(quint64 value)
|
||||
{
|
||||
if (ui->deltaMinus->isChecked()) {
|
||||
if (ui->deltaMinus->isChecked())
|
||||
{
|
||||
m_channelMarker->setCenterFrequency(-value);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_channelMarker->setCenterFrequency(value);
|
||||
}
|
||||
}
|
||||
|
@ -172,7 +180,8 @@ void WFMDemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
|||
|
||||
void WFMDemodGUI::onMenuDoubleClicked()
|
||||
{
|
||||
if(!m_basicSettingsShown) {
|
||||
if(!m_basicSettingsShown)
|
||||
{
|
||||
m_basicSettingsShown = true;
|
||||
BasicChannelSettingsWidget* bcsw = new BasicChannelSettingsWidget(m_channelMarker, this);
|
||||
bcsw->show();
|
||||
|
@ -191,12 +200,10 @@ WFMDemodGUI::WFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked()));
|
||||
|
||||
m_audioFifo = new AudioFifo(4, 250000); // TODO: check. Room for 1s FIFO at max rate
|
||||
m_nullSink = new NullSink();
|
||||
m_wfmDemod = new WFMDemod(m_audioFifo, m_nullSink);
|
||||
m_wfmDemod = new WFMDemod(m_audioFifo, 0);
|
||||
m_channelizer = new Channelizer(m_wfmDemod);
|
||||
m_threadedSampleSink = new ThreadedSampleSink(m_channelizer);
|
||||
m_pluginAPI->addAudioSource(m_audioFifo);
|
||||
m_pluginAPI->addSampleSink(m_threadedSampleSink);
|
||||
DSPEngine::instance()->addAudioSink(m_audioFifo);
|
||||
DSPEngine::instance()->addThreadedSink(m_channelizer);
|
||||
|
||||
m_channelMarker = new ChannelMarker(this);
|
||||
m_channelMarker->setColor(Qt::blue);
|
||||
|
@ -212,12 +219,10 @@ WFMDemodGUI::WFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
WFMDemodGUI::~WFMDemodGUI()
|
||||
{
|
||||
m_pluginAPI->removeChannelInstance(this);
|
||||
m_pluginAPI->removeAudioSource(m_audioFifo);
|
||||
m_pluginAPI->removeSampleSink(m_threadedSampleSink);
|
||||
delete m_threadedSampleSink;
|
||||
DSPEngine::instance()->removeAudioSink(m_audioFifo);
|
||||
DSPEngine::instance()->removeThreadedSink(m_channelizer);
|
||||
delete m_channelizer;
|
||||
delete m_wfmDemod;
|
||||
delete m_nullSink;
|
||||
delete m_audioFifo;
|
||||
delete m_channelMarker;
|
||||
delete ui;
|
||||
|
@ -226,12 +231,15 @@ WFMDemodGUI::~WFMDemodGUI()
|
|||
void WFMDemodGUI::applySettings()
|
||||
{
|
||||
setTitleColor(m_channelMarker->getColor());
|
||||
m_channelizer->configure(m_threadedSampleSink->getMessageQueue(),
|
||||
|
||||
m_channelizer->configure(m_channelizer->getInputMessageQueue(),
|
||||
requiredBW(m_rfBW[ui->rfBW->value()]), // TODO: this is where requested sample rate is specified
|
||||
m_channelMarker->getCenterFrequency());
|
||||
|
||||
ui->deltaFrequency->setValue(abs(m_channelMarker->getCenterFrequency()));
|
||||
ui->deltaMinus->setChecked(m_channelMarker->getCenterFrequency() < 0);
|
||||
m_wfmDemod->configure(m_threadedSampleSink->getMessageQueue(),
|
||||
|
||||
m_wfmDemod->configure(m_wfmDemod->getInputMessageQueue(),
|
||||
m_rfBW[ui->rfBW->value()],
|
||||
ui->afBW->value() * 1000.0,
|
||||
ui->volume->value() / 10.0,
|
||||
|
|
|
@ -8,10 +8,8 @@ class PluginAPI;
|
|||
class ChannelMarker;
|
||||
|
||||
class AudioFifo;
|
||||
class ThreadedSampleSink;
|
||||
class Channelizer;
|
||||
class WFMDemod;
|
||||
class NullSink;
|
||||
|
||||
namespace Ui {
|
||||
class WFMDemodGUI;
|
||||
|
@ -32,7 +30,7 @@ public:
|
|||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
|
||||
bool handleMessage(Message* message);
|
||||
virtual bool handleMessage(const Message& message);
|
||||
|
||||
private slots:
|
||||
void viewChanged();
|
||||
|
@ -52,15 +50,13 @@ private:
|
|||
bool m_basicSettingsShown;
|
||||
|
||||
AudioFifo* m_audioFifo;
|
||||
ThreadedSampleSink* m_threadedSampleSink;
|
||||
Channelizer* m_channelizer;
|
||||
WFMDemod* m_wfmDemod;
|
||||
NullSink *m_nullSink;
|
||||
|
||||
static const int m_rfBW[];
|
||||
|
||||
explicit WFMDemodGUI(PluginAPI* pluginAPI, QWidget* parent = NULL);
|
||||
~WFMDemodGUI();
|
||||
virtual ~WFMDemodGUI();
|
||||
|
||||
void applySettings();
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "ui_bladerfgui.h"
|
||||
#include "plugin/pluginapi.h"
|
||||
#include "gui/colormapper.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "bladerfgui.h"
|
||||
|
||||
BladerfGui::BladerfGui(PluginAPI* pluginAPI, QWidget* parent) :
|
||||
|
@ -35,8 +36,8 @@ BladerfGui::BladerfGui(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
|
||||
displaySettings();
|
||||
|
||||
m_sampleSource = new BladerfInput(m_pluginAPI->getMainWindowMessageQueue());
|
||||
m_pluginAPI->setSampleSource(m_sampleSource);
|
||||
m_sampleSource = new BladerfInput();
|
||||
DSPEngine::instance()->setSource(m_sampleSource);
|
||||
}
|
||||
|
||||
BladerfGui::~BladerfGui()
|
||||
|
@ -61,32 +62,14 @@ QString BladerfGui::getName() const
|
|||
|
||||
void BladerfGui::resetToDefaults()
|
||||
{
|
||||
m_generalSettings.resetToDefaults();
|
||||
m_settings.resetToDefaults();
|
||||
displaySettings();
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
QByteArray BladerfGui::serializeGeneral() const
|
||||
{
|
||||
return m_generalSettings.serialize();
|
||||
}
|
||||
|
||||
bool BladerfGui::deserializeGeneral(const QByteArray&data)
|
||||
{
|
||||
if(m_generalSettings.deserialize(data)) {
|
||||
displaySettings();
|
||||
sendSettings();
|
||||
return true;
|
||||
} else {
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
qint64 BladerfGui::getCenterFrequency() const
|
||||
{
|
||||
return m_generalSettings.m_centerFrequency;
|
||||
return m_settings.m_centerFrequency;
|
||||
}
|
||||
|
||||
QByteArray BladerfGui::serialize() const
|
||||
|
@ -106,23 +89,25 @@ bool BladerfGui::deserialize(const QByteArray& data)
|
|||
}
|
||||
}
|
||||
|
||||
bool BladerfGui::handleMessage(Message* message)
|
||||
bool BladerfGui::handleMessage(const Message& message)
|
||||
{
|
||||
if(BladerfInput::MsgReportBladerf::match(message)) {
|
||||
if (BladerfInput::MsgReportBladerf::match(message))
|
||||
{
|
||||
displaySettings();
|
||||
message->completed();
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void BladerfGui::displaySettings()
|
||||
{
|
||||
ui->centerFrequency->setValue(m_generalSettings.m_centerFrequency / 1000);
|
||||
ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
|
||||
|
||||
ui->samplerateText->setText(tr("%1k").arg(m_settings.m_samplerate / 1000));
|
||||
unsigned int sampleRateIndex = BladerfSampleRates::getRateIndex(m_settings.m_samplerate);
|
||||
ui->samplerateText->setText(tr("%1k").arg(m_settings.m_devSampleRate / 1000));
|
||||
unsigned int sampleRateIndex = BladerfSampleRates::getRateIndex(m_settings.m_devSampleRate);
|
||||
ui->samplerate->setValue(sampleRateIndex);
|
||||
|
||||
ui->bandwidthText->setText(tr("%1k").arg(m_settings.m_bandwidth / 1000));
|
||||
|
@ -154,7 +139,7 @@ void BladerfGui::sendSettings()
|
|||
|
||||
void BladerfGui::on_centerFrequency_changed(quint64 value)
|
||||
{
|
||||
m_generalSettings.m_centerFrequency = value * 1000;
|
||||
m_settings.m_centerFrequency = value * 1000;
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
|
@ -162,7 +147,7 @@ void BladerfGui::on_samplerate_valueChanged(int value)
|
|||
{
|
||||
int newrate = BladerfSampleRates::getRate(value);
|
||||
ui->samplerateText->setText(tr("%1k").arg(newrate));
|
||||
m_settings.m_samplerate = newrate * 1000;
|
||||
m_settings.m_devSampleRate = newrate * 1000;
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
|
@ -291,8 +276,8 @@ void BladerfGui::on_xb200_currentIndexChanged(int index)
|
|||
|
||||
void BladerfGui::updateHardware()
|
||||
{
|
||||
BladerfInput::MsgConfigureBladerf* message = BladerfInput::MsgConfigureBladerf::create(m_generalSettings, m_settings);
|
||||
message->submit(m_pluginAPI->getDSPEngineMessageQueue());
|
||||
BladerfInput::MsgConfigureBladerf* message = BladerfInput::MsgConfigureBladerf::create( m_settings);
|
||||
m_sampleSource->getInputMessageQueue()->push(message);
|
||||
m_updateTimer.stop();
|
||||
}
|
||||
|
||||
|
|
|
@ -34,25 +34,22 @@ class BladerfGui : public QWidget, public PluginGUI {
|
|||
|
||||
public:
|
||||
explicit BladerfGui(PluginAPI* pluginAPI, QWidget* parent = NULL);
|
||||
~BladerfGui();
|
||||
virtual ~BladerfGui();
|
||||
void destroy();
|
||||
|
||||
void setName(const QString& name);
|
||||
QString getName() const;
|
||||
|
||||
void resetToDefaults();
|
||||
QByteArray serializeGeneral() const;
|
||||
bool deserializeGeneral(const QByteArray&data);
|
||||
qint64 getCenterFrequency() const;
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
bool handleMessage(Message* message);
|
||||
virtual bool handleMessage(const Message& message);
|
||||
|
||||
private:
|
||||
Ui::BladerfGui* ui;
|
||||
|
||||
PluginAPI* m_pluginAPI;
|
||||
SampleSource::GeneralSettings m_generalSettings;
|
||||
BladerfInput::Settings m_settings;
|
||||
QTimer m_updateTimer;
|
||||
std::vector<int> m_gains;
|
||||
|
|
|
@ -29,10 +29,11 @@ MESSAGE_CLASS_DEFINITION(BladerfInput::MsgConfigureBladerf, Message)
|
|||
MESSAGE_CLASS_DEFINITION(BladerfInput::MsgReportBladerf, Message)
|
||||
|
||||
BladerfInput::Settings::Settings() :
|
||||
m_centerFrequency(435000*1000),
|
||||
m_devSampleRate(3072000),
|
||||
m_lnaGain(0),
|
||||
m_vga1(20),
|
||||
m_vga2(9),
|
||||
m_samplerate(3072000),
|
||||
m_bandwidth(1500000),
|
||||
m_log2Decim(0),
|
||||
m_fcPos(FC_POS_INFRA),
|
||||
|
@ -44,10 +45,11 @@ BladerfInput::Settings::Settings() :
|
|||
|
||||
void BladerfInput::Settings::resetToDefaults()
|
||||
{
|
||||
m_centerFrequency = 435000*1000;
|
||||
m_devSampleRate = 3072000;
|
||||
m_lnaGain = 0;
|
||||
m_vga1 = 20;
|
||||
m_vga2 = 9;
|
||||
m_samplerate = 3072000;
|
||||
m_bandwidth = 1500000;
|
||||
m_log2Decim = 0;
|
||||
m_fcPos = FC_POS_INFRA;
|
||||
|
@ -59,16 +61,17 @@ void BladerfInput::Settings::resetToDefaults()
|
|||
QByteArray BladerfInput::Settings::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
s.writeS32(1, m_lnaGain);
|
||||
s.writeS32(2, m_vga1);
|
||||
s.writeS32(3, m_vga2);
|
||||
s.writeS32(4, m_samplerate);
|
||||
s.writeU32(5, m_log2Decim);
|
||||
s.writeBool(6, m_xb200);
|
||||
s.writeS32(7, (int) m_xb200Path);
|
||||
s.writeS32(8, (int) m_xb200Filter);
|
||||
s.writeS32(9, m_bandwidth);
|
||||
s.writeS32(10, (int) m_fcPos);
|
||||
s.writeU64(1, m_centerFrequency);
|
||||
s.writeS32(2, m_devSampleRate);
|
||||
s.writeS32(3, m_lnaGain);
|
||||
s.writeS32(4, m_vga1);
|
||||
s.writeS32(5, m_vga2);
|
||||
s.writeU32(6, m_log2Decim);
|
||||
s.writeBool(7, m_xb200);
|
||||
s.writeS32(8, (int) m_xb200Path);
|
||||
s.writeS32(9, (int) m_xb200Filter);
|
||||
s.writeS32(10, m_bandwidth);
|
||||
s.writeS32(11, (int) m_fcPos);
|
||||
return s.final();
|
||||
}
|
||||
|
||||
|
@ -76,63 +79,75 @@ bool BladerfInput::Settings::deserialize(const QByteArray& data)
|
|||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if(!d.isValid()) {
|
||||
if (!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.getVersion() == 1) {
|
||||
if (d.getVersion() == 1)
|
||||
{
|
||||
int intval;
|
||||
d.readS32(1, &m_lnaGain, 0);
|
||||
d.readS32(2, &m_vga1, 20);
|
||||
d.readS32(3, &m_vga2, 9);
|
||||
d.readS32(4, &m_samplerate, 0);
|
||||
d.readU32(5, &m_log2Decim, 0);
|
||||
d.readBool(6, &m_xb200);
|
||||
d.readS32(7, &intval);
|
||||
m_xb200Path = (bladerf_xb200_path) intval;
|
||||
d.readU64(1, &m_centerFrequency, 435000*1000);
|
||||
d.readS32(2, &m_devSampleRate, 3072000);
|
||||
d.readS32(3, &m_lnaGain, 0);
|
||||
d.readS32(4, &m_vga1, 20);
|
||||
d.readS32(5, &m_vga2, 9);
|
||||
d.readU32(6, &m_log2Decim, 0);
|
||||
d.readBool(7, &m_xb200);
|
||||
d.readS32(8, &intval);
|
||||
m_xb200Path = (bladerf_xb200_path) intval;
|
||||
d.readS32(9, &intval);
|
||||
m_xb200Filter = (bladerf_xb200_filter) intval;
|
||||
d.readS32(9, &m_bandwidth, 0);
|
||||
d.readS32(10, &intval, 0);
|
||||
d.readS32(10, &m_bandwidth, 0);
|
||||
d.readS32(11, &intval, 0);
|
||||
m_fcPos = (fcPos_t) intval;
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
BladerfInput::BladerfInput(MessageQueue* msgQueueToGUI) :
|
||||
SampleSource(msgQueueToGUI),
|
||||
BladerfInput::BladerfInput() :
|
||||
m_settings(),
|
||||
m_dev(NULL),
|
||||
m_bladerfThread(NULL),
|
||||
m_dev(0),
|
||||
m_bladerfThread(0),
|
||||
m_deviceDescription("BladeRF")
|
||||
{
|
||||
}
|
||||
|
||||
BladerfInput::~BladerfInput()
|
||||
{
|
||||
stopInput();
|
||||
stop();
|
||||
}
|
||||
|
||||
bool BladerfInput::startInput(int device)
|
||||
bool BladerfInput::init(const Message& cmd)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BladerfInput::start(int device)
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if(m_dev != NULL)
|
||||
stopInput();
|
||||
if (m_dev != 0)
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
int res;
|
||||
int fpga_loaded;
|
||||
|
||||
if(!m_sampleFifo.setSize(96000 * 4)) {
|
||||
if (!m_sampleFifo.setSize(96000 * 4))
|
||||
{
|
||||
qCritical("Could not allocate SampleFifo");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((m_dev = open_bladerf_from_serial(0)) == NULL) // TODO: fix; Open first available device as there is no proper handling for multiple devices
|
||||
if ((m_dev = open_bladerf_from_serial(0)) == 0) // TODO: fix; Open first available device as there is no proper handling for multiple devices
|
||||
{
|
||||
qCritical("could not open BladeRF");
|
||||
return false;
|
||||
|
@ -140,11 +155,14 @@ bool BladerfInput::startInput(int device)
|
|||
|
||||
fpga_loaded = bladerf_is_fpga_configured(m_dev);
|
||||
|
||||
if (fpga_loaded < 0) {
|
||||
if (fpga_loaded < 0)
|
||||
{
|
||||
qCritical("Failed to check FPGA state: %s",
|
||||
bladerf_strerror(fpga_loaded));
|
||||
return false;
|
||||
} else if (fpga_loaded == 0) {
|
||||
}
|
||||
else if (fpga_loaded == 0)
|
||||
{
|
||||
qCritical("The device's FPGA is not loaded.");
|
||||
return false;
|
||||
}
|
||||
|
@ -170,31 +188,34 @@ bool BladerfInput::startInput(int device)
|
|||
m_bladerfThread->startWork();
|
||||
|
||||
mutexLocker.unlock();
|
||||
applySettings(m_generalSettings, m_settings, true);
|
||||
applySettings(m_settings, true);
|
||||
|
||||
qDebug("BladerfInput::startInput: started");
|
||||
//MsgReportBladerf::create(m_gains)->submit(m_guiMessageQueue); Pass anything here
|
||||
|
||||
return true;
|
||||
|
||||
failed:
|
||||
stopInput();
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
void BladerfInput::stopInput()
|
||||
void BladerfInput::stop()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if(m_bladerfThread != NULL) {
|
||||
if(m_bladerfThread != 0)
|
||||
{
|
||||
m_bladerfThread->stopWork();
|
||||
delete m_bladerfThread;
|
||||
m_bladerfThread = NULL;
|
||||
m_bladerfThread = 0;
|
||||
}
|
||||
if(m_dev != NULL) {
|
||||
|
||||
if(m_dev != 0)
|
||||
{
|
||||
bladerf_close(m_dev);
|
||||
m_dev = NULL;
|
||||
m_dev = 0;
|
||||
}
|
||||
|
||||
m_deviceDescription.clear();
|
||||
}
|
||||
|
||||
|
@ -205,28 +226,28 @@ const QString& BladerfInput::getDeviceDescription() const
|
|||
|
||||
int BladerfInput::getSampleRate() const
|
||||
{
|
||||
int rate = m_settings.m_samplerate;
|
||||
int rate = m_settings.m_devSampleRate;
|
||||
return (rate / (1<<m_settings.m_log2Decim));
|
||||
}
|
||||
|
||||
quint64 BladerfInput::getCenterFrequency() const
|
||||
{
|
||||
return m_generalSettings.m_centerFrequency;
|
||||
return m_settings.m_centerFrequency;
|
||||
}
|
||||
|
||||
bool BladerfInput::handleMessage(Message* message)
|
||||
bool BladerfInput::handleMessage(const Message& message)
|
||||
{
|
||||
if (MsgConfigureBladerf::match(message))
|
||||
{
|
||||
qDebug() << "BladerfInput::handleMessage: MsgConfigureBladerf";
|
||||
|
||||
MsgConfigureBladerf* conf = (MsgConfigureBladerf*) message;
|
||||
MsgConfigureBladerf& conf = (MsgConfigureBladerf&) message;
|
||||
|
||||
if(!applySettings(conf->getGeneralSettings(), conf->getSettings(), false)) {
|
||||
if (!applySettings(conf.getSettings(), false))
|
||||
{
|
||||
qDebug("BladeRF config error");
|
||||
}
|
||||
|
||||
message->completed();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -235,7 +256,7 @@ bool BladerfInput::handleMessage(Message* message)
|
|||
}
|
||||
}
|
||||
|
||||
bool BladerfInput::applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force)
|
||||
bool BladerfInput::applySettings(const Settings& settings, bool force)
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
|
@ -245,11 +266,14 @@ bool BladerfInput::applySettings(const GeneralSettings& generalSettings, const S
|
|||
{
|
||||
m_settings.m_lnaGain = settings.m_lnaGain;
|
||||
|
||||
if (m_dev != NULL)
|
||||
if (m_dev != 0)
|
||||
{
|
||||
if(bladerf_set_lna_gain(m_dev, getLnaGain(m_settings.m_lnaGain)) != 0) {
|
||||
if(bladerf_set_lna_gain(m_dev, getLnaGain(m_settings.m_lnaGain)) != 0)
|
||||
{
|
||||
qDebug("bladerf_set_lna_gain() failed");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "BladerfInput: LNA gain set to " << getLnaGain(m_settings.m_lnaGain);
|
||||
}
|
||||
}
|
||||
|
@ -259,11 +283,14 @@ bool BladerfInput::applySettings(const GeneralSettings& generalSettings, const S
|
|||
{
|
||||
m_settings.m_vga1 = settings.m_vga1;
|
||||
|
||||
if (m_dev != NULL)
|
||||
if (m_dev != 0)
|
||||
{
|
||||
if(bladerf_set_rxvga1(m_dev, m_settings.m_vga1) != 0) {
|
||||
if(bladerf_set_rxvga1(m_dev, m_settings.m_vga1) != 0)
|
||||
{
|
||||
qDebug("bladerf_set_rxvga1() failed");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "BladerfInput: VGA1 gain set to " << m_settings.m_vga1;
|
||||
}
|
||||
}
|
||||
|
@ -273,11 +300,14 @@ bool BladerfInput::applySettings(const GeneralSettings& generalSettings, const S
|
|||
{
|
||||
m_settings.m_vga2 = settings.m_vga2;
|
||||
|
||||
if(m_dev != NULL)
|
||||
if(m_dev != 0)
|
||||
{
|
||||
if(bladerf_set_rxvga2(m_dev, m_settings.m_vga2) != 0) {
|
||||
if(bladerf_set_rxvga2(m_dev, m_settings.m_vga2) != 0)
|
||||
{
|
||||
qDebug("bladerf_set_rxvga2() failed");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "BladerfInput: VGA2 gain set to " << m_settings.m_vga2;
|
||||
}
|
||||
}
|
||||
|
@ -287,21 +317,27 @@ bool BladerfInput::applySettings(const GeneralSettings& generalSettings, const S
|
|||
{
|
||||
m_settings.m_xb200 = settings.m_xb200;
|
||||
|
||||
if (m_dev != NULL)
|
||||
if (m_dev != 0)
|
||||
{
|
||||
if (m_settings.m_xb200)
|
||||
{
|
||||
if (bladerf_expansion_attach(m_dev, BLADERF_XB_200) != 0) {
|
||||
if (bladerf_expansion_attach(m_dev, BLADERF_XB_200) != 0)
|
||||
{
|
||||
qDebug("bladerf_expansion_attach(xb200) failed");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "BladerfInput: Attach XB200";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bladerf_expansion_attach(m_dev, BLADERF_XB_NONE) != 0) {
|
||||
if (bladerf_expansion_attach(m_dev, BLADERF_XB_NONE) != 0)
|
||||
{
|
||||
qDebug("bladerf_expansion_attach(none) failed");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "BladerfInput: Detach XB200";
|
||||
}
|
||||
}
|
||||
|
@ -311,11 +347,15 @@ bool BladerfInput::applySettings(const GeneralSettings& generalSettings, const S
|
|||
if ((m_settings.m_xb200Path != settings.m_xb200Path) || force)
|
||||
{
|
||||
m_settings.m_xb200Path = settings.m_xb200Path;
|
||||
if (m_dev != NULL)
|
||||
|
||||
if (m_dev != 0)
|
||||
{
|
||||
if(bladerf_xb200_set_path(m_dev, BLADERF_MODULE_RX, m_settings.m_xb200Path) != 0) {
|
||||
if(bladerf_xb200_set_path(m_dev, BLADERF_MODULE_RX, m_settings.m_xb200Path) != 0)
|
||||
{
|
||||
qDebug("bladerf_xb200_set_path(BLADERF_MODULE_RX) failed");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "BladerfInput: set xb200 path to " << m_settings.m_xb200Path;
|
||||
}
|
||||
}
|
||||
|
@ -325,32 +365,35 @@ bool BladerfInput::applySettings(const GeneralSettings& generalSettings, const S
|
|||
{
|
||||
m_settings.m_xb200Filter = settings.m_xb200Filter;
|
||||
|
||||
if(m_dev != NULL)
|
||||
if (m_dev != 0)
|
||||
{
|
||||
if(bladerf_xb200_set_filterbank(m_dev, BLADERF_MODULE_RX, m_settings.m_xb200Filter) != 0) {
|
||||
if(bladerf_xb200_set_filterbank(m_dev, BLADERF_MODULE_RX, m_settings.m_xb200Filter) != 0)
|
||||
{
|
||||
qDebug("bladerf_xb200_set_filterbank(BLADERF_MODULE_RX) failed");
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "BladerfInput: set xb200 filter to " << m_settings.m_xb200Filter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_settings.m_samplerate != settings.m_samplerate) || force)
|
||||
if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force)
|
||||
{
|
||||
m_settings.m_samplerate = settings.m_samplerate;
|
||||
m_settings.m_devSampleRate = settings.m_devSampleRate;
|
||||
|
||||
if (m_dev != NULL)
|
||||
if (m_dev != 0)
|
||||
{
|
||||
unsigned int actualSamplerate;
|
||||
|
||||
if (bladerf_set_sample_rate(m_dev, BLADERF_MODULE_RX, m_settings.m_samplerate, &actualSamplerate) < 0)
|
||||
if (bladerf_set_sample_rate(m_dev, BLADERF_MODULE_RX, m_settings.m_devSampleRate, &actualSamplerate) < 0)
|
||||
{
|
||||
qCritical("could not set sample rate: %d", m_settings.m_samplerate);
|
||||
qCritical("could not set sample rate: %d", m_settings.m_devSampleRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "bladerf_set_sample_rate(BLADERF_MODULE_RX) actual sample rate is " << actualSamplerate;
|
||||
m_bladerfThread->setSamplerate(m_settings.m_samplerate);
|
||||
m_bladerfThread->setSamplerate(m_settings.m_devSampleRate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -359,13 +402,16 @@ bool BladerfInput::applySettings(const GeneralSettings& generalSettings, const S
|
|||
{
|
||||
m_settings.m_bandwidth = settings.m_bandwidth;
|
||||
|
||||
if(m_dev != NULL)
|
||||
if(m_dev != 0)
|
||||
{
|
||||
unsigned int actualBandwidth;
|
||||
|
||||
if( bladerf_set_bandwidth(m_dev, BLADERF_MODULE_RX, m_settings.m_bandwidth, &actualBandwidth) < 0)
|
||||
qCritical("could not set sample rate: %d", m_settings.m_samplerate);
|
||||
else {
|
||||
{
|
||||
qCritical("could not set bandwidth: %d", m_settings.m_bandwidth);
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug() << "bladerf_set_bandwidth(BLADERF_MODULE_RX) actual bandwidth is " << actualBandwidth;
|
||||
}
|
||||
}
|
||||
|
@ -375,7 +421,7 @@ bool BladerfInput::applySettings(const GeneralSettings& generalSettings, const S
|
|||
{
|
||||
m_settings.m_log2Decim = settings.m_log2Decim;
|
||||
|
||||
if(m_dev != NULL)
|
||||
if(m_dev != 0)
|
||||
{
|
||||
m_bladerfThread->setLog2Decimation(m_settings.m_log2Decim);
|
||||
qDebug() << "BladerfInput: set decimation to " << (1<<m_settings.m_log2Decim);
|
||||
|
@ -386,22 +432,22 @@ bool BladerfInput::applySettings(const GeneralSettings& generalSettings, const S
|
|||
{
|
||||
m_settings.m_fcPos = settings.m_fcPos;
|
||||
|
||||
if(m_dev != NULL)
|
||||
if(m_dev != 0)
|
||||
{
|
||||
m_bladerfThread->setFcPos((int) m_settings.m_fcPos);
|
||||
qDebug() << "BladerfInput: set fc pos (enum) to " << (int) m_settings.m_fcPos;
|
||||
}
|
||||
}
|
||||
|
||||
m_generalSettings.m_centerFrequency = generalSettings.m_centerFrequency;
|
||||
m_settings.m_centerFrequency = settings.m_centerFrequency;
|
||||
|
||||
qint64 centerFrequency = m_generalSettings.m_centerFrequency;
|
||||
qint64 centerFrequency = m_settings.m_centerFrequency;
|
||||
qint64 f_img = centerFrequency;
|
||||
qint64 f_cut = centerFrequency + m_settings.m_bandwidth/2;
|
||||
|
||||
if ((m_settings.m_log2Decim == 0) || (m_settings.m_fcPos == FC_POS_CENTER))
|
||||
{
|
||||
centerFrequency = m_generalSettings.m_centerFrequency;
|
||||
centerFrequency = m_settings.m_centerFrequency;
|
||||
f_img = centerFrequency;
|
||||
f_cut = centerFrequency + m_settings.m_bandwidth/2;
|
||||
}
|
||||
|
@ -409,29 +455,30 @@ bool BladerfInput::applySettings(const GeneralSettings& generalSettings, const S
|
|||
{
|
||||
if (m_settings.m_fcPos == FC_POS_INFRA)
|
||||
{
|
||||
centerFrequency = m_generalSettings.m_centerFrequency + (m_settings.m_samplerate / 4);
|
||||
f_img = centerFrequency + m_settings.m_samplerate/2;
|
||||
centerFrequency = m_settings.m_centerFrequency + (m_settings.m_devSampleRate / 4);
|
||||
f_img = centerFrequency + m_settings.m_devSampleRate/2;
|
||||
f_cut = centerFrequency + m_settings.m_bandwidth/2;
|
||||
}
|
||||
else if (m_settings.m_fcPos == FC_POS_SUPRA)
|
||||
{
|
||||
centerFrequency = m_generalSettings.m_centerFrequency - (m_settings.m_samplerate / 4);
|
||||
f_img = centerFrequency - m_settings.m_samplerate/2;
|
||||
centerFrequency = m_settings.m_centerFrequency - (m_settings.m_devSampleRate / 4);
|
||||
f_img = centerFrequency - m_settings.m_devSampleRate/2;
|
||||
f_cut = centerFrequency - m_settings.m_bandwidth/2;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_dev != NULL)
|
||||
{
|
||||
if (bladerf_set_frequency( m_dev, BLADERF_MODULE_RX, centerFrequency ) != 0) {
|
||||
qDebug("bladerf_set_frequency(%lld) failed", m_generalSettings.m_centerFrequency);
|
||||
if (bladerf_set_frequency( m_dev, BLADERF_MODULE_RX, centerFrequency ) != 0)
|
||||
{
|
||||
qDebug("bladerf_set_frequency(%lld) failed", m_settings.m_centerFrequency);
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << " - center freq: " << m_generalSettings.m_centerFrequency << " Hz"
|
||||
qDebug() << " - center freq: " << m_settings.m_centerFrequency << " Hz"
|
||||
<< " RF center freq: " << centerFrequency << " Hz"
|
||||
<< " RF sample rate: " << m_settings.m_samplerate << "Hz"
|
||||
<< " Actual sample rate: " << m_settings.m_samplerate/(1<<m_settings.m_log2Decim) << "Hz"
|
||||
<< " RF sample rate: " << m_settings.m_devSampleRate << "Hz"
|
||||
<< " Actual sample rate: " << m_settings.m_devSampleRate/(1<<m_settings.m_log2Decim) << "Hz"
|
||||
<< " BW: " << m_settings.m_bandwidth << "Hz"
|
||||
<< " img: " << f_img << "Hz"
|
||||
<< " cut: " << f_cut << "Hz"
|
||||
|
@ -442,11 +489,16 @@ bool BladerfInput::applySettings(const GeneralSettings& generalSettings, const S
|
|||
|
||||
bladerf_lna_gain BladerfInput::getLnaGain(int lnaGain)
|
||||
{
|
||||
if (lnaGain == 2) {
|
||||
if (lnaGain == 2)
|
||||
{
|
||||
return BLADERF_LNA_GAIN_MAX;
|
||||
} else if (lnaGain == 1) {
|
||||
}
|
||||
else if (lnaGain == 1)
|
||||
{
|
||||
return BLADERF_LNA_GAIN_MID;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return BLADERF_LNA_GAIN_BYPASS;
|
||||
}
|
||||
}
|
||||
|
@ -465,21 +517,27 @@ struct bladerf *BladerfInput::open_bladerf_from_serial(const char *serial)
|
|||
|
||||
/* Specify the desired device's serial number, while leaving all other
|
||||
* fields in the info structure wildcard values */
|
||||
if (serial != NULL) {
|
||||
if (serial != NULL)
|
||||
{
|
||||
strncpy(info.serial, serial, BLADERF_SERIAL_LENGTH - 1);
|
||||
info.serial[BLADERF_SERIAL_LENGTH - 1] = '\0';
|
||||
}
|
||||
|
||||
status = bladerf_open_with_devinfo(&dev, &info);
|
||||
|
||||
if (status == BLADERF_ERR_NODEV) {
|
||||
if (status == BLADERF_ERR_NODEV)
|
||||
{
|
||||
fprintf(stderr, "No devices available with serial=%s\n", serial);
|
||||
return NULL;
|
||||
} else if (status != 0) {
|
||||
}
|
||||
else if (status != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to open device with serial=%s (%s)\n",
|
||||
serial, bladerf_strerror(status));
|
||||
return NULL;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return dev;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,10 +32,11 @@ public:
|
|||
} fcPos_t;
|
||||
|
||||
struct Settings {
|
||||
quint64 m_centerFrequency;
|
||||
qint32 m_devSampleRate;
|
||||
qint32 m_lnaGain;
|
||||
qint32 m_vga1;
|
||||
qint32 m_vga2;
|
||||
qint32 m_samplerate;
|
||||
qint32 m_bandwidth;
|
||||
quint32 m_log2Decim;
|
||||
fcPos_t m_fcPos;
|
||||
|
@ -53,21 +54,18 @@ public:
|
|||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
const GeneralSettings& getGeneralSettings() const { return m_generalSettings; }
|
||||
const Settings& getSettings() const { return m_settings; }
|
||||
|
||||
static MsgConfigureBladerf* create(const GeneralSettings& generalSettings, const Settings& settings)
|
||||
static MsgConfigureBladerf* create(const Settings& settings)
|
||||
{
|
||||
return new MsgConfigureBladerf(generalSettings, settings);
|
||||
return new MsgConfigureBladerf(settings);
|
||||
}
|
||||
|
||||
private:
|
||||
GeneralSettings m_generalSettings;
|
||||
Settings m_settings;
|
||||
|
||||
MsgConfigureBladerf(const GeneralSettings& generalSettings, const Settings& settings) :
|
||||
MsgConfigureBladerf(const Settings& settings) :
|
||||
Message(),
|
||||
m_generalSettings(generalSettings),
|
||||
m_settings(settings)
|
||||
{ }
|
||||
};
|
||||
|
@ -89,28 +87,29 @@ public:
|
|||
{ }
|
||||
};
|
||||
|
||||
BladerfInput(MessageQueue* msgQueueToGUI);
|
||||
~BladerfInput();
|
||||
BladerfInput();
|
||||
virtual ~BladerfInput();
|
||||
|
||||
bool startInput(int device);
|
||||
void stopInput();
|
||||
virtual bool init(const Message& message);
|
||||
virtual bool start(int device);
|
||||
virtual void stop();
|
||||
|
||||
const QString& getDeviceDescription() const;
|
||||
int getSampleRate() const;
|
||||
quint64 getCenterFrequency() const;
|
||||
virtual const QString& getDeviceDescription() const;
|
||||
virtual int getSampleRate() const;
|
||||
virtual quint64 getCenterFrequency() const;
|
||||
|
||||
bool handleMessage(Message* message);
|
||||
virtual bool handleMessage(const Message& message);
|
||||
|
||||
private:
|
||||
bool applySettings(const Settings& settings, bool force);
|
||||
bladerf_lna_gain getLnaGain(int lnaGain);
|
||||
struct bladerf *open_bladerf_from_serial(const char *serial);
|
||||
|
||||
QMutex m_mutex;
|
||||
Settings m_settings;
|
||||
struct bladerf* m_dev;
|
||||
BladerfThread* m_bladerfThread;
|
||||
QString m_deviceDescription;
|
||||
|
||||
bool applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force);
|
||||
bladerf_lna_gain getLnaGain(int lnaGain);
|
||||
struct bladerf *open_bladerf_from_serial(const char *serial);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_BLADERFINPUT_H
|
||||
|
|
|
@ -5,7 +5,6 @@ set(fcd_SOURCES
|
|||
fcdinput.cpp
|
||||
fcdplugin.cpp
|
||||
fcdthread.cpp
|
||||
fcdsource.cpp
|
||||
hid-libusb.c
|
||||
)
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "fcdgui.h"
|
||||
#include "ui_fcdgui.h"
|
||||
#include "plugin/pluginapi.h"
|
||||
#include "dsp/dspengine.h"
|
||||
|
||||
FCDGui::FCDGui(PluginAPI* pluginAPI, QWidget* parent) :
|
||||
QWidget(parent),
|
||||
|
@ -14,8 +15,8 @@ FCDGui::FCDGui(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
|
||||
displaySettings();
|
||||
|
||||
m_sampleSource = new FCDInput(m_pluginAPI->getMainWindowMessageQueue());
|
||||
m_pluginAPI->setSampleSource(m_sampleSource);
|
||||
m_sampleSource = new FCDInput();
|
||||
DSPEngine::instance()->setSource(m_sampleSource);
|
||||
}
|
||||
|
||||
FCDGui::~FCDGui()
|
||||
|
@ -40,34 +41,11 @@ QString FCDGui::getName() const
|
|||
|
||||
void FCDGui::resetToDefaults()
|
||||
{
|
||||
m_generalSettings.resetToDefaults();
|
||||
m_settings.resetToDefaults();
|
||||
displaySettings();
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
QByteArray FCDGui::serializeGeneral() const
|
||||
{
|
||||
return m_generalSettings.serialize();
|
||||
}
|
||||
|
||||
bool FCDGui::deserializeGeneral(const QByteArray&data)
|
||||
{
|
||||
if(m_generalSettings.deserialize(data)) {
|
||||
displaySettings();
|
||||
sendSettings();
|
||||
return true;
|
||||
} else {
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
qint64 FCDGui::getCenterFrequency() const
|
||||
{
|
||||
return m_generalSettings.m_centerFrequency;
|
||||
}
|
||||
|
||||
QByteArray FCDGui::serialize() const
|
||||
{
|
||||
return m_settings.serialize();
|
||||
|
@ -75,24 +53,27 @@ QByteArray FCDGui::serialize() const
|
|||
|
||||
bool FCDGui::deserialize(const QByteArray& data)
|
||||
{
|
||||
if(m_settings.deserialize(data)) {
|
||||
if(m_settings.deserialize(data))
|
||||
{
|
||||
displaySettings();
|
||||
sendSettings();
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FCDGui::handleMessage(Message* message)
|
||||
bool FCDGui::handleMessage(const Message& message)
|
||||
{
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void FCDGui::displaySettings()
|
||||
{
|
||||
ui->centerFrequency->setValue(m_generalSettings.m_centerFrequency / 1000);
|
||||
ui->centerFrequency->setValue(m_settings.centerFrequency / 1000);
|
||||
ui->checkBoxR->setChecked(m_settings.range);
|
||||
ui->checkBoxG->setChecked(m_settings.gain);
|
||||
ui->checkBoxB->setChecked(m_settings.bias);
|
||||
|
@ -106,49 +87,61 @@ void FCDGui::sendSettings()
|
|||
|
||||
void FCDGui::on_centerFrequency_changed(quint64 value)
|
||||
{
|
||||
m_generalSettings.m_centerFrequency = value * 1000;
|
||||
m_settings.centerFrequency = value * 1000;
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void FCDGui::updateHardware()
|
||||
{
|
||||
FCDInput::MsgConfigureFCD* message = FCDInput::MsgConfigureFCD::create(m_generalSettings, m_settings);
|
||||
message->submit(m_pluginAPI->getDSPEngineMessageQueue());
|
||||
FCDInput::MsgConfigureFCD* message = FCDInput::MsgConfigureFCD::create(m_settings);
|
||||
m_sampleSource->getInputMessageQueue()->push(message);
|
||||
m_updateTimer.stop();
|
||||
}
|
||||
|
||||
void FCDGui::on_checkBoxR_stateChanged(int state)
|
||||
{
|
||||
if (state == Qt::Checked) {
|
||||
if (state == Qt::Checked)
|
||||
{
|
||||
ui->centerFrequency->setValueRange(7, 150U, 240000U);
|
||||
ui->centerFrequency->setValue(7000);
|
||||
m_generalSettings.m_centerFrequency = 7000 * 1000;
|
||||
m_settings.centerFrequency = 7000 * 1000;
|
||||
m_settings.range = 1;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
ui->centerFrequency->setValueRange(7, 420000U, 1900000U);
|
||||
ui->centerFrequency->setValue(434450);
|
||||
m_generalSettings.m_centerFrequency = 434450 * 1000;
|
||||
ui->centerFrequency->setValue(435000);
|
||||
m_settings.centerFrequency = 435000 * 1000;
|
||||
m_settings.range = 0;
|
||||
}
|
||||
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void FCDGui::on_checkBoxG_stateChanged(int state)
|
||||
{
|
||||
if (state == Qt::Checked) {
|
||||
if (state == Qt::Checked)
|
||||
{
|
||||
m_settings.gain = 1;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings.gain = 0;
|
||||
}
|
||||
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void FCDGui::on_checkBoxB_stateChanged(int state)
|
||||
{
|
||||
if (state == Qt::Checked) {
|
||||
if (state == Qt::Checked)
|
||||
{
|
||||
m_settings.bias = 1;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings.bias = 0;
|
||||
}
|
||||
|
||||
sendSettings();
|
||||
}
|
||||
|
|
|
@ -16,25 +16,22 @@ class FCDGui : public QWidget, public PluginGUI {
|
|||
|
||||
public:
|
||||
explicit FCDGui(PluginAPI* pluginAPI, QWidget* parent = NULL);
|
||||
~FCDGui();
|
||||
virtual ~FCDGui();
|
||||
void destroy();
|
||||
|
||||
void setName(const QString& name);
|
||||
QString getName() const;
|
||||
|
||||
void resetToDefaults();
|
||||
QByteArray serializeGeneral() const;
|
||||
bool deserializeGeneral(const QByteArray&data);
|
||||
qint64 getCenterFrequency() const;
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
bool handleMessage(Message* message);
|
||||
|
||||
virtual bool handleMessage(const Message& message);
|
||||
|
||||
private:
|
||||
Ui::FCDGui* ui;
|
||||
|
||||
PluginAPI* m_pluginAPI;
|
||||
SampleSource::GeneralSettings m_generalSettings;
|
||||
FCDInput::Settings m_settings;
|
||||
QTimer m_updateTimer;
|
||||
std::vector<int> m_gains;
|
||||
|
|
|
@ -20,12 +20,14 @@
|
|||
#include "fcdinput.h"
|
||||
#include "fcdthread.h"
|
||||
#include "fcdgui.h"
|
||||
#include "qthid.h"
|
||||
#include "util/simpleserializer.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(FCDInput::MsgConfigureFCD, Message)
|
||||
//MESSAGE_CLASS_DEFINITION(FCDInput::MsgReportFCD, Message)
|
||||
|
||||
FCDInput::Settings::Settings() :
|
||||
centerFrequency(435000000),
|
||||
range(0),
|
||||
gain(0),
|
||||
bias(0)
|
||||
|
@ -34,6 +36,7 @@ FCDInput::Settings::Settings() :
|
|||
|
||||
void FCDInput::Settings::resetToDefaults()
|
||||
{
|
||||
centerFrequency = 435000000;
|
||||
range = 0;
|
||||
gain = 0;
|
||||
bias = 0;
|
||||
|
@ -42,75 +45,92 @@ void FCDInput::Settings::resetToDefaults()
|
|||
QByteArray FCDInput::Settings::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
s.writeS32(1, range);
|
||||
s.writeS32(2, gain);
|
||||
s.writeS32(3, bias);
|
||||
s.writeU64(1, centerFrequency);
|
||||
s.writeS32(2, range);
|
||||
s.writeS32(3, gain);
|
||||
s.writeS32(4, bias);
|
||||
return s.final();
|
||||
}
|
||||
|
||||
bool FCDInput::Settings::deserialize(const QByteArray& data)
|
||||
{
|
||||
SimpleDeserializer d(data);
|
||||
if(d.isValid() && d.getVersion() == 1) {
|
||||
d.readS32(1, &range, 0);
|
||||
d.readS32(2, &gain, 0);
|
||||
d.readS32(3, &bias, 0);
|
||||
|
||||
if (d.isValid() && d.getVersion() == 1)
|
||||
{
|
||||
d.readU64(1, ¢erFrequency, 435000000);
|
||||
d.readS32(2, &range, 0);
|
||||
d.readS32(3, &gain, 0);
|
||||
d.readS32(4, &bias, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
resetToDefaults();
|
||||
return true;
|
||||
}
|
||||
|
||||
FCDInput::FCDInput(MessageQueue* msgQueueToGUI) :
|
||||
SampleSource(msgQueueToGUI),
|
||||
FCDInput::FCDInput() :
|
||||
m_settings(),
|
||||
m_FCDThread(NULL),
|
||||
m_FCDThread(0),
|
||||
m_deviceDescription()
|
||||
{
|
||||
}
|
||||
|
||||
FCDInput::~FCDInput()
|
||||
{
|
||||
stopInput();
|
||||
stop();
|
||||
}
|
||||
|
||||
bool FCDInput::startInput(int device)
|
||||
bool FCDInput::init(const Message& cmd)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FCDInput::start(int device)
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if(m_FCDThread)
|
||||
if (m_FCDThread)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Apply settings before streaming to avoid bus contention;
|
||||
* there is very little spare bandwidth on a full speed USB device.
|
||||
* Failure is harmless if no device is found */
|
||||
applySettings(m_generalSettings, m_settings, true);
|
||||
|
||||
if(!m_sampleFifo.setSize(4096*16)) {
|
||||
applySettings(m_settings, true);
|
||||
|
||||
if(!m_sampleFifo.setSize(4096*16))
|
||||
{
|
||||
qCritical("Could not allocate SampleFifo");
|
||||
return false;
|
||||
}
|
||||
|
||||
if((m_FCDThread = new FCDThread(&m_sampleFifo)) == NULL) {
|
||||
if ((m_FCDThread = new FCDThread(&m_sampleFifo)) == NULL)
|
||||
{
|
||||
qFatal("out of memory");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_deviceDescription = QString("Funcube Dongle");
|
||||
|
||||
qDebug("FCDInput: start");
|
||||
qDebug("FCDInput::start");
|
||||
return true;
|
||||
}
|
||||
|
||||
void FCDInput::stopInput()
|
||||
void FCDInput::stop()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if(m_FCDThread) {
|
||||
if (m_FCDThread)
|
||||
{
|
||||
m_FCDThread->stopWork();
|
||||
// wait for thread to quit ?
|
||||
delete m_FCDThread;
|
||||
m_FCDThread = NULL;
|
||||
m_FCDThread = 0;
|
||||
}
|
||||
|
||||
m_deviceDescription.clear();
|
||||
}
|
||||
|
||||
|
@ -121,45 +141,66 @@ const QString& FCDInput::getDeviceDescription() const
|
|||
|
||||
int FCDInput::getSampleRate() const
|
||||
{
|
||||
return 192000;
|
||||
return 96000;
|
||||
}
|
||||
|
||||
quint64 FCDInput::getCenterFrequency() const
|
||||
{
|
||||
return m_generalSettings.m_centerFrequency;
|
||||
return m_settings.centerFrequency;
|
||||
}
|
||||
|
||||
bool FCDInput::handleMessage(Message* message)
|
||||
bool FCDInput::handleMessage(const Message& message)
|
||||
{
|
||||
if(MsgConfigureFCD::match(message)) {
|
||||
MsgConfigureFCD* conf = (MsgConfigureFCD*)message;
|
||||
applySettings(conf->getGeneralSettings(), conf->getSettings(), false);
|
||||
message->completed();
|
||||
if(MsgConfigureFCD::match(message))
|
||||
{
|
||||
MsgConfigureFCD& conf = (MsgConfigureFCD&) message;
|
||||
applySettings(conf.getSettings(), false);
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void FCDInput::applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force)
|
||||
void FCDInput::applySettings(const Settings& settings, bool force)
|
||||
{
|
||||
bool freqChange;
|
||||
bool sampleSourcChange = false;
|
||||
|
||||
if((m_generalSettings.m_centerFrequency != generalSettings.m_centerFrequency))
|
||||
freqChange = true;
|
||||
else
|
||||
freqChange = false;
|
||||
|
||||
if(freqChange || force) {
|
||||
m_generalSettings.m_centerFrequency = generalSettings.m_centerFrequency;
|
||||
set_center_freq( (double)(generalSettings.m_centerFrequency) );
|
||||
if ((m_settings.centerFrequency != settings.centerFrequency))
|
||||
{
|
||||
m_settings.centerFrequency = settings.centerFrequency;
|
||||
set_center_freq((double) m_settings.centerFrequency);
|
||||
sampleSourcChange = true;
|
||||
}
|
||||
|
||||
if(!freqChange || force) {
|
||||
set_lna_gain(settings.gain);
|
||||
set_bias_t(settings.bias);
|
||||
if (!sampleSourcChange || force)
|
||||
{
|
||||
set_lna_gain(settings.gain > 0);
|
||||
set_bias_t(settings.bias > 0);
|
||||
}
|
||||
}
|
||||
|
||||
void FCDInput::set_center_freq(double freq)
|
||||
{
|
||||
if (fcdAppSetFreq(freq) == FCD_MODE_NONE)
|
||||
{
|
||||
qDebug("No FCD HID found for frquency change");
|
||||
}
|
||||
}
|
||||
|
||||
void FCDInput::set_bias_t(bool on)
|
||||
{
|
||||
quint8 cmd = on ? 1 : 0;
|
||||
|
||||
fcdAppSetParam(FCD_CMD_APP_SET_BIAS_TEE, &cmd, 1);
|
||||
}
|
||||
|
||||
void FCDInput::set_lna_gain(bool on)
|
||||
{
|
||||
quint8 cmd = on ? 1 : 0;
|
||||
|
||||
fcdAppSetParam(FCD_CMD_APP_SET_LNA_GAIN, &cmd, 1);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
|
||||
struct fcd_buffer {
|
||||
void *start;
|
||||
size_t length;
|
||||
std::size_t length;
|
||||
};
|
||||
|
||||
class FCDThread;
|
||||
|
@ -32,6 +32,7 @@ class FCDInput : public SampleSource {
|
|||
public:
|
||||
struct Settings {
|
||||
Settings();
|
||||
quint64 centerFrequency;
|
||||
qint32 range;
|
||||
qint32 gain;
|
||||
qint32 bias;
|
||||
|
@ -44,46 +45,46 @@ public:
|
|||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
const GeneralSettings& getGeneralSettings() const { return m_generalSettings; }
|
||||
const Settings& getSettings() const { return m_settings; }
|
||||
|
||||
static MsgConfigureFCD* create(const GeneralSettings& generalSettings, const Settings& settings)
|
||||
static MsgConfigureFCD* create(const Settings& settings)
|
||||
{
|
||||
return new MsgConfigureFCD(generalSettings, settings);
|
||||
return new MsgConfigureFCD(settings);
|
||||
}
|
||||
|
||||
private:
|
||||
GeneralSettings m_generalSettings;
|
||||
Settings m_settings;
|
||||
|
||||
MsgConfigureFCD(const GeneralSettings& generalSettings, const Settings& settings) :
|
||||
MsgConfigureFCD(const Settings& settings) :
|
||||
Message(),
|
||||
m_generalSettings(generalSettings),
|
||||
m_settings(settings)
|
||||
{ }
|
||||
};
|
||||
|
||||
FCDInput();
|
||||
virtual ~FCDInput();
|
||||
|
||||
FCDInput(MessageQueue* msgQueueToGUI);
|
||||
~FCDInput();
|
||||
virtual bool init(const Message& cmd);
|
||||
virtual bool start(int device);
|
||||
virtual void stop();
|
||||
|
||||
bool startInput(int device);
|
||||
void stopInput();
|
||||
virtual const QString& getDeviceDescription() const;
|
||||
virtual int getSampleRate() const;
|
||||
virtual quint64 getCenterFrequency() const;
|
||||
|
||||
virtual bool handleMessage(const Message& message);
|
||||
|
||||
const QString& getDeviceDescription() const;
|
||||
int getSampleRate() const;
|
||||
void set_center_freq(double freq);
|
||||
void set_bias_t(bool on);
|
||||
void set_lna_gain(bool on);
|
||||
quint64 getCenterFrequency() const;
|
||||
bool handleMessage(Message* message);
|
||||
|
||||
private:
|
||||
void applySettings(const Settings& settings, bool force);
|
||||
|
||||
QMutex m_mutex;
|
||||
Settings m_settings;
|
||||
FCDThread* m_FCDThread;
|
||||
QString m_deviceDescription;
|
||||
void applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_FCD_H
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
/* (C)2015 John Greb
|
||||
*
|
||||
* Funcube Dongle command line interface
|
||||
* Copyright 2011 David Pello EA1IDZ
|
||||
* Copyright 2011 Pieter-Tjerk de Boer PA3FWM
|
||||
* Copyright 2012-2014 Alexandru Csete OZ9AEC
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public Licence version 3.
|
||||
*/
|
||||
|
||||
#include "fcdinput.h"
|
||||
#include "fcdthread.h"
|
||||
#include "qthid.h"
|
||||
|
||||
bool FCDThread::OpenSource(const char* cardname)
|
||||
{
|
||||
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 )
|
||||
return false;
|
||||
|
||||
snd_pcm_hw_params_alloca(¶ms);
|
||||
if ( snd_pcm_hw_params_any(fcd_handle, params) < 0 )
|
||||
fail = true;
|
||||
else if ( snd_pcm_hw_params(fcd_handle, params) < 0 ) {
|
||||
fail = true;
|
||||
// TODO: check actual samplerate, may be crippled firmware
|
||||
} else {
|
||||
if ( snd_pcm_start(fcd_handle) < 0 )
|
||||
fail = true;
|
||||
}
|
||||
if (fail) {
|
||||
qCritical("Funcube Dongle stream start failed");
|
||||
snd_pcm_close( fcd_handle );
|
||||
return false;
|
||||
} else {
|
||||
qDebug("Funcube stream started");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void FCDThread::CloseSource()
|
||||
{
|
||||
if (fcd_handle)
|
||||
snd_pcm_close( fcd_handle );
|
||||
fcd_handle = NULL;
|
||||
}
|
||||
|
||||
void FCDInput::set_center_freq(double freq)
|
||||
{
|
||||
if (fcdAppSetFreq(freq) == FCD_MODE_NONE)
|
||||
qDebug("No FCD HID found for frquency change");
|
||||
}
|
||||
|
||||
void FCDInput::set_bias_t(bool on)
|
||||
{
|
||||
quint8 cmd = on ? 1 : 0;
|
||||
|
||||
fcdAppSetParam(FCD_CMD_APP_SET_BIAS_TEE, &cmd, 1);
|
||||
}
|
||||
|
||||
void FCDInput::set_lna_gain(bool on)
|
||||
{
|
||||
quint8 cmd = on ? 1 : 0;
|
||||
|
||||
fcdAppSetParam(FCD_CMD_APP_SET_LNA_GAIN, &cmd, 1);
|
||||
}
|
||||
|
||||
int FCDThread::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;
|
||||
}
|
||||
|
||||
|
|
@ -54,3 +54,84 @@ void FCDThread::run()
|
|||
CloseSource();
|
||||
}
|
||||
|
||||
bool FCDThread::OpenSource(const char* cardname)
|
||||
{
|
||||
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)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
snd_pcm_hw_params_alloca(¶ms);
|
||||
|
||||
if (snd_pcm_hw_params_any(fcd_handle, params) < 0)
|
||||
{
|
||||
fail = true;
|
||||
}
|
||||
else if (snd_pcm_hw_params(fcd_handle, params) < 0)
|
||||
{
|
||||
fail = true;
|
||||
// TODO: check actual samplerate, may be crippled firmware
|
||||
}
|
||||
else
|
||||
{
|
||||
if (snd_pcm_start(fcd_handle) < 0)
|
||||
{
|
||||
fail = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (fail)
|
||||
{
|
||||
qCritical("Funcube Dongle stream start failed");
|
||||
snd_pcm_close( fcd_handle );
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
qDebug("Funcube stream started");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FCDThread::CloseSource()
|
||||
{
|
||||
if (fcd_handle)
|
||||
{
|
||||
snd_pcm_close( fcd_handle );
|
||||
}
|
||||
|
||||
fcd_handle = NULL;
|
||||
}
|
||||
|
||||
int FCDThread::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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "ui_filesourcegui.h"
|
||||
#include "plugin/pluginapi.h"
|
||||
#include "gui/colormapper.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
#include "filesourcegui.h"
|
||||
|
@ -49,8 +50,8 @@ FileSourceGui::FileSourceGui(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
connect(&(m_pluginAPI->getMainWindow()->getMasterTimer()), SIGNAL(timeout()), this, SLOT(tick()));
|
||||
displaySettings();
|
||||
|
||||
m_sampleSource = new FileSourceInput(m_pluginAPI->getMainWindowMessageQueue(), m_pluginAPI->getMainWindow()->getMasterTimer());
|
||||
m_pluginAPI->setSampleSource(m_sampleSource);
|
||||
m_sampleSource = new FileSourceInput(m_pluginAPI->getMainWindow()->getMasterTimer());
|
||||
DSPEngine::instance()->setSource(m_sampleSource);
|
||||
}
|
||||
|
||||
FileSourceGui::~FileSourceGui()
|
||||
|
@ -75,32 +76,14 @@ QString FileSourceGui::getName() const
|
|||
|
||||
void FileSourceGui::resetToDefaults()
|
||||
{
|
||||
m_generalSettings.resetToDefaults();
|
||||
m_settings.resetToDefaults();
|
||||
displaySettings();
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
QByteArray FileSourceGui::serializeGeneral() const
|
||||
{
|
||||
return m_generalSettings.serialize();
|
||||
}
|
||||
|
||||
bool FileSourceGui::deserializeGeneral(const QByteArray&data)
|
||||
{
|
||||
if(m_generalSettings.deserialize(data)) {
|
||||
displaySettings();
|
||||
sendSettings();
|
||||
return true;
|
||||
} else {
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
qint64 FileSourceGui::getCenterFrequency() const
|
||||
{
|
||||
return m_generalSettings.m_centerFrequency;
|
||||
return m_centerFrequency;
|
||||
}
|
||||
|
||||
QByteArray FileSourceGui::serialize() const
|
||||
|
@ -120,28 +103,25 @@ bool FileSourceGui::deserialize(const QByteArray& data)
|
|||
}
|
||||
}
|
||||
|
||||
bool FileSourceGui::handleMessage(Message* message)
|
||||
bool FileSourceGui::handleMessage(const Message& message)
|
||||
{
|
||||
if(FileSourceInput::MsgReportFileSourceAcquisition::match(message))
|
||||
{
|
||||
m_acquisition = ((FileSourceInput::MsgReportFileSourceAcquisition*)message)->getAcquisition();
|
||||
m_acquisition = ((FileSourceInput::MsgReportFileSourceAcquisition&)message).getAcquisition();
|
||||
updateWithAcquisition();
|
||||
message->completed();
|
||||
return true;
|
||||
}
|
||||
else if(FileSourceInput::MsgReportFileSourceStreamData::match(message))
|
||||
{
|
||||
m_sampleRate = ((FileSourceInput::MsgReportFileSourceStreamData*)message)->getSampleRate();
|
||||
m_centerFrequency = ((FileSourceInput::MsgReportFileSourceStreamData*)message)->getCenterFrequency();
|
||||
m_startingTimeStamp = ((FileSourceInput::MsgReportFileSourceStreamData*)message)->getStartingTimeStamp();
|
||||
message->completed();
|
||||
m_sampleRate = ((FileSourceInput::MsgReportFileSourceStreamData&)message).getSampleRate();
|
||||
m_centerFrequency = ((FileSourceInput::MsgReportFileSourceStreamData&)message).getCenterFrequency();
|
||||
m_startingTimeStamp = ((FileSourceInput::MsgReportFileSourceStreamData&)message).getStartingTimeStamp();
|
||||
updateWithStreamData();
|
||||
return true;
|
||||
}
|
||||
else if(FileSourceInput::MsgReportFileSourceStreamTiming::match(message))
|
||||
{
|
||||
m_samplesCount = ((FileSourceInput::MsgReportFileSourceStreamTiming*)message)->getSamplesCount();
|
||||
message->completed();
|
||||
m_samplesCount = ((FileSourceInput::MsgReportFileSourceStreamTiming&)message).getSamplesCount();
|
||||
updateWithStreamTime();
|
||||
return true;
|
||||
}
|
||||
|
@ -157,31 +137,25 @@ void FileSourceGui::displaySettings()
|
|||
|
||||
void FileSourceGui::sendSettings()
|
||||
{
|
||||
/*
|
||||
if(!m_updateTimer.isActive())
|
||||
m_updateTimer.start(100);
|
||||
*/
|
||||
}
|
||||
|
||||
void FileSourceGui::updateHardware()
|
||||
{
|
||||
/*
|
||||
FileSourceInput::MsgConfigureFileSource* message = FileSourceInput::MsgConfigureFileSource::create(m_generalSettings, m_settings);
|
||||
message->submit(m_pluginAPI->getDSPEngineMessageQueue());
|
||||
m_updateTimer.stop();*/
|
||||
}
|
||||
|
||||
void FileSourceGui::on_play_toggled(bool checked)
|
||||
{
|
||||
FileSourceInput::MsgConfigureFileSourceWork* message = FileSourceInput::MsgConfigureFileSourceWork::create(checked);
|
||||
message->submit(m_pluginAPI->getDSPEngineMessageQueue());
|
||||
m_sampleSource->getInputMessageQueue()->push(message);
|
||||
}
|
||||
|
||||
void FileSourceGui::on_showFileDialog_clicked(bool checked)
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this,
|
||||
tr("Open I/Q record file"), ".", tr("SDR I/Q Files (*.sdriq)"));
|
||||
if (fileName != "") {
|
||||
|
||||
if (fileName != "")
|
||||
{
|
||||
m_fileName = fileName;
|
||||
ui->fileNameText->setText(m_fileName);
|
||||
configureFileName();
|
||||
|
@ -192,7 +166,7 @@ void FileSourceGui::configureFileName()
|
|||
{
|
||||
qDebug() << "FileSourceGui::configureFileName: " << m_fileName.toStdString().c_str();
|
||||
FileSourceInput::MsgConfigureFileSourceName* message = FileSourceInput::MsgConfigureFileSourceName::create(m_fileName);
|
||||
message->submit(m_pluginAPI->getDSPEngineMessageQueue());
|
||||
m_sampleSource->getInputMessageQueue()->push(message);
|
||||
}
|
||||
|
||||
void FileSourceGui::updateWithAcquisition()
|
||||
|
@ -239,6 +213,6 @@ void FileSourceGui::tick()
|
|||
{
|
||||
if ((++m_tickCount & 0xf) == 0) {
|
||||
FileSourceInput::MsgConfigureFileSourceStreamTiming* message = FileSourceInput::MsgConfigureFileSourceStreamTiming::create();
|
||||
message->submit(m_pluginAPI->getDSPEngineMessageQueue());
|
||||
m_sampleSource->getInputMessageQueue()->push(message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,25 +33,22 @@ class FileSourceGui : public QWidget, public PluginGUI {
|
|||
|
||||
public:
|
||||
explicit FileSourceGui(PluginAPI* pluginAPI, QWidget* parent = NULL);
|
||||
~FileSourceGui();
|
||||
virtual ~FileSourceGui();
|
||||
void destroy();
|
||||
|
||||
void setName(const QString& name);
|
||||
QString getName() const;
|
||||
|
||||
void resetToDefaults();
|
||||
QByteArray serializeGeneral() const;
|
||||
bool deserializeGeneral(const QByteArray&data);
|
||||
qint64 getCenterFrequency() const;
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
bool handleMessage(Message* message);
|
||||
virtual bool handleMessage(const Message& message);
|
||||
|
||||
private:
|
||||
Ui::FileSourceGui* ui;
|
||||
|
||||
PluginAPI* m_pluginAPI;
|
||||
SampleSource::GeneralSettings m_generalSettings;
|
||||
FileSourceInput::Settings m_settings;
|
||||
QTimer m_updateTimer;
|
||||
std::vector<int> m_gains;
|
||||
|
|
|
@ -69,8 +69,7 @@ bool FileSourceInput::Settings::deserialize(const QByteArray& data)
|
|||
}
|
||||
}
|
||||
|
||||
FileSourceInput::FileSourceInput(MessageQueue* msgQueueToGUI, const QTimer& masterTimer) :
|
||||
SampleSource(msgQueueToGUI),
|
||||
FileSourceInput::FileSourceInput(const QTimer& masterTimer) :
|
||||
m_settings(),
|
||||
m_fileSourceThread(NULL),
|
||||
m_deviceDescription(),
|
||||
|
@ -84,7 +83,7 @@ FileSourceInput::FileSourceInput(MessageQueue* msgQueueToGUI, const QTimer& mast
|
|||
|
||||
FileSourceInput::~FileSourceInput()
|
||||
{
|
||||
stopInput();
|
||||
stop();
|
||||
}
|
||||
|
||||
void FileSourceInput::openFileStream()
|
||||
|
@ -105,19 +104,15 @@ void FileSourceInput::openFileStream()
|
|||
m_centerFrequency = header.centerFrequency;
|
||||
m_startingTimeStamp = header.startTimeStamp;
|
||||
|
||||
MsgReportFileSourceStreamData::create(m_sampleRate, m_centerFrequency, m_startingTimeStamp)->submit(m_guiMessageQueue); // file stream data
|
||||
MsgReportFileSourceStreamData *report = MsgReportFileSourceStreamData::create(m_sampleRate, m_centerFrequency, m_startingTimeStamp); // file stream data
|
||||
getOutputMessageQueue()->push(report);
|
||||
}
|
||||
|
||||
bool FileSourceInput::startInput(int device)
|
||||
bool FileSourceInput::start(int device)
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
qDebug() << "FileSourceInput::startInput";
|
||||
|
||||
/*
|
||||
if (!m_ifstream.is_open()) {
|
||||
openFileStream();
|
||||
}*/
|
||||
|
||||
if (m_ifstream.tellg() != 0) {
|
||||
m_ifstream.clear();
|
||||
m_ifstream.seekg(0, std::ios::beg);
|
||||
|
@ -132,7 +127,8 @@ bool FileSourceInput::startInput(int device)
|
|||
|
||||
if((m_fileSourceThread = new FileSourceThread(&m_ifstream, &m_sampleFifo)) == NULL) {
|
||||
qFatal("out of memory");
|
||||
goto failed;
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_fileSourceThread->setSamplerate(m_sampleRate);
|
||||
|
@ -144,29 +140,28 @@ bool FileSourceInput::startInput(int device)
|
|||
//applySettings(m_generalSettings, m_settings, true);
|
||||
qDebug("FileSourceInput::startInput: started");
|
||||
|
||||
MsgReportFileSourceAcquisition::create(true)->submit(m_guiMessageQueue); // acquisition on
|
||||
MsgReportFileSourceAcquisition *report = MsgReportFileSourceAcquisition::create(true); // acquisition on
|
||||
getOutputMessageQueue()->push(report);
|
||||
|
||||
return true;
|
||||
|
||||
failed:
|
||||
stopInput();
|
||||
return false;
|
||||
}
|
||||
|
||||
void FileSourceInput::stopInput()
|
||||
void FileSourceInput::stop()
|
||||
{
|
||||
qDebug() << "FileSourceInput::stopInput";
|
||||
qDebug() << "FileSourceInput::stop";
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if(m_fileSourceThread != NULL) {
|
||||
if(m_fileSourceThread != 0)
|
||||
{
|
||||
m_fileSourceThread->stopWork();
|
||||
delete m_fileSourceThread;
|
||||
m_fileSourceThread = NULL;
|
||||
m_fileSourceThread = 0;
|
||||
}
|
||||
|
||||
m_deviceDescription.clear();
|
||||
|
||||
MsgReportFileSourceAcquisition::create(false)->submit(m_guiMessageQueue); // acquisition off
|
||||
MsgReportFileSourceAcquisition *report = MsgReportFileSourceAcquisition::create(false); // acquisition off
|
||||
getOutputMessageQueue()->push(report);
|
||||
}
|
||||
|
||||
const QString& FileSourceInput::getDeviceDescription() const
|
||||
|
@ -189,40 +184,52 @@ std::time_t FileSourceInput::getStartingTimeStamp() const
|
|||
return m_startingTimeStamp;
|
||||
}
|
||||
|
||||
bool FileSourceInput::handleMessage(Message* message)
|
||||
bool FileSourceInput::handleMessage(const Message& message)
|
||||
{
|
||||
if (MsgConfigureFileSourceName::match(message))
|
||||
{
|
||||
MsgConfigureFileSourceName* conf = (MsgConfigureFileSourceName*) message;
|
||||
m_fileName = conf->getFileName();
|
||||
MsgConfigureFileSourceName& conf = (MsgConfigureFileSourceName&) message;
|
||||
m_fileName = conf.getFileName();
|
||||
openFileStream();
|
||||
message->completed();
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureFileSourceWork::match(message))
|
||||
{
|
||||
MsgConfigureFileSourceWork* conf = (MsgConfigureFileSourceWork*) message;
|
||||
bool working = conf->isWorking();
|
||||
MsgConfigureFileSourceWork& conf = (MsgConfigureFileSourceWork&) message;
|
||||
bool working = conf.isWorking();
|
||||
|
||||
if (m_fileSourceThread != 0)
|
||||
{
|
||||
if (working) {
|
||||
if (working)
|
||||
{
|
||||
m_fileSourceThread->startWork();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_fileSourceThread->stopWork();
|
||||
}
|
||||
|
||||
MsgReportFileSourceStreamTiming::create(m_fileSourceThread->getSamplesCount())->submit(m_guiMessageQueue);
|
||||
MsgReportFileSourceStreamTiming *report =
|
||||
MsgReportFileSourceStreamTiming::create(m_fileSourceThread->getSamplesCount());
|
||||
getOutputMessageQueue()->push(report);
|
||||
}
|
||||
message->completed();
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureFileSourceStreamTiming::match(message))
|
||||
{
|
||||
if (m_fileSourceThread != 0) {
|
||||
MsgReportFileSourceStreamTiming::create(m_fileSourceThread->getSamplesCount())->submit(m_guiMessageQueue);
|
||||
}else {
|
||||
MsgReportFileSourceStreamTiming::create(0)->submit(m_guiMessageQueue);
|
||||
MsgReportFileSourceStreamTiming *report;
|
||||
|
||||
if (m_fileSourceThread != 0)
|
||||
{
|
||||
report = MsgReportFileSourceStreamTiming::create(m_fileSourceThread->getSamplesCount());
|
||||
}
|
||||
else
|
||||
{
|
||||
report = MsgReportFileSourceStreamTiming::create(0);
|
||||
}
|
||||
|
||||
getOutputMessageQueue()->push(report);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -230,30 +237,38 @@ bool FileSourceInput::handleMessage(Message* message)
|
|||
}
|
||||
}
|
||||
|
||||
bool FileSourceInput::applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force)
|
||||
bool FileSourceInput::applySettings(const Settings& settings, bool force)
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
bool wasRunning = false;
|
||||
|
||||
if((m_settings.m_fileName != settings.m_fileName) || force) {
|
||||
if((m_settings.m_fileName != settings.m_fileName) || force)
|
||||
{
|
||||
m_settings.m_fileName = settings.m_fileName;
|
||||
|
||||
if (m_fileSourceThread != 0) {
|
||||
if (m_fileSourceThread != 0)
|
||||
{
|
||||
wasRunning = m_fileSourceThread->isRunning();
|
||||
if (wasRunning) {
|
||||
|
||||
if (wasRunning)
|
||||
{
|
||||
m_fileSourceThread->stopWork();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_ifstream.is_open()) {
|
||||
if (m_ifstream.is_open())
|
||||
{
|
||||
m_ifstream.close();
|
||||
}
|
||||
|
||||
openFileStream();
|
||||
|
||||
if (m_fileSourceThread != 0) {
|
||||
if (m_fileSourceThread != 0)
|
||||
{
|
||||
m_fileSourceThread->setSamplerate(m_sampleRate);
|
||||
if (wasRunning) {
|
||||
|
||||
if (wasRunning)
|
||||
{
|
||||
m_fileSourceThread->startWork();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,21 +41,18 @@ public:
|
|||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
const GeneralSettings& getGeneralSettings() const { return m_generalSettings; }
|
||||
const Settings& getSettings() const { return m_settings; }
|
||||
|
||||
static MsgConfigureFileSource* create(const GeneralSettings& generalSettings, const Settings& settings)
|
||||
static MsgConfigureFileSource* create(const Settings& settings)
|
||||
{
|
||||
return new MsgConfigureFileSource(generalSettings, settings);
|
||||
return new MsgConfigureFileSource(settings);
|
||||
}
|
||||
|
||||
private:
|
||||
GeneralSettings m_generalSettings;
|
||||
Settings m_settings;
|
||||
|
||||
MsgConfigureFileSource(const GeneralSettings& generalSettings, const Settings& settings) :
|
||||
MsgConfigureFileSource(const Settings& settings) :
|
||||
Message(),
|
||||
m_generalSettings(generalSettings),
|
||||
m_settings(settings)
|
||||
{ }
|
||||
};
|
||||
|
@ -183,18 +180,19 @@ public:
|
|||
{ }
|
||||
};
|
||||
|
||||
FileSourceInput(MessageQueue* msgQueueToGUI, const QTimer& masterTimer);
|
||||
~FileSourceInput();
|
||||
FileSourceInput(const QTimer& masterTimer);
|
||||
virtual ~FileSourceInput();
|
||||
|
||||
bool startInput(int device);
|
||||
void stopInput();
|
||||
virtual bool init(const Message& message);
|
||||
virtual bool start(int device);
|
||||
virtual void stop();
|
||||
|
||||
const QString& getDeviceDescription() const;
|
||||
int getSampleRate() const;
|
||||
quint64 getCenterFrequency() const;
|
||||
virtual const QString& getDeviceDescription() const;
|
||||
virtual int getSampleRate() const;
|
||||
virtual quint64 getCenterFrequency() const;
|
||||
std::time_t getStartingTimeStamp() const;
|
||||
|
||||
bool handleMessage(Message* message);
|
||||
virtual bool handleMessage(const Message& message);
|
||||
|
||||
private:
|
||||
QMutex m_mutex;
|
||||
|
@ -208,7 +206,7 @@ private:
|
|||
std::time_t m_startingTimeStamp;
|
||||
const QTimer& m_masterTimer;
|
||||
|
||||
bool applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force);
|
||||
bool applySettings(const Settings& settings, bool force);
|
||||
void openFileStream();
|
||||
};
|
||||
|
||||
|
|
|
@ -2,13 +2,14 @@
|
|||
#include "ui_rtlsdrgui.h"
|
||||
#include "plugin/pluginapi.h"
|
||||
#include "gui/colormapper.h"
|
||||
#include "dsp/dspengine.h"
|
||||
|
||||
RTLSDRGui::RTLSDRGui(PluginAPI* pluginAPI, QWidget* parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::RTLSDRGui),
|
||||
m_pluginAPI(pluginAPI),
|
||||
m_settings(),
|
||||
m_sampleSource(NULL)
|
||||
m_sampleSource(0)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::ReverseGold));
|
||||
|
@ -16,8 +17,8 @@ RTLSDRGui::RTLSDRGui(PluginAPI* pluginAPI, QWidget* parent) :
|
|||
connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware()));
|
||||
displaySettings();
|
||||
|
||||
m_sampleSource = new RTLSDRInput(m_pluginAPI->getMainWindowMessageQueue());
|
||||
m_pluginAPI->setSampleSource(m_sampleSource);
|
||||
m_sampleSource = new RTLSDRInput();
|
||||
DSPEngine::instance()->setSource(m_sampleSource);
|
||||
}
|
||||
|
||||
RTLSDRGui::~RTLSDRGui()
|
||||
|
@ -42,32 +43,14 @@ QString RTLSDRGui::getName() const
|
|||
|
||||
void RTLSDRGui::resetToDefaults()
|
||||
{
|
||||
m_generalSettings.resetToDefaults();
|
||||
m_settings.resetToDefaults();
|
||||
displaySettings();
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
QByteArray RTLSDRGui::serializeGeneral() const
|
||||
{
|
||||
return m_generalSettings.serialize();
|
||||
}
|
||||
|
||||
bool RTLSDRGui::deserializeGeneral(const QByteArray&data)
|
||||
{
|
||||
if(m_generalSettings.deserialize(data)) {
|
||||
displaySettings();
|
||||
sendSettings();
|
||||
return true;
|
||||
} else {
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
qint64 RTLSDRGui::getCenterFrequency() const
|
||||
{
|
||||
return m_generalSettings.m_centerFrequency;
|
||||
return m_settings.m_centerFrequency;
|
||||
}
|
||||
|
||||
QByteArray RTLSDRGui::serialize() const
|
||||
|
@ -77,53 +60,65 @@ QByteArray RTLSDRGui::serialize() const
|
|||
|
||||
bool RTLSDRGui::deserialize(const QByteArray& data)
|
||||
{
|
||||
if(m_settings.deserialize(data)) {
|
||||
if (m_settings.deserialize(data))
|
||||
{
|
||||
displaySettings();
|
||||
sendSettings();
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool RTLSDRGui::handleMessage(Message* message)
|
||||
bool RTLSDRGui::handleMessage(const Message& message)
|
||||
{
|
||||
if(RTLSDRInput::MsgReportRTLSDR::match(message)) {
|
||||
m_gains = ((RTLSDRInput::MsgReportRTLSDR*)message)->getGains();
|
||||
if (RTLSDRInput::MsgReportRTLSDR::match(message))
|
||||
{
|
||||
m_gains = ((RTLSDRInput::MsgReportRTLSDR&) message).getGains();
|
||||
displaySettings();
|
||||
message->completed();
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void RTLSDRGui::displaySettings()
|
||||
{
|
||||
ui->centerFrequency->setValue(m_generalSettings.m_centerFrequency / 1000);
|
||||
ui->samplerateText->setText(tr("%1k").arg(m_settings.m_samplerate / 1000));
|
||||
unsigned int sampleRateIndex = RTLSDRSampleRates::getRateIndex(m_settings.m_samplerate);
|
||||
ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000);
|
||||
ui->samplerateText->setText(tr("%1k").arg(m_settings.m_devSampleRate / 1000));
|
||||
unsigned int sampleRateIndex = RTLSDRSampleRates::getRateIndex(m_settings.m_devSampleRate);
|
||||
ui->samplerate->setValue(sampleRateIndex);
|
||||
ui->ppm->setValue(m_settings.m_loPpmCorrection);
|
||||
ui->ppmText->setText(tr("%1").arg(m_settings.m_loPpmCorrection));
|
||||
ui->decimText->setText(tr("%1").arg(1<<m_settings.m_log2Decim));
|
||||
ui->decim->setValue(m_settings.m_log2Decim);
|
||||
|
||||
if(m_gains.size() > 0) {
|
||||
if (m_gains.size() > 0)
|
||||
{
|
||||
int dist = abs(m_settings.m_gain - m_gains[0]);
|
||||
int pos = 0;
|
||||
for(uint i = 1; i < m_gains.size(); i++) {
|
||||
if(abs(m_settings.m_gain - m_gains[i]) < dist) {
|
||||
|
||||
for (uint i = 1; i < m_gains.size(); i++)
|
||||
{
|
||||
if (abs(m_settings.m_gain - m_gains[i]) < dist)
|
||||
{
|
||||
dist = abs(m_settings.m_gain - m_gains[i]);
|
||||
pos = i;
|
||||
}
|
||||
}
|
||||
|
||||
ui->gainText->setText(tr("%1.%2").arg(m_gains[pos] / 10).arg(abs(m_gains[pos] % 10)));
|
||||
ui->gain->setMaximum(m_gains.size() - 1);
|
||||
ui->gain->setEnabled(true);
|
||||
ui->gain->setValue(pos);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->gain->setMaximum(0);
|
||||
ui->gain->setEnabled(false);
|
||||
ui->gain->setValue(0);
|
||||
|
@ -133,40 +128,54 @@ void RTLSDRGui::displaySettings()
|
|||
void RTLSDRGui::sendSettings()
|
||||
{
|
||||
if(!m_updateTimer.isActive())
|
||||
{
|
||||
m_updateTimer.start(100);
|
||||
}
|
||||
}
|
||||
|
||||
void RTLSDRGui::on_centerFrequency_changed(quint64 value)
|
||||
{
|
||||
m_generalSettings.m_centerFrequency = value * 1000;
|
||||
m_settings.m_centerFrequency = value * 1000;
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void RTLSDRGui::on_decim_valueChanged(int value)
|
||||
{
|
||||
if ((value <0) || (value > 4))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ui->decimText->setText(tr("%1").arg(1<<value));
|
||||
m_settings.m_log2Decim = value;
|
||||
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void RTLSDRGui::on_ppm_valueChanged(int value)
|
||||
{
|
||||
if((value > 99) || (value < -99))
|
||||
if ((value > 99) || (value < -99))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ui->ppmText->setText(tr("%1").arg(value));
|
||||
m_settings.m_loPpmCorrection = value;
|
||||
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void RTLSDRGui::on_gain_valueChanged(int value)
|
||||
{
|
||||
if(value > (int)m_gains.size())
|
||||
if (value > (int)m_gains.size())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int gain = m_gains[value];
|
||||
ui->gainText->setText(tr("%1.%2").arg(gain / 10).arg(abs(gain % 10)));
|
||||
m_settings.m_gain = gain;
|
||||
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
|
@ -174,34 +183,39 @@ void RTLSDRGui::on_samplerate_valueChanged(int value)
|
|||
{
|
||||
int newrate = RTLSDRSampleRates::getRate(value);
|
||||
ui->samplerateText->setText(tr("%1k").arg(newrate));
|
||||
m_settings.m_samplerate = newrate * 1000;
|
||||
m_settings.m_devSampleRate = newrate * 1000;
|
||||
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
void RTLSDRGui::updateHardware()
|
||||
{
|
||||
RTLSDRInput::MsgConfigureRTLSDR* message = RTLSDRInput::MsgConfigureRTLSDR::create(m_generalSettings, m_settings);
|
||||
message->submit(m_pluginAPI->getDSPEngineMessageQueue());
|
||||
RTLSDRInput::MsgConfigureRTLSDR* message = RTLSDRInput::MsgConfigureRTLSDR::create(m_settings);
|
||||
m_sampleSource->getInputMessageQueue()->push(message);
|
||||
m_updateTimer.stop();
|
||||
}
|
||||
|
||||
void RTLSDRGui::on_checkBox_stateChanged(int state) {
|
||||
if (state == Qt::Checked){
|
||||
void RTLSDRGui::on_checkBox_stateChanged(int state)
|
||||
{
|
||||
if (state == Qt::Checked)
|
||||
{
|
||||
// Direct Modes: 0: off, 1: I, 2: Q, 3: NoMod.
|
||||
((RTLSDRInput*)m_sampleSource)->set_ds_mode(3);
|
||||
ui->gain->setEnabled(false);
|
||||
ui->centerFrequency->setValueRange(7, 1000U, 275000U);
|
||||
ui->centerFrequency->setValue(7000);
|
||||
m_generalSettings.m_centerFrequency = 7000 * 1000;
|
||||
m_settings.m_centerFrequency = 7000 * 1000;
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
((RTLSDRInput*)m_sampleSource)->set_ds_mode(0);
|
||||
ui->gain->setEnabled(true);
|
||||
ui->centerFrequency->setValueRange(7, 28500U, 1700000U);
|
||||
ui->centerFrequency->setValue(434000);
|
||||
ui->gain->setValue(0);
|
||||
m_generalSettings.m_centerFrequency = 434000 * 1000;
|
||||
m_settings.m_centerFrequency = 435000 * 1000;
|
||||
}
|
||||
|
||||
sendSettings();
|
||||
}
|
||||
|
||||
|
|
|
@ -17,25 +17,22 @@ class RTLSDRGui : public QWidget, public PluginGUI {
|
|||
|
||||
public:
|
||||
explicit RTLSDRGui(PluginAPI* pluginAPI, QWidget* parent = NULL);
|
||||
~RTLSDRGui();
|
||||
virtual ~RTLSDRGui();
|
||||
void destroy();
|
||||
|
||||
void setName(const QString& name);
|
||||
QString getName() const;
|
||||
|
||||
void resetToDefaults();
|
||||
QByteArray serializeGeneral() const;
|
||||
bool deserializeGeneral(const QByteArray&data);
|
||||
qint64 getCenterFrequency() const;
|
||||
QByteArray serialize() const;
|
||||
bool deserialize(const QByteArray& data);
|
||||
bool handleMessage(Message* message);
|
||||
virtual bool handleMessage(const Message& message);
|
||||
|
||||
private:
|
||||
Ui::RTLSDRGui* ui;
|
||||
|
||||
PluginAPI* m_pluginAPI;
|
||||
SampleSource::GeneralSettings m_generalSettings;
|
||||
RTLSDRInput::Settings m_settings;
|
||||
QTimer m_updateTimer;
|
||||
std::vector<int> m_gains;
|
||||
|
|
|
@ -26,8 +26,9 @@ MESSAGE_CLASS_DEFINITION(RTLSDRInput::MsgConfigureRTLSDR, Message)
|
|||
MESSAGE_CLASS_DEFINITION(RTLSDRInput::MsgReportRTLSDR, Message)
|
||||
|
||||
RTLSDRInput::Settings::Settings() :
|
||||
m_devSampleRate(1024*1000),
|
||||
m_centerFrequency(435000*1000),
|
||||
m_gain(0),
|
||||
m_samplerate(1024000),
|
||||
m_loPpmCorrection(0),
|
||||
m_log2Decim(4)
|
||||
{
|
||||
|
@ -35,8 +36,9 @@ RTLSDRInput::Settings::Settings() :
|
|||
|
||||
void RTLSDRInput::Settings::resetToDefaults()
|
||||
{
|
||||
m_devSampleRate = 1024*1000;
|
||||
m_centerFrequency = 435000*1000;
|
||||
m_gain = 0;
|
||||
m_samplerate = 1024000;
|
||||
m_loPpmCorrection = 0;
|
||||
m_log2Decim = 4;
|
||||
}
|
||||
|
@ -44,10 +46,11 @@ void RTLSDRInput::Settings::resetToDefaults()
|
|||
QByteArray RTLSDRInput::Settings::serialize() const
|
||||
{
|
||||
SimpleSerializer s(1);
|
||||
s.writeS32(1, m_gain);
|
||||
s.writeS32(2, m_samplerate);
|
||||
s.writeS32(3, m_loPpmCorrection);
|
||||
s.writeU32(4, m_log2Decim);
|
||||
s.writeS32(1, m_devSampleRate);
|
||||
s.writeU64(2, m_centerFrequency);
|
||||
s.writeS32(3, m_gain);
|
||||
s.writeS32(4, m_loPpmCorrection);
|
||||
s.writeU32(5, m_log2Decim);
|
||||
return s.final();
|
||||
}
|
||||
|
||||
|
@ -55,43 +58,49 @@ bool RTLSDRInput::Settings::deserialize(const QByteArray& data)
|
|||
{
|
||||
SimpleDeserializer d(data);
|
||||
|
||||
if(!d.isValid()) {
|
||||
if (!d.isValid())
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
|
||||
if(d.getVersion() == 1) {
|
||||
d.readS32(1, &m_gain, 0);
|
||||
d.readS32(2, &m_samplerate, 0);
|
||||
d.readS32(3, &m_loPpmCorrection, 0);
|
||||
d.readU32(4, &m_log2Decim, 4);
|
||||
if(d.getVersion() == 1)
|
||||
{
|
||||
d.readS32(1, &m_devSampleRate, 1024*1000);
|
||||
d.readU64(2, &m_centerFrequency, 435000*1000);
|
||||
d.readS32(3, &m_gain, 0);
|
||||
d.readS32(4, &m_loPpmCorrection, 0);
|
||||
d.readU32(5, &m_log2Decim, 4);
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
resetToDefaults();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RTLSDRInput::RTLSDRInput(MessageQueue* msgQueueToGUI) :
|
||||
SampleSource(msgQueueToGUI),
|
||||
RTLSDRInput::RTLSDRInput() :
|
||||
m_settings(),
|
||||
m_dev(NULL),
|
||||
m_rtlSDRThread(NULL),
|
||||
m_dev(0),
|
||||
m_rtlSDRThread(0),
|
||||
m_deviceDescription()
|
||||
{
|
||||
}
|
||||
|
||||
RTLSDRInput::~RTLSDRInput()
|
||||
{
|
||||
stopInput();
|
||||
stop();
|
||||
}
|
||||
|
||||
bool RTLSDRInput::startInput(int device)
|
||||
bool RTLSDRInput::start(int device)
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if(m_dev != NULL)
|
||||
stopInput();
|
||||
if (m_dev != 0)
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
char vendor[256];
|
||||
char product[256];
|
||||
|
@ -99,12 +108,14 @@ bool RTLSDRInput::startInput(int device)
|
|||
int res;
|
||||
int numberOfGains;
|
||||
|
||||
if(!m_sampleFifo.setSize(96000 * 4)) {
|
||||
if (!m_sampleFifo.setSize(96000 * 4))
|
||||
{
|
||||
qCritical("Could not allocate SampleFifo");
|
||||
return false;
|
||||
}
|
||||
|
||||
if((res = rtlsdr_open(&m_dev, device)) < 0) {
|
||||
if ((res = rtlsdr_open(&m_dev, device)) < 0)
|
||||
{
|
||||
qCritical("could not open RTLSDR #%d: %s", device, strerror(errno));
|
||||
return false;
|
||||
}
|
||||
|
@ -112,74 +123,101 @@ bool RTLSDRInput::startInput(int device)
|
|||
vendor[0] = '\0';
|
||||
product[0] = '\0';
|
||||
serial[0] = '\0';
|
||||
if((res = rtlsdr_get_usb_strings(m_dev, vendor, product, serial)) < 0) {
|
||||
|
||||
if ((res = rtlsdr_get_usb_strings(m_dev, vendor, product, serial)) < 0)
|
||||
{
|
||||
qCritical("error accessing USB device");
|
||||
goto failed;
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
qWarning("RTLSDRInput open: %s %s, SN: %s", vendor, product, serial);
|
||||
m_deviceDescription = QString("%1 (SN %2)").arg(product).arg(serial);
|
||||
|
||||
if((res = rtlsdr_set_sample_rate(m_dev, 1024000)) < 0) {
|
||||
if ((res = rtlsdr_set_sample_rate(m_dev, 1024000)) < 0)
|
||||
{
|
||||
qCritical("could not set sample rate: 1024k S/s");
|
||||
goto failed;
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
if((res = rtlsdr_set_tuner_gain_mode(m_dev, 1)) < 0) {
|
||||
if ((res = rtlsdr_set_tuner_gain_mode(m_dev, 1)) < 0)
|
||||
{
|
||||
qCritical("error setting tuner gain mode");
|
||||
goto failed;
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
if((res = rtlsdr_set_agc_mode(m_dev, 0)) < 0) {
|
||||
|
||||
if ((res = rtlsdr_set_agc_mode(m_dev, 0)) < 0)
|
||||
{
|
||||
qCritical("error setting agc mode");
|
||||
goto failed;
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
numberOfGains = rtlsdr_get_tuner_gains(m_dev, NULL);
|
||||
if(numberOfGains < 0) {
|
||||
|
||||
if (numberOfGains < 0)
|
||||
{
|
||||
qCritical("error getting number of gain values supported");
|
||||
goto failed;
|
||||
}
|
||||
m_gains.resize(numberOfGains);
|
||||
if(rtlsdr_get_tuner_gains(m_dev, &m_gains[0]) < 0) {
|
||||
qCritical("error getting gain values");
|
||||
goto failed;
|
||||
}
|
||||
if((res = rtlsdr_reset_buffer(m_dev)) < 0) {
|
||||
qCritical("could not reset USB EP buffers: %s", strerror(errno));
|
||||
goto failed;
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
if((m_rtlSDRThread = new RTLSDRThread(m_dev, &m_sampleFifo)) == NULL) {
|
||||
qFatal("out of memory");
|
||||
goto failed;
|
||||
m_gains.resize(numberOfGains);
|
||||
|
||||
if (rtlsdr_get_tuner_gains(m_dev, &m_gains[0]) < 0)
|
||||
{
|
||||
qCritical("error getting gain values");
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((res = rtlsdr_reset_buffer(m_dev)) < 0)
|
||||
{
|
||||
qCritical("could not reset USB EP buffers: %s", strerror(errno));
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((m_rtlSDRThread = new RTLSDRThread(m_dev, &m_sampleFifo)) == NULL)
|
||||
{
|
||||
qFatal("out of memory");
|
||||
stop();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_rtlSDRThread->startWork();
|
||||
|
||||
mutexLocker.unlock();
|
||||
applySettings(m_generalSettings, m_settings, true);
|
||||
|
||||
qDebug("RTLSDRInput: start");
|
||||
MsgReportRTLSDR::create(m_gains)->submit(m_guiMessageQueue);
|
||||
applySettings(m_settings, true);
|
||||
|
||||
qDebug("RTLSDRInput::start");
|
||||
|
||||
MsgReportRTLSDR *message = MsgReportRTLSDR::create(m_gains);
|
||||
getOutputMessageQueue()->push(message);
|
||||
|
||||
return true;
|
||||
|
||||
failed:
|
||||
stopInput();
|
||||
return false;
|
||||
}
|
||||
|
||||
void RTLSDRInput::stopInput()
|
||||
void RTLSDRInput::stop()
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if(m_rtlSDRThread != NULL) {
|
||||
if (m_rtlSDRThread != 0)
|
||||
{
|
||||
m_rtlSDRThread->stopWork();
|
||||
delete m_rtlSDRThread;
|
||||
m_rtlSDRThread = NULL;
|
||||
m_rtlSDRThread = 0;
|
||||
}
|
||||
if(m_dev != NULL) {
|
||||
|
||||
if (m_dev != 0)
|
||||
{
|
||||
rtlsdr_close(m_dev);
|
||||
m_dev = NULL;
|
||||
m_dev = 0;
|
||||
}
|
||||
|
||||
m_deviceDescription.clear();
|
||||
}
|
||||
|
||||
|
@ -190,88 +228,110 @@ const QString& RTLSDRInput::getDeviceDescription() const
|
|||
|
||||
int RTLSDRInput::getSampleRate() const
|
||||
{
|
||||
int rate = m_settings.m_samplerate;
|
||||
int rate = m_settings.m_devSampleRate;
|
||||
return (rate / (1<<m_settings.m_log2Decim));
|
||||
/*
|
||||
if (rate < 800000)
|
||||
return (rate / 4);
|
||||
if ((rate == 1152000) || (rate == 2048000))
|
||||
return (rate / 8);
|
||||
return (rate / 16);
|
||||
*/
|
||||
}
|
||||
|
||||
quint64 RTLSDRInput::getCenterFrequency() const
|
||||
{
|
||||
return m_generalSettings.m_centerFrequency;
|
||||
return m_settings.m_centerFrequency;
|
||||
}
|
||||
|
||||
bool RTLSDRInput::handleMessage(Message* message)
|
||||
bool RTLSDRInput::handleMessage(const Message& message)
|
||||
{
|
||||
if(MsgConfigureRTLSDR::match(message)) {
|
||||
MsgConfigureRTLSDR* conf = (MsgConfigureRTLSDR*)message;
|
||||
if(!applySettings(conf->getGeneralSettings(), conf->getSettings(), false))
|
||||
if (MsgConfigureRTLSDR::match(message))
|
||||
{
|
||||
MsgConfigureRTLSDR& conf = (MsgConfigureRTLSDR&) message;
|
||||
|
||||
if (!applySettings(conf.getSettings(), false))
|
||||
{
|
||||
qDebug("RTLSDR config error");
|
||||
message->completed();
|
||||
}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool RTLSDRInput::applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force)
|
||||
bool RTLSDRInput::applySettings(const Settings& settings, bool force)
|
||||
{
|
||||
QMutexLocker mutexLocker(&m_mutex);
|
||||
|
||||
if((m_settings.m_gain != settings.m_gain) || force) {
|
||||
if ((m_settings.m_gain != settings.m_gain) || force)
|
||||
{
|
||||
m_settings.m_gain = settings.m_gain;
|
||||
if(m_dev != NULL) {
|
||||
|
||||
if(m_dev != 0)
|
||||
{
|
||||
if(rtlsdr_set_tuner_gain(m_dev, m_settings.m_gain) != 0)
|
||||
{
|
||||
qDebug("rtlsdr_set_tuner_gain() failed");
|
||||
}
|
||||
}
|
||||
|
||||
if((m_settings.m_samplerate != settings.m_samplerate) || force) {
|
||||
if(m_dev != NULL) {
|
||||
if( rtlsdr_set_sample_rate(m_dev, settings.m_samplerate) < 0)
|
||||
qCritical("could not set sample rate: %d", settings.m_samplerate);
|
||||
else {
|
||||
m_settings.m_samplerate = settings.m_samplerate;
|
||||
m_rtlSDRThread->setSamplerate(settings.m_samplerate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((m_settings.m_loPpmCorrection != settings.m_loPpmCorrection) || force) {
|
||||
if(m_dev != NULL) {
|
||||
if( rtlsdr_set_freq_correction(m_dev, settings.m_loPpmCorrection) < 0)
|
||||
if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || force)
|
||||
{
|
||||
if(m_dev != 0)
|
||||
{
|
||||
if( rtlsdr_set_sample_rate(m_dev, settings.m_devSampleRate) < 0)
|
||||
{
|
||||
qCritical("could not set sample rate: %d", settings.m_devSampleRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings.m_devSampleRate = settings.m_devSampleRate;
|
||||
m_rtlSDRThread->setSamplerate(settings.m_devSampleRate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((m_settings.m_loPpmCorrection != settings.m_loPpmCorrection) || force)
|
||||
{
|
||||
if (m_dev != 0)
|
||||
{
|
||||
if (rtlsdr_set_freq_correction(m_dev, settings.m_loPpmCorrection) < 0)
|
||||
{
|
||||
qCritical("could not set LO ppm correction: %d", settings.m_loPpmCorrection);
|
||||
else {
|
||||
}
|
||||
else
|
||||
{
|
||||
m_settings.m_loPpmCorrection = settings.m_loPpmCorrection;
|
||||
//m_rtlSDRThread->setSamplerate(settings.m_samplerate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if((m_settings.m_log2Decim != settings.m_log2Decim) || force) {
|
||||
if(m_dev != NULL) {
|
||||
if ((m_settings.m_log2Decim != settings.m_log2Decim) || force)
|
||||
{
|
||||
if(m_dev != 0)
|
||||
{
|
||||
m_settings.m_log2Decim = settings.m_log2Decim;
|
||||
m_rtlSDRThread->setLog2Decimation(settings.m_log2Decim);
|
||||
}
|
||||
}
|
||||
|
||||
m_generalSettings.m_centerFrequency = generalSettings.m_centerFrequency;
|
||||
if(m_dev != NULL) {
|
||||
qint64 centerFrequency = m_generalSettings.m_centerFrequency + (m_settings.m_samplerate / 4);
|
||||
m_settings.m_centerFrequency = settings.m_centerFrequency;
|
||||
|
||||
if (m_settings.m_log2Decim == 0) { // Little wooby-doop if no decimation
|
||||
centerFrequency = m_generalSettings.m_centerFrequency;
|
||||
} else {
|
||||
centerFrequency = m_generalSettings.m_centerFrequency + (m_settings.m_samplerate / 4);
|
||||
if(m_dev != 0)
|
||||
{
|
||||
qint64 centerFrequency = m_settings.m_centerFrequency + (m_settings.m_devSampleRate / 4);
|
||||
|
||||
if (m_settings.m_log2Decim == 0)
|
||||
{ // Little wooby-doop if no decimation
|
||||
centerFrequency = m_settings.m_centerFrequency;
|
||||
}
|
||||
else
|
||||
{
|
||||
centerFrequency = m_settings.m_centerFrequency + (m_settings.m_devSampleRate / 4);
|
||||
}
|
||||
|
||||
if(rtlsdr_set_center_freq( m_dev, centerFrequency ) != 0)
|
||||
qDebug("osmosdr_set_center_freq(%lld) failed", m_generalSettings.m_centerFrequency);
|
||||
if (rtlsdr_set_center_freq( m_dev, centerFrequency ) != 0)
|
||||
{
|
||||
qDebug("rtlsdr_set_center_freq(%lld) failed", m_settings.m_centerFrequency);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -27,8 +27,9 @@ class RTLSDRThread;
|
|||
class RTLSDRInput : public SampleSource {
|
||||
public:
|
||||
struct Settings {
|
||||
int m_devSampleRate;
|
||||
quint64 m_centerFrequency;
|
||||
qint32 m_gain;
|
||||
qint32 m_samplerate;
|
||||
qint32 m_loPpmCorrection;
|
||||
quint32 m_log2Decim;
|
||||
|
||||
|
@ -42,21 +43,18 @@ public:
|
|||
MESSAGE_CLASS_DECLARATION
|
||||
|
||||
public:
|
||||
const GeneralSettings& getGeneralSettings() const { return m_generalSettings; }
|
||||
const Settings& getSettings() const { return m_settings; }
|
||||
|
||||
static MsgConfigureRTLSDR* create(const GeneralSettings& generalSettings, const Settings& settings)
|
||||
static MsgConfigureRTLSDR* create(const Settings& settings)
|
||||
{
|
||||
return new MsgConfigureRTLSDR(generalSettings, settings);
|
||||
return new MsgConfigureRTLSDR(settings);
|
||||
}
|
||||
|
||||
private:
|
||||
GeneralSettings m_generalSettings;
|
||||
Settings m_settings;
|
||||
|
||||
MsgConfigureRTLSDR(const GeneralSettings& generalSettings, const Settings& settings) :
|
||||
MsgConfigureRTLSDR(const Settings& settings) :
|
||||
Message(),
|
||||
m_generalSettings(generalSettings),
|
||||
m_settings(settings)
|
||||
{ }
|
||||
};
|
||||
|
@ -81,18 +79,18 @@ public:
|
|||
{ }
|
||||
};
|
||||
|
||||
RTLSDRInput(MessageQueue* msgQueueToGUI);
|
||||
~RTLSDRInput();
|
||||
RTLSDRInput();
|
||||
virtual ~RTLSDRInput();
|
||||
|
||||
bool startInput(int device);
|
||||
void stopInput();
|
||||
virtual bool init(const Message& message);
|
||||
virtual bool start(int device);
|
||||
virtual void stop();
|
||||
|
||||
const QString& getDeviceDescription() const;
|
||||
int getSampleRate() const;
|
||||
quint64 getCenterFrequency() const;
|
||||
|
||||
bool handleMessage(Message* message);
|
||||
virtual const QString& getDeviceDescription() const;
|
||||
virtual int getSampleRate() const;
|
||||
virtual quint64 getCenterFrequency() const;
|
||||
|
||||
virtual bool handleMessage(const Message& message);
|
||||
|
||||
void set_ds_mode(int on);
|
||||
|
||||
|
@ -104,7 +102,7 @@ private:
|
|||
QString m_deviceDescription;
|
||||
std::vector<int> m_gains;
|
||||
|
||||
bool applySettings(const GeneralSettings& generalSettings, const Settings& settings, bool force);
|
||||
bool applySettings(const Settings& settings, bool force);
|
||||
};
|
||||
|
||||
#endif // INCLUDE_RTLSDRINPUT_H
|
||||
|
|
|
@ -20,22 +20,6 @@ Channelizer::~Channelizer()
|
|||
freeFilterChain();
|
||||
}
|
||||
|
||||
bool Channelizer::init(const Message& cmd)
|
||||
{
|
||||
if (DSPSignalNotification::match(&cmd))
|
||||
{
|
||||
DSPSignalNotification* notif = (DSPSignalNotification*) &cmd;
|
||||
m_inputSampleRate = notif->getSampleRate();
|
||||
qDebug() << "FileSink::init: DSPSignalNotification: m_inputSampleRate: " << m_inputSampleRate;
|
||||
emit inputSampleRateChanged();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Channelizer::configure(MessageQueue* messageQueue, int sampleRate, int centerFrequency)
|
||||
{
|
||||
Message* cmd = new DSPConfigureChannelizer(sampleRate, centerFrequency);
|
||||
|
@ -84,31 +68,27 @@ bool Channelizer::handleMessage(const Message& cmd)
|
|||
{
|
||||
qDebug() << "Channelizer::handleMessage: " << cmd.getIdentifier();
|
||||
|
||||
/*
|
||||
if (DSPSignalNotification::match(&cmd))
|
||||
if (DSPSignalNotification::match(cmd))
|
||||
{
|
||||
DSPSignalNotification* notif = (DSPSignalNotification*) &cmd;
|
||||
m_inputSampleRate = notif->getSampleRate();
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) cmd;
|
||||
m_inputSampleRate = notif.getSampleRate();
|
||||
qDebug() << "Channelizer::handleMessage: DSPSignalNotification: m_inputSampleRate: " << m_inputSampleRate;
|
||||
applyConfiguration();
|
||||
|
||||
delete cmd;
|
||||
|
||||
if (m_sampleSink != NULL)
|
||||
{
|
||||
DSPSignalNotification notif(m_currentOutputSampleRate, m_currentCenterFrequency);
|
||||
m_sampleSink->handleMessage(notif))
|
||||
m_sampleSink->handleMessage(notif);
|
||||
}
|
||||
|
||||
emit inputSampleRateChanged();
|
||||
return true;
|
||||
}
|
||||
else*/
|
||||
if (DSPConfigureChannelizer::match(&cmd))
|
||||
else
|
||||
if (DSPConfigureChannelizer::match(cmd))
|
||||
{
|
||||
DSPConfigureChannelizer* chan = (DSPConfigureChannelizer*) &cmd;
|
||||
m_requestedOutputSampleRate = chan->getSampleRate();
|
||||
m_requestedCenterFrequency = chan->getCenterFrequency();
|
||||
DSPConfigureChannelizer& chan = (DSPConfigureChannelizer&) cmd;
|
||||
m_requestedOutputSampleRate = chan.getSampleRate();
|
||||
m_requestedCenterFrequency = chan.getCenterFrequency();
|
||||
|
||||
qDebug() << "Channelizer::handleMessage: DSPConfigureChannelizer:"
|
||||
<< " m_requestedOutputSampleRate: " << m_requestedOutputSampleRate
|
||||
|
|
|
@ -27,6 +27,8 @@ MESSAGE_CLASS_DEFINITION(DSPGetErrorMessage, Message)
|
|||
MESSAGE_CLASS_DEFINITION(DSPSetSource, Message)
|
||||
MESSAGE_CLASS_DEFINITION(DSPAddSink, Message)
|
||||
MESSAGE_CLASS_DEFINITION(DSPRemoveSink, Message)
|
||||
MESSAGE_CLASS_DEFINITION(DSPAddThreadedSink, Message)
|
||||
MESSAGE_CLASS_DEFINITION(DSPRemoveThreadedSink, Message)
|
||||
MESSAGE_CLASS_DEFINITION(DSPAddAudioSink, Message)
|
||||
MESSAGE_CLASS_DEFINITION(DSPRemoveAudioSink, Message)
|
||||
MESSAGE_CLASS_DEFINITION(DSPConfigureSpectrumVis, Message)
|
||||
|
|
|
@ -21,13 +21,14 @@
|
|||
#include "dsp/channelizer.h"
|
||||
#include "dsp/samplefifo.h"
|
||||
#include "dsp/samplesink.h"
|
||||
#include "dsp/threadedsamplesink.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
#include "dsp/samplesource/samplesource.h"
|
||||
|
||||
DSPEngine::DSPEngine(QObject* parent) :
|
||||
QThread(parent),
|
||||
m_state(StNotStarted),
|
||||
m_sampleSource(NULL),
|
||||
m_sampleSource(0),
|
||||
m_sampleSinks(),
|
||||
m_sampleRate(0),
|
||||
m_centerFrequency(0),
|
||||
|
@ -71,34 +72,34 @@ void DSPEngine::start()
|
|||
qDebug() << "DSPEngine::start";
|
||||
DSPPing cmd;
|
||||
QThread::start();
|
||||
m_syncMessenger.sendWait(&cmd);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
}
|
||||
|
||||
void DSPEngine::stop()
|
||||
{
|
||||
qDebug() << "DSPEngine::stop";
|
||||
DSPExit cmd;
|
||||
m_syncMessenger.sendWait(&cmd);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
}
|
||||
|
||||
bool DSPEngine::initAcquisition()
|
||||
{
|
||||
DSPAcquisitionInit cmd;
|
||||
|
||||
return m_syncMessenger.sendWait(&cmd) == StReady;
|
||||
return m_syncMessenger.sendWait(cmd) == StReady;
|
||||
}
|
||||
|
||||
bool DSPEngine::startAcquisition()
|
||||
{
|
||||
DSPAcquisitionStart cmd;
|
||||
|
||||
return m_syncMessenger.sendWait(&cmd) == StRunning;
|
||||
return m_syncMessenger.sendWait(cmd) == StRunning;
|
||||
}
|
||||
|
||||
void DSPEngine::stopAcquistion()
|
||||
{
|
||||
DSPAcquisitionStop cmd;
|
||||
m_syncMessenger.sendWait(&cmd);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
|
||||
if(m_dcOffsetCorrection)
|
||||
{
|
||||
|
@ -109,32 +110,45 @@ void DSPEngine::stopAcquistion()
|
|||
void DSPEngine::setSource(SampleSource* source)
|
||||
{
|
||||
DSPSetSource cmd(source);
|
||||
m_syncMessenger.sendWait(&cmd);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
}
|
||||
|
||||
void DSPEngine::addSink(SampleSink* sink)
|
||||
{
|
||||
qDebug() << "DSPEngine::addSink: " << sink->objectName().toStdString().c_str();
|
||||
DSPAddSink cmd(sink);
|
||||
m_syncMessenger.sendWait(&cmd);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
}
|
||||
|
||||
void DSPEngine::removeSink(SampleSink* sink)
|
||||
{
|
||||
DSPRemoveSink cmd(sink);
|
||||
m_syncMessenger.sendWait(&cmd);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
}
|
||||
|
||||
void DSPEngine::addThreadedSink(SampleSink* sink)
|
||||
{
|
||||
qDebug() << "DSPEngine::addThreadedSink: " << sink->objectName().toStdString().c_str();
|
||||
DSPAddThreadedSink cmd(sink);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
}
|
||||
|
||||
void DSPEngine::removeThreadedSink(SampleSink* sink)
|
||||
{
|
||||
DSPRemoveThreadedSink cmd(sink);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
}
|
||||
|
||||
void DSPEngine::addAudioSink(AudioFifo* audioFifo)
|
||||
{
|
||||
DSPAddAudioSink cmd(audioFifo);
|
||||
m_syncMessenger.sendWait(&cmd);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
}
|
||||
|
||||
void DSPEngine::removeAudioSink(AudioFifo* audioFifo)
|
||||
{
|
||||
DSPRemoveAudioSink cmd(audioFifo);
|
||||
m_syncMessenger.sendWait(&cmd);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
}
|
||||
|
||||
void DSPEngine::configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCorrection)
|
||||
|
@ -146,14 +160,14 @@ void DSPEngine::configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCo
|
|||
QString DSPEngine::errorMessage()
|
||||
{
|
||||
DSPGetErrorMessage cmd;
|
||||
m_syncMessenger.sendWait(&cmd);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
return cmd.getErrorMessage();
|
||||
}
|
||||
|
||||
QString DSPEngine::sourceDeviceDescription()
|
||||
{
|
||||
DSPGetSourceDeviceDescription cmd;
|
||||
m_syncMessenger.sendWait(&cmd);
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
return cmd.getDeviceDescription();
|
||||
}
|
||||
|
||||
|
@ -360,11 +374,18 @@ DSPEngine::State DSPEngine::gotoInit()
|
|||
<< " sampleRate: " << m_sampleRate
|
||||
<< " centerFrequency: " << m_centerFrequency;
|
||||
|
||||
for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); it++)
|
||||
DSPSignalNotification notif(m_sampleRate, m_centerFrequency);
|
||||
|
||||
for (SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); ++it)
|
||||
{
|
||||
qDebug() << " - initializing " << (*it)->objectName().toStdString().c_str();
|
||||
DSPSignalNotification notif(m_sampleRate, m_centerFrequency);
|
||||
(*it)->init(notif);
|
||||
(*it)->handleMessage(notif);
|
||||
}
|
||||
|
||||
for (ThreadedSampleSinks::const_iterator it = m_threadedSampleSinks.begin(); it != m_threadedSampleSinks.end(); ++it)
|
||||
{
|
||||
qDebug() << " - initializing ThreadedSampleSink(" << (*it)->getSampleSinkObjectName().toStdString().c_str() << ")";
|
||||
(*it)->sendWaitSink(notif);
|
||||
}
|
||||
|
||||
// pass sample rate to main window
|
||||
|
@ -416,6 +437,12 @@ DSPEngine::State DSPEngine::gotoRunning()
|
|||
(*it)->start();
|
||||
}
|
||||
|
||||
for (ThreadedSampleSinks::const_iterator it = m_threadedSampleSinks.begin(); it != m_threadedSampleSinks.end(); ++it)
|
||||
{
|
||||
qDebug() << " - starting ThreadedSampleSink(" << (*it)->getSampleSinkObjectName().toStdString().c_str() << ")";
|
||||
(*it)->start();
|
||||
}
|
||||
|
||||
qDebug() << " - input message queue pending: " << m_inputMessageQueue.size();
|
||||
|
||||
return StRunning;
|
||||
|
@ -459,7 +486,7 @@ void DSPEngine::handleData()
|
|||
}
|
||||
}
|
||||
|
||||
void DSPEngine::handleSynchronousMessages(Message *message)
|
||||
void DSPEngine::handleSynchronousMessages(const Message& message)
|
||||
{
|
||||
if (DSPExit::match(message))
|
||||
{
|
||||
|
@ -493,27 +520,27 @@ void DSPEngine::handleSynchronousMessages(Message *message)
|
|||
}
|
||||
else if (DSPGetSourceDeviceDescription::match(message))
|
||||
{
|
||||
((DSPGetSourceDeviceDescription*)message)->setDeviceDescription(m_deviceDescription);
|
||||
((DSPGetSourceDeviceDescription&) message).setDeviceDescription(m_deviceDescription);
|
||||
m_syncMessenger.done(m_state);
|
||||
}
|
||||
else if (DSPGetErrorMessage::match(message))
|
||||
{
|
||||
((DSPGetErrorMessage*)message)->setErrorMessage(m_errorMessage);
|
||||
((DSPGetErrorMessage&) message).setErrorMessage(m_errorMessage);
|
||||
m_syncMessenger.done(m_state);
|
||||
}
|
||||
else if (DSPSetSource::match(message)) {
|
||||
handleSetSource(((DSPSetSource*)message)->getSampleSource());
|
||||
handleSetSource(((DSPSetSource&) message).getSampleSource());
|
||||
m_syncMessenger.done(m_state);
|
||||
}
|
||||
else if (DSPAddSink::match(message))
|
||||
{
|
||||
SampleSink* sink = ((DSPAddSink*)message)->getSampleSink();
|
||||
SampleSink* sink = ((DSPAddSink&)message).getSampleSink();
|
||||
m_sampleSinks.push_back(sink);
|
||||
m_syncMessenger.done(m_state);
|
||||
}
|
||||
else if (DSPRemoveSink::match(message))
|
||||
{
|
||||
SampleSink* sink = ((DSPRemoveSink*)message)->getSampleSink();
|
||||
SampleSink* sink = ((DSPRemoveSink&)message).getSampleSink();
|
||||
|
||||
if(m_state == StRunning) {
|
||||
sink->stop();
|
||||
|
@ -522,14 +549,46 @@ void DSPEngine::handleSynchronousMessages(Message *message)
|
|||
m_sampleSinks.remove(sink);
|
||||
m_syncMessenger.done(m_state);
|
||||
}
|
||||
else if (DSPAddThreadedSink::match(message))
|
||||
{
|
||||
SampleSink* sink = ((DSPAddThreadedSink&) message).getSampleSink();
|
||||
ThreadedSampleSink *threadedSink = new ThreadedSampleSink(sink);
|
||||
m_threadedSampleSinks.push_back(threadedSink);
|
||||
threadedSink->start();
|
||||
m_syncMessenger.done(m_state);
|
||||
}
|
||||
else if (DSPRemoveThreadedSink::match(message))
|
||||
{
|
||||
SampleSink* sink = ((DSPRemoveThreadedSink&) message).getSampleSink();
|
||||
ThreadedSampleSinks::iterator threadedSinkIt = m_threadedSampleSinks.begin();
|
||||
|
||||
for (; threadedSinkIt != m_threadedSampleSinks.end(); ++threadedSinkIt)
|
||||
{
|
||||
if ((*threadedSinkIt)->getSink() == sink)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (threadedSinkIt != m_threadedSampleSinks.end())
|
||||
{
|
||||
if (m_state == StRunning)
|
||||
{
|
||||
(*threadedSinkIt)->stop();
|
||||
}
|
||||
|
||||
m_threadedSampleSinks.remove(*threadedSinkIt);
|
||||
delete (*threadedSinkIt);
|
||||
}
|
||||
}
|
||||
else if (DSPAddAudioSink::match(message))
|
||||
{
|
||||
m_audioSink.addFifo(((DSPAddAudioSink*)message)->getAudioFifo());
|
||||
m_audioSink.addFifo(((DSPAddAudioSink&) message).getAudioFifo());
|
||||
m_syncMessenger.done(m_state);
|
||||
}
|
||||
else if (DSPRemoveAudioSink::match(message))
|
||||
{
|
||||
m_audioSink.removeFifo(((DSPRemoveAudioSink*)message)->getAudioFifo());
|
||||
m_audioSink.removeFifo(((DSPRemoveAudioSink&) message).getAudioFifo());
|
||||
m_syncMessenger.done(m_state);
|
||||
}
|
||||
|
||||
|
@ -544,9 +603,9 @@ void DSPEngine::handleInputMessages()
|
|||
{
|
||||
qDebug("DSPEngine::handleInputMessages: Message: %s", message->getIdentifier());
|
||||
|
||||
if (DSPConfigureCorrection::match(message))
|
||||
if (DSPConfigureCorrection::match(*message))
|
||||
{
|
||||
DSPConfigureCorrection* conf = (DSPConfigureCorrection*)message;
|
||||
DSPConfigureCorrection* conf = (DSPConfigureCorrection*) message;
|
||||
m_iqImbalanceCorrection = conf->getIQImbalanceCorrection();
|
||||
|
||||
if(m_dcOffsetCorrection != conf->getDCOffsetCorrection())
|
||||
|
@ -577,21 +636,29 @@ void DSPEngine::handleSourceMessages()
|
|||
|
||||
while ((message = m_sampleSource->getOutputMessageQueue()->pop()) != 0)
|
||||
{
|
||||
if (DSPSignalNotification::match(message))
|
||||
if (DSPSignalNotification::match(*message))
|
||||
{
|
||||
DSPSignalNotification *notif = (DSPSignalNotification *) &message;
|
||||
DSPSignalNotification *notif = (DSPSignalNotification *) message;
|
||||
|
||||
// update DSP values
|
||||
|
||||
m_sampleRate = notif->getSampleRate();
|
||||
m_centerFrequency = notif->getFrequencyOffset();
|
||||
|
||||
qDebug() << " - DSPSignalNotification(" << m_sampleRate << "," << m_centerFrequency << ")";
|
||||
|
||||
// forward source changes to sinks
|
||||
|
||||
for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); it++)
|
||||
{
|
||||
qDebug() << " - initializing " << (*it)->objectName().toStdString().c_str();
|
||||
(*it)->init(*message);
|
||||
qDebug() << " - forward message to " << (*it)->objectName().toStdString().c_str();
|
||||
(*it)->handleMessage(*message);
|
||||
}
|
||||
|
||||
for (ThreadedSampleSinks::const_iterator it = m_threadedSampleSinks.begin(); it != m_threadedSampleSinks.end(); ++it)
|
||||
{
|
||||
qDebug() << " - forward message to ThreadedSampleSink(" << (*it)->getSampleSinkObjectName().toStdString().c_str() << ")";
|
||||
(*it)->sendWaitSink(*message);
|
||||
}
|
||||
|
||||
// forward changes to listeners
|
||||
|
|
|
@ -30,22 +30,6 @@ void FileSink::configure(MessageQueue* msgQueue, const std::string& filename)
|
|||
msgQueue->push(cmd);
|
||||
}
|
||||
|
||||
bool FileSink::init(const Message& cmd)
|
||||
{
|
||||
if (DSPSignalNotification::match(&cmd))
|
||||
{
|
||||
DSPSignalNotification* notif = (DSPSignalNotification*) &cmd;
|
||||
m_sampleRate = notif->getSampleRate();
|
||||
m_centerFrequency = notif->getFrequencyOffset();
|
||||
qDebug() << "FileSink::init: DSPSignalNotification: m_inputSampleRate: " << m_sampleRate;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void FileSink::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
|
||||
{
|
||||
// if no recording is active, send the samples to /dev/null
|
||||
|
@ -99,12 +83,22 @@ void FileSink::stopRecording()
|
|||
|
||||
bool FileSink::handleMessage(const Message& message)
|
||||
{
|
||||
if (MsgConfigureFileSink::match(&message))
|
||||
qDebug() << "FileSink::handleMessage";
|
||||
|
||||
if (DSPSignalNotification::match(message))
|
||||
{
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) message;
|
||||
m_sampleRate = notif.getSampleRate();
|
||||
m_centerFrequency = notif.getFrequencyOffset();
|
||||
qDebug() << " - DSPSignalNotification: m_inputSampleRate: " << m_sampleRate
|
||||
<< " m_centerFrequency: " << m_centerFrequency;
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureFileSink::match(message))
|
||||
{
|
||||
MsgConfigureFileSink* conf = (MsgConfigureFileSink*) &message;
|
||||
handleConfigure(conf->getFileName());
|
||||
qDebug() << "FileSink::handleMessage:"
|
||||
<< " fileName: " << m_fileName.c_str();
|
||||
MsgConfigureFileSink& conf = (MsgConfigureFileSink&) message;
|
||||
handleConfigure(conf.getFileName());
|
||||
qDebug() << " - MsgConfigureFileSink: fileName: " << m_fileName.c_str();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1,9 +1,25 @@
|
|||
#include "dsp/samplesink.h"
|
||||
#include "util/message.h"
|
||||
|
||||
SampleSink::SampleSink()
|
||||
{
|
||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessage()));
|
||||
}
|
||||
|
||||
SampleSink::~SampleSink()
|
||||
{
|
||||
}
|
||||
|
||||
void SampleSink::handleInputMessages()
|
||||
{
|
||||
Message* message;
|
||||
|
||||
while ((message = m_inputMessageQueue.pop()) != 0)
|
||||
{
|
||||
if (handleMessage(*message))
|
||||
{
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,41 +16,11 @@
|
|||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "dsp/samplesource/samplesource.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
SampleSource::SampleSource() :
|
||||
m_sampleRate(0),
|
||||
m_centerFrequency(0)
|
||||
SampleSource::SampleSource()
|
||||
{
|
||||
}
|
||||
|
||||
SampleSource::~SampleSource()
|
||||
{
|
||||
}
|
||||
|
||||
void SampleSource::setSampleRate(int sampleRate)
|
||||
{
|
||||
if (sampleRate != m_sampleRate)
|
||||
{
|
||||
// TODO: adjust FIFO size
|
||||
m_sampleRate = sampleRate;
|
||||
sendNewData();
|
||||
}
|
||||
}
|
||||
|
||||
void SampleSource::setCenterFrequency(quint64 centerFrequency)
|
||||
{
|
||||
if (centerFrequency != m_centerFrequency)
|
||||
{
|
||||
m_centerFrequency = centerFrequency;
|
||||
sendNewData();
|
||||
}
|
||||
}
|
||||
|
||||
void SampleSource::sendNewData()
|
||||
{
|
||||
DSPSignalNotification *notif = new DSPSignalNotification(m_sampleRate, m_centerFrequency);
|
||||
m_outputMessageQueue.push(notif);
|
||||
}
|
||||
|
|
|
@ -55,20 +55,6 @@ void ScopeVis::configure(MessageQueue* msgQueue,
|
|||
msgQueue->push(cmd);
|
||||
}
|
||||
|
||||
bool ScopeVis::init(const Message& cmd)
|
||||
{
|
||||
if (DSPSignalNotification::match(&cmd))
|
||||
{
|
||||
DSPSignalNotification* signal = (DSPSignalNotification*) &cmd;
|
||||
m_sampleRate = signal->getSampleRate();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void ScopeVis::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
|
||||
{
|
||||
if (m_triggerChannel == TriggerFreeRun) {
|
||||
|
@ -220,28 +206,47 @@ void ScopeVis::stop()
|
|||
|
||||
bool ScopeVis::handleMessage(const Message& message)
|
||||
{
|
||||
if (MsgConfigureScopeVis::match(&message))
|
||||
qDebug() << "ScopeVis::handleMessage";
|
||||
|
||||
if (DSPSignalNotification::match(message))
|
||||
{
|
||||
MsgConfigureScopeVis* conf = (MsgConfigureScopeVis*) &message;
|
||||
m_tracebackCount = 0;
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) message;
|
||||
m_sampleRate = notif.getSampleRate();
|
||||
qDebug() << " - DSPSignalNotification: m_sampleRate: " << m_sampleRate;
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MsgConfigureScopeVis::match(message))
|
||||
{
|
||||
MsgConfigureScopeVis& conf = (MsgConfigureScopeVis&) message;
|
||||
|
||||
m_tracebackCount = 0;
|
||||
m_triggerState = Config;
|
||||
m_triggerChannel = (TriggerChannel) conf->getTriggerChannel();
|
||||
m_triggerLevel = conf->getTriggerLevel();
|
||||
m_triggerPositiveEdge = conf->getTriggerPositiveEdge();
|
||||
m_triggerBothEdges = conf->getTriggerBothEdges();
|
||||
m_triggerPre = conf->getTriggerPre();
|
||||
if (m_triggerPre >= m_traceback.size()) {
|
||||
m_triggerChannel = (TriggerChannel) conf.getTriggerChannel();
|
||||
m_triggerLevel = conf.getTriggerLevel();
|
||||
m_triggerPositiveEdge = conf.getTriggerPositiveEdge();
|
||||
m_triggerBothEdges = conf.getTriggerBothEdges();
|
||||
m_triggerPre = conf.getTriggerPre();
|
||||
|
||||
if (m_triggerPre >= m_traceback.size())
|
||||
{
|
||||
m_triggerPre = m_traceback.size() - 1; // top sample in FIFO is always the triggering one (pre-trigger delay = 0)
|
||||
}
|
||||
m_triggerDelay = conf->getTriggerDelay();
|
||||
uint newSize = conf->getTraceSize();
|
||||
if (newSize != m_trace.size()) {
|
||||
|
||||
m_triggerDelay = conf.getTriggerDelay();
|
||||
uint newSize = conf.getTraceSize();
|
||||
|
||||
if (newSize != m_trace.size())
|
||||
{
|
||||
m_trace.resize(newSize);
|
||||
}
|
||||
if (newSize > m_traceback.size()) { // fitting the exact required space is not a requirement for the back trace
|
||||
|
||||
if (newSize > m_traceback.size()) // fitting the exact required space is not a requirement for the back trace
|
||||
{
|
||||
m_traceback.resize(newSize);
|
||||
}
|
||||
qDebug() << "ScopeVis::handleMessage:"
|
||||
|
||||
qDebug() << " - MsgConfigureScopeVis:"
|
||||
<< " m_triggerChannel: " << m_triggerChannel
|
||||
<< " m_triggerLevel: " << m_triggerLevel
|
||||
<< " m_triggerPositiveEdge: " << (m_triggerPositiveEdge ? "edge+" : "edge-")
|
||||
|
@ -249,6 +254,7 @@ bool ScopeVis::handleMessage(const Message& message)
|
|||
<< " m_preTrigger: " << m_triggerPre
|
||||
<< " m_triggerDelay: " << m_triggerDelay
|
||||
<< " m_traceSize: " << m_trace.size();
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -13,14 +13,6 @@ SpectrumScopeComboVis::~SpectrumScopeComboVis()
|
|||
{
|
||||
}
|
||||
|
||||
bool SpectrumScopeComboVis::init(const Message& cmd)
|
||||
{
|
||||
bool spectDone = m_spectrumVis->init(cmd);
|
||||
bool scopeDone = m_scopeVis->init(cmd);
|
||||
|
||||
return (spectDone || scopeDone);
|
||||
}
|
||||
|
||||
void SpectrumScopeComboVis::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
|
||||
{
|
||||
m_scopeVis->feed(begin, end, false);
|
||||
|
|
|
@ -30,11 +30,6 @@ SpectrumVis::~SpectrumVis()
|
|||
delete m_fft;
|
||||
}
|
||||
|
||||
bool SpectrumVis::init(const Message& cmd)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void SpectrumVis::configure(MessageQueue* msgQueue, int fftSize, int overlapPercent, FFTWindow::Function window)
|
||||
{
|
||||
DSPConfigureSpectrumVis* cmd = new DSPConfigureSpectrumVis(fftSize, overlapPercent, window);
|
||||
|
@ -69,13 +64,13 @@ void SpectrumVis::feed(SampleVector::const_iterator begin, SampleVector::const_i
|
|||
return;
|
||||
|
||||
while(begin < end) {
|
||||
size_t todo = end - begin;
|
||||
size_t samplesNeeded = m_refillSize - m_fftBufferFill;
|
||||
std::size_t todo = end - begin;
|
||||
std::size_t samplesNeeded = m_refillSize - m_fftBufferFill;
|
||||
|
||||
if(todo >= samplesNeeded) {
|
||||
// fill up the buffer
|
||||
std::vector<Complex>::iterator it = m_fftBuffer.begin() + m_fftBufferFill;
|
||||
for(size_t i = 0; i < samplesNeeded; ++i, ++begin)
|
||||
for(std::size_t i = 0; i < samplesNeeded; ++i, ++begin)
|
||||
*it++ = Complex(begin->real() / 32768.0, begin->imag() / 32768.0);
|
||||
|
||||
// apply fft window (and copy from m_fftBuffer to m_fftIn)
|
||||
|
@ -90,10 +85,10 @@ void SpectrumVis::feed(SampleVector::const_iterator begin, SampleVector::const_i
|
|||
const Complex* fftOut = m_fft->out();
|
||||
Complex c;
|
||||
Real v;
|
||||
size_t halfSize = m_fftSize / 2;
|
||||
std::size_t halfSize = m_fftSize / 2;
|
||||
|
||||
if ( positiveOnly ) {
|
||||
for(size_t i = 0; i < halfSize; i++) {
|
||||
for(std::size_t i = 0; i < halfSize; i++) {
|
||||
c = fftOut[i];
|
||||
v = c.real() * c.real() + c.imag() * c.imag();
|
||||
v = mult * log2f(v) + ofs;
|
||||
|
@ -101,7 +96,7 @@ void SpectrumVis::feed(SampleVector::const_iterator begin, SampleVector::const_i
|
|||
m_logPowerSpectrum[i * 2 + 1] = v;
|
||||
}
|
||||
} else {
|
||||
for(size_t i = 0; i < halfSize; i++) {
|
||||
for(std::size_t i = 0; i < halfSize; i++) {
|
||||
c = fftOut[i + halfSize];
|
||||
v = c.real() * c.real() + c.imag() * c.imag();
|
||||
v = mult * log2f(v) + ofs;
|
||||
|
@ -143,10 +138,10 @@ void SpectrumVis::stop()
|
|||
|
||||
bool SpectrumVis::handleMessage(const Message& message)
|
||||
{
|
||||
if(DSPConfigureSpectrumVis::match(&message))
|
||||
if (DSPConfigureSpectrumVis::match(message))
|
||||
{
|
||||
DSPConfigureSpectrumVis* conf = (DSPConfigureSpectrumVis*) &message;
|
||||
handleConfigure(conf->getFFTSize(), conf->getOverlapPercent(), conf->getWindow());
|
||||
DSPConfigureSpectrumVis& conf = (DSPConfigureSpectrumVis&) message;
|
||||
handleConfigure(conf.getFFTSize(), conf.getOverlapPercent(), conf.getWindow());
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -4,59 +4,56 @@
|
|||
#include "util/message.h"
|
||||
|
||||
ThreadedSampleSink::ThreadedSampleSink(SampleSink* sampleSink) :
|
||||
m_thread(new QThread),
|
||||
m_sampleSink(sampleSink)
|
||||
{
|
||||
setObjectName("ThreadedSampleSink");
|
||||
moveToThread(m_thread);
|
||||
connect(m_thread, SIGNAL(started()), this, SLOT(threadStarted()));
|
||||
connect(m_thread, SIGNAL(finished()), this, SLOT(threadFinished()));
|
||||
|
||||
m_messageQueue.moveToThread(m_thread);
|
||||
connect(&m_messageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleMessages()));
|
||||
|
||||
m_sampleFifo.moveToThread(m_thread);
|
||||
connect(&m_sampleFifo, SIGNAL(dataReady()), this, SLOT(handleData()));
|
||||
m_sampleFifo.setSize(262144);
|
||||
|
||||
sampleSink->moveToThread(m_thread);
|
||||
moveToThread(this);
|
||||
}
|
||||
|
||||
ThreadedSampleSink::~ThreadedSampleSink()
|
||||
{
|
||||
m_thread->exit();
|
||||
m_thread->wait();
|
||||
delete m_thread;
|
||||
}
|
||||
|
||||
void ThreadedSampleSink::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
|
||||
{
|
||||
Q_UNUSED(positiveOnly);
|
||||
m_sampleFifo.write(begin, end);
|
||||
wait();
|
||||
}
|
||||
|
||||
void ThreadedSampleSink::start()
|
||||
{
|
||||
m_thread->start();
|
||||
QThread::start();
|
||||
}
|
||||
|
||||
void ThreadedSampleSink::stop()
|
||||
{
|
||||
m_thread->exit();
|
||||
m_thread->wait();
|
||||
m_sampleFifo.readCommit(m_sampleFifo.fill());
|
||||
exit();
|
||||
wait();
|
||||
}
|
||||
|
||||
bool ThreadedSampleSink::handleMessage(Message* cmd)
|
||||
void ThreadedSampleSink::run()
|
||||
{
|
||||
qDebug() << "ThreadedSampleSink::handleMessage: "
|
||||
<< m_sampleSink->objectName().toStdString().c_str()
|
||||
<< ": " << cmd->getIdentifier();
|
||||
// called from other thread
|
||||
m_messageQueue.submit(cmd);
|
||||
return true;
|
||||
connect(&m_syncMessenger, SIGNAL(messageSent(const Message&)), this, SLOT(handleSynchronousMessages(const Message&)), Qt::QueuedConnection);
|
||||
exec();
|
||||
}
|
||||
|
||||
void ThreadedSampleSink::feed(SampleVector::const_iterator& begin, SampleVector::const_iterator& end, bool positiveOnly)
|
||||
{
|
||||
m_sampleSink->feed(begin, end, positiveOnly);
|
||||
}
|
||||
|
||||
bool ThreadedSampleSink::sendWaitSink(const Message& cmd)
|
||||
{
|
||||
m_syncMessenger.sendWait(cmd);
|
||||
}
|
||||
|
||||
void ThreadedSampleSink::handleSynchronousMessages(const Message& message)
|
||||
{
|
||||
m_sampleSink->handleMessage(message); // just delegate to the sink
|
||||
m_syncMessenger.done();
|
||||
}
|
||||
|
||||
QString ThreadedSampleSink::getSampleSinkObjectName() const
|
||||
{
|
||||
return m_sampleSink->objectName();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void ThreadedSampleSink::handleData()
|
||||
{
|
||||
bool positiveOnly = false;
|
||||
|
@ -84,30 +81,5 @@ void ThreadedSampleSink::handleData()
|
|||
m_sampleFifo.readCommit(part2end - part2begin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
void ThreadedSampleSink::handleMessages()
|
||||
{
|
||||
Message* message;
|
||||
while((message = m_messageQueue.accept()) != NULL) {
|
||||
qDebug("ThreadedSampleSink::handleMessages: %s", message->getIdentifier());
|
||||
if(m_sampleSink != NULL) {
|
||||
if(!m_sampleSink->handleMessage(message))
|
||||
message->completed();
|
||||
} else {
|
||||
message->completed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ThreadedSampleSink::threadStarted()
|
||||
{
|
||||
if(m_sampleSink != NULL)
|
||||
m_sampleSink->start();
|
||||
}
|
||||
|
||||
void ThreadedSampleSink::threadFinished()
|
||||
{
|
||||
if(m_sampleSink != NULL)
|
||||
m_sampleSink->stop();
|
||||
}
|
||||
|
|
|
@ -325,9 +325,9 @@ void MainWindow::handleDSPMessages()
|
|||
|
||||
std::cerr << "MainWindow::handleDSPMessages: " << message->getIdentifier() << std::endl;
|
||||
|
||||
if (DSPEngineReport::match(message))
|
||||
if (DSPEngineReport::match(*message))
|
||||
{
|
||||
DSPEngineReport* rep = (DSPEngineReport*)message;
|
||||
DSPEngineReport* rep = (DSPEngineReport*) message;
|
||||
m_sampleRate = rep->getSampleRate();
|
||||
m_centerFrequency = rep->getCenterFrequency();
|
||||
qDebug("SampleRate:%d, CenterFrequency:%llu", rep->getSampleRate(), rep->getCenterFrequency());
|
||||
|
@ -350,7 +350,7 @@ void MainWindow::handleMessages()
|
|||
qDebug("Message: %s", message->getIdentifier());
|
||||
std::cerr << "MainWindow::handleMessages: " << message->getIdentifier() << std::endl;
|
||||
|
||||
if (!m_pluginManager->handleMessage(message))
|
||||
if (!m_pluginManager->handleMessage(*message))
|
||||
{
|
||||
delete message;
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ void PluginAPI::removeChannelMarker(ChannelMarker* channelMarker)
|
|||
m_mainWindow->removeChannelMarker(channelMarker);
|
||||
}
|
||||
|
||||
/*
|
||||
void PluginAPI::setSampleSource(SampleSource* sampleSource)
|
||||
{
|
||||
m_dspEngine->stopAcquistion();
|
||||
|
@ -83,7 +84,7 @@ void PluginAPI::addAudioSource(AudioFifo* audioFifo)
|
|||
void PluginAPI::removeAudioSource(AudioFifo* audioFifo)
|
||||
{
|
||||
m_dspEngine->removeAudioSink(audioFifo);
|
||||
}
|
||||
}*/
|
||||
|
||||
void PluginAPI::registerSampleSource(const QString& sourceName, PluginInterface* plugin)
|
||||
{
|
||||
|
|
|
@ -177,21 +177,30 @@ void PluginManager::freeAll()
|
|||
}
|
||||
}
|
||||
|
||||
bool PluginManager::handleMessage(Message* message)
|
||||
bool PluginManager::handleMessage(const Message& message)
|
||||
{
|
||||
if(m_sampleSourceInstance != NULL) {
|
||||
if((message->getDestination() == NULL) || (message->getDestination() == m_sampleSourceInstance)) {
|
||||
if(m_sampleSourceInstance->handleMessage(message))
|
||||
if (m_sampleSourceInstance != 0)
|
||||
{
|
||||
if ((message.getDestination() == 0) || (message.getDestination() == m_sampleSourceInstance))
|
||||
{
|
||||
if (m_sampleSourceInstance->handleMessage(message))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(ChannelInstanceRegistrations::iterator it = m_channelInstanceRegistrations.begin(); it != m_channelInstanceRegistrations.end(); ++it) {
|
||||
if((message->getDestination() == NULL) || (message->getDestination() == it->m_gui)) {
|
||||
if(it->m_gui->handleMessage(message))
|
||||
for (ChannelInstanceRegistrations::iterator it = m_channelInstanceRegistrations.begin(); it != m_channelInstanceRegistrations.end(); ++it)
|
||||
{
|
||||
if ((message.getDestination() == 0) || (message.getDestination() == it->m_gui))
|
||||
{
|
||||
if (it->m_gui->handleMessage(message))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ SyncMessenger::SyncMessenger() :
|
|||
SyncMessenger::~SyncMessenger()
|
||||
{}
|
||||
|
||||
int SyncMessenger::sendWait(Message *message, unsigned long msPollTime)
|
||||
int SyncMessenger::sendWait(const Message& message, unsigned long msPollTime)
|
||||
{
|
||||
m_mutex.lock();
|
||||
m_complete.testAndSetAcquire(0, 1);
|
||||
|
|
Loading…
Reference in New Issue