mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2026-09-10 16:49:36 +00:00
POCSAG: show '?' for characters from uncorrectable codewords (#3138)
Use per-character error tracking to substitute '?' when a character's bits came from an uncorrectable codeword (BCH error_count >= 3). Previously these displayed as garbage.
This commit is contained in:
@@ -282,8 +282,9 @@ void POCSAGAppView::handle_decoded(Timestamp timestamp, const std::string& prefi
|
|||||||
|
|
||||||
/* Serial: header + first chunk.
|
/* Serial: header + first chunk.
|
||||||
* hex field contains rendered alpha as hex bytes (color escapes
|
* hex field contains rendered alpha as hex bytes (color escapes
|
||||||
* stripped). Non-printable and uncorrectable chars show as '.'
|
* stripped). Non-printable chars show as '.' (0x2E),
|
||||||
* (0x2E) — original 7-bit values are not preserved.
|
* uncorrectable chars show as '?' (0x3F) — original 7-bit
|
||||||
|
* values are not preserved.
|
||||||
* Numeric decode goes in the quoted message field only. */
|
* Numeric decode goes in the quoted message field only. */
|
||||||
if (portapack::usb_serial.serial_connected()) {
|
if (portapack::usb_serial.serial_connected()) {
|
||||||
/* Build hex representation of decoded alpha characters. */
|
/* Build hex representation of decoded alpha characters. */
|
||||||
|
|||||||
@@ -537,6 +537,9 @@ bool pocsag_decode_batch(const POCSAGPacket& batch, POCSAGState& state) {
|
|||||||
uint8_t msg_codewords = 0;
|
uint8_t msg_codewords = 0;
|
||||||
// Also build raw alpha for heuristic (before non-printable replacement).
|
// Also build raw alpha for heuristic (before non-printable replacement).
|
||||||
std::string raw_alpha{};
|
std::string raw_alpha{};
|
||||||
|
// Track whether any characters came from uncorrectable codewords.
|
||||||
|
// If so, heuristic scoring is unreliable — skip it and default to alpha.
|
||||||
|
bool has_bad_chars = false;
|
||||||
|
|
||||||
while (state.codeword_index < codeword_max) {
|
while (state.codeword_index < codeword_max) {
|
||||||
auto codeword = batch[state.codeword_index];
|
auto codeword = batch[state.codeword_index];
|
||||||
@@ -578,7 +581,9 @@ bool pocsag_decode_batch(const POCSAGPacket& batch, POCSAGState& state) {
|
|||||||
if (is_address) {
|
if (is_address) {
|
||||||
// Got another address. Run heuristic before returning if we have pending data.
|
// Got another address. Run heuristic before returning if we have pending data.
|
||||||
if (!state.type_decided && msg_codewords > 0) {
|
if (!state.type_decided && msg_codewords > 0) {
|
||||||
state.detected = detect_message_type(raw_alpha, nibbles, nibble_count, msg_codewords);
|
state.detected = has_bad_chars
|
||||||
|
? DET_ALPHA
|
||||||
|
: detect_message_type(raw_alpha, nibbles, nibble_count, msg_codewords);
|
||||||
state.type_decided = true;
|
state.type_decided = true;
|
||||||
state.msg_codewords = msg_codewords;
|
state.msg_codewords = msg_codewords;
|
||||||
if (state.detected == DET_NUMERIC) {
|
if (state.detected == DET_NUMERIC) {
|
||||||
@@ -600,7 +605,9 @@ bool pocsag_decode_batch(const POCSAGPacket& batch, POCSAGState& state) {
|
|||||||
if (is_address) {
|
if (is_address) {
|
||||||
// Message ended. Run heuristic before returning.
|
// Message ended. Run heuristic before returning.
|
||||||
if (!state.type_decided && msg_codewords > 0) {
|
if (!state.type_decided && msg_codewords > 0) {
|
||||||
state.detected = detect_message_type(raw_alpha, nibbles, nibble_count, msg_codewords);
|
state.detected = has_bad_chars
|
||||||
|
? DET_ALPHA
|
||||||
|
: detect_message_type(raw_alpha, nibbles, nibble_count, msg_codewords);
|
||||||
state.type_decided = true;
|
state.type_decided = true;
|
||||||
state.msg_codewords = msg_codewords;
|
state.msg_codewords = msg_codewords;
|
||||||
if (state.detected == DET_NUMERIC) {
|
if (state.detected == DET_NUMERIC) {
|
||||||
@@ -632,9 +639,8 @@ bool pocsag_decode_batch(const POCSAGPacket& batch, POCSAGState& state) {
|
|||||||
state.ascii_idx += 20;
|
state.ascii_idx += 20;
|
||||||
|
|
||||||
while (state.ascii_idx >= 7) {
|
while (state.ascii_idx >= 7) {
|
||||||
// Determine error level for this character.
|
// Per-character error level from codeword error tracking.
|
||||||
// If some bits came from previous codeword and some from current,
|
// Characters spanning a codeword boundary get the worst level.
|
||||||
// use the worst of both error levels.
|
|
||||||
uint8_t char_err;
|
uint8_t char_err;
|
||||||
if (bits_from_prev >= 7) {
|
if (bits_from_prev >= 7) {
|
||||||
// Entire character from previous codeword's leftover bits.
|
// Entire character from previous codeword's leftover bits.
|
||||||
@@ -663,8 +669,11 @@ bool pocsag_decode_batch(const POCSAGPacket& batch, POCSAGState& state) {
|
|||||||
if (!state.type_decided)
|
if (!state.type_decided)
|
||||||
raw_alpha += ascii_char;
|
raw_alpha += ascii_char;
|
||||||
|
|
||||||
// Translate non-printable chars.
|
// Substitute '?' for characters from uncorrectable codewords
|
||||||
if (ascii_char < 32 || ascii_char > 126)
|
if (char_err >= 3) {
|
||||||
|
state.output += "?";
|
||||||
|
has_bad_chars = true;
|
||||||
|
} else if (ascii_char < 32 || ascii_char > 126)
|
||||||
state.output += ".";
|
state.output += ".";
|
||||||
else
|
else
|
||||||
state.output += ascii_char;
|
state.output += ascii_char;
|
||||||
@@ -694,7 +703,9 @@ bool pocsag_decode_batch(const POCSAGPacket& batch, POCSAGState& state) {
|
|||||||
|
|
||||||
// End of batch. If we have message data and type not yet decided, run heuristic.
|
// End of batch. If we have message data and type not yet decided, run heuristic.
|
||||||
if (state.out_type == MESSAGE && !state.type_decided && msg_codewords > 0) {
|
if (state.out_type == MESSAGE && !state.type_decided && msg_codewords > 0) {
|
||||||
state.detected = detect_message_type(raw_alpha, nibbles, nibble_count, msg_codewords);
|
state.detected = has_bad_chars
|
||||||
|
? DET_ALPHA
|
||||||
|
: detect_message_type(raw_alpha, nibbles, nibble_count, msg_codewords);
|
||||||
state.type_decided = true;
|
state.type_decided = true;
|
||||||
state.msg_codewords = msg_codewords;
|
state.msg_codewords = msg_codewords;
|
||||||
if (state.detected == DET_NUMERIC) {
|
if (state.detected == DET_NUMERIC) {
|
||||||
|
|||||||
Reference in New Issue
Block a user