mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-04-08 16:03:43 +00:00
Move DFT/TDR calculation into dedicated thread, limit update rate
This commit is contained in:
parent
fd786c4176
commit
8e47d14192
5 changed files with 299 additions and 148 deletions
|
|
@ -6,6 +6,8 @@
|
|||
#include "ui_dftdialog.h"
|
||||
#include "ui_dftexplanationwidget.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
using namespace std;
|
||||
|
||||
Math::DFT::DFT()
|
||||
|
|
@ -13,9 +15,22 @@ Math::DFT::DFT()
|
|||
automaticDC = true;
|
||||
DCfreq = 1000000000.0;
|
||||
|
||||
destructing = false;
|
||||
thread = new DFTThread(*this);
|
||||
thread->start(TDRThread::Priority::LowestPriority);
|
||||
|
||||
connect(&window, &WindowFunction::changed, this, &DFT::updateDFT);
|
||||
}
|
||||
|
||||
Math::DFT::~DFT()
|
||||
{
|
||||
// tell thread to exit
|
||||
destructing = true;
|
||||
semphr.release();
|
||||
thread->wait();
|
||||
delete thread;
|
||||
}
|
||||
|
||||
TraceMath::DataType Math::DFT::outputType(TraceMath::DataType inputType)
|
||||
{
|
||||
if(inputType == DataType::Time) {
|
||||
|
|
@ -120,66 +135,8 @@ void Math::DFT::inputSamplesChanged(unsigned int begin, unsigned int end)
|
|||
// not the end, do nothing
|
||||
return;
|
||||
}
|
||||
double DC = DCfreq;
|
||||
TDR *tdr = nullptr;
|
||||
if(automaticDC) {
|
||||
// find the last operation that transformed from the frequency domain to the time domain
|
||||
auto in = input;
|
||||
while(in->getInput()->getDataType() != DataType::Frequency) {
|
||||
in = input->getInput();
|
||||
}
|
||||
switch(in->getType()) {
|
||||
case Type::TDR: {
|
||||
tdr = static_cast<TDR*>(in);
|
||||
if(tdr->getMode() == TDR::Mode::Lowpass) {
|
||||
DC = 0;
|
||||
} else {
|
||||
// bandpass mode, assume DC is in the middle of the frequency data
|
||||
DC = tdr->getInput()->getSample(tdr->getInput()->numSamples()/2).x;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// unknown, assume DC is in the middle of the frequency data
|
||||
DC = in->getInput()->getSample(in->getInput()->numSamples()/2).x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto samples = input->rData().size();
|
||||
auto timeSpacing = input->rData()[1].x - input->rData()[0].x;
|
||||
vector<complex<double>> timeDomain(samples);
|
||||
for(unsigned int i=0;i<samples;i++) {
|
||||
timeDomain.at(i) = input->rData()[i].y;
|
||||
}
|
||||
|
||||
Fft::shift(timeDomain, false);
|
||||
window.apply(timeDomain);
|
||||
Fft::shift(timeDomain, true);
|
||||
Fft::transform(timeDomain, false);
|
||||
// shift DC bin into the middle
|
||||
Fft::shift(timeDomain, false);
|
||||
|
||||
double binSpacing = 1.0 / (timeSpacing * timeDomain.size());
|
||||
data.clear();
|
||||
int DCbin = timeDomain.size() / 2, startBin = 0;
|
||||
if(DC > 0) {
|
||||
data.resize(timeDomain.size());
|
||||
} else {
|
||||
startBin = (timeDomain.size()+1) / 2;
|
||||
data.resize(timeDomain.size()/2);
|
||||
}
|
||||
|
||||
// reverse effect of frequency domain window function from TDR (if available)
|
||||
if(tdr) {
|
||||
tdr->getWindow().reverse(timeDomain);
|
||||
}
|
||||
|
||||
for(int i = startBin;(unsigned int) i<timeDomain.size();i++) {
|
||||
auto freq = (i - DCbin) * binSpacing + DC;
|
||||
data[i - startBin].x = round(freq);
|
||||
data[i - startBin].y = timeDomain.at(i);
|
||||
}
|
||||
emit outputSamplesChanged(0, data.size());
|
||||
// trigger calculation in thread
|
||||
semphr.release();
|
||||
success();
|
||||
}
|
||||
|
||||
|
|
@ -189,3 +146,85 @@ void Math::DFT::updateDFT()
|
|||
inputSamplesChanged(0, input->rData().size());
|
||||
}
|
||||
}
|
||||
|
||||
Math::DFTThread::DFTThread(Math::DFT &dft)
|
||||
: dft(dft)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Math::DFTThread::run()
|
||||
{
|
||||
qDebug() << "DFT thread starting";
|
||||
while(1) {
|
||||
dft.semphr.acquire();
|
||||
// clear possible additional semaphores
|
||||
dft.semphr.tryAcquire(dft.semphr.available());
|
||||
if(dft.destructing) {
|
||||
// TDR object about to be deleted, exit thread
|
||||
qDebug() << "DFT thread exiting";
|
||||
return;
|
||||
}
|
||||
qDebug() << "DFT thread calculating";
|
||||
double DC = dft.DCfreq;
|
||||
TDR *tdr = nullptr;
|
||||
if(dft.automaticDC) {
|
||||
// find the last operation that transformed from the frequency domain to the time domain
|
||||
auto in = dft.input;
|
||||
while(in->getInput()->getDataType() != DFT::DataType::Frequency) {
|
||||
in = dft.input->getInput();
|
||||
}
|
||||
switch(in->getType()) {
|
||||
case DFT::Type::TDR: {
|
||||
tdr = static_cast<TDR*>(in);
|
||||
if(tdr->getMode() == TDR::Mode::Lowpass) {
|
||||
DC = 0;
|
||||
} else {
|
||||
// bandpass mode, assume DC is in the middle of the frequency data
|
||||
DC = tdr->getInput()->getSample(tdr->getInput()->numSamples()/2).x;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// unknown, assume DC is in the middle of the frequency data
|
||||
DC = in->getInput()->getSample(in->getInput()->numSamples()/2).x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto samples = dft.input->rData().size();
|
||||
auto timeSpacing = dft.input->rData()[1].x - dft.input->rData()[0].x;
|
||||
vector<complex<double>> timeDomain(samples);
|
||||
for(unsigned int i=0;i<samples;i++) {
|
||||
timeDomain.at(i) = dft.input->rData()[i].y;
|
||||
}
|
||||
|
||||
Fft::shift(timeDomain, false);
|
||||
dft.window.apply(timeDomain);
|
||||
Fft::shift(timeDomain, true);
|
||||
Fft::transform(timeDomain, false);
|
||||
// shift DC bin into the middle
|
||||
Fft::shift(timeDomain, false);
|
||||
|
||||
double binSpacing = 1.0 / (timeSpacing * timeDomain.size());
|
||||
dft.data.clear();
|
||||
int DCbin = timeDomain.size() / 2, startBin = 0;
|
||||
if(DC > 0) {
|
||||
dft.data.resize(timeDomain.size());
|
||||
} else {
|
||||
startBin = (timeDomain.size()+1) / 2;
|
||||
dft.data.resize(timeDomain.size()/2);
|
||||
}
|
||||
|
||||
// reverse effect of frequency domain window function from TDR (if available)
|
||||
if(tdr) {
|
||||
tdr->getWindow().reverse(timeDomain);
|
||||
}
|
||||
|
||||
for(int i = startBin;(unsigned int) i<timeDomain.size();i++) {
|
||||
auto freq = (i - DCbin) * binSpacing + DC;
|
||||
dft.data[i - startBin].x = round(freq);
|
||||
dft.data[i - startBin].y = timeDomain.at(i);
|
||||
}
|
||||
emit dft.outputSamplesChanged(0, dft.data.size());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue