ccsds
The ccsds library implements predicates for parsing and generating
CCSDS (Consultative Committee for Space Data Systems) Space Packets
following the CCSDS 133.0-B-2 standard (Space Packet Protocol).
Reference documentation:
Packet Structure
A CCSDS Space Packet consists of:
Primary Header (6 bytes):
Version Number (3 bits) - Always 000 for Space Packets
Packet Type (1 bit) - 0=Telemetry, 1=Telecommand
Secondary Header Flag (1 bit) - 0=absent, 1=present
Application Process ID (APID) (11 bits) - 0-2047
Sequence Flags (2 bits) - 00=continuation, 01=first, 10=last, 11=standalone
Packet Sequence Count (14 bits) - 0-16383
Packet Data Length (16 bits) - Number of octets in data field minus 1
User Data Field - Variable length payload
Representation
Packets are represented using the compound term:
ccsds_packet(Version, Type, SecHeaderFlag, APID, SeqFlags, SeqCount, SecHeader, UserData)
Where:
Versionis an integer (0-7, typically 0)Typeis an integer (0=telemetry, 1=telecommand)SecHeaderFlagis an integer (0 or 1)APIDis an integer (0-2047)SeqFlagsis an integer (0-3)SeqCountis an integer (0-16383)SecHeaderis eithernoneorsecondary_header(Bytes)whereBytesis a list of bytesUserDatais a list of bytes
Note that the DataLength field from the wire format is not stored in
the term representation as it can be computed from SecHeader and
UserData. The data_length/2 accessor predicate computes and
returns this value when needed.
Parsing
The parse/2 predicate accepts a source term as its first argument.
The source can be file(File), stream(Stream), or
bytes(Bytes). All source types return a list of packets for
uniformity.
To parse packets from a list of bytes:
| ?- ccsds::parse(bytes([0x08, 0x01, 0xC0, 0x00, 0x00, 0x03, 0xDE, 0xAD, 0xBE, 0xEF]), Packets).
Packets = [ccsds_packet(0, 0, 1, 1, 3, 0, none, [222, 173, 190, 239])]
yes
To parse packets from a binary file:
| ?- ccsds::parse(file('telemetry.bin'), Packets).
To parse packets from a binary stream:
| ?- ccsds::parse(stream(Stream), Packets).
When the packets include a secondary header, the secondary header length
must be known. In this case, use the ccsds(SecondaryHeaderLength)
object instead of the ccsds object. For example, to parse packets
with a secondary header of 6 bytes:
| ?- ccsds(6)::parse(bytes([0x08, 0x01, 0xC0, 0x00, 0x00, 0x07, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0xAA, 0xBB]), Packets).
Generating
The generate/2 predicate accepts a sink term as its first argument
and a list of packet terms as the second argument. The sink can be
file(File), stream(Stream), or bytes(Bytes).
To generate bytes from a list of packet terms:
| ?- ccsds::generate(bytes(Bytes), [ccsds_packet(0, 0, 1, 1, 3, 0, none, [0xDE, 0xAD, 0xBE, 0xEF])]).
Bytes = [8, 1, 192, 0, 0, 3, 222, 173, 190, 239]
yes
To write the bytes generated from a list of packet terms to a binary file:
| ?- ccsds::generate(file('output.bin'), Packets).
To write the bytes generated from a list of packet terms to a binary stream:
| ?- ccsds::generate(stream(Stream), Packets).
Accessor Predicates
The library provides convenient accessor predicates for extracting packet fields:
| ?- ccsds::apid(Packet, APID).
% Returns telemetry or telecommand
| ?- ccsds::type(Packet, Type).
% Returns continuation, first, last, or standalone
| ?- ccsds::sequence_flags(Packet, Flags).
% Returns the secondary header as a list of bytes or none
| ?- ccsds::secondary_header(Packet, SecHeader).
% Returns the secondary header time as a cuc_time(Coarse, Fine) term or fails if no time is available
| ?- ccsds::secondary_header_time(Packet, Time).
| ?- ccsds::user_data(Packet, Data).
% Returns the packet data length (computed from secondary header and user data)
| ?- ccsds::data_length(Packet, Length).
Types and arbitrary generators
The library includes a ccsds_types category that provides
ccsds_packet and ccsds_packet(SecondaryHeaderLength) types and
arbitrary generators for CCSDS packets. For example:
| ?- type::check(ccsds_packet, Bytes).
| ?- type::arbitrary(ccsds_packet(42), Bytes).
It also provides a ccsds_packets(N) and
ccsds_packets(SecondaryHeaderLength, N) types for generating a list
with N packets. For example:
| ?- type::arbitrary(ccsds_packets(10), Bytes).
| ?- type::check(ccsds_packets(42, 10), Bytes).
For a term representation of a packet, use the ccsds_packet_term and
ccsds_packet_term(SecondaryHeaderLength) types and arbitrary
generators. For example:
| ?- type::check(ccsds_packet_term, Packet).
| ?- type::arbitrary(ccsds_packet_term(42), Packet).
API documentation
Open the ../../apis/library_index.html#ccsds link in a web browser.
Loading
To load all entities in this library, load the loader.lgt file:
| ?- logtalk_load(ccsds(loader)).
Testing
To test this library predicates, load the tester.lgt file:
| ?- logtalk_load(ccsds(tester)).
To test the performance of the library parsing predicates, load the
tester_performance.lgt file:
| ?- logtalk_load(ccsds(tester_performance)).