tcdl

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: 7 Imported by: 0

Documentation

Index

Constants

View Source
const (
	SegContinuation uint8 = 0b00
	SegFirst        uint8 = 0b01
	SegLast         uint8 = 0b10
	SegUnsegmented  uint8 = 0b11
)

Segment sequence flag constants.

View Source
const (
	// PrimaryHeaderSize is the size of the TC primary header in bytes.
	PrimaryHeaderSize = 5
	// MaxFrameLength is the maximum total TC frame length in bytes.
	MaxFrameLength = 1024
	// FECSize is the size of the Frame Error Control field in bytes.
	FECSize = 2
)

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 version number is not 0 for TC Transfer Frame.
	ErrInvalidVersion = errors.New("invalid version: must be 0 for TC 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-63 (6 bits)")

	// ErrInvalidFrameLength indicates the frame length field is out of range.
	ErrInvalidFrameLength = errors.New("invalid frame length: must cover header and FECF and not exceed 1024 bytes")

	// ErrInvalidReservedBits indicates the reserved bits are not zero.
	ErrInvalidReservedBits = errors.New("invalid reserved bits: must be 00")

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

	// ErrInvalidSequenceFlags indicates the segment sequence flags are out of range.
	ErrInvalidSequenceFlags = errors.New("invalid sequence flags: must be in range 0-3 (2 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 exceeds the maximum TC frame capacity.
	ErrDataTooLarge = errors.New("data exceeds maximum TC frame capacity")

	// 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")

	// 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")

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

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

	// ErrIncompleteSegment indicates a gap in segment reassembly: a
	// segmented packet was interrupted before its Last segment arrived,
	// or a Continuation/Last segment arrived without a First.
	ErrIncompleteSegment = errors.New("incomplete segment: missing continuation or last segment")

	// ErrInvalidFrameType indicates an invalid Bypass/Control Command flag
	// combination (Bypass=0 with Control Command=1 per CCSDS 232.0-B-4 4.1.2.3).
	ErrInvalidFrameType = errors.New("invalid frame type: Bypass=0 with Control Command=1")

	// ErrInvalidControlCommand indicates a Type-BC frame data field that is
	// neither Unlock (0x00) nor Set V(R) (0x82 0x00 <V(R)>).
	ErrInvalidControlCommand = errors.New("invalid control command: expected Unlock (0x00) or Set V(R) (0x82 0x00 vr)")

	// ErrSegmentHeaderOnControlCommand indicates a Type-BC frame carrying a
	// Segment Header, which CCSDS 232.0-B-4 4.1.3.2.2.1.3 forbids.
	ErrSegmentHeaderOnControlCommand = errors.New("segment header must not be present on a control command frame")
)

Functions

func BuildSetVRCommand added in v0.3.0

func BuildSetVRCommand(vr uint8) []byte

BuildSetVRCommand returns the data field of a Set V(R) control command for the given V(R) value.

func BuildUnlockCommand added in v0.3.0

func BuildUnlockCommand() []byte

BuildUnlockCommand returns the data field of an Unlock control command.

func IsBypass

func IsBypass(frame *TCTransferFrame) bool

IsBypass reports whether the frame is a Type-B (bypass/expedited) frame.

func IsControlFrame

func IsControlFrame(frame *TCTransferFrame) bool

IsControlFrame reports whether the frame is a control command frame.

Types

type ControlCommandType added in v0.3.0

type ControlCommandType int

ControlCommandType identifies a decoded COP-1 control command.

const (
	// ControlUnlock is the Unlock control command (data field 0x00).
	ControlUnlock ControlCommandType = iota

	// ControlSetVR is the Set V(R) control command
	// (data field 0x82 0x00 <V(R)>).
	ControlSetVR
)

func ParseControlCommand added in v0.3.0

func ParseControlCommand(data []byte) (ControlCommandType, uint8, error)

ParseControlCommand decodes the data field of a Type-BC frame. For Unlock it returns (ControlUnlock, 0, nil); for Set V(R) it returns (ControlSetVR, vr, nil). Any other content returns ErrInvalidControlCommand.

type FrameCounter

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

FrameCounter manages per-VC 8-bit frame sequence numbers N(S) for COP-1.

func NewFrameCounter

func NewFrameCounter() *FrameCounter

NewFrameCounter creates a new FrameCounter.

func (*FrameCounter) Next

func (fc *FrameCounter) Next(vcid uint8) uint8

Next returns the current sequence number for the given VCID, then increments it.

type FrameGapDetector

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

FrameGapDetector tracks per-VC frame sequence numbers to detect gaps caused by lost frames. TC has only per-VC sequence numbers (no MC counter).

func NewFrameGapDetector

func NewFrameGapDetector() *FrameGapDetector

NewFrameGapDetector creates a new detector.

func (*FrameGapDetector) Track

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

Track examines the frame's VC sequence number 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(*TCTransferFrame)

FrameOption configures optional fields on a TCTransferFrame.

func WithBypass

func WithBypass() FrameOption

WithBypass sets the Bypass Flag to 1 (Type-B expedited frame).

func WithControlCommand

func WithControlCommand() FrameOption

WithControlCommand sets the Control Command Flag to 1, producing a Type-BC frame. Per CCSDS 232.0-B-4 4.1.2.3 a control command frame is always a bypass frame (Bypass=0 with Control Command=1 is invalid), so the Bypass Flag is set to 1 as well.

func WithSegmentHeader

func WithSegmentHeader(sh SegmentHeader) FrameOption

WithSegmentHeader attaches a segment header to the frame. Combining it with WithControlCommand is refused: CCSDS 232.0-B-4 4.1.3.2.2.1.3 bars a segment header from a frame carrying a control command.

func WithSequenceNumber

func WithSequenceNumber(n uint8) FrameOption

WithSequenceNumber sets the Frame Sequence Number (N(S) for COP-1).

type MAPAccessService

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

MAPAccessService implements the MAP Access Service. Sends raw data units without packet boundaries.

func NewMAPAccessService

func NewMAPAccessService(scid uint16, vcid uint8, mapID uint8, bypass bool, vc *VirtualChannel, counter *FrameCounter) *MAPAccessService

NewMAPAccessService creates a new MAP Access Service instance.

func (*MAPAccessService) Flush

func (s *MAPAccessService) Flush() error

Flush is a no-op for MAP Access Service.

func (*MAPAccessService) Receive

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

Receive returns the data field of the next frame.

func (*MAPAccessService) Send

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

Send wraps data into a TC frame with an unsegmented segment header.

type MAPPacketService

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

MAPPacketService implements the MAP Packet Service. Supports segmentation: packets larger than one frame are split across multiple frames using the segment header sequence flags.

func NewMAPPacketService

func NewMAPPacketService(scid uint16, vcid uint8, mapID uint8, bypass bool, vc *VirtualChannel, counter *FrameCounter) *MAPPacketService

NewMAPPacketService creates a new MAP Packet Service instance.

func (*MAPPacketService) Flush

func (s *MAPPacketService) Flush() error

Flush is a no-op for MAP Packet Service.

func (*MAPPacketService) Receive

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

Receive extracts the next complete packet. Segmented packets are reassembled from First/Continuation/Last frames; a frame data field carrying several packets back to back is delimited with the configured PacketSizer, and the extra packets are buffered for later calls.

A gap in a segment sequence (a First or Unsegmented frame arriving while a reassembly is in progress, a Continuation or Last without a First, or a MAP ID change mid-packet) discards the partial packet and returns ErrIncompleteSegment. The interrupting frame is preserved and delivered by the next call.

func (*MAPPacketService) Send

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

Send encodes and segments a packet into one or more TC frames. Small packets produce a single unsegmented frame. Large packets are split using first/continuation/last segment flags.

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 TC Transfer Frames for a Master Channel identified by SCID.

