Documentation
¶
Index ¶
- Constants
- Variables
- func IsIdleFrame(frame *TMTransferFrame) bool
- type ChannelConfig
- type FrameCounter
- type FrameGapDetector
- type MasterChannel
- func (mc *MasterChannel) AddFrame(frame *TMTransferFrame) error
- func (mc *MasterChannel) AddVirtualChannel(vc *VirtualChannel, priority int)
- func (mc *MasterChannel) GetNextFrame() (*TMTransferFrame, error)
- func (mc *MasterChannel) GetNextFrameOrIdle() (*TMTransferFrame, error)
- func (mc *MasterChannel) HasPendingFrames() bool
- func (mc *MasterChannel) LastFSH() []byte
- func (mc *MasterChannel) LastOCF() []byte
- func (mc *MasterChannel) MCFrameGap() int
- func (mc *MasterChannel) SCID() uint16
- func (mc *MasterChannel) SetFSHSupplier(supplier func() []byte)
- func (mc *MasterChannel) SetFrameCounter(counter *FrameCounter)
- func (mc *MasterChannel) SetIdleVCID(vcid uint8)
- func (mc *MasterChannel) SetOCFSupplier(supplier func() []byte)
- func (mc *MasterChannel) VCFrameGap() int
- type OIDSequence
- type PacketSizer
- type PhysicalChannel
- func (pc *PhysicalChannel) AddFrame(frame *TMTransferFrame) error
- func (pc *PhysicalChannel) AddMasterChannel(mc *MasterChannel, priority int)
- func (pc *PhysicalChannel) GetNextFrame() (*TMTransferFrame, error)
- func (pc *PhysicalChannel) GetNextFrameOrIdle() (*TMTransferFrame, error)
- func (pc *PhysicalChannel) HasPendingFrames() bool
- func (pc *PhysicalChannel) Len() int
- type PrimaryHeader
- type SecondaryHeader
- type Service
- type ServiceType
- type TMServiceManager
- type TMTransferFrame
- func DecodeTMTransferFrame(data []byte) (*TMTransferFrame, error)
- func DecodeTMTransferFrameWithConfig(data []byte, config ChannelConfig) (*TMTransferFrame, error)
- func NewIdleFrame(scid uint16, vcid uint8, config ChannelConfig) (*TMTransferFrame, error)
- func NewIdleFrameWithCounter(scid uint16, vcid uint8, config ChannelConfig, counter *FrameCounter, ...) (*TMTransferFrame, error)
- func NewTMTransferFrame(scid uint16, vcid uint8, data []byte, secondaryHeaderData []byte, ocf []byte) (*TMTransferFrame, error)
- type VCAStatus
- type VirtualChannel
- type VirtualChannelAccessService
- func (s *VirtualChannelAccessService) Flush() error
- func (s *VirtualChannelAccessService) LastFSH() []byte
- func (s *VirtualChannelAccessService) LastStatus() VCAStatus
- func (s *VirtualChannelAccessService) Receive() ([]byte, error)
- func (s *VirtualChannelAccessService) Send(data []byte) error
- func (s *VirtualChannelAccessService) SetFSHSupplier(supplier func() []byte)
- func (s *VirtualChannelAccessService) SetOCFSupplier(supplier func() []byte)
- func (s *VirtualChannelAccessService) SetSendStatus(status VCAStatus)
- type VirtualChannelFrameService
- type VirtualChannelMultiplexer
- type VirtualChannelPacketService
- func (s *VirtualChannelPacketService) Flush() error
- func (s *VirtualChannelPacketService) LastFSH() []byte
- func (s *VirtualChannelPacketService) Receive() ([]byte, error)
- func (s *VirtualChannelPacketService) Send(data []byte) error
- func (s *VirtualChannelPacketService) SetFSHSupplier(supplier func() []byte)
- func (s *VirtualChannelPacketService) SetGapResync(enabled bool)
- func (s *VirtualChannelPacketService) SetOCFSupplier(supplier func() []byte)
- func (s *VirtualChannelPacketService) SetPacketSizer(sizer PacketSizer)
Constants ¶
const ( // FHPNoPacketStart means no packet begins in this data field. FHPNoPacketStart uint16 = 0x07FF // FHPOnlyIdleData marks an OID frame: the data field is entirely idle. FHPOnlyIdleData uint16 = 0x07FE )
FirstHeaderPtr values with a meaning of their own, from CCSDS 132.0-B-3 Clause 4.1.2.7.6 and ECSS-E-ST-50-03C 5.2.7.6f and g.
The two are not interchangeable. A frame whose data field simply continues a packet started earlier says NoPacketStart; a frame that is nothing but fill says OnlyIdleData. Telling them apart is the whole reason there are two codes: the first still carries payload, the second can be dropped.
const IdleFrameVCID uint8 = 7
IdleFrameVCID is the fallback virtual channel for idle frames when the caller knows no better. CCSDS 132.0-B-3 clause 4.1.4.6.3 requires the VCID of an OID frame to be one of the VCIDs used for transferring packets, so MasterChannel picks a registered packet VCID instead; this constant is used only when no virtual channel is registered at all, where no conformant choice exists.
const MaxFrameLength = 2048
MaxFrameLength is the longest TM Transfer Frame ECSS-E-ST-50-03C 5.1b allows, in octets.
CCSDS 132.0-B-3 sets no such ceiling; this is the European profile constraining it. A mission following CCSDS alone may exceed it, so the limit is checked by Validate rather than enforced silently.
const MaxSecondaryHeaderSize = 64
MaxSecondaryHeaderSize is the largest Transfer Frame Secondary Header, counting the identification octet: CCSDS 132.0-B-3 clause 4.1.3.2 and ECSS-E-ST-50-03C 5.3.1c both cap it at 64 octets.
Variables ¶
var ( // ErrDataTooShort indicates the provided data is too short for decoding. ErrDataTooShort = errors.New("provided data is too short to decode") // ErrInvalidVersion indicates the version number is not 0 for TM Transfer Frame. ErrInvalidVersion = errors.New("invalid version: must be 0 for TM Transfer Frame") // ErrInvalidSpacecraftID indicates the spacecraft ID is out of range. ErrInvalidSpacecraftID = errors.New("invalid spacecraft ID: must be in range 0-1023 (10 bits)") // ErrInvalidVCID indicates the virtual channel ID is out of range. ErrInvalidVCID = errors.New("invalid virtual channel ID: must be in range 0-7 (3 bits)") // ErrInvalidPacketOrderFlag indicates the packet order flag is set when sync flag is 0. ErrInvalidPacketOrderFlag = errors.New("invalid packet order flag: must be 0 when sync flag is 0") // ErrInvalidSegmentLengthID indicates the segment length ID is invalid for the current sync flag. ErrInvalidSegmentLengthID = errors.New("invalid segment length ID: must be 3 (0b11) when sync flag is 0") // ErrInvalidFirstHeaderPtr indicates the first header pointer is out of range or inconsistent. ErrInvalidFirstHeaderPtr = errors.New("invalid first header pointer: must be in range 0-2047 (11 bits)") // ErrInvalidSecondaryHeaderVersion indicates the secondary header version is not 0. ErrInvalidSecondaryHeaderVersion = errors.New("invalid secondary header version: must be 0 for Version 1") // ErrFrameTooLong indicates a frame length past the 2048-octet maximum of // ECSS-E-ST-50-03C 5.1b. ErrFrameTooLong = errors.New("frame length exceeds the 2048-octet ECSS maximum") // ErrInvalidHeaderLength indicates the secondary header length is out of range. ErrInvalidHeaderLength = errors.New("invalid header length: must be in range 0-63 (6 bits)") // 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") // 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") // ErrSizeMismatch indicates the data size does not match the expected fixed size. ErrSizeMismatch = errors.New("data size does not match expected fixed size") // 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 VCP service. ErrNoPacketSizer = errors.New("no PacketSizer configured: call SetPacketSizer before Receive") // ErrNoMasterChannels aliases sdl.ErrNoMasterChannels. ErrNoMasterChannels = sdl.ErrNoMasterChannels // ErrInvalidOCFLength indicates the Operational Control Field is not exactly 4 bytes. ErrInvalidOCFLength = errors.New("operational control field must be exactly 4 bytes when OCF flag is set") // ErrFrameLengthMismatch indicates a frame whose encoded length differs // from the fixed ChannelConfig.FrameLength of its physical channel. ErrFrameLengthMismatch = errors.New("frame length does not match the fixed channel frame length") // ErrFSHNotPresent indicates an FSH_SDU was supplied for a channel whose // frames carry no Transfer Frame Secondary Header. Set // ChannelConfig.FSHDataLength so the frames have a header to fill. ErrFSHNotPresent = errors.New("frame secondary header service configured but frames carry no secondary header") // ErrOCFNotPresent indicates an OCF_SDU was supplied for a channel whose // frames carry no Operational Control Field. Set ChannelConfig.HasOCF. ErrOCFNotPresent = errors.New("operational control field service configured but frames carry no OCF") // ErrFSHSizeMismatch indicates an FSH_SDU whose length differs from the // channel's fixed ChannelConfig.FSHDataLength. CCSDS 132.0-B-3 clause 4.1.3.1.6 // fixes the secondary header length for the channel, so a differently // sized SDU cannot be carried. ErrFSHSizeMismatch = errors.New("FSH_SDU length does not match the channel's fixed secondary header length") )
Functions ¶
func IsIdleFrame ¶
func IsIdleFrame(frame *TMTransferFrame) bool
IsIdleFrame reports whether the frame is an OID frame: a data field holding nothing but idle data, per ECSS-E-ST-50-03C 5.2.7.6g.
FHPNoPacketStart is deliberately not accepted here. A frame carrying the continuation of a packet started in an earlier frame also has no packet header in it, and discarding that as idle would lose real payload.
Types ¶
type ChannelConfig ¶
type ChannelConfig struct {
FrameLength int // Total frame length in octets (fixed per physical channel)
HasOCF bool // Whether Operational Control Field (4 bytes) is present
HasFEC bool // Whether Frame Error Control (2-byte CRC) is present
// FSHDataLength is the length in octets of the Transfer Frame Secondary
// Header Data Field carried by every frame on the channel, or 0 when the
// channel carries no secondary header. CCSDS 132.0-B-3 clause 4.1.3.1.6 fixes
// the secondary header length for the associated channel throughout a
// Mission Phase, which is why it is channel configuration rather than a
// per-frame choice. The encoded header adds one identification octet, so
// a value of N costs N+1 octets of frame space. Range 1 to 63.
//
// Services fill the header from their FSH supplier (the VC_FSH service of
// Clause 3.5) or with zeros when none is installed; MasterChannel's supplier
// (the MC_FSH service of clause 3.8) overwrites it at frame release.
FSHDataLength int
}
ChannelConfig defines the fixed parameters of a physical channel per CCSDS 132.0-B-3. All frames on a physical channel share the same fixed length and optional field configuration.
func (ChannelConfig) DataFieldCapacity ¶
func (c ChannelConfig) DataFieldCapacity(secondaryHeaderLen int) int
DataFieldCapacity returns the maximum data field size available in frames on this physical channel. secondaryHeaderLen is the length of the secondary header data field (0 if not present); when present, the encoded secondary header adds 1 prefix byte plus secondaryHeaderLen data bytes.
func (ChannelConfig) Validate ¶ added in v0.3.0
func (c ChannelConfig) Validate() error
Validate checks the configuration against the profile limits.
It is not called automatically: a CCSDS-only mission may legitimately run frames longer than the ECSS ceiling. Call it when conformance to ECSS-E-ST-50-03C matters.
type FrameCounter ¶
type FrameCounter struct {
// contains filtered or unexported fields
}
FrameCounter manages 8-bit MC and VC frame counts per CCSDS 132.0-B-3. Share a single FrameCounter across all services for the same spacecraft so the Master Channel count increments correctly.
func NewFrameCounter ¶
func NewFrameCounter() *FrameCounter
NewFrameCounter creates a new FrameCounter.
func (*FrameCounter) Next ¶
func (fc *FrameCounter) Next(vcid uint8) (mc, vc uint8)
Next returns the current MC and VC frame counts for the given VCID, then increments both counters.
type FrameGapDetector ¶
type FrameGapDetector struct {
// contains filtered or unexported fields
}
FrameGapDetector tracks Master Channel and Virtual Channel frame counts to detect gaps caused by lost frames during transmission. Per CCSDS 132.0-B-3, MCFrameCount and VCFrameCount are 8-bit counters that wrap from 255 to 0.
func NewFrameGapDetector ¶
func NewFrameGapDetector() *FrameGapDetector
NewFrameGapDetector creates a new detector. The first frame seen initializes the expected counts (no gap reported).
func (*FrameGapDetector) MCFrameGap ¶
func (d *FrameGapDetector) MCFrameGap() int
MCFrameGap returns the MC gap detected by the last Track call. 0 means no gap (or first frame).
func (*FrameGapDetector) Track ¶
func (d *FrameGapDetector) Track(frame *TMTransferFrame) (mcGap, vcGap int)
Track examines the frame's MC and VC counts and records any gaps. A gap of N means N frames were lost between the previous frame and this one. Returns the MC gap and VC gap for convenience.
func (*FrameGapDetector) VCFrameGap ¶
func (d *FrameGapDetector) VCFrameGap() int
VCFrameGap returns the VC gap detected by the last Track call. 0 means no gap (or first frame for that VCID).
type MasterChannel ¶
type MasterChannel struct {
// contains filtered or unexported fields
}
MasterChannel manages TM 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 *TMTransferFrame) error
AddFrame routes an inbound frame to the appropriate Virtual Channel.
Before routing, the Master Channel Reception Function of CCSDS 132.0-B-3 Clause 4.3.5 decommutates the frame: the secondary header and operational control field SDUs are recorded and readable from LastFSH and LastOCF, which is the delivery path of MC_FSH.indication and MC_OCF.indication.
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() (*TMTransferFrame, error)
GetNextFrame retrieves the next frame from the multiplexer, applying the Master Channel Generation Function of CCSDS 132.0-B-3 clause 4.2.5: the MC_FSH and MC_OCF SDUs, when suppliers are installed, are placed into the frame before it is released.
func (*MasterChannel) GetNextFrameOrIdle ¶
func (mc *MasterChannel) GetNextFrameOrIdle() (*TMTransferFrame, error)
GetNextFrameOrIdle returns the next frame or an idle (OID) frame if none is available, which is the Virtual Channel Multiplexing Function's duty under CCSDS 132.0-B-3 clause 4.2.4.4: keep the transmitted stream continuous.
Idle frames are stamped from the FrameCounter installed with SetFrameCounter, so their MC and VC frame counts continue the channel's sequence (clause 4.1.2.5); without a counter they carry zeros. Their data field is filled from the channel's persistent PN generator (clause 4.1.4.6.2) and their VCID is one that carries packets (clause 4.1.4.6.3). MC_FSH and MC_OCF SDUs are applied to them like any other released frame.
func (*MasterChannel) HasPendingFrames ¶
func (mc *MasterChannel) HasPendingFrames() bool
HasPendingFrames checks if any Virtual Channel has pending frames.
func (*MasterChannel) LastFSH ¶ added in v0.3.0
func (mc *MasterChannel) LastFSH() []byte
LastFSH returns the FSH_SDU carried by the most recently received frame, or nil when none has carried one. It is the MC_FSH.indication of clause 3.8.3.3; pair it with MCFrameGap for the optional FSH_SDU Loss Flag.
func (*MasterChannel) LastOCF ¶ added in v0.3.0
func (mc *MasterChannel) LastOCF() []byte
LastOCF returns the OCF_SDU carried by the most recently received frame, or nil when none has carried one. It is the MC_OCF.indication of clause 3.9.3.3; pair it with MCFrameGap for the optional OCF_SDU Loss Flag.
func (*MasterChannel) MCFrameGap ¶
func (mc *MasterChannel) MCFrameGap() int
MCFrameGap returns the MC gap from the last AddFrame call.
func (*MasterChannel) SCID ¶
func (mc *MasterChannel) SCID() uint16
SCID returns the Spacecraft Identifier for this Master Channel.
func (*MasterChannel) SetFSHSupplier ¶ added in v0.3.0
func (mc *MasterChannel) SetFSHSupplier(supplier func() []byte)
SetFSHSupplier installs the MC_FSH service user (CCSDS 132.0-B-3 clause 3.8): a callback whose FSH_SDU is placed into the Transfer Frame Secondary Header of every frame released through this Master Channel, per the Master Channel Generation Function of clause 4.2.5.2. The SDU must be exactly the channel's ChannelConfig.FSHDataLength octets, and frames must carry a secondary header for it to fill, set FSHDataLength on the channel configuration.
func (*MasterChannel) SetFrameCounter ¶ added in v0.3.0
func (mc *MasterChannel) SetFrameCounter(counter *FrameCounter)
SetFrameCounter installs the shared FrameCounter used to stamp the MC and VC frame counts of idle frames created by GetNextFrameOrIdle. Pass the same counter the channel's services use, so idle frames continue the master channel count per CCSDS 132.0-B-3 clause 4.1.2.5 instead of carrying zeros.
func (*MasterChannel) SetIdleVCID ¶ added in v0.3.0
func (mc *MasterChannel) SetIdleVCID(vcid uint8)
SetIdleVCID pins the VCID that idle (OID) frames from GetNextFrameOrIdle are emitted on. CCSDS 132.0-B-3 clause 4.1.4.6.3 requires it to be one of the VCIDs used for transferring packets. Without an explicit choice, the lowest registered Virtual Channel's VCID is used.
func (*MasterChannel) SetOCFSupplier ¶ added in v0.3.0
func (mc *MasterChannel) SetOCFSupplier(supplier func() []byte)
SetOCFSupplier installs the MC_OCF service user (CCSDS 132.0-B-3 clause 3.9): a callback whose 4-octet OCF_SDU is placed into the Operational Control Field of every frame released through this Master Channel, per clause 4.2.5.3. Frames must carry an OCF for it to fill, set HasOCF on the channel configuration.
func (*MasterChannel) VCFrameGap ¶
func (mc *MasterChannel) VCFrameGap() int
VCFrameGap returns the VC gap from the last AddFrame call.
type OIDSequence ¶ added in v0.3.0
type OIDSequence = pn.OIDSequence
OIDSequence generates the mandatory Pseudo Noise (PN) sequence that fills the data field of OID Transfer Frames (CCSDS 132.0-B-3 clause 4.1.4.6.2, annex D): 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 45 1F. It is safe for concurrent use.
USLP mandates the same generator (CCSDS 732.1-B-3 clause 4.1.4.1.10), so the implementation is shared with pkg/usdl rather than copied.
func NewOIDSequence ¶ added in v0.3.0
func NewOIDSequence() *OIDSequence
NewOIDSequence returns a PN generator in the 'all ones' start-up state. Keep one generator per channel for the life of the device; clause 4.1.4.6.2.1 forbids restarting the sequence across OID frames.
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 // Channel identifier (e.g., "X-band")
// contains filtered or unexported fields
}
PhysicalChannel represents a single physical communication link that carries one or more Master Channels. It handles MC-level multiplexing (send path) and demultiplexing (receive path) per CCSDS 132.0-B-3. For sync-layer operations (ASM, randomization, CADU wrapping), use the tmsc package (CCSDS 131.0-B-5).
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 *TMTransferFrame) error
AddFrame demultiplexes an inbound frame to the appropriate Master Channel based on the Spacecraft ID in the frame header.
func (*PhysicalChannel) AddMasterChannel ¶
func (pc *PhysicalChannel) AddMasterChannel(mc *MasterChannel, priority int)
AddMasterChannel registers a Master Channel with a priority weight for the MC multiplexing scheme. Priority must be at least 1.
func (*PhysicalChannel) GetNextFrame ¶
func (pc *PhysicalChannel) GetNextFrame() (*TMTransferFrame, error)
GetNextFrame selects the next frame for transmission using weighted round-robin MC multiplexing across registered Master Channels.
func (*PhysicalChannel) GetNextFrameOrIdle ¶
func (pc *PhysicalChannel) GetNextFrameOrIdle() (*TMTransferFrame, error)
GetNextFrameOrIdle returns the next frame from MC multiplexing, or an idle frame if no Master Channel has pending data.
The idle frame comes from a deterministically chosen Master Channel (the lowest registered SCID) which builds it per CCSDS 132.0-B-3 clause 4.2.6.4: on a packet-carrying VCID, counted by the channel's FrameCounter, filled from its persistent PN generator, and carrying its MC_FSH/MC_OCF SDUs when suppliers are installed. With no Master Channel registered at all, a bare idle frame is produced with SCID 0 and the fallback IdleFrameVCID, drawing on the physical channel's own PN generator.
func (*PhysicalChannel) HasPendingFrames ¶
func (pc *PhysicalChannel) HasPendingFrames() bool
HasPendingFrames checks if any Master Channel has pending frames.
func (*PhysicalChannel) Len ¶
func (pc *PhysicalChannel) Len() int
Len returns the number of registered Master Channels.
type PrimaryHeader ¶
type PrimaryHeader struct {
VersionNumber uint8 // 2 bits (0-1) - Transfer Frame Version Number (00 for TM)
SpacecraftID uint16 // 10 bits (2-11) - Spacecraft Identifier
VirtualChannelID uint8 // 3 bits (12-14) - Virtual Channel Identifier
OCFFlag bool // 1 bit (15) - Operational Control Field Flag
MCFrameCount uint8 // 8 bits (16-23) - Master Channel Frame Count
VCFrameCount uint8 // 8 bits (24-31) - Virtual Channel Frame Count
FSHFlag bool // 1 bit (32) - Frame Secondary Header Flag
SyncFlag bool // 1 bit (33) - Synchronization Flag
PacketOrderFlag bool // 1 bit (34) - Packet Order Flag
SegmentLengthID uint8 // 2 bits (35-36) - Segment Length Identifier
FirstHeaderPtr uint16 // 11 bits (37-47) - First Header Pointer
}
PrimaryHeader represents the CCSDS TM Transfer Frame Primary Header.
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) GVCID ¶
func (h *PrimaryHeader) GVCID() uint16
GVCID returns the Global Virtual Channel Identifier.
func (*PrimaryHeader) Humanize ¶
func (h *PrimaryHeader) Humanize() string
Humanize generates a human-readable representation of the PrimaryHeader.
func (*PrimaryHeader) MCID ¶
func (h *PrimaryHeader) MCID() uint16
MCID returns the Master Channel Identifier (MCID) for the TM Transfer Frame.
func (*PrimaryHeader) Validate ¶
func (h *PrimaryHeader) Validate() error
Validate checks if the header values are within valid ranges.
With the Synchronization Flag set, the Packet Order Flag, Segment Length Identifier, and First Header Pointer are undefined by CCSDS 132.0-B-3 (notes under clause 4.1.2.7.4 through clause 4.1.2.7.6), and clause 3.4.2.3 hands those bits to the VCA service user as the VCA Status Fields, so any value passes here. With the flag clear, the Packet Order Flag must be '0' and the Segment Length Identifier '11'.
type SecondaryHeader ¶
type SecondaryHeader struct {
VersionNumber uint8 // 2 bits (0-1) - Always `00` for Version 1
// HeaderLength is the field of bits 2-7. CCSDS 132.0-B-3 clause 4.1.3.2.2.3 and
// ECSS-E-ST-50-03C 5.3.2.3c define it as the TOTAL secondary header length
// in octets minus one, the total being this identification octet plus the
// data field. So for an N-octet data field the value is N, not N-1.
HeaderLength uint8
DataField []byte // Transfer Frame Secondary Header Data
}
SecondaryHeader represents the Transfer Frame Secondary Header as per CCSDS 132.0-B-3.
func (*SecondaryHeader) Decode ¶
func (sh *SecondaryHeader) Decode(data []byte) error
Decode deserializes a byte slice into the SecondaryHeader.
func (*SecondaryHeader) Encode ¶
func (sh *SecondaryHeader) Encode() ([]byte, error)
Encode serializes the SecondaryHeader into a byte slice.
func (*SecondaryHeader) Humanize ¶
func (sh *SecondaryHeader) Humanize() string
Humanize generates a human-readable representation of the SecondaryHeader.
func (*SecondaryHeader) SetDataField ¶ added in v0.3.0
func (sh *SecondaryHeader) SetDataField(data []byte) error
SetDataField installs the data field and derives HeaderLength from it, which is the safe way to build a secondary header by hand.
func (*SecondaryHeader) TotalLength ¶ added in v0.3.0
func (sh *SecondaryHeader) TotalLength() int
TotalLength returns the encoded size of the secondary header in octets.
func (*SecondaryHeader) Validate ¶
func (sh *SecondaryHeader) Validate() error
Validate checks if the header values are within valid ranges.
type ServiceType ¶
type ServiceType int
ServiceType defines the types of TM services available.
const ( VCP ServiceType = iota // Virtual Channel Packet Service VCA // Virtual Channel Access Service VCF // Virtual Channel Frame Service )
type TMServiceManager ¶
type TMServiceManager = sdl.ServiceManager[ServiceType, *TMTransferFrame]
TMServiceManager manages multiple TM services and Master Channels, wiring the pipeline: Service -> VirtualChannel -> Mux -> MasterChannel.
func NewTMServiceManager ¶
func NewTMServiceManager() *TMServiceManager
NewTMServiceManager creates a new TM Service Manager.
type TMTransferFrame ¶
type TMTransferFrame struct {
Header PrimaryHeader
SecondaryHeader SecondaryHeader
DataField []byte // Main telemetry data
OperationalControl []byte // 4-byte OCF (if used)
FrameErrorControl uint16 // 16-bit CRC (Error Control)
}
TMTransferFrame represents a CCSDS TM Space Data Link Protocol Transfer Frame.
func DecodeTMTransferFrame ¶
func DecodeTMTransferFrame(data []byte) (*TMTransferFrame, error)
DecodeTMTransferFrame parses a byte slice into a TM Transfer Frame, treating the last two octets as a Frame Error Control Field and verifying them.
Use DecodeTMTransferFrameWithConfig for a channel that carries no such field, which clause 5.6.1b permits under Reed-Solomon coding.
func DecodeTMTransferFrameWithConfig ¶ added in v0.3.0
func DecodeTMTransferFrameWithConfig(data []byte, config ChannelConfig) (*TMTransferFrame, error)
DecodeTMTransferFrameWithConfig parses a frame, verifying the Frame Error Control Field only when the channel carries one.
When config.FrameLength is set, the input must be exactly that long ( frames on a physical channel are fixed-length per CCSDS 132.0-B-3 clause 2.1.3) and any other size returns ErrFrameLengthMismatch.
func NewIdleFrame ¶
func NewIdleFrame(scid uint16, vcid uint8, config ChannelConfig) (*TMTransferFrame, error)
NewIdleFrame creates an idle (OID) TM Transfer Frame: a PN-filled data field with the First Header Pointer set to FHPOnlyIdleData, per CCSDS 132.0-B-3 clause 4.1.2.7.6.5 and clause 4.1.4.6.
The frame's MC and VC counts are zero and its PN sequence starts fresh. Use NewIdleFrameWithCounter so idle frames continue the master channel sequence and draw from the channel's persistent PN generator.
func NewIdleFrameWithCounter ¶ added in v0.3.0
func NewIdleFrameWithCounter(scid uint16, vcid uint8, config ChannelConfig, counter *FrameCounter, fill *OIDSequence) (*TMTransferFrame, error)
NewIdleFrameWithCounter creates an idle (OID) TM Transfer Frame, stamps its MC and VC frame counts from the given counter, and fills its data field from the given PN generator.
Pass the same FrameCounter the channel's services use: CCSDS 132.0-B-3 Clause 4.1.2.5 counts every frame of the master channel, idle frames included, so an unstamped idle frame breaks the MC sequence at any conformant receiver. A nil counter leaves both counts zero.
Pass the channel's persistent OIDSequence: Clause 4.1.4.6.2 mandates the PN fill and forbids restarting the generator between frames. A nil fill starts a fresh sequence for this frame only, which is fine for a single frame but repeats the same octets on every frame of a long-lived sender, MasterChannel keeps one generator for exactly this reason.
When the channel carries a secondary header (config.FSHDataLength > 0) the idle frame includes a zero-filled one: Clause 4.1.2.7.2.3 keeps the Secondary Header Flag static across the channel, and the OID notes under clause 4.1.4.6 expect the header to stay usable on idle frames. MasterChannel overwrites it from the MC_FSH supplier when one is installed. The same applies to the Operational Control Field under config.HasOCF.
func NewTMTransferFrame ¶
func NewTMTransferFrame(scid uint16, vcid uint8, data []byte, secondaryHeaderData []byte, ocf []byte) (*TMTransferFrame, error)
NewTMTransferFrame initializes a new TM Transfer Frame.
func (*TMTransferFrame) Encode ¶
func (tf *TMTransferFrame) Encode() ([]byte, error)
Encode converts the TM Transfer Frame to a byte slice.
The Frame Error Control Field is computed from the frame's current contents on every call, so header or data changes made after construction are always covered. Use EncodeWithoutFEC to build a frame with a deliberately invalid CRC.
func (*TMTransferFrame) EncodeWithConfig ¶ added in v0.3.0
func (tf *TMTransferFrame) EncodeWithConfig(config ChannelConfig) ([]byte, error)
EncodeWithConfig converts the frame to bytes, appending the Frame Error Control Field only when the channel carries one.
CCSDS 132.0-B-3 clause 4.1.6 and ECSS-E-ST-50-03C 5.6.1b make the field mandatory when the frame is not Reed-Solomon encoded, and optional when it travels inside a code block, the code block already protects it. Clause 5.6.1c then requires the choice to hold for the whole physical channel, which is why it belongs to ChannelConfig rather than to a single frame.
When config.FrameLength is set, the encoded frame must come out exactly that long (CCSDS 132.0-B-3 clause 2.1.3 fixes the frame length per physical channel) and any other size returns ErrFrameLengthMismatch.
func (*TMTransferFrame) EncodeWithoutFEC ¶
func (tf *TMTransferFrame) EncodeWithoutFEC() ([]byte, error)
EncodeWithoutFEC converts the frame to bytes excluding the CRC field.
type VCAStatus ¶
type VCAStatus struct {
SyncFlag bool
PacketOrderFlag bool
SegmentLengthID uint8
FirstHeaderPtr uint16
}
VCAStatus contains the VCA Status Fields of CCSDS 132.0-B-3 clause 3.4.2.3: the Packet Order Flag, the Segment Length Identifier, and the First Header Pointer of the Transfer Frame Data Field Status. With the Synchronization Flag set these bits are undefined by CCSDS and belong to the VCA service user, who gives them whatever meaning the mission needs, validity, sequence, or other status of the VCA_SDU. Providing the field is mandatory; the semantics are user-optional.
SyncFlag is reported on receive for completeness. It is not a status field the user sets: Clause 4.1.2.7.3.2 fixes it at '1' for a frame carrying a VCA_SDU, and VirtualChannelAccessService.Send always sets it.
type VirtualChannel ¶
type VirtualChannel = sdl.Channel[*TMTransferFrame]
VirtualChannel is a frame buffer for a single TM virtual channel.
func NewVirtualChannel ¶
func NewVirtualChannel(vcid uint8, bufferSize int) *VirtualChannel
NewVirtualChannel creates a new TM Virtual Channel with the given VCID and buffer capacity.
type VirtualChannelAccessService ¶
type VirtualChannelAccessService struct {
// contains filtered or unexported fields
}
VirtualChannelAccessService implements the VCA service.
func NewVirtualChannelAccessService ¶
func NewVirtualChannelAccessService(scid uint16, vcid uint8, vcaSize int, vc *VirtualChannel, config ChannelConfig, counter *FrameCounter) *VirtualChannelAccessService
NewVirtualChannelAccessService creates a new VCA service instance.
func (*VirtualChannelAccessService) Flush ¶
func (s *VirtualChannelAccessService) Flush() error
Flush is a no-op for VCA service.
func (*VirtualChannelAccessService) LastFSH ¶ added in v0.3.0
func (s *VirtualChannelAccessService) LastFSH() []byte
LastFSH returns the FSH_SDU carried by the most recently received frame, or nil when none carried one (the VC_FSH.indication of clause 3.5.3.3).
func (*VirtualChannelAccessService) LastStatus ¶
func (s *VirtualChannelAccessService) LastStatus() VCAStatus
LastStatus returns the status fields from the most recent Receive.
func (*VirtualChannelAccessService) Receive ¶
func (s *VirtualChannelAccessService) Receive() ([]byte, error)
Receive retrieves the next frame and returns its data field.
func (*VirtualChannelAccessService) Send ¶
func (s *VirtualChannelAccessService) Send(data []byte) error
Send wraps a fixed-length SDU into a TM Transfer Frame.
CCSDS 132.0-B-3 clause 3.4.2.2 fixes the VCA_SDU length per virtual channel, so data must be exactly vcaSize octets. On a fixed-length channel the SDU must also fit the data field: a vcaSize past DataFieldCapacity returns ErrDataTooLarge, since the padding a larger SDU would force could not be told apart from SDU content by any receiver.
func (*VirtualChannelAccessService) SetFSHSupplier ¶ added in v0.3.0
func (s *VirtualChannelAccessService) SetFSHSupplier(supplier func() []byte)
SetFSHSupplier installs the VC_FSH service user (CCSDS 132.0-B-3 clause 3.5) for this virtual channel; see VirtualChannelPacketService.SetFSHSupplier.
func (*VirtualChannelAccessService) SetOCFSupplier ¶ added in v0.3.0
func (s *VirtualChannelAccessService) 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 the field is all zeros.
func (*VirtualChannelAccessService) SetSendStatus ¶ added in v0.3.0
func (s *VirtualChannelAccessService) SetSendStatus(status VCAStatus)
SetSendStatus sets the VCA Status Fields carried by frames from subsequent Send calls. It is the VCA Status Fields parameter of the VCA.request primitive (CCSDS 132.0-B-3 clause 3.4.3.2.2), a mandatory parameter whose semantics belong to the service user.
The Synchronization Flag field of the argument is ignored: Clause 4.1.2.7.3.2 fixes it at '1' for a frame carrying a VCA_SDU, and Send always sets it.
type VirtualChannelFrameService ¶
type VirtualChannelFrameService struct {
// contains filtered or unexported fields
}
VirtualChannelFrameService implements the VCF service.
func NewVirtualChannelFrameService ¶
func NewVirtualChannelFrameService(vcid uint8, vc *VirtualChannel) *VirtualChannelFrameService
NewVirtualChannelFrameService creates a new VCF service instance.
func (*VirtualChannelFrameService) Flush ¶
func (s *VirtualChannelFrameService) Flush() error
Flush is a no-op for VCF service.
func (*VirtualChannelFrameService) Receive ¶
func (s *VirtualChannelFrameService) Receive() ([]byte, error)
Receive retrieves the next frame from the Virtual Channel and returns it as encoded bytes.
func (*VirtualChannelFrameService) Send ¶
func (s *VirtualChannelFrameService) Send(data []byte) error
Send decodes the provided bytes as a TM Transfer Frame and pushes it into the Virtual Channel.
func (*VirtualChannelFrameService) SetChannelConfig ¶ added in v0.3.0
func (s *VirtualChannelFrameService) SetChannelConfig(config ChannelConfig)
SetChannelConfig tells the service how its channel is framed, which matters only for HasFEC: a channel carrying no Frame Error Control Field needs the pass-through decode and re-encode to agree with it.
type VirtualChannelMultiplexer ¶
type VirtualChannelMultiplexer = sdl.Multiplexer[*TMTransferFrame]
VirtualChannelMultiplexer is a weighted round-robin frame scheduler for TM Virtual Channels.
func NewMultiplexer ¶
func NewMultiplexer() *VirtualChannelMultiplexer
NewMultiplexer creates a new TM Virtual Channel multiplexer.
type VirtualChannelPacketService ¶
type VirtualChannelPacketService struct {
// contains filtered or unexported fields
}
VirtualChannelPacketService implements the VCP service. When ChannelConfig is set, packets are packed into fixed-length frames using native CCSDS FirstHeaderPtr for boundary detection, with FHP-based resync on frame loss. A PacketSizer must be set via SetPacketSizer before calling Receive (e.g., spp.PacketSizer for CCSDS Space Packets).
func NewVirtualChannelPacketService ¶
func NewVirtualChannelPacketService(scid uint16, vcid uint8, vc *VirtualChannel, config ChannelConfig, counter *FrameCounter) *VirtualChannelPacketService
NewVirtualChannelPacketService creates a new VCP service instance. Gap-based resync is enabled automatically when a FrameCounter is provided. For pure receivers (counter=nil) that consume externally-stamped frames, call SetGapResync(true) to enable resync on frame loss.
func (*VirtualChannelPacketService) Flush ¶
func (s *VirtualChannelPacketService) Flush() error
Flush fills any remaining buffered data up to a frame boundary with an SPP idle packet (APID 0x7FF) and emits the resulting frame(s). Only meaningful when ChannelConfig is set.
CCSDS 132.0-B-3 clause 4.2.2 and ECSS-E-ST-50-03C 5.4.3.4g require spare data field space to carry idle packets a conformant receiver can parse and discard, not raw fill it would misread as a packet header. When the spare space is under the seven-octet minimum packet size, the idle packet spans into one or more following frames, so Flush may emit more than one frame.
func (*VirtualChannelPacketService) LastFSH ¶ added in v0.3.0
func (s *VirtualChannelPacketService) LastFSH() []byte
LastFSH returns the FSH_SDU carried by the most recently received frame, or nil when none carried one. It is the VC_FSH.indication of clause 3.5.3.3; pair it with the VC frame gap for the optional FSH_SDU Loss Flag.
func (*VirtualChannelPacketService) Receive ¶
func (s *VirtualChannelPacketService) Receive() ([]byte, error)
Receive extracts the next complete packet from frame data. When ChannelConfig is not set, returns the data field of one frame (legacy). When ChannelConfig is set, uses FHP to find packet boundaries and PacketSizer to determine packet length. Resyncs after frame loss.
func (*VirtualChannelPacketService) Send ¶
func (s *VirtualChannelPacketService) Send(data []byte) error
Send appends packet data to the send buffer and generates full frames. When ChannelConfig is set, packs packets into fixed-length frames with proper FirstHeaderPtr. Call Flush() after the last Send() to emit any remaining partial frame, padded with SPP idle packets.
When ChannelConfig is not set, Send creates one variable-length frame per packet. That legacy path violates the fixed-frame-length rule of CCSDS 132.0-B-3 clause 2.1.3 and exists only for in-process loopback and tests; set ChannelConfig.FrameLength for anything that leaves the process.
func (*VirtualChannelPacketService) SetFSHSupplier ¶ added in v0.3.0
func (s *VirtualChannelPacketService) SetFSHSupplier(supplier func() []byte)
SetFSHSupplier installs the VC_FSH service user (CCSDS 132.0-B-3 clause 3.5): a callback whose FSH_SDU fills the Transfer Frame Secondary Header of every frame this service emits. The SDU must be exactly ChannelConfig.FSHDataLength octets. Without a supplier the header is zero-filled, since clause 4.1.3.1.5 requires it in every frame of the channel once the channel carries one.
func (*VirtualChannelPacketService) SetGapResync ¶ added in v0.3.0
func (s *VirtualChannelPacketService) SetGapResync(enabled bool)
SetGapResync enables or disables gap-based resync on the receive side. When enabled, the receiver discards partially-assembled packets whenever a frame gap is detected. Enable this for pure receivers that consume externally-stamped frames without a local FrameCounter.
func (*VirtualChannelPacketService) SetOCFSupplier ¶ added in v0.3.0
func (s *VirtualChannelPacketService) 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 the field is all zeros, which a receiver reads as an empty Type-1-Report; per CCSDS 132.0-B-3 clause 4.1.5 the field content should come from the OCF service user.
func (*VirtualChannelPacketService) SetPacketSizer ¶
func (s *VirtualChannelPacketService) SetPacketSizer(sizer PacketSizer)
SetPacketSizer configures the PacketSizer used by Receive() to detect packet boundaries. Must be set before calling Receive() when ChannelConfig is set (e.g., pass spp.PacketSizer for Space Packets).