mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2024-12-25 02:18:30 +01:00
multi-vfo
This commit is contained in:
parent
7759de96da
commit
b65bddc1b3
@ -14,15 +14,13 @@
|
|||||||
#define FAST_ATAN2_COEF2 3.0f * FAST_ATAN2_COEF1
|
#define FAST_ATAN2_COEF2 3.0f * FAST_ATAN2_COEF1
|
||||||
|
|
||||||
inline float fast_arctan2(float y, float x) {
|
inline float fast_arctan2(float y, float x) {
|
||||||
float abs_y = fabs(y)+1e-10;
|
float abs_y = fabs(y) + (1e-10);
|
||||||
float r, angle;
|
float r, angle;
|
||||||
if (x>=0)
|
if (x>=0) {
|
||||||
{
|
|
||||||
r = (x - abs_y) / (x + abs_y);
|
r = (x - abs_y) / (x + abs_y);
|
||||||
angle = FAST_ATAN2_COEF1 - FAST_ATAN2_COEF1 * r;
|
angle = FAST_ATAN2_COEF1 - FAST_ATAN2_COEF1 * r;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
r = (x + abs_y) / (abs_y - x);
|
r = (x + abs_y) / (abs_y - x);
|
||||||
angle = FAST_ATAN2_COEF2 - FAST_ATAN2_COEF1 * r;
|
angle = FAST_ATAN2_COEF2 - FAST_ATAN2_COEF1 * r;
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,8 @@ int main() {
|
|||||||
//mod::loadModule("../modules/demo/build/Release/demo.dll", "Demo Module 2");
|
//mod::loadModule("../modules/demo/build/Release/demo.dll", "Demo Module 2");
|
||||||
//mod::loadModule("../modules/demo/build/Release/demo.dll", "Demo Module 3");
|
//mod::loadModule("../modules/demo/build/Release/demo.dll", "Demo Module 3");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
spdlog::info("Ready.");
|
spdlog::info("Ready.");
|
||||||
|
|
||||||
// Main loop
|
// Main loop
|
||||||
|
@ -40,8 +40,20 @@ void windowInit() {
|
|||||||
int sampleRate = 8000000;
|
int sampleRate = 8000000;
|
||||||
wtf.setBandwidth(sampleRate);
|
wtf.setBandwidth(sampleRate);
|
||||||
wtf.setCenterFrequency(90500000);
|
wtf.setCenterFrequency(90500000);
|
||||||
wtf.setVFOBandwidth(200000);
|
// wtf.setVFOBandwidth(200000);
|
||||||
wtf.setVFOOffset(0);
|
// wtf.setVFOOffset(0);
|
||||||
|
|
||||||
|
wtf.vfos["Radio"] = new ImGui::WaterfallVFO;
|
||||||
|
wtf.vfos["Radio"]->setReference(ImGui::WaterfallVFO::REF_CENTER);
|
||||||
|
wtf.vfos["Radio"]->setBandwidth(200000);
|
||||||
|
wtf.vfos["Radio"]->setOffset(0);
|
||||||
|
|
||||||
|
wtf.vfos["Radio 2"] = new ImGui::WaterfallVFO;
|
||||||
|
wtf.vfos["Radio 2"]->setReference(ImGui::WaterfallVFO::REF_CENTER);
|
||||||
|
wtf.vfos["Radio 2"]->setBandwidth(200000);
|
||||||
|
wtf.vfos["Radio 2"]->setOffset(300000);
|
||||||
|
|
||||||
|
wtf.selectedVFO = "Radio";
|
||||||
|
|
||||||
fSel.init();
|
fSel.init();
|
||||||
fSel.setFrequency(90500000);
|
fSel.setFrequency(90500000);
|
||||||
@ -71,14 +83,20 @@ int sampleRate = 1000000;
|
|||||||
bool playing = false;
|
bool playing = false;
|
||||||
watcher<bool> dcbias(false, false);
|
watcher<bool> dcbias(false, false);
|
||||||
watcher<bool> bandPlanEnabled(true, false);
|
watcher<bool> bandPlanEnabled(true, false);
|
||||||
|
bool selectedVFOChanged = false;
|
||||||
|
|
||||||
void setVFO(float freq) {
|
void setVFO(float freq) {
|
||||||
float currentOff = wtf.getVFOOfset();
|
if (wtf.selectedVFO == "") {
|
||||||
float currentTune = wtf.getCenterFrequency() + currentOff;
|
return;
|
||||||
|
}
|
||||||
|
ImGui::WaterfallVFO* vfo = wtf.vfos[wtf.selectedVFO];
|
||||||
|
|
||||||
|
float currentOff = vfo->centerOffset;
|
||||||
|
float currentTune = wtf.getCenterFrequency() + vfo->generalOffset;
|
||||||
float delta = freq - currentTune;
|
float delta = freq - currentTune;
|
||||||
|
|
||||||
float newVFO = currentOff + delta;
|
float newVFO = currentOff + delta;
|
||||||
float vfoBW = wtf.getVFOBandwidth();
|
float vfoBW = vfo->bandwidth;
|
||||||
float vfoBottom = newVFO - (vfoBW / 2.0f);
|
float vfoBottom = newVFO - (vfoBW / 2.0f);
|
||||||
float vfoTop = newVFO + (vfoBW / 2.0f);
|
float vfoTop = newVFO + (vfoBW / 2.0f);
|
||||||
|
|
||||||
@ -95,7 +113,7 @@ void setVFO(float freq) {
|
|||||||
// VFO still fints in the view
|
// VFO still fints in the view
|
||||||
if (vfoBottom > viewBottom && vfoTop < viewTop) {
|
if (vfoBottom > viewBottom && vfoTop < viewTop) {
|
||||||
sigPath.setVFOFrequency(newVFO);
|
sigPath.setVFOFrequency(newVFO);
|
||||||
wtf.setVFOOffset(newVFO);
|
vfo->setCenterOffset(newVFO);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +122,7 @@ void setVFO(float freq) {
|
|||||||
wtf.setViewOffset((BW / 2.0f) - (viewBW / 2.0f));
|
wtf.setViewOffset((BW / 2.0f) - (viewBW / 2.0f));
|
||||||
float newVFOOffset = (BW / 2.0f) - (vfoBW / 2.0f) - (viewBW / 10.0f);
|
float newVFOOffset = (BW / 2.0f) - (vfoBW / 2.0f) - (viewBW / 10.0f);
|
||||||
sigPath.setVFOFrequency(newVFOOffset);
|
sigPath.setVFOFrequency(newVFOOffset);
|
||||||
wtf.setVFOOffset(newVFOOffset);
|
vfo->setCenterOffset(newVFOOffset);
|
||||||
wtf.setCenterFrequency(freq - newVFOOffset);
|
wtf.setCenterFrequency(freq - newVFOOffset);
|
||||||
soapy.setFrequency(freq - newVFOOffset);
|
soapy.setFrequency(freq - newVFOOffset);
|
||||||
return;
|
return;
|
||||||
@ -115,7 +133,7 @@ void setVFO(float freq) {
|
|||||||
wtf.setViewOffset((viewBW / 2.0f) - (BW / 2.0f));
|
wtf.setViewOffset((viewBW / 2.0f) - (BW / 2.0f));
|
||||||
float newVFOOffset = (vfoBW / 2.0f) - (BW / 2.0f) + (viewBW / 10.0f);
|
float newVFOOffset = (vfoBW / 2.0f) - (BW / 2.0f) + (viewBW / 10.0f);
|
||||||
sigPath.setVFOFrequency(newVFOOffset);
|
sigPath.setVFOFrequency(newVFOOffset);
|
||||||
wtf.setVFOOffset(newVFOOffset);
|
vfo->setCenterOffset(newVFOOffset);
|
||||||
wtf.setCenterFrequency(freq - newVFOOffset);
|
wtf.setCenterFrequency(freq - newVFOOffset);
|
||||||
soapy.setFrequency(freq - newVFOOffset);
|
soapy.setFrequency(freq - newVFOOffset);
|
||||||
return;
|
return;
|
||||||
@ -128,7 +146,7 @@ void setVFO(float freq) {
|
|||||||
float newViewTop = newViewOff + (viewBW / 2.0f);
|
float newViewTop = newViewOff + (viewBW / 2.0f);
|
||||||
|
|
||||||
if (newViewBottom > bottom) {
|
if (newViewBottom > bottom) {
|
||||||
wtf.setVFOOffset(newVFO);
|
vfo->setCenterOffset(newVFO);
|
||||||
wtf.setViewOffset(newViewOff);
|
wtf.setViewOffset(newViewOff);
|
||||||
sigPath.setVFOFrequency(newVFO);
|
sigPath.setVFOFrequency(newVFO);
|
||||||
return;
|
return;
|
||||||
@ -137,7 +155,7 @@ void setVFO(float freq) {
|
|||||||
wtf.setViewOffset((BW / 2.0f) - (viewBW / 2.0f));
|
wtf.setViewOffset((BW / 2.0f) - (viewBW / 2.0f));
|
||||||
float newVFOOffset = (BW / 2.0f) - (vfoBW / 2.0f) - (viewBW / 10.0f);
|
float newVFOOffset = (BW / 2.0f) - (vfoBW / 2.0f) - (viewBW / 10.0f);
|
||||||
sigPath.setVFOFrequency(newVFOOffset);
|
sigPath.setVFOFrequency(newVFOOffset);
|
||||||
wtf.setVFOOffset(newVFOOffset);
|
vfo->setCenterOffset(newVFOOffset);
|
||||||
wtf.setCenterFrequency(freq - newVFOOffset);
|
wtf.setCenterFrequency(freq - newVFOOffset);
|
||||||
soapy.setFrequency(freq - newVFOOffset);
|
soapy.setFrequency(freq - newVFOOffset);
|
||||||
}
|
}
|
||||||
@ -147,7 +165,7 @@ void setVFO(float freq) {
|
|||||||
float newViewTop = newViewOff + (viewBW / 2.0f);
|
float newViewTop = newViewOff + (viewBW / 2.0f);
|
||||||
|
|
||||||
if (newViewTop < top) {
|
if (newViewTop < top) {
|
||||||
wtf.setVFOOffset(newVFO);
|
vfo->setCenterOffset(newVFO);
|
||||||
wtf.setViewOffset(newViewOff);
|
wtf.setViewOffset(newViewOff);
|
||||||
sigPath.setVFOFrequency(newVFO);
|
sigPath.setVFOFrequency(newVFO);
|
||||||
return;
|
return;
|
||||||
@ -156,13 +174,20 @@ void setVFO(float freq) {
|
|||||||
wtf.setViewOffset((viewBW / 2.0f) - (BW / 2.0f));
|
wtf.setViewOffset((viewBW / 2.0f) - (BW / 2.0f));
|
||||||
float newVFOOffset = (vfoBW / 2.0f) - (BW / 2.0f) + (viewBW / 10.0f);
|
float newVFOOffset = (vfoBW / 2.0f) - (BW / 2.0f) + (viewBW / 10.0f);
|
||||||
sigPath.setVFOFrequency(newVFOOffset);
|
sigPath.setVFOFrequency(newVFOOffset);
|
||||||
wtf.setVFOOffset(newVFOOffset);
|
vfo->setCenterOffset(newVFOOffset);
|
||||||
wtf.setCenterFrequency(freq - newVFOOffset);
|
wtf.setCenterFrequency(freq - newVFOOffset);
|
||||||
soapy.setFrequency(freq - newVFOOffset);
|
soapy.setFrequency(freq - newVFOOffset);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawWindow() {
|
void drawWindow() {
|
||||||
|
ImGui::WaterfallVFO* vfo = wtf.vfos[wtf.selectedVFO];
|
||||||
|
|
||||||
|
if (selectedVFOChanged) {
|
||||||
|
selectedVFOChanged = false;
|
||||||
|
fSel.setFrequency(vfo->generalOffset + wtf.getCenterFrequency());
|
||||||
|
}
|
||||||
|
|
||||||
if (fSel.frequencyChanged) {
|
if (fSel.frequencyChanged) {
|
||||||
fSel.frequencyChanged = false;
|
fSel.frequencyChanged = false;
|
||||||
setVFO(fSel.frequency);
|
setVFO(fSel.frequency);
|
||||||
@ -171,12 +196,12 @@ void drawWindow() {
|
|||||||
if (wtf.centerFreqMoved) {
|
if (wtf.centerFreqMoved) {
|
||||||
wtf.centerFreqMoved = false;
|
wtf.centerFreqMoved = false;
|
||||||
soapy.setFrequency(wtf.getCenterFrequency());
|
soapy.setFrequency(wtf.getCenterFrequency());
|
||||||
fSel.setFrequency(wtf.getCenterFrequency() + wtf.getVFOOfset());
|
fSel.setFrequency(wtf.getCenterFrequency() + vfo->generalOffset);
|
||||||
}
|
}
|
||||||
if (wtf.vfoFreqChanged) {
|
if (wtf.vfoFreqChanged) {
|
||||||
wtf.vfoFreqChanged = false;
|
wtf.vfoFreqChanged = false;
|
||||||
sigPath.setVFOFrequency(wtf.getVFOOfset());
|
sigPath.setVFOFrequency(vfo->centerOffset);
|
||||||
fSel.setFrequency(wtf.getCenterFrequency() + wtf.getVFOOfset());
|
fSel.setFrequency(wtf.getCenterFrequency() + vfo->generalOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (volume.changed()) {
|
if (volume.changed()) {
|
||||||
@ -303,42 +328,41 @@ void drawWindow() {
|
|||||||
ImGui::Columns(4, "RadioModeColumns", false);
|
ImGui::Columns(4, "RadioModeColumns", false);
|
||||||
if (ImGui::RadioButton("NFM", demod == 0) && demod != 0) {
|
if (ImGui::RadioButton("NFM", demod == 0) && demod != 0) {
|
||||||
sigPath.setDemodulator(SignalPath::DEMOD_NFM); demod = 0;
|
sigPath.setDemodulator(SignalPath::DEMOD_NFM); demod = 0;
|
||||||
wtf.setVFOBandwidth(12500);
|
vfo->setBandwidth(12500);
|
||||||
wtf.setVFOReference(ImGui::WaterFall::REF_CENTER);
|
vfo->setReference(ImGui::WaterFall::REF_CENTER);
|
||||||
}
|
}
|
||||||
if (ImGui::RadioButton("WFM", demod == 1) && demod != 1) {
|
if (ImGui::RadioButton("WFM", demod == 1) && demod != 1) {
|
||||||
sigPath.setDemodulator(SignalPath::DEMOD_FM);
|
sigPath.setDemodulator(SignalPath::DEMOD_FM);
|
||||||
demod = 1;
|
demod = 1;
|
||||||
wtf.setVFOBandwidth(200000);
|
vfo->setBandwidth(200000);
|
||||||
wtf.setVFOReference(ImGui::WaterFall::REF_CENTER);
|
vfo->setReference(ImGui::WaterFall::REF_CENTER);
|
||||||
}
|
}
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
if (ImGui::RadioButton("AM", demod == 2) && demod != 2) {
|
if (ImGui::RadioButton("AM", demod == 2) && demod != 2) {
|
||||||
sigPath.setDemodulator(SignalPath::DEMOD_AM);
|
sigPath.setDemodulator(SignalPath::DEMOD_AM);
|
||||||
demod = 2;
|
demod = 2;
|
||||||
wtf.setVFOBandwidth(12500);
|
vfo->setBandwidth(12500);
|
||||||
wtf.setVFOReference(ImGui::WaterFall::REF_CENTER);
|
vfo->setReference(ImGui::WaterFall::REF_CENTER);
|
||||||
}
|
}
|
||||||
if (ImGui::RadioButton("DSB", demod == 3) && demod != 3) { demod = 3; };
|
if (ImGui::RadioButton("DSB", demod == 3) && demod != 3) { demod = 3; };
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
if (ImGui::RadioButton("USB", demod == 4) && demod != 4) {
|
if (ImGui::RadioButton("USB", demod == 4) && demod != 4) {
|
||||||
sigPath.setDemodulator(SignalPath::DEMOD_USB);
|
sigPath.setDemodulator(SignalPath::DEMOD_USB);
|
||||||
demod = 4;
|
demod = 4;
|
||||||
wtf.setVFOBandwidth(3000);
|
vfo->setBandwidth(3000);
|
||||||
wtf.setVFOReference(ImGui::WaterFall::REF_LOWER);
|
vfo->setReference(ImGui::WaterFall::REF_LOWER);
|
||||||
}
|
}
|
||||||
if (ImGui::RadioButton("CW", demod == 5) && demod != 5) { demod = 5; };
|
if (ImGui::RadioButton("CW", demod == 5) && demod != 5) { demod = 5; };
|
||||||
ImGui::NextColumn();
|
ImGui::NextColumn();
|
||||||
if (ImGui::RadioButton("LSB", demod == 6) && demod != 6) {
|
if (ImGui::RadioButton("LSB", demod == 6) && demod != 6) {
|
||||||
sigPath.setDemodulator(SignalPath::DEMOD_LSB);
|
sigPath.setDemodulator(SignalPath::DEMOD_LSB);
|
||||||
demod = 6;
|
demod = 6;
|
||||||
wtf.setVFOBandwidth(3000);
|
vfo->setBandwidth(3000);
|
||||||
wtf.setVFOReference(ImGui::WaterFall::REF_UPPER);
|
vfo->setReference(ImGui::WaterFall::REF_UPPER);
|
||||||
}
|
}
|
||||||
if (ImGui::RadioButton("RAW", demod == 7) && demod != 7) { demod = 7; };
|
if (ImGui::RadioButton("RAW", demod == 7) && demod != 7) { demod = 7; };
|
||||||
ImGui::Columns(1, "EndRadioModeColumns", false);
|
ImGui::Columns(1, "EndRadioModeColumns", false);
|
||||||
|
|
||||||
//ImGui::InputInt("Frequency (kHz)", &freq);
|
|
||||||
ImGui::Checkbox("DC Bias Removal", &dcbias.val);
|
ImGui::Checkbox("DC Bias Removal", &dcbias.val);
|
||||||
|
|
||||||
ImGui::EndGroup();
|
ImGui::EndGroup();
|
||||||
@ -363,6 +387,17 @@ void drawWindow() {
|
|||||||
if(ImGui::CollapsingHeader("Debug")) {
|
if(ImGui::CollapsingHeader("Debug")) {
|
||||||
ImGui::Text("Frame time: %.3f ms/frame", 1000.0f / ImGui::GetIO().Framerate);
|
ImGui::Text("Frame time: %.3f ms/frame", 1000.0f / ImGui::GetIO().Framerate);
|
||||||
ImGui::Text("Framerate: %.1f FPS", ImGui::GetIO().Framerate);
|
ImGui::Text("Framerate: %.1f FPS", ImGui::GetIO().Framerate);
|
||||||
|
ImGui::Text("Center Frequency: %.1f FPS", wtf.getCenterFrequency());
|
||||||
|
|
||||||
|
if (ImGui::Button("Radio##__sdsd__")) {
|
||||||
|
wtf.selectedVFO = "Radio";
|
||||||
|
selectedVFOChanged = true;
|
||||||
|
}
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Button("Radio 2")) {
|
||||||
|
wtf.selectedVFO = "Radio 2";
|
||||||
|
selectedVFOChanged = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
@ -391,7 +426,7 @@ void drawWindow() {
|
|||||||
|
|
||||||
if (bw.changed()) {
|
if (bw.changed()) {
|
||||||
wtf.setViewBandwidth(bw.val);
|
wtf.setViewBandwidth(bw.val);
|
||||||
wtf.setViewOffset(wtf.getVFOOfset());
|
wtf.setViewOffset(vfo->centerOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
wtf.setFFTMin(fftMin);
|
wtf.setFFTMin(fftMin);
|
||||||
|
5
src/vfo_manager.h
Normal file
5
src/vfo_manager.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace vfoman {
|
||||||
|
|
||||||
|
};
|
@ -173,38 +173,35 @@ namespace ImGui {
|
|||||||
ImVec2(widgetPos.x + 50 + dataWidth, widgetPos.y + fftHeight + 51 + waterfallHeight));
|
ImVec2(widgetPos.x + 50 + dataWidth, widgetPos.y + fftHeight + 51 + waterfallHeight));
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaterFall::drawVFO() {
|
void WaterFall::drawVFOs() {
|
||||||
float width = (vfoBandwidth / viewBandwidth) * (float)dataWidth;
|
for (auto const& [name, vfo] : vfos) {
|
||||||
int center = roundf((((vfoOffset - viewOffset) / (viewBandwidth / 2.0f)) + 1.0f) * ((float)dataWidth / 2.0f));
|
if (vfo->redrawRequired) {
|
||||||
int left;
|
vfo->redrawRequired = false;
|
||||||
int right;
|
vfo->updateDrawingVars(viewBandwidth, dataWidth, viewOffset, widgetPos, fftHeight);
|
||||||
|
}
|
||||||
|
vfo->draw(window, name == selectedVFO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaterFall::processInputs() {
|
||||||
ImVec2 mousePos = ImGui::GetMousePos();
|
ImVec2 mousePos = ImGui::GetMousePos();
|
||||||
ImVec2 drag = ImGui::GetMouseDragDelta(ImGuiMouseButton_Left);
|
ImVec2 drag = ImGui::GetMouseDragDelta(ImGuiMouseButton_Left);
|
||||||
ImVec2 dragOrigin(mousePos.x - drag.x, mousePos.y - drag.y);
|
ImVec2 dragOrigin(mousePos.x - drag.x, mousePos.y - drag.y);
|
||||||
|
|
||||||
|
if (ImGui::IsMouseClicked(ImGuiMouseButton_Left)) {
|
||||||
|
spdlog::info("Clicked!");
|
||||||
|
}
|
||||||
|
|
||||||
bool freqDrag = ImGui::IsMouseDragging(ImGuiMouseButton_Left) && IS_IN_AREA(dragOrigin, freqAreaMin, freqAreaMax);
|
bool freqDrag = ImGui::IsMouseDragging(ImGuiMouseButton_Left) && IS_IN_AREA(dragOrigin, freqAreaMin, freqAreaMax);
|
||||||
|
|
||||||
if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && IS_IN_AREA(mousePos, fftAreaMin, fftAreaMax) && !freqDrag) {
|
// TODO: Process VFO drag
|
||||||
int refCenter = mousePos.x - (widgetPos.x + 50);
|
|
||||||
if (refCenter >= 0 && refCenter < dataWidth && mousePos.y > widgetPos.y && mousePos.y < (widgetPos.y + widgetSize.y)) {
|
|
||||||
vfoOffset = ((((float)refCenter / ((float)dataWidth / 2.0f)) - 1.0f) * (viewBandwidth / 2.0f)) + viewOffset;
|
|
||||||
center = refCenter;
|
|
||||||
}
|
|
||||||
vfoFreqChanged = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (vfoRef == REF_CENTER) {
|
// if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && IS_IN_AREA(mousePos, fftAreaMin, fftAreaMax) && !freqDrag) {
|
||||||
// left = center - (width / 2.0f) + 1;
|
// int refCenter = mousePos.x - (widgetPos.x + 50);
|
||||||
// right = center + (width / 2.0f) + 1;
|
// if (refCenter >= 0 && refCenter < dataWidth && mousePos.y > widgetPos.y && mousePos.y < (widgetPos.y + widgetSize.y)) {
|
||||||
|
// vfoOffset = ((((float)refCenter / ((float)dataWidth / 2.0f)) - 1.0f) * (viewBandwidth / 2.0f)) + viewOffset;
|
||||||
// }
|
// }
|
||||||
// if (vfoRef == REF_LOWER) {
|
// vfoFreqChanged = true;
|
||||||
// left = center;
|
|
||||||
// right = center + width + 1;
|
|
||||||
// }
|
|
||||||
// if (vfoRef == REF_UPPER) {
|
|
||||||
// left = center;
|
|
||||||
// right = center - width + 1;
|
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (freqDrag) {
|
if (freqDrag) {
|
||||||
@ -234,35 +231,6 @@ namespace ImGui {
|
|||||||
else {
|
else {
|
||||||
lastDrag = 0;
|
lastDrag = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
left = center - (width / 2.0f) + 1;
|
|
||||||
right = center + (width / 2.0f) + 1;
|
|
||||||
|
|
||||||
if ((left < 0 && right < 0) || (left >= dataWidth && right >= dataWidth)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
left = std::clamp<int>(left, 0, dataWidth - 1);
|
|
||||||
right = std::clamp<int>(right, 0, dataWidth - 1);
|
|
||||||
window->DrawList->AddRectFilled(ImVec2(widgetPos.x + 50 + left, widgetPos.y + 10),
|
|
||||||
ImVec2(widgetPos.x + 50 + right, widgetPos.y + fftHeight + 10), IM_COL32(255, 255, 255, 50));
|
|
||||||
if (center >= 0 && center < dataWidth) {
|
|
||||||
if (vfoRef == REF_CENTER) {
|
|
||||||
window->DrawList->AddLine(ImVec2(widgetPos.x + 50 + center, widgetPos.y + 9),
|
|
||||||
ImVec2(widgetPos.x + 50 + center, widgetPos.y + fftHeight + 9),
|
|
||||||
IM_COL32(255, 0, 0, 255), 1.0f);
|
|
||||||
}
|
|
||||||
else if (vfoRef == REF_LOWER) {
|
|
||||||
window->DrawList->AddLine(ImVec2(widgetPos.x + 50 + left, widgetPos.y + 9),
|
|
||||||
ImVec2(widgetPos.x + 50 + left, widgetPos.y + fftHeight + 9),
|
|
||||||
IM_COL32(255, 0, 0, 255), 1.0f);
|
|
||||||
}
|
|
||||||
else if (vfoRef == REF_UPPER) {
|
|
||||||
window->DrawList->AddLine(ImVec2(widgetPos.x + 50 + right, widgetPos.y + 9),
|
|
||||||
ImVec2(widgetPos.x + 50 + right, widgetPos.y + fftHeight + 9),
|
|
||||||
IM_COL32(255, 0, 0, 255), 1.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaterFall::updateWaterfallFb() {
|
void WaterFall::updateWaterfallFb() {
|
||||||
@ -382,6 +350,7 @@ namespace ImGui {
|
|||||||
vRange = 10.0f;
|
vRange = 10.0f;
|
||||||
|
|
||||||
updateWaterfallFb();
|
updateWaterfallFb();
|
||||||
|
updateAllVFOs();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaterFall::draw() {
|
void WaterFall::draw() {
|
||||||
@ -408,9 +377,11 @@ namespace ImGui {
|
|||||||
window->DrawList->AddRect(widgetPos, widgetEndPos, IM_COL32( 50, 50, 50, 255 ));
|
window->DrawList->AddRect(widgetPos, widgetEndPos, IM_COL32( 50, 50, 50, 255 ));
|
||||||
window->DrawList->AddLine(ImVec2(widgetPos.x, widgetPos.y + fftHeight + 50), ImVec2(widgetPos.x + widgetSize.x, widgetPos.y + fftHeight + 50), IM_COL32(50, 50, 50, 255), 1.0f);
|
window->DrawList->AddLine(ImVec2(widgetPos.x, widgetPos.y + fftHeight + 50), ImVec2(widgetPos.x + widgetSize.x, widgetPos.y + fftHeight + 50), IM_COL32(50, 50, 50, 255), 1.0f);
|
||||||
|
|
||||||
|
processInputs();
|
||||||
|
|
||||||
drawFFT();
|
drawFFT();
|
||||||
drawWaterfall();
|
drawWaterfall();
|
||||||
drawVFO();
|
drawVFOs();
|
||||||
if (bandplan != NULL) {
|
if (bandplan != NULL) {
|
||||||
drawBandPlan();
|
drawBandPlan();
|
||||||
}
|
}
|
||||||
@ -475,6 +446,7 @@ namespace ImGui {
|
|||||||
centerFreq = freq;
|
centerFreq = freq;
|
||||||
lowerFreq = (centerFreq + viewOffset) - (viewBandwidth / 2.0f);
|
lowerFreq = (centerFreq + viewOffset) - (viewBandwidth / 2.0f);
|
||||||
upperFreq = (centerFreq + viewOffset) + (viewBandwidth / 2.0f);
|
upperFreq = (centerFreq + viewOffset) + (viewBandwidth / 2.0f);
|
||||||
|
updateAllVFOs();
|
||||||
}
|
}
|
||||||
|
|
||||||
float WaterFall::getCenterFrequency() {
|
float WaterFall::getCenterFrequency() {
|
||||||
@ -485,35 +457,13 @@ namespace ImGui {
|
|||||||
float currentRatio = viewBandwidth / wholeBandwidth;
|
float currentRatio = viewBandwidth / wholeBandwidth;
|
||||||
wholeBandwidth = bandWidth;
|
wholeBandwidth = bandWidth;
|
||||||
setViewBandwidth(bandWidth * currentRatio);
|
setViewBandwidth(bandWidth * currentRatio);
|
||||||
|
updateAllVFOs();
|
||||||
}
|
}
|
||||||
|
|
||||||
float WaterFall::getBandwidth() {
|
float WaterFall::getBandwidth() {
|
||||||
return wholeBandwidth;
|
return wholeBandwidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WaterFall::setVFOOffset(float offset) {
|
|
||||||
vfoOffset = offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
float WaterFall::getVFOOfset() {
|
|
||||||
return vfoOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaterFall::setVFOBandwidth(float bandwidth) {
|
|
||||||
vfoBandwidth = bandwidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
float WaterFall::getVFOBandwidth() {
|
|
||||||
return vfoBandwidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaterFall::setVFOReference(int ref) {
|
|
||||||
if (ref < 0 || ref >= _REF_COUNT) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
vfoRef = ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WaterFall::setViewBandwidth(float bandWidth) {
|
void WaterFall::setViewBandwidth(float bandWidth) {
|
||||||
if (bandWidth == viewBandwidth) {
|
if (bandWidth == viewBandwidth) {
|
||||||
return;
|
return;
|
||||||
@ -531,6 +481,7 @@ namespace ImGui {
|
|||||||
upperFreq = (centerFreq + viewOffset) + (viewBandwidth / 2.0f);
|
upperFreq = (centerFreq + viewOffset) + (viewBandwidth / 2.0f);
|
||||||
range = findBestRange(bandWidth, maxHSteps);
|
range = findBestRange(bandWidth, maxHSteps);
|
||||||
updateWaterfallFb();
|
updateWaterfallFb();
|
||||||
|
updateAllVFOs();
|
||||||
}
|
}
|
||||||
|
|
||||||
float WaterFall::getViewBandwidth() {
|
float WaterFall::getViewBandwidth() {
|
||||||
@ -551,6 +502,7 @@ namespace ImGui {
|
|||||||
lowerFreq = (centerFreq + viewOffset) - (viewBandwidth / 2.0f);
|
lowerFreq = (centerFreq + viewOffset) - (viewBandwidth / 2.0f);
|
||||||
upperFreq = (centerFreq + viewOffset) + (viewBandwidth / 2.0f);
|
upperFreq = (centerFreq + viewOffset) + (viewBandwidth / 2.0f);
|
||||||
updateWaterfallFb();
|
updateWaterfallFb();
|
||||||
|
updateAllVFOs();
|
||||||
}
|
}
|
||||||
|
|
||||||
float WaterFall::getViewOffset() {
|
float WaterFall::getViewOffset() {
|
||||||
@ -598,5 +550,130 @@ namespace ImGui {
|
|||||||
float WaterFall::getWaterfallMax() {
|
float WaterFall::getWaterfallMax() {
|
||||||
return waterfallMax;
|
return waterfallMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WaterFall::updateAllVFOs() {
|
||||||
|
for (auto const& [name, vfo] : vfos) {
|
||||||
|
vfo->updateDrawingVars(viewBandwidth, dataWidth, viewOffset, widgetPos, fftHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaterfallVFO::setOffset(float offset) {
|
||||||
|
generalOffset = offset;
|
||||||
|
if (reference == REF_CENTER) {
|
||||||
|
centerOffset = offset;
|
||||||
|
lowerOffset = offset - (bandwidth / 2.0f);
|
||||||
|
upperOffset = offset + (bandwidth / 2.0f);
|
||||||
|
}
|
||||||
|
else if (reference == REF_LOWER) {
|
||||||
|
lowerOffset = offset;
|
||||||
|
centerOffset = offset + (bandwidth / 2.0f);
|
||||||
|
upperOffset = offset + bandwidth;
|
||||||
|
}
|
||||||
|
else if (reference == REF_UPPER) {
|
||||||
|
upperOffset = offset;
|
||||||
|
centerOffset = offset - (bandwidth / 2.0f);
|
||||||
|
lowerOffset = offset - bandwidth;
|
||||||
|
}
|
||||||
|
centerOffsetChanged = true;
|
||||||
|
upperOffsetChanged = true;
|
||||||
|
lowerOffsetChanged = true;
|
||||||
|
redrawRequired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaterfallVFO::setCenterOffset(float offset) {
|
||||||
|
if (reference == REF_CENTER) {
|
||||||
|
generalOffset = offset;
|
||||||
|
}
|
||||||
|
else if (reference == REF_LOWER) {
|
||||||
|
generalOffset = offset - (bandwidth / 2.0f);
|
||||||
|
}
|
||||||
|
else if (reference == REF_UPPER) {
|
||||||
|
generalOffset = offset + (bandwidth / 2.0f);
|
||||||
|
}
|
||||||
|
centerOffset = offset;
|
||||||
|
lowerOffset = offset - (bandwidth / 2.0f);
|
||||||
|
upperOffset = offset + (bandwidth / 2.0f);
|
||||||
|
centerOffsetChanged = true;
|
||||||
|
upperOffsetChanged = true;
|
||||||
|
lowerOffsetChanged = true;
|
||||||
|
redrawRequired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaterfallVFO::setBandwidth(float bw) {
|
||||||
|
if (bandwidth == bw || bw < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bandwidth = bw;
|
||||||
|
if (reference == REF_CENTER) {
|
||||||
|
lowerOffset = centerOffset - (bandwidth / 2.0f);
|
||||||
|
upperOffset = centerOffset + (bandwidth / 2.0f);
|
||||||
|
}
|
||||||
|
else if (reference == REF_LOWER) {
|
||||||
|
centerOffset = lowerOffset + (bandwidth / 2.0f);
|
||||||
|
upperOffset = lowerOffset + bandwidth;
|
||||||
|
centerOffsetChanged;
|
||||||
|
}
|
||||||
|
else if (reference == REF_UPPER) {
|
||||||
|
centerOffset = upperOffset - (bandwidth / 2.0f);
|
||||||
|
lowerOffset = upperOffset - bandwidth;
|
||||||
|
centerOffsetChanged;
|
||||||
|
}
|
||||||
|
redrawRequired = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaterfallVFO::setReference(int ref) {
|
||||||
|
if (reference == ref || ref < 0 || ref >= _REF_COUNT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
reference = ref;
|
||||||
|
if (reference == REF_CENTER) {
|
||||||
|
setOffset(centerOffset);
|
||||||
|
}
|
||||||
|
else if (reference == REF_LOWER) {
|
||||||
|
setOffset(lowerOffset);
|
||||||
|
}
|
||||||
|
else if (reference == REF_UPPER) {
|
||||||
|
setOffset(upperOffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaterfallVFO::updateDrawingVars(float viewBandwidth, float dataWidth, float viewOffset, ImVec2 widgetPos, int fftHeight) {
|
||||||
|
float width = (bandwidth / viewBandwidth) * (float)dataWidth;
|
||||||
|
int center = roundf((((centerOffset - viewOffset) / (viewBandwidth / 2.0f)) + 1.0f) * ((float)dataWidth / 2.0f));
|
||||||
|
int left = roundf((((lowerOffset - viewOffset) / (viewBandwidth / 2.0f)) + 1.0f) * ((float)dataWidth / 2.0f));
|
||||||
|
int right = roundf((((upperOffset - viewOffset) / (viewBandwidth / 2.0f)) + 1.0f) * ((float)dataWidth / 2.0f));
|
||||||
|
|
||||||
|
if (left >= 0 && left < dataWidth && reference == REF_LOWER) {
|
||||||
|
lineMin = ImVec2(widgetPos.x + 50 + left, widgetPos.y + 9);
|
||||||
|
lineMax = ImVec2(widgetPos.x + 50 + left, widgetPos.y + fftHeight + 9);
|
||||||
|
lineVisible = true;
|
||||||
|
}
|
||||||
|
else if (center >= 0 && center < dataWidth && reference == REF_CENTER) {
|
||||||
|
lineMin = ImVec2(widgetPos.x + 50 + center, widgetPos.y + 9);
|
||||||
|
lineMax = ImVec2(widgetPos.x + 50 + center, widgetPos.y + fftHeight + 9);
|
||||||
|
lineVisible = true;
|
||||||
|
}
|
||||||
|
else if (right >= 0 && right < dataWidth && reference == REF_UPPER) {
|
||||||
|
lineMin = ImVec2(widgetPos.x + 50 + right, widgetPos.y + 9);
|
||||||
|
lineMax = ImVec2(widgetPos.x + 50 + right, widgetPos.y + fftHeight + 9);
|
||||||
|
lineVisible = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lineVisible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
left = std::clamp<int>(left, 0, dataWidth - 1);
|
||||||
|
right = std::clamp<int>(right, 0, dataWidth - 1);
|
||||||
|
|
||||||
|
rectMin = ImVec2(widgetPos.x + 50 + left, widgetPos.y + 10);
|
||||||
|
rectMax = ImVec2(widgetPos.x + 51 + right, widgetPos.y + fftHeight + 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WaterfallVFO::draw(ImGuiWindow* window, bool selected) {
|
||||||
|
window->DrawList->AddRectFilled(rectMin, rectMax, IM_COL32(255, 255, 255, 50));
|
||||||
|
if (lineVisible) {
|
||||||
|
window->DrawList->AddLine(lineMin, lineMax, selected ? IM_COL32(255, 0, 0, 255) : IM_COL32(255, 255, 0, 255));
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,6 +12,41 @@
|
|||||||
|
|
||||||
namespace ImGui {
|
namespace ImGui {
|
||||||
|
|
||||||
|
class WaterfallVFO {
|
||||||
|
public:
|
||||||
|
void setOffset(float offset);
|
||||||
|
void setCenterOffset(float offset);
|
||||||
|
void setBandwidth(float bw);
|
||||||
|
void setReference(int ref);
|
||||||
|
void updateDrawingVars(float viewBandwidth, float dataWidth, float viewOffset, ImVec2 widgetPos, int fftHeight);
|
||||||
|
void draw(ImGuiWindow* window, bool selected);
|
||||||
|
|
||||||
|
enum {
|
||||||
|
REF_LOWER,
|
||||||
|
REF_CENTER,
|
||||||
|
REF_UPPER,
|
||||||
|
_REF_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
float generalOffset;
|
||||||
|
float centerOffset;
|
||||||
|
float lowerOffset;
|
||||||
|
float upperOffset;
|
||||||
|
float bandwidth;
|
||||||
|
int reference = REF_CENTER;
|
||||||
|
|
||||||
|
ImVec2 rectMin;
|
||||||
|
ImVec2 rectMax;
|
||||||
|
ImVec2 lineMin;
|
||||||
|
ImVec2 lineMax;
|
||||||
|
|
||||||
|
bool centerOffsetChanged = false;
|
||||||
|
bool lowerOffsetChanged = false;
|
||||||
|
bool upperOffsetChanged = false;
|
||||||
|
bool redrawRequired = true;
|
||||||
|
bool lineVisible = true;
|
||||||
|
};
|
||||||
|
|
||||||
class WaterFall {
|
class WaterFall {
|
||||||
public:
|
public:
|
||||||
WaterFall();
|
WaterFall();
|
||||||
@ -27,14 +62,6 @@ namespace ImGui {
|
|||||||
void setBandwidth(float bandWidth);
|
void setBandwidth(float bandWidth);
|
||||||
float getBandwidth();
|
float getBandwidth();
|
||||||
|
|
||||||
void setVFOOffset(float offset);
|
|
||||||
float getVFOOfset();
|
|
||||||
|
|
||||||
void setVFOBandwidth(float bandwidth);
|
|
||||||
float getVFOBandwidth();
|
|
||||||
|
|
||||||
void setVFOReference(int ref);
|
|
||||||
|
|
||||||
void setViewBandwidth(float bandWidth);
|
void setViewBandwidth(float bandWidth);
|
||||||
float getViewBandwidth();
|
float getViewBandwidth();
|
||||||
|
|
||||||
@ -63,6 +90,9 @@ namespace ImGui {
|
|||||||
bool bandplanEnabled = false;
|
bool bandplanEnabled = false;
|
||||||
bandplan::BandPlan_t* bandplan = NULL;
|
bandplan::BandPlan_t* bandplan = NULL;
|
||||||
|
|
||||||
|
std::map<std::string, WaterfallVFO*> vfos;
|
||||||
|
std::string selectedVFO;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
REF_LOWER,
|
REF_LOWER,
|
||||||
REF_CENTER,
|
REF_CENTER,
|
||||||
@ -74,12 +104,14 @@ namespace ImGui {
|
|||||||
private:
|
private:
|
||||||
void drawWaterfall();
|
void drawWaterfall();
|
||||||
void drawFFT();
|
void drawFFT();
|
||||||
void drawVFO();
|
void drawVFOs();
|
||||||
void drawBandPlan();
|
void drawBandPlan();
|
||||||
|
void processInputs();
|
||||||
void onPositionChange();
|
void onPositionChange();
|
||||||
void onResize();
|
void onResize();
|
||||||
void updateWaterfallFb();
|
void updateWaterfallFb();
|
||||||
void updateWaterfallTexture();
|
void updateWaterfallTexture();
|
||||||
|
void updateAllVFOs();
|
||||||
|
|
||||||
bool waterfallUpdate = false;
|
bool waterfallUpdate = false;
|
||||||
|
|
||||||
@ -129,10 +161,6 @@ namespace ImGui {
|
|||||||
float centerFreq;
|
float centerFreq;
|
||||||
float wholeBandwidth;
|
float wholeBandwidth;
|
||||||
|
|
||||||
// VFO
|
|
||||||
float vfoOffset;
|
|
||||||
float vfoBandwidth;
|
|
||||||
|
|
||||||
// Ranges
|
// Ranges
|
||||||
float fftMin;
|
float fftMin;
|
||||||
float fftMax;
|
float fftMax;
|
||||||
|
Loading…
Reference in New Issue
Block a user