mirror of
https://github.com/eried/portapack-mayhem.git
synced 2025-01-12 07:49:32 -05:00
Refactor bit pattern matching.
Remove AccessCodeCorrelator, Unstuff classes.
This commit is contained in:
parent
f918a774b7
commit
36689f5c45
@ -140,7 +140,6 @@ CPPSRC = main.cpp \
|
|||||||
proc_wideband_spectrum.cpp \
|
proc_wideband_spectrum.cpp \
|
||||||
dsp_squelch.cpp \
|
dsp_squelch.cpp \
|
||||||
clock_recovery.cpp \
|
clock_recovery.cpp \
|
||||||
access_code_correlator.cpp \
|
|
||||||
packet_builder.cpp \
|
packet_builder.cpp \
|
||||||
dsp_fft.cpp \
|
dsp_fft.cpp \
|
||||||
dsp_fir_taps.cpp \
|
dsp_fir_taps.cpp \
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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 <cstdint>
|
|
||||||
#include <cstddef>
|
|
||||||
|
|
||||||
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<uint32_t>((1ULL << n) - 1ULL);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif/*__ACCESS_CODE_CORRELATOR_H__*/
|
|
@ -59,7 +59,6 @@
|
|||||||
#include "proc_wideband_spectrum.hpp"
|
#include "proc_wideband_spectrum.hpp"
|
||||||
|
|
||||||
#include "clock_recovery.hpp"
|
#include "clock_recovery.hpp"
|
||||||
#include "access_code_correlator.hpp"
|
|
||||||
#include "packet_builder.hpp"
|
#include "packet_builder.hpp"
|
||||||
|
|
||||||
#include "message_queue.hpp"
|
#include "message_queue.hpp"
|
||||||
|
@ -22,11 +22,12 @@
|
|||||||
#include "packet_builder.hpp"
|
#include "packet_builder.hpp"
|
||||||
|
|
||||||
void PacketBuilder::configure(
|
void PacketBuilder::configure(
|
||||||
uint32_t unstuffing_pattern,
|
const BitPattern preamble,
|
||||||
size_t unstuffing_length,
|
const BitPattern unstuff,
|
||||||
size_t new_payload_length
|
size_t new_payload_length
|
||||||
) {
|
) {
|
||||||
unstuff.configure(unstuffing_pattern, unstuffing_length);
|
preamble_pattern = preamble;
|
||||||
|
unstuff_pattern = unstuff;
|
||||||
|
|
||||||
if( new_payload_length <= payload.size() ) {
|
if( new_payload_length <= payload.size() ) {
|
||||||
payload_length = new_payload_length;
|
payload_length = new_payload_length;
|
||||||
@ -37,6 +38,5 @@ void PacketBuilder::configure(
|
|||||||
|
|
||||||
void PacketBuilder::reset_state() {
|
void PacketBuilder::reset_state() {
|
||||||
bits_received = 0;
|
bits_received = 0;
|
||||||
unstuff.reset();
|
state = State::Preamble;
|
||||||
state = State::AccessCodeSearch;
|
|
||||||
}
|
}
|
||||||
|
@ -26,37 +26,38 @@
|
|||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
|
||||||
#include "symbol_coding.hpp"
|
#include "bit_pattern.hpp"
|
||||||
|
|
||||||
class PacketBuilder {
|
class PacketBuilder {
|
||||||
public:
|
public:
|
||||||
void configure(
|
void configure(
|
||||||
uint32_t unstuffing_pattern,
|
const BitPattern preamble,
|
||||||
size_t unstuffing_length,
|
const BitPattern unstuffing,
|
||||||
size_t new_payload_length
|
size_t new_payload_length
|
||||||
);
|
);
|
||||||
|
|
||||||
template<typename PayloadHandler>
|
template<typename PayloadHandler>
|
||||||
void execute(
|
void execute(
|
||||||
const uint_fast8_t symbol,
|
const uint_fast8_t symbol,
|
||||||
const bool access_code_found,
|
|
||||||
PayloadHandler payload_handler
|
PayloadHandler payload_handler
|
||||||
) {
|
) {
|
||||||
|
bit_history.add(symbol);
|
||||||
|
|
||||||
switch(state) {
|
switch(state) {
|
||||||
case State::AccessCodeSearch:
|
case State::Preamble:
|
||||||
if( access_code_found ) {
|
if( found_preamble() ) {
|
||||||
state = State::Payload;
|
state = State::Payload;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case State::Payload:
|
case State::Payload:
|
||||||
if( bits_received < payload_length ) {
|
if( found_end_flag() || packet_truncated() ) {
|
||||||
if( !unstuff.is_stuffing_bit(symbol) ) {
|
|
||||||
payload[bits_received++] = symbol;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
payload_handler(payload, bits_received);
|
payload_handler(payload, bits_received);
|
||||||
reset_state();
|
reset_state();
|
||||||
|
} else {
|
||||||
|
if( !found_stuffing_bit() ) {
|
||||||
|
payload[bits_received++] = symbol;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -68,15 +69,35 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
enum State {
|
enum State {
|
||||||
AccessCodeSearch,
|
Preamble,
|
||||||
Payload,
|
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 payload_length { 0 };
|
||||||
size_t bits_received { 0 };
|
size_t bits_received { 0 };
|
||||||
State state { State::AccessCodeSearch };
|
State state { State::Preamble };
|
||||||
std::bitset<256> payload;
|
std::bitset<256> payload;
|
||||||
symbol_coding::Unstuff unstuff;
|
|
||||||
|
|
||||||
void reset_state();
|
void reset_state();
|
||||||
};
|
};
|
||||||
|
@ -45,14 +45,9 @@ FSKProcessor::~FSKProcessor() {
|
|||||||
void FSKProcessor::configure(const FSKConfiguration new_configuration) {
|
void FSKProcessor::configure(const FSKConfiguration new_configuration) {
|
||||||
// TODO: Matched filter characteristics are hard-coded for the moment. YUCK!
|
// TODO: Matched filter characteristics are hard-coded for the moment. YUCK!
|
||||||
clock_recovery.configure(sampling_rate / 4, new_configuration.symbol_rate);
|
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(
|
packet_builder.configure(
|
||||||
new_configuration.unstuffing_pattern,
|
{ new_configuration.access_code, new_configuration.access_code_length, new_configuration.access_code_tolerance },
|
||||||
new_configuration.unstuffing_length,
|
{ new_configuration.unstuffing_pattern, new_configuration.unstuffing_length },
|
||||||
new_configuration.packet_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 uint_fast8_t sliced_symbol = (raw_symbol >= 0.0f) ? 1 : 0;
|
||||||
const auto decoded_symbol = nrzi_decode(sliced_symbol);
|
const auto decoded_symbol = nrzi_decode(sliced_symbol);
|
||||||
const bool access_code_found = access_code_correlator(decoded_symbol);
|
|
||||||
|
|
||||||
packet_builder.execute(
|
packet_builder.execute(
|
||||||
decoded_symbol,
|
decoded_symbol,
|
||||||
access_code_found,
|
|
||||||
payload_handler_fn
|
payload_handler_fn
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,6 @@
|
|||||||
|
|
||||||
#include "clock_recovery.hpp"
|
#include "clock_recovery.hpp"
|
||||||
#include "symbol_coding.hpp"
|
#include "symbol_coding.hpp"
|
||||||
#include "access_code_correlator.hpp"
|
|
||||||
#include "packet_builder.hpp"
|
#include "packet_builder.hpp"
|
||||||
|
|
||||||
#include "message.hpp"
|
#include "message.hpp"
|
||||||
@ -85,7 +84,6 @@ 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;
|
||||||
AccessCodeCorrelator access_code_correlator;
|
|
||||||
PacketBuilder packet_builder;
|
PacketBuilder packet_builder;
|
||||||
|
|
||||||
MessageHandlerMap& message_handlers;
|
MessageHandlerMap& message_handlers;
|
||||||
|
@ -39,33 +39,6 @@ private:
|
|||||||
uint_fast8_t last { 0 };
|
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 */
|
} /* namespace symbol_coding */
|
||||||
|
|
||||||
#endif/*__SYMBOL_CODING_H__*/
|
#endif/*__SYMBOL_CODING_H__*/
|
||||||
|
74
firmware/common/bit_pattern.hpp
Normal file
74
firmware/common/bit_pattern.hpp
Normal file
@ -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 <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
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__*/
|
Loading…
Reference in New Issue
Block a user