--- 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 (0–3) 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 (4–7) 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 0–7; 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 7–4 of CSDW. - `enum TimeStatuses` — Values: `TimeNotValid`, `TimeValid`, `RESERVED`. - `TimeStatuses TimeStatus { get; set; }` — Bits 3–0 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 15–12 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 7–4 of CSDW. - `enum TimeSources` — Values: `Internal`, `External`, `InternalFromRMM`, `Reserved`, `None`. - `TimeSources TimeSource { get; set; }` — Bits 3–0 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 27–24 of CSDW. - `int TotChan { get; set; }` — Bits 23–16 of CSDW. - `long Subchan { get; set; }` — Bits 15–8 of CSDW. - `long Length { get; set; }` — Bits 7–2 of CSDW. - `enum Modes` — Values: `DataIsPacked`, `DataIsUnpackedLSBPadded`, `Reserved`, `DataIsUnpackedMSBPadded`. - `Modes Mode { get; set; }` — Bits 1–0 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`.