diff --git a/core/src/dsp/resampling.h b/core/src/dsp/resampling.h index 44ba2a79..b3bc09e9 100644 --- a/core/src/dsp/resampling.h +++ b/core/src/dsp/resampling.h @@ -83,14 +83,14 @@ namespace dsp { void updateWindow(dsp::filter_window::generic_window* window) { std::lock_guard lck(generic_block>::ctrlMtx); - generic_block>::tempStop(); + //generic_block>::tempStop(); _window = window; volk_free(taps); tapCount = window->getTapCount(); taps = (float*)volk_malloc(tapCount * sizeof(float), volk_get_alignment()); window->createTaps(taps, tapCount, _interp); buildTapPhases(); - generic_block>::tempStart(); + //generic_block>::tempStart(); } int calcOutSize(int in) { @@ -103,6 +103,8 @@ namespace dsp { return -1; } + ctrlMtx.lock(); + int outCount = calcOutSize(count); memcpy(&buffer[tapsPerPhase], _in->readBuf, count * sizeof(T)); @@ -129,6 +131,8 @@ namespace dsp { memmove(buffer, &buffer[count], tapsPerPhase * sizeof(T)); + ctrlMtx.unlock(); + return count; } diff --git a/core/src/gui/widgets/waterfall.cpp b/core/src/gui/widgets/waterfall.cpp index 35a0dac6..49b43e26 100644 --- a/core/src/gui/widgets/waterfall.cpp +++ b/core/src/gui/widgets/waterfall.cpp @@ -220,6 +220,10 @@ namespace ImGui { vfo->wfRectMax = ImVec2(vfo->rectMax.x, wfMax.y); vfo->wfLineMin = ImVec2(vfo->lineMin.x, wfMin.y); vfo->wfLineMax = ImVec2(vfo->lineMax.x, wfMax.y); + vfo->wfLbwSelMin = ImVec2(vfo->wfRectMin.x - 2, vfo->wfRectMin.y); + vfo->wfLbwSelMax = ImVec2(vfo->wfRectMin.x + 2, vfo->wfRectMax.y); + vfo->wfRbwSelMin = ImVec2(vfo->wfRectMax.x - 2, vfo->wfRectMin.y); + vfo->wfRbwSelMax = ImVec2(vfo->wfRectMax.x + 2, vfo->wfRectMax.y); } vfo->draw(window, name == selectedVFO); } @@ -238,64 +242,93 @@ namespace ImGui { } void WaterFall::processInputs() { - WaterfallVFO* vfo = NULL; + // Pre calculate useful values + WaterfallVFO* selVfo = NULL; if (selectedVFO != "") { - vfo = vfos[selectedVFO]; + selVfo = vfos[selectedVFO]; } ImVec2 mousePos = ImGui::GetMousePos(); ImVec2 drag = ImGui::GetMouseDragDelta(ImGuiMouseButton_Left); ImVec2 dragOrigin(mousePos.x - drag.x, mousePos.y - drag.y); bool mouseHovered, mouseHeld; - bool mouseClicked = ImGui::ButtonBehavior(ImRect(fftAreaMin, fftAreaMax), GetID("WaterfallID"), &mouseHovered, &mouseHeld, + bool mouseClicked = ImGui::ButtonBehavior(ImRect(fftAreaMin, wfMax), GetID("WaterfallID"), &mouseHovered, &mouseHeld, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_PressedOnClick); - mouseClicked |= ImGui::ButtonBehavior(ImRect(wfMin, wfMax), GetID("WaterfallID2"), &mouseHovered, &mouseHeld, - ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_PressedOnClick); - bool draging = ImGui::IsMouseDragging(ImGuiMouseButton_Left) && ImGui::IsWindowFocused(); bool mouseInFreq = IS_IN_AREA(dragOrigin, freqAreaMin, freqAreaMax); bool mouseInFFT = IS_IN_AREA(dragOrigin, fftAreaMin, fftAreaMax); bool mouseInWaterfall = IS_IN_AREA(dragOrigin, wfMin, wfMax); - - // If mouse was clicked on a VFO, select VFO and return - // If mouse was clicked but not on a VFO, move selected VFO to position + // Deselect everything if the mouse is released + if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) { + freqScaleSelect = false; + vfoSelect = false; + vfoBorderSelect = false; + lastDrag = 0; + } + + // If mouse was clicked, check what was clicked if (mouseClicked) { + bool targetFound = false; + mouseDownPos = mousePos; + + // First, check if a VFO border was selected for (auto const& [name, _vfo] : vfos) { - if (name == selectedVFO) { - continue; + if (_vfo->bandwidthLocked) { continue; } + bool resizing = false; + if (_vfo->reference != REF_LOWER) { + if (IS_IN_AREA(mousePos, _vfo->lbwSelMin, _vfo->lbwSelMax)) { resizing = true; } + else if (IS_IN_AREA(mousePos, _vfo->wfLbwSelMin, _vfo->wfLbwSelMax)) { resizing = true; } } - if (IS_IN_AREA(mousePos, _vfo->rectMin, _vfo->rectMax) || IS_IN_AREA(mousePos, _vfo->wfRectMin, _vfo->wfRectMax)) { - selectedVFO = name; - selectedVFOChanged = true; - return; + if (_vfo->reference != REF_UPPER) { + if (IS_IN_AREA(mousePos, _vfo->rbwSelMin, _vfo->rbwSelMax)) { resizing = true; } + else if (IS_IN_AREA(mousePos, _vfo->wfRbwSelMin, _vfo->wfRbwSelMax)) { resizing = true; } + } + if (!resizing) { continue; } + relatedVfo = _vfo; + vfoBorderSelect = true; + targetFound = true; + break; + } + + // Next, check if a VFO was selected + if (!targetFound) { + for (auto const& [name, _vfo] : vfos) { + if (name == selectedVFO) { + continue; + } + + // If another VFO is selected, select it and cancel out + if (IS_IN_AREA(mousePos, _vfo->rectMin, _vfo->rectMax) || IS_IN_AREA(mousePos, _vfo->wfRectMin, _vfo->wfRectMax)) { + selectedVFO = name; + selectedVFOChanged = true; + targetFound = true; + return; + } } } - if (vfo != NULL) { - int refCenter = mousePos.x - (widgetPos.x + 50); - if (refCenter >= 0 && refCenter < dataWidth) { - double off = ((((double)refCenter / ((double)dataWidth / 2.0)) - 1.0) * (viewBandwidth / 2.0)) + viewOffset; - off += centerFreq; - off = (round(off / vfo->snapInterval) * vfo->snapInterval) - centerFreq; - vfo->setOffset(off); - } + + // Now, check frequency scale + if (!targetFound && mouseInFreq) { + freqScaleSelect = true; } } - // Draging VFO - if (draging && (mouseInFFT || mouseInWaterfall)) { - int refCenter = mousePos.x - (widgetPos.x + 50); - if (refCenter >= 0 && refCenter < dataWidth && mousePos.y > widgetPos.y && mousePos.y < (widgetPos.y + widgetSize.y) && vfo != NULL) { - double off = ((((double)refCenter / ((double)dataWidth / 2.0)) - 1.0) * (viewBandwidth / 2.0)) + viewOffset; - off += centerFreq; - off = (round(off / vfo->snapInterval) * vfo->snapInterval) - centerFreq; - vfo->setOffset(off); + // If a vfo border is selected, resize VFO accordingly + if (vfoBorderSelect) { + double dist = fabsf(mousePos.x - relatedVfo->lineMin.x); + double hzDist = dist * (viewBandwidth / (double)dataWidth); + if (relatedVfo->reference == REF_CENTER) { + hzDist *= 2.0; } - } + hzDist = std::clamp(hzDist, relatedVfo->minBandwidth, relatedVfo->maxBandwidth); + relatedVfo->setBandwidth(hzDist); + return; + } - // Draging frequency scale - if (draging && mouseInFreq) { + // If the frequency scale is selected, move it + if (freqScaleSelect) { double deltax = drag.x - lastDrag; lastDrag = drag.x; double viewDelta = deltax * (viewBandwidth / (double)dataWidth); @@ -322,10 +355,21 @@ namespace ImGui { updateAllVFOs(); if (_fullUpdate) { updateWaterfallFb(); }; } + return; } - else { - lastDrag = 0; - } + + // Finally, if nothing else was selected, just move the VFO + if (ImGui::IsMouseDown(ImGuiMouseButton_Left)) { + if (selVfo != NULL) { + int refCenter = mousePos.x - (widgetPos.x + 50); + if (refCenter >= 0 && refCenter < dataWidth) { + double off = ((((double)refCenter / ((double)dataWidth / 2.0)) - 1.0) * (viewBandwidth / 2.0)) + viewOffset; + off += centerFreq; + off = (round(off / selVfo->snapInterval) * selVfo->snapInterval) - centerFreq; + selVfo->setOffset(off); + } + } + } } void WaterFall::setFastFFT(bool fastFFT) { @@ -815,6 +859,11 @@ namespace ImGui { vfo->wfRectMax = ImVec2(vfo->rectMax.x, wfMax.y); vfo->wfLineMin = ImVec2(vfo->lineMin.x, wfMin.y); vfo->wfLineMax = ImVec2(vfo->lineMax.x, wfMax.y); + + vfo->wfLbwSelMin = ImVec2(vfo->wfRectMin.x - 2, vfo->wfRectMin.y); + vfo->wfLbwSelMax = ImVec2(vfo->wfRectMin.x + 2, vfo->wfRectMax.y); + vfo->wfRbwSelMin = ImVec2(vfo->wfRectMax.x - 2, vfo->wfRectMin.y); + vfo->wfRbwSelMax = ImVec2(vfo->wfRectMax.x + 2, vfo->wfRectMax.y); } } @@ -897,6 +946,7 @@ namespace ImGui { lowerOffset = upperOffset - bandwidth; centerOffsetChanged = true; } + bandwidthChanged = true; redrawRequired = true; } @@ -940,8 +990,10 @@ namespace ImGui { rectMin = ImVec2(widgetPos.x + 50 + left, widgetPos.y + 10); rectMax = ImVec2(widgetPos.x + 51 + right, widgetPos.y + fftHeight + 10); - lbwSelMin = ImVec2(rectMin.x - 1, rectMin.y); - lbwSelMax = ImVec2(rectMin.x + 1, rectMax.y); + lbwSelMin = ImVec2(rectMin.x - 2, rectMin.y); + lbwSelMax = ImVec2(rectMin.x + 2, rectMax.y); + rbwSelMin = ImVec2(rectMax.x - 2, rectMin.y); + rbwSelMax = ImVec2(rectMax.x + 2, rectMax.y); } void WaterfallVFO::draw(ImGuiWindow* window, bool selected) { @@ -949,6 +1001,16 @@ namespace ImGui { if (lineVisible) { window->DrawList->AddLine(lineMin, lineMax, selected ? IM_COL32(255, 0, 0, 255) : IM_COL32(255, 255, 0, 255)); } + + ImVec2 mousePos = ImGui::GetMousePos(); + if (reference != REF_LOWER && !bandwidthLocked) { + if (IS_IN_AREA(mousePos, lbwSelMin, lbwSelMax)) { ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); } + else if (IS_IN_AREA(mousePos, wfLbwSelMin, wfLbwSelMax)) { ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); } + } + if (reference != REF_UPPER && !bandwidthLocked) { + if (IS_IN_AREA(mousePos, rbwSelMin, rbwSelMax)) { ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); } + else if (IS_IN_AREA(mousePos, wfRbwSelMin, wfRbwSelMax)) { ImGui::SetMouseCursor(ImGuiMouseCursor_ResizeEW); } + } }; void WaterFall::showWaterfall() { diff --git a/core/src/gui/widgets/waterfall.h b/core/src/gui/widgets/waterfall.h index a0b576aa..85f38090 100644 --- a/core/src/gui/widgets/waterfall.h +++ b/core/src/gui/widgets/waterfall.h @@ -56,6 +56,11 @@ namespace ImGui { bool upperOffsetChanged = false; bool redrawRequired = true; bool lineVisible = true; + bool bandwidthChanged = false; + + double minBandwidth; + double maxBandwidth; + bool bandwidthLocked; }; class WaterFall { @@ -228,5 +233,12 @@ namespace ImGui { bool _fullUpdate = true; int bandPlanPos = BANDPLAN_POS_BOTTOM; + + // UI Select elements + bool freqScaleSelect = false; + bool vfoSelect = false; + bool vfoBorderSelect = false; + WaterfallVFO* relatedVfo = NULL; + ImVec2 mouseDownPos; }; }; \ No newline at end of file diff --git a/core/src/signal_path/vfo_manager.cpp b/core/src/signal_path/vfo_manager.cpp index 8520c2a2..dbe8e8c1 100644 --- a/core/src/signal_path/vfo_manager.cpp +++ b/core/src/signal_path/vfo_manager.cpp @@ -1,13 +1,16 @@ #include #include -VFOManager::VFO::VFO(std::string name, int reference, double offset, double bandwidth, double sampleRate, int blockSize) { +VFOManager::VFO::VFO(std::string name, int reference, double offset, double bandwidth, double sampleRate, double minBandwidth, double maxBandwidth, bool bandwidthLocked) { this->name = name; dspVFO = sigpath::signalPath.addVFO(name, sampleRate, bandwidth, offset); wtfVFO = new ImGui::WaterfallVFO; wtfVFO->setReference(reference); wtfVFO->setBandwidth(bandwidth); wtfVFO->setOffset(offset); + wtfVFO->minBandwidth = minBandwidth; + wtfVFO->maxBandwidth = maxBandwidth; + wtfVFO->bandwidthLocked = bandwidthLocked; output = dspVFO->out; gui::waterfall.vfos[name] = wtfVFO; } @@ -32,8 +35,8 @@ void VFOManager::VFO::setCenterOffset(double offset) { dspVFO->setOffset(offset); } -void VFOManager::VFO::setBandwidth(double bandwidth) { - wtfVFO->setBandwidth(bandwidth); +void VFOManager::VFO::setBandwidth(double bandwidth, bool updateWaterfall) { + if (updateWaterfall) { wtfVFO->setBandwidth(bandwidth); } dspVFO->setBandwidth(bandwidth); } @@ -46,25 +49,35 @@ void VFOManager::VFO::setReference(int ref) { wtfVFO->setReference(ref); } -int VFOManager::VFO::getOutputBlockSize() { - // NOTE: This shouldn't be needed anymore - return 1; //dspVFO->getOutputBlockSize(); -} - void VFOManager::VFO::setSnapInterval(double interval) { wtfVFO->setSnapInterval(interval); } +void VFOManager::VFO::setBandwidthLimits(double minBandwidth, double maxBandwidth, bool bandwidthLocked) { + wtfVFO->minBandwidth = minBandwidth; + wtfVFO->maxBandwidth = maxBandwidth; + wtfVFO->bandwidthLocked = bandwidthLocked; +} + +bool VFOManager::VFO::getBandwidthChanged(bool erase) { + bool val = wtfVFO->bandwidthChanged; + if (erase) { wtfVFO->bandwidthChanged = false; } + return val; +} + +double VFOManager::VFO::getBandwidth() { + return wtfVFO->bandwidth; +} VFOManager::VFOManager() { } -VFOManager::VFO* VFOManager::createVFO(std::string name, int reference, double offset, double bandwidth, double sampleRate, int blockSize) { +VFOManager::VFO* VFOManager::createVFO(std::string name, int reference, double offset, double bandwidth, double sampleRate, double minBandwidth, double maxBandwidth, bool bandwidthLocked) { if (vfos.find(name) != vfos.end() || name == "") { return NULL; } - VFOManager::VFO* vfo = new VFO(name, reference, offset, bandwidth, sampleRate, blockSize); + VFOManager::VFO* vfo = new VFO(name, reference, offset, bandwidth, sampleRate, minBandwidth, maxBandwidth, bandwidthLocked); vfos[name] = vfo; return vfo; } @@ -98,11 +111,11 @@ void VFOManager::setCenterOffset(std::string name, double offset) { vfos[name]->setCenterOffset(offset); } -void VFOManager::setBandwidth(std::string name, double bandwidth) { +void VFOManager::setBandwidth(std::string name, double bandwidth, bool updateWaterfall) { if (vfos.find(name) == vfos.end()) { return; } - vfos[name]->setBandwidth(bandwidth); + vfos[name]->setBandwidth(bandwidth, updateWaterfall); } void VFOManager::setSampleRate(std::string name, double sampleRate, double bandwidth) { @@ -119,11 +132,25 @@ void VFOManager::setReference(std::string name, int ref) { vfos[name]->setReference(ref); } -int VFOManager::getOutputBlockSize(std::string name) { +void VFOManager::setBandwidthLimits(std::string name, double minBandwidth, double maxBandwidth, bool bandwidthLocked) { if (vfos.find(name) == vfos.end()) { - return -1; + return; } - return vfos[name]->getOutputBlockSize(); + vfos[name]->setBandwidthLimits(minBandwidth, maxBandwidth, bandwidthLocked); +} + +bool VFOManager::getBandwidthChanged(std::string name, bool erase) { + if (vfos.find(name) == vfos.end()) { + return false; + } + return vfos[name]->getBandwidthChanged(erase); +} + +double VFOManager::getBandwidth(std::string name) { + if (vfos.find(name) == vfos.end()) { + return NAN; + } + return vfos[name]->getBandwidth(); } void VFOManager::updateFromWaterfall(ImGui::WaterFall* wtf) { diff --git a/core/src/signal_path/vfo_manager.h b/core/src/signal_path/vfo_manager.h index 194c9ef8..e255790f 100644 --- a/core/src/signal_path/vfo_manager.h +++ b/core/src/signal_path/vfo_manager.h @@ -9,16 +9,18 @@ public: class VFO { public: - VFO(std::string name, int reference, double offset, double bandwidth, double sampleRate, int blockSize); + VFO(std::string name, int reference, double offset, double bandwidth, double sampleRate, double minBandwidth, double maxBandwidth, bool bandwidthLocked); ~VFO(); void setOffset(double offset); void setCenterOffset(double offset); - void setBandwidth(double bandwidth); + void setBandwidth(double bandwidth, bool updateWaterfall = true); void setSampleRate(double sampleRate, double bandwidth); void setReference(int ref); - int getOutputBlockSize(); void setSnapInterval(double interval); + void setBandwidthLimits(double minBandwidth, double maxBandwidth, bool bandwidthLocked); + bool getBandwidthChanged(bool erase = true); + double getBandwidth(); dsp::stream* output; @@ -31,15 +33,17 @@ public: }; - VFOManager::VFO* createVFO(std::string name, int reference, double offset, double bandwidth, double sampleRate, int blockSize); + VFOManager::VFO* createVFO(std::string name, int reference, double offset, double bandwidth, double sampleRate, double minBandwidth, double maxBandwidth, bool bandwidthLocked); void deleteVFO(VFOManager::VFO* vfo); void setOffset(std::string name, double offset); void setCenterOffset(std::string name, double offset); - void setBandwidth(std::string name, double bandwidth); + void setBandwidth(std::string name, double bandwidth, bool updateWaterfall = true); void setSampleRate(std::string name, double sampleRate, double bandwidth); void setReference(std::string name, int ref); - int getOutputBlockSize(std::string name); + void setBandwidthLimits(std::string name, double minBandwidth, double maxBandwidth, bool bandwidthLocked); + bool getBandwidthChanged(std::string name, bool erase = true); + double getBandwidth(std::string name); void updateFromWaterfall(ImGui::WaterFall* wtf); diff --git a/falcon9_decoder/src/main.cpp b/falcon9_decoder/src/main.cpp index 2afe322e..a83d42ff 100644 --- a/falcon9_decoder/src/main.cpp +++ b/falcon9_decoder/src/main.cpp @@ -43,7 +43,7 @@ public: Falcon9DecoderModule(std::string name) { this->name = name; - vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 4000000, INPUT_SAMPLE_RATE, 1); + vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 4000000, INPUT_SAMPLE_RATE, 4000000, 4000000, true); // dsp::Splitter split; // dsp::Reshaper reshape; @@ -89,7 +89,7 @@ public: } void enable() { - vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 4000000, INPUT_SAMPLE_RATE, 1); + vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 4000000, INPUT_SAMPLE_RATE, 4000000, 4000000, true); demod.setInput(vfo->output); diff --git a/meteor_demodulator/src/main.cpp b/meteor_demodulator/src/main.cpp index c38524cc..e520dc55 100644 --- a/meteor_demodulator/src/main.cpp +++ b/meteor_demodulator/src/main.cpp @@ -48,7 +48,7 @@ public: writeBuffer = new int8_t[STREAM_BUFFER_SIZE]; - vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 150000, INPUT_SAMPLE_RATE, 1); + vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 150000, INPUT_SAMPLE_RATE, 150000, 150000, true); demod.init(vfo->output, INPUT_SAMPLE_RATE, 72000.0f, 32, 0.6f, 0.1f, 0.005f); split.init(demod.out); split.bindStream(&symSinkStream); @@ -71,7 +71,7 @@ public: } void enable() { - vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 150000, INPUT_SAMPLE_RATE, 1); + vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 150000, INPUT_SAMPLE_RATE, 150000, 150000, true); demod.setInput(vfo->output); diff --git a/radio/src/am_demod.h b/radio/src/am_demod.h index c6effcfc..54752397 100644 --- a/radio/src/am_demod.h +++ b/radio/src/am_demod.h @@ -80,6 +80,7 @@ public: _vfo->setSampleRate(bbSampRate, bw); _vfo->setSnapInterval(snapInterval); _vfo->setReference(ImGui::WaterfallVFO::REF_CENTER); + _vfo->setBandwidthLimits(bwMin, bwMax, false); } void setVFO(VFOManager::VFO* vfo) { @@ -126,6 +127,15 @@ public: _config->conf[uiPrefix]["AM"]["bandwidth"] = bw; _config->release(true); } + if (running) { + if (_vfo->getBandwidthChanged()) { + bw = _vfo->getBandwidth(); + setBandwidth(bw, false); + _config->aquire(); + _config->conf[uiPrefix]["AM"]["bandwidth"] = bw; + _config->release(true); + } + } ImGui::Text("Snap Interval"); ImGui::SameLine(); @@ -150,9 +160,9 @@ public: } private: - void setBandwidth(float bandWidth) { + void setBandwidth(float bandWidth, bool updateWaterfall = true) { bw = bandWidth; - _vfo->setBandwidth(bw); + _vfo->setBandwidth(bw, updateWaterfall); float audioBW = std::min(audioSampRate / 2.0f, bw / 2.0f); win.setSampleRate(bbSampRate * resamp.getInterpolation()); win.setCutoff(audioBW); diff --git a/radio/src/cw_demod.h b/radio/src/cw_demod.h index d106a0f5..bcf0e2aa 100644 --- a/radio/src/cw_demod.h +++ b/radio/src/cw_demod.h @@ -87,6 +87,7 @@ public: _vfo->setSampleRate(bbSampRate, bw); _vfo->setSnapInterval(snapInterval); _vfo->setReference(ImGui::WaterfallVFO::REF_CENTER); + _vfo->setBandwidthLimits(bwMin, bwMax, false); } void setVFO(VFOManager::VFO* vfo) { @@ -133,6 +134,14 @@ public: _config->aquire(); _config->conf[uiPrefix]["CW"]["bandwidth"] = bw; _config->release(true); + }if (running) { + if (_vfo->getBandwidthChanged()) { + bw = _vfo->getBandwidth(); + setBandwidth(bw, false); + _config->aquire(); + _config->conf[uiPrefix]["CW"]["bandwidth"] = bw; + _config->release(true); + } } ImGui::Text("Snap Interval"); @@ -158,9 +167,9 @@ public: } private: - void setBandwidth(float bandWidth) { + void setBandwidth(float bandWidth, bool updateWaterfall = true) { bw = bandWidth; - _vfo->setBandwidth(bw); + _vfo->setBandwidth(bw, updateWaterfall); } void setSnapInterval(float snapInt) { diff --git a/radio/src/dsb_demod.h b/radio/src/dsb_demod.h index 4f40227a..6887a18e 100644 --- a/radio/src/dsb_demod.h +++ b/radio/src/dsb_demod.h @@ -80,6 +80,7 @@ public: _vfo->setSampleRate(bbSampRate, bw); _vfo->setSnapInterval(snapInterval); _vfo->setReference(ImGui::WaterfallVFO::REF_CENTER); + _vfo->setBandwidthLimits(bwMin, bwMax, false); } void setVFO(VFOManager::VFO* vfo) { @@ -126,6 +127,15 @@ public: _config->conf[uiPrefix]["DSB"]["bandwidth"] = bw; _config->release(true); } + if (running) { + if (_vfo->getBandwidthChanged()) { + bw = _vfo->getBandwidth(); + setBandwidth(bw, false); + _config->aquire(); + _config->conf[uiPrefix]["DSB"]["bandwidth"] = bw; + _config->release(true); + } + } ImGui::Text("Snap Interval"); ImGui::SameLine(); @@ -150,9 +160,9 @@ public: } private: - void setBandwidth(float bandWidth) { + void setBandwidth(float bandWidth, bool updateWaterfall = true) { bw = bandWidth; - _vfo->setBandwidth(bw); + _vfo->setBandwidth(bw, updateWaterfall); } void setSnapInterval(float snapInt) { diff --git a/radio/src/fm_demod.h b/radio/src/fm_demod.h index d2c66484..e326e6bc 100644 --- a/radio/src/fm_demod.h +++ b/radio/src/fm_demod.h @@ -72,6 +72,7 @@ public: _vfo->setSampleRate(bbSampRate, bw); _vfo->setSnapInterval(snapInterval); _vfo->setReference(ImGui::WaterfallVFO::REF_CENTER); + _vfo->setBandwidthLimits(bwMin, bwMax, false); } void setVFO(VFOManager::VFO* vfo) { @@ -118,6 +119,15 @@ public: _config->conf[uiPrefix]["FM"]["bandwidth"] = bw; _config->release(true); } + if (running) { + if (_vfo->getBandwidthChanged()) { + bw = _vfo->getBandwidth(); + setBandwidth(bw, false); + _config->aquire(); + _config->conf[uiPrefix]["FM"]["bandwidth"] = bw; + _config->release(true); + } + } ImGui::Text("Snap Interval"); ImGui::SameLine(); @@ -142,9 +152,9 @@ public: } private: - void setBandwidth(float bandWidth) { + void setBandwidth(float bandWidth, bool updateWaterfall = true) { bw = bandWidth; - _vfo->setBandwidth(bw); + _vfo->setBandwidth(bw, updateWaterfall); demod.setDeviation(bw / 2.0f); setAudioSampleRate(audioSampRate); } diff --git a/radio/src/lsb_demod.h b/radio/src/lsb_demod.h index 065ebf26..f237bf06 100644 --- a/radio/src/lsb_demod.h +++ b/radio/src/lsb_demod.h @@ -80,6 +80,7 @@ public: _vfo->setSampleRate(bbSampRate, bw); _vfo->setSnapInterval(snapInterval); _vfo->setReference(ImGui::WaterfallVFO::REF_UPPER); + _vfo->setBandwidthLimits(bwMin, bwMax, false); } void setVFO(VFOManager::VFO* vfo) { @@ -125,6 +126,14 @@ public: _config->aquire(); _config->conf[uiPrefix]["LSB"]["bandwidth"] = bw; _config->release(true); + }if (running) { + if (_vfo->getBandwidthChanged()) { + bw = _vfo->getBandwidth(); + setBandwidth(bw, false); + _config->aquire(); + _config->conf[uiPrefix]["LSB"]["bandwidth"] = bw; + _config->release(true); + } } ImGui::Text("Snap Interval"); @@ -150,9 +159,9 @@ public: } private: - void setBandwidth(float bandWidth) { + void setBandwidth(float bandWidth, bool updateWaterfall = true) { bw = bandWidth; - _vfo->setBandwidth(bw); + _vfo->setBandwidth(bw, updateWaterfall); demod.setBandWidth(bw); float audioBW = std::min(audioSampRate / 2.0f, bw); win.setSampleRate(bbSampRate * resamp.getInterpolation()); diff --git a/radio/src/main.cpp b/radio/src/main.cpp index 62650b2a..be5a8bc8 100644 --- a/radio/src/main.cpp +++ b/radio/src/main.cpp @@ -33,7 +33,7 @@ public: RadioModule(std::string name) { this->name = name; - vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 200000, 200000, 1); + vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 200000, 200000, 50000, 200000, false); ns.init(vfo->output); @@ -70,7 +70,7 @@ public: } void enable() { - vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 200000, 200000, 1); + vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 200000, 200000, 50000, 200000, false); wfmDemod.setVFO(vfo); fmDemod.setVFO(vfo); diff --git a/radio/src/raw_demod.h b/radio/src/raw_demod.h index df91d7fa..d29ac926 100644 --- a/radio/src/raw_demod.h +++ b/radio/src/raw_demod.h @@ -61,6 +61,7 @@ public: _vfo->setSampleRate(audioSampRate, audioSampRate); _vfo->setSnapInterval(snapInterval); _vfo->setReference(ImGui::WaterfallVFO::REF_CENTER); + _vfo->setBandwidthLimits(0, 0, true); } void setVFO(VFOManager::VFO* vfo) { diff --git a/radio/src/usb_demod.h b/radio/src/usb_demod.h index 94accd2d..e3ed4ac7 100644 --- a/radio/src/usb_demod.h +++ b/radio/src/usb_demod.h @@ -80,6 +80,7 @@ public: _vfo->setSampleRate(bbSampRate, bw); _vfo->setSnapInterval(snapInterval); _vfo->setReference(ImGui::WaterfallVFO::REF_LOWER); + _vfo->setBandwidthLimits(bwMin, bwMax, false); } void setVFO(VFOManager::VFO* vfo) { @@ -125,6 +126,14 @@ public: _config->aquire(); _config->conf[uiPrefix]["USB"]["bandwidth"] = bw; _config->release(true); + }if (running) { + if (_vfo->getBandwidthChanged()) { + bw = _vfo->getBandwidth(); + setBandwidth(bw, false); + _config->aquire(); + _config->conf[uiPrefix]["USB"]["bandwidth"] = bw; + _config->release(true); + } } ImGui::Text("Snap Interval"); @@ -150,9 +159,9 @@ public: } private: - void setBandwidth(float bandWidth) { + void setBandwidth(float bandWidth, bool updateWaterfall = true) { bw = bandWidth; - _vfo->setBandwidth(bw); + _vfo->setBandwidth(bw, updateWaterfall); demod.setBandWidth(bw); float audioBW = std::min(audioSampRate / 2.0f, bw); win.setSampleRate(bbSampRate * resamp.getInterpolation()); diff --git a/radio/src/wfm_demod.h b/radio/src/wfm_demod.h index 7266b837..c1869e36 100644 --- a/radio/src/wfm_demod.h +++ b/radio/src/wfm_demod.h @@ -85,6 +85,7 @@ public: _vfo->setSampleRate(bbSampRate, bw); _vfo->setSnapInterval(snapInterval); _vfo->setReference(ImGui::WaterfallVFO::REF_CENTER); + _vfo->setBandwidthLimits(bwMin, bwMax, false); } void setVFO(VFOManager::VFO* vfo) { @@ -128,12 +129,22 @@ public: ImGui::SetNextItemWidth(menuWidth); if (ImGui::InputFloat(("##_radio_wfm_bw_" + uiPrefix).c_str(), &bw, 1, 100, "%.0f", 0)) { + spdlog::warn("TEST"); bw = std::clamp(bw, bwMin, bwMax); setBandwidth(bw); _config->aquire(); _config->conf[uiPrefix]["WFM"]["bandwidth"] = bw; _config->release(true); } + if (running) { + if (_vfo->getBandwidthChanged()) { + bw = _vfo->getBandwidth(); + setBandwidth(bw, false); + _config->aquire(); + _config->conf[uiPrefix]["WFM"]["bandwidth"] = bw; + _config->release(true); + } + } ImGui::Text("Snap Interval"); ImGui::SameLine(); @@ -169,9 +180,9 @@ public: } private: - void setBandwidth(float bandWidth) { + void setBandwidth(float bandWidth, bool updateWaterfall = true) { bw = bandWidth; - _vfo->setBandwidth(bw); + _vfo->setBandwidth(bw, updateWaterfall); demod.setDeviation(bw / 2.0f); } diff --git a/weather_sat_decoder/src/main.cpp b/weather_sat_decoder/src/main.cpp index b7a81c90..c8800eef 100644 --- a/weather_sat_decoder/src/main.cpp +++ b/weather_sat_decoder/src/main.cpp @@ -45,7 +45,7 @@ public: WeatherSatDecoderModule(std::string name) { this->name = name; - vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 1000000, 1000000, 1); + vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 1000000, 1000000, 1000000, 1000000, true); decoders["NOAA HRPT"] = new NOAAHRPTDecoder(vfo, name); @@ -68,7 +68,7 @@ public: } void enable() { - vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 1000000, 1000000, 1); + vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, 0, 1000000, 1000000, 1000000, 1000000, true); for (auto const& [name, dec] : decoders) { dec->setVFO(vfo); } decoder->select(); decoder->start(); diff --git a/weather_sat_decoder/src/noaa_hrpt_decoder.h b/weather_sat_decoder/src/noaa_hrpt_decoder.h index b0428618..e0db3702 100644 --- a/weather_sat_decoder/src/noaa_hrpt_decoder.h +++ b/weather_sat_decoder/src/noaa_hrpt_decoder.h @@ -72,6 +72,7 @@ public: void select() { _vfo->setSampleRate(NOAA_HRPT_VFO_SR, NOAA_HRPT_VFO_BW); _vfo->setReference(ImGui::WaterfallVFO::REF_CENTER); + _vfo->setBandwidthLimits(NOAA_HRPT_VFO_BW, NOAA_HRPT_VFO_BW, true); }; void start() {