mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2024-12-24 01:48:28 +01:00
Fixed issues with new module system
This commit is contained in:
parent
d6b9e1d86a
commit
9de585190f
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,4 +2,5 @@ build/
|
||||
.vscode/
|
||||
*.old
|
||||
*.dll
|
||||
*.exe
|
||||
*.exe
|
||||
*.zip
|
@ -9,13 +9,16 @@ else()
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive -fsanitize=address -g")
|
||||
# set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive")
|
||||
endif (MSVC)
|
||||
add_definitions(-DSDRPP_IS_CORE)
|
||||
|
||||
# Main code
|
||||
file(GLOB SRC "src/*.cpp")
|
||||
file(GLOB GUI "src/gui/*.cpp")
|
||||
file(GLOB SIGPATH "src/signal_path/*.cpp")
|
||||
file(GLOB IMGUI "src/imgui/*.cpp")
|
||||
|
||||
# Add code to dyn lib
|
||||
add_library(sdrpp_core SHARED ${SRC} ${IMGUI})
|
||||
add_library(sdrpp_core SHARED ${SRC} ${GUI} ${SIGPATH} ${IMGUI})
|
||||
|
||||
# Include core headers
|
||||
target_include_directories(sdrpp_core PUBLIC "src/")
|
||||
|
@ -4,12 +4,12 @@
|
||||
#include <stdio.h>
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <main_window.h>
|
||||
#include <style.h>
|
||||
#include <icons.h>
|
||||
#include <gui/main_window.h>
|
||||
#include <gui/style.h>
|
||||
#include <gui/icons.h>
|
||||
#include <version.h>
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <bandplan.h>
|
||||
#include <gui/bandplan.h>
|
||||
#include <module.h>
|
||||
#include <stb_image.h>
|
||||
#include <config.h>
|
||||
@ -139,23 +139,23 @@ int sdrpp_main() {
|
||||
|
||||
|
||||
// ====================================================
|
||||
// glfwPollEvents();
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
// ImGui_ImplGlfw_NewFrame();
|
||||
// ImGui::NewFrame();
|
||||
// // glfwPollEvents();
|
||||
// ImGui_ImplOpenGL3_NewFrame();
|
||||
// // ImGui_ImplGlfw_NewFrame();
|
||||
// // ImGui::NewFrame();
|
||||
|
||||
// ImGui::ShowDemoWindow();
|
||||
// // ImGui::ShowDemoWindow();
|
||||
|
||||
// ImGui::Render();
|
||||
int display_w, display_h;
|
||||
glfwGetFramebufferSize(window, &display_w, &display_h);
|
||||
glViewport(0, 0, display_w, display_h);
|
||||
glClearColor(0.0666f, 0.0666f, 0.0666f, 1.0f);
|
||||
//glClearColor(0.9f, 0.9f, 0.9f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
// ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
// // ImGui::Render();
|
||||
// int display_w, display_h;
|
||||
// glfwGetFramebufferSize(window, &display_w, &display_h);
|
||||
// glViewport(0, 0, display_w, display_h);
|
||||
// glClearColor(0.0666f, 0.0666f, 0.0666f, 1.0f);
|
||||
// //glClearColor(0.9f, 0.9f, 0.9f, 1.0f);
|
||||
// glClear(GL_COLOR_BUFFER_BIT);
|
||||
// // ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
// glfwSwapBuffers(window);
|
||||
// ====================================================
|
||||
|
||||
spdlog::info("Loading icons");
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <bandplan.h>
|
||||
#include <gui/bandplan.h>
|
||||
|
||||
namespace bandplan {
|
||||
std::map<std::string, BandPlan_t> bandplans;
|
@ -1,4 +1,4 @@
|
||||
#include <frequency_select.h>
|
||||
#include <gui/frequency_select.h>
|
||||
|
||||
bool isInArea(ImVec2 val, ImVec2 min, ImVec2 max) {
|
||||
return val.x >= min.x && val.x < max.x && val.y >= min.y && val.y < max.y;
|
6
core/src/gui/gui.cpp
Normal file
6
core/src/gui/gui.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include <gui/gui.h>
|
||||
|
||||
namespace gui {
|
||||
ImGui::WaterFall waterfall;
|
||||
FrequencySelect freqSelect;
|
||||
};
|
9
core/src/gui/gui.h
Normal file
9
core/src/gui/gui.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <gui/waterfall.h>
|
||||
#include <gui/frequency_select.h>
|
||||
#include <module.h>
|
||||
|
||||
namespace gui {
|
||||
SDRPP_EXPORT ImGui::WaterFall waterfall;
|
||||
SDRPP_EXPORT FrequencySelect freqSelect;
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
#include <icons.h>
|
||||
#include <gui/icons.h>
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <imgui/stb_image.h>
|
@ -1,9 +1,8 @@
|
||||
#include <main_window.h>
|
||||
#include <gui/main_window.h>
|
||||
#include <gui/gui.h>
|
||||
|
||||
std::thread worker;
|
||||
std::mutex fft_mtx;
|
||||
ImGui::WaterFall wtf;
|
||||
FrequencySelect fSel;
|
||||
fftwf_complex *fft_in, *fft_out;
|
||||
fftwf_plan p;
|
||||
float* tempData;
|
||||
@ -14,8 +13,6 @@ ImFont* bigFont;
|
||||
int fftSize = 8192 * 8;
|
||||
|
||||
io::SoapyWrapper soapy;
|
||||
|
||||
SignalPath sigPath;
|
||||
std::vector<float> _data;
|
||||
std::vector<float> fftTaps;
|
||||
void fftHandler(dsp::complex_t* samples) {
|
||||
@ -33,7 +30,7 @@ void fftHandler(dsp::complex_t* samples) {
|
||||
_data[i] = (_data[i - 4] + _data[i - 3] + _data[i - 2] + _data[i - 1] + _data[i]) / 5.0f;
|
||||
}
|
||||
|
||||
wtf.pushFFT(_data, fftSize);
|
||||
gui::waterfall.pushFFT(_data, fftSize);
|
||||
_data.clear();
|
||||
}
|
||||
|
||||
@ -87,7 +84,7 @@ void loadSourceConfig(std::string name) {
|
||||
else {
|
||||
srId = std::distance(soapy.sampleRates.begin(), _srIt);
|
||||
}
|
||||
sigPath.setSampleRate(sampleRate);
|
||||
sigpath::signalPath.setSampleRate(sampleRate);
|
||||
soapy.setSampleRate(sampleRate);
|
||||
|
||||
// Set gains
|
||||
@ -107,8 +104,8 @@ void loadSourceConfig(std::string name) {
|
||||
}
|
||||
|
||||
// Update GUI
|
||||
wtf.setBandwidth(sampleRate);
|
||||
wtf.setViewBandwidth(sampleRate);
|
||||
gui::waterfall.setBandwidth(sampleRate);
|
||||
gui::waterfall.setViewBandwidth(sampleRate);
|
||||
bw.val = sampleRate;
|
||||
}
|
||||
|
||||
@ -158,21 +155,19 @@ void windowInit() {
|
||||
spdlog::info("Initializing SoapySDR");
|
||||
soapy.init();
|
||||
|
||||
fSel.init();
|
||||
gui::freqSelect.init();
|
||||
|
||||
fft_in = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize);
|
||||
fft_out = (fftwf_complex*) fftwf_malloc(sizeof(fftwf_complex) * fftSize);
|
||||
p = fftwf_plan_dft_1d(fftSize, fft_in, fft_out, FFTW_FORWARD, FFTW_ESTIMATE);
|
||||
|
||||
sigPath.init(sampleRate, 20, fftSize, &soapy.output, (dsp::complex_t*)fft_in, fftHandler);
|
||||
sigPath.start();
|
||||
|
||||
vfoman::init(&wtf, &sigPath);
|
||||
sigpath::signalPath.init(sampleRate, 20, fftSize, &soapy.output, (dsp::complex_t*)fft_in, fftHandler);
|
||||
sigpath::signalPath.start();
|
||||
|
||||
uiGains = new float[soapy.gainList.size()];
|
||||
|
||||
spdlog::info("Loading modules");
|
||||
mod::initAPI(&wtf);
|
||||
mod::initAPI(&gui::waterfall);
|
||||
mod::loadFromList(config::getRootDirectory() + "/module_list.json");
|
||||
|
||||
bigFont = ImGui::GetIO().Fonts->AddFontFromFileTTF((config::getRootDirectory() + "/res/fonts/Roboto-Medium.ttf").c_str(), 128.0f);
|
||||
@ -206,7 +201,7 @@ void windowInit() {
|
||||
sourceName = soapy.devNameList[0];
|
||||
}
|
||||
sampleRate = soapy.getSampleRate();
|
||||
sigPath.setSampleRate(sampleRate);
|
||||
sigpath::signalPath.setSampleRate(sampleRate);
|
||||
}
|
||||
// Search for the first source in the list to have a config
|
||||
// If no pre-defined source, selected default device
|
||||
@ -229,10 +224,10 @@ void windowInit() {
|
||||
// Update UI settings
|
||||
fftMin = config::config["min"];
|
||||
fftMax = config::config["max"];
|
||||
wtf.setFFTMin(fftMin);
|
||||
wtf.setWaterfallMin(fftMin);
|
||||
wtf.setFFTMax(fftMax);
|
||||
wtf.setWaterfallMax(fftMax);
|
||||
gui::waterfall.setFFTMin(fftMin);
|
||||
gui::waterfall.setWaterfallMin(fftMin);
|
||||
gui::waterfall.setFFTMax(fftMax);
|
||||
gui::waterfall.setWaterfallMax(fftMax);
|
||||
|
||||
bandPlanEnabled.val = config::config["bandPlanEnabled"];
|
||||
bandPlanEnabled.markAsChanged();
|
||||
@ -243,10 +238,10 @@ void windowInit() {
|
||||
bandplanId.val = std::distance(bandplan::bandplans.begin(), bandplan::bandplans.find(bandPlanName));
|
||||
|
||||
if (bandPlanEnabled.val) {
|
||||
wtf.bandplan = &bandplan::bandplans[bandPlanName];
|
||||
gui::waterfall.bandplan = &bandplan::bandplans[bandPlanName];
|
||||
}
|
||||
else {
|
||||
wtf.bandplan = NULL;
|
||||
gui::waterfall.bandplan = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -255,16 +250,16 @@ void windowInit() {
|
||||
bandplanId.markAsChanged();
|
||||
|
||||
|
||||
fSel.setFrequency(frequency);
|
||||
fSel.frequencyChanged = false;
|
||||
gui::freqSelect.setFrequency(frequency);
|
||||
gui::freqSelect.frequencyChanged = false;
|
||||
soapy.setFrequency(frequency);
|
||||
wtf.setCenterFrequency(frequency);
|
||||
wtf.setBandwidth(sampleRate);
|
||||
wtf.setViewBandwidth(sampleRate);
|
||||
gui::waterfall.setCenterFrequency(frequency);
|
||||
gui::waterfall.setBandwidth(sampleRate);
|
||||
gui::waterfall.setViewBandwidth(sampleRate);
|
||||
bw.val = sampleRate;
|
||||
wtf.vfoFreqChanged = false;
|
||||
wtf.centerFreqMoved = false;
|
||||
wtf.selectFirstVFO();
|
||||
gui::waterfall.vfoFreqChanged = false;
|
||||
gui::waterfall.centerFreqMoved = false;
|
||||
gui::waterfall.selectFirstVFO();
|
||||
|
||||
for (auto [name, stream] : audio::streams) {
|
||||
if (config::config["audio"].contains(name)) {
|
||||
@ -277,7 +272,7 @@ void windowInit() {
|
||||
}
|
||||
}
|
||||
|
||||
audioStreamName = audio::getNameFromVFO(wtf.selectedVFO);
|
||||
audioStreamName = audio::getNameFromVFO(gui::waterfall.selectedVFO);
|
||||
if (audioStreamName != "") {
|
||||
volume = &audio::streams[audioStreamName]->volume;
|
||||
}
|
||||
@ -287,18 +282,18 @@ void windowInit() {
|
||||
|
||||
showWaterfall = config::config["showWaterfall"];
|
||||
if (!showWaterfall) {
|
||||
wtf.hideWaterfall();
|
||||
gui::waterfall.hideWaterfall();
|
||||
}
|
||||
|
||||
fftHeight = config::config["fftHeight"];
|
||||
wtf.setFFTHeight(fftHeight);
|
||||
gui::waterfall.setFFTHeight(fftHeight);
|
||||
}
|
||||
|
||||
void setVFO(float freq) {
|
||||
ImGui::WaterfallVFO* vfo = wtf.vfos[wtf.selectedVFO];
|
||||
ImGui::WaterfallVFO* vfo = gui::waterfall.vfos[gui::waterfall.selectedVFO];
|
||||
|
||||
float currentOff = vfo->centerOffset;
|
||||
float currentTune = wtf.getCenterFrequency() + vfo->generalOffset;
|
||||
float currentTune = gui::waterfall.getCenterFrequency() + vfo->generalOffset;
|
||||
float delta = freq - currentTune;
|
||||
|
||||
float newVFO = currentOff + delta;
|
||||
@ -306,38 +301,38 @@ void setVFO(float freq) {
|
||||
float vfoBottom = newVFO - (vfoBW / 2.0f);
|
||||
float vfoTop = newVFO + (vfoBW / 2.0f);
|
||||
|
||||
float view = wtf.getViewOffset();
|
||||
float viewBW = wtf.getViewBandwidth();
|
||||
float view = gui::waterfall.getViewOffset();
|
||||
float viewBW = gui::waterfall.getViewBandwidth();
|
||||
float viewBottom = view - (viewBW / 2.0f);
|
||||
float viewTop = view + (viewBW / 2.0f);
|
||||
|
||||
float wholeFreq = wtf.getCenterFrequency();
|
||||
float BW = wtf.getBandwidth();
|
||||
float wholeFreq = gui::waterfall.getCenterFrequency();
|
||||
float BW = gui::waterfall.getBandwidth();
|
||||
float bottom = -(BW / 2.0f);
|
||||
float top = (BW / 2.0f);
|
||||
|
||||
// VFO still fints in the view
|
||||
if (vfoBottom > viewBottom && vfoTop < viewTop) {
|
||||
vfoman::setCenterOffset(wtf.selectedVFO, newVFO);
|
||||
sigpath::vfoManager.setCenterOffset(gui::waterfall.selectedVFO, newVFO);
|
||||
return;
|
||||
}
|
||||
|
||||
// VFO too low for current SDR tuning
|
||||
if (vfoBottom < bottom) {
|
||||
wtf.setViewOffset((BW / 2.0f) - (viewBW / 2.0f));
|
||||
gui::waterfall.setViewOffset((BW / 2.0f) - (viewBW / 2.0f));
|
||||
float newVFOOffset = (BW / 2.0f) - (vfoBW / 2.0f) - (viewBW / 10.0f);
|
||||
vfoman::setCenterOffset(wtf.selectedVFO, newVFOOffset);
|
||||
wtf.setCenterFrequency(freq - newVFOOffset);
|
||||
sigpath::vfoManager.setCenterOffset(gui::waterfall.selectedVFO, newVFOOffset);
|
||||
gui::waterfall.setCenterFrequency(freq - newVFOOffset);
|
||||
soapy.setFrequency(freq - newVFOOffset);
|
||||
return;
|
||||
}
|
||||
|
||||
// VFO too high for current SDR tuning
|
||||
if (vfoTop > top) {
|
||||
wtf.setViewOffset((viewBW / 2.0f) - (BW / 2.0f));
|
||||
gui::waterfall.setViewOffset((viewBW / 2.0f) - (BW / 2.0f));
|
||||
float newVFOOffset = (vfoBW / 2.0f) - (BW / 2.0f) + (viewBW / 10.0f);
|
||||
vfoman::setCenterOffset(wtf.selectedVFO, newVFOOffset);
|
||||
wtf.setCenterFrequency(freq - newVFOOffset);
|
||||
sigpath::vfoManager.setCenterOffset(gui::waterfall.selectedVFO, newVFOOffset);
|
||||
gui::waterfall.setCenterFrequency(freq - newVFOOffset);
|
||||
soapy.setFrequency(freq - newVFOOffset);
|
||||
return;
|
||||
}
|
||||
@ -349,15 +344,15 @@ void setVFO(float freq) {
|
||||
float newViewTop = newViewOff + (viewBW / 2.0f);
|
||||
|
||||
if (newViewBottom > bottom) {
|
||||
wtf.setViewOffset(newViewOff);
|
||||
vfoman::setCenterOffset(wtf.selectedVFO, newVFO);
|
||||
gui::waterfall.setViewOffset(newViewOff);
|
||||
sigpath::vfoManager.setCenterOffset(gui::waterfall.selectedVFO, newVFO);
|
||||
return;
|
||||
}
|
||||
|
||||
wtf.setViewOffset((BW / 2.0f) - (viewBW / 2.0f));
|
||||
gui::waterfall.setViewOffset((BW / 2.0f) - (viewBW / 2.0f));
|
||||
float newVFOOffset = (BW / 2.0f) - (vfoBW / 2.0f) - (viewBW / 10.0f);
|
||||
vfoman::setCenterOffset(wtf.selectedVFO, newVFOOffset);
|
||||
wtf.setCenterFrequency(freq - newVFOOffset);
|
||||
sigpath::vfoManager.setCenterOffset(gui::waterfall.selectedVFO, newVFOOffset);
|
||||
gui::waterfall.setCenterFrequency(freq - newVFOOffset);
|
||||
soapy.setFrequency(freq - newVFOOffset);
|
||||
}
|
||||
else {
|
||||
@ -366,15 +361,15 @@ void setVFO(float freq) {
|
||||
float newViewTop = newViewOff + (viewBW / 2.0f);
|
||||
|
||||
if (newViewTop < top) {
|
||||
wtf.setViewOffset(newViewOff);
|
||||
vfoman::setCenterOffset(wtf.selectedVFO, newVFO);
|
||||
gui::waterfall.setViewOffset(newViewOff);
|
||||
sigpath::vfoManager.setCenterOffset(gui::waterfall.selectedVFO, newVFO);
|
||||
return;
|
||||
}
|
||||
|
||||
wtf.setViewOffset((viewBW / 2.0f) - (BW / 2.0f));
|
||||
gui::waterfall.setViewOffset((viewBW / 2.0f) - (BW / 2.0f));
|
||||
float newVFOOffset = (vfoBW / 2.0f) - (BW / 2.0f) + (viewBW / 10.0f);
|
||||
vfoman::setCenterOffset(wtf.selectedVFO, newVFOOffset);
|
||||
wtf.setCenterFrequency(freq - newVFOOffset);
|
||||
sigpath::vfoManager.setCenterOffset(gui::waterfall.selectedVFO, newVFOOffset);
|
||||
gui::waterfall.setCenterFrequency(freq - newVFOOffset);
|
||||
soapy.setFrequency(freq - newVFOOffset);
|
||||
}
|
||||
}
|
||||
@ -382,61 +377,61 @@ void setVFO(float freq) {
|
||||
void drawWindow() {
|
||||
ImGui::Begin("Main", NULL, WINDOW_FLAGS);
|
||||
|
||||
ImGui::WaterfallVFO* vfo = wtf.vfos[wtf.selectedVFO];
|
||||
ImGui::WaterfallVFO* vfo = gui::waterfall.vfos[gui::waterfall.selectedVFO];
|
||||
|
||||
if (vfo->centerOffsetChanged) {
|
||||
fSel.setFrequency(wtf.getCenterFrequency() + vfo->generalOffset);
|
||||
fSel.frequencyChanged = false;
|
||||
config::config["frequency"] = fSel.frequency;
|
||||
gui::freqSelect.setFrequency(gui::waterfall.getCenterFrequency() + vfo->generalOffset);
|
||||
gui::freqSelect.frequencyChanged = false;
|
||||
config::config["frequency"] = gui::freqSelect.frequency;
|
||||
config::configModified = true;
|
||||
}
|
||||
|
||||
vfoman::updateFromWaterfall();
|
||||
sigpath::vfoManager.updateFromWaterfall(&gui::waterfall);
|
||||
|
||||
if (wtf.selectedVFOChanged) {
|
||||
wtf.selectedVFOChanged = false;
|
||||
fSel.setFrequency(vfo->generalOffset + wtf.getCenterFrequency());
|
||||
fSel.frequencyChanged = false;
|
||||
if (gui::waterfall.selectedVFOChanged) {
|
||||
gui::waterfall.selectedVFOChanged = false;
|
||||
gui::freqSelect.setFrequency(vfo->generalOffset + gui::waterfall.getCenterFrequency());
|
||||
gui::freqSelect.frequencyChanged = false;
|
||||
mod::broadcastEvent(mod::EVENT_SELECTED_VFO_CHANGED);
|
||||
audioStreamName = audio::getNameFromVFO(wtf.selectedVFO);
|
||||
audioStreamName = audio::getNameFromVFO(gui::waterfall.selectedVFO);
|
||||
if (audioStreamName != "") {
|
||||
volume = &audio::streams[audioStreamName]->volume;
|
||||
}
|
||||
config::config["frequency"] = fSel.frequency;
|
||||
config::config["frequency"] = gui::freqSelect.frequency;
|
||||
config::configModified = true;
|
||||
}
|
||||
|
||||
if (fSel.frequencyChanged) {
|
||||
fSel.frequencyChanged = false;
|
||||
setVFO(fSel.frequency);
|
||||
if (gui::freqSelect.frequencyChanged) {
|
||||
gui::freqSelect.frequencyChanged = false;
|
||||
setVFO(gui::freqSelect.frequency);
|
||||
vfo->centerOffsetChanged = false;
|
||||
vfo->lowerOffsetChanged = false;
|
||||
vfo->upperOffsetChanged = false;
|
||||
config::config["frequency"] = fSel.frequency;
|
||||
config::config["frequency"] = gui::freqSelect.frequency;
|
||||
config::configModified = true;
|
||||
}
|
||||
|
||||
if (wtf.centerFreqMoved) {
|
||||
wtf.centerFreqMoved = false;
|
||||
soapy.setFrequency(wtf.getCenterFrequency());
|
||||
fSel.setFrequency(wtf.getCenterFrequency() + vfo->generalOffset);
|
||||
config::config["frequency"] = fSel.frequency;
|
||||
if (gui::waterfall.centerFreqMoved) {
|
||||
gui::waterfall.centerFreqMoved = false;
|
||||
soapy.setFrequency(gui::waterfall.getCenterFrequency());
|
||||
gui::freqSelect.setFrequency(gui::waterfall.getCenterFrequency() + vfo->generalOffset);
|
||||
config::config["frequency"] = gui::freqSelect.frequency;
|
||||
config::configModified = true;
|
||||
}
|
||||
|
||||
if (dcbias.changed()) {
|
||||
sigPath.setDCBiasCorrection(dcbias.val);
|
||||
sigpath::signalPath.setDCBiasCorrection(dcbias.val);
|
||||
}
|
||||
|
||||
if (bandplanId.changed() && bandPlanEnabled.val) {
|
||||
wtf.bandplan = &bandplan::bandplans[bandplan::bandplanNames[bandplanId.val]];
|
||||
gui::waterfall.bandplan = &bandplan::bandplans[bandplan::bandplanNames[bandplanId.val]];
|
||||
}
|
||||
|
||||
if (bandPlanEnabled.changed()) {
|
||||
wtf.bandplan = bandPlanEnabled.val ? &bandplan::bandplans[bandplan::bandplanNames[bandplanId.val]] : NULL;
|
||||
gui::waterfall.bandplan = bandPlanEnabled.val ? &bandplan::bandplans[bandplan::bandplanNames[bandplanId.val]] : NULL;
|
||||
}
|
||||
|
||||
int _fftHeight = wtf.getFFTHeight();
|
||||
int _fftHeight = gui::waterfall.getFFTHeight();
|
||||
if (fftHeight != _fftHeight) {
|
||||
fftHeight = _fftHeight;
|
||||
config::config["fftHeight"] = fftHeight;
|
||||
@ -472,7 +467,7 @@ void drawWindow() {
|
||||
else {
|
||||
if (ImGui::ImageButton(icons::PLAY, ImVec2(40, 40), ImVec2(0, 0), ImVec2(1, 1), 0) && soapy.devList.size() > 0) {
|
||||
soapy.start();
|
||||
soapy.setFrequency(wtf.getCenterFrequency());
|
||||
soapy.setFrequency(gui::waterfall.getCenterFrequency());
|
||||
playing = true;
|
||||
}
|
||||
}
|
||||
@ -494,7 +489,7 @@ void drawWindow() {
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
fSel.draw();
|
||||
gui::freqSelect.draw();
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
@ -564,9 +559,9 @@ void drawWindow() {
|
||||
srId = 0;
|
||||
sampleRate = soapy.getSampleRate();
|
||||
bw.val = sampleRate;
|
||||
wtf.setBandwidth(sampleRate);
|
||||
wtf.setViewBandwidth(sampleRate);
|
||||
sigPath.setSampleRate(sampleRate);
|
||||
gui::waterfall.setBandwidth(sampleRate);
|
||||
gui::waterfall.setViewBandwidth(sampleRate);
|
||||
sigpath::signalPath.setSampleRate(sampleRate);
|
||||
|
||||
if (soapy.gainList.size() >= 0) {
|
||||
delete[] uiGains;
|
||||
@ -576,7 +571,7 @@ void drawWindow() {
|
||||
}
|
||||
}
|
||||
}
|
||||
setVFO(fSel.frequency);
|
||||
setVFO(gui::freqSelect.frequency);
|
||||
config::config["source"] = sourceName;
|
||||
config::configModified = true;
|
||||
}
|
||||
@ -586,9 +581,9 @@ void drawWindow() {
|
||||
spdlog::info("Changed sample rate: {0}", srId);
|
||||
sampleRate = soapy.sampleRates[srId];
|
||||
soapy.setSampleRate(sampleRate);
|
||||
wtf.setBandwidth(sampleRate);
|
||||
wtf.setViewBandwidth(sampleRate);
|
||||
sigPath.setSampleRate(sampleRate);
|
||||
gui::waterfall.setBandwidth(sampleRate);
|
||||
gui::waterfall.setViewBandwidth(sampleRate);
|
||||
sigpath::signalPath.setSampleRate(sampleRate);
|
||||
bw.val = sampleRate;
|
||||
|
||||
if (!config::config["sourceSettings"].contains(sourceName)) {
|
||||
@ -739,7 +734,7 @@ void drawWindow() {
|
||||
|
||||
if (ImGui::CollapsingHeader("Display", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||
if (ImGui::Checkbox("Show waterfall", &showWaterfall)) {
|
||||
showWaterfall ? wtf.showWaterfall() : wtf.hideWaterfall();
|
||||
showWaterfall ? gui::waterfall.showWaterfall() : gui::waterfall.hideWaterfall();
|
||||
}
|
||||
ImGui::Spacing();
|
||||
}
|
||||
@ -747,7 +742,7 @@ void drawWindow() {
|
||||
if(ImGui::CollapsingHeader("Debug")) {
|
||||
ImGui::Text("Frame time: %.3f ms/frame", 1000.0f / ImGui::GetIO().Framerate);
|
||||
ImGui::Text("Framerate: %.1f FPS", ImGui::GetIO().Framerate);
|
||||
ImGui::Text("Center Frequency: %.0f Hz", wtf.getCenterFrequency());
|
||||
ImGui::Text("Center Frequency: %.0f Hz", gui::waterfall.getCenterFrequency());
|
||||
ImGui::Text("Source name: %s", sourceName.c_str());
|
||||
ImGui::Spacing();
|
||||
}
|
||||
@ -769,7 +764,7 @@ void drawWindow() {
|
||||
|
||||
ImGui::BeginChild("Waterfall");
|
||||
|
||||
wtf.draw();
|
||||
gui::waterfall.draw();
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
@ -807,14 +802,14 @@ void drawWindow() {
|
||||
ImGui::EndChild();
|
||||
|
||||
if (bw.changed()) {
|
||||
wtf.setViewBandwidth(bw.val);
|
||||
wtf.setViewOffset(vfo->centerOffset);
|
||||
gui::waterfall.setViewBandwidth(bw.val);
|
||||
gui::waterfall.setViewOffset(vfo->centerOffset);
|
||||
}
|
||||
|
||||
wtf.setFFTMin(fftMin);
|
||||
wtf.setFFTMax(fftMax);
|
||||
wtf.setWaterfallMin(fftMin);
|
||||
wtf.setWaterfallMax(fftMax);
|
||||
gui::waterfall.setFFTMin(fftMin);
|
||||
gui::waterfall.setFFTMax(fftMax);
|
||||
gui::waterfall.setWaterfallMin(fftMin);
|
||||
gui::waterfall.setWaterfallMax(fftMax);
|
||||
|
||||
|
||||
ImGui::End();
|
@ -13,19 +13,20 @@
|
||||
#include <complex>
|
||||
#include <dsp/source.h>
|
||||
#include <dsp/math.h>
|
||||
#include <waterfall.h>
|
||||
#include <frequency_select.h>
|
||||
#include <gui/waterfall.h>
|
||||
#include <gui/frequency_select.h>
|
||||
#include <fftw3.h>
|
||||
#include <signal_path.h>
|
||||
#include <signal_path/dsp.h>
|
||||
#include <io/soapy.h>
|
||||
#include <icons.h>
|
||||
#include <bandplan.h>
|
||||
#include <gui/icons.h>
|
||||
#include <gui/bandplan.h>
|
||||
#include <watcher.h>
|
||||
#include <module.h>
|
||||
#include <vfo_manager.h>
|
||||
#include <audio.h>
|
||||
#include <style.h>
|
||||
#include <signal_path/vfo_manager.h>
|
||||
#include <signal_path/audio.h>
|
||||
#include <gui/style.h>
|
||||
#include <config.h>
|
||||
#include <signal_path/signal_path.h>
|
||||
|
||||
#define WINDOW_FLAGS ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoBackground
|
||||
|
24
core/src/gui/menu.cpp
Normal file
24
core/src/gui/menu.cpp
Normal file
@ -0,0 +1,24 @@
|
||||
#include <gui/menu.h>
|
||||
|
||||
Menu::Menu() {
|
||||
|
||||
}
|
||||
|
||||
void Menu::registerEntry(std::string name, void (*drawHandler)(void* ctx), void* ctx) {
|
||||
MenuItem_t item;
|
||||
item.drawHandler = drawHandler;
|
||||
item.ctx = ctx;
|
||||
items[name] = item;
|
||||
}
|
||||
|
||||
void Menu::removeEntry(std::string name) {
|
||||
items.erase(name);
|
||||
}
|
||||
|
||||
void Menu::draw() {
|
||||
MenuItem_t item;
|
||||
for (std::string name : order) {
|
||||
item = items[name];
|
||||
item.drawHandler(item.ctx);
|
||||
}
|
||||
}
|
23
core/src/gui/menu.h
Normal file
23
core/src/gui/menu.h
Normal file
@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
class Menu {
|
||||
public:
|
||||
Menu();
|
||||
|
||||
struct MenuItem_t {
|
||||
void (*drawHandler)(void* ctx);
|
||||
void* ctx;
|
||||
};
|
||||
|
||||
void registerEntry(std::string name, void (*drawHandler)(void* ctx), void* ctx = NULL);
|
||||
void removeEntry(std::string name);
|
||||
void draw();
|
||||
|
||||
std::vector<std::string> order;
|
||||
|
||||
private:
|
||||
std::map<std::string, MenuItem_t> items;
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
#include <style.h>
|
||||
#include <gui/style.h>
|
||||
|
||||
namespace style {
|
||||
void setDefaultStyle() {
|
@ -1,4 +1,4 @@
|
||||
#include <waterfall.h>
|
||||
#include <gui/waterfall.h>
|
||||
|
||||
float COLOR_MAP[][3] = {
|
||||
{0x00, 0x00, 0x20},
|
||||
@ -650,6 +650,7 @@ namespace ImGui {
|
||||
}
|
||||
|
||||
void WaterfallVFO::setOffset(float offset) {
|
||||
printf("WaterfallVFO::SetOffset: %p\n", this);
|
||||
generalOffset = offset;
|
||||
if (reference == REF_CENTER) {
|
||||
centerOffset = offset;
|
@ -5,7 +5,7 @@
|
||||
#include <mutex>
|
||||
#include <GL/glew.h>
|
||||
#include <imutils.h>
|
||||
#include <bandplan.h>
|
||||
#include <gui/bandplan.h>
|
||||
#include <algorithm>
|
||||
|
||||
#define WATERFALL_RESOLUTION 1000000
|
@ -1,7 +1,7 @@
|
||||
#include <module.h>
|
||||
#include <vfo_manager.h>
|
||||
#include <main_window.h>
|
||||
#include <audio.h>
|
||||
#include <signal_path/vfo_manager.h>
|
||||
#include <gui/main_window.h>
|
||||
#include <signal_path/audio.h>
|
||||
|
||||
namespace mod {
|
||||
API_t API;
|
||||
@ -16,16 +16,6 @@ namespace mod {
|
||||
void initAPI(ImGui::WaterFall* wtf) {
|
||||
_wtf = wtf;
|
||||
|
||||
// VFO Manager
|
||||
API.registerVFO = vfoman::create;
|
||||
API.setVFOOffset = vfoman::setOffset;
|
||||
API.setVFOCenterOffset = vfoman::setCenterOffset;
|
||||
API.setVFOBandwidth = vfoman::setBandwidth;
|
||||
API.setVFOSampleRate = vfoman::setSampleRate;
|
||||
API.getVFOOutputBlockSize = vfoman::getOutputBlockSize;
|
||||
API.setVFOReference = vfoman::setReference;
|
||||
API.removeVFO = vfoman::remove;
|
||||
|
||||
// GUI
|
||||
API.getSelectedVFOName = api_getSelectedVFOName;
|
||||
API.bindVolumeVariable = bindVolumeVariable;
|
||||
|
@ -7,16 +7,25 @@
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <dsp/types.h>
|
||||
#include <dsp/stream.h>
|
||||
#include <waterfall.h>
|
||||
#include <gui/waterfall.h>
|
||||
#include <json.hpp>
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef SDRPP_IS_CORE
|
||||
#define SDRPP_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#define SDRPP_EXPORT extern "C" __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define SDRPP_EXPORT /**/
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#define MOD_EXPORT extern "C" \
|
||||
__declspec(dllexport)
|
||||
#define MOD_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#define MOD_EXPORT extern "C"
|
||||
#define MOD_EXPORT extern "C"
|
||||
#endif
|
||||
|
||||
namespace mod {
|
||||
|
@ -1,4 +1,4 @@
|
||||
#include <audio.h>
|
||||
#include <signal_path/audio.h>
|
||||
|
||||
namespace audio {
|
||||
std::map<std::string, AudioStream_t*> streams;
|
@ -1,4 +1,4 @@
|
||||
#include <signal_path.h>
|
||||
#include <signal_path/dsp.h>
|
||||
|
||||
SignalPath::SignalPath() {
|
||||
|
6
core/src/signal_path/signal_path.cpp
Normal file
6
core/src/signal_path/signal_path.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
#include <signal_path/signal_path.h>
|
||||
|
||||
namespace sigpath {
|
||||
SignalPath signalPath;
|
||||
VFOManager vfoManager;
|
||||
};
|
9
core/src/signal_path/signal_path.h
Normal file
9
core/src/signal_path/signal_path.h
Normal file
@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#include <signal_path/dsp.h>
|
||||
#include <signal_path/vfo_manager.h>
|
||||
#include <module.h>
|
||||
|
||||
namespace sigpath {
|
||||
SDRPP_EXPORT SignalPath signalPath;
|
||||
SDRPP_EXPORT VFOManager vfoManager;
|
||||
};
|
128
core/src/signal_path/vfo_manager.cpp
Normal file
128
core/src/signal_path/vfo_manager.cpp
Normal file
@ -0,0 +1,128 @@
|
||||
#include <signal_path/vfo_manager.h>
|
||||
#include <signal_path/signal_path.h>
|
||||
|
||||
VFOManager::VFO::VFO(std::string name, int reference, float offset, float bandwidth, float sampleRate, int blockSize) {
|
||||
this->name = name;
|
||||
dspVFO = sigpath::signalPath.addVFO(name, sampleRate, bandwidth, offset);
|
||||
wtfVFO = new ImGui::WaterfallVFO;
|
||||
wtfVFO->setReference(reference);
|
||||
wtfVFO->setBandwidth(bandwidth);
|
||||
wtfVFO->setOffset(offset);
|
||||
output = dspVFO->output;
|
||||
printf("Created VFO: %p", wtfVFO);
|
||||
gui::waterfall.vfos[name] = wtfVFO;
|
||||
}
|
||||
|
||||
VFOManager::VFO::~VFO() {
|
||||
gui::waterfall.vfos.erase(name);
|
||||
sigpath::signalPath.removeVFO(name);
|
||||
delete wtfVFO;
|
||||
}
|
||||
|
||||
void VFOManager::VFO::setOffset(float offset) {
|
||||
wtfVFO->setOffset(offset);
|
||||
dspVFO->setOffset(wtfVFO->centerOffset);
|
||||
}
|
||||
|
||||
void VFOManager::VFO::setCenterOffset(float offset) {
|
||||
wtfVFO->setCenterOffset(offset);
|
||||
dspVFO->setOffset(offset);
|
||||
}
|
||||
|
||||
void VFOManager::VFO::setBandwidth(float bandwidth) {
|
||||
wtfVFO->setBandwidth(bandwidth);
|
||||
dspVFO->setBandwidth(bandwidth);
|
||||
}
|
||||
|
||||
void VFOManager::VFO::setSampleRate(float sampleRate, float bandwidth) {
|
||||
dspVFO->setOutputSampleRate(sampleRate, bandwidth);
|
||||
wtfVFO->setBandwidth(bandwidth);
|
||||
}
|
||||
|
||||
void VFOManager::VFO::setReference(int ref) {
|
||||
wtfVFO->setReference(ref);
|
||||
}
|
||||
|
||||
int VFOManager::VFO::getOutputBlockSize() {
|
||||
return dspVFO->getOutputBlockSize();
|
||||
}
|
||||
|
||||
|
||||
VFOManager::VFOManager() {
|
||||
|
||||
}
|
||||
|
||||
VFOManager::VFO* VFOManager::createVFO(std::string name, int reference, float offset, float bandwidth, float sampleRate, int blockSize) {
|
||||
if (vfos.find(name) != vfos.end() || name == "") {
|
||||
return NULL;
|
||||
}
|
||||
VFOManager::VFO* vfo = new VFO(name, reference, offset, bandwidth, sampleRate, blockSize);
|
||||
vfos[name] = vfo;
|
||||
return vfo;
|
||||
}
|
||||
|
||||
void VFOManager::deleteVFO(VFOManager::VFO* vfo) {
|
||||
std::string name = "";
|
||||
for (auto const& [_name, _vfo] : vfos) {
|
||||
if (_vfo == vfo) {
|
||||
name == _name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (name == "") {
|
||||
return;
|
||||
}
|
||||
vfos.erase(name);
|
||||
}
|
||||
|
||||
void VFOManager::setOffset(std::string name, float offset) {
|
||||
if (vfos.find(name) == vfos.end()) {
|
||||
return;
|
||||
}
|
||||
vfos[name]->setOffset(offset);
|
||||
}
|
||||
|
||||
void VFOManager::setCenterOffset(std::string name, float offset) {
|
||||
if (vfos.find(name) == vfos.end()) {
|
||||
return;
|
||||
}
|
||||
vfos[name]->setCenterOffset(offset);
|
||||
}
|
||||
|
||||
void VFOManager::setBandwidth(std::string name, float bandwidth) {
|
||||
if (vfos.find(name) == vfos.end()) {
|
||||
return;
|
||||
}
|
||||
vfos[name]->setBandwidth(bandwidth);
|
||||
}
|
||||
|
||||
void VFOManager::setSampleRate(std::string name, float sampleRate, float bandwidth) {
|
||||
if (vfos.find(name) == vfos.end()) {
|
||||
return;
|
||||
}
|
||||
vfos[name]->setSampleRate(sampleRate, bandwidth);
|
||||
}
|
||||
|
||||
void VFOManager::setReference(std::string name, int ref) {
|
||||
if (vfos.find(name) == vfos.end()) {
|
||||
return;
|
||||
}
|
||||
vfos[name]->setReference(ref);
|
||||
}
|
||||
|
||||
int VFOManager::getOutputBlockSize(std::string name) {
|
||||
if (vfos.find(name) == vfos.end()) {
|
||||
return -1;
|
||||
}
|
||||
return vfos[name]->getOutputBlockSize();
|
||||
}
|
||||
|
||||
void VFOManager::updateFromWaterfall(ImGui::WaterFall* wtf) {
|
||||
for (auto const& [name, vfo] : vfos) {
|
||||
if (vfo->wtfVFO->centerOffsetChanged) {
|
||||
spdlog::info("UH OH: Change!");
|
||||
vfo->wtfVFO->centerOffsetChanged = false;
|
||||
vfo->dspVFO->setOffset(vfo->wtfVFO->centerOffset);
|
||||
}
|
||||
}
|
||||
}
|
47
core/src/signal_path/vfo_manager.h
Normal file
47
core/src/signal_path/vfo_manager.h
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
#include <dsp/vfo.h>
|
||||
#include <gui/waterfall.h>
|
||||
#include <gui/gui.h>
|
||||
|
||||
class VFOManager {
|
||||
public:
|
||||
VFOManager();
|
||||
|
||||
class VFO {
|
||||
public:
|
||||
VFO(std::string name, int reference, float offset, float bandwidth, float sampleRate, int blockSize);
|
||||
~VFO();
|
||||
|
||||
void setOffset(float offset);
|
||||
void setCenterOffset(float offset);
|
||||
void setBandwidth(float bandwidth);
|
||||
void setSampleRate(float sampleRate, float bandwidth);
|
||||
void setReference(int ref);
|
||||
int getOutputBlockSize();
|
||||
|
||||
dsp::stream<dsp::complex_t>* output;
|
||||
|
||||
friend class VFOManager;
|
||||
|
||||
private:
|
||||
std::string name;
|
||||
dsp::VFO* dspVFO;
|
||||
ImGui::WaterfallVFO* wtfVFO;
|
||||
|
||||
};
|
||||
|
||||
VFOManager::VFO* createVFO(std::string name, int reference, float offset, float bandwidth, float sampleRate, int blockSize);
|
||||
void deleteVFO(VFOManager::VFO* vfo);
|
||||
|
||||
void setOffset(std::string name, float offset);
|
||||
void setCenterOffset(std::string name, float offset);
|
||||
void setBandwidth(std::string name, float bandwidth);
|
||||
void setSampleRate(std::string name, float sampleRate, float bandwidth);
|
||||
void setReference(std::string name, int ref);
|
||||
int getOutputBlockSize(std::string name);
|
||||
|
||||
void updateFromWaterfall(ImGui::WaterFall* wtf);
|
||||
|
||||
private:
|
||||
std::map<std::string, VFO*> vfos;
|
||||
};
|
@ -1,99 +0,0 @@
|
||||
#include <vfo_manager.h>
|
||||
|
||||
namespace vfoman {
|
||||
std::map<std::string, VFO_t> vfos;
|
||||
ImGui::WaterFall* _wtf;
|
||||
SignalPath* _sigPath;
|
||||
|
||||
void init(ImGui::WaterFall* wtf, SignalPath* sigPath) {
|
||||
_wtf = wtf;
|
||||
_sigPath = sigPath;
|
||||
}
|
||||
|
||||
dsp::stream<dsp::complex_t>* create(std::string name, int reference, float offset, float bandwidth, float sampleRate, int blockSize) {
|
||||
if (vfos.find(name) != vfos.end()) {
|
||||
spdlog::warn("Tried to add VFO with an already existing name: {0}", name);
|
||||
return NULL;
|
||||
}
|
||||
spdlog::info("Creating new VFO '{0}'", name);
|
||||
VFO_t vfo;
|
||||
vfo.dspVFO = _sigPath->addVFO(name, sampleRate, bandwidth, offset);
|
||||
vfo.wtfVFO = new ImGui::WaterfallVFO;
|
||||
vfo.wtfVFO->setReference(reference);
|
||||
vfo.wtfVFO->setBandwidth(bandwidth);
|
||||
vfo.wtfVFO->setOffset(offset);
|
||||
_wtf->vfos[name] = vfo.wtfVFO;
|
||||
vfos[name] = vfo;
|
||||
return vfo.dspVFO->output;
|
||||
}
|
||||
|
||||
void setOffset(std::string name, float offset) {
|
||||
if (vfos.find(name) == vfos.end()) {
|
||||
return;
|
||||
}
|
||||
VFO_t vfo = vfos[name];
|
||||
vfo.wtfVFO->setOffset(offset);
|
||||
vfo.dspVFO->setOffset(vfo.wtfVFO->centerOffset);
|
||||
}
|
||||
|
||||
void setCenterOffset(std::string name, float offset) {
|
||||
if (vfos.find(name) == vfos.end()) {
|
||||
return;
|
||||
}
|
||||
VFO_t vfo = vfos[name];
|
||||
vfo.wtfVFO->setCenterOffset(offset);
|
||||
vfo.dspVFO->setOffset(offset);
|
||||
}
|
||||
|
||||
void setBandwidth(std::string name, float bandwidth) {
|
||||
if (vfos.find(name) == vfos.end()) {
|
||||
return;
|
||||
}
|
||||
VFO_t vfo = vfos[name];
|
||||
vfo.wtfVFO->setBandwidth(bandwidth);
|
||||
vfo.dspVFO->setBandwidth(bandwidth);
|
||||
}
|
||||
|
||||
void setSampleRate(std::string name, float sampleRate, float bandwidth) {
|
||||
if (vfos.find(name) == vfos.end()) {
|
||||
return;
|
||||
}
|
||||
VFO_t vfo = vfos[name];
|
||||
vfo.dspVFO->setOutputSampleRate(sampleRate, bandwidth);
|
||||
vfo.wtfVFO->setBandwidth(bandwidth);
|
||||
}
|
||||
|
||||
void setReference(std::string name, int ref){
|
||||
if (vfos.find(name) == vfos.end()) {
|
||||
return;
|
||||
}
|
||||
vfos[name].wtfVFO->setReference(ref);
|
||||
}
|
||||
|
||||
int getOutputBlockSize(std::string name) {
|
||||
if (vfos.find(name) == vfos.end()) {
|
||||
return -1;
|
||||
}
|
||||
return vfos[name].dspVFO->getOutputBlockSize();
|
||||
}
|
||||
|
||||
void remove(std::string name) {
|
||||
if (vfos.find(name) == vfos.end()) {
|
||||
return;
|
||||
}
|
||||
VFO_t vfo = vfos[name];
|
||||
_wtf->vfos.erase(name);
|
||||
_sigPath->removeVFO(name);
|
||||
delete vfo.wtfVFO;
|
||||
vfos.erase(name);
|
||||
}
|
||||
|
||||
void updateFromWaterfall() {
|
||||
for (auto const& [name, vfo] : vfos) {
|
||||
if (vfo.wtfVFO->centerOffsetChanged) {
|
||||
vfo.wtfVFO->centerOffsetChanged = false;
|
||||
vfo.dspVFO->setOffset(vfo.wtfVFO->centerOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
@ -1,24 +0,0 @@
|
||||
#pragma once
|
||||
#include <dsp/vfo.h>
|
||||
#include <waterfall.h>
|
||||
#include <signal_path.h>
|
||||
|
||||
namespace vfoman {
|
||||
struct VFO_t {
|
||||
dsp::VFO* dspVFO;
|
||||
ImGui::WaterfallVFO* wtfVFO;
|
||||
};
|
||||
|
||||
void init(ImGui::WaterFall* wtf, SignalPath* sigPath);
|
||||
|
||||
dsp::stream<dsp::complex_t>* create(std::string name, int reference, float offset, float bandwidth, float sampleRate, int blockSize);
|
||||
void setOffset(std::string name, float offset);
|
||||
void setCenterOffset(std::string name, float offset);
|
||||
void setBandwidth(std::string name, float bandwidth);
|
||||
void setSampleRate(std::string name, float sampleRate, float bandwidth);
|
||||
void setReference(std::string name, int ref);
|
||||
int getOutputBlockSize(std::string name);
|
||||
void remove(std::string name);
|
||||
|
||||
void updateFromWaterfall();
|
||||
};
|
@ -1,6 +1,13 @@
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
project(demo)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive -fsanitize=address -g")
|
||||
# set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive")
|
||||
endif (MSVC)
|
||||
|
||||
file(GLOB SRC "src/*.cpp")
|
||||
|
||||
add_library(demo SHARED ${SRC})
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <thread>
|
||||
#include <ctime>
|
||||
#include <stdio.h>
|
||||
#include <style.h>
|
||||
#include <gui/style.h>
|
||||
|
||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||
|
||||
|
@ -3,53 +3,14 @@ project(radio)
|
||||
|
||||
if (MSVC)
|
||||
set(CMAKE_CXX_FLAGS "-O2 /std:c++17")
|
||||
link_directories(radio "C:/Program Files/PothosSDR/lib/")
|
||||
include_directories(radio "C:/Program Files/PothosSDR/include/volk/")
|
||||
include_directories(radio "C:/Program Files/PothosSDR/include/")
|
||||
else()
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fsanitize=address -g")
|
||||
include_directories(radio "/usr/include/volk")
|
||||
link_libraries(pthread)
|
||||
link_libraries(GL)
|
||||
link_libraries(GLEW)
|
||||
link_libraries(glfw)
|
||||
link_libraries(fftw3)
|
||||
link_libraries(fftw3f)
|
||||
link_libraries(portaudio)
|
||||
link_libraries(X11)
|
||||
link_libraries(Xxf86vm)
|
||||
set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive -fsanitize=address -g")
|
||||
# set(CMAKE_CXX_FLAGS "-O3 -std=c++17 -fpermissive")
|
||||
endif (MSVC)
|
||||
|
||||
link_libraries(volk)
|
||||
link_libraries(SoapySDR)
|
||||
|
||||
# Main code
|
||||
include_directories(radio "src/")
|
||||
include_directories(radio "../core/src/")
|
||||
include_directories(radio "../core/src/imgui")
|
||||
file(GLOB SRC "src/*.cpp")
|
||||
file(GLOB IMGUI "../core/src/imgui/*.cpp")
|
||||
add_library(radio SHARED ${SRC} ${IMGUI})
|
||||
set_target_properties(radio PROPERTIES PREFIX "")
|
||||
|
||||
if (MSVC)
|
||||
# Glew
|
||||
find_package(GLEW REQUIRED)
|
||||
target_link_libraries(radio PRIVATE GLEW::GLEW)
|
||||
include_directories("src/")
|
||||
|
||||
# GLFW3
|
||||
find_package(glfw3 CONFIG REQUIRED)
|
||||
target_link_libraries(radio PRIVATE glfw)
|
||||
|
||||
# FFTW3
|
||||
find_package(FFTW3 CONFIG REQUIRED)
|
||||
target_link_libraries(radio PRIVATE FFTW3::fftw3)
|
||||
find_package(FFTW3f CONFIG REQUIRED)
|
||||
target_link_libraries(radio PRIVATE FFTW3::fftw3f)
|
||||
|
||||
# PortAudio
|
||||
find_package(portaudio CONFIG REQUIRED)
|
||||
target_link_libraries(radio PRIVATE portaudio portaudio_static)
|
||||
endif (MSVC)
|
||||
|
||||
# cmake .. "-DCMAKE_TOOLCHAIN_FILE=C:/Users/Alex/vcpkg/scripts/buildsystems/vcpkg.cmake" -G "Visual Studio 15 2017 Win64"
|
||||
add_library(radio SHARED ${SRC})
|
||||
target_link_libraries(radio PRIVATE sdrpp_core)
|
@ -25,7 +25,7 @@ MOD_EXPORT void* _INIT_(mod::API_t* _API, ImGuiContext* imctx, std::string _name
|
||||
ctx->bandWidth = 200000;
|
||||
ctx->bandWidthMin = 100000;
|
||||
ctx->bandWidthMax = 200000;
|
||||
ctx->sigPath.init(_name, 200000, 1000, API->registerVFO(_name, mod::API_t::REF_CENTER, 0, 200000, 200000, 1000));
|
||||
ctx->sigPath.init(_name, 200000, 1000);
|
||||
ctx->sigPath.start();
|
||||
ImGui::SetCurrentContext(imctx);
|
||||
return ctx;
|
||||
@ -49,7 +49,6 @@ MOD_EXPORT void _DRAW_MENU_(RadioContext_t* ctx) {
|
||||
ctx->bandWidthMin = 8000;
|
||||
ctx->bandWidthMax = 16000;
|
||||
ctx->sigPath.setDemodulator(SigPath::DEMOD_NFM, ctx->bandWidth);
|
||||
API->setVFOReference(ctx->name, mod::API_t::REF_CENTER);
|
||||
}
|
||||
if (ImGui::RadioButton(CONCAT("WFM##_", ctx->name), ctx->demod == 1) && ctx->demod != 1) {
|
||||
ctx->demod = 1;
|
||||
@ -57,7 +56,6 @@ MOD_EXPORT void _DRAW_MENU_(RadioContext_t* ctx) {
|
||||
ctx->bandWidthMin = 100000;
|
||||
ctx->bandWidthMax = 200000;
|
||||
ctx->sigPath.setDemodulator(SigPath::DEMOD_FM, ctx->bandWidth);
|
||||
API->setVFOReference(ctx->name, mod::API_t::REF_CENTER);
|
||||
}
|
||||
ImGui::NextColumn();
|
||||
if (ImGui::RadioButton(CONCAT("AM##_", ctx->name), ctx->demod == 2) && ctx->demod != 2) {
|
||||
@ -66,7 +64,6 @@ MOD_EXPORT void _DRAW_MENU_(RadioContext_t* ctx) {
|
||||
ctx->bandWidthMin = 6250;
|
||||
ctx->bandWidthMax = 12500;
|
||||
ctx->sigPath.setDemodulator(SigPath::DEMOD_AM, ctx->bandWidth);
|
||||
API->setVFOReference(ctx->name, mod::API_t::REF_CENTER);
|
||||
}
|
||||
if (ImGui::RadioButton(CONCAT("DSB##_", ctx->name), ctx->demod == 3) && ctx->demod != 3) {
|
||||
ctx->demod = 3;
|
||||
@ -74,7 +71,6 @@ MOD_EXPORT void _DRAW_MENU_(RadioContext_t* ctx) {
|
||||
ctx->bandWidthMin = 3000;
|
||||
ctx->bandWidthMax = 6000;
|
||||
ctx->sigPath.setDemodulator(SigPath::DEMOD_DSB, ctx->bandWidth);
|
||||
API->setVFOReference(ctx->name, mod::API_t::REF_CENTER);
|
||||
}
|
||||
ImGui::NextColumn();
|
||||
if (ImGui::RadioButton(CONCAT("USB##_", ctx->name), ctx->demod == 4) && ctx->demod != 4) {
|
||||
@ -83,7 +79,6 @@ MOD_EXPORT void _DRAW_MENU_(RadioContext_t* ctx) {
|
||||
ctx->bandWidthMin = 1500;
|
||||
ctx->bandWidthMax = 3000;
|
||||
ctx->sigPath.setDemodulator(SigPath::DEMOD_USB, ctx->bandWidth);
|
||||
API->setVFOReference(ctx->name, mod::API_t::REF_LOWER);
|
||||
}
|
||||
if (ImGui::RadioButton(CONCAT("CW##_", ctx->name), ctx->demod == 5) && ctx->demod != 5) { ctx->demod = 5; };
|
||||
ImGui::NextColumn();
|
||||
@ -93,7 +88,6 @@ MOD_EXPORT void _DRAW_MENU_(RadioContext_t* ctx) {
|
||||
ctx->bandWidthMin = 1500;
|
||||
ctx->bandWidthMax = 3000;
|
||||
ctx->sigPath.setDemodulator(SigPath::DEMOD_LSB, ctx->bandWidth);
|
||||
API->setVFOReference(ctx->name, mod::API_t::REF_UPPER);
|
||||
}
|
||||
if (ImGui::RadioButton(CONCAT("RAW##_", ctx->name), ctx->demod == 7) && ctx->demod != 7) {
|
||||
ctx->demod = 7;
|
||||
@ -101,7 +95,6 @@ MOD_EXPORT void _DRAW_MENU_(RadioContext_t* ctx) {
|
||||
ctx->bandWidthMin = 3000;
|
||||
ctx->bandWidthMax = 10000;
|
||||
ctx->sigPath.setDemodulator(SigPath::DEMOD_RAW, ctx->bandWidth);
|
||||
API->setVFOReference(ctx->name, mod::API_t::REF_CENTER);
|
||||
};
|
||||
ImGui::Columns(1, CONCAT("EndRadioModeColumns##_", ctx->name), false);
|
||||
|
||||
|
@ -18,11 +18,13 @@ int SigPath::sampleRateChangeHandler(void* ctx, float sampleRate) {
|
||||
return _this->audioResamp.getOutputBlockSize();
|
||||
}
|
||||
|
||||
void SigPath::init(std::string vfoName, uint64_t sampleRate, int blockSize, dsp::stream<dsp::complex_t>* input) {
|
||||
void SigPath::init(std::string vfoName, uint64_t sampleRate, int blockSize) {
|
||||
this->sampleRate = sampleRate;
|
||||
this->blockSize = blockSize;
|
||||
this->vfoName = vfoName;
|
||||
|
||||
vfo = sigpath::vfoManager.createVFO(vfoName, mod::API_t::REF_CENTER, 0, 200000, 200000, 1000);
|
||||
|
||||
_demod = DEMOD_FM;
|
||||
_deemp = DEEMP_50US;
|
||||
bandwidth = 200000;
|
||||
@ -31,10 +33,10 @@ void SigPath::init(std::string vfoName, uint64_t sampleRate, int blockSize, dsp:
|
||||
// TODO: ajust deemphasis for different output sample rates
|
||||
// TODO: Add a mono to stereo for different modes
|
||||
|
||||
demod.init(input, 100000, 200000, 800);
|
||||
amDemod.init(input, 50);
|
||||
ssbDemod.init(input, 6000, 3000, 22);
|
||||
cpx2stereo.init(input, 22);
|
||||
demod.init(vfo->output, 100000, 200000, 800);
|
||||
amDemod.init(vfo->output, 50);
|
||||
ssbDemod.init(vfo->output, 6000, 3000, 22);
|
||||
cpx2stereo.init(vfo->output, 22);
|
||||
|
||||
audioResamp.init(&demod.output, 200000, 48000, 800);
|
||||
deemp.init(&audioResamp.output, 800, 50e-6, 48000);
|
||||
@ -91,72 +93,79 @@ void SigPath::setDemodulator(int demId, float bandWidth) {
|
||||
// Set input of the audio resampler
|
||||
// TODO: Set bandwidth from argument
|
||||
if (demId == DEMOD_FM) {
|
||||
API->setVFOSampleRate(vfoName, 200000, bandwidth);
|
||||
demod.setBlockSize(API->getVFOOutputBlockSize(vfoName));
|
||||
vfo->setSampleRate(200000, bandwidth);
|
||||
demod.setBlockSize(vfo->getOutputBlockSize());
|
||||
demod.setSampleRate(200000);
|
||||
demod.setDeviation(bandwidth / 2.0f);
|
||||
audioResamp.setInput(&demod.output);
|
||||
audioBw = std::min<float>(bandwidth, outputSampleRate / 2.0f);
|
||||
audioResamp.setInputSampleRate(200000, API->getVFOOutputBlockSize(vfoName), audioBw, audioBw);
|
||||
audioResamp.setInputSampleRate(200000, vfo->getOutputBlockSize(), audioBw, audioBw);
|
||||
deemp.bypass = (_deemp == DEEMP_NONE);
|
||||
vfo->setReference(mod::API_t::REF_CENTER);
|
||||
demod.start();
|
||||
}
|
||||
else if (demId == DEMOD_NFM) {
|
||||
API->setVFOSampleRate(vfoName, 16000, bandwidth);
|
||||
demod.setBlockSize(API->getVFOOutputBlockSize(vfoName));
|
||||
vfo->setSampleRate(16000, bandwidth);
|
||||
demod.setBlockSize(vfo->getOutputBlockSize());
|
||||
demod.setSampleRate(16000);
|
||||
demod.setDeviation(bandwidth / 2.0f);
|
||||
audioResamp.setInput(&demod.output);
|
||||
audioBw = std::min<float>(bandwidth, outputSampleRate / 2.0f);
|
||||
audioResamp.setInputSampleRate(16000, API->getVFOOutputBlockSize(vfoName), audioBw, audioBw);
|
||||
audioResamp.setInputSampleRate(16000, vfo->getOutputBlockSize(), audioBw, audioBw);
|
||||
deemp.bypass = true;
|
||||
vfo->setReference(mod::API_t::REF_CENTER);
|
||||
demod.start();
|
||||
}
|
||||
else if (demId == DEMOD_AM) {
|
||||
API->setVFOSampleRate(vfoName, 12500, bandwidth);
|
||||
amDemod.setBlockSize(API->getVFOOutputBlockSize(vfoName));
|
||||
vfo->setSampleRate(12500, bandwidth);
|
||||
amDemod.setBlockSize(vfo->getOutputBlockSize());
|
||||
audioResamp.setInput(&amDemod.output);
|
||||
audioBw = std::min<float>(bandwidth, outputSampleRate / 2.0f);
|
||||
audioResamp.setInputSampleRate(12500, API->getVFOOutputBlockSize(vfoName), audioBw, audioBw);
|
||||
audioResamp.setInputSampleRate(12500, vfo->getOutputBlockSize(), audioBw, audioBw);
|
||||
deemp.bypass = true;
|
||||
vfo->setReference(mod::API_t::REF_CENTER);
|
||||
amDemod.start();
|
||||
}
|
||||
else if (demId == DEMOD_USB) {
|
||||
API->setVFOSampleRate(vfoName, 6000, bandwidth);
|
||||
ssbDemod.setBlockSize(API->getVFOOutputBlockSize(vfoName));
|
||||
vfo->setSampleRate(6000, bandwidth);
|
||||
ssbDemod.setBlockSize(vfo->getOutputBlockSize());
|
||||
ssbDemod.setMode(dsp::SSBDemod::MODE_USB);
|
||||
audioResamp.setInput(&ssbDemod.output);
|
||||
audioBw = std::min<float>(bandwidth, outputSampleRate / 2.0f);
|
||||
audioResamp.setInputSampleRate(6000, API->getVFOOutputBlockSize(vfoName), audioBw, audioBw);
|
||||
audioResamp.setInputSampleRate(6000, vfo->getOutputBlockSize(), audioBw, audioBw);
|
||||
deemp.bypass = true;
|
||||
vfo->setReference(mod::API_t::REF_LOWER);
|
||||
ssbDemod.start();
|
||||
}
|
||||
else if (demId == DEMOD_LSB) {
|
||||
API->setVFOSampleRate(vfoName, 6000, bandwidth);
|
||||
ssbDemod.setBlockSize(API->getVFOOutputBlockSize(vfoName));
|
||||
vfo->setSampleRate(6000, bandwidth);
|
||||
ssbDemod.setBlockSize(vfo->getOutputBlockSize());
|
||||
ssbDemod.setMode(dsp::SSBDemod::MODE_LSB);
|
||||
audioResamp.setInput(&ssbDemod.output);
|
||||
audioBw = std::min<float>(bandwidth, outputSampleRate / 2.0f);
|
||||
audioResamp.setInputSampleRate(6000, API->getVFOOutputBlockSize(vfoName), audioBw, audioBw);
|
||||
audioResamp.setInputSampleRate(6000, vfo->getOutputBlockSize(), audioBw, audioBw);
|
||||
deemp.bypass = true;
|
||||
vfo->setReference(mod::API_t::REF_UPPER);
|
||||
ssbDemod.start();
|
||||
}
|
||||
else if (demId == DEMOD_DSB) {
|
||||
API->setVFOSampleRate(vfoName, 6000, bandwidth);
|
||||
ssbDemod.setBlockSize(API->getVFOOutputBlockSize(vfoName));
|
||||
vfo->setSampleRate(6000, bandwidth);
|
||||
ssbDemod.setBlockSize(vfo->getOutputBlockSize());
|
||||
ssbDemod.setMode(dsp::SSBDemod::MODE_DSB);
|
||||
audioResamp.setInput(&ssbDemod.output);
|
||||
audioBw = std::min<float>(bandwidth, outputSampleRate / 2.0f);
|
||||
audioResamp.setInputSampleRate(6000, API->getVFOOutputBlockSize(vfoName), audioBw, audioBw);
|
||||
audioResamp.setInputSampleRate(6000, vfo->getOutputBlockSize(), audioBw, audioBw);
|
||||
deemp.bypass = true;
|
||||
vfo->setReference(mod::API_t::REF_CENTER);
|
||||
ssbDemod.start();
|
||||
}
|
||||
else if (demId == DEMOD_RAW) {
|
||||
API->setVFOSampleRate(vfoName, 10000, bandwidth);
|
||||
cpx2stereo.setBlockSize(API->getVFOOutputBlockSize(vfoName));
|
||||
vfo->setSampleRate(10000, bandwidth);
|
||||
cpx2stereo.setBlockSize(vfo->getOutputBlockSize());
|
||||
//audioResamp.setInput(&cpx2stereo.output);
|
||||
audioBw = std::min<float>(bandwidth, outputSampleRate / 2.0f);
|
||||
audioResamp.setInputSampleRate(10000, API->getVFOOutputBlockSize(vfoName), audioBw, audioBw);
|
||||
audioResamp.setInputSampleRate(10000, vfo->getOutputBlockSize(), audioBw, audioBw);
|
||||
vfo->setReference(mod::API_t::REF_LOWER);
|
||||
cpx2stereo.start();
|
||||
}
|
||||
else {
|
||||
@ -192,7 +201,7 @@ void SigPath::setDeemphasis(int deemph) {
|
||||
|
||||
void SigPath::setBandwidth(float bandWidth) {
|
||||
bandwidth = bandWidth;
|
||||
API->setVFOBandwidth(vfoName, bandwidth);
|
||||
vfo->setBandwidth(bandwidth);
|
||||
if (_demod == DEMOD_FM) {
|
||||
demod.stop();
|
||||
demod.setDeviation(bandwidth / 2.0f);
|
||||
@ -231,7 +240,7 @@ void SigPath::setBandwidth(float bandWidth) {
|
||||
if (audioBw != _audioBw) {
|
||||
audioBw = _audioBw;
|
||||
audioResamp.stop();
|
||||
audioResamp.setInputSampleRate(6000, API->getVFOOutputBlockSize(vfoName), audioBw, audioBw);
|
||||
audioResamp.setInputSampleRate(6000, vfo->getOutputBlockSize(), audioBw, audioBw);
|
||||
audioResamp.start();
|
||||
}
|
||||
}
|
||||
|
@ -10,11 +10,12 @@
|
||||
#include <dsp/vfo.h>
|
||||
#include <io/audio.h>
|
||||
#include <module.h>
|
||||
#include <signal_path/signal_path.h>
|
||||
|
||||
class SigPath {
|
||||
public:
|
||||
SigPath();
|
||||
void init(std::string vfoName, uint64_t sampleRate, int blockSize, dsp::stream<dsp::complex_t>* input);
|
||||
void init(std::string vfoName, uint64_t sampleRate, int blockSize);
|
||||
void start();
|
||||
void setSampleRate(float sampleRate);
|
||||
void setVFOFrequency(uint64_t frequency);
|
||||
@ -46,6 +47,8 @@ public:
|
||||
|
||||
private:
|
||||
static int sampleRateChangeHandler(void* ctx, float sampleRate);
|
||||
|
||||
VFOManager::VFO* vfo;
|
||||
|
||||
dsp::stream<dsp::complex_t> input;
|
||||
|
||||
|
@ -3,13 +3,13 @@
|
||||
"Radio": {
|
||||
"device": "Speakers (Realtek High Definiti",
|
||||
"sampleRate": 48000.0,
|
||||
"volume": 0.4032258093357086
|
||||
"volume": 0.6666666865348816
|
||||
}
|
||||
},
|
||||
"bandPlan": "General",
|
||||
"bandPlanEnabled": true,
|
||||
"fftHeight": 300,
|
||||
"frequency": 99000000,
|
||||
"frequency": 103200000,
|
||||
"max": 0.0,
|
||||
"maximized": false,
|
||||
"menuWidth": 300,
|
||||
|
Loading…
Reference in New Issue
Block a user