///|
/// Block types for record operations.
pub let block_type_iod_write_req_header : Int = 8

///|
pub let block_type_iod_read_req_header : Int = 9

///|
pub let block_type_iod_read_res_header : Int = 0x8009

///|
pub let block_type_iod_write_res_header : Int = 0x8008

///|
pub let block_type_iod_control_req : Int = 272

///|
pub let block_type_iod_control_res : Int = 0x8110

///|
pub let block_type_release_req : Int = 276

///|
pub let block_type_release_res : Int = 0x8114

///|
/// Common record indices.
pub let index_iam0 : Int = 0xAFF0

///|
pub let index_iam1 : Int = 0xAFF1

///|
pub let index_iam2 : Int = 0xAFF2

///|
pub let index_iam3 : Int = 0xAFF3

///|
pub let index_iam4 : Int = 0xAFF4

///|
pub let index_real_identification : Int = 0xF000

///|
pub let index_expected_identification : Int = 0xF001

///|
pub let index_diagnosis : Int = 0xF00A

///|
pub let index_logbook : Int = 0xF00D

///|
/// MultipleWrite wrapper record index used during parametrization.
pub let index_multiple_write : Int = 0xE040

///|
/// I/O control commands.
pub let control_command_prmend : Int = 0x0001

///|
pub let control_command_application_ready : Int = 0x0002

///|
pub let control_command_release : Int = 0x0004

///|
pub let control_command_done : Int = 0x0008

///|
pub fn control_command_label(cmd : Int) -> String {
  match cmd {
    0x0001 => "PrmEnd"
    0x0002 => "ApplicationReady"
    0x0004 => "Release"
    0x0008 => "Done"
    _ => "Unknown(0x" + @frame.uint16_to_hex(cmd) + ")"
  }
}

///|
fn push_u16_be(output : Array[Byte], value : Int) -> Unit {
  output.push(((value >> 8) & 0xFF).to_byte())
  output.push((value & 0xFF).to_byte())
}

///|
fn push_u32_be(output : Array[Byte], value : Int) -> Unit {
  output.push(((value >> 24) & 0xFF).to_byte())
  output.push(((value >> 16) & 0xFF).to_byte())
  output.push(((value >> 8) & 0xFF).to_byte())
  output.push((value & 0xFF).to_byte())
}

///|
fn read_u16_be(data : Bytes, offset : Int) -> Int {
  (data[offset].to_int() << 8) + data[offset + 1].to_int()
}

///|
fn read_u32_be(data : Bytes, offset : Int) -> Int {
  (data[offset].to_int() << 24) +
  (data[offset + 1].to_int() << 16) +
  (data[offset + 2].to_int() << 8) +
  data[offset + 3].to_int()
}

///|
fn append_bytes(output : Array[Byte], data : Bytes) -> Unit {
  for byte in data {
    output.push(byte)
  }
}