usdl

package
v0.4.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 2, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package usdl implements the CCSDS Unified Space Data Link Protocol (USLP) per CCSDS 732.1-B-3.

USLP Transfer Frames carry a Transfer Frame Data Field whose layout is declared in-band by the TFDZ Construction Rules of the TFDF Header. Frames are either non-truncated (full primary header with frame length, flags, and an optional Virtual Channel Frame Count of 0-7 octets) or truncated (a fixed 4-octet header for short telecommands, annex D).

Index

Constants

View Source
const (
	// RulePacketsSpanning ('000'): fixed-length TFDZ of concatenated CCSDS
	// packets that may span frame boundaries; the First Header Pointer is
	// required.
	RulePacketsSpanning uint8 = 0b000
	// RuleStartOfSDU ('001'): fixed-length TFDZ holding the start of (or a
	// complete) MAPA_SDU/VCA_SDU; the Last Valid Octet Pointer is required.
	RuleStartOfSDU uint8 = 0b001
	// RuleContinuingSDU ('010'): fixed-length TFDZ continuing a
	// MAPA_SDU/VCA_SDU started earlier; the Last Valid Octet Pointer is
	// required.
	RuleContinuingSDU uint8 = 0b010
	// RuleOctetStream ('011'): variable-length TFDZ carrying a continuous
	// octet-aligned stream.
	RuleOctetStream uint8 = 0b011
	// RuleStartingSegment ('100'): variable-length TFDZ with the starting
	// segment of a segmented SDU.
	RuleStartingSegment uint8 = 0b100
	// RuleContinuingSegment ('101'): variable-length TFDZ with a continuing
	// segment.
	RuleContinuingSegment uint8 = 0b101
	// RuleLastSegment ('110'): variable-length TFDZ with the last segment.
	RuleLastSegment uint8 = 0b110
	// RuleNoSegmentation ('111'): variable-length TFDZ holding complete
	// SDUs or packets, unsegmented.
	RuleNoSegmentation uint8 = 0b111
)

TFDZ Construction Rules per CCSDS 732.1-B-3 clause 4.1.4.2.2.2.

View Source
const (
	// FHPNoPacketStart: for rule '000', no packet starts within this TFDZ
	// ('all ones', clause 4.1.4.2.4.4).
	FHPNoPacketStart uint16 = 0xFFFF
	// LVOPIncomplete: for rules '001'/'010', the SDU does not complete
	// within this TFDZ ('all ones', clause 4.1.4.2.4.6).
	LVOPIncomplete uint16 = 0xFFFF
)

Special pointer values (CCSDS 732.1-B-3 clause 4.1.4.2.4).

View Source
const (
	UPIDSpacePackets       uint8 = 0  // Space Packets or Encapsulation Packets
	UPIDCOP1Control        uint8 = 1  // COP-1 Control Commands
	UPIDCOPPControl        uint8 = 2  // COP-P Control Commands
	UPIDUserOctetStream    uint8 = 4  // User-defined Octet Stream
	UPIDMissionSpecific1   uint8 = 5  // Mission Specific Information-1 (one MAPA_SDU)
	UPIDProx1PseudoPacket1 uint8 = 6  // Proximity-1 Pseudo Packet ID 1
	UPIDProx1SPDU          uint8 = 7  // Proximity-1 SPDUs
	UPIDProx1PseudoPacket2 uint8 = 8  // Proximity-1 Pseudo Packet ID 2
	UPIDIdle               uint8 = 31 // Idle Data (OID frames)
)

