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

View File

@ -56,8 +56,11 @@ private:
[this](const float symbol) { this->consume_symbol(symbol); } [this](const float symbol) { this->consume_symbol(symbol); }
}; };
symbol_coding::NRZIDecoder nrzi_decode; symbol_coding::NRZIDecoder nrzi_decode;
PacketBuilder packet_builder { PacketBuilder<BitPattern, BitPattern, BitPattern> packet_builder {
[this](const PacketBuilder::PayloadType& payload, const size_t bits_received) { { 0b0101010101111110, 16, 1 },
{ 0b111110, 6 },
{ 0b01111110, 8 },
[this](const payload_t& payload, const size_t bits_received) {
this->payload_handler(payload, 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) { decoded_packet packet_decode(const std::bitset<1024>& payload, const size_t payload_length) {
// TODO: Unstuff here, not in baseband! // 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 ) { if( data_and_fcs_length < 38 ) {
return { "short " + ui::to_string_dec_uint(data_and_fcs_length, 3), "" }; return { "short " + ui::to_string_dec_uint(data_and_fcs_length, 3), "" };

View File

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