74 lines
5.5 KiB
Markdown
74 lines
5.5 KiB
Markdown
|
|
---
|
|||
|
|
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.
|