USLP Protocol Identifiers from the SANA UPID registry (https://sanaregistry.org/r/uslp_protocol_id, CCSDS 732.1-B-3 clause 4.1.4.2.3).

View Source
const (
	// TruncatedPrimaryHeaderSize is the fixed size of the truncated
	// primary header (annex D1.3: exactly 4 octets).
	TruncatedPrimaryHeaderSize = 4
	// PrimaryHeaderBaseSize is the size of the non-truncated primary
	// header before the variable Virtual Channel Frame Count.
	PrimaryHeaderBaseSize = 7
	// MaxVCFCountLen is the largest VCF Count field length in octets
	// (clause 4.1.2.11, table 4-2).
	MaxVCFCountLen = 7
)

Primary header sizes.

View Source
const DefaultIdleFill byte = 0x55

DefaultIdleFill is the idle fill byte used when ChannelConfig.IdlePattern is empty. It fills the unused tail of fixed-length TFDZs behind the Last Valid Octet Pointer and the body of Encapsulation Idle Packets; that idle pattern is project-specified (clause 4.1.4.3 note 1; a random pattern is preferred) and can be overridden via ChannelConfig.IdlePattern. The TFDZ of an OID frame is NOT filled with this pattern: Clause 4.1.4.1.10 mandates the PN sequence generated by OIDSequence.

View Source
const FECSize16 = 2

FECSize16 is the size of the 16-bit Frame Error Control Field (clause 4.1.6.2.2: when present, the FECF occupies the last 16 bits of every Transfer Frame, USLP has no other FECF size).

View Source
const MaxTruncatedFrameLen = 32

MaxTruncatedFrameLen is the largest total truncated frame length in octets (annex D1.3.2 note 3: the complete frame must fit within one LDPC(512, 256) codeword; annex D1.4.2.4 caps the TFDZ at 27 octets).

View Source
const OCFSize = 4

OCFSize is the size of the Operational Control Field in bytes.

View Source
const OIDVCID = 63

OIDVCID is the Virtual Channel ID reserved for Only Idle Data frames (CCSDS 732.1-B-3 clause 4.1.4.1.6: 'all ones').

View Source
const TFVN = 12 // 0b1100

TFVN is the USLP Transfer Frame Version Number (CCSDS 732.1-B-3 Clause 4.1.2.2.2: '1100').

Variables

View Source
var (
	// ErrDataTooShort indicates the provided data is too short for decoding.
	ErrDataTooShort = errors.New("provided data is too short to decode")

	// ErrInvalidVersion indicates the TFVN is not 12 (0b1100) for USLP.
	ErrInvalidVersion = errors.New("invalid version: TFVN must be 12 (0b1100) for USLP")

	// ErrInvalidSpacecraftID indicates the spacecraft ID is out of range.
	ErrInvalidSpacecraftID = errors.New("invalid spacecraft ID: must be in range 0-65535 (16 bits)")

	// ErrInvalidVCID indicates the virtual channel ID is out of range.
	ErrInvalidVCID = errors.New("invalid virtual channel ID: must be in range 0-63 (6 bits)")

	// ErrInvalidMAPID indicates the MAP ID is out of range.
	ErrInvalidMAPID = errors.New("invalid MAP ID: must be in range 0-15 (4 bits)")

	// ErrInvalidFrameLength indicates the frame length field is out of range.
	ErrInvalidFrameLength = errors.New("invalid frame length: exceeds maximum of 65536 bytes")

	// ErrFrameLengthMismatch indicates the decoded frame length field does
	// not match the length of the delivered frame buffer.
	ErrFrameLengthMismatch = errors.New("frame length field does not match buffer length")

	// ErrInvalidVCFCountLen indicates the VCF Count length exceeds 7 octets.
	ErrInvalidVCFCountLen = errors.New("invalid VCF count length: must be in range 0-7 octets")

	// ErrInvalidVCFCount indicates the VCF Count does not fit its field width.
	ErrInvalidVCFCount = errors.New("invalid VCF count: exceeds configured field width")

	// ErrInvalidHeaderSpare indicates the reserved spare bits of the primary
	// header are not zero.
	ErrInvalidHeaderSpare = errors.New("invalid primary header: reserved spare bits must be 00")

	// ErrTruncatedFrameFields indicates a truncated frame carries fields it
	// cannot have (insert zone, OCF, FECF, or a pointer-carrying rule).
	ErrTruncatedFrameFields = errors.New("truncated frame cannot carry insert zone, OCF, FECF, or a pointer")

	// ErrInvalidFECSize indicates the FECF size is not 0 or 2 octets. The
	// USLP FECF, when present, is always the 16-bit CRC of clause 4.1.6.2.2.
	ErrInvalidFECSize = errors.New("invalid FECF size: must be 0 or 2 octets (USLP has only the 16-bit FECF)")

	// ErrTruncatedFrameTooShort indicates a truncated frame with an empty
	// TFDZ (annex D1.3.2 note 2: minimum 6 octets in total).
	ErrTruncatedFrameTooShort = errors.New("truncated frame TFDZ must carry at least one octet (minimum frame length 6)")

	// ErrTruncatedFrameTooLong indicates a truncated frame over 32 octets
	// (annex D1.3.2 note 3 and D1.4.2.4).
	ErrTruncatedFrameTooLong = errors.New("truncated frame exceeds the 32-octet maximum length")

	// ErrNoOCFSupplier indicates the channel is configured with HasOCF but
	// no OCF supplier is installed; the OCF content must come from the OCF
	// service user (clause 4.1.5) rather than being fabricated as zeros.
	ErrNoOCFSupplier = errors.New("channel requires an OCF but no supplier is set: call SetOCFSupplier")

	// ErrOctetStreamFixedLength indicates an octet stream was sent on a
	// fixed-length channel (CCSDS 732.1-B-3 clause 4.2.4.1 forbids it).
	ErrOctetStreamFixedLength = errors.New("octet stream service requires variable-length transfer frames")

	// ErrInvalidConstructionRule indicates an invalid TFDZ construction rule.
	ErrInvalidConstructionRule = errors.New("invalid TFDZ construction rule: must be in range 0-7 (3 bits)")

	// ErrInvalidPointer indicates the FHP/LVOP is out of range for the TFDZ.
	ErrInvalidPointer = errors.New("invalid pointer: exceeds data zone length")

	// ErrCRCMismatch indicates the received CRC does not match the computed CRC.
	ErrCRCMismatch = errors.New("CRC mismatch: received CRC does not match computed CRC")

	// ErrDataTooLarge indicates the data field exceeds the maximum frame length.
	ErrDataTooLarge = errors.New("data field exceeds maximum frame length")

	// ErrEmptyData indicates that the provided data is empty.
	ErrEmptyData = errors.New("data cannot be empty")

	// ErrSizeMismatch indicates the data size does not match the expected fixed size.
	ErrSizeMismatch = errors.New("data size does not match expected fixed size")

	// ErrInvalidOCFLength indicates the OCF is not exactly 4 bytes.
	ErrInvalidOCFLength = errors.New("operational control field must be exactly 4 bytes when present")

	// ErrInvalidInsertZoneLength indicates the insert zone length is invalid.
	ErrInvalidInsertZoneLength = errors.New("insert zone length exceeds maximum")

	// ErrNoFramesAvailable aliases sdl.ErrNoFramesAvailable.
	ErrNoFramesAvailable = sdl.ErrNoFramesAvailable

	// ErrBufferFull aliases sdl.ErrBufferFull.
	ErrBufferFull = sdl.ErrBufferFull

	// ErrSCIDMismatch indicates the frame SCID does not match the master channel SCID.
	ErrSCIDMismatch = errors.New("frame SCID does not match master channel SCID")

	// ErrServiceNotFound aliases sdl.ErrServiceNotFound.
	ErrServiceNotFound = sdl.ErrServiceNotFound

	// ErrMasterChannelNotFound aliases sdl.ErrMasterChannelNotFound.
	ErrMasterChannelNotFound = sdl.ErrMasterChannelNotFound

	// ErrNoVirtualChannels aliases sdl.ErrNoChannels.
	ErrNoVirtualChannels = sdl.ErrNoChannels

	// ErrVirtualChannelNotFound indicates no virtual channel exists for the given VCID.
	ErrVirtualChannelNotFound = errors.New("virtual channel not found for specified VCID")

	// ErrDataFieldTooSmall indicates the data field capacity is too small for framing.
	ErrDataFieldTooSmall = errors.New("data field capacity too small")

	// ErrNoPacketSizer indicates no PacketSizer has been set on the MAP Packet service.
	ErrNoPacketSizer = errors.New("no PacketSizer configured: call SetPacketSizer before Receive")

	// ErrNoMasterChannels aliases sdl.ErrNoMasterChannels.
	ErrNoMasterChannels = sdl.ErrNoMasterChannels
)

Functions

func IsIdleFrame

func IsIdleFrame(frame *TransferFrame) bool

IsIdleFrame reports whether the frame is an Only Idle Data frame. Per CCSDS 732.1-B-3 clause 4.1.4.1.6, OID frames use VCID 63.

Types

type ChannelConfig

type ChannelConfig struct {
	FrameLength   int    // Total frame length in octets (fixed per physical channel; 0 = variable)
	HasOCF        bool   // Whether the Operational Control Field (4 bytes) is carried
	HasFECF       bool   // Whether the 16-bit Frame Error Control Field is present
	InsertZoneLen int    // Insert zone length in bytes (0 if none)
	VCFCountLen   uint8  // VCF Count field length in octets (0-7; 0 = no count)
	IdlePattern   []byte // Idle fill pattern (repeating); empty means DefaultIdleFill
}

ChannelConfig defines the managed parameters of a USLP channel.

IdlePattern is the project-specified idle pattern that fills the unused tail of fixed-length TFDZs behind the Last Valid Octet Pointer and the body of Encapsulation Idle Packets (clause 4.1.4.3 note 1). It does not fill OID frames: their TFDZ carries the mandatory PN sequence (clause 4.1.4.1.10).

func (ChannelConfig) DataFieldCapacity

func (c ChannelConfig) DataFieldCapacity(dfhSize int) int

DataFieldCapacity returns the maximum Transfer Frame Data Zone size for fixed-length frames, given the size of the TFDF header in use (1 octet, or 3 when the construction rule carries a pointer). Fixed-length frames use the full (non-truncated) primary header.

type DataFieldHeader

type DataFieldHeader struct {
	ConstructionRule uint8  // 3 bits - TFDZ construction rule
	UPID             uint8  // 5 bits - USLP Protocol Identifier
	Pointer          uint16 // 16 bits - FHP (rule '000') or LVOP (rules '001'/'010')
}

DataFieldHeader represents the USLP Transfer Frame Data Field Header (TFDF Header, CCSDS 732.1-B-3 clause 4.1.4.2): one mandatory octet holding the TFDZ Construction Rules (3 bits) and the UPID (5 bits), followed by a 16-bit First Header Pointer / Last Valid Octet Pointer only for the construction rules that require one ('000', '001', '010').

func (*DataFieldHeader) Decode

func (h *DataFieldHeader) Decode(data []byte) error

Decode parses a TFDF header from the start of data.

func (*DataFieldHeader) Encode

func (h *DataFieldHeader) Encode() ([]byte, error)

Encode packs the DataFieldHeader into a byte slice.

func (*DataFieldHeader) HasPointer

func (h *DataFieldHeader) HasPointer() bool

HasPointer reports whether the construction rule carries the 16-bit pointer field (clause 4.1.4.2.4.1: rules '000', '001', and '010' only).

func (*DataFieldHeader) Humanize

func (h *DataFieldHeader) Humanize() string

Humanize returns a human-readable representation of the DataFieldHeader.

func (*DataFieldHeader) Size

func (h *DataFieldHeader) Size() int

Size returns the encoded size of the TFDF header in bytes: 1, or 3 when the construction rule carries a pointer.

func (*DataFieldHeader) Validate

func (h *DataFieldHeader) Validate() error

Validate checks the data field header values.

type FrameCounter

type FrameCounter struct {
	// contains filtered or unexported fields
}

FrameCounter manages Virtual Channel Frame Counts per CCSDS 732.1-B-3 Clause 4.1.2.12, keyed by VC and quality of service (clause 4.1.2.12.4-12.5: one sequence-controlled and one expedited count per VC). The count is carried in the primary header's VCF Count field, whose width (0-7 octets) is a managed parameter (clause 4.1.2.11).

func NewFrameCounter

func NewFrameCounter() *FrameCounter

NewFrameCounter creates a new FrameCounter.

func (*FrameCounter) Next

func (fc *FrameCounter) Next(vcid uint8, expedited bool) uint64

Next returns the current frame count for the given VCID and quality of service (expedited = Bypass/Sequence Control Flag set), then increments the counter. Callers mask the value to the managed VCF Count field width.

type FrameGapDetector

type FrameGapDetector struct {
	// contains filtered or unexported fields
}

FrameGapDetector tracks per-VC Virtual Channel Frame Counts to detect gaps caused by lost frames (CCSDS 732.1-B-3 clause 4.1.2.12). The count width is the managed VCF Count Length of the channel (clause 4.1.2.11). Sequence- controlled and expedited frames keep separate counts per VC (clause 4.1.2.12.4-12.5), so tracking is keyed by both the VCID and the Bypass/Sequence Control Flag.

func NewFrameGapDetector

func NewFrameGapDetector(countLen uint8) *FrameGapDetector

NewFrameGapDetector creates a detector for the given VCF Count field length in octets (0-7). With a length of zero, no count is carried and Track always reports no gap.

func (*FrameGapDetector) Track

func (d *FrameGapDetector) Track(frame *TransferFrame) int

Track examines the frame's VCF Count and records any gap. Returns the VC gap (0 means no gap or first frame).

func (*FrameGapDetector) VCFrameGap

func (d *FrameGapDetector) VCFrameGap() int

VCFrameGap returns the VC gap detected by the last Track call.

type FrameOption

type FrameOption func(*TransferFrame)

FrameOption configures optional fields on a TransferFrame.

func WithBypassSeqCtrl

func WithBypassSeqCtrl() FrameOption

WithBypassSeqCtrl marks the frame as expedited (bypass flag set).

func WithConstructionRule

func WithConstructionRule(rule uint8) FrameOption

WithConstructionRule sets the TFDZ construction rule.

func WithInsertZone

func WithInsertZone(data []byte) FrameOption

WithInsertZone sets the insert zone data.

func WithOCF

func WithOCF(ocf []byte) FrameOption

WithOCF sets the Operational Control Field. Its presence is signaled by the OCF Flag in the primary header.

func WithPointer

func WithPointer(p uint16) FrameOption

WithPointer sets the First Header Pointer / Last Valid Octet Pointer. It is encoded only for construction rules '000', '001', and '010'.

func WithProtCtrlCmd

func WithProtCtrlCmd() FrameOption

WithProtCtrlCmd marks the TFDF as carrying protocol control commands.

func WithSourceOrDest

func WithSourceOrDest(flag uint8) FrameOption

WithSourceOrDest sets the source-or-destination flag.

func WithUPID

func WithUPID(upid uint8) FrameOption

WithUPID sets the USLP Protocol Identifier.

func WithVCFCount

func WithVCFCount(countLen uint8, count uint64) FrameOption

WithVCFCount sets the Virtual Channel Frame Count and its field length in octets (0-7).

func WithoutFECF

func WithoutFECF() FrameOption

WithoutFECF omits the Frame Error Control Field. Its presence is a managed parameter of the physical channel (clause 4.1.6.2.1).

type MAPAccessService

type MAPAccessService struct {
	// contains filtered or unexported fields
}

MAPAccessService implements the MAP Access service (MAPA) for USLP: transfer of fixed-length MAPA_SDUs.

On fixed-length channels an SDU is carried under construction rule '001' (start) and, when it spans frames, rule '010' (continuation), delimited by the Last Valid Octet Pointer. On variable-length channels each SDU rides alone in a rule '111' frame.

func NewMAPAccessService

func NewMAPAccessService(scid uint16, vcid, mapid uint8, sduSize int, vc *VirtualChannel, config ChannelConfig, counter *FrameCounter) *MAPAccessService

NewMAPAccessService creates a new MAPA service instance.

func (*MAPAccessService) Flush

func (s *MAPAccessService) Flush() error

Flush is a no-op for MAPA service.

func (*MAPAccessService) Receive

func (s *MAPAccessService) Receive() ([]byte, error)

Receive returns the next complete MAPA_SDU, reassembling SDUs that span frames via the construction rules and Last Valid Octet Pointer.

func (*MAPAccessService) Send

func (s *MAPAccessService) Send(data []byte) error

Send transfers one MAPA_SDU of the configured constant length.

func (*MAPAccessService) SetOCFSupplier

func (s *MAPAccessService) SetOCFSupplier(supplier func() []byte)

SetOCFSupplier installs a callback that supplies the 4-octet Operational Control Field (typically a CLCW) for every frame emitted on a channel configured with HasOCF. Without a supplier such a channel refuses to emit frames (ErrNoOCFSupplier) rather than fabricating an all-zero Type-1 report (clause 4.1.5).

type MAPOctetStreamService

type MAPOctetStreamService struct {
	// contains filtered or unexported fields
}

MAPOctetStreamService implements the MAP Octet Stream service (MAPO) for USLP: a continuous octet-aligned stream under construction rule '011'. Per CCSDS 732.1-B-3 clause 4.2.4.1 an octet stream is carried only in variable-length Transfer Frames.

func NewMAPOctetStreamService

func NewMAPOctetStreamService(scid uint16, vcid, mapid uint8, vc *VirtualChannel, config ChannelConfig, counter *FrameCounter) *MAPOctetStreamService

NewMAPOctetStreamService creates a new MAPO service instance.

func (*MAPOctetStreamService) Flush

func (s *MAPOctetStreamService) Flush() error

Flush is a no-op for MAPO service.

func (*MAPOctetStreamService) Receive

func (s *MAPOctetStreamService) Receive() ([]byte, error)

Receive retrieves the next frame's data field.

func (*MAPOctetStreamService) Send

func (s *MAPOctetStreamService) Send(data []byte) error

Send emits the supplied octets in one rule '011' frame.

func (*MAPOctetStreamService) SetOCFSupplier

func (s *MAPOctetStreamService) SetOCFSupplier(supplier func() []byte)

SetOCFSupplier installs a callback that supplies the 4-octet Operational Control Field (typically a CLCW) for every frame emitted on a channel configured with HasOCF. Without a supplier such a channel refuses to emit frames (ErrNoOCFSupplier) rather than fabricating an all-zero Type-1 report (clause 4.1.5).

type MAPPacketService

type MAPPacketService struct {
	// contains filtered or unexported fields
}

MAPPacketService implements the MAP Packet service (MAPP) for USLP.

On fixed-length channels, packets are concatenated into fixed-length TFDZs under construction rule '000' with the First Header Pointer for boundary recovery; a partially filled final TFDZ is completed with an Encapsulation Idle Packet (clause 4.1.4.3.4). On variable-length channels, each Send emits one frame under rule '111' (No Segmentation).

func NewMAPPacketService

func NewMAPPacketService(scid uint16, vcid, mapid uint8, vc *VirtualChannel, config ChannelConfig, counter *FrameCounter) *MAPPacketService

NewMAPPacketService creates a new MAPP service instance.

func (*MAPPacketService) Flush

func (s *MAPPacketService) Flush() error

Flush completes any remaining buffered packet data with an Encapsulation Idle Packet and emits the final frame (clause 4.1.4.3.4).

func (*MAPPacketService) Receive

func (s *MAPPacketService) Receive() ([]byte, error)

Receive extracts the next complete packet from frame data.

Rule '000' fill is exactly delimited: spare TFDZ space carries Encapsulation Idle Packets (clause 4.1.4.3.4), which stripIdleEncap removes. No pattern heuristic is applied to user data, so payloads that happen to look like an idle pattern are delivered intact.

func (*MAPPacketService) Send

func (s *MAPPacketService) Send(data []byte) error

Send accepts one packet. On variable-length channels it emits one frame per packet; on fixed-length channels it buffers and emits full frames, with Flush() emitting the final partial frame.

func (*MAPPacketService) SetOCFSupplier

func (s *MAPPacketService) SetOCFSupplier(supplier func() []byte)

SetOCFSupplier installs a callback that supplies the 4-octet Operational Control Field (typically a CLCW) for every frame emitted on a channel configured with HasOCF. Without a supplier such a channel refuses to emit frames (ErrNoOCFSupplier) rather than fabricating an all-zero Type-1 report (clause 4.1.5).

func (*MAPPacketService) SetPacketSizer

func (s *MAPPacketService) SetPacketSizer(sizer PacketSizer)

SetPacketSizer configures the PacketSizer used by Receive() to detect packet boundaries.

type MasterChannel

type MasterChannel struct {
	// contains filtered or unexported fields
}

MasterChannel manages USLP Transfer Frames for a Master Channel identified by SCID.

func NewMasterChannel

func NewMasterChannel(scid uint16, config ChannelConfig) *MasterChannel

NewMasterChannel creates a new Master Channel for the given spacecraft ID.

func (*MasterChannel) AddFrame

func (mc *MasterChannel) AddFrame(frame *TransferFrame) error

AddFrame routes an inbound frame to the appropriate Virtual Channel.

func (*MasterChannel) AddVirtualChannel

func (mc *MasterChannel) AddVirtualChannel(vc *VirtualChannel, priority int)

AddVirtualChannel registers a Virtual Channel with this Master Channel.

func (*MasterChannel) GetNextFrame

func (mc *MasterChannel) GetNextFrame() (*TransferFrame, error)

GetNextFrame retrieves the next frame from the multiplexer.

func (*MasterChannel) GetNextFrameOrIdle

func (mc *MasterChannel) GetNextFrameOrIdle() (*TransferFrame, error)

GetNextFrameOrIdle returns the next frame or an OID idle frame if none is available. OID frames exist only on fixed-length physical channels. Their TFDZ is drawn from the master channel's persistent PN sequence, which is never restarted across frames (clause 4.1.4.1.10).

func (*MasterChannel) HasPendingFrames

func (mc *MasterChannel) HasPendingFrames() bool

HasPendingFrames checks if any Virtual Channel has pending frames.

func (*MasterChannel) SCID

func (mc *MasterChannel) SCID() uint16

SCID returns the Spacecraft Identifier for this Master Channel.

func (*MasterChannel) SetOCFSupplier

func (mc *MasterChannel) SetOCFSupplier(supplier func() []byte)

SetOCFSupplier installs a callback that supplies the 4-octet Operational Control Field (typically a CLCW) for the OID frames GetNextFrameOrIdle generates on a channel configured with HasOCF. Without a supplier such a channel refuses to build idle frames (ErrNoOCFSupplier) rather than fabricating an all-zero Type-1 report.

func (*MasterChannel) VCFrameGap

func (mc *MasterChannel) VCFrameGap() int

VCFrameGap returns the VC gap from the last AddFrame call.

type OIDSequence

type OIDSequence = pn.OIDSequence

OIDSequence generates the mandatory Pseudo Noise (PN) sequence that fills the TFDZ of OID Transfer Frames (CCSDS 732.1-B-3 clause 4.1.4.1.10, annex H): a 32-cell Fibonacci-form Linear Feedback Shift Register with polynomial D0 + D1 + D2 + D22 + D32, initialized to the 'all ones' state at device start-up and never restarted for subsequent frames. The first octets of the stream are FF FF FF FF 6D B6 D8 61 ... (annex H). It is safe for concurrent use.

TM mandates the same generator (CCSDS 132.0-B-3 clause 4.1.4.6.2), so the implementation is shared with pkg/tmdl rather than copied.

func NewOIDSequence

func NewOIDSequence() *OIDSequence

NewOIDSequence returns a PN generator in the 'all ones' start-up state. Keep one generator per physical channel for the life of the device; the sequence must not be restarted across OID frames (clause 4.1.4.1.10.1).

type PacketSizer

type PacketSizer = sdl.PacketSizer

PacketSizer returns the total length in bytes of the packet starting at data[0], or -1 if the data is too short to determine length.

type PhysicalChannel

type PhysicalChannel struct {
	Name string
	// contains filtered or unexported fields
}

PhysicalChannel represents a single USLP physical communication link.

func NewPhysicalChannel

func NewPhysicalChannel(name string, config ChannelConfig) *PhysicalChannel

NewPhysicalChannel creates a physical channel with the given configuration.

func (*PhysicalChannel) AddFrame

func (pc *PhysicalChannel) AddFrame(frame *TransferFrame) error

AddFrame demultiplexes an inbound frame to the appropriate Master Channel.

func (*PhysicalChannel) AddMasterChannel

func (pc *PhysicalChannel) AddMasterChannel(mc *MasterChannel, priority int)

AddMasterChannel registers a Master Channel with a priority weight.

func (*PhysicalChannel) GetNextFrame

func (pc *PhysicalChannel) GetNextFrame() (*TransferFrame, error)

GetNextFrame selects the next frame for transmission.

func (*PhysicalChannel) HasPendingFrames

func (pc *PhysicalChannel) HasPendingFrames() bool

HasPendingFrames checks if any Master Channel has pending frames.

type PrimaryHeader

type PrimaryHeader struct {
	TFVN          uint8  // 4 bits  - Transfer Frame Version Number (must be 12 = 0b1100)
	SCID          uint16 // 16 bits - Spacecraft Identifier
	SourceOrDest  uint8  // 1 bit   - 0=SCID is source, 1=SCID is destination
	VCID          uint8  // 6 bits  - Virtual Channel Identifier (0-63)
	MAPID         uint8  // 4 bits  - Multiplexer Access Point Identifier (0-15)
	EndOfFPH      bool   // 1 bit   - End of Frame Primary Header flag (truncated header)
	FrameLength   uint16 // 16 bits - total frame octets minus 1 (non-truncated only)
	BypassSeqCtrl bool   // 1 bit   - Bypass/Sequence Control flag (1 = expedited)
	ProtCtrlCmd   bool   // 1 bit   - Protocol Control Command flag (1 = protocol control)
	OCFFlag       bool   // 1 bit   - Operational Control Field present
	VCFCountLen   uint8  // 3 bits  - VCF Count field length in octets (0-7)
	VCFCount      uint64 // 0-56 bits - Virtual Channel Frame Count
}

PrimaryHeader represents the USLP Transfer Frame Primary Header.

Bit layout (CCSDS 732.1-B-3 clause 4.1.2):

Byte 0:  TFVN[3:0]    | SCID[15:12]
Byte 1:  SCID[11:4]
Byte 2:  SCID[3:0]    | SourceOrDest | VCID[5:3]
Byte 3:  VCID[2:0]    | MAPID[3:0]   | EndOfFPH

EndOfFPH = 1 marks the truncated header, which is exactly these 4 octets (annex D). A non-truncated header (EndOfFPH = 0) continues:

Bytes 4-5: Frame Length (total octets - 1)
Byte 6:    Bypass/SeqCtrl | ProtCtrlCmd | spares(2) | OCFFlag | VCFCountLen[2:0]
Bytes 7+:  VCF Count (VCFCountLen octets, big-endian)

func (*PrimaryHeader) Decode

func (h *PrimaryHeader) Decode(data []byte) error

Decode parses a byte slice into the PrimaryHeader.

func (*PrimaryHeader) Encode

func (h *PrimaryHeader) Encode() ([]byte, error)

Encode packs the PrimaryHeader fields into a byte slice.

func (*PrimaryHeader) GMAPID

func (h *PrimaryHeader) GMAPID() uint32

GMAPID returns the Global MAP Identifier (GVCID + MAP ID).

func (*PrimaryHeader) GVCID

func (h *PrimaryHeader) GVCID() uint32

GVCID returns the Global Virtual Channel Identifier (MCID + VCID).

func (*PrimaryHeader) Humanize

func (h *PrimaryHeader) Humanize() string

Humanize returns a human-readable representation of the PrimaryHeader.

func (*PrimaryHeader) MCID

func (h *PrimaryHeader) MCID() uint32

MCID returns the Master Channel Identifier (TFVN + SCID).

func (*PrimaryHeader) Size

func (h *PrimaryHeader) Size() int

Size returns the encoded size of the primary header in bytes.

func (*PrimaryHeader) Validate

func (h *PrimaryHeader) Validate() error

Validate checks that header values are within their bit-field widths.

type Service

type Service = sdl.Service

Service is the interface for all USLP Data Link services.

type ServiceType

type ServiceType int

ServiceType identifies the USLP service carried on a MAP channel.

const (
	MAPP ServiceType = iota // MAP Packet Service
	MAPA                    // MAP Access Service
	MAPO                    // MAP Octet Stream Service
)

type TransferFrame

type TransferFrame struct {
	Header          PrimaryHeader
	InsertZone      []byte          // optional, fixed length per physical channel
	DataFieldHeader DataFieldHeader // TFDF header
	DataField       []byte          // Transfer Frame Data Zone (TFDZ)
	OCF             []byte          // 4 bytes when present (signaled by OCFFlag)
	FECF            []byte          // Frame Error Control Field (16-bit CRC)
	HasFECF         bool            // FECF present (managed per physical channel)
}

TransferFrame represents a USLP Transfer Frame per CCSDS 732.1-B-3.

Layout: PrimaryHeader | InsertZone? | TFDF Header | TFDZ | OCF? | FECF?

Truncated frames (annex D) carry only the 4-octet primary header, a 1-octet TFDF header, and the TFDZ: no insert zone, OCF, or FECF.

func DecodeTransferFrame

func DecodeTransferFrame(data []byte, fecSize int, insertZoneLen int) (*TransferFrame, error)

DecodeTransferFrame parses a byte slice into a USLP Transfer Frame.

fecSize is the managed FECF presence for the physical channel: 0 (absent) or FECSize16 (clause 4.1.6.2.2: the FECF, when present, is the last 16 bits of the frame). insertZoneLen is the managed insert zone length (0 if none). OCF presence is signaled in-band by the OCF Flag. Truncated frames (EndOfFPH set) carry no insert zone, OCF, or FECF, regardless of the managed parameters.

func NewIdleFrame

func NewIdleFrame(scid uint16, config ChannelConfig, fill *OIDSequence, ocf []byte) (*TransferFrame, error)

NewIdleFrame creates an OID (Only Idle Data) Transfer Frame per CCSDS 732.1-B-3 clause 4.1.4.1: VCID 63, MAP ID 0, construction rule '001' with the Last Valid Octet Pointer set to the last TFDZ octet, UPID 'Idle Data', and a TFDZ filled from the mandatory PN sequence (clause 4.1.4.1.10). OID frames exist only on fixed-length physical channels.

fill is the channel's persistent PN generator; passing nil starts a fresh sequence for this frame only, which is fine for a single frame but violates the never-restarted rule across frames, long-lived senders must keep one OIDSequence (MasterChannel does). ocf supplies the 4-octet Operational Control Field when config.HasOCF is set; with HasOCF and no OCF the frame is refused rather than fabricating an all-zero report.

func NewTransferFrame

func NewTransferFrame(scid uint16, vcid, mapid uint8, data []byte, opts ...FrameOption) (*TransferFrame, error)

NewTransferFrame creates a new non-truncated USLP Transfer Frame. The frame length field is computed from the frame contents, the OCF flag from OCF presence, and the FECF (present by default) from the encoded frame.

func NewTruncatedFrame

func NewTruncatedFrame(scid uint16, vcid, mapid uint8, data []byte, opts ...FrameOption) (*TransferFrame, error)

NewTruncatedFrame creates a truncated USLP Transfer Frame (annex D): a 4-octet primary header, a 1-octet TFDF header with construction rule '111' (No Segmentation), and the TFDZ. Truncated frames carry no insert zone, OCF, or FECF, and are allowed only on variable-length virtual channels. The TFDZ must hold at least one octet (annex D1.3.2 note 2: minimum total length 6 octets) and at most 27 (annex D1.4.2.4: maximum total length 32 octets).

func (*TransferFrame) Encode

func (f *TransferFrame) Encode() ([]byte, error)

Encode converts the USLP Transfer Frame to a byte slice.

The frame length field and the Frame Error Control Field are refreshed from the frame's current contents on every call, so changes made after construction are always covered. Use EncodeWithoutFECF to build a frame with a deliberately invalid FECF.

func (*TransferFrame) EncodeWithoutFECF

func (f *TransferFrame) EncodeWithoutFECF() ([]byte, error)

EncodeWithoutFECF serializes the frame excluding the Frame Error Control Field. Use it to build frames with a deliberately invalid FECF; Encode always writes a correct one.

func (*TransferFrame) Humanize

func (f *TransferFrame) Humanize() string

Humanize returns a human-readable representation of the TransferFrame.

type USDLServiceManager

type USDLServiceManager = sdl.ServiceManager[ServiceType, *TransferFrame]

USDLServiceManager manages multiple USLP services and Master Channels.

func NewUSDLServiceManager

func NewUSDLServiceManager() *USDLServiceManager

NewUSDLServiceManager creates a new USLP Service Manager.

type VirtualChannel

type VirtualChannel struct {
	*sdl.Channel[*TransferFrame]
	// contains filtered or unexported fields
}

VirtualChannel is a frame buffer for a single USLP virtual channel. It owns the MAP demultiplexer for the up-to-16 MAP channels it carries (clause 4.3): services pull their own MAP's frames via NextForMAP, and frames for other MAP channels are held for their services rather than lost.

func NewVirtualChannel

func NewVirtualChannel(vcid uint8, bufferSize int) *VirtualChannel

NewVirtualChannel creates a new USLP Virtual Channel with the given VCID and buffer capacity.

func (*VirtualChannel) NextForMAP

func (vc *VirtualChannel) NextForMAP(mapid uint8) (*TransferFrame, error)

NextForMAP returns the next frame for the given MAP channel. Frames of other MAP IDs pulled from the shared VC buffer are queued for their own services instead of being discarded (clause 4.3 MAP demultiplexing); OID frames carry no service data and are dropped.

type VirtualChannelMultiplexer

type VirtualChannelMultiplexer = sdl.Multiplexer[*TransferFrame]

VirtualChannelMultiplexer is a weighted round-robin frame scheduler for USLP Virtual Channels.

func NewMultiplexer

func NewMultiplexer() *VirtualChannelMultiplexer

NewMultiplexer creates a new USLP Virtual Channel multiplexer.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL