#pragma once #include #include #include // SECS-I block-header primitives (SEMI E4). Each block carries a 10-byte // header with the same general shape as HSMS but laid out differently: // the R-bit lives in the upper bit of byte 0, the W-bit in the upper bit // of byte 2 (stream), and the E-bit + block number live in bytes 4-5 // (E-bit = MSB of byte 4). Bytes 6-9 are the 32-bit system bytes. namespace secsgem::secsi { // One SECS-I block carries up to 244 bytes of payload (length byte 10..254 // covers 10-byte header + up to 244 bytes; 255 is reserved). inline constexpr std::size_t kHeaderSize = 10; inline constexpr std::size_t kMaxBlockBody = 244; inline constexpr uint8_t kMaxLengthByte = 254; struct Header { // R-bit + 15-bit device ID packed into bytes 0-1 (big-endian). // R=1 means "host -> equipment", R=0 means "equipment -> host". uint16_t device_id = 0; bool r_bit = false; // W-bit + 7-bit stream packed into byte 2. W=1 marks a primary message // that expects a reply (same semantics as HSMS). uint8_t stream = 0; bool w_bit = false; uint8_t function = 0; // byte 3 // E-bit + 15-bit block number packed into bytes 4-5 (big-endian). // E=1 marks the last block of a multi-block message; numbering is // 1-based per E4 ยง7.2.3. uint16_t block_number = 1; bool end_block = true; uint32_t system_bytes = 0; // bytes 6-9 (big-endian) std::array encode() const; static Header decode(const uint8_t* data); // reads exactly 10 bytes std::string describe() const; bool operator==(const Header&) const = default; }; } // namespace secsgem::secsi