diff --git a/apps/m17-demod.cpp b/apps/m17-demod.cpp index 92dc952..93df08c 100644 --- a/apps/m17-demod.cpp +++ b/apps/m17-demod.cpp @@ -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; } diff --git a/apps/m17-mod.cpp b/apps/m17-mod.cpp index f386457..e8dee6e 100644 --- a/apps/m17-mod.cpp +++ b/apps/m17-mod.cpp @@ -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; diff --git a/include/m17cxx/Util.h b/include/m17cxx/Util.h index 510eb1c..e734974 100644 --- a/include/m17cxx/Util.h +++ b/include/m17cxx/Util.h @@ -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 = (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; + bit_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) { - // Need to sync the PRBS with the incoming data. - 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; - 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; - } - } + 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; } diff --git a/tests/UtilTest.cpp b/tests/UtilTest.cpp index 6c89937..6af1784 100644 --- a/tests/UtilTest.cpp +++ b/tests/UtilTest.cpp @@ -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;