Code table
Defines acceptable timing ranges for warm-up/synchronization and the interpretation of pulse lengths during message decoding.
ACARSd’s production decoder used a lightweight, empirical strategy: repeated passes over PCM audio, multiple timing code tables, message validation and automatic reordering of the strategies that worked best on a particular receiver chain.
The recovered libacarsd2 source preserves the preamble literally as {'*',0x16,0x16,0x01}. Hex 0x16 is SYN and 0x01 is SOH. A second accepted preamble contains four SYN characters before SOH.
The production path walks the PCM stream sample by sample and observes meaningful changes in signal direction. The number of samples between those transitions becomes a cheap proxy for the signal’s timing structure.
That avoids performing a Fourier transform on every analysis window. For early-2000s hardware, the difference mattered: the same computer could decode several receiver channels in real time.
if (signal changes direction) {
halfwave_length = samples_between_changes;
chkContent(..., halfwave_length, ...);
}Analog scanner audio is messy. Levels, filters, sound cards and noise differ. ACARSd therefore did not demand one mathematically perfect waveform. It tried several interpretations cheaply and let message structure and CRC decide which one was credible.
LOW CPUREAL AUDIOMULTI-PASSThe library maintains multiple threshold tables. Each table represents a slightly different set of timing decisions. A second dimension — the decoder pass — changes the sensitivity used to recognize a transition in the PCM signal.
Defines acceptable timing ranges for warm-up/synchronization and the interpretation of pulse lengths during message decoding.
Changes the threshold at which an amplitude change is considered significant, helping with quiet, distorted or noisy recordings.
Candidate frames are checked against synchronization, field plausibility, parity and CRC. The winning decode is selected by confidence rather than by signal guess alone.
Successful tables incremented per-table counters. acarsd_sorttables() then reordered the tables so the combinations that worked best on a particular station were tried earlier.
Lib->acarsd_utable[codeT]++; ... acarsd_sorttables(Lib);
This is not machine learning in the modern sense. It is a very effective adaptive heuristic: optimize the search order using the observed success rate of the real installation.
The source itself explains the goal. Accuracy was gained by trying alternatives; speed was recovered by learning which alternatives usually succeeded first.
When ANAD decoded audio that ACARSd missed, a special build saved the failed sound. Those recordings became real-world examples against which the decoder could be improved. The library also contains a “learn” path that sweeps parameter combinations and records successful settings.
decode_buffer_learn(...)
vary timing parameters
decode the same captured audio
if successful:
write combination to /tmp/success.txt
update successful min/max rangesThe famous contemporary comparison documented on acarsd.org: “ANAD 137 — ACARSd 169 in one hour.”
The RCS archive contains FFT routines and functions such as ACARS_Decoder_FFT(). Their surrounding code contains debug-oriented behavior and experimental scaffolding. The mature production path is the code-table/multi-pass decoder.
This matches the project story: FFTW was suggested early, but the successful system came from empirically understanding the actual waveform and building a decoder around what worked.
A theoretically elegant approach is not automatically the most robust approach on inexpensive receivers, analog audio paths and early-2000s CPUs. ACARSd traded a little redundant work for fault tolerance.
Stereo audio is interleaved L/R. ACARSd changed the stride to two samples: pass one started on the left channel, pass two on the right. No costly buffer split was needed.
// conceptual form forward = 2; decode(buffer + 0); // L L L L ... decode(buffer + 1); // R R R R ...
That efficiency is one reason the architecture scaled from one receiver to two, then to several sound cards and eventually eight scanners.
Because Dr. Armin Zundel, KjM's boss at INLINE and a mathematician, was quite convinced that a Fast Fourier Transform was the proper solution. Prof. Kay Berkling also helped with the FFT experiments. The April 2003 README already records both contributions — and adds the dry parenthesis that “acarsd is still running without it”. Those experiments survived in the source tree. In practice, however, FFT never became the heart of the production decoder. The empirical multi-pass/code-table approach won because it worked better for the real signals and hardware they were testing.
The mathematician proposed FFT. The baker kept testing real radio signals. The code tables won.