satdump/plugins/dvb_support/dvbs2/dvbs2_pl_sync.cpp
2023-05-08 23:08:34 +02:00

156 lines
No EOL
4.7 KiB
C++

#include "dvbs2_pl_sync.h"
#include "logger.h"
namespace dvbs2
{
S2PLSyncBlock::S2PLSyncBlock(std::shared_ptr<dsp::stream<complex_t>> input, int slot_number, bool pilots)
: Block(input), slot_number(slot_number)
{
ring_buffer.init(10000000);
raw_frame_size = (slot_number + 1) * 90; // PL (90 Symbols) + slots of 90 symbols
if (pilots)
{
int raw_size = (raw_frame_size - 90) / 90;
int pilot_cnt = 1;
raw_size -= 16; // First pilot is 16 slots after the SOF
while (raw_size > 16)
{
raw_size -= 16; // The rest is 32 symbols further
pilot_cnt++;
}
raw_frame_size += pilot_cnt * 36;
logger->info("Pilots size (PLSYNC) : %d", raw_frame_size);
}
correlation_buffer = new complex_t[raw_frame_size];
}
S2PLSyncBlock::~S2PLSyncBlock()
{
delete[] correlation_buffer;
}
void S2PLSyncBlock::work()
{
int nsamples = input_stream->read();
if (nsamples <= 0)
{
input_stream->flush();
return;
}
ring_buffer.write(input_stream->readBuf, nsamples);
input_stream->flush();
}
void S2PLSyncBlock::work2()
{
/*int got =*/ring_buffer.read(correlation_buffer, raw_frame_size);
// Correlate the PLHeader
int best_pos = 0;
double best_match = 0;
complex_t best_match_raw = 0;
complex_t plheader_symbols[sof.LENGTH + pls.LENGTH];
for (int ss = 0; ss < raw_frame_size - sof.LENGTH - pls.LENGTH; ss++)
{
#if 0
complex_t prev = 0;
for (int i = 0; i < sof.LENGTH + pls.LENGTH; i++)
{
float phase2 = 0;
// complex_t vco = complex_t(cosf(phase2), sinf(phase2));
plheader_symbols[i] = conjprod(prev, correlation_buffer[ss + i] /* * vco*/);
prev = correlation_buffer[ss + i] /* * vco*/;
// phase2 += freq;
}
#endif
plheader_symbols[0] = 0;
volk_32fc_conjugate_32fc((lv_32fc_t *)&plheader_symbols[1], (lv_32fc_t *)&correlation_buffer[ss], sof.LENGTH + pls.LENGTH - 1);
volk_32fc_x2_multiply_32fc((lv_32fc_t *)plheader_symbols, (lv_32fc_t *)plheader_symbols, (lv_32fc_t *)&correlation_buffer[ss], sof.LENGTH + pls.LENGTH);
double difference = 0;
// complex_t d = correlate_sof_diff(sof_raw_syms);
complex_t csof = correlate_sof_diff(plheader_symbols);
complex_t cplsc = correlate_plscode_diff(&plheader_symbols[sof.LENGTH]);
complex_t c0 = csof + cplsc; // Best when b7==0 (pilots off)
complex_t c1 = csof - cplsc; // Best when b7==1 (pilots on)
complex_t c = c0.norm() > c1.norm() ? c0 : c1;
complex_t d = c * (1.0f / (26 - 1 + 64 / 2));
difference = d.norm();
// sof_difference = difference;
if (difference > best_match && d.imag > 0)
{
best_match = difference;
best_pos = ss;
best_match_raw = d;
current_position = best_pos;
if (difference > thresold)
goto skip_slow_corr;
}
}
skip_slow_corr:
// logger->info(best_pos);
if (best_pos != 0 && best_pos < raw_frame_size) // Safety
{
int pos = best_pos;
memmove(&correlation_buffer[0], &correlation_buffer[pos], (raw_frame_size - pos) * sizeof(complex_t));
ring_buffer.read(&correlation_buffer[raw_frame_size - pos], pos);
best_pos = 0;
}
memcpy(output_stream->writeBuf, correlation_buffer, raw_frame_size * sizeof(complex_t));
output_stream->swap(raw_frame_size);
}
complex_t S2PLSyncBlock::correlate_sof_diff(complex_t *diffs)
{
complex_t c = 0;
const uint32_t dsof = sof.VALUE ^ (sof.VALUE >> 1);
for (int i = 0; i < sof.LENGTH; ++i)
{
// Constant odd bit => +PI/4
// Constant even bit => -PI/4
// Toggled odd bit => -PI/4
// Toggled even bit => +PI/4
if (((dsof >> (sof.LENGTH - 1 - i)) ^ i) & 1)
c += diffs[i];
else
c -= diffs[i];
}
return c;
}
complex_t S2PLSyncBlock::correlate_plscode_diff(complex_t *diffs)
{
complex_t c = 0;
uint64_t dscr = pls.SCRAMBLING ^ (pls.SCRAMBLING >> 1);
for (int i = 1; i < pls.LENGTH; i += 2)
{
if ((dscr >> (pls.LENGTH - 1 - i)) & 1)
c -= diffs[i];
else
c += diffs[i];
}
return c;
}
}