# `ccsds_packetization`

The `ccsds_packetization` library provides the inverse service-layer helpers to the existing `ccsds_packet_services` library.

The current implementation covers:

- fitting packet streams into TM and AOS packet-service regions

- preserving partially emitted packet bytes across frame boundaries

- tracking queued packets per frame type, spacecraft identifier, and virtual channel identifier

- generating idle packets deliberately when there is remaining frame capacity

- reporting explicit packetization events for buffered fragments and generated idle packets

## API documentation

Open the ../../apis/library_index.html#ccsds_packetization link in a web browser.

## Loading

To load all entities in this library, load the `loader.lgt` file:

    | ?- logtalk_load(ccsds_packetization(loader)).

## Testing

To test this library predicates, load the `tester.lgt` file:

    | ?- logtalk_load(ccsds_packetization(tester)).

## Representation

Packetizer state is represented using the compound term:

    packetizer_state(Channels)

Where `Channels` is a list of terms of the form:

    packetizer_channel(FrameType, SpacecraftId, VirtualChannelId, PendingBytes, QueuedPackets)

Where:

- `FrameType` is either `tm` or `aos`

- `SpacecraftId` is the keyed spacecraft identifier

- `VirtualChannelId` is the keyed virtual channel identifier

- `PendingBytes` is a list of packet bytes already started in an earlier frame but not yet fully emitted

- `QueuedPackets` is a list of complete `ccsds_packet(...)` terms waiting to be packetized for that keyed channel

Idle packets are generated as telemetry packets using APID `2047`, standalone sequence flags, the requested sequence count, a zero-filled secondary header of the requested length, and zero-filled user data.

## Packetization

To get the initial packetizer state:

    | ?- ccsds_packetization::initial_state(State).

To inspect the currently buffered pending bytes and queued packets:

    | ?- ccsds_packetization::pending_packets(packetizer_state([packetizer_channel(tm, 42, 3, [0x22,0x33], [ccsds_packet(0,0,0,1,3,7,none,[0x44])])]), PendingPackets).

To packetize packets into a TM transfer frame:

    | ?- ccsds_packetization::packetize_tm_packets(tm_transfer_frame(0, 42, 3, 0, 16, 32, 0, 0, 0, 3, 2047, none, [0,0,0,0,0,0,0], none, none), 0, packetizer_state([]), [ccsds_packet(0, 0, 0, 0, 3, 0, none, [0x42])], UpdatedFrame, UpdatedState).

When the input TM frame already carries a `fecf/1` term, `packetize_tm_packets/6-7` refresh it from the updated frame bytes. Frames with `none` keep `none`.

To packetize packets into an AOS transfer frame:

    | ?- ccsds_packetization::packetize_aos_packets(aos_transfer_frame(1, 42, 3, 16, signaling_field(0,0,0,0), none, [0,0,0,0,0,0,0,0,0], none, none), 0, packetizer_state([]), [ccsds_packet(0, 0, 0, 0, 3, 0, none, [0x42])], UpdatedFrame, UpdatedState).

When the input AOS frame already carries a `fecf/1` term, `packetize_aos_packets/6-7` refresh it from the updated frame bytes. Frames with `none` keep `none`.

To packetize packets across a sequence of TM transfer frames:

    | ?- ccsds_packetization::packetize_tm_frames([Frame1, Frame2], 0, packetizer_state([]), Packets, UpdatedFrames, RemainingPackets, UpdatedState).

## Events

The richer single-frame and multi-frame packetization predicates return event lists using the terms:

    buffered_packet_fragment(FrameType, SpacecraftId, VirtualChannelId, PendingBytes)
    generated_idle_packet(FrameType, SpacecraftId, VirtualChannelId, Packet)

Where:

- `buffered_packet_fragment/4` reports trailing packet bytes buffered for the next frame

- `generated_idle_packet/4` reports an idle packet synthesized to consume remaining frame capacity

## Idle packets

To generate a telemetry idle packet with APID `2047`:

    | ?- ccsds_packetization::generate_idle_packet(0, 7, 2, Packet).