New stuff
This commit is contained in:
@@ -8,13 +8,16 @@
|
||||
#include <dsp/source.h>
|
||||
#include <dsp/math.h>
|
||||
#include <waterfall.h>
|
||||
#include <frequency_select.h>
|
||||
#include <fftw3.h>
|
||||
#include <signal_path.h>
|
||||
#include <io/soapy.h>
|
||||
#include <icons.h>
|
||||
|
||||
std::thread worker;
|
||||
std::mutex fft_mtx;
|
||||
ImGui::WaterFall wtf;
|
||||
FrequencySelect fSel;
|
||||
fftwf_complex *fft_in, *fft_out;
|
||||
fftwf_plan p;
|
||||
float* tempData;
|
||||
@@ -50,9 +53,12 @@ void fftHandler(dsp::complex_t* samples) {
|
||||
void windowInit() {
|
||||
int sampleRate = 8000000;
|
||||
wtf.setBandwidth(sampleRate);
|
||||
//wtf.range = 500000;
|
||||
wtf.setCenterFrequency(90500000);
|
||||
printf("fft taps: %d\n", fftTaps.size());
|
||||
wtf.setVFOBandwidth(200000);
|
||||
wtf.setVFOOffset(0);
|
||||
|
||||
fSel.init();
|
||||
fSel.setFrequency(90500000);
|
||||
|
||||
fft_in = (fftwf_complex*) fftw_malloc(sizeof(fftwf_complex) * fftSize);
|
||||
fft_out = (fftwf_complex*) fftw_malloc(sizeof(fftwf_complex) * fftSize);
|
||||
@@ -72,8 +78,8 @@ int _srId = -1;
|
||||
|
||||
bool showExample = false;
|
||||
|
||||
int freq = 90500;
|
||||
int _freq = 90500;
|
||||
long freq = 90500000;
|
||||
long _freq = 90500000;
|
||||
|
||||
int demod = 0;
|
||||
|
||||
@@ -90,19 +96,127 @@ float fftMin = -70.0f;
|
||||
float fftMax = 0.0f;
|
||||
|
||||
float offset = 0.0f;
|
||||
float lastOffset = -1.0f;
|
||||
float bw = 8000000.0f;
|
||||
float lastBW = -1.0f;
|
||||
|
||||
int sampleRate = 1000000;
|
||||
|
||||
bool playing = false;
|
||||
|
||||
void setVFO(float freq) {
|
||||
float currentOff = wtf.getVFOOfset();
|
||||
float currentTune = wtf.getCenterFrequency() + currentOff;
|
||||
float delta = freq - currentTune;
|
||||
|
||||
float newVFO = currentOff + delta;
|
||||
float vfoBW = wtf.getVFOBandwidth();
|
||||
float vfoBottom = newVFO - (vfoBW / 2.0f);
|
||||
float vfoTop = newVFO + (vfoBW / 2.0f);
|
||||
|
||||
float view = wtf.getViewOffset();
|
||||
float viewBW = wtf.getViewBandwidth();
|
||||
float viewBottom = view - (viewBW / 2.0f);
|
||||
float viewTop = view + (viewBW / 2.0f);
|
||||
|
||||
float wholeFreq = wtf.getCenterFrequency();
|
||||
float BW = wtf.getBandwidth();
|
||||
float bottom = -(BW / 2.0f);
|
||||
float top = (BW / 2.0f);
|
||||
|
||||
// VFO still fints in the view
|
||||
if (vfoBottom > viewBottom && vfoTop < viewTop) {
|
||||
sigPath.setVFOFrequency(newVFO);
|
||||
wtf.setVFOOffset(newVFO);
|
||||
return;
|
||||
}
|
||||
|
||||
// VFO too low for current SDR tuning
|
||||
if (vfoBottom < bottom) {
|
||||
wtf.setViewOffset((BW / 2.0f) - (viewBW / 2.0f));
|
||||
float newVFOOffset = (BW / 2.0f) - (vfoBW / 2.0f) - (viewBW / 10.0f);
|
||||
sigPath.setVFOFrequency(newVFOOffset);
|
||||
wtf.setVFOOffset(newVFOOffset);
|
||||
wtf.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));
|
||||
float newVFOOffset = (vfoBW / 2.0f) - (BW / 2.0f) + (viewBW / 10.0f);
|
||||
sigPath.setVFOFrequency(newVFOOffset);
|
||||
wtf.setVFOOffset(newVFOOffset);
|
||||
wtf.setCenterFrequency(freq - newVFOOffset);
|
||||
soapy.setFrequency(freq - newVFOOffset);
|
||||
return;
|
||||
}
|
||||
|
||||
// VFO is still without the SDR's bandwidth
|
||||
if (delta < 0) {
|
||||
float newViewOff = vfoTop - (viewBW / 2.0f) + (viewBW / 10.0f);
|
||||
float newViewBottom = newViewOff - (viewBW / 2.0f);
|
||||
float newViewTop = newViewOff + (viewBW / 2.0f);
|
||||
|
||||
if (newViewBottom > bottom) {
|
||||
wtf.setVFOOffset(newVFO);
|
||||
wtf.setViewOffset(newViewOff);
|
||||
sigPath.setVFOFrequency(newVFO);
|
||||
return;
|
||||
}
|
||||
|
||||
wtf.setViewOffset((BW / 2.0f) - (viewBW / 2.0f));
|
||||
float newVFOOffset = (BW / 2.0f) - (vfoBW / 2.0f) - (viewBW / 10.0f);
|
||||
sigPath.setVFOFrequency(newVFOOffset);
|
||||
wtf.setVFOOffset(newVFOOffset);
|
||||
wtf.setCenterFrequency(freq - newVFOOffset);
|
||||
soapy.setFrequency(freq - newVFOOffset);
|
||||
}
|
||||
else {
|
||||
float newViewOff = vfoBottom + (viewBW / 2.0f) - (viewBW / 10.0f);
|
||||
float newViewBottom = newViewOff - (viewBW / 2.0f);
|
||||
float newViewTop = newViewOff + (viewBW / 2.0f);
|
||||
|
||||
if (newViewTop < top) {
|
||||
wtf.setVFOOffset(newVFO);
|
||||
wtf.setViewOffset(newViewOff);
|
||||
sigPath.setVFOFrequency(newVFO);
|
||||
return;
|
||||
}
|
||||
|
||||
wtf.setViewOffset((viewBW / 2.0f) - (BW / 2.0f));
|
||||
float newVFOOffset = (vfoBW / 2.0f) - (BW / 2.0f) + (viewBW / 10.0f);
|
||||
sigPath.setVFOFrequency(newVFOOffset);
|
||||
wtf.setVFOOffset(newVFOOffset);
|
||||
wtf.setCenterFrequency(freq - newVFOOffset);
|
||||
soapy.setFrequency(freq - newVFOOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void drawWindow() {
|
||||
if (freq != _freq) {
|
||||
_freq = freq;
|
||||
wtf.setCenterFrequency(freq * 1000);
|
||||
soapy.setFrequency(freq * 1000);
|
||||
if (fSel.frequencyChanged) {
|
||||
fSel.frequencyChanged = false;
|
||||
setVFO(fSel.frequency);
|
||||
}
|
||||
|
||||
if (vfoFreq != lastVfoFreq) {
|
||||
lastVfoFreq = vfoFreq;
|
||||
sigPath.setVFOFrequency(vfoFreq - (freq * 1000));
|
||||
if (wtf.centerFreqMoved) {
|
||||
wtf.centerFreqMoved = false;
|
||||
soapy.setFrequency(wtf.getCenterFrequency());
|
||||
fSel.setFrequency(wtf.getCenterFrequency() + wtf.getVFOOfset());
|
||||
}
|
||||
if (wtf.vfoFreqChanged) {
|
||||
wtf.vfoFreqChanged = false;
|
||||
sigPath.setVFOFrequency(wtf.getVFOOfset());
|
||||
fSel.setFrequency(wtf.getCenterFrequency() + wtf.getVFOOfset());
|
||||
}
|
||||
|
||||
// vfoFreq = wtf.getVFOOfset() + freq;
|
||||
|
||||
// if (vfoFreq != lastVfoFreq) {
|
||||
// lastVfoFreq = vfoFreq;
|
||||
// sigPath.setVFOFrequency(vfoFreq - freq);
|
||||
// }
|
||||
|
||||
if (volume != lastVolume) {
|
||||
lastVolume = volume;
|
||||
@@ -115,23 +229,30 @@ void drawWindow() {
|
||||
}
|
||||
|
||||
if (srId != _srId) {
|
||||
soapy.setSampleRate(soapy.sampleRates[srId]);
|
||||
_srId = srId;
|
||||
sampleRate = soapy.sampleRates[srId];
|
||||
printf("Setting sample rate to %f\n", (float)soapy.sampleRates[srId]);
|
||||
soapy.setSampleRate(sampleRate);
|
||||
wtf.setBandwidth(sampleRate);
|
||||
wtf.setViewBandwidth(sampleRate);
|
||||
sigPath.setSampleRate(sampleRate);
|
||||
bw = sampleRate;
|
||||
}
|
||||
|
||||
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::BeginMenu("File"))
|
||||
{
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Edit"))
|
||||
{
|
||||
ImGui::MenuItem("Show Example Window", "", &showExample);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
// if (ImGui::BeginMenuBar())
|
||||
// {
|
||||
// if (ImGui::BeginMenu("File"))
|
||||
// {
|
||||
// ImGui::EndMenu();
|
||||
// }
|
||||
// if (ImGui::BeginMenu("Edit"))
|
||||
// {
|
||||
// ImGui::MenuItem("Show Example Window", "", &showExample);
|
||||
// ImGui::EndMenu();
|
||||
// }
|
||||
// ImGui::EndMenuBar();
|
||||
// }
|
||||
|
||||
if (showExample) {
|
||||
ImGui::ShowDemoWindow();
|
||||
@@ -144,8 +265,37 @@ void drawWindow() {
|
||||
int width = vMax.x - vMin.x;
|
||||
int height = vMax.y - vMin.y;
|
||||
|
||||
ImGui::Columns(2, "WindowColumns", false);
|
||||
// To Bar
|
||||
if (playing) {
|
||||
if (ImGui::ImageButton(icons::STOP_RAW, ImVec2(30, 30))) {
|
||||
soapy.stop();
|
||||
playing = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ImGui::ImageButton(icons::PLAY_RAW, ImVec2(30, 30))) {
|
||||
soapy.start();
|
||||
soapy.setFrequency(wtf.getCenterFrequency());
|
||||
playing = true;
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 8);
|
||||
ImGui::SetNextItemWidth(200);
|
||||
ImGui::SliderFloat("##_2_", &volume, 0.0f, 1.0f, "");
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
fSel.draw();
|
||||
|
||||
|
||||
ImGui::Columns(3, "WindowColumns", false);
|
||||
ImVec2 winSize = ImGui::GetWindowSize();
|
||||
ImGui::SetColumnWidth(0, 300);
|
||||
ImGui::SetColumnWidth(1, winSize.x - 300 - 50);
|
||||
ImGui::SetColumnWidth(2, 50);
|
||||
|
||||
// Left Column
|
||||
ImGui::BeginChild("Left Column");
|
||||
@@ -155,16 +305,6 @@ void drawWindow() {
|
||||
ImGui::Combo("##_0_", &devId, soapy.txtDevList.c_str());
|
||||
ImGui::Combo("##_1_", &srId, soapy.txtSampleRateList.c_str());
|
||||
|
||||
ImGui::SliderFloat("##_2_", &volume, 0.0f, 1.0f, "");
|
||||
if (ImGui::Button("Start") && !state) {
|
||||
state = true;
|
||||
soapy.start();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Stop") && state) {
|
||||
state = false;
|
||||
soapy.stop();
|
||||
}
|
||||
if (ImGui::Button("Refresh")) {
|
||||
soapy.refresh();
|
||||
}
|
||||
@@ -174,20 +314,44 @@ void drawWindow() {
|
||||
ImGui::BeginGroup();
|
||||
|
||||
ImGui::Columns(4, "RadioModeColumns", false);
|
||||
if (ImGui::RadioButton("NFM", demod == 0) && demod != 0) { demod = 0; };
|
||||
if (ImGui::RadioButton("WFM", demod == 1) && demod != 1) { sigPath.setDemodulator(SignalPath::DEMOD_FM); demod = 1; };
|
||||
if (ImGui::RadioButton("NFM", demod == 0) && demod != 0) {
|
||||
sigPath.setDemodulator(SignalPath::DEMOD_NFM); demod = 0;
|
||||
wtf.setVFOBandwidth(12500);
|
||||
wtf.setVFOReference(ImGui::WaterFall::REF_CENTER);
|
||||
}
|
||||
if (ImGui::RadioButton("WFM", demod == 1) && demod != 1) {
|
||||
sigPath.setDemodulator(SignalPath::DEMOD_FM);
|
||||
demod = 1;
|
||||
wtf.setVFOBandwidth(200000);
|
||||
wtf.setVFOReference(ImGui::WaterFall::REF_CENTER);
|
||||
}
|
||||
ImGui::NextColumn();
|
||||
if (ImGui::RadioButton("AM", demod == 2) && demod != 2) { sigPath.setDemodulator(SignalPath::DEMOD_AM); demod = 2; };
|
||||
if (ImGui::RadioButton("AM", demod == 2) && demod != 2) {
|
||||
sigPath.setDemodulator(SignalPath::DEMOD_AM);
|
||||
demod = 2;
|
||||
wtf.setVFOBandwidth(12500);
|
||||
wtf.setVFOReference(ImGui::WaterFall::REF_CENTER);
|
||||
}
|
||||
if (ImGui::RadioButton("DSB", demod == 3) && demod != 3) { demod = 3; };
|
||||
ImGui::NextColumn();
|
||||
if (ImGui::RadioButton("USB", demod == 4) && demod != 4) { demod = 4; };
|
||||
if (ImGui::RadioButton("USB", demod == 4) && demod != 4) {
|
||||
sigPath.setDemodulator(SignalPath::DEMOD_USB);
|
||||
demod = 4;
|
||||
wtf.setVFOBandwidth(3000);
|
||||
wtf.setVFOReference(ImGui::WaterFall::REF_LOWER);
|
||||
}
|
||||
if (ImGui::RadioButton("CW", demod == 5) && demod != 5) { demod = 5; };
|
||||
ImGui::NextColumn();
|
||||
if (ImGui::RadioButton("LSB", demod == 6) && demod != 6) { demod = 6; };
|
||||
if (ImGui::RadioButton("LSB", demod == 6) && demod != 6) {
|
||||
sigPath.setDemodulator(SignalPath::DEMOD_LSB);
|
||||
demod = 6;
|
||||
wtf.setVFOBandwidth(3000);
|
||||
wtf.setVFOReference(ImGui::WaterFall::REF_UPPER);
|
||||
}
|
||||
if (ImGui::RadioButton("RAW", demod == 7) && demod != 7) { demod = 7; };
|
||||
ImGui::Columns(1, "EndRadioModeColumns", false);
|
||||
|
||||
ImGui::InputInt("Frequency (kHz)", &freq);
|
||||
//ImGui::InputInt("Frequency (kHz)", &freq);
|
||||
ImGui::Checkbox("DC Bias Removal", &dcbias);
|
||||
|
||||
ImGui::EndGroup();
|
||||
@@ -202,31 +366,8 @@ 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::SliderFloat("##_3_", &fftMax, 0.0f, -100.0f, "");
|
||||
ImGui::SliderFloat("##_4_", &fftMin, 0.0f, -100.0f, "");
|
||||
|
||||
if (ImGui::Button("Auto Range")) {
|
||||
printf("Auto ranging...\n");
|
||||
wtf.autoRange();
|
||||
}
|
||||
|
||||
ImGui::SliderFloat("##_5_", &offset, -4000000.0f, 4000000.0f, "");
|
||||
ImGui::SliderFloat("##_6_", &bw, 1.0f, 8000000.0f, "");
|
||||
|
||||
wtf.setViewOffset(offset);
|
||||
wtf.setViewBandwidth(bw);
|
||||
|
||||
wtf.setFFTMin(fftMin);
|
||||
wtf.setFFTMax(fftMax);
|
||||
wtf.setWaterfallMin(fftMin);
|
||||
wtf.setWaterfallMax(fftMax);
|
||||
}
|
||||
|
||||
ImVec2 delta = ImGui::GetMouseDragDelta();
|
||||
ImGui::ResetMouseDragDelta();
|
||||
//printf("%f %f\n", delta.x, delta.y);
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
// Right Column
|
||||
@@ -235,4 +376,29 @@ void drawWindow() {
|
||||
ImGui::BeginChild("Waterfall");
|
||||
wtf.draw();
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::NextColumn();
|
||||
|
||||
ImGui::Text("Zoom");
|
||||
ImGui::NewLine();
|
||||
ImGui::VSliderFloat("##_7_", ImVec2(20.0f, 150.0f), &bw, 1000.0f, sampleRate, "");
|
||||
|
||||
ImGui::Text("Max");
|
||||
ImGui::NewLine();
|
||||
ImGui::VSliderFloat("##_8_", ImVec2(20.0f, 150.0f), &fftMax, -100.0f, 0.0f, "");
|
||||
|
||||
ImGui::Text("Min");
|
||||
ImGui::NewLine();
|
||||
ImGui::VSliderFloat("##_9_", ImVec2(20.0f, 150.0f), &fftMin, -100.0f, 0.0f, "");
|
||||
|
||||
if (bw != lastBW) {
|
||||
lastBW = bw;
|
||||
wtf.setViewOffset(wtf.getVFOOfset());
|
||||
wtf.setViewBandwidth(bw);
|
||||
}
|
||||
|
||||
wtf.setFFTMin(fftMin);
|
||||
wtf.setFFTMax(fftMax);
|
||||
wtf.setWaterfallMin(fftMin);
|
||||
wtf.setWaterfallMax(fftMax);
|
||||
}
|
||||
Reference in New Issue
Block a user