Preface
I am currently working on an ACARS decoding implementation for the Web-888 SDR. As part of this work I built and ran acarsdec against the Web-888's audio output. Without any changes to the code, acarsdec is unable to decode ACARS signals received via the Web-888, because of the timebase error described below.
Summary
In Airband (VHF) mode, the Web-888 delivers audio with a timebase error of ~2.5%. All audio tones are scaled by a factor of 0.9756 (e.g. a 2400 Hz ACARS mark tone appears at ~2341.5 Hz, a 1200 Hz tone at ~1170 Hz). This is not a receiver frequency offset and not a demodulation error - it is a sample-rate mismatch introduced by the firmware commit that changed the VHF ADC clock.
Root cause
The Web-888 derives its audio sample rate from the ADC clock via:
rx_decim = (int)(ADC_CLOCK / snd_rate) // main.cpp:237
decim = rx_decim / 256 // peri.cpp:205 (fpga_start_rx)
The FPGA decimates the ADC clock in steps of 256. The audio rate is therefore always ADC_CLOCK / (decim * 256).
Commit bafc446 ("Change ADC rate to 100.7616Mhz", Jan 6 2025) changed the VHF ADC clock from 98.304 MHz to 100.7616 MHz in init/clk.h:
#define ADC_CLOCK_HF (122.88 * MHz)
#define ADC_CLOCK_VHF (100.7616 * MHz)
100.7616 MHz was chosen to cover the full VHF Airband, but it is NOT an exact multiple of 12000 * 256 = 3,072,000 Hz.
Worked example (Airband, snd_rate = 12000):
ADC clock = 100.7616 MHz
rx_decim = (int)(100761600 / 12000) = 8396 (8396.8 truncated)
decim = 8396 / 256 = 32 (32.79 truncated)
real rate = 100.7616 MHz / (32 * 256) = 100.7616 MHz / 8192 = 12300 Hz
So the FPGA actually produces audio at 12300 Hz while the software declares 12000 Hz (and kiwirecorder records a nominal 12001 Hz header).
real_rate / declared_rate = 12300 / 12000 = 1.025
-> all tones appear scaled by 12000/12300 = 0.9756
This exactly matches the observed factor of ~1.025.
Why only Airband mode is affected
-
HF mode: 122.88 MHz / (12000 * 256) = 40.0 exactly integer
audio rate = 122.88 MHz / 10240 = 12000 Hz -> correct
-
Airband: 100.7616 MHz / (12000 * 256) = 32.79 not integer
audio rate = 100.7616 MHz / 8192 = 12300 Hz -> 2.5% error
Therefore all HF-mode receivers (HFDL, DRM, FAX, ...) are unaffected; every audio output in Airband mode (AM, NFM, and all other modes) carries the 2.5% timebase error. ACARS/VHF-band decoders (acarsdec, dumpvdl2, ...) are the ones that hit it.
References
- init/clk.h:29-30 ADC_CLOCK_HF / ADC_CLOCK_VHF definitions
- main.cpp:236-237 snd_rate and rx_decim computation
- zynq/peri.cpp:205 fpga_start_rx() passes rx_decim/256 to the FPGA
- commit bafc446 "Change ADC rate to 100.7616Mhz"
Suggested fixes
- Choose an ADC clock that is an exact multiple of 12000 * 256:
e.g. 98.304 MHz (= 32 * 12000 * 256, the previous value) or 122.88 MHz (= 40 * 12000 * 256)
- Or adapt the decimation path so that the resulting audio rate is exactly 12000 Hz for the chosen ADC clock.
- Until fixed in firmware, client-side resampling by ~1.025 restores the correct audio rate (e.g. a streaming linear-interpolation resampler in front of the ACARS decoder).
Preface
I am currently working on an ACARS decoding implementation for the Web-888 SDR. As part of this work I built and ran acarsdec against the Web-888's audio output. Without any changes to the code, acarsdec is unable to decode ACARS signals received via the Web-888, because of the timebase error described below.
Summary
In Airband (VHF) mode, the Web-888 delivers audio with a timebase error of ~2.5%. All audio tones are scaled by a factor of 0.9756 (e.g. a 2400 Hz ACARS mark tone appears at ~2341.5 Hz, a 1200 Hz tone at ~1170 Hz). This is not a receiver frequency offset and not a demodulation error - it is a sample-rate mismatch introduced by the firmware commit that changed the VHF ADC clock.
Root cause
The Web-888 derives its audio sample rate from the ADC clock via:
The FPGA decimates the ADC clock in steps of 256. The audio rate is therefore always ADC_CLOCK / (decim * 256).
Commit bafc446 ("Change ADC rate to 100.7616Mhz", Jan 6 2025) changed the VHF ADC clock from 98.304 MHz to 100.7616 MHz in init/clk.h:
100.7616 MHz was chosen to cover the full VHF Airband, but it is NOT an exact multiple of 12000 * 256 = 3,072,000 Hz.
Worked example (Airband, snd_rate = 12000):
ADC clock = 100.7616 MHz
rx_decim = (int)(100761600 / 12000) = 8396 (8396.8 truncated)
decim = 8396 / 256 = 32 (32.79 truncated)
real rate = 100.7616 MHz / (32 * 256) = 100.7616 MHz / 8192 = 12300 Hz
So the FPGA actually produces audio at 12300 Hz while the software declares 12000 Hz (and kiwirecorder records a nominal 12001 Hz header).
This exactly matches the observed factor of ~1.025.
Why only Airband mode is affected
HF mode: 122.88 MHz / (12000 * 256) = 40.0 exactly integer
audio rate = 122.88 MHz / 10240 = 12000 Hz -> correct
Airband: 100.7616 MHz / (12000 * 256) = 32.79 not integer
audio rate = 100.7616 MHz / 8192 = 12300 Hz -> 2.5% error
Therefore all HF-mode receivers (HFDL, DRM, FAX, ...) are unaffected; every audio output in Airband mode (AM, NFM, and all other modes) carries the 2.5% timebase error. ACARS/VHF-band decoders (acarsdec, dumpvdl2, ...) are the ones that hit it.
References
Suggested fixes
e.g. 98.304 MHz (= 32 * 12000 * 256, the previous value) or 122.88 MHz (= 40 * 12000 * 256)