Communications Operation Procedure-1 (CCSDS 232.1-B-2)

Files
README.md

cop1 #

The Communications Operation Procedure-1 (COP-1) of CCSDS 232.1-B-2, for OCaml.

A telecommand uplink loses frames, and a spacecraft must execute commands once and in order. COP-1 is the CCSDS answer: a go-back-N retransmission protocol over the TC Space Data Link Protocol, with a sender on the ground (FOP-1) and a receiver on the spacecraft (FARM-1). The receiver reports what it has accepted in the Command Link Control Word (CLCW) that the spacecraft sends down with its telemetry. This package implements both state machines of CCSDS 232.1-B-2 without I/O, following the event numbering of its state tables, and cop1-eio runs them with an Eio clock for the retransmission timer.

Packages #

  • cop1: the FOP-1 and FARM-1 state machines, without I/O.
  • cop1-eio: services that run them with an Eio clock and build the frames.

Install #

$ opam install cop1 cop1-eio

If opam cannot find the packages, add the overlay repository first:

$ opam repo add samoht https://tangled.org/gazagnaire.org/opam-overlay.git
$ opam update
$ opam install cop1 cop1-eio

Usage #

FOP-1, the ground side #

Frames come in three types. A Type-AD frame is sequence-controlled: it carries a sequence number N(S), the receiver accepts it only in order, and FOP-1 retransmits it until a CLCW confirms it; this is the AD service (A for acceptance, D for data). A Type-BD frame bypasses that check and is accepted whenever the receiver has room, for an emergency such as commanding a spacecraft whose FARM-1 is in lockout. A Type-BC frame carries one of the two control commands, Unlock and Set V(R).

A new FOP-1 machine is in state Initial. Each event (a directive, a frame accepted or rejected by the lower layer, a CLCW, a timer expiry) returns the new state and the actions the caller must take:

let fop = Cop1.Fop1.v ()
let fop', actions =
  Cop1.Fop1.incoming fop
    (Cop1.Fop1.Directive Cop1.Fop1.Initiate_ad_without_clcw)

(* Initiating AD service moves Initial -> Active, and accepts and confirms
   the directive (CCSDS 232.1-B-2 table 5-1, E23). *)
let () = assert (Cop1.Fop1.equal_state (Cop1.Fop1.state fop') Cop1.Fop1.Active)
let () = assert (actions = [ Cop1.Fop1.Accept; Cop1.Fop1.Confirm ])

Cop1.Fop1.transfer_ad and transfer_bd return the Higher Procedures answer alongside the state and actions. Cop1.Recovery selects recovery directives from that same state and the last CLCW. These operations are pure; the Eio service installs their state and performs their actions.

FARM-1, the spacecraft side #

FARM-1 accepts or rejects each received transfer frame, updates its expected sequence number V(R) and its flags, and produces the CLCW from which the ground advances its window:

let farm = Cop1.Farm1.v ()
let farm', _actions =
  Cop1.Farm1.incoming farm (Cop1.Farm1.Frame (Cop1.Farm1.Valid_ad 0))
let clcw = Cop1.Farm1.to_clcw farm' ~vcid:0

(* The in-sequence frame is accepted: V(R) advances to 1 and the CLCW
   reports the next expected sequence number. *)
let () = assert (Cop1.Farm1.vr farm' = 1)
let () = assert (clcw.Cop1.Clcw.report_value = 1)

FARM-1 splits the 256 sequence numbers around V(R) into a positive window of W/2 numbers from V(R), a negative window of W/2 numbers below it, and a lockout area of 256 − W numbers. A Type-AD frame numbered V(R) is accepted. A frame ahead of V(R) but inside the positive window means that a frame was lost: FARM-1 discards it and sets the retransmit flag, which asks FOP-1 to go back to the lost frame. A frame in the negative window is a repeat and is discarded quietly. Only a frame in the lockout area puts FARM-1 in lockout, where it refuses every Type-AD frame until an Unlock arrives. With V(R) = 0, frame 5 falls in the positive window:

let farm = Cop1.Farm1.v ()
let farm', _ =
  Cop1.Farm1.incoming farm (Cop1.Farm1.Frame (Cop1.Farm1.Valid_ad 5))

(* Frame 5 is ahead of V(R) = 0 but inside the window, so it is
   discarded and sets the retransmit flag in the next CLCW. *)
let () = assert (Cop1.Farm1.retransmit_flag farm')

Parameters #

Cop1.Fop1.v takes the sliding window width fop_width, the timer value t1_initial, the transmission_limit and the timeout_type, and Cop1.Farm1.v takes farm_width (126 by default), so that a caller can use the values agreed for a virtual channel. The standard requires W to be even, from 2 to 254, when Type-AD frames may be retransmitted, because the window splits into two equal halves (CCSDS 232.1-B-2, sections 6.1.8.2 and 6.1.8.3.1); the default takes 63 numbers on each side. Cop1.Farm1.control declares W as the limit FARM_Sliding_Window_Width and checks its graph at the widths 2, 10, 126 and 254.

License #

ISC. See LICENSE.md.