init
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/Attributes/DescriptionDecoder.cs
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/Attributes/PacketHeaderValueAttribute.cs
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/Attributes/DataTypeVersionValueAttribute.cs
|
||||
generated_at: "2026-04-16T03:43:04.052592+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "32d5e734af040685"
|
||||
---
|
||||
|
||||
# IRIG CH10 Attribute Decoders Documentation
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides utility classes for extracting metadata annotations from .NET `enum` values, specifically tailored for IRIG CH10 data format compliance. It enables serialization logic to retrieve human-readable descriptions, maximum length constraints, packet header values, and data type version numbers associated with enum fields via custom attributes (`DescriptionAttribute`, `MaxLengthAttribute`, `PacketHeaderValueAttribute`, `DataTypeVersionValueAttribute`). These utilities bridge the gap between strongly-typed enum definitions and the string/byte-level requirements of the IRIG CH10 specification (e.g., TMATS file generation, packet header construction).
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `DescriptionDecoder.GetDescription(Enum value)`
|
||||
- **Signature**: `public static string GetDescription(Enum value)`
|
||||
- **Behavior**: Returns the `DescriptionAttribute.Description` value attached to the enum field corresponding to `value`. If no such attribute exists, returns the enum's `ToString()` representation.
|
||||
|
||||
### `MaxLengthDecoder.GetMaxLength(Enum value)`
|
||||
- **Signature**: `public static int GetMaxLength(Enum value)`
|
||||
- **Behavior**: Returns the `Length` property of the `MaxLengthAttribute` attached to the enum field corresponding to `value`. If no such attribute exists, returns `0`.
|
||||
|
||||
### `PacketHeaderValueAttribute.GetPacketHeaderValue(Enum value)`
|
||||
- **Signature**: `public static byte GetPacketHeaderValue(Enum value)`
|
||||
- **Behavior**: Returns the `PacketHeaderValue` property of the `PacketHeaderValueAttribute` attached to the enum field corresponding to `value`. If no such attribute exists, returns `Default.PacketHeaderValue` (which is `0x00`).
|
||||
|
||||
### `DataTypeVersionValueAttribute.GetDataTypeVersionValue(Enum value)`
|
||||
- **Signature**: `public static byte GetDataTypeVersionValue(Enum value)`
|
||||
- **Behavior**: Returns the `DataTypeVersionValue` property of the `DataTypeVersionValueAttribute` attached to the enum field corresponding to `value`. If no such attribute exists, returns `Default.DataTypeVersionValue` (which is `0x00`).
|
||||
|
||||
> **Note**: The static methods `GetPacketHeaderValue` and `GetDataTypeVersionValue` are *instance methods* on their respective attribute classes, not static methods on the class itself. They are called on the attribute class (e.g., `PacketHeaderValueAttribute.GetPacketHeaderValue(someEnum)`) and operate on the enum value passed.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **Enum Field Resolution**: All decoder methods assume the `Enum` value corresponds to a valid field name in its declaring type (via `value.ToString()` → `GetField()`). If the enum value is invalid or the field name resolution fails (e.g., due to compiler-generated names or custom `ToString()` overrides), behavior is undefined (likely throws `NullReferenceException` or returns incorrect data).
|
||||
- **Attribute Uniqueness**: Methods return the *first* attribute found via `GetCustomAttributes(...)`. If multiple attributes of the same type exist on a single field, only the first is used.
|
||||
- **Default Values**: When no attribute is present:
|
||||
- `GetDescription` falls back to `value.ToString()`
|
||||
- `GetMaxLength` returns `0`
|
||||
- `GetPacketHeaderValue` returns `0x00`
|
||||
- `GetDataTypeVersionValue` returns `0x00`
|
||||
- **Attribute Scope**: `PacketHeaderValueAttribute` and `DataTypeVersionValueAttribute` are decorated with `[AttributeUsage(AttributeTargets.All)]`, meaning they *can* be applied to any program element (not just enums), though the decoders assume usage on enum fields.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Dependencies *of* this module:
|
||||
- **System.ComponentModel**: For `DescriptionAttribute`
|
||||
- **System.ComponentModel.DataAnnotations**: For `MaxLengthAttribute`
|
||||
- **System.Linq**: For `Any()` and `First()` LINQ methods
|
||||
- **System.Reflection**: For `GetType()`, `GetField()`, `GetCustomAttributes()`
|
||||
|
||||
### Dependencies *on* this module:
|
||||
- Other IRIG CH10 serialization components (not visible in source) that rely on these decoders to:
|
||||
- Generate TMATS string descriptions from enums
|
||||
- Enforce or suggest max-length constraints for string fields
|
||||
- Construct packet headers (e.g., for packet type/version identification)
|
||||
- Serialize data type version information per CH10 spec
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **No null-safety**: All methods call `value.ToString()` and `GetField(...)` without validating that `value` is non-null or that the field exists. Passing `null` or an invalid enum value will cause a `NullReferenceException`.
|
||||
- **Case sensitivity**: `value.ToString()` is used directly for `GetField()`. If the enum field name differs in casing (e.g., due to compiler optimizations or custom `ToString()` overrides), field resolution may fail.
|
||||
- **`MaxLengthAttribute` is advisory only**: As noted in the `MaxLengthDecoder` summary, CH10 specifies max lengths as *suggestions*, not hard requirements. Consumers should not assume enforcement.
|
||||
- **Default attribute behavior**: The `Default` static fields (`PacketHeaderValueAttribute.Default`, `DataTypeVersionValueAttribute.Default`) are *new instances* with `0x00` values—not singleton references to a shared default. This is safe but worth noting for equality comparisons.
|
||||
- **No validation of attribute targets**: While `PacketHeaderValueAttribute` and `DataTypeVersionValueAttribute` allow `AttributeTargets.All`, their static `Get*Value` methods assume usage on enum fields. Applying them to non-enum members (e.g., classes, methods) will likely cause runtime errors.
|
||||
- **No support for inherited attributes**: `GetCustomAttributes(..., false)` excludes inherited attributes. If attributes are defined on base enum values (in inheritance hierarchies), they will be ignored.
|
||||
|
||||
None identified from source alone beyond those above.
|
||||
@@ -0,0 +1,110 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/Enums/Enums.cs
|
||||
generated_at: "2026-04-16T03:42:48.006856+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "cc430983f5236d17"
|
||||
---
|
||||
|
||||
# Documentation: `DTS.Serialization.IRIGCH10.Enums` Namespace
|
||||
|
||||
## 1. Purpose
|
||||
This module defines a set of strongly-typed enumerations used to represent standardized IRIG-106 Chapter 10 data types, time sources, time formats, and related metadata as specified in the IRIG-106 standard. These enums serve as the semantic foundation for parsing and serializing IRIG-106-compliant binary data files, mapping raw packet header values (e.g., data type codes, checksum types, time formats) to human-readable and type-safe enum members. They are used internally by serialization/deserialization logic to interpret and construct IRIG-106 packets correctly.
|
||||
|
||||
## 2. Public Interface
|
||||
All types are `public enum`s in the `DTS.Serialization.IRIGCH10.Enums` namespace. No classes, interfaces, or methods are exposed.
|
||||
|
||||
### `DataFileDataTypes`
|
||||
- **Description**: Enumerates all defined IRIG-106 Chapter 10 data format types (e.g., PCM, MIL-STD-1553, Video, Ethernet), identified by a `PacketHeaderValue` (1-byte code) and a `DataTypeVersionValue`.
|
||||
- **Key Members**:
|
||||
- `ComputerGeneratedDataFormat0` (0x00), `ComputerGeneratedDataFormat1` (0x01), ..., `ComputerGeneratedDataFormat7` (0x07)
|
||||
- `PCMDataFormat1` (0x09) — *Chapter 4 or 8*
|
||||
- `TimeDataFormat1` (0x11) — *RCC/GPS/RTC*
|
||||
- `MILSTD1553DataFormat1` (0x19) — *MIL-STD-1553B*
|
||||
- `AnalogDataFormat1` (0x21) — *Analog Data*
|
||||
- `DiscreteDataFormat1` (0x29) — *Discrete Data*
|
||||
- `MessageDataFormat0` (0x30) — *Generic Message Data*
|
||||
- `ARINC429DataFormat0` (0x38) — *ARINC-429 Data*
|
||||
- `VideoDataFormat0` (0x40) — *MPEG-2/H.264 Video*
|
||||
- `VideoDataFormat1` (0x41) — *ISO 13818-1 MPEG-2*
|
||||
- `VideoDataFormat2` (0x42) — *ISO 14496 MPEG-4 Part10 110 AVC/H.264*
|
||||
- `VideoDataFormat3` (0x43) — *MJPEG* (version 0x07)
|
||||
- `VideoDataFormat4` (0x44) — *MJPEG 2000* (version 0x07)
|
||||
- `ImageDataFormat0` (0x48) — *Image Data*
|
||||
- `ImageDataFormat1` (0x49) — *Still Imagery*
|
||||
- `ImageDataFormat2` (0x4A) — *Dynamic Imagery*
|
||||
- `UARTDataFormat0` (0x50) — *UART Data*
|
||||
- `IEEE1394DataFormat0` (0x58) — *IEEE 1394 Transaction*
|
||||
- `IEEE1394DataFormat1` (0x59) — *IEEE 1394 Physical Layer*
|
||||
- `ParallelDataFormat0` (0x60) — *Parallel Data*
|
||||
- `EthernetDataFormat0` (0x68) — *Ethernet Data* (version 0x07)
|
||||
- `EthernetDataFormat1` (0x69) — *Ethernet UDP Payload*
|
||||
- `TSPI_CTSDataFormat0` (0x70) — *GPS NMEA-RTCM*
|
||||
- `TSPI_CTSDataFormat1` (0x71) — *EAG ACMI*
|
||||
- `TSPI_CTSDataFormat2` (0x72) — *ACTTS*
|
||||
- `ControllerAreaNetworkBus` (0x78) — *CAN Bus*
|
||||
- `FibreChannelDataFormat0` (0x79) — *Fibre Channel Data* (version 0x07)
|
||||
- **Note**: All formats follow a pattern: `XxxDataFormatN`, where `N` (0–7) allows for vendor-specific or variant definitions. Only `Format1` variants (e.g., `AnalogDataFormat1`) are standardized; others are reserved.
|
||||
|
||||
### `TimeSource`
|
||||
- **Description**: Specifies the origin of time metadata in a packet.
|
||||
- **Members**:
|
||||
- `Internal` (0x00) — *Time derived from a clock in the recorder*
|
||||
- `External` (0x01) — *Time derived from a clock not in the recorder*
|
||||
- `InternalFromRMM` (0x02) — *Internal from RMM (Time derived from the clock in the RMM)*
|
||||
- `None` (0x0F) — *No time source*
|
||||
|
||||
### `TimeFormats`
|
||||
- **Description**: Specifies the encoding format of time data (e.g., IRIG-B, UTC, GPS).
|
||||
- **Members**:
|
||||
- `IRIGB` (0x00) — *IRIG-B*
|
||||
- `IRIGA` (0x01) — *IRIG-A*
|
||||
- `IRIGG` (0x02) — *IRIG-G*
|
||||
- `RTC` (0x03) — *Real-Time Clock*
|
||||
- `UTC` (0x04) — *UTC Time from GPS*
|
||||
- `GPS` (0x05) — *Native GPS Time*
|
||||
- `None` (0x0F) — *No time format*
|
||||
|
||||
### `DataTypeVersion`
|
||||
- **Description**: Represents the version of the IRIG-106 standard used for the data type definition.
|
||||
- **Members**:
|
||||
- `InitialRelease` (0x01) — *Initial Release (IRIG-106-04)*
|
||||
- `TG78` (0x02) — *TG-78 (IRIG-106-05)*
|
||||
- `IRIG106_07` (0x03) — *IRIG-106-07*
|
||||
|
||||
### `SecondaryHeaderTimeFormat`
|
||||
- **Description**: Indicates the binary format of time in the secondary header (if present).
|
||||
- **Members**:
|
||||
- `IRIG106Chapter4` (0x00) — *IRIG 106 Chapter 4 binary weighted 48-bit time format*
|
||||
- `IEEE1588` (0x01) — *IEEE-1588 Time format*
|
||||
|
||||
### `DataCheckSumType`
|
||||
- **Description**: Specifies the checksum algorithm used for packet integrity.
|
||||
- **Members**:
|
||||
- `None` (0x00)
|
||||
- `EightBit` (0x01)
|
||||
- `SixteenBit` (0x02)
|
||||
- `ThirtyTwoBit` (0x03)
|
||||
|
||||
## 3. Invariants
|
||||
- **`PacketHeaderValue` is unique per enum member**: Each enum value is annotated with `[PacketHeaderValue(byte)]`, and no two members share the same value. This ensures unambiguous mapping between raw bytes and enum members.
|
||||
- **`DataTypeVersionValue` is consistent per `DataFileDataTypes` member**: Every `DataFileDataTypes` member has exactly one `[DataTypeVersionValue(byte)]` attribute. Values observed are `0x06` (most common) and `0x07` (e.g., `ComputerGeneratedDataFormat1`, `VideoDataFormat3`, `VideoDataFormat4`, `EthernetDataFormat0`, `FibreChannelDataFormat0`).
|
||||
- **Reserved formats are strictly reserved**: All enum members with descriptions containing “Reserved for future use” must not be interpreted as active data types. Their `PacketHeaderValue`s are contiguous in blocks (e.g., `0x04`–`0x07`, `0x0A`–`0x0F`, etc.), but their usage is undefined.
|
||||
- **No overlapping `PacketHeaderValue`s across enums**: While not enforced in code, the values are allocated per IRIG-106 spec to avoid ambiguity (e.g., `TimeSource.None = 0x0F` does not conflict with `TimeFormats.None = 0x0F` because they apply to different contexts).
|
||||
|
||||
## 4. Dependencies
|
||||
- **Internal dependencies**:
|
||||
- `DTS.Serialization.IRIGCh10.Attributes` — Custom attributes `[PacketHeaderValue]`, `[DataTypeVersionValue]`, and `[Description]` are defined here (not shown, but referenced).
|
||||
- **External dependencies**:
|
||||
- `System.ComponentModel` — Used for `[Description]` attribute.
|
||||
- **Consumers** (inferred from naming and structure):
|
||||
- Serialization/deserialization logic for IRIG-106 Chapter 10 files (e.g., packet header parsers, metadata extractors).
|
||||
- Likely used in `Packet` or `Stream` classes in sibling namespaces (e.g., `DTS.Serialization.IRIGCH10.Packets`).
|
||||
|
||||
## 5. Gotchas
|
||||
- **Typo in enum member name**: `FibreChannelDataFormats1`, `FibreChannelDataFormats2`, etc. (note the trailing `s` in `Formats`) — inconsistent with naming pattern (`FibreChannelDataFormat0`). Likely a typo; verify usage in deserialization logic.
|
||||
- **Version inconsistency**: Most `DataFileDataTypes` use `DataTypeVersionValue(0x06)`, but `ComputerGeneratedDataFormat1`, `VideoDataFormat3`, `VideoDataFormat4`, `EthernetDataFormat0`, and all `FibreChannelDataFormats*` use `0x07`. Ensure deserialization logic handles version-specific parsing.
|
||||
- **`None` values are context-sensitive**: `TimeSource.None` (0x0F) and `TimeFormats.None` (0x0F) are distinct and valid in their respective contexts (e.g., absence of time metadata), but must not be confused.
|
||||
- **No validation of reserved ranges**: The enum does not prevent invalid or future-use values (e.g., `0x80`–`0xFF` are undefined). Consumers must handle unknown values gracefully.
|
||||
- **Missing `Description` attributes**: Some members (e.g., `MILSTD1553DataFormat0`, `AnalogDataFormat0`) lack `[Description]`, relying solely on naming. This may cause issues if `Description` is used for logging or UI.
|
||||
@@ -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 (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`.
|
||||
@@ -0,0 +1,181 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/TMATS/DescriptionDecoder.cs
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/TMATS/TMATSectionNumbered.cs
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/TMATS/TMATSSection.cs
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/TMATS/TMATS.cs
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/TMATS/GeneralInformation.cs
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/TMATS/PCM.cs
|
||||
generated_at: "2026-04-16T03:43:40.628941+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "3279c734bbc2d68c"
|
||||
---
|
||||
|
||||
# Documentation: TMATS Serialization Module
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module provides serialization infrastructure for generating TMATS (Telemetry and Tracking Data Format Standard) documents compliant with IRIG 106 Chapter 10. It enables structured construction of TMATS records by encapsulating attribute-value pairs, handling numbered sections (e.g., per-channel PCM data), and enforcing formatting rules derived from metadata attributes (`DescriptionAttribute`, `MaxLengthAttribute`). The module serves as the foundational serialization layer for converting in-memory telemetry configuration objects into the standardized text-based TMATS format used in IRIG 106-compliant telemetry files.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### `DescriptionDecoder.GetDescription(Enum value)`
|
||||
- **Signature**: `public static string GetDescription(Enum value)`
|
||||
- **Behavior**: Retrieves the `DescriptionAttribute.Description` value associated with the given enum field. If no attribute exists, returns the enum's `ToString()` value.
|
||||
|
||||
### `MaxLengthDecoder.GetMaxLength(Enum value)`
|
||||
- **Signature**: `public static int GetMaxLength(Enum value)`
|
||||
- **Behavior**: Retrieves the `Length` property of the `MaxLengthAttribute` associated with the given enum field. If no attribute exists, returns `0`.
|
||||
|
||||
### `TMATSSection<T>.SetValue(T tag, string value)`
|
||||
- **Signature**: `public void SetValue(T tag, string value) where T : Enum`
|
||||
- **Behavior**: Stores the value for the specified enum tag in an internal dictionary.
|
||||
|
||||
### `TMATSSection<T>.GetValue(T tag)`
|
||||
- **Signature**: `public string GetValue(T tag) where T : Enum`
|
||||
- **Behavior**: Returns the stored value for the given tag, or `null` if not set.
|
||||
|
||||
### `TMATSSection<T>.SetDate(T tag, DateTime? value)`
|
||||
- **Signature**: `public void SetDate(T tag, DateTime? value)`
|
||||
- **Behavior**: Stores a date as `"MM-DD-YYYY"` string (e.g., `"11-20-2018"`), or an empty string if `value` is `null`.
|
||||
|
||||
### `TMATSSection<T>.GetDate(T tag)`
|
||||
- **Signature**: `public DateTime? GetDate(T tag)`
|
||||
- **Behavior**: Parses and returns a `DateTime?` from the stored value using `"MM-DD-YYYY"` format. Returns `null` if not set or invalid.
|
||||
|
||||
### `TMATSSection<T>.GetIntOrNull(T tag)`
|
||||
- **Signature**: `public int? GetIntOrNull(T tag)`
|
||||
- **Behavior**: Parses and returns an `int?` from the stored value. Returns `null` if not set or invalid.
|
||||
|
||||
### `TMATSSection<T>.SetIntOrNull(T tag, int? val)`
|
||||
- **Signature**: `public void SetIntOrNull(T tag, int? val)`
|
||||
- **Behavior**: Stores the integer as a string, or an empty string if `val` is `null`.
|
||||
|
||||
### `TMATSSection<T>.SetValueWithLength(T tag, string value)`
|
||||
- **Signature**: `public void SetValueWithLength(T tag, string value)`
|
||||
- **Behavior**: Stores the value. *Note: Length validation is currently disabled (commented out in source).*
|
||||
|
||||
### `TMATSSection<T>.Serialize()`
|
||||
- **Signature**: `public virtual string Serialize()`
|
||||
- **Behavior**: Serializes all non-empty tag-value pairs into lines of the format `Identifier\Attribute:value;` or `Identifier-N\Attribute:value;` if `_number >= 0`.
|
||||
|
||||
### `TMATSSection<T>.Serialize(T tag)`
|
||||
- **Signature**: `protected string Serialize(T tag)`
|
||||
- **Behavior**: Serializes a single tag-value pair. Returns `null` if value is empty/whitespace.
|
||||
|
||||
### `TMATSSection<T>` constructors
|
||||
- **`TMATSSection()`**: Default constructor for unnumbered sections.
|
||||
- **`TMATSSection(AttributeIdentifiers attribute, int number)`**: Constructor for numbered sections (e.g., per-channel PCM). Sets `_attribute` and `_number`.
|
||||
|
||||
### `TMATSectionNumbered<T>.SetValue(T tag, string value)`
|
||||
- **Signature**: `public void SetValue(T tag, string value) where T : Enum`
|
||||
- **Behavior**: Stores value for the given tag in internal dictionary.
|
||||
|
||||
### `TMATSectionNumbered<T>.GetValue(T tag)`
|
||||
- **Signature**: `public string GetValue(T tag) where T : Enum`
|
||||
- **Behavior**: Returns stored value for the tag, or `null`.
|
||||
|
||||
### `TMATSectionNumbered<T>.Serialize(int number)`
|
||||
- **Signature**: `public string Serialize(int number)`
|
||||
- **Behavior**: Serializes all non-empty tag-value pairs. Format:
|
||||
`Identifier-N\Attribute<number>:value;` if `Number > 0`, else `Identifier\Attribute<number>:value;`.
|
||||
|
||||
### `TMATSectionNumbered<T>.SetValueWithLength(T tag, string value)`
|
||||
- **Signature**: `public void SetValueWithLength(T tag, string value)`
|
||||
- **Behavior**: Calls `SetValue(tag, value)`. *Note: Length validation is currently disabled.*
|
||||
|
||||
### `TMATSectionNumberedArray<T>.SetValue(int number, T tag, string value)`
|
||||
- **Signature**: `public virtual void SetValue(int number, T tag, string value)`
|
||||
- **Behavior**: Ensures `_items` has `number` elements via `SetCount`, then calls `SetValueWithLength` on the `number`-th item (1-based index).
|
||||
|
||||
### `TMATSectionNumberedArray<T>.GetValue(int number, T tag)`
|
||||
- **Signature**: `public string GetValue(int number, T tag)`
|
||||
- **Behavior**: Returns value from the `number`-th item (1-based), or `null`.
|
||||
|
||||
### `TMATSectionNumberedArray<T>.Serialize()`
|
||||
- **Signature**: `public string Serialize()`
|
||||
- **Behavior**: Serializes all items. Includes a header line `Identifier-N\Tag:Count;` if `_numberedTag` is non-empty. Then serializes each item with its 1-based index.
|
||||
|
||||
### `TMATSectionNumberedArray<T>.SetCount(int count)`
|
||||
- **Signature**: `public void SetCount(int count)`
|
||||
- **Behavior**: Resizes `_items` list to `count`. Throws `Exception` if `count > _maxNumber`. If shrinking, truncates items; if expanding, creates new `TMATSectionNumbered<T>` instances with `_attributeIdentifier` and `_number` set.
|
||||
|
||||
### `TMATSectionNumberedArray<T>.GetCount()`
|
||||
- **Signature**: `public int GetCount() => _items.Count`
|
||||
|
||||
### `AttributeIdentifiers` enum
|
||||
- **Members**: `GeneralInformation`, `TransmitionAttributes`, `StorageSourceAttributes`, `MultiplexingAttributes`, `PCMFormatAttributes`, `PCMMeasurementDescription`, `BusDataAttributes`, `PacketFormatAttributes`, `PAMAttributes`, `DataConversionAttributes`, `AirborneHardwareAttributes`, `VendorSpecificAttributes`
|
||||
- **Behavior**: Each member has a `[Description]` attribute (e.g., `"G"`, `"P"`) used in serialization.
|
||||
|
||||
### `GeneralInformationGroup` class
|
||||
- **Key Properties**:
|
||||
- `ProgramName`, `TestItem`, `IRIG106RevisionLevel`, `OriginationDate`, etc.
|
||||
- `NumberOfDataSources`, `NumberOfPointsOfContact`
|
||||
- `PreTestRequirement`, `PostTestRequirement`
|
||||
- **Methods**:
|
||||
- `SetDataSourceField(int number, DataSourceIdentificationTags tag, string value)`
|
||||
Enforces uniqueness of `DataSourceID` (throws `Exception` if duplicate).
|
||||
- `SetDataSourceType(int number, DataSourceTypes sourceType)`
|
||||
- `SetContactField(int number, PointOfContactTags tag, string value)`
|
||||
- **Nested Types**:
|
||||
- `CommentSection`, `SecuritySection`, `Information` (with nested `PointOfContactTags`, `DataSourceIdentificationTags`, `DataSourceTypes`, `TestInformationTags`).
|
||||
- `Information.DataSourceIdentificationTags.DataSourceID` has `[MaxLength(32)]`.
|
||||
|
||||
### `PCM` class
|
||||
- **Key Properties**:
|
||||
- `DataLinkName`, `PCMCode`, `BitsPerSecond`, `DataRandomized`, `Polarity`, `DataDirection`, `TypeFormat`, `NumberOfBitsInCommonWordLength`, `WordTransferOrder`, `PCMWordParity`
|
||||
- **Constructors**:
|
||||
- `PCM(int number)` → calls `base(AttributeIdentifiers.PCMFormatAttributes, number)`
|
||||
- **Nested Types**:
|
||||
- `PCMTypeFormat` (section for type-specific attributes like `TypeFormat`, `CommonWordLength`, etc.)
|
||||
- `MinorFrameSection` (section for minor frame sync data)
|
||||
- `PCMTypeFormats`, `PCMWordTransferOrders`, `PCMWordParities`, `PCMCodes`, `Polarities`, `PCMDataDirections` enums.
|
||||
|
||||
### `MinorFrameSection` class
|
||||
- **Key Properties**:
|
||||
- `NumberOfMinorFramesInAMajorFrame`, `NumberOfWordsInMinorFrame`, `NumberOfBitsInMinorFrame`, `SyncLength`, `SynchronizationPattern`
|
||||
- **Constructor**: `MinorFrameSection(int number=1)` → `base(AttributeIdentifiers.PCMFormatAttributes, number)`
|
||||
|
||||
### `TMATSCreationTest.CreateTMATS()`
|
||||
- **Signature**: `public static string CreateTMATS()`
|
||||
- **Behavior**: Demonstrates usage by constructing a sample TMATS document for a PCM telemetry system with 4 channels (1 time, 2 PCM, 1 message data). Returns the serialized string.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- **Tag Uniqueness per Section**: In `GeneralInformationGroup.Information`, `DataSourceID` values must be unique across all data sources (enforced in `SetDataSourceField`).
|
||||
- **Numbered Sections**: Sections requiring numbering (e.g., PCM, MinorFrame) use `_number` to generate identifiers like `P-1\DLN:value;`.
|
||||
- **Date Format**: Dates are stored and parsed strictly as `"MM-DD-YYYY"` (e.g., `"11-20-2018"`).
|
||||
- **Enum Serialization**: Enum values are serialized using their `[Description]` attribute, falling back to `ToString()` if missing.
|
||||
- **Empty Value Handling**: Empty/whitespace values are skipped during serialization (`string.IsNullOrWhiteSpace`).
|
||||
- **Array Bounds**: `TMATSectionNumberedArray<T>.SetCount` enforces `_maxNumber` limit if set.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Internal Dependencies
|
||||
- **`System.ComponentModel.DataAnnotations`**: Used for `DescriptionAttribute`, `MaxLengthAttribute`.
|
||||
- **`System.Linq`**: Used for `Enum.GetValues`, `Cast<T>()`, `Any()`, `Take()`, `ToArray()`.
|
||||
- **`System.Text`**: Used for `StringBuilder`.
|
||||
- **`IRIGCh10.AttributeIdentifiers`**: Defines section identifiers (e.g., `"P"` for PCM).
|
||||
- **Nested enums** (e.g., `GeneralTags`, `InformationTags`, `DataSourceIdentificationTags`, `PCMAttributes`, `TypeFormatTags`, `MinorFrameTags`) define attribute names.
|
||||
|
||||
### External Dependencies
|
||||
- **`GeneralInformationGroup`** depends on `Information`, `CommentSection`, `SecuritySection`.
|
||||
- **`PCM`** depends on `PCMTypeFormat`, `MinorFrameSection`.
|
||||
- **`TMATSCreationTest.CreateTMATS()`** depends on `GeneralInformationGroup`, `Storage`, `PCM`, `MinorFrameSection`, `SubframeSync`, `MessageDataType` (not shown in source but referenced).
|
||||
|
||||
### Inferred Usage
|
||||
- The module is used by higher-level classes (e.g., `Storage`, `MessageDataType`) to serialize TMATS sections.
|
||||
- `DescriptionDecoder` and `MaxLengthDecoder` are utility classes used by `TMATSSection<T>`, `TMATSectionNumbered<T>`, and `TMATSectionNumberedArray<T>`.
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **Length Validation Disabled**: Both `SetValueWithLength` methods (`TMATSSection<T>`, `TMATSectionNumbered<T>`) *do not enforce* `MaxLengthAttribute`—the validation code is commented out. This is explicitly noted in comments:
|
||||
> *"maxlength is just a suggestion ..."*
|
||||
> *"apprently maxlength is just a suggestion ..."*
|
||||
- **DataSourceID Uniqueness Check**: `SetDataSourceField` checks for duplicates *only when setting `DataSourceID`*, but the check uses `_datasources.GetValue(number, tag)` *before* the new value is stored, which may not catch all edge cases (e.g., concurrent modifications).
|
||||
- **Indexing Inconsistency**: `TMATSectionNumberedArray<T>.SetValue` uses 1-based indexing for `number`, but internal `_items` list is 0-based (`_items[number - 1]`).
|
||||
- **Date Parsing Strictness**: `GetDate` uses `DateTime.TryParseExact` with `"MM-DD-YYYY"` format and `CultureInfo.InvariantCulture`. Any deviation (e.g., `"11/20/2018"`) will fail.
|
||||
- **Enum Parsing Fallbacks**: Enum property getters (e.g., `PCM.PCMCode`, `PCM.Polarity`) fall back to default values (`null`, `Normal`) if the stored string does not match any `Description`. This may mask serialization errors.
|
||||
- **Missing Section Types**: `SubframeSync`, `MessageDataType`, and `Storage` classes are referenced in `CreateTMATS` but not provided in the source files—behavior is inferred but not verifiable.
|
||||
- **Typo in Enum**: `AttributeIdentifiers.TransmitionAttributes` is misspelled (should be `"Transmission"`).
|
||||
@@ -0,0 +1,199 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/TMATS/DataConversion/DataConversionSection.cs
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/TMATS/DataConversion/TelemetrySection.cs
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/TMATS/DataConversion/CoefficientSection.cs
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/TMATS/DataConversion/Measurand.cs
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/TMATS/DataConversion/OtherInformationSection.cs
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/TMATS/DataConversion/TransducerInformation.cs
|
||||
generated_at: "2026-04-16T03:44:20.663456+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "7f4dfba0264ee789"
|
||||
---
|
||||
|
||||
# Data Conversion Section Documentation
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This module implements the TMATS (Telemetry and Tracking Attributes Standard) data conversion sections as defined in IRIG Chapter 10 specification (Chapter 9 of the TMATS document). It provides strongly-typed C# classes to represent and serialize various aspects of data conversion metadata—including conversion types, binary formats, polynomial coefficients, measurand descriptions, transducer information, and other measurement-related attributes—into the TMATS packet format used in IRIG 110-04 telemetry standards. These sections enable structured representation of how raw telemetry data is processed, calibrated, and interpreted for engineering analysis.
|
||||
|
||||
## 2. Public Interface
|
||||
|
||||
### Enums
|
||||
|
||||
#### `DataConversionAttributes` (namespace `DTS.Serialization.IRIGCH10.Attributes`)
|
||||
- **`ConversionType`**: Attribute identifier `"DCT"` for specifying the data conversion type.
|
||||
|
||||
#### `ConversionTypes` (namespace `DTS.Serialization.IRIGCH10.Attributes`)
|
||||
- **`None`**: `"NON"` — No conversion applied.
|
||||
- **`PairSets`**: `"PRS"` — Conversion via pair sets.
|
||||
- **`Coefficients`**: `"COE"` — Polynomial coefficients (positive).
|
||||
- **`CoefficientsNegative`**: `"NPC"` — Polynomial coefficients (negative).
|
||||
- **`Derived`**: `"DER"` — Derived channel.
|
||||
- **`Discrete`**: `"DIS"` — Discrete (digital) channel.
|
||||
- **`PCMTime`**: `"PTM"` — PCM time channel.
|
||||
- **`Time1553`**: `"BTM"` — 1553 time channel.
|
||||
- **`DigitalVoice`**: `"VOI"` — Digital voice channel.
|
||||
- **`DigitalVideo`**: `"VID"` — Digital video channel.
|
||||
- **`SpecializedProcessing`**: `"SP"` — Specialized processing.
|
||||
- **`Other`**: `"OTH"` — Other conversion type.
|
||||
|
||||
#### `TelemetryAttributes` (namespace `DTS.Serialization.IRIGCH10.TMATS.DataConversion`)
|
||||
- **`BinaryFormat`**: Attribute identifier `"BFM"` for specifying binary data format.
|
||||
|
||||
#### `BinaryFormats` (namespace `DTS.Serialization.IRIGCH10.TMATS.DataConversion`)
|
||||
- **`Integer`**: `"INT"` — Integer format.
|
||||
- **`UnsignedBinary`**: `"UNS"` — Unsigned binary.
|
||||
- **`SignAndMagnitudeSig`**: `"SIG"` — Sign and magnitude (SIG).
|
||||
- **`SignAndMagnitudeSim`**: `"SIM"` — Sign and magnitude (SIM).
|
||||
- **`OnesCompliment`**: `"ONE"` — One’s complement.
|
||||
- **`TwosCompliment`**: `"TWO"` — Two’s complement.
|
||||
- **`OffsetBinary`**: `"OFF"` — Offset binary.
|
||||
- **`FloatingPoint`**: `"FPT"` — Floating point.
|
||||
- **`BinaryCodedDecimal`**: `"BCD"` — BCD.
|
||||
- **`BitWeight`**: `"BWT"` — Bit weight.
|
||||
- **`Other`**: `"OTH"` — Other format.
|
||||
|
||||
#### `CoefficientsAttributes` (namespace `DTS.Serialization.IRIGCH10.TMATS.DataConversion`)
|
||||
- **`OrderOfCurveFit`**: `"CO\\N"` — Polynomial order *n*.
|
||||
- **`DerivedFromPairSet`**: `"CO1"` — Indicates derivation from pair set.
|
||||
- **`Coefficient0`** to **`Coefficient7`**: `"CO"`, `"CO-1"` … `"CO-7"` — Polynomial coefficients (0th to 7th order).
|
||||
|
||||
#### `MeasurandAttributes` (namespace `DTS.Serialization.IRIGCH10.TMATS.DataConversion`)
|
||||
- **`Description`**: `"MN1"` — Measurand description (max 64 chars).
|
||||
- **`MeasurementAlias`**: `"MNA"` — Alternate name (max 32 chars).
|
||||
- **`ExcitationVoltage`**: `"MN2"` — Sensor excitation voltage in volts (max 10 chars).
|
||||
- **`EngineeringUnits`**: `"MN3"` — Engineering units (max 16 chars).
|
||||
- **`LinkType`**: `"MN4"` — Source data link type (max 3 chars).
|
||||
|
||||
#### `SourceDataTypeLinks` (namespace `DTS.Serialization.IRIGCH10.TMATS.DataConversion`)
|
||||
- **`FM`**: `"ANA"` — Analog (FM).
|
||||
- **`PCM`**: `"PCM"` — PCM.
|
||||
- **`PAM`**: `"PAM"` — PAM.
|
||||
- **`Other`**: `"OTH"` — Other.
|
||||
|
||||
#### `OtherInformationAttributes` (namespace `DTS.Serialization.IRIGCH10.Attributes`)
|
||||
- **`HighMeasurementValue`**: `"MOT1"` — Max engineering value (max 32 chars).
|
||||
- **`LowMeasurementValue`**: `"MOT2"` — Min engineering value (max 32 chars).
|
||||
- **`HighAlertLimitValue`**: `"MOT3"` — High alert limit (max 32 chars).
|
||||
- **`LowAlertLimitValue`**: `"MOT4"` — Low alert limit (max 32 chars).
|
||||
- **`HighWarningLimitValue`**: `"MOT5"` — High warning limit (max 32 chars).
|
||||
- **`LowWarningLimitValue`**: `"MOT6"` — Low warning limit (max 32 chars).
|
||||
- **`SampleRate`**: `"SR"` — Sample rate in samples/sec (max 6 chars).
|
||||
|
||||
#### `TransducerInformation` (namespace `DTS.Serialization.IRIGCH10.TMATS.DataConversion`)
|
||||
- **`MeasurementName`**: `"DCN"` — Measurement name (max 32 chars).
|
||||
- **`Type`**: `"TRD1"` — Sensor type (max 32 chars).
|
||||
- **`ModelNumber`**: `"TRD2"` — Model number (max 32 chars).
|
||||
- **`SerialNumber`**: `"TRD3"` — Serial number (max 32 chars).
|
||||
- **`SecurityClassification`**: `"TRD4"` — Classification code (max 2 chars).
|
||||
- **`OriginationDate`**: `"TRD5"` — Date in `MM-DD-YYYY` format (max 10 chars).
|
||||
- **`RevisionNumber`**: `"TRD6"` — Revision number (max 4 chars).
|
||||
- **`Orientation`**: `"TRD7"` — Physical orientation (max 32 chars).
|
||||
- **`PointOfContactName`**: `"POC1"` — POC name (max 32 chars).
|
||||
- **`PointOfContactAgency`**: `"POC2"` — POC agency (max 48 chars).
|
||||
- **`PointOfContectAddress`**: `"POC3"` — POC address (max 48 chars).
|
||||
- **`PointOfContactTelephone`**: `"POC4"` — POC telephone (max 20 chars).
|
||||
|
||||
#### `ClassificationTypes` (namespace `DTS.Serialization.IRIGCH10.TMATS.DataConversion`)
|
||||
- **`Unclassified`**: `"U"`
|
||||
- **`Confidential`**: `"C"`
|
||||
- **`Secret`**: `"S"`
|
||||
- **`TopSecret`**: `"T"`
|
||||
- **`Other`**: `"O"`
|
||||
|
||||
### Classes
|
||||
|
||||
#### `DataConversionSection`
|
||||
- **Constructor**: `DataConversionSection(int number)`
|
||||
Initializes the section with `AttributeIdentifiers.DataConversionAttributes` and given `number`.
|
||||
- **`SetConversionType(ConversionTypes type)`**:
|
||||
Sets the `"DCT"` attribute to the encoded description of `type` (e.g., `"COE"` for `Coefficients`).
|
||||
|
||||
#### `TelemetrySection`
|
||||
- **Constructor**: `TelemetrySection(int number)`
|
||||
Initializes the section with `AttributeIdentifiers.DataConversionAttributes` and given `number`.
|
||||
- **`SetBinaryFormat(BinaryFormats format)`**:
|
||||
Sets the `"BFM"` attribute to the encoded description of `format` (e.g., `"TWO"` for `TwosCompliment`).
|
||||
|
||||
#### `CoefficientSection`
|
||||
- **Constructor**: `CoefficientSection(int number)`
|
||||
Initializes the section with `AttributeIdentifiers.DataConversionAttributes` and given `number`.
|
||||
- **`OrderOfCurveFit`**: `int?`
|
||||
Gets/sets the `"CO\\N"` attribute (polynomial order *n*).
|
||||
- **`Coefficient0`**: `string`
|
||||
Gets/sets the `"CO"` attribute (0th-order coefficient, e.g., offset).
|
||||
- **`Coefficient1`**: `string`
|
||||
Gets/sets the `"CO-1"` attribute (1st-order coefficient, equivalent to bit weight).
|
||||
|
||||
#### `MeasurandSection`
|
||||
- **Constructor**: `MeasurandSection(int number)`
|
||||
Initializes the section with `AttributeIdentifiers.DataConversionAttributes` and given `number`.
|
||||
- **`Description`**: `string`
|
||||
Gets/sets `"MN1"` — Measurand description.
|
||||
- **`MeasurementAlias`**: `string`
|
||||
Gets/sets `"MNA"` — Alternate name.
|
||||
- **`ExcitationVoltage`**: `string`
|
||||
Gets/sets `"MN2"` — Sensor excitation voltage (volts).
|
||||
- **`EngineeringUnits`**: `string`
|
||||
Gets/sets `"MN3"` — Engineering units.
|
||||
- **`SetLinkType(SourceDataTypeLinks linkType)`**:
|
||||
Sets `"MN4"` to the encoded description of `linkType`.
|
||||
|
||||
#### `OtherInformationSection`
|
||||
- **Constructor**: `OtherInformationSection(int number)`
|
||||
Initializes the section with `AttributeIdentifiers.DataConversionAttributes` and given `number`.
|
||||
- **`HighMeasurementValue`**, **`LowMeasurementValue`**, **`HighAlertLimitValue`**, **`LowAlertLimitValue`**, **`HighWarningLimitValue`**, **`LowWarningLimitValue`**: `string`
|
||||
Gets/sets corresponding `"MOTx"` attributes (engineering unit limits).
|
||||
- **`SampleRate`**: `string`
|
||||
Gets/sets `"SR"` — Sample rate (samples/sec).
|
||||
|
||||
#### `TransducerInformationSection`
|
||||
- **Constructor**: `TransducerInformationSection(int number)`
|
||||
Initializes the section with `AttributeIdentifiers.DataConversionAttributes` and given `number`.
|
||||
- **`MeasurementName`**, **`Type`**, **`ModelNumber`**, **`SerialNumber`**, **`RevisionNumber`**, **`Orientation`**: `string`
|
||||
Gets/sets respective `"DCN"`, `"TRDx"`, `"TRD7"` attributes.
|
||||
- **`SecurityClassification`**: `string`
|
||||
Gets/sets `"TRD4"` — Classification code.
|
||||
- **`SetSecurityClassification(ClassificationTypes type, bool signalClassified, bool measurandClassified)`**:
|
||||
Sets `"TRD4"` to `type` description, optionally appending `"B"` (both), `"R"` (signal only), or `"E"` (measurand only).
|
||||
- **`OriginationDate`**: `DateTime?`
|
||||
Gets/sets `"TRD5"` — Date in `MM-DD-YYYY` format.
|
||||
- **`PointOfContact`**: `POC`
|
||||
Gets/sets POC data via `POC` class (see below).
|
||||
|
||||
#### `POC` (nested class in `TransducerInformationSection`)
|
||||
- **Properties**: `Name`, `Agency`, `Address`, `Telephone` (`string`).
|
||||
- **Constructors**: Parameterized and default.
|
||||
|
||||
## 3. Invariants
|
||||
|
||||
- All sections inherit from `TMATSSection<T>` and are initialized with `AttributeIdentifiers.DataConversionAttributes`, indicating they belong to the *Data Conversion* TMATS section group.
|
||||
- Attribute values are stored as strings with explicit length encoding via `SetValueWithLength`.
|
||||
- Integer attributes (`OrderOfCurveFit`) use `GetIntOrNull`/`SetIntOrNull`, implying nullable integer handling.
|
||||
- Date values (`OriginationDate`) are serialized in strict `MM-DD-YYYY` format (e.g., `03-15-2023`); parsing is lenient (`DateTime.TryParse`).
|
||||
- Classification codes may be extended with suffixes (`B`, `R`, `E`) depending on `signalClassified`/`measurandClassified` flags.
|
||||
- String attributes have maximum lengths enforced via `[MaxLength]` attributes on enum fields (e.g., `Description` max 64 chars), though enforcement occurs at serialization time via `SetValueWithLength`.
|
||||
|
||||
## 4. Dependencies
|
||||
|
||||
### Dependencies *of* this module:
|
||||
- **IRIGCh10.dll**: Provides base infrastructure (`TMATSSection<T>`, `AttributeIdentifiers`, `DescriptionDecoder`).
|
||||
- **System.ComponentModel**: Used for `[Description]` and `[MaxLength]` attributes.
|
||||
- **System.ComponentModel.DataAnnotations**: Used for `[MaxLength]`.
|
||||
|
||||
### Dependencies *on* this module:
|
||||
- Other TMATS section implementations (e.g., `TMATSSection<T>` base class).
|
||||
- Likely consumed by higher-level TMATS packet builders (e.g., `TMATSPacketBuilder`).
|
||||
- `DescriptionDecoder.GetDescription(Enum)` is used extensively to convert enum values to their IRIG-compliant string codes.
|
||||
|
||||
## 5. Gotchas
|
||||
|
||||
- **Typo in POC property**: In `TransducerInformationSection.PointOfContact.get`, `Address` is incorrectly assigned from `PointOfContectAddress` *twice* (should be `PointOfContectAddress` for `Address`, `PointOfContactTelephone` for `Telephone`). This is likely a bug.
|
||||
- **Classification suffix logic**: The `SetSecurityClassification` method appends `"B"`, `"R"`, or `"E"` to the base classification code. This is non-standard and may be proprietary extension; verify against IRIG spec.
|
||||
- **`DerivedFromPairSet` attribute (`CO1`)**: Defined in `CoefficientsAttributes` but has no corresponding property or setter in `CoefficientSection`. Its purpose is unclear from source.
|
||||
- **`SampleRate` max length**: Only 6 characters — may truncate high-precision rates (e.g., `123456` Hz is valid, but `1.23456e5` may exceed limit).
|
||||
- **`OriginationDate` format**: Hardcoded as `MM-DD-YYYY` (e.g., `03-15-2023`). This differs from ISO 8601 and may cause parsing issues in non-US locales.
|
||||
- **No validation on coefficient values**: `Coefficient0`, `Coefficient1`, etc., accept arbitrary strings (including scientific notation), but no validation ensures syntactic correctness.
|
||||
- **`BinaryFormats.SignAndMagnitudeSig` vs `SignAndMagnitudeSim`**: Ambiguous naming (`SIG`/`SIM`) — unclear if these correspond to distinct IRIG codes or are implementation-specific variants.
|
||||
@@ -0,0 +1,74 @@
|
||||
---
|
||||
source_files:
|
||||
- Common/DTS.Common.Serialization/IRIGCH10/Utils/Utils.cs
|
||||
generated_at: "2026-04-16T03:42:52.923027+00:00"
|
||||
model: "Qwen/Qwen3-Coder-Next-FP8"
|
||||
schema_version: 1
|
||||
sha256: "675d2f03b19fde67"
|
||||
---
|
||||
|
||||
# Utils
|
||||
|
||||
## Documentation: `DTS.Serialization.IRIGCH10.Utils.Utils`
|
||||
|
||||
---
|
||||
|
||||
### 1. Purpose
|
||||
|
||||
This module provides low-level utility functions for handling IRIG CH10 (Inter-Range Instrumentation Group Command Handler, Chapter 10) data format conventions. Specifically, it supports conversion of integer values to Binary-Coded Decimal (BCD) representation (for fields like dates), and computation of checksums (8-bit, 16-bit, and 32-bit) as required by the CH10 specification. It also offers bit-level manipulation helpers for packing/unpacking bitfields from `BitArray` objects—common when serializing/deserializing packet headers and metadata fields.
|
||||
|
||||
---
|
||||
|
||||
### 2. Public Interface
|
||||
|
||||
All members are `static` and defined in the `abstract` class `Utils`. No public constructors or instance members exist.
|
||||
|
||||
| Method | Signature | Behavior |
|
||||
|--------|-----------|----------|
|
||||
| `GetBCDBytes` | `public static byte[] GetBCDBytes(int value)` | Converts an integer `value` (0–9999) into a 2-byte BCD representation (least significant digit in lower nibble of byte 0). Throws `ArgumentOutOfRangeException` if `value` is outside [0, 9999]. |
|
||||
| `GetCheckSum8` | `public static ushort GetCheckSum8(byte[] bytes)` | Computes an 8-bit checksum by summing all bytes in `bytes` and returning the low 16 bits of the sum (i.e., `sum & 0xFFFF`). No padding or alignment assumptions. |
|
||||
| `GetCheckSum16` | `public static ushort GetCheckSum16(byte[] bytes)` | Computes a 16-bit checksum per CH10 spec: interprets `bytes` as an array of `ushort` (little-endian, via `Buffer.BlockCopy`) and sums all `ushort` values. **Requires** `bytes.Length` to be even; asserts this via `Trace.Assert`. |
|
||||
| `GetCheckSum32` | `public static uint GetCheckSum32(byte[] bytes)` | Computes a 32-bit checksum per CH10 spec: interprets `bytes` as an array of `uint` (little-endian) and sums all `uint` values. **Requires** `bytes.Length` to be divisible by 4; asserts this via `Trace.Assert`. |
|
||||
| `BitArrayToInt32` | `public static int BitArrayToInt32(BitArray ba, int startIndex, int endIndex)` | Extracts bits from `ba` between `startIndex` and `endIndex` (inclusive), interpreting them as a little-endian integer (bit 0 = LSB). Returns an `int` (up to 32 bits). |
|
||||
| `SetBits` | `public static void SetBits(BitArray b, uint value, int startIndex, int endIndex)` | Writes the least-significant bits of `value` (covering `(endIndex - startIndex + 1)` bits) into `b`, starting at `startIndex`. Bits are copied in little-endian order (bit 0 of `value` → `b[startIndex]`). |
|
||||
|
||||
---
|
||||
|
||||
### 3. Invariants
|
||||
|
||||
- **BCD Range**: `GetBCDBytes` enforces `0 ≤ value ≤ 9999`. Values outside this range throw `ArgumentOutOfRangeException`.
|
||||
- **Checksum Input Length**:
|
||||
- `GetCheckSum16` requires `bytes.Length % 2 == 0`.
|
||||
- `GetCheckSum32` requires `bytes.Length % 4 == 0`.
|
||||
- These are enforced via `Trace.Assert`, which may be compiled out in Release builds—**no runtime exception is thrown** if the invariant is violated in non-Debug builds.
|
||||
- **Bit Index Bounds**: `BitArrayToInt32` and `SetBits` assume `0 ≤ startIndex ≤ endIndex < ba.Length` (or `b.Length`). No explicit bounds checking is performed; out-of-range indices will cause `IndexOutOfRangeException` at runtime.
|
||||
- **Endianness**: All multi-byte integer interpretations (via `Buffer.BlockCopy` into `ushort[]`/`uint[]`) assume **little-endian byte order**, consistent with .NET’s default on most platforms.
|
||||
|
||||
---
|
||||
|
||||
### 4. Dependencies
|
||||
|
||||
**Imports/Usings**:
|
||||
- `System`
|
||||
- `System.Collections` (`BitArray`)
|
||||
|
||||
**Used By**:
|
||||
- Other modules in `DTS.Serialization.IRIGCH10` (inferred from namespace), particularly those handling packet serialization/deserialization (e.g., header construction, data packet checksumming, date/time field encoding).
|
||||
|
||||
**Used For**:
|
||||
- Encoding/decoding BCD fields (e.g., timestamps, counters).
|
||||
- Computing checksums for CH10 packet headers (`GetCheckSum16`) and data payloads (`GetCheckSum32`).
|
||||
- Bit-level manipulation of packet fields (e.g., flags, variable-length integers).
|
||||
|
||||
---
|
||||
|
||||
### 5. Gotchas
|
||||
|
||||
- **`Trace.Assert` is not a runtime guard**: In non-Debug builds, failed assertions in `GetCheckSum16` and `GetCheckSum32` will not throw exceptions—invalid input lengths may cause silent corruption or incorrect checksums. Callers must ensure input alignment themselves.
|
||||
- **BCD encoding is fixed to 4 decimal digits**: `GetBCDBytes` only supports values up to 9999 (2 bytes). Larger values require multiple calls or a different approach (not provided here).
|
||||
- **Little-endian assumption**: `GetCheckSum16`/`GetCheckSum32` rely on `Buffer.BlockCopy` interpreting bytes as little-endian `ushort`/`uint`. This is platform-dependent on .NET (true on x86/x64), but may break on big-endian systems.
|
||||
- **No overflow handling in checksums**: Sums wrap around modulo 2¹⁶ (for `ushort`) or 2³² (for `uint`), per CH10 spec—but this is implicit, not documented in code.
|
||||
- **`SetBits` uses `BitConverter.GetBytes(value)`**: This assumes little-endian layout for `value`, and only the lowest `(endIndex - startIndex + 1)` bits are copied. If `value` has more bits set than `endIndex - startIndex + 1`, higher bits are silently ignored. No validation ensures `value` fits the bit range.
|
||||
- **`BitArrayToInt32` uses LSB-first indexing**: Bit 0 of the result corresponds to `ba[startIndex]`, not `ba[endIndex]`. This matches CH10’s typical bit numbering but may be counterintuitive.
|
||||
|
||||
None identified beyond the above.
|
||||
Reference in New Issue
Block a user