mirror of
https://github.com/SatDump/SatDump
synced 2026-08-13 17:47:30 -04:00
WIP DSP Stuff
This commit is contained in:
parent
5c7a7edb1a
commit
7bc49436b9
7 changed files with 147 additions and 6 deletions
67
src-core/dsp/clock_recovery/simple_gardner_recovery.cpp
Normal file
67
src-core/dsp/clock_recovery/simple_gardner_recovery.cpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
#include "simple_gardner_recovery.h"
|
||||
|
||||
namespace satdump
|
||||
{
|
||||
namespace ndsp
|
||||
{
|
||||
SimpleGardnerRecoveryBlock::SimpleGardnerRecoveryBlock() : BlockSimple<complex_t, complex_t>("simple_gardner_recovery_c", {{"in", DSP_SAMPLE_TYPE_CF32}}, {{"out", DSP_SAMPLE_TYPE_CF32}}) {}
|
||||
|
||||
SimpleGardnerRecoveryBlock::~SimpleGardnerRecoveryBlock() {}
|
||||
|
||||
void SimpleGardnerRecoveryBlock::init() {}
|
||||
|
||||
bool SimpleGardnerRecoveryBlock::clock_recovery(complex_t sample, complex_t *sym)
|
||||
{
|
||||
bool fired = 0;
|
||||
|
||||
// Down to next half-symbol
|
||||
phase -= 1.0f;
|
||||
|
||||
if (phase <= 0.0f)
|
||||
{
|
||||
// Interpolation either midpoint or
|
||||
float frac = 1.0f + phase;
|
||||
complex_t samp = last_sample + (sample - last_sample) * frac;
|
||||
|
||||
if (is_mid)
|
||||
{
|
||||
// Midpoint sample (between two symbols)
|
||||
mid = samp;
|
||||
is_mid = false;
|
||||
phase += period / 2.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
// On-time symbol sample
|
||||
complex_t curr = samp;
|
||||
|
||||
complex_t diff = curr - prev_sym;
|
||||
float err = diff.real * mid.real + diff.imag * mid.imag;
|
||||
|
||||
// Advance to next midpoint with error
|
||||
phase += period / 2.0f - alpha * err;
|
||||
|
||||
prev_sym = curr;
|
||||
is_mid = true;
|
||||
|
||||
*sym = curr;
|
||||
fired = 1;
|
||||
}
|
||||
}
|
||||
|
||||
last_sample = sample;
|
||||
|
||||
return fired;
|
||||
}
|
||||
|
||||
uint32_t SimpleGardnerRecoveryBlock::process(complex_t *in, uint32_t nsamples, complex_t *out)
|
||||
{
|
||||
uint32_t oo = 0;
|
||||
complex_t sym;
|
||||
for (uint32_t i = 0; i < nsamples; i++)
|
||||
if (clock_recovery(in[i], &sym))
|
||||
out[oo++] = sym;
|
||||
return oo;
|
||||
}
|
||||
} // namespace ndsp
|
||||
} // namespace satdump
|
||||
68
src-core/dsp/clock_recovery/simple_gardner_recovery.h
Normal file
68
src-core/dsp/clock_recovery/simple_gardner_recovery.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
#pragma once
|
||||
|
||||
#include "common/dsp/complex.h"
|
||||
#include "dsp/block_simple.h"
|
||||
|
||||
namespace satdump
|
||||
{
|
||||
namespace ndsp
|
||||
{
|
||||
class SimpleGardnerRecoveryBlock : public BlockSimple<complex_t, complex_t>
|
||||
{
|
||||
private:
|
||||
float period = 4;
|
||||
float alpha = 0.02f;
|
||||
|
||||
complex_t last_sample = 0.0f;
|
||||
|
||||
// Gardner stuff, since we need a midpoint
|
||||
complex_t prev_sym = 0.0f;
|
||||
complex_t mid = 0.0f;
|
||||
bool is_mid = true;
|
||||
|
||||
// Samples until next half-symbol
|
||||
float phase = 0.0f;
|
||||
|
||||
private:
|
||||
bool clock_recovery(complex_t sample, complex_t *sym);
|
||||
|
||||
public:
|
||||
uint32_t process(complex_t *input, uint32_t nsamples, complex_t *output);
|
||||
|
||||
public:
|
||||
SimpleGardnerRecoveryBlock();
|
||||
~SimpleGardnerRecoveryBlock();
|
||||
|
||||
void init();
|
||||
|
||||
nlohmann::ordered_json get_cfg_list()
|
||||
{
|
||||
nlohmann::ordered_json p;
|
||||
add_param_simple(p, "sps", "float");
|
||||
add_param_simple(p, "alpha", "float");
|
||||
return p;
|
||||
}
|
||||
|
||||
nlohmann::json get_cfg(std::string key)
|
||||
{
|
||||
if (key == "sps")
|
||||
return period;
|
||||
else if (key == "alpha")
|
||||
return alpha;
|
||||
else
|
||||
throw satdump_exception(key);
|
||||
}
|
||||
|
||||
Block::cfg_res_t set_cfg(std::string key, nlohmann::json v)
|
||||
{
|
||||
if (key == "sps")
|
||||
period = v;
|
||||
else if (key == "alpha")
|
||||
alpha = v;
|
||||
else
|
||||
throw satdump_exception(key);
|
||||
return Block::RES_OK;
|
||||
}
|
||||
};
|
||||
} // namespace ndsp
|
||||
} // namespace satdump
|
||||
|
|
@ -5,7 +5,7 @@ namespace satdump
|
|||
{
|
||||
namespace ndsp
|
||||
{
|
||||
SimpleZeroCrossingRecoveryBlock::SimpleZeroCrossingRecoveryBlock() : BlockSimple<float, float>("simple_zc_recovery", {{"in", DSP_SAMPLE_TYPE_F32}}, {{"out", DSP_SAMPLE_TYPE_F32}}) {}
|
||||
SimpleZeroCrossingRecoveryBlock::SimpleZeroCrossingRecoveryBlock() : BlockSimple<float, float>("simple_zc_recovery_f", {{"in", DSP_SAMPLE_TYPE_F32}}, {{"out", DSP_SAMPLE_TYPE_F32}}) {}
|
||||
|
||||
SimpleZeroCrossingRecoveryBlock::~SimpleZeroCrossingRecoveryBlock() {}
|
||||
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ namespace satdump
|
|||
|
||||
oblk.size = i->filter.process(oblk.getSamples<complex_t>(), iblk.size, oblk.getSamples<complex_t>());
|
||||
|
||||
#if 0
|
||||
if (i->decimation > 1)
|
||||
{
|
||||
int size_out = 0;
|
||||
|
|
@ -156,6 +157,7 @@ namespace satdump
|
|||
{
|
||||
oblk.size = iblk.size;
|
||||
}
|
||||
#endif
|
||||
|
||||
o.fifo->wait_enqueue(oblk);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "core/exception.h"
|
||||
#include "dsp/block.h"
|
||||
#include "dsp/block_helpers.h"
|
||||
#include "dsp/filter/decimating_fir.h"
|
||||
#include "dsp/filter/fir.h"
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
|
@ -125,12 +126,13 @@ namespace satdump
|
|||
if (bandwidth == 0)
|
||||
return;
|
||||
|
||||
auto v = calc_filter(sr, 0, bandwidth / 2, 30, 80);
|
||||
auto v = calc_filter(sr, 0, bandwidth / 2, 300, 80);
|
||||
|
||||
filter.set_cfg("taps", v /*dsp::firdes::low_pass(1, sr, bandwidth / 2, 1e3)*/);
|
||||
filter.set_cfg("decimation", decimation);
|
||||
}
|
||||
|
||||
FIRBlock<complex_t> filter;
|
||||
DecimatingFIRBlock<complex_t> filter;
|
||||
|
||||
IOInfo(std::string id, bool forward_terminator, double f = 0, double b = 0, double d = 0) : id(id), forward_terminator(forward_terminator), frequency(f), bandwidth(b), decimation(d) {}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@
|
|||
#include "dsp/agc/agc_fast.h"
|
||||
#include "dsp/clock_recovery/clock_recovery_mm.h"
|
||||
#include "dsp/clock_recovery/clock_recovery_mm_fast.h"
|
||||
#include "dsp/clock_recovery/simple_gardner_recovery.h"
|
||||
#include "dsp/clock_recovery/simple_zc_recovery.h"
|
||||
#include "dsp/conv/char_to_float.h"
|
||||
#include "dsp/conv/complex_to_float.h"
|
||||
|
|
@ -288,6 +289,7 @@ namespace satdump
|
|||
registerNodeSimple<ndsp::PLLCarrierTrackingBlock>(flowgraph, "PLL/PLL Carrier Tracking");
|
||||
|
||||
registerNodeSimple<ndsp::SimpleZeroCrossingRecoveryBlock>(flowgraph, "Timing/Simple Zero-Crossing Clock Recovery FF");
|
||||
registerNodeSimple<ndsp::SimpleGardnerRecoveryBlock>(flowgraph, "Timing/Simple Gardner Clock Recovery CC");
|
||||
|
||||
registerNodeSimple<ndsp::MMClockRecoveryBlock<complex_t>>(flowgraph, "Timing/Clock Recovery MM CC");
|
||||
registerNodeSimple<ndsp::MMClockRecoveryBlock<float>>(flowgraph, "Timing/Clock Recovery MM FF");
|
||||
|
|
|
|||
|
|
@ -53,10 +53,10 @@ namespace satdump
|
|||
vco_blk.start();
|
||||
}
|
||||
|
||||
void stop(bool stop_snow, bool force)
|
||||
void stop(bool stop_snow = false, bool force = false)
|
||||
{
|
||||
fir_blk.stop(stop_snow);
|
||||
vco_blk.stop(stop_snow);
|
||||
fir_blk.stop(stop_snow, force);
|
||||
vco_blk.stop(stop_snow, force);
|
||||
}
|
||||
|
||||
nlohmann::ordered_json get_cfg_list()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue