satdump/src-core/common/codings/correlator.cpp

178 lines
4.5 KiB
C++
Raw Normal View History

2021-05-09 17:13:27 +02:00
#include "correlator.h"
uint64_t rotate_64(uint64_t word, uint64_t p)
{
uint64_t i = word & 0xaaaaaaaaaaaaaaaa;
uint64_t q = word & 0x5555555555555555;
switch (p)
{
case PHASE_0:
break;
case PHASE_90:
word = ((i ^ 0xaaaaaaaaaaaaaaaa) >> 1) | (q << 1);
break;
case PHASE_180:
word = word ^ 0xffffffffffffffff;
break;
case PHASE_270:
word = (i >> 1) | ((q ^ 0x5555555555555555) << 1);
break;
default:
break;
}
return ((word & 0x5555555555555555) << 1) | ((word & 0xAAAAAAAAAAAAAAAA) >> 1);
}
int corr_64(uint64_t v1, uint64_t v2)
{
int cor = 0;
uint64_t diff = v1 ^ v2;
for (; diff; cor++)
diff &= diff - 1;
return 64 - cor;
}
uint64_t swapIQ(uint64_t in)
{
uint64_t i = in & 0xaaaaaaaaaaaaaaaa;
uint64_t q = in & 0x5555555555555555;
return (i >> 1) | (q << 1);
}
Correlator::Correlator(constellation_t mod, uint64_t syncword) : d_modulation(mod)
2021-05-09 17:13:27 +02:00
{
hard_buf = new uint8_t[8192 * 20];
2021-06-24 16:01:00 +02:00
if (d_modulation == BPSK)
{
// Generate syncwords
syncwords[0] = syncword;
syncwords[1] = syncword ^ 0xFFFFFFFFFFFFFFFF;
}
else if (d_modulation == QPSK)
2021-05-09 17:13:27 +02:00
{
// Generate syncwords
for (int i = 0; i < 4; i++)
syncwords[i] = rotate_64(syncword, (phase_t)i);
// Generate rotated syncwords
for (int i = 4; i < 8; i++)
syncwords[i] = rotate_64((swapIQ(syncword) ^ 0xFFFFFFFFFFFFFFFF), (phase_t)(i - 4));
}
}
Correlator::~Correlator()
{
delete[] hard_buf;
}
int Correlator::correlate(int8_t *soft_input, phase_t &phase, bool &swap, int &cor, int length)
{
int correlation = 0, offset = 0, pos = 0;
2021-06-24 16:01:00 +02:00
// Pack into hard symbols
int bits = 0, bytes = 0;
uint8_t shifter = 0;
for (int i = 0; i < length; i++)
2021-05-09 17:13:27 +02:00
{
shifter = shifter << 1 | (soft_input[i] > 0);
2021-06-24 16:01:00 +02:00
bits++;
if (bits == 8)
2021-05-09 17:13:27 +02:00
{
2021-06-24 16:01:00 +02:00
hard_buf[bytes] = shifter;
bits = 0;
bytes++;
}
}
uint64_t current = ((uint64_t)hard_buf[0] << 56) | ((uint64_t)hard_buf[1] << 48) | ((uint64_t)hard_buf[2] << 40) |
((uint64_t)hard_buf[3] << 32) | ((uint64_t)hard_buf[4] << 24) | ((uint64_t)hard_buf[5] << 16) |
((uint64_t)hard_buf[6] << 8) | ((uint64_t)hard_buf[7] << 0);
if (d_modulation == BPSK)
{
pos += 8;
2021-05-09 17:13:27 +02:00
2021-06-24 16:01:00 +02:00
// Check pos 0
for (int p = 0; p < 2; p++)
{
int corr = corr_64(syncwords[p], current);
if (corr > 45)
2021-05-09 17:13:27 +02:00
{
2021-06-24 16:01:00 +02:00
cor = corr;
phase = p ? PHASE_180 : PHASE_0;
swap = 0;
return 0;
2021-05-09 17:13:27 +02:00
}
}
2021-06-24 16:01:00 +02:00
// Check the rest
for (int i = 0; i < length - 8; i++)
{
for (int ii = 0; ii < 8; ii += 1)
{
for (int p = 0; p < 2; p++)
{
int corr = corr_64(syncwords[p], current);
if (corr > correlation)
{
correlation = corr;
offset = i * 8 + ii;
phase = p ? PHASE_180 : PHASE_0;
swap = 0;
}
}
current = (current << 1) | ((hard_buf[pos] >> (7 - ii)) & 0b1);
}
pos++;
}
}
else if (d_modulation == QPSK)
{
2021-05-09 17:13:27 +02:00
pos += 8;
// Check pos 0
for (int p = 0; p < 8; p++)
{
2021-06-24 16:01:00 +02:00
int corr = corr_64(syncwords[p], current);
if (corr > 45)
2021-05-09 17:13:27 +02:00
{
2021-06-24 16:01:00 +02:00
cor = corr;
2021-05-09 17:13:27 +02:00
phase = (phase_t)(p % 4);
swap = (p / 4) == 0;
return 0;
}
}
// Check the rest
for (int i = 0; i < length - 8; i++)
{
for (int ii = 0; ii < 8; ii += 2)
{
for (int p = 0; p < 8; p++)
{
int corr = corr_64(syncwords[p], current);
if (corr > correlation)
{
correlation = corr;
offset = i * 8 + ii;
phase = (phase_t)(p % 4);
swap = (p / 4) == 0;
}
}
2021-05-16 18:44:05 +02:00
current = (current << 2) | ((hard_buf[pos] >> (6 - ii)) & 0b11);
2021-05-09 17:13:27 +02:00
}
pos++;
}
}
cor = correlation;
return offset;
}