Flexible Advanced Coding and Modulation (CCSDS 131.2-B-1)

Files
README.md

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.