flexacm #
Flexible Advanced Coding and Modulation (CCSDS 131.2-B-1) for OCaml.
A pass is the interval during which a satellite is above a ground station's
horizon, a few minutes for a low orbit: the elevation angle rises from zero to
a maximum and falls back, and the path length, and with it the received signal
strength, changes as it does. A satellite's link to the ground therefore gets
better and worse over a pass as the elevation angle and the weather change.
Adaptive coding and modulation (ACM) uses a denser modulation and a lighter
code when the signal is strong, and falls back to a sparser modulation and a
stronger code when it fades. flexacm provides the types and helpers for ACM
on space links as specified by CCSDS 131.2-B-1: the modes that
combine a modulation (QPSK, 8-PSK, 16-APSK, 32-APSK) with a coding rate from
1/4 to 9/10, and the PLOP header that tells the receiver which mode is active.
The library expands PLOP as the Physical Layer Operations Control Field: a
header prepended to each physical-layer frame that carries the mode id and the
coded frame length in bits, and whose type sets what the transmitter sends
between frames (PLOP-1 an unmodulated carrier, PLOP-2 a continuous modulated
signal). That naming is the library's own: in CCSDS usage PLOP-1 and PLOP-2
are the Physical Layer Operations Procedures of the telecommand uplink, and
131.2-B-1 signals the mode in the header of its own physical-layer frame.
Installation #
Install with opam:
$ opam install flexacm
If opam cannot find the package, it may not yet be released in the
public opam-repository. Add the overlay repository, then install
it:
$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install flexacm
Usage #
Several presets from CCSDS 131.2-B Table 5-1 are built in. Spectral efficiency, in information bits per symbol, is log2(M) times the code rate, where M is the number of points of the constellation. 32-APSK carries log2 32 = 5 bits per symbol, and at rate 5/6 that is 5 x 5/6 = 4.17 information bits per symbol:
# let m = Flexacm.thirty_two_apsk_5_6 in
Fmt.str "%a %.2f bits/symbol"
Flexacm.pp_modulation m.modulation m.spectral_efficiency
- : string = "32-APSK 4.17 bits/symbol"
Custom modes can be constructed directly; 16-APSK at rate 3/4 gives 4 x 3/4 = 3:
# let m =
Flexacm.acm_mode ~mode_id:42
~modulation:Flexacm.Sixteen_APSK ~code_rate:Flexacm.Rate_3_4 in
(m.mode_id, m.spectral_efficiency)
- : int * float = (42, 3.)
PLOP frame #
Wrap a coded data unit with a PLOP header so the receiver can demodulate:
# let plop =
{ Flexacm.plop_type = Flexacm.Plop_2;
acm_mode_id = Flexacm.qpsk_1_2.mode_id;
frame_len = 2048 } in
let frame = Flexacm.frame ~plop (Bytes.of_string "coded bytes") in
Fmt.str "%a" Flexacm.pp_frame frame
- : string = "{ plop={ plop=PLOP-2; mode=2; frame_len=2048 }; data_len=11 }"
Adaptive mode selection #
Given a table of modes sorted by ascending efficiency, mode_for_snr returns
the mode with the highest throughput whose threshold is below the current SNR:
# let table = [
Flexacm.qpsk_1_4; Flexacm.qpsk_1_2; Flexacm.qpsk_3_4;
Flexacm.eight_psk_2_3; Flexacm.sixteen_apsk_3_4;
Flexacm.thirty_two_apsk_5_6 ] in
match Flexacm.mode_for_snr table 8.0 with
| Some m -> Fmt.str "%a" Flexacm.pp_modulation m.modulation
| None -> "link budget too low"
- : string = "16-APSK"
The built-in threshold uses spectral efficiency as a proxy: a mode of efficiency eta qualifies when the SNR is at least 3 eta - 2 dB. For the table above the thresholds are -0.5, 1, 2.5, 4, 7 and 10.5 dB, so at 8 dB 16-APSK 3/4 (7 dB) qualifies and 32-APSK 5/6 (10.5 dB) does not. A real link uses per-mode Eb/N0 thresholds from its own link budget instead; Eb/N0 is the energy per information bit divided by the noise power spectral density, the quantity a link budget states for each mode.
Licence #
ISC. See LICENSE.md.
- OCaml 100%