Skip to content

Commit

Permalink
add mutex for trace data (fixes DFT/TDR thread crashes)
Browse files Browse the repository at this point in the history
  • Loading branch information
jankae committed Dec 17, 2024
1 parent acb79fa commit 70ac53a
Show file tree
Hide file tree
Showing 17 changed files with 315 additions and 141 deletions.
42 changes: 31 additions & 11 deletions Software/PC_Application/LibreVNA-GUI/Traces/Math/dft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,9 @@ void Math::DFT::inputSamplesChanged(unsigned int begin, unsigned int end)
{
Q_UNUSED(begin);
Q_UNUSED(end);
if(input->rData().size() < 2) {
if(input->getData().size() < 2) {
// not enough input data
data.clear();
emit outputSamplesChanged(0, 0);
clearOutput();
warning("Not enough input samples");
return;
}
Expand All @@ -162,10 +161,18 @@ void Math::DFT::inputSamplesChanged(unsigned int begin, unsigned int end)
void Math::DFT::updateDFT()
{
if(dataType != DataType::Invalid) {
inputSamplesChanged(0, input->rData().size());
inputSamplesChanged(0, input->getData().size());
}
}

void Math::DFT::clearOutput()
{
dataMutex.lock();
data.clear();
dataMutex.unlock();
emit outputSamplesChanged(0, 0);
}

Math::DFTThread::DFTThread(Math::DFT &dft)
: dft(dft)
{
Expand All @@ -186,11 +193,18 @@ void Math::DFTThread::run()
qDebug() << "DFT thread exiting";
return;
}
// qDebug() << "DFT thread calculating";
// qDebug() << "DFT thread calculating";
if(!dft.input) {
// not connected, skip calculation
continue;
}
auto inputData = dft.input->getData();
if(!inputData.size()) {
dft.clearOutput();
dft.warning("Not enough input samples");
continue;
}

double DC = dft.DCfreq;
TDR *tdr = nullptr;
// find the last TDR operation
Expand All @@ -213,14 +227,15 @@ void Math::DFTThread::run()
DC = tdr->getInput()->getSample(tdr->getInput()->numSamples()/2).x;
}
}
auto samples = dft.input->rData().size();
auto timeSpacing = dft.input->rData()[1].x - dft.input->rData()[0].x;
auto samples = inputData.size();
auto timeSpacing = inputData[1].x - inputData[0].x;
vector<complex<double>> timeDomain(samples);
for(unsigned int i=0;i<samples;i++) {
timeDomain.at(i) = dft.input->rData()[i].y;
timeDomain.at(i) = inputData[i].y;
}

dft.window.apply(timeDomain);
Fft::shift(timeDomain, true);
Fft::transform(timeDomain, false);
// shift DC bin into the middle
Fft::shift(timeDomain, false);
Expand All @@ -229,7 +244,10 @@ void Math::DFTThread::run()

if(tdr) {
// split in padding and actual data sections
unsigned int padding = timeDomain.size() - tdr->getUnpaddedInputSize();
unsigned int padding = 0;
if(timeDomain.size() > tdr->getUnpaddedInputSize()) {
padding = timeDomain.size() - tdr->getUnpaddedInputSize();
}
std::vector<std::complex<double>> pad_front(timeDomain.begin(), timeDomain.begin()+padding/2);
std::vector<std::complex<double>> data(timeDomain.begin()+padding/2, timeDomain.end()-padding/2);
std::vector<std::complex<double>> pad_back(timeDomain.end()-padding/2, timeDomain.end());
Expand All @@ -248,8 +266,8 @@ void Math::DFTThread::run()
}
}

dft.data.clear();
int DCbin = timeDomain.size() / 2, startBin = 0;
dft.dataMutex.lock();
if(DC > 0) {
dft.data.resize(timeDomain.size(), TraceMath::Data());
} else {
Expand All @@ -262,7 +280,9 @@ void Math::DFTThread::run()
dft.data[i - startBin].x = round(freq);
dft.data[i - startBin].y = timeDomain.at(i);
}
emit dft.outputSamplesChanged(0, dft.data.size());
auto size = dft.data.size();
dft.dataMutex.unlock();
emit dft.outputSamplesChanged(0, size);

// limit update rate if configured in preferences
auto &p = Preferences::getInstance();
Expand Down
1 change: 1 addition & 0 deletions Software/PC_Application/LibreVNA-GUI/Traces/Math/dft.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public slots:

private:
void updateDFT();
void clearOutput();
bool automaticDC;
double DCfreq;
WindowFunction window;
Expand Down
11 changes: 8 additions & 3 deletions Software/PC_Application/LibreVNA-GUI/Traces/Math/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ void Math::Expression::fromJSON(nlohmann::json j)

void Math::Expression::inputSamplesChanged(unsigned int begin, unsigned int end)
{
auto in = input->rData();
std::vector<Data> in;
if(input) {
in = input->getData();
}
dataMutex.lock();
data.resize(in.size());
try {
for(unsigned int i=begin;i<end;i++) {
Expand All @@ -100,10 +104,11 @@ void Math::Expression::inputSamplesChanged(unsigned int begin, unsigned int end)
data[i].y = res.GetComplex();
}
success();
emit outputSamplesChanged(begin, end);
} catch (const ParserError &e) {
error(QString::fromStdString(e.GetMsg()));
}
dataMutex.unlock();
emit outputSamplesChanged(begin, end);
}

void Math::Expression::expressionChanged()
Expand Down Expand Up @@ -137,6 +142,6 @@ void Math::Expression::expressionChanged()
break;
}
if(input) {
inputSamplesChanged(0, input->rData().size());
inputSamplesChanged(0, input->getData().size());
}
}
32 changes: 20 additions & 12 deletions Software/PC_Application/LibreVNA-GUI/Traces/Math/medianfilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,14 @@ void MedianFilter::fromJSON(nlohmann::json j)
}

void MedianFilter::inputSamplesChanged(unsigned int begin, unsigned int end) {
if(data.size() != input->rData().size()) {
data.resize(input->rData().size());
std::vector<Data> inputData;
if(input) {
inputData = input->getData();
}
if(data.size() != inputData.size()) {
dataMutex.lock();
data.resize(inputData.size());
dataMutex.unlock();
}
if(data.size() > 0) {
auto kernelOffset = (kernelSize-1)/2;
Expand All @@ -89,8 +95,8 @@ void MedianFilter::inputSamplesChanged(unsigned int begin, unsigned int end) {
if(start < 0) {
start = 0;
}
if(stop > input->rData().size()) {
stop = input->rData().size();
if(stop > inputData.size()) {
stop = inputData.size();
}

auto comp = [=](const complex<double>&a, const complex<double>&b){
Expand All @@ -104,19 +110,20 @@ void MedianFilter::inputSamplesChanged(unsigned int begin, unsigned int end) {
};

vector<complex<double>> kernel(kernelSize);
dataMutex.lock();
for(unsigned int out=start;out<stop;out++) {
if(out == (unsigned int) start) {
// this is the first sample to update, fill initial kernel
for(unsigned int in=0;in<kernelSize;in++) {
unsigned int inputSample;
if(kernelOffset > in + out) {
inputSample = 0;
} else if(in + out >= input->rData().size() + kernelOffset) {
inputSample = input->rData().size() - 1;
} else if(in + out >= inputData.size() + kernelOffset) {
inputSample = inputData.size() - 1;
} else {
inputSample = in + out - kernelOffset;
}
auto sample = input->rData().at(inputSample).y;
auto sample = inputData.at(inputSample).y;
kernel[in] = sample;
}
// sort initial kernel
Expand All @@ -129,20 +136,21 @@ void MedianFilter::inputSamplesChanged(unsigned int begin, unsigned int end) {
if(toRemove < 0) {
toRemove = 0;
}
if(toAdd >= input->rData().size()) {
toAdd = input->rData().size() - 1;
if(toAdd >= inputData.size()) {
toAdd = inputData.size() - 1;
}
auto sampleToRemove = input->rData().at(toRemove).y;
auto sampleToRemove = inputData.at(toRemove).y;
auto remove_iterator = lower_bound(kernel.begin(), kernel.end(), sampleToRemove, comp);
kernel.erase(remove_iterator);

auto sampleToAdd = input->rData().at(toAdd).y;
auto sampleToAdd = inputData.at(toAdd).y;
// insert sample at correct position in vector
kernel.insert(upper_bound(kernel.begin(), kernel.end(), sampleToAdd, comp), sampleToAdd);
}
data.at(out).y = kernel[kernelOffset];
data.at(out).x = input->rData().at(out).x;
data.at(out).x = inputData.at(out).x;
}
dataMutex.unlock();
emit outputSamplesChanged(start, stop);
success();
} else {
Expand Down
Loading

0 comments on commit 70ac53a

Please sign in to comment.