Skip to content

Commit 477ed81

Browse files
committed
feat(tmdl): add sync flag and packet order validations
1 parent 44d023d commit 477ed81

4 files changed

Lines changed: 44 additions & 39 deletions

File tree

pkg/tmdl/frame.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ func NewTMTransferFrame(scid uint16, vcid uint8, data []byte, secondaryHeaderDat
2626

2727
frame := &TMTransferFrame{
2828
Header: PrimaryHeader{
29-
VersionNumber: 0b01, // Default CCSDS TM version
29+
VersionNumber: 0b00, // Default CCSDS TM version
3030
SpacecraftID: scid & 0x03FF, // Mask to 10 bits
3131
VirtualChannelID: vcid & 0x3F, // Mask to 6 bits
3232
OCFFlag: len(ocf) > 0, // Set OCF flag if present
@@ -35,8 +35,8 @@ func NewTMTransferFrame(scid uint16, vcid uint8, data []byte, secondaryHeaderDat
3535
VCFrameCount: 0, // To be set dynamically
3636
SyncFlag: false,
3737
PacketOrderFlag: false,
38-
SegmentLengthID: 0, // Default segment length ID
39-
FirstHeaderPtr: 0, // Default "no packet start" pointer
38+
SegmentLengthID: 0b11, // Default segment length ID
39+
FirstHeaderPtr: 0, // Default "no packet start" pointer
4040
},
4141
SecondaryHeader: secondaryHeader,
4242
DataField: data,

pkg/tmdl/frame_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
// TestHeaderEncoding ensures header values are encoded correctly.
1212
func TestHeaderEncoding(t *testing.T) {
1313
header := tmdl.PrimaryHeader{
14-
VersionNumber: 0b01,
14+
VersionNumber: 0b00,
1515
SpacecraftID: 933,
1616
VirtualChannelID: 2,
1717
OCFFlag: true,
@@ -69,7 +69,7 @@ func TestFrameEncoding(t *testing.T) {
6969
// TestFrameDecoding verifies if decoding reconstructs correct values.
7070
func TestFrameDecoding(t *testing.T) {
7171
encodedFrame := []byte{
72-
0x7A, 0x5A, 0x00, 0x00, 0x00, 0x00, // Header
72+
0x3A, 0x5A, 0x00, 0x00, 0x18, 0x00, // Header
7373
'T', 'e', 'l', 'e', 'm', 'e', 't', 'r', 'y', ' ', 'D', 'a', 't', 'a', // Data
7474
}
7575

pkg/tmdl/header.go

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type PrimaryHeader struct {
1616
MCFrameCount uint8 // 8 bits (16-23) - Master Channel Frame Count
1717
VCFrameCount uint8 // 8 bits (24-31) - Virtual Channel Frame Count
1818
FSHFlag bool // 1 bit (32) - Frame Secondary Header Flag
19-
SyncFlag bool // 1 bit (33) - Synchronization Flag (Always 0 for TM)
19+
SyncFlag bool // 1 bit (33) - Synchronization Flag
2020
PacketOrderFlag bool // 1 bit (34) - Packet Order Flag
2121
SegmentLengthID uint8 // 2 bits (35-36) - Segment Length Identifier
2222
FirstHeaderPtr uint16 // 11 bits (37-47) - First Header Pointer
@@ -78,48 +78,53 @@ func (h *PrimaryHeader) Decode(data []byte) (*PrimaryHeader, error) {
7878
}
7979

8080
// Extract fields
81-
version := (data[0] >> 6) & 0x03
82-
scid := (uint16(data[0]&0x3F) << 4) | uint16(data[1]>>4)
83-
vcid := (data[1] >> 1) & 0x07
84-
ocfFlag := (data[1] & 1) != 0
85-
mcfc := data[2]
86-
vcfc := data[3]
87-
flags := data[4]
88-
fshFlag := (flags & (1 << 7)) != 0
89-
syncFlag := (flags & (1 << 6)) != 0
90-
packetOrderFlag := (flags & (1 << 5)) != 0
91-
segmentLengthID := (flags >> 3) & 0x03
92-
firstHeaderPtr := (uint16(flags&0x07) << 8) | uint16(data[5])
93-
94-
return &PrimaryHeader{
95-
VersionNumber: version,
96-
SpacecraftID: scid,
97-
VirtualChannelID: vcid,
98-
OCFFlag: ocfFlag,
99-
MCFrameCount: mcfc,
100-
VCFrameCount: vcfc,
101-
FSHFlag: fshFlag,
102-
SyncFlag: syncFlag,
103-
PacketOrderFlag: packetOrderFlag,
104-
SegmentLengthID: segmentLengthID,
105-
FirstHeaderPtr: firstHeaderPtr,
106-
}, nil
81+
header := &PrimaryHeader{
82+
VersionNumber: (data[0] >> 6) & 0x03,
83+
SpacecraftID: (uint16(data[0]&0x3F) << 4) | uint16(data[1]>>4),
84+
VirtualChannelID: (data[1] >> 1) & 0x07,
85+
OCFFlag: (data[1] & 1) != 0,
86+
MCFrameCount: data[2],
87+
VCFrameCount: data[3],
88+
FSHFlag: (data[4] & (1 << 7)) != 0,
89+
SyncFlag: (data[4] & (1 << 6)) != 0,
90+
PacketOrderFlag: (data[4] & (1 << 5)) != 0,
91+
SegmentLengthID: (data[4] >> 3) & 0x03,
92+
FirstHeaderPtr: (uint16(data[4]&0x07) << 8) | uint16(data[5]),
93+
}
94+
95+
if err := header.Validate(); err != nil {
96+
return nil, err
97+
}
98+
99+
return header, nil
107100
}
108101

109102
// Validate checks if the header values are within valid ranges.
110103
func (h *PrimaryHeader) Validate() error {
111104
if h.VersionNumber > 0b11 {
112105
return errors.New("invalid VersionNumber: must be in range 0-3 (2 bits)")
113106
}
107+
if h.VersionNumber != 0 {
108+
return errors.New("invalid VersionNumber: must be 0 for TM Transfer Frame")
109+
}
114110
if h.SpacecraftID > 0x03FF {
115111
return errors.New("invalid SpacecraftID: must be in range 0-1023 (10 bits)")
116112
}
117113
if h.VirtualChannelID > 0x07 {
118114
return errors.New("invalid VirtualChannelID: must be in range 0-7 (3 bits)")
119115
}
116+
if !h.SyncFlag && h.PacketOrderFlag {
117+
return errors.New("invalid PacketOrderFlag: must be 0 when SyncFlag is 0")
118+
}
119+
if !h.SyncFlag && h.SegmentLengthID != 0b11 {
120+
return errors.New("invalid SegmentLengthID: must be 3 (0b11) when SyncFlag is 0")
121+
}
120122
if h.SegmentLengthID > 0x03 {
121123
return errors.New("invalid SegmentLengthID: must be in range 0-3 (2 bits)")
122124
}
125+
if h.SyncFlag && h.FirstHeaderPtr != 0xFFFF {
126+
return errors.New("invalid FirstHeaderPtr: must be 0xFFFF when SyncFlag is 1")
127+
}
123128
return nil
124129
}
125130

pkg/tmdl/header_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ import (
1010

1111
func TestPrimaryHeader_EncodeDecode(t *testing.T) {
1212
original := &tmdl.PrimaryHeader{
13-
VersionNumber: 1,
13+
VersionNumber: 0,
1414
SpacecraftID: 0x3FF,
1515
VirtualChannelID: 0x07,
1616
OCFFlag: true,
1717
MCFrameCount: 0xFF,
1818
VCFrameCount: 0xFF,
1919
FSHFlag: true,
2020
SyncFlag: false,
21-
PacketOrderFlag: true,
21+
PacketOrderFlag: false,
2222
SegmentLengthID: 0x03,
2323
FirstHeaderPtr: 0x07FF,
2424
}
@@ -42,7 +42,7 @@ func TestPrimaryHeader_EncodeDecode(t *testing.T) {
4242

4343
func TestPrimaryHeader_Validate(t *testing.T) {
4444
validHeader := &tmdl.PrimaryHeader{
45-
VersionNumber: 1,
45+
VersionNumber: 0,
4646
SpacecraftID: 0x3FF,
4747
VirtualChannelID: 0x07,
4848
SegmentLengthID: 0x03,
@@ -67,24 +67,24 @@ func TestPrimaryHeader_Validate(t *testing.T) {
6767
func TestPrimaryHeader_EncodeDecode_ValidHeader(t *testing.T) {
6868
// Create a fully populated Header
6969
original := &tmdl.PrimaryHeader{
70-
VersionNumber: 1, // 01
70+
VersionNumber: 0, // 00
7171
SpacecraftID: 0x3A5, // 933 (11 1010 0101)
7272
VirtualChannelID: 5, // 101
7373
OCFFlag: true, // 1
7474
MCFrameCount: 20, // 0001 0100
7575
VCFrameCount: 40, // 0010 1000
7676
FSHFlag: true, // 1
7777
SyncFlag: false, // 0
78-
PacketOrderFlag: true, // 1
79-
SegmentLengthID: 2, // 10
78+
PacketOrderFlag: false, // 0
79+
SegmentLengthID: 3, // 10
8080
FirstHeaderPtr: 500, // 001 1111 0100
8181
}
8282
// Encode the header
8383
encoded := original.Encode()
8484

8585
// Convert to hex for readability
8686
hexEncoded := hex.EncodeToString(encoded)
87-
expectedHex := "7a5b1428b1f4"
87+
expectedHex := "3a5b142899f4"
8888
if hexEncoded != expectedHex {
8989
t.Errorf("Expected encoded header to be %s, got %s", expectedHex, hexEncoded)
9090
}

0 commit comments

Comments
 (0)