mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-12-24 23:09:26 -05:00
Rework BitHistory, BitPattern, PacketBuilder.
Templatize PacketBuilder to optionally bit unstuff, and have flexible packet termination behavior.
This commit is contained in:
parent
0b522abbc1
commit
0789d50fdf
@ -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;
|
|
||||||
}
|
|
||||||
|
@ -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__*/
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -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), "" };
|
||||||
|
@ -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__*/
|
||||||
|
Loading…
Reference in New Issue
Block a user