From b9b501bd000c0c25c3873973fd242ee4a4876d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4berich?= Date: Fri, 21 Oct 2022 19:50:06 +0200 Subject: [PATCH] Improve display of eye diagram --- .../LibreVNA-GUI/Traces/Math/tdr.cpp | 3 +- .../LibreVNA-GUI/Traces/Math/tracemath.h | 1 + .../Traces/eyediagrameditdialog.ui | 14 + .../LibreVNA-GUI/Traces/eyediagramplot.cpp | 77 ++++- .../LibreVNA-GUI/Traces/eyediagramplot.h | 1 + .../PC_Application/LibreVNA-GUI/test.setup | 327 ------------------ 6 files changed, 79 insertions(+), 344 deletions(-) delete mode 100644 Software/PC_Application/LibreVNA-GUI/test.setup diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/Math/tdr.cpp b/Software/PC_Application/LibreVNA-GUI/Traces/Math/tdr.cpp index a54d3a9..e2d95d5 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/Math/tdr.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Traces/Math/tdr.cpp @@ -321,8 +321,7 @@ void TDRThread::run() Fft::transform(frequencyDomain, true); - tdr.data.clear(); - tdr.data.resize(fft_bins); + tdr.data.resize(fft_bins, TraceMath::Data()); for(unsigned int i = 0;i y; }; diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/eyediagrameditdialog.ui b/Software/PC_Application/LibreVNA-GUI/Traces/eyediagrameditdialog.ui index d7ee6f6..0485f4e 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/eyediagrameditdialog.ui +++ b/Software/PC_Application/LibreVNA-GUI/Traces/eyediagrameditdialog.ui @@ -405,6 +405,20 @@ + + + + Trace blurring: + + + + + + + 20 + + + diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/eyediagramplot.cpp b/Software/PC_Application/LibreVNA-GUI/Traces/eyediagramplot.cpp index 155e55e..24d35bf 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/eyediagramplot.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Traces/eyediagramplot.cpp @@ -34,7 +34,8 @@ EyeDiagramPlot::EyeDiagramPlot(TraceModel &model, QWidget *parent) jitter(0.0000000001), linearEdge(true), patternbits(9), - cycles(200) + cycles(200), + traceBlurring(2) { plotAreaTop = 0; plotAreaLeft = 0; @@ -179,6 +180,7 @@ void EyeDiagramPlot::fromJSON(nlohmann::json j) patternbits = j.value("patternBits", patternbits); cycles = j.value("cycles", cycles); xSamples = j.value("xSamples", xSamples); + traceBlurring = j.value("traceBlurring", traceBlurring); for(unsigned int hash : j["traces"]) { // attempt to find the traces with this hash @@ -231,6 +233,7 @@ nlohmann::json EyeDiagramPlot::toJSON() j["patternBits"] = patternbits; j["cycles"] = cycles; j["xSamples"] = xSamples; + j["traceBlurring"] = traceBlurring; return j; } @@ -308,6 +311,7 @@ void EyeDiagramPlot::axisSetupDialog() ui->displayedCycles->setValue(cycles); ui->pointsPerCycle->setValue(xSamples); + ui->traceBlurring->setValue(traceBlurring); connect(ui->Xauto, &QCheckBox::toggled, [=](bool checked) { ui->Xmin->setEnabled(!checked); @@ -345,6 +349,7 @@ void EyeDiagramPlot::axisSetupDialog() cycles = ui->displayedCycles->value(); xSamples = ui->pointsPerCycle->value(); + traceBlurring = ui->traceBlurring->value(); xAxis.set(xAxis.getType(), false, ui->Xauto->isChecked(), ui->Xmin->value(), ui->Xmax->value(), ui->Xdivs->value()); yAxis.set(yAxis.getType(), false, ui->Yauto->isChecked(), ui->Ymin->value(), ui->Ymax->value(), ui->Ydivs->value()); @@ -547,6 +552,9 @@ void EyeDiagramPlot::draw(QPainter &p) if(displayData->size() >= 2) { std::lock_guard guard(bufferSwitchMutex); + if((*displayData)[0].y[0] == 0.0 && (*displayData)[0].y[1] == 0.0) { + qDebug() << "detected null data, displaydata:" << displayData; + } unsigned int pxWidth = plotAreaWidth; unsigned int pxHeight = plotAreaBottom - plotAreaTop; std::vector> bitmap; @@ -555,7 +563,7 @@ void EyeDiagramPlot::draw(QPainter &p) y.resize(pxHeight, 0); } unsigned int highestIntensity = 0; - unsigned int numTraces = (*displayData)[0].y.size(); + unsigned int numTraces = (*displayData)[displayData->size()-1].y.size(); auto addLine = [&](int x0, int y0, int x1, int y1, bool skipFirst = true) { bool first = true; @@ -564,13 +572,19 @@ void EyeDiagramPlot::draw(QPainter &p) first = false; return; } - if(x < 0 || x >= (int) pxWidth || y < 0 || y >= (int) pxHeight) { - return; - } - auto &bin = bitmap[x][y]; - bin++; - if(bin > highestIntensity) { - highestIntensity = bin; + for(int i=-traceBlurring;i<=traceBlurring;i++) { + for(int j=-traceBlurring;j<=traceBlurring;j++) { + if(i*i+j*j <= traceBlurring*traceBlurring) { + if(x+i < 0 || x+i >= (int) pxWidth || y+j < 0 || y+j >= (int) pxHeight) { + return; + } + auto &bin = bitmap[x+i][y+j]; + bin++; + if(bin > highestIntensity) { + highestIntensity = bin; + } + } + } } }; @@ -588,7 +602,7 @@ void EyeDiagramPlot::draw(QPainter &p) }; // Assemble the bitmap - for(unsigned int i=1;isize();i++) { int x0 = xAxis.transform((*displayData)[i-1].x, 0, pxWidth); int x1 = xAxis.transform((*displayData)[i].x, 0, pxWidth); if((x0 < 0 && x1 < 0) || (x0 >= (int) pxWidth && x1 >= (int) pxWidth)) { @@ -602,19 +616,46 @@ void EyeDiagramPlot::draw(QPainter &p) } } + /* + * Only a small amount of pixels will have a lot of traces of top of each other. + * This would result in using mostly the colder colors in the intensity grading. + * + * Generate a histogram of pixel usage and create an adjustment curve to evenly + * distribute all intensity colors + */ + unsigned int hist[highestIntensity+1]; + memset(hist, 0, sizeof(hist)); + unsigned long total = 0; + for(unsigned int i=1;i 0) { - double value = (double) bitmap[i][j] / highestIntensity; + double value = correctedCurve[bitmap[i][j]]; pen.setColor(Util::getIntensityGradeColor(value)); p.setPen(pen); p.drawPoint(plotAreaLeft + i + 1, plotAreaTop + j + 1); } } } + } else { + qDebug() << "Empty eye data, displaydata:" << displayData; } if(dropPending) { p.setOpacity(0.5); @@ -627,7 +668,7 @@ void EyeDiagramPlot::draw(QPainter &p) p.setFont(font); p.setOpacity(1.0); p.setPen(Qt::white); - auto text = "Drop here to add\n" + dropTrace->name() + "\nto waterfall plot"; + auto text = "Drop here to add\n" + dropTrace->name() + "\nto eye diagram"; p.drawText(plotRect, Qt::AlignCenter, text); } } @@ -720,6 +761,7 @@ void EyeDiagramPlot::updateThread(unsigned int xSamples) std::vector> inVec(xSamples * (cycles + 1), 0.0); // needs to calculate one more cycle than required for the display (settling) // resize working buffer + qDebug() << "Clearing old eye data, calcData:" << calcData; calcData->clear(); calcData->resize(xSamples); for(auto& s : *calcData) { @@ -879,12 +921,12 @@ void EyeDiagramPlot::updateThread(unsigned int xSamples) // fill data from outVec for(unsigned int i=0;i guard(bufferSwitchMutex); // switch buffers + qDebug() << "Switching diplay buffers, calcData:" << calcData; auto buf = displayData; displayData = calcData; calcData = buf; + if((*displayData)[0].y[0] == 0.0 && (*displayData)[0].y[1] == 0.0) { + qDebug() << "detected null after eye calculation"; + } + qDebug() << "Buffer switch complete, displayData:" << displayData; } setStatus("Eye calculation complete"); diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/eyediagramplot.h b/Software/PC_Application/LibreVNA-GUI/Traces/eyediagramplot.h index a6d0022..d6c0be6 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/eyediagramplot.h +++ b/Software/PC_Application/LibreVNA-GUI/Traces/eyediagramplot.h @@ -91,6 +91,7 @@ private: bool linearEdge; unsigned int patternbits; unsigned int cycles; + int traceBlurring; int plotAreaLeft, plotAreaWidth, plotAreaBottom, plotAreaTop; diff --git a/Software/PC_Application/LibreVNA-GUI/test.setup b/Software/PC_Application/LibreVNA-GUI/test.setup deleted file mode 100644 index 4269ed3..0000000 --- a/Software/PC_Application/LibreVNA-GUI/test.setup +++ /dev/null @@ -1,327 +0,0 @@ -{ - "Modes": [ - { - "name": "Vector Network Analyzer", - "settings": { - "de-embedding": null, - "de-embedding_enabled": false, - "markers": null, - "sweep": { - "IFBW": 10000.0, - "frequency": { - "log": false, - "power": -10.0, - "start": 1000000.0, - "stop": 6000000000.0 - }, - "points": 501, - "power": { - "frequency": 1000000000.0, - "start": -30.0, - "stop": -15.0 - }, - "single": false, - "type": "Frequency" - }, - "tiles": { - "orientation": "vertical", - "sizes": [ - 373, - 372 - ], - "split": true, - "tile1": { - "orientation": "horizontal", - "sizes": [ - 797, - 796 - ], - "split": true, - "tile1": { - "plot": "smithchart", - "plotsettings": { - "Z0": 50.0, - "constantLines": null, - "edge_reflection": 1.0, - "frequency_override": false, - "limit_to_edge": true, - "limit_to_span": true, - "offset_axis_x": 0.0, - "override_max": 6000000000.0, - "override_min": 0.0, - "traces": [ - 753243053 - ] - }, - "split": false - }, - "tile2": { - "plot": "EyeDiagram", - "plotsettings": { - "XAxis": { - "autorange": false, - "div": 7.62939453125e-09, - "max": 5.653089396158854e-08, - "min": -1.9763051350911456e-08 - }, - "YAxis": { - "autorange": false, - "div": 0.3814697265625, - "max": 2.9595544473356057, - "min": -2.381021724539393 - }, - "bitPerSymbol": 1, - "cycles": 200, - "datarate": 100000000.0, - "falltime": 1e-09, - "highlevel": 1.0, - "jitter": 1e-10, - "linearEdge": true, - "lowlevel": 0.0, - "noise": 0.01, - "patternBits": 9, - "risetime": 1e-09, - "traces": [ - 3153058534 - ], - "xSamples": 200 - }, - "split": false - } - }, - "tile2": { - "orientation": "horizontal", - "sizes": [ - 797, - 796 - ], - "split": true, - "tile1": { - "plot": "EyeDiagram", - "plotsettings": { - "XAxis": { - "autorange": true, - "div": 1e-07, - "max": 1e-06, - "min": 0.0 - }, - "YAxis": { - "autorange": true, - "div": 0.1, - "max": 1.2, - "min": -0.2 - }, - "bitPerSymbol": 2, - "cycles": 200, - "datarate": 2000000.0, - "falltime": 1e-09, - "highlevel": 1.0, - "jitter": 4e-10, - "linearEdge": true, - "lowlevel": 0.0, - "noise": 0.03, - "patternBits": 9, - "risetime": 1e-09, - "traces": [ - 2663219575 - ], - "xSamples": 200 - }, - "split": false - }, - "tile2": { - "plot": "smithchart", - "plotsettings": { - "Z0": 50.0, - "constantLines": null, - "edge_reflection": 1.0, - "frequency_override": false, - "limit_to_edge": true, - "limit_to_span": true, - "offset_axis_x": 0.0, - "override_max": 6000000000.0, - "override_min": 0.0, - "traces": [ - 1360958916 - ] - }, - "split": false - } - } - }, - "traces": [ - { - "color": "#ffff00", - "hash": 753243053, - "livetype": 0, - "math": null, - "math_enabled": false, - "name": "S11", - "parameter": "S11", - "paused": false, - "reflection": true, - "type": "Live", - "velocityFactor": 0.66, - "visible": true - }, - { - "color": "#0000ff", - "hash": 3153058534, - "livetype": 0, - "math": null, - "math_enabled": false, - "name": "S12", - "parameter": "S12", - "paused": false, - "reflection": false, - "type": "Live", - "velocityFactor": 0.66, - "visible": true - }, - { - "color": "#00ff00", - "hash": 2663219575, - "livetype": 0, - "math": null, - "math_enabled": false, - "name": "S21", - "parameter": "S21", - "paused": false, - "reflection": false, - "type": "Live", - "velocityFactor": 0.66, - "visible": true - }, - { - "color": "#ff0000", - "hash": 1360958916, - "livetype": 0, - "math": null, - "math_enabled": false, - "name": "S22", - "parameter": "S22", - "paused": false, - "reflection": true, - "type": "Live", - "velocityFactor": 0.66, - "visible": true - } - ] - }, - "type": "Vector Network Analyzer" - }, - { - "name": "Signal Generator", - "settings": { - "frequency": 1000000000.0, - "port": 0, - "power": 0.0, - "sweep": { - "dwell": 1.0, - "enabled": false, - "span": 0.0, - "steps": 100.0 - } - }, - "type": "Signal Generator" - }, - { - "name": "Spectrum Analyzer", - "settings": { - "markers": null, - "sweep": { - "acquisition": { - "RBW": 100.0, - "detector": "+Peak", - "signal ID": true, - "window": "Kaiser" - }, - "frequency": { - "start": 999975000.0, - "stop": 1000025000.0 - }, - "single": false, - "trackingGenerator": { - "enabled": false, - "offset": 0.0, - "port": 1, - "power": -20.0 - } - }, - "tiles": { - "plot": "XY-plot", - "plotsettings": { - "XAxis": { - "div": 5000.0, - "log": false, - "max": 1000025000.0, - "min": 999975000.0, - "mode": "Use Span", - "type": "Frequency" - }, - "YPrimary": { - "autorange": false, - "div": 10.0, - "log": false, - "max": 0.0, - "min": -120.0, - "traces": [ - 3115643686, - 1375490686 - ], - "type": "Magnitude" - }, - "YSecondary": { - "autorange": true, - "div": 0.0, - "log": false, - "max": 1.0, - "min": -1.0, - "traces": null, - "type": "Disabled" - }, - "limitLines": null - }, - "split": false - }, - "traces": [ - { - "color": "#ffff00", - "hash": 1375490686, - "livetype": 0, - "math": null, - "math_enabled": false, - "name": "PORT1", - "parameter": "PORT1", - "paused": false, - "reflection": false, - "type": "Live", - "velocityFactor": 0.66, - "visible": true - }, - { - "color": "#0000ff", - "hash": 3115643686, - "livetype": 0, - "math": null, - "math_enabled": false, - "name": "PORT2", - "parameter": "PORT2", - "paused": false, - "reflection": false, - "type": "Live", - "velocityFactor": 0.66, - "visible": true - } - ] - }, - "type": "Spectrum Analyzer" - } - ], - "Reference": { - "Mode": "Internal", - "Output": "Off" - }, - "activeMode": "Vector Network Analyzer", - "version": "1.5.0-alpha.1-329f4487e" -}