func NewMasterChannel

func NewMasterChannel(scid uint16) *MasterChannel

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

func (*MasterChannel) AddFrame

func (mc *MasterChannel) AddFrame(frame *TCTransferFrame) 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() (*TCTransferFrame, error)

GetNextFrame retrieves the next frame from the multiplexer.

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) VCFrameGap

func (mc *MasterChannel) VCFrameGap() int

VCFrameGap returns the VC gap from the last AddFrame call.

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 TC uplink physical communication link. It handles MC-level multiplexing (send path) and demultiplexing (receive path) per CCSDS 232.0-B-4. For sync-layer operations (CLTU, BCH), use a separate tcsc package.

func NewPhysicalChannel

func NewPhysicalChannel(name string) *PhysicalChannel

NewPhysicalChannel creates a TC physical channel.

func (*PhysicalChannel) AddFrame

func (pc *PhysicalChannel) AddFrame(frame *TCTransferFrame) 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() (*TCTransferFrame, error)

GetNextFrame selects the next frame for transmission using weighted round-robin MC multiplexing.

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  - Transfer Frame Version Number (must be 00)
	BypassFlag         uint8  // 1 bit   - 0=Type-A (sequence-controlled), 1=Type-B (expedited)
	ControlCommandFlag uint8  // 1 bit   - 0=data transfer, 1=control command
	Reserved           uint8  // 2 bits  - spare, must be 00
	SpacecraftID       uint16 // 10 bits - Spacecraft Identifier (0-1023)
	VirtualChannelID   uint8  // 6 bits  - Virtual Channel Identifier (0-63)
	FrameLength        uint16 // 10 bits - total frame octets minus 1 (0-1023)
	FrameSequenceNum   uint8  // 8 bits  - per-VC sequence number N(S) for COP-1
}

PrimaryHeader represents the CCSDS TC Transfer Frame Primary Header (5 bytes). Per CCSDS 232.0-B-4 Section 4.1.2.

func (*PrimaryHeader) Decode

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

Decode parses a 5-byte slice into the PrimaryHeader.

func (*PrimaryHeader) Encode

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

Encode packs the PrimaryHeader fields into a 5-byte slice.

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() uint16

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

func (*PrimaryHeader) Validate

func (h *PrimaryHeader) Validate() error

Validate checks if the header values are within valid ranges.

type SegmentHeader

type SegmentHeader struct {
	SequenceFlags uint8 // 2 bits - 11=unsegmented, 01=first, 00=continuation, 10=last
	MAPID         uint8 // 6 bits - Multiplexer Access Point Identifier (0-63)
}

SegmentHeader represents the TC Segment Header (1 byte). Per CCSDS 232.0-B-4 Section 4.1.4.1.

func (*SegmentHeader) Decode

func (sh *SegmentHeader) Decode(data []byte) error

Decode parses a 1-byte slice into the SegmentHeader.

func (*SegmentHeader) Encode

func (sh *SegmentHeader) Encode() ([]byte, error)

Encode packs the SegmentHeader into a 1-byte slice.

func (*SegmentHeader) Humanize

func (sh *SegmentHeader) Humanize() string

Humanize returns a human-readable representation of the SegmentHeader.

func (*SegmentHeader) Validate

func (sh *SegmentHeader) Validate() error

Validate checks if the segment header values are within valid ranges.

type Service

type Service = sdl.Service

Service is the interface for all TC Data Link services.

type ServiceType

type ServiceType int

ServiceType defines the types of TC services available.

const (
	MAPPacket ServiceType = iota // MAP Packet Service
	MAPAccess                    // MAP Access Service
	VCFrame                      // VC Frame Service
)

type TCServiceManager

type TCServiceManager = sdl.ServiceManager[ServiceType, *TCTransferFrame]

TCServiceManager manages multiple TC services and Master Channels.

func NewTCServiceManager

func NewTCServiceManager() *TCServiceManager

NewTCServiceManager creates a new TC Service Manager.

type TCTransferFrame

type TCTransferFrame struct {
	Header            PrimaryHeader
	SegmentHeader     *SegmentHeader // optional, present when MAP sublayer is used
	DataField         []byte         // Frame Data Field
	FrameErrorControl uint16         // 16-bit CRC-16-CCITT
}

TCTransferFrame represents a CCSDS TC Space Data Link Protocol Transfer Frame.

func DecodeTCTransferFrame

func DecodeTCTransferFrame(data []byte) (*TCTransferFrame, error)

DecodeTCTransferFrame parses a byte slice into a TC Transfer Frame. Verifies CRC integrity. The segment header, if present, remains in DataField because the primary header has no flag to indicate its presence. Use DecodeTCTransferFrameWithSegmentHeader when the MAP sublayer is known to be in use.

func DecodeTCTransferFrameWithSegmentHeader added in v0.3.0

func DecodeTCTransferFrameWithSegmentHeader(data []byte) (*TCTransferFrame, error)

DecodeTCTransferFrameWithSegmentHeader parses a byte slice into a TC Transfer Frame, treating the first byte of the data field as a MAP Segment Header. Use this when the MAP sublayer is known to be in use. Type-BC frames are excepted: they carry no segment header (CCSDS 232.0-B-4 4.1.3.2.2.1.3) and their data field is returned whole.

func NewSetVRFrame added in v0.3.0

func NewSetVRFrame(scid uint16, vcid uint8, vr uint8) (*TCTransferFrame, error)

NewSetVRFrame builds a Type-BC frame carrying the Set V(R) control command for the given V(R) value (Bypass=1, Control Command=1, N(S)=0, no segment header).

func NewTCTransferFrame

func NewTCTransferFrame(scid uint16, vcid uint8, data []byte, opts ...FrameOption) (*TCTransferFrame, error)

NewTCTransferFrame creates a new TC Transfer Frame. The frame length is automatically computed. CRC is auto-calculated.

func NewUnlockFrame added in v0.3.0

func NewUnlockFrame(scid uint16, vcid uint8) (*TCTransferFrame, error)

NewUnlockFrame builds a Type-BC frame carrying the Unlock control command (Bypass=1, Control Command=1, N(S)=0, no segment header).

func (*TCTransferFrame) Encode

func (tf *TCTransferFrame) Encode() ([]byte, error)

Encode converts the TC Transfer Frame to a byte slice including CRC.

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 (*TCTransferFrame) EncodeWithoutFEC

func (tf *TCTransferFrame) EncodeWithoutFEC() ([]byte, error)

EncodeWithoutFEC converts the frame to bytes excluding the CRC field.

type VCFrameService

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

VCFrameService implements the VC Frame Service. Pass-through: sends and receives pre-encoded TC frames.

func NewVCFrameService

func NewVCFrameService(vcid uint8, vc *VirtualChannel) *VCFrameService

NewVCFrameService creates a new VC Frame Service instance.

func (*VCFrameService) Flush

func (s *VCFrameService) Flush() error

Flush is a no-op for VC Frame Service.

func (*VCFrameService) Receive

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

Receive retrieves the next frame and returns it as encoded bytes.

func (*VCFrameService) Send

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

Send decodes bytes as a TC Transfer Frame and pushes into the VC.

type VirtualChannel

type VirtualChannel = sdl.Channel[*TCTransferFrame]

VirtualChannel is a frame buffer for a single TC virtual channel.

func NewVirtualChannel

func NewVirtualChannel(vcid uint8, bufferSize int) *VirtualChannel

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

type VirtualChannelMultiplexer

type VirtualChannelMultiplexer = sdl.Multiplexer[*TCTransferFrame]

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

func NewMultiplexer

func NewMultiplexer() *VirtualChannelMultiplexer

NewMultiplexer creates a new TC Virtual Channel multiplexer.

Jump to

Keyboard shortcuts

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