mirror of
https://github.com/SatDump/SatDump
synced 2026-08-13 17:47:30 -04:00
178 lines
No EOL
4.5 KiB
C++
178 lines
No EOL
4.5 KiB
C++
#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)
|
|
{
|
|
hard_buf = new uint8_t[8192 * 20];
|
|
|
|
if (d_modulation == BPSK)
|
|
{
|
|
// Generate syncwords
|
|
syncwords[0] = syncword;
|
|
syncwords[1] = syncword ^ 0xFFFFFFFFFFFFFFFF;
|
|
}
|
|
else if (d_modulation == QPSK)
|
|
{
|
|
// 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;
|
|
|
|
// Pack into hard symbols
|
|
int bits = 0, bytes = 0;
|
|
uint8_t shifter = 0;
|
|
for (int i = 0; i < length; i++)
|
|
{
|
|
shifter = shifter << 1 | (soft_input[i] > 0);
|
|
bits++;
|
|
|
|
if (bits == 8)
|
|
{
|
|
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;
|
|
|
|
// Check pos 0
|
|
for (int p = 0; p < 2; p++)
|
|
{
|
|
int corr = corr_64(syncwords[p], current);
|
|
if (corr > 45)
|
|
{
|
|
cor = corr;
|
|
phase = p ? PHASE_180 : PHASE_0;
|
|
swap = 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
pos += 8;
|
|
|
|
// Check pos 0
|
|
for (int p = 0; p < 8; p++)
|
|
{
|
|
int corr = corr_64(syncwords[p], current);
|
|
if (corr > 45)
|
|
{
|
|
cor = corr;
|
|
phase = (phase_t)(p % 4);
|
|
swap = (p / 4) == 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
// Check the rest
|
|
for (int i = 0; i < (length / 8) - 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;
|
|
}
|
|
}
|
|
|
|
current = (current << 2) | ((hard_buf[pos] >> (6 - ii)) & 0b11);
|
|
}
|
|
|
|
pos++;
|
|
}
|
|
}
|
|
|
|
cor = correlation;
|
|
return offset;
|
|
} |