diff --git a/core/src/gui/widgets/waterfall.cpp b/core/src/gui/widgets/waterfall.cpp index 975fa8d1..3fbef32a 100644 --- a/core/src/gui/widgets/waterfall.cpp +++ b/core/src/gui/widgets/waterfall.cpp @@ -77,6 +77,7 @@ namespace ImGui { lastWidgetSize.x = 0; lastWidgetSize.y = 0; latestFFT = new float[1]; + latestFFTHold = new float[1]; waterfallFb = new uint32_t[1]; viewBandwidth = 1.0; @@ -97,6 +98,7 @@ namespace ImGui { char buf[100]; ImU32 trace = ImGui::GetColorU32(ImGuiCol_PlotLines); + ImU32 traceHold = ImGui::ColorConvertFloat4ToU32(ImVec4(1.0, 1.0, 0.0, 1.0)); ImU32 shadow = ImGui::GetColorU32(ImGuiCol_PlotLines, 0.2); ImU32 text = ImGui::GetColorU32(ImGuiCol_Text); float textVOffset = 10.0f * style::uiScale; @@ -143,6 +145,18 @@ namespace ImGui { } } + // Hold + if (fftHold && latestFFT != NULL && latestFFTHold != NULL && fftLines != 0) { + for (int i = 1; i < dataWidth; i++) { + double aPos = fftAreaMax.y - ((latestFFTHold[i - 1] - fftMin) * scaleFactor); + double bPos = fftAreaMax.y - ((latestFFTHold[i] - fftMin) * scaleFactor); + aPos = std::clamp(aPos, fftAreaMin.y + 1, fftAreaMax.y); + bPos = std::clamp(bPos, fftAreaMin.y + 1, fftAreaMax.y); + window->DrawList->AddLine(ImVec2(fftAreaMin.x + i - 1, roundf(aPos)), + ImVec2(fftAreaMin.x + i, roundf(bPos)), traceHold, 1.0); + } + } + FFTRedrawArgs args; args.min = fftAreaMin; args.max = fftAreaMax; @@ -712,11 +726,18 @@ namespace ImGui { // ============== } + // Reallocate display FFT if (latestFFT != NULL) { delete[] latestFFT; } latestFFT = new float[dataWidth]; + // Reallocate hold FFT + if (latestFFTHold != NULL) { + delete[] latestFFTHold; + } + latestFFTHold = new float[dataWidth]; + if (waterfallVisible) { delete[] waterfallFb; waterfallFb = new uint32_t[dataWidth * waterfallHeight]; @@ -724,6 +745,7 @@ namespace ImGui { } for (int i = 0; i < dataWidth; i++) { latestFFT[i] = -1000.0; // Hide everything + latestFFTHold[i] = -1000.0; } fftAreaMin = ImVec2(widgetPos.x + (50.0f * style::uiScale), widgetPos.y + (9.0f * style::uiScale)); @@ -863,6 +885,13 @@ namespace ImGui { calculateVFOSignalInfo(waterfallVisible ? &rawFFTs[currentFFTLine * rawFFTSize] : rawFFTs, vfos[selectedVFO], dummy, selectedVFOSNR); } + // If FFT hold is enabled, update it + if (fftHold && latestFFT != NULL && latestFFTHold != NULL && fftLines != 0) { + for (int i = 1; i < dataWidth; i++) { + latestFFTHold[i] = std::max(latestFFT[i], latestFFTHold[i] - 0.3f); + } + } + buf_mtx.unlock(); } @@ -1074,6 +1103,15 @@ namespace ImGui { bandPlanPos = pos; } + void WaterFall::setFFTHold(bool hold) { + fftHold = hold; + if (fftHold && latestFFTHold) { + for (int i = 0; i < dataWidth; i++) { + latestFFTHold[i] = -1000.0; + } + } + } + void WaterfallVFO::setOffset(double offset) { generalOffset = offset; if (reference == REF_CENTER) { diff --git a/core/src/gui/widgets/waterfall.h b/core/src/gui/widgets/waterfall.h index 6373215c..fdc06e52 100644 --- a/core/src/gui/widgets/waterfall.h +++ b/core/src/gui/widgets/waterfall.h @@ -176,6 +176,8 @@ namespace ImGui { void setBandPlanPos(int pos); + void setFFTHold(bool hold); + bool centerFreqMoved = false; bool vfoFreqChanged = false; bool bandplanEnabled = false; @@ -307,6 +309,7 @@ namespace ImGui { int rawFFTSize; float* rawFFTs = NULL; float* latestFFT; + float* latestFFTHold; int currentFFTLine = 0; int fftLines = 0; @@ -324,6 +327,8 @@ namespace ImGui { int bandPlanPos = BANDPLAN_POS_BOTTOM; + bool fftHold = false; + // UI Select elements bool fftResizeSelect = false; bool freqScaleSelect = false;