Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

flexdec

A pure-Python FLEX paging protocol decoder library. It consumes FM-demodulated audio at 22050 Hz (mono float32, e.g. the output of rtl_fm -M fm -s 22050) and emits decoded pager messages.

The decoder is heavily based on multimon-ng's demod_flex.c — the symbol recovery, sync detection, deinterleaving, and message parsing logic were ported from that C implementation. This port fixes several bugs that affect real-world message recovery (see below) and packages the decoder as a reusable Python library.

Quick start

from flexdec import FlexDecoder

decoder = FlexDecoder(sample_rate=22050)

# feed() accepts any iterable of float samples in [-1, 1]
for msg in decoder.feed(audio_samples):
    print(f"[{msg.baud}/{msg.levels}] capcode={msg.capcode} "
          f"type={msg.kind} body={msg.body}")

# Decoder state is available at any time
print(decoder.stats.locked, decoder.stats.frames_decoded)

feed() returns a list of FlexMessage objects. You can also pass a callback via on_message= to receive messages as they are decoded.

Each FlexMessage contains: capcode, kind ("ALN", "NUM", "TON", "UNK"), body, baud, levels, phase, cycleno, frameno, frag_flag, and BCH error counts.

Installation

pip install git+https://github.com/lmore377-aiexp/flexdec.git

Requires Python >= 3.11 and numpy >= 1.26. For development (tests):

pip install "flexdec[dev] @ git+https://github.com/lmore377-aiexp/flexdec.git"

Supported FLEX modes

Sync code Baud Levels
0x870C 1600 2
0xB068 1600 4
0x7B18 3200 2
0xDEA0 3200 4
0x4C7C 3200 4

The decoder has been tested off-air against multimon-ng in 3200/4 mode.

Bug fixes vs multimon-ng

This port fixes several bugs in multimon-ng's demod_flex.c:

  1. Early return on BCH failure (high severity) -- multimon-ng abandons an entire phase on the first uncorrectable codeword, silently truncating all remaining messages in that phase. flexdec marks bad codewords individually and decodes everything else.

  2. cycleno++ mutation (medium) -- a post-increment side effect corrupts the FIW cycle number mid-frame, producing wrong cycle/frame labels on emitted messages.

  3. Long-address capcodes are wrong (medium) -- the two-word long-address path is commented out upstream; capcodes above 0x1E0000 are decoded incorrectly by both decoders (fix is TODO here too).

  4. Lock flag never clears (medium) -- once locked, multimon-ng stays "locked" forever even on pure noise. flexdec adds a watchdog that drops the lock after ~4 frame periods without a valid FIW.

  5. Aggressive idle detection (low) -- bailing on the first all-zero codeword can theoretically lose binary-payload messages.

Full details with code examples and suggested upstream patches are in UPSTREAM_BUGS.md. (Note: this was written entirely by Claude and this doc might not actually be accurate. I still need to test the stuff in there)

License

This library is licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later), as it is derived from multimon-ng's GPL-v3-licensed demod_flex.c.

The BCH error-correction module (bch.py) is ported from multimon-ng's bch.c, which is released into the public domain (Unlicense).

About

FLEX paging protocol decoder library

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages