This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1,221 @@
---
source_files:
- Common/DTS.Common.Serialization/IRIGCH10/Packets/ITransportStreamHeader.cs
- Common/DTS.Common.Serialization/IRIGCH10/Packets/ISecondaryTimeFormatHeader.cs
- Common/DTS.Common.Serialization/IRIGCH10/Packets/TransportStreamHeader.cs
- Common/DTS.Common.Serialization/IRIGCH10/Packets/SecondaryTimeFormatHeader.cs
- Common/DTS.Common.Serialization/IRIGCH10/Packets/TimeDataPacket.cs
- Common/DTS.Common.Serialization/IRIGCH10/Packets/TMATSPacket.cs
- Common/DTS.Common.Serialization/IRIGCH10/Packets/RootRecorderIndexPacket.cs
- Common/DTS.Common.Serialization/IRIGCH10/Packets/RecorderIndexPacket.cs
- Common/DTS.Common.Serialization/IRIGCH10/Packets/TimePacketFormat2.cs
- Common/DTS.Common.Serialization/IRIGCH10/Packets/IDataPacket.cs
- Common/DTS.Common.Serialization/IRIGCH10/Packets/TimePacketFormat1.cs
- Common/DTS.Common.Serialization/IRIGCH10/Packets/AnalogDataFormat1Packet.cs
generated_at: "2026-04-16T03:43:44.837011+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "a37b40770bf1428d"
---
# IRIG CH10 Packet Serialization Module Documentation
## 1. Purpose
This module provides serialization and deserialization support for IRIG CH10 data packets, implementing core packet types required for recording and playback of time-synchronized embedded system data streams. It defines interfaces and concrete classes for transport headers, secondary time headers, and various data packet formats—including time data (Formats 1 and 2), analog data (Format 1), TMATS metadata, and recorder indexing structures—enabling interoperability with IRIG CH10-compliant systems. The module is designed for use in data acquisition and post-processing pipelines where precise time-stamping and structured binary packet formatting are required.
## 2. Public Interface
### Interfaces
- **`ITransportStreamHeader`**
- `int MessageFormat { get; }` — 4-bit field identifying the message format (must be `1` per spec).
- `int MessageType { get; }` — 4-bit field identifying the message type (must be `0` per spec).
- `int SequenceNumber { get; }` — 24-bit UDP sequence number, incremented per packet.
- **`ISecondaryTimeFormatHeader`**
- `int NanoSeconds { get; }` — Nanosecond component of the time stamp.
- `int Seconds { get; }` — Seconds since Unix epoch (1970-01-01).
- `ushort Reserved { get; }` — Reserved field (always `0` in current implementation).
- `ushort CheckSum { get; }` — 8-bit checksum over preceding fields (stored as `ushort`).
- `DateTime LocalTime { get; }` — Computed local time from `Seconds` and `NanoSeconds`.
- **`IDataPacket`**
- `IPacketHeader PacketHeader { get; }` — Access to the packet header metadata.
- `uint ComputeCheckSum()` — Computes CRC32 checksum over data bytes.
- `byte[] GetBytes()` — Serializes the entire packet to a byte array.
- `void SetRTC(long rtc)` — Sets the Real-Time Counter (10 MHz) value.
- `void SetDataVersion(DataTypeVersion version)` — Sets the data version field in the header.
- `void SetChannelID(ushort channelID)` — Sets the channel ID.
- `void SetSequenceNumber(ushort seq)` — Sets the packet sequence number.
### Concrete Classes
- **`TransportStreamHeader`** (implements `ITransportStreamHeader`)
- `TransportStreamHeader()` — Default constructor (fields uninitialized).
- `TransportStreamHeader(byte[] input)` — Parses 4-byte header; validates length (`TRANSPORT_HEADER_LENGTH = 4`), extracts `MessageFormat`, `MessageType`, and `SequenceNumber` via bit manipulation.
- `const int TRANSPORT_HEADER_LENGTH = 4` — Header size in bytes.
- **`SecondaryTimeFormatHeader`** (implements `ISecondaryTimeFormatHeader`)
- `SecondaryTimeFormatHeader(byte[] input)` — Parses 12-byte header; validates checksum via `Utils.Utils.GetCheckSum8`; logs mismatch via `Trace.WriteLine`.
- `static byte[] GetBytes(int nanoseconds, int seconds)` — Serializes header with `Reserved=0`, computes checksum.
- `const int SECONDARY_TIME_HEADER_LENGTH = 12` — Header size in bytes.
- **`TimeDataPacket`** (implements `IDataPacket`, extends `AbstractDataPacket`)
- `TimeDataPacket()` — Initializes with `DataFileDataTypes.TimeDataFormat1`, 12-byte `_dataBytes`.
- `DateTime GetDateTime()` — Returns internal `_dt`.
- `void SetTime(DateTime dt)` — Encodes time fields (ms/10, sec, min, hour, day, month, year) as BCD into `_dataBytes[4..11]`.
- `void SetTimeSource(byte b)` — Sets time source bits (03) in `_dataBytes[0]`.
- `void SetTimeSource(TimeSource src)` — Sets time source using `PacketHeaderValueAttribute.GetPacketHeaderValue(src)`; bit-reverses order (per CH10 spec).
- `void SetTimeFormat(TimeFormats fmt)` — Sets time format bits (47) similarly.
- **`TMATSPacket`** (implements `IDataPacket`, extends `AbstractDataPacket`)
- `TMATSPacket(int nanoseconds, int seconds, string tmatsDoc, bool secondaryHeaderPresent)` — Constructs TMATS packet with ASCII/XML doc; sets data version (`0x01` or `0x09`).
- `TMATSPacket(byte[] bytes)` — Deserializes from byte array.
- `bool XMLFormat { get; }` — Extracted from bit 9 of `ChannelSpecificDataWord`.
- `bool SetupRecordConfigurationChange { get; }` — Extracted from bit 8.
- `RCCChapter10Versions Chapter10Version { get; }` — Extracted from bits 07; maps to enum (`RESERVED`, `RCC_106_07`, ..., `RCC_106_15`).
- `string TMATSDocument { get; }` — Extracts TMATS string from `_dataBytes` after skipping CSDW and optional secondary header.
- **`RootRecorderIndexPacket`** (implements `IDataPacket`, extends `AbstractDataPacket`)
- `RootRecorderIndexPacket(DateTime dt)` — Initializes with `DataFileDataTypes.ComputerGeneratedDataFormat3`.
- `void SetRootPacketAddress(long address)` — Stores 8-byte address.
- `void AddRecordingIndex(RecordingIndexIndex index)` — Adds to `_indices` list.
- `override byte[] GetBytes()` — Appends a self-referencing index entry before serializing.
- **`RecordingIndexIndex`**
- `const int SIZE = 24` — 8 bytes (RTC) + 8 bytes (DateTime BCD) + 8 bytes (data packet offset).
- `RecordingIndexIndex(long rtc, long offset, DateTime dt)` — Constructor.
- `byte[] GetBytes()` — Serializes fields in order: RTC, DateTime (BCD), offset.
- **`RecorderIndexPacket`** (implements `IDataPacket`, extends `AbstractDataPacket`)
- `RecorderIndexPacket()` — Initializes with `DataFileDataTypes.ComputerGeneratedDataFormat3`.
- `DateTime GetDateTime()` — Returns `GetDateTime()` of first `RecordingIndex`.
- `int NumberOfEntries { get; }` — Count of `_indices`.
- `void AddRecordingIndex(RecordingIndex index)` — Adds to `_indices`.
- `override byte[] GetBytes()` — Serializes channel-specific data word, root address, and indices.
- **`RecordingIndex`**
- `const int SIZE = 35` — 8 (RTC) + 8 (DateTime BCD) + 2 (ChannelId) + 1 (DataType) + 1 (Reserved) + 8 (offset).
- `DateTime GetDateTime()` — Returns stored `_dt`.
- `RecordingIndex(long rtc, long offset, DateTime dt)` — Constructor.
- `byte[] GetBytes()` — Serializes fields.
- **`TimePacketFormat2`** (implements `IDataPacket`, extends `AbstractDataPacket`)
- `TimePacketFormat2(byte sequenceNumber, bool rtcSyncError, int nanoseconds, int seconds, long rtc, bool includeSecondaryHeader)` — Constructor.
- `TimePacketFormat2(byte[] bytes)` — Deserializes from byte array.
- `DateTime LocalTimeOfFirstSample { get; }` — Populated if secondary header present.
- `enum NetworkTimeFormats` — Values: `NetworkTimeProtocolVersion3`, `IEEE1588_2002`, `IEEE1588_2008`, `RESERVED`.
- `NetworkTimeFormats NetworkTimeFormat { get; set; }` — Bits 74 of CSDW.
- `enum TimeStatuses` — Values: `TimeNotValid`, `TimeValid`, `RESERVED`.
- `TimeStatuses TimeStatus { get; set; }` — Bits 30 of CSDW.
- `uint UnsignedSeconds { get; }` — Parsed from data section.
- `uint UnsignedNanoSeconds { get; }` — Parsed from data section.
- `string PTPTime { get; }` — Formatted via `PTP1588Timestamps.ToDateTimeString(...)`.
- **`TimePacketFormat1`** (implements `IDataPacket`, extends `AbstractDataPacket`)
- `TimePacketFormat1(byte sequenceNumber, DateTime packetTime, long rtc, int nanoseconds, int seconds)` — Constructor.
- `enum IRIGTimeSource` — Values: `IRIG_TCG_freewheeling`, ..., `RESERVED`.
- `IRIGTimeSource ITS { get; set; }` — Bits 1512 of CSDW (not serialized per comment).
- `enum TimeFormats` — Values: `IRIG_B`, `IRIG_A`, `IRIG_G`, `RTC`, `UTC`, `NativeGPS`, `RESERVED`, `NONE`.
- `TimeFormats TimeFormat { get; set; }` — Bits 74 of CSDW.
- `enum TimeSources` — Values: `Internal`, `External`, `InternalFromRMM`, `Reserved`, `None`.
- `TimeSources TimeSource { get; set; }` — Bits 30 of CSDW.
- `enum DateFormats` — Values: `IRIGDayAvailable`, `MonthAndYearAvailable`.
- `DateFormats DateFormat { get; set; }` — Bit 9 of CSDW.
- `DateTime TimePacketTime { get; set; }` — Stored time.
- `bool IsLeapYear { get; set; }` — Bit 8 of CSDW.
- **`AnalogDataFormat1Packet`** (implements `IDataPacket`, extends `AbstractDataPacket`)
- `AnalogDataFormat1Packet(int nanoseconds, int seconds, Chapter10File.GetNextSampleDelegate getNextSample, int totalChannels, long channelLength, long rtc, long numSamples, long currentSample, byte sequenceNumber, ushort channelId, bool includeSecondaryHeader)` — Constructor.
- `AnalogDataFormat1Packet(byte[] bytes)` — Deserializes from byte array.
- `DateTime LocalTimeOfFirstSample { get; }` — Populated if secondary header present.
- `bool Same { get; set; }` — Bit 28 of CSDW.
- `int Factor { get; set; }` — Bits 2724 of CSDW.
- `int TotChan { get; set; }` — Bits 2316 of CSDW.
- `long Subchan { get; set; }` — Bits 158 of CSDW.
- `long Length { get; set; }` — Bits 72 of CSDW.
- `enum Modes` — Values: `DataIsPacked`, `DataIsUnpackedLSBPadded`, `Reserved`, `DataIsUnpackedMSBPadded`.
- `Modes Mode { get; set; }` — Bits 10 of CSDW.
- `SampleData[] Samples { get; }` — Array of sample records; each contains `short[] ChannelData`.
- **`AbstractDataPacket`** (abstract base class)
- `protected uint ChannelSpecificDataWord { get; protected set; }` — CSDW field.
- `IPacketHeader PacketHeader { get; protected set; }` — Header reference.
- `void SetCSDWBit(int bit, bool value)` — Sets/clears a single bit in CSDW.
- `bool GetCSDWBit(int bit)` — Reads a bit from CSDW.
- `protected int CommonHeaderWork(...)` — Initializes header fields, computes packet length, handles padding, and writes secondary header/CSDW into `_dataBytes`.
- `uint ComputeCheckSum()` — Returns CRC32 via `Utils.Utils.GetCheckSum32`.
- `void SetRTC(long rtc)` / `long GetRTC()` — Manages `_rtc` and header RTC.
- `const long BASE_RTC = 141989612500056L` — Reference RTC value.
- `virtual byte[] GetBytes()` — Serializes header + `_dataBytes`.
- Protected constructors for initialization and deserialization.
## 3. Invariants
- **TransportStreamHeader**:
- `MessageFormat` must be `1`.
- `MessageType` must be `0`.
- `SequenceNumber` is a 24-bit integer (range `0x000000``0xFFFFFF`).
- Input byte array must be exactly 4 bytes.
- **SecondaryTimeFormatHeader**:
- Input byte array must be exactly 12 bytes.
- `CheckSum` is validated against `Utils.Utils.GetCheckSum8`; mismatch triggers a trace warning but does not throw.
- `LocalTime` is computed as `new DateTime(1970, 1, 1).AddSeconds(Seconds).AddTicks(NanoSeconds / 100).ToLocalTime()`.
- **Data Packets**:
- All packets must have a valid `IPacketHeader` with correct `DataFileDataTypes`.
- `PacketHeader.PacketLength` is padded to a multiple of 4 bytes.
- `ChannelSpecificDataWord` is always 4 bytes and written into `_dataBytes` after optional secondary header.
- `ComputeCheckSum()` operates over `_dataBytes` only (not header).
- `SetSequenceNumber(ushort seq)` writes only the least significant byte of `seq` to `PacketHeader.SequenceNum`.
- **TimeDataPacket**:
- `_dataBytes` is fixed at 12 bytes.
- Time fields are encoded in BCD format.
- **TMATSPacket**:
- `TMATSDocument` extraction assumes ASCII encoding and skips 4-byte CSDW and optional secondary header.
- **AnalogDataFormat1Packet**:
- Data is stored as big-endian `ushort` (MSB first), converted to signed `short` with offset `+0x8000`.
- `Mode` defaults to `DataIsUnpackedMSBPadded`; `Length` defaults to `16`.
## 4. Dependencies
### Internal Dependencies
- **`DTS.Serialization.IRIGCH10.Enums`** — Defines `DataFileDataTypes`, `DataTypeVersion`, `TimeSource`, `TimeFormats`, etc.
- **`DTS.Serialization.IRIGCH10.Attributes`** — Used by `TimeDataPacket` for `PacketHeaderValueAttribute.GetPacketHeaderValue`.
- **`DTS.Serialization.IRIGCH10.Packets`** — Contains `PacketHeader`, `IPacketHeader`, `ITransportStreamHeader`, `ISecondaryTimeFormatHeader`, and related classes.
- **`DTS.Common.Utilities`** — Provides `Utils` class with methods:
- `BitArrayToInt32(BitArray, int, int)`
- `SetBits(BitArray, uint, int, int)`
- `GetCheckSum8(byte[])`
- `GetCheckSum32(byte[])`
- `GetBCDBytes(int)`
### External Dependencies
- **`System`** — Core types (`BitConverter`, `BitArray`, `DateTime`, `Encoding`, `Array`, `Buffer`, `MemoryStream`, `BinaryWriter`).
- **`System.IO`** — For `MemoryStream`, `BinaryWriter`.
### Inferred Usage
- `AbstractDataPacket` and `IDataPacket` are used by higher-level file writers/readers (e.g., `Chapter10File`).
- `TransportStreamHeader` is likely used in UDP packet serialization/deserialization.
- `SecondaryTimeFormatHeader` is used in `TimePacketFormat2`, `AnalogDataFormat1Packet`, and `TMATSPacket` when `secondaryHeaderPresent=true`.
- `PTP1588Timestamps.ToDateTimeString(...)` is referenced but not defined in source—assumed external.
## 5. Gotchas
- **`TimeDataPacket.SetSequenceNumber`** writes only the LSB of the input `ushort`, ignoring the high byte.
- **`TransportStreamHeader`** performs bit extraction in reverse order (LSB-first) via `BitArrayToInt32(bits, start, end)`, where `end` is inclusive and higher than `start`.
- **`SecondaryTimeFormatHeader.CheckSum`** is stored as `ushort` but computed as 8-bit; only the low byte is meaningful.
- **`TimePacketFormat1.ITS`** is documented as *not serialized* to CSDW due to validation tool incompatibility (commented as of 2023-10-27).
- **`AnalogDataFormat1Packet`** uses two different data versions: `0x06` (DASSAULT) for secondary headers, `0x01` (CH10 v105) otherwise.
- **`RecordingIndexIndex` and `RecordingIndex`** store `DateTime` in BCD format (e.g., `0x12` for month=12), not binary.
- **`TimeDataPacket.SetTime`** encodes `dt.Millisecond / 10` (tens of milliseconds), not full milliseconds.
- **`AbstractDataPacket.SetRTC`** updates both `_rtc` and `PacketHeader.SetRTC(rtc)`; `GetRTC()` returns `_rtc`.
- **`TMATSPacket.TMATSDocument`** extraction assumes ASCII encoding; no validation of XML/ASCII format beyond `XMLFormat` bit.
- **`TransportStreamHeader`** constructor throws `NullReferenceException` for null input (should be `ArgumentNullException` per .NET conventions).
- **`TimePacketFormat2.TimeStatus`** and **`NetworkTimeFormat`** enums include `RESERVED` as a valid return value, but deserialization does not throw on unknown values—defaults to `RESERVED`.
- **`AnalogDataFormat1Packet`** samples are stored as `short[]` in `SampleData`, but the underlying data is big-endian `ushort`; conversion is handled in `GetChannels`.