Added decimation

pull/190/head
Ryzerth 2021-07-26 21:18:06 +02:00
rodzic ffed602246
commit e62351c206
5 zmienionych plików z 195 dodań i 8 usunięć

Wyświetl plik

@ -47,13 +47,15 @@ namespace core {
GLFWwindow* window;
void setInputSampleRate(double samplerate) {
sigpath::signalPath.sourceSampleRate = samplerate;
double effectiveSr = samplerate / ((double)(1 << sigpath::signalPath.decimation));
// NOTE: Zoom controls won't work
spdlog::info("New DSP samplerate: {0}", samplerate);
gui::waterfall.setBandwidth(samplerate);
spdlog::info("New DSP samplerate: {0} (source samplerate is {1})", effectiveSr, samplerate);
gui::waterfall.setBandwidth(effectiveSr);
gui::waterfall.setViewOffset(0);
gui::waterfall.setViewBandwidth(samplerate);
sigpath::signalPath.setSampleRate(samplerate);
gui::mainWindow.setViewBandwidthSlider(samplerate);
gui::waterfall.setViewBandwidth(effectiveSr);
sigpath::signalPath.setSampleRate(effectiveSr);
gui::mainWindow.setViewBandwidthSlider(effectiveSr);
}
};
@ -202,6 +204,7 @@ int sdrpp_main(int argc, char *argv[]) {
defConfig["showMenu"] = true;
defConfig["showWaterfall"] = true;
defConfig["source"] = "";
defConfig["decimationPower"] = 0;
defConfig["streams"]["Radio"]["muted"] = false;
defConfig["streams"]["Radio"]["sink"] = "Audio";

Wyświetl plik

@ -0,0 +1,108 @@
#pragma once
#include <dsp/block.h>
#include <dsp/stream.h>
#include <dsp/types.h>
#include <dsp/window.h>
namespace dsp {
template <class T>
class HalfDecimator : public generic_block<HalfDecimator<T>> {
public:
HalfDecimator() {}
HalfDecimator(stream<T>* in, dsp::filter_window::generic_window* window) { init(in, window); }
~HalfDecimator() {
if (!generic_block<HalfDecimator<T>>::_block_init) { return; }
generic_block<HalfDecimator<T>>::stop();
volk_free(buffer);
volk_free(taps);
generic_block<HalfDecimator<T>>::_block_init = false;
}
void init(stream<T>* in, dsp::filter_window::generic_window* window) {
_in = in;
tapCount = window->getTapCount();
taps = (float*)volk_malloc(tapCount * sizeof(float), volk_get_alignment());
window->createTaps(taps, tapCount);
buffer = (T*)volk_malloc(STREAM_BUFFER_SIZE * sizeof(T) * 2, volk_get_alignment());
bufStart = &buffer[tapCount];
generic_block<HalfDecimator<T>>::registerInput(_in);
generic_block<HalfDecimator<T>>::registerOutput(&out);
generic_block<HalfDecimator<T>>::_block_init = true;
}
void setInput(stream<T>* in) {
assert(generic_block<HalfDecimator<T>>::_block_init);
std::lock_guard<std::mutex> lck(generic_block<HalfDecimator<T>>::ctrlMtx);
generic_block<HalfDecimator<T>>::tempStop();
generic_block<HalfDecimator<T>>::unregisterInput(_in);
_in = in;
generic_block<HalfDecimator<T>>::registerInput(_in);
generic_block<HalfDecimator<T>>::tempStart();
}
void updateWindow(dsp::filter_window::generic_window* window) {
assert(generic_block<HalfDecimator<T>>::_block_init);
std::lock_guard<std::mutex> lck(generic_block<HalfDecimator<T>>::ctrlMtx);
_window = window;
volk_free(taps);
tapCount = window->getTapCount();
taps = (float*)volk_malloc(tapCount * sizeof(float), volk_get_alignment());
bufStart = &buffer[tapCount];
window->createTaps(taps, tapCount);
}
int run() {
int count = _in->read();
if (count < 0) { return -1; }
generic_block<HalfDecimator<T>>::ctrlMtx.lock();
memcpy(bufStart, _in->readBuf, count * sizeof(T));
_in->flush();
int inIndex = _inIndex;
int outIndex = 0;
if constexpr (std::is_same_v<T, float>) {
while (inIndex < count) {
volk_32f_x2_dot_prod_32f((float*)&out.writeBuf[outIndex], (float*)&buffer[inIndex+1], taps, tapCount);
inIndex += 2;
outIndex++;
}
}
if constexpr (std::is_same_v<T, complex_t>) {
while (inIndex < count) {
volk_32fc_32f_dot_prod_32fc((lv_32fc_t*)&out.writeBuf[outIndex], (lv_32fc_t*)&buffer[inIndex+1], taps, tapCount);
inIndex += 2;
outIndex++;
}
}
_inIndex = inIndex - count;
if (!out.swap(outIndex)) { return -1; }
memmove(buffer, &buffer[count], tapCount * sizeof(T));
generic_block<HalfDecimator<T>>::ctrlMtx.unlock();
return count;
}
stream<T> out;
private:
stream<T>* _in;
dsp::filter_window::generic_window* _window;
T* bufStart;
T* buffer;
int tapCount;
float* taps;
int _inIndex = 0;
};
}

Wyświetl plik

@ -11,6 +11,7 @@ namespace sourecmenu {
int sourceId = 0;
double customOffset = 0.0;
double effectiveOffset = 0.0;
int decimationPower = 0;
EventHandler<std::string> sourceRegisteredHandler;
EventHandler<std::string> sourceUnregisterHandler;
@ -39,6 +40,14 @@ namespace sourecmenu {
"Ku LNB (9750MHz)\0"
"Ku LNB (10700MHz)\0";
const char* decimationStages = "None\0"
"2\0"
"4\0"
"8\0"
"16\0"
"32\0"
"64\0";
void updateOffset() {
if (offsetMode == OFFSET_MODE_CUSTOM) { effectiveOffset = customOffset; }
else if (offsetMode == OFFSET_MODE_SPYVERTER) { effectiveOffset = 120000000; } // 120MHz Up-conversion
@ -113,10 +122,12 @@ namespace sourecmenu {
std::string selected = core::configManager.conf["source"];
customOffset = core::configManager.conf["offset"];
offsetMode = core::configManager.conf["offsetMode"];
decimationPower = core::configManager.conf["decimationPower"];
updateOffset();
refreshSources();
selectSource(selected);
sigpath::signalPath.setDecimation(decimationPower);
sourceRegisteredHandler.handler = onSourceRegistered;
sourceUnregisterHandler.handler = onSourceUnregister;
@ -130,8 +141,9 @@ namespace sourecmenu {
void draw(void* ctx) {
float itemWidth = ImGui::GetContentRegionAvailWidth();
bool running = gui::mainWindow.sdrIsRunning();
if (gui::mainWindow.sdrIsRunning()) { style::beginDisabled(); }
if (running) { style::beginDisabled(); }
ImGui::SetNextItemWidth(itemWidth);
if (ImGui::Combo("##source", &sourceId, sourceNamesTxt.c_str())) {
@ -141,7 +153,7 @@ namespace sourecmenu {
core::configManager.release(true);
}
if (gui::mainWindow.sdrIsRunning()) { style::endDisabled(); }
if (running) { style::endDisabled(); }
sigpath::sourceManager.showSelectedMenu();
@ -171,5 +183,17 @@ namespace sourecmenu {
ImGui::InputDouble("##freq_offset", &effectiveOffset, 1.0, 100.0);
style::endDisabled();
}
if (running) { style::beginDisabled(); }
ImGui::Text("Decimation");
ImGui::SameLine();
ImGui::SetNextItemWidth(itemWidth - ImGui::GetCursorPosX());
if (ImGui::Combo("##source_decim", &decimationPower, decimationStages)) {
sigpath::signalPath.setDecimation(decimationPower);
core::configManager.acquire();
core::configManager.conf["decimationPower"] = decimationPower;
core::configManager.release(true);
}
if (running) { style::endDisabled(); }
}
}

Wyświetl plik

@ -1,4 +1,5 @@
#include <signal_path/dsp.h>
#include <core.h>
SignalPath::SignalPath() {
@ -6,10 +7,13 @@ SignalPath::SignalPath() {
void SignalPath::init(uint64_t sampleRate, int fftRate, int fftSize, dsp::stream<dsp::complex_t>* input, dsp::complex_t* fftBuffer, void fftHandler(dsp::complex_t*,int,void*), void* fftHandlerCtx) {
this->sampleRate = sampleRate;
this->sourceSampleRate = sampleRate;
this->fftRate = fftRate;
this->fftSize = fftSize;
inputBlockSize = sampleRate / 200.0f;
halfBandWindow.init(1000000, 200000, 4000000);
// split.init(input);
inputBuffer.init(input);
split.init(&inputBuffer.out);
@ -47,17 +51,25 @@ double SignalPath::getSampleRate() {
}
void SignalPath::start() {
for (auto& decimator : decimators) {
decimator->start();
}
inputBuffer.start();
split.start();
reshape.start();
fftHandlerSink.start();
running = true;
}
void SignalPath::stop() {
for (auto& decimator : decimators) {
decimator->stop();
}
inputBuffer.stop();
split.stop();
reshape.stop();
fftHandlerSink.stop();
running = false;
}
dsp::VFO* SignalPath::addVFO(std::string name, double outSampleRate, double bandwidth, double offset) {
@ -87,7 +99,6 @@ void SignalPath::removeVFO(std::string name) {
}
void SignalPath::setInput(dsp::stream<dsp::complex_t>* input) {
// split.setInput(input);
inputBuffer.setInput(input);
}
@ -120,4 +131,38 @@ void SignalPath::stopFFT() {
void SignalPath::setBuffering(bool enabled) {
inputBuffer.bypass = !enabled;
}
void SignalPath::setDecimation(int dec) {
decimation = dec;
// Stop existing decimators
if (!decimators.empty()) {
for (auto& decimator : decimators) {
decimator->stop();
delete decimator;
}
}
decimators.clear();
// If no decimation, reconnect
if (!dec) {
split.setInput(&inputBuffer.out);
core::setInputSampleRate(sourceSampleRate);
return;
}
// Create new decimators
if (running) { split.stop(); }
for (int i = 0; i < dec; i++) {
dsp::HalfDecimator<dsp::complex_t>* decimator = new dsp::HalfDecimator<dsp::complex_t>((i == 0) ? &inputBuffer.out : &decimators[i-1]->out, &halfBandWindow);
if (running) { decimator->start(); }
// TODO: ONLY start if running
decimators.push_back(decimator);
}
split.setInput(&decimators[decimators.size()-1]->out);
if (running) { split.start(); }
// Update the DSP sample rate
core::setInputSampleRate(sourceSampleRate);
}

Wyświetl plik

@ -3,6 +3,7 @@
#include <dsp/vfo.h>
#include <map>
#include <dsp/sink.h>
#include <dsp/decimation.h>
class SignalPath {
public:
@ -21,8 +22,11 @@ public:
void startFFT();
void stopFFT();
void setBuffering(bool enabled);
void setDecimation(int dec);
dsp::SampleFrameBuffer<dsp::complex_t> inputBuffer;
double sourceSampleRate = 0;
int decimation = 0;
private:
struct VFO_t {
@ -39,10 +43,13 @@ private:
// VFO
std::map<std::string, VFO_t> vfos;
std::vector<dsp::HalfDecimator<dsp::complex_t>*> decimators;
dsp::filter_window::BlackmanWindow halfBandWindow;
double sampleRate;
double fftRate;
int fftSize;
int inputBlockSize;
bool bufferingEnabled = false;
bool running = false;
};