Rework BitHistory, BitPattern, PacketBuilder.

Templatize PacketBuilder to optionally bit unstuff, and have flexible packet termination behavior.
This commit is contained in:
Jared Boone 2015-11-09 14:38:09 -08:00
parent 0b522abbc1
commit 0789d50fdf
5 changed files with 59 additions and 69 deletions

View File

@ -20,18 +20,3 @@
*/
#include "packet_builder.hpp"
void PacketBuilder::configure(
const BitPattern preamble,
const BitPattern unstuff
) {
preamble_pattern = preamble;
unstuff_pattern = unstuff;
reset_state();
}
void PacketBuilder::reset_state() {
bits_received = 0;
state = State::Preamble;
}

View File

@ -29,21 +29,33 @@
#include "bit_pattern.hpp"
template<typename PreambleMatcher, typename UnstuffMatcher, typename EndMatcher>
class PacketBuilder {
public:
using PayloadType = std::bitset<1024>;
using PayloadHandlerFunc = std::function<void(const PayloadType& payload, const size_t bits_received)>;
PacketBuilder(
const PreambleMatcher preamble_matcher,
const UnstuffMatcher unstuff_matcher,
const EndMatcher end_matcher,
const PayloadHandlerFunc payload_handler
) : payload_handler { payload_handler }
) : payload_handler { payload_handler },
preamble(preamble_matcher),
unstuff(unstuff_matcher),
end(end_matcher)
{
}
void configure(
const BitPattern preamble,
const BitPattern unstuffing
);
const PreambleMatcher preamble_matcher,
const UnstuffMatcher unstuff_matcher
) {
preamble = preamble_matcher;
unstuff = unstuff_matcher;
reset_state();
}
void execute(
const uint_fast8_t symbol
@ -52,25 +64,24 @@ public:
switch(state) {
case State::Preamble:
if( found_preamble() ) {
if( preamble(bit_history, bits_received) ) {
state = State::Payload;
}
break;
case State::Payload:
if( !found_stuffing_bit() ) {
if( !unstuff(bit_history, bits_received) ) {
payload[bits_received++] = symbol;
}
if( found_end_flag() ) {
payload_handler(payload, bits_received - 7);
if( end(bit_history, bits_received) ) {
payload_handler(payload, bits_received);
reset_state();
} else {
if( packet_truncated() ) {
reset_state();
}
}
break;
default:
@ -89,30 +100,21 @@ private:
return bits_received >= payload.size();
}
bool found_preamble() const {
return bit_history.matches(preamble_pattern);
}
bool found_stuffing_bit() const {
return bit_history.matches(unstuff_pattern);
}
bool found_end_flag() const {
return bit_history.matches(end_flag_pattern);
}
const PayloadHandlerFunc payload_handler;
BitHistory bit_history;
BitPattern preamble_pattern { 0b0101010101111110, 16, 1 };
BitPattern unstuff_pattern { 0b111110, 6 };
BitPattern end_flag_pattern { 0b01111110, 8 };
PreambleMatcher preamble;
UnstuffMatcher unstuff;
EndMatcher end;
size_t bits_received { 0 };
State state { State::Preamble };
PayloadType payload;
void reset_state();
void reset_state() {
bits_received = 0;
state = State::Preamble;
}
};
#endif/*__PACKET_BUILDER_H__*/

View File

@ -56,8 +56,11 @@ private:
[this](const float symbol) { this->consume_symbol(symbol); }
};
symbol_coding::NRZIDecoder nrzi_decode;
PacketBuilder packet_builder {
[this](const PacketBuilder::PayloadType& payload, const size_t bits_received) {
PacketBuilder<BitPattern, BitPattern, BitPattern> packet_builder {
{ 0b0101010101111110, 16, 1 },
{ 0b111110, 6 },
{ 0b01111110, 8 },
[this](const payload_t& payload, const size_t bits_received) {
this->payload_handler(payload, bits_received);
}
};

View File

@ -299,7 +299,8 @@ static std::string ais_format_navigational_status(const unsigned int value) {
decoded_packet packet_decode(const std::bitset<1024>& payload, const size_t payload_length) {
// TODO: Unstuff here, not in baseband!
const size_t data_and_fcs_length = payload_length;
// Subtract end flag (6 bits) + one unstuffing bit (occurs during end flag).
const size_t data_and_fcs_length = payload_length - 7;
if( data_and_fcs_length < 38 ) {
return { "short " + ui::to_string_dec_uint(data_and_fcs_length, 3), "" };

View File

@ -25,8 +25,29 @@
#include <cstdint>
#include <cstddef>
class BitHistory {
public:
void add(const uint_fast8_t bit) {
history = (history << 1) | (bit & 1);
}
uint32_t value() const {
return history;
}
private:
uint32_t history { 0 };
};
class BitPattern {
public:
constexpr BitPattern(
) : code_ { 0 },
mask_ { 0 },
maximum_hanning_distance_ { 0 }
{
}
constexpr BitPattern(
const uint32_t code,
const size_t code_length,
@ -37,16 +58,10 @@ public:
{
}
uint32_t code() const {
return code_;
}
uint32_t mask() const {
return mask_;
}
size_t maximum_hanning_distance() const {
return maximum_hanning_distance_;
bool operator()(const BitHistory& history, const size_t) const {
const auto delta_bits = (history.value() ^ code_) & mask_;
const size_t count = __builtin_popcountl(delta_bits);
return (count <= maximum_hanning_distance_);
}
private:
@ -55,20 +70,4 @@ private:
size_t maximum_hanning_distance_;
};
class BitHistory {
public:
void add(const uint_fast8_t bit) {
history = (history << 1) | (bit & 1);
}
bool matches(const BitPattern& pattern) const {
const auto delta_bits = (history ^ pattern.code()) & pattern.mask();
const size_t count = __builtin_popcountl(delta_bits);
return (count <= pattern.maximum_hanning_distance());
}
private:
uint32_t history { 0 };
};
#endif/*__BIT_PATTERN_H__*/