From 36689f5c457b4738c41fa37c3045d0d71c6d787b Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 28 Sep 2015 12:05:36 -0700 Subject: [PATCH] Refactor bit pattern matching. Remove AccessCodeCorrelator, Unstuff classes. --- firmware/baseband/Makefile | 1 - firmware/baseband/access_code_correlator.cpp | 34 --------- firmware/baseband/access_code_correlator.hpp | 57 --------------- firmware/baseband/main.cpp | 1 - firmware/baseband/packet_builder.cpp | 10 +-- firmware/baseband/packet_builder.hpp | 49 +++++++++---- firmware/baseband/proc_fsk.cpp | 11 +-- firmware/baseband/proc_fsk.hpp | 2 - firmware/baseband/symbol_coding.hpp | 27 ------- firmware/common/bit_pattern.hpp | 74 ++++++++++++++++++++ 10 files changed, 116 insertions(+), 150 deletions(-) delete mode 100644 firmware/baseband/access_code_correlator.cpp delete mode 100644 firmware/baseband/access_code_correlator.hpp create mode 100644 firmware/common/bit_pattern.hpp diff --git a/firmware/baseband/Makefile b/firmware/baseband/Makefile index b92cf0c8..6bf1b1fc 100755 --- a/firmware/baseband/Makefile +++ b/firmware/baseband/Makefile @@ -140,7 +140,6 @@ CPPSRC = main.cpp \ proc_wideband_spectrum.cpp \ dsp_squelch.cpp \ clock_recovery.cpp \ - access_code_correlator.cpp \ packet_builder.cpp \ dsp_fft.cpp \ dsp_fir_taps.cpp \ diff --git a/firmware/baseband/access_code_correlator.cpp b/firmware/baseband/access_code_correlator.cpp deleted file mode 100644 index 654983e9..00000000 --- a/firmware/baseband/access_code_correlator.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. - * - * This file is part of PortaPack. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#include "access_code_correlator.hpp" - -void AccessCodeCorrelator::configure( - const uint32_t new_code, - const size_t new_code_length, - const size_t new_maximum_hamming_distance -) { - if( new_code_length <= 32 ) { - code = new_code; - mask = mask_value(new_code_length); - maximum_hamming_distance = new_maximum_hamming_distance; - } -} diff --git a/firmware/baseband/access_code_correlator.hpp b/firmware/baseband/access_code_correlator.hpp deleted file mode 100644 index e1e447f4..00000000 --- a/firmware/baseband/access_code_correlator.hpp +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc. - * - * This file is part of PortaPack. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Street, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __ACCESS_CODE_CORRELATOR_H__ -#define __ACCESS_CODE_CORRELATOR_H__ - -#include -#include - -class AccessCodeCorrelator { -public: - void configure( - const uint32_t new_code, - const size_t new_code_length, - const size_t new_maximum_hamming_distance - ); - - bool operator()( - const uint_fast8_t in - ) { - history = (history << 1) | (in & 1); - const auto delta_bits = (history ^ code) & mask; - //const size_t count = __builtin_popcountll(delta_bits); - const size_t count = __builtin_popcountl(delta_bits); - return (count <= maximum_hamming_distance); - } - -private: - uint32_t code { 0 }; - uint32_t mask { 0 }; - uint32_t history { 0 }; - size_t maximum_hamming_distance { 0 }; - - static constexpr uint32_t mask_value(const size_t n) { - return static_cast((1ULL << n) - 1ULL); - } -}; - -#endif/*__ACCESS_CODE_CORRELATOR_H__*/ diff --git a/firmware/baseband/main.cpp b/firmware/baseband/main.cpp index badadb6c..3c167110 100755 --- a/firmware/baseband/main.cpp +++ b/firmware/baseband/main.cpp @@ -59,7 +59,6 @@ #include "proc_wideband_spectrum.hpp" #include "clock_recovery.hpp" -#include "access_code_correlator.hpp" #include "packet_builder.hpp" #include "message_queue.hpp" diff --git a/firmware/baseband/packet_builder.cpp b/firmware/baseband/packet_builder.cpp index 94bc3401..cacfb72d 100644 --- a/firmware/baseband/packet_builder.cpp +++ b/firmware/baseband/packet_builder.cpp @@ -22,11 +22,12 @@ #include "packet_builder.hpp" void PacketBuilder::configure( - uint32_t unstuffing_pattern, - size_t unstuffing_length, + const BitPattern preamble, + const BitPattern unstuff, size_t new_payload_length ) { - unstuff.configure(unstuffing_pattern, unstuffing_length); + preamble_pattern = preamble; + unstuff_pattern = unstuff; if( new_payload_length <= payload.size() ) { payload_length = new_payload_length; @@ -37,6 +38,5 @@ void PacketBuilder::configure( void PacketBuilder::reset_state() { bits_received = 0; - unstuff.reset(); - state = State::AccessCodeSearch; + state = State::Preamble; } diff --git a/firmware/baseband/packet_builder.hpp b/firmware/baseband/packet_builder.hpp index dd2bd202..618fc849 100644 --- a/firmware/baseband/packet_builder.hpp +++ b/firmware/baseband/packet_builder.hpp @@ -26,37 +26,38 @@ #include #include -#include "symbol_coding.hpp" +#include "bit_pattern.hpp" class PacketBuilder { public: void configure( - uint32_t unstuffing_pattern, - size_t unstuffing_length, + const BitPattern preamble, + const BitPattern unstuffing, size_t new_payload_length ); template void execute( const uint_fast8_t symbol, - const bool access_code_found, PayloadHandler payload_handler ) { + bit_history.add(symbol); + switch(state) { - case State::AccessCodeSearch: - if( access_code_found ) { + case State::Preamble: + if( found_preamble() ) { state = State::Payload; } break; case State::Payload: - if( bits_received < payload_length ) { - if( !unstuff.is_stuffing_bit(symbol) ) { - payload[bits_received++] = symbol; - } - } else { + if( found_end_flag() || packet_truncated() ) { payload_handler(payload, bits_received); reset_state(); + } else { + if( !found_stuffing_bit() ) { + payload[bits_received++] = symbol; + } } break; @@ -68,15 +69,35 @@ public: private: enum State { - AccessCodeSearch, + Preamble, Payload, }; + bool packet_truncated() const { + 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); + } + + BitHistory bit_history; + BitPattern preamble_pattern { 0b01010101010101010101111110, 26, 1 }; + BitPattern unstuff_pattern { 0b111110, 6 }; + BitPattern end_flag_pattern { 0b01111110, 8 }; + size_t payload_length { 0 }; size_t bits_received { 0 }; - State state { State::AccessCodeSearch }; + State state { State::Preamble }; std::bitset<256> payload; - symbol_coding::Unstuff unstuff; void reset_state(); }; diff --git a/firmware/baseband/proc_fsk.cpp b/firmware/baseband/proc_fsk.cpp index 889d3e23..d169906c 100644 --- a/firmware/baseband/proc_fsk.cpp +++ b/firmware/baseband/proc_fsk.cpp @@ -45,14 +45,9 @@ FSKProcessor::~FSKProcessor() { void FSKProcessor::configure(const FSKConfiguration new_configuration) { // TODO: Matched filter characteristics are hard-coded for the moment. YUCK! clock_recovery.configure(sampling_rate / 4, new_configuration.symbol_rate); - access_code_correlator.configure( - new_configuration.access_code, - new_configuration.access_code_length, - new_configuration.access_code_tolerance - ); packet_builder.configure( - new_configuration.unstuffing_pattern, - new_configuration.unstuffing_length, + { new_configuration.access_code, new_configuration.access_code_length, new_configuration.access_code_tolerance }, + { new_configuration.unstuffing_pattern, new_configuration.unstuffing_length }, new_configuration.packet_length ); } @@ -117,11 +112,9 @@ void FSKProcessor::consume_symbol( const uint_fast8_t sliced_symbol = (raw_symbol >= 0.0f) ? 1 : 0; const auto decoded_symbol = nrzi_decode(sliced_symbol); - const bool access_code_found = access_code_correlator(decoded_symbol); packet_builder.execute( decoded_symbol, - access_code_found, payload_handler_fn ); } diff --git a/firmware/baseband/proc_fsk.hpp b/firmware/baseband/proc_fsk.hpp index 8a675732..b6b2da89 100644 --- a/firmware/baseband/proc_fsk.hpp +++ b/firmware/baseband/proc_fsk.hpp @@ -31,7 +31,6 @@ #include "clock_recovery.hpp" #include "symbol_coding.hpp" -#include "access_code_correlator.hpp" #include "packet_builder.hpp" #include "message.hpp" @@ -85,7 +84,6 @@ private: [this](const float symbol) { this->consume_symbol(symbol); } }; symbol_coding::NRZIDecoder nrzi_decode; - AccessCodeCorrelator access_code_correlator; PacketBuilder packet_builder; MessageHandlerMap& message_handlers; diff --git a/firmware/baseband/symbol_coding.hpp b/firmware/baseband/symbol_coding.hpp index f13965a9..03a42455 100644 --- a/firmware/baseband/symbol_coding.hpp +++ b/firmware/baseband/symbol_coding.hpp @@ -39,33 +39,6 @@ private: uint_fast8_t last { 0 }; }; -class Unstuff { -public: - uint_fast8_t is_stuffing_bit(const uint_fast8_t symbol) { - history = (history << 1) | (symbol & 1); - return (history & mask) == match; - } - - void configure( - const uint32_t pattern, - const size_t length - ) { - // Ensure that length=0 (unstuffing disabled) never matches. - match = length ? pattern : 1; - mask = (1U << length) - 1; - reset(); - } - - void reset() { - history = 0; - } - -private: - uint32_t history { 0 }; - uint32_t match { 0b111110 }; - uint32_t mask { 0b111111 }; -}; - } /* namespace symbol_coding */ #endif/*__SYMBOL_CODING_H__*/ diff --git a/firmware/common/bit_pattern.hpp b/firmware/common/bit_pattern.hpp new file mode 100644 index 00000000..43726c34 --- /dev/null +++ b/firmware/common/bit_pattern.hpp @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc. + * + * This file is part of PortaPack. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef __BIT_PATTERN_H__ +#define __BIT_PATTERN_H__ + +#include +#include + +class BitPattern { +public: + constexpr BitPattern( + const uint32_t code, + const size_t code_length, + const size_t maximum_hanning_distance = 0 + ) : code_ { code }, + mask_ { (1UL << code_length) - 1UL }, + maximum_hanning_distance_ { maximum_hanning_distance } + { + } + + uint32_t code() const { + return code_; + } + + uint32_t mask() const { + return mask_; + } + + size_t maximum_hanning_distance() const { + return maximum_hanning_distance_; + } + +private: + uint32_t code_; + uint32_t mask_; + 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__*/