kopia lustrzana https://github.com/mobilinkd/m17-cxx-demod
Clean up PRBS9 implementation.
rodzic
33af8c4d82
commit
ab54d373b1
|
@ -244,7 +244,7 @@ bool decode_bert(mobilinkd::M17FrameDecoder::bert_buffer_t const& bert)
|
|||
for (int j = 0; j != 24; ++j) {
|
||||
auto b = bert[j];
|
||||
for (int i = 0; i != 8; ++i) {
|
||||
prbs(b & 0x80);
|
||||
prbs.validate(b & 0x80);
|
||||
b <<= 1;
|
||||
}
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ bool decode_bert(mobilinkd::M17FrameDecoder::bert_buffer_t const& bert)
|
|||
auto b = bert[24];
|
||||
for (int i = 0; i != 5; ++i)
|
||||
{
|
||||
prbs(b & 0x80);
|
||||
prbs.validate(b & 0x80);
|
||||
b <<= 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -436,7 +436,7 @@ bitstream_t make_bert_frame(PRBS& prbs)
|
|||
uint8_t byte = 0;
|
||||
for (int i = 0; i != 8; ++i) {
|
||||
byte <<= 1;
|
||||
byte |= prbs();
|
||||
byte |= prbs.generate();
|
||||
}
|
||||
data[i] = byte;
|
||||
}
|
||||
|
@ -444,7 +444,7 @@ bitstream_t make_bert_frame(PRBS& prbs)
|
|||
uint8_t byte = 0;
|
||||
for (int i = 0; i != 5; ++i) {
|
||||
byte <<= 1;
|
||||
byte |= prbs();
|
||||
byte |= prbs.generate();
|
||||
}
|
||||
byte <<= 3;
|
||||
data[24] = byte;
|
||||
|
|
|
@ -322,6 +322,7 @@ struct PRBS9
|
|||
static constexpr uint8_t TAP_1 = 8; // Bit 9
|
||||
static constexpr uint8_t TAP_2 = 4; // Bit 5
|
||||
static constexpr uint8_t LOCK_COUNT = 18; // 18 consecutive good bits.
|
||||
static constexpr uint8_t UNLOCK_COUNT = 25; // 18 consecutive good bits.
|
||||
|
||||
uint16_t state = 1;
|
||||
bool synced = false;
|
||||
|
@ -332,69 +333,67 @@ struct PRBS9
|
|||
size_t hist_count = 0;
|
||||
size_t hist_pos = 0;
|
||||
|
||||
void count_errors(bool error)
|
||||
{
|
||||
bit_count += 1;
|
||||
hist_count -= (history[hist_pos >> 3] & (1 << (hist_pos & 7))) != 0;
|
||||
if (error) {
|
||||
err_count += 1;
|
||||
hist_count += 1;
|
||||
history[hist_pos >> 3] |= (1 << (hist_pos & 7));
|
||||
if (hist_count >= UNLOCK_COUNT) synced = false;
|
||||
} else {
|
||||
history[hist_pos >> 3] &= ~(1 << (hist_pos & 7));
|
||||
}
|
||||
if (++hist_pos == 128) hist_pos = 0;
|
||||
}
|
||||
|
||||
// PRBS generator.
|
||||
bool operator()()
|
||||
bool generate()
|
||||
{
|
||||
bool result = ((state >> TAP_1) ^ (state >> TAP_2)) & 1;
|
||||
state = ((state << 1) | result) & MASK;
|
||||
return result;
|
||||
}
|
||||
|
||||
// PRBS validator.
|
||||
bool operator()(bool bit)
|
||||
// PRBS Syncronizer. Returns 0 if the bit matches the PRBS, otherwise 1.
|
||||
// When synchronizing the LFSR used in the PRBS, a single bad input bit will
|
||||
// result in 3 error bits being emitted.
|
||||
bool synchronize(bool bit)
|
||||
{
|
||||
bool result;
|
||||
if (!synced) {
|
||||
// Need to sync the PRBS with the incoming data.
|
||||
result = (bit ^ (state >> TAP_1) ^ (state >> TAP_2)) & 1;
|
||||
bool result = (bit ^ (state >> TAP_1) ^ (state >> TAP_2)) & 1;
|
||||
state = ((state << 1) | bit) & MASK;
|
||||
if (result) {
|
||||
sync_count = 0; // error
|
||||
} else {
|
||||
if (++sync_count == LOCK_COUNT) {
|
||||
synced = true;
|
||||
err_count = 0;
|
||||
bit_count = LOCK_COUNT;
|
||||
bit_count += LOCK_COUNT;
|
||||
history.fill(0);
|
||||
hist_count = 0;
|
||||
hist_pos = 0;
|
||||
sync_count = 0;
|
||||
}
|
||||
}
|
||||
} else if (hist_count > 25) {
|
||||
result = (bit ^ (state >> TAP_1) ^ (state >> TAP_2)) & 1;
|
||||
state = ((state << 1) | bit) & MASK;
|
||||
if (result) {
|
||||
sync_count = 0;
|
||||
} else {
|
||||
if (++sync_count == LOCK_COUNT) {
|
||||
history.fill(0);
|
||||
hist_count = 0;
|
||||
hist_pos = 0;
|
||||
sync_count = 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// PRBS validator. Returns 0 if the bit matches the PRBS, otherwise 1.
|
||||
// The results are only valid when sync() returns true;
|
||||
bool validate(bool bit)
|
||||
{
|
||||
bool result;
|
||||
if (!synced) {
|
||||
result = synchronize(bit);
|
||||
} else {
|
||||
// PRBS is now free-running.
|
||||
result = ((state >> TAP_1) ^ (state >> TAP_2)) & 1;
|
||||
state = ((state << 1) | result) & MASK;
|
||||
|
||||
bit_count += 1;
|
||||
hist_count -= (history[hist_pos >> 3] & (1 << (hist_pos & 7))) != 0;
|
||||
if (result != bit) {
|
||||
err_count += 1;
|
||||
hist_count += 1;
|
||||
history[hist_pos >> 3] |= (1 << (hist_pos & 7));
|
||||
} else {
|
||||
history[hist_pos >> 3] &= ~(1 << (hist_pos & 7));
|
||||
}
|
||||
if (++hist_pos == 128) hist_pos = 0;
|
||||
result = bit != generate();
|
||||
count_errors(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool sync() const { return synced; }
|
||||
|
||||
uint32_t errors() const { assert(synced); return err_count; }
|
||||
uint32_t bits() const { assert(synced); return bit_count; }
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ TEST_F(UtilTest, PRBS9)
|
|||
for (size_t i = 0; i != 511; ++i) {
|
||||
lfsr = ((__builtin_popcount(lfsr & 0x11) & 1) << 8) | (lfsr >> 1);
|
||||
bool p = (lfsr & 0x100) == 0x100;
|
||||
bool n = prbs();
|
||||
bool n = prbs.generate();
|
||||
EXPECT_EQ(p,n) << "i = " << i;
|
||||
}
|
||||
}
|
||||
|
@ -227,7 +227,7 @@ TEST_F(UtilTest, PRBS9_FULL)
|
|||
uint16_t byte = 0;
|
||||
uint16_t bits = 0;
|
||||
for (size_t i = 0; i != 1000; ++i) {
|
||||
bool n = prbs_generator();
|
||||
bool n = prbs_generator.generate();
|
||||
byte <<= 1;
|
||||
byte |= n;
|
||||
if (++bits == 8) {
|
||||
|
@ -238,7 +238,7 @@ TEST_F(UtilTest, PRBS9_FULL)
|
|||
|
||||
if (i == 499) n = !n;
|
||||
else if (i == 510) n = !n;
|
||||
prbs_validator(n);
|
||||
prbs_validator.validate(n);
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
|
|
Ładowanie…
Reference in New Issue