satdump/src-core/common/dsp/costas_loop.cpp

69 lines
2.3 KiB
C++
Raw Normal View History

2021-03-12 17:56:29 +01:00
#include "costas_loop.h"
namespace dsp
{
2021-10-22 15:26:17 +02:00
CostasLoopBlock::CostasLoopBlock(std::shared_ptr<dsp::stream<complex_t>> input, float loop_bw, unsigned int order) : Block(input), order(order), loop_bw(loop_bw)
2021-03-12 17:56:29 +01:00
{
2021-10-22 15:26:17 +02:00
float damping = sqrtf(2.0f) / 2.0f;
float denom = (1.0 + 2.0 * damping * loop_bw + loop_bw * loop_bw);
alpha = (4 * damping * loop_bw) / denom;
beta = (4 * loop_bw * loop_bw) / denom;
2021-03-12 17:56:29 +01:00
}
void CostasLoopBlock::work()
{
int nsamples = input_stream->read();
if (nsamples <= 0)
2021-08-13 10:55:45 +02:00
{
input_stream->flush();
2021-03-12 17:56:29 +01:00
return;
2021-08-13 10:55:45 +02:00
}
2021-10-22 15:26:17 +02:00
for (int i = 0; i < nsamples; i++)
{
// Mix input & VCO
2021-10-27 20:35:12 +02:00
tmp_val = input_stream->readBuf[i] * complex_t(cosf(-phase), sinf(-phase));
2021-10-22 15:26:17 +02:00
output_stream->writeBuf[i] = tmp_val;
// Calculate error
switch (order)
{
case 2: // Order 2, BPSK
error = tmp_val.real * tmp_val.imag;
break;
case 4: // Order 4, QPSK
error = (tmp_val.real > 0.0f ? 1.0f : -1.0f) * tmp_val.imag - (tmp_val.imag > 0.0f ? 1.0f : -1.0f) * tmp_val.real;
break;
case 8: // Order 8, 8-PSK
const float K = (sqrtf(2.0) - 1);
if (fabsf(tmp_val.real) >= fabsf(tmp_val.imag))
error = ((tmp_val.real > 0.0f ? 1.0f : -1.0f) * tmp_val.imag - (tmp_val.imag > 0.0f ? 1.0f : -1.0f) * tmp_val.real * K);
else
error = ((tmp_val.real > 0.0f ? 1.0f : -1.0f) * tmp_val.imag * K - (tmp_val.imag > 0.0f ? 1.0f : -1.0f) * tmp_val.real);
break;
}
// Clip error
2021-10-27 20:35:12 +02:00
error = branchless_clip(error, 1.0);
2021-10-22 15:26:17 +02:00
2021-10-27 20:35:12 +02:00
// Compute new freq and phase.
2021-10-22 15:26:17 +02:00
freq += beta * error;
2021-10-27 20:35:12 +02:00
phase += freq + alpha * error;
2021-10-22 15:26:17 +02:00
// Wrap phase
while (phase > (2 * M_PI))
phase -= 2 * M_PI;
while (phase < (-2 * M_PI))
phase += 2 * M_PI;
2021-10-27 20:35:12 +02:00
// Clamp freq
if (freq > 1.0)
freq = 1.0;
if (freq < -1.0)
freq = -1.0;
2021-10-22 15:26:17 +02:00
}
2021-03-12 17:56:29 +01:00
input_stream->flush();
output_stream->swap(nsamples);
}
}