{
  "protocol": "ActuatorFD",
  "major": 1,
  "minor": 0,
  "status": "draft_for_implementation_and_hardware_validation",
  "endianness": "little",
  "arbitration_bps": 1000000,
  "data_bps": 5000000,
  "identifier": {
    "format": "extended_29_bit",
    "layout": "priority[28:26],service[25:18],source[17:11],destination[10:4],major[3:0]",
    "host_id": 0,
    "actuator_id_min": 1,
    "actuator_id_max": 126,
    "broadcast_id": 127
  },
  "padding": "Zero to smallest valid CAN-FD DLC; reject nonzero padding and incorrect DLC.",
  "messages": [
    {
      "name": "emergency_disable",
      "service": 0,
      "priority": 0,
      "fields": [
        {
          "name": "reason",
          "type": "u32",
          "unit": ""
        }
      ],
      "purpose": "Latching disable; accepted without session authentication, never permits enable."
    },
    {
      "name": "fault",
      "service": 1,
      "priority": 1,
      "fields": [
        {
          "name": "session",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "sequence",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "fault_bits",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "latched_bits",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "time_us",
          "type": "u32",
          "unit": ""
        }
      ],
      "purpose": "Asynchronous fault event; clearing does not enable torque."
    },
    {
      "name": "sync",
      "service": 2,
      "priority": 2,
      "fields": [
        {
          "name": "session",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "time_us",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "cycle",
          "type": "u32",
          "unit": ""
        }
      ],
      "purpose": "Coordinator monotonic time; 32-bit microseconds wrap with modular arithmetic."
    },
    {
      "name": "command",
      "service": 3,
      "priority": 3,
      "fields": [
        {
          "name": "session",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "sequence",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "execute_us",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "valid_until_us",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "position_rad",
          "type": "f32",
          "unit": "rad"
        },
        {
          "name": "velocity_rad_s",
          "type": "f32",
          "unit": "rad/s"
        },
        {
          "name": "feedforward_nm",
          "type": "f32",
          "unit": "Nm"
        },
        {
          "name": "kp_nm_rad",
          "type": "f32",
          "unit": "Nm/rad"
        },
        {
          "name": "kd_nm_s_rad",
          "type": "f32",
          "unit": "Nm s/rad"
        },
        {
          "name": "mode",
          "type": "u8",
          "unit": ""
        },
        {
          "name": "flags",
          "type": "u8",
          "unit": ""
        }
      ],
      "purpose": "Output-axis SI units. Modes 0 disabled, 1 torque, 2 velocity, 3 impedance. Position uses impedance with feedforward. Flags must be zero in v1."
    },
    {
      "name": "state",
      "service": 4,
      "priority": 4,
      "fields": [
        {
          "name": "session",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "sequence",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "time_us",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "output_position_rad",
          "type": "f32",
          "unit": "rad"
        },
        {
          "name": "motor_position_rad",
          "type": "f32",
          "unit": "rad"
        },
        {
          "name": "velocity_rad_s",
          "type": "f32",
          "unit": "rad/s"
        },
        {
          "name": "iq_a",
          "type": "f32",
          "unit": "A"
        },
        {
          "name": "estimated_torque_nm",
          "type": "f32",
          "unit": "Nm"
        },
        {
          "name": "temperature_c",
          "type": "f32",
          "unit": "degC"
        },
        {
          "name": "fault_bits",
          "type": "u32",
          "unit": ""
        }
      ],
      "purpose": "Sampled output and motor readings; estimated torque is not torque-sensor measurement. Position unwrapping status follows capabilities."
    },
    {
      "name": "health",
      "service": 5,
      "priority": 5,
      "fields": [
        {
          "name": "session",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "sequence",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "bus_voltage_v",
          "type": "f32",
          "unit": "V"
        },
        {
          "name": "winding_temperature_c",
          "type": "f32",
          "unit": "degC"
        },
        {
          "name": "inverter_temperature_c",
          "type": "f32",
          "unit": "degC"
        },
        {
          "name": "uptime_ms",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "rx_errors",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "tx_errors",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "mode",
          "type": "u8",
          "unit": ""
        }
      ],
      "purpose": "Lower-rate thermal, power and communication telemetry."
    },
    {
      "name": "discover",
      "service": 16,
      "priority": 6,
      "fields": [
        {
          "name": "nonce",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "slot_count",
          "type": "u16",
          "unit": ""
        },
        {
          "name": "slot_duration_us",
          "type": "u32",
          "unit": ""
        }
      ],
      "purpose": "Only while all joints are disabled. Unassigned devices hash unique ID and nonce into response slots; repeat with new nonce to resolve collisions."
    },
    {
      "name": "identity",
      "service": 17,
      "priority": 6,
      "fields": [
        {
          "name": "nonce",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "unique_id",
          "type": "bytes16",
          "unit": ""
        },
        {
          "name": "hardware_revision",
          "type": "u16",
          "unit": ""
        },
        {
          "name": "firmware_version",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "node_id",
          "type": "u8",
          "unit": ""
        }
      ],
      "purpose": "Discovery response contains immutable factory unique ID."
    },
    {
      "name": "assign_address",
      "service": 18,
      "priority": 6,
      "fields": [
        {
          "name": "nonce",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "unique_id",
          "type": "bytes16",
          "unit": ""
        },
        {
          "name": "node_id",
          "type": "u8",
          "unit": ""
        }
      ],
      "purpose": "Target by unique ID; node IDs 1..126. Persistent address assignment requires disabled state and acknowledgement."
    },
    {
      "name": "capabilities",
      "service": 19,
      "priority": 6,
      "fields": [
        {
          "name": "protocol_minor",
          "type": "u16",
          "unit": ""
        },
        {
          "name": "capability_bits",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "continuous_torque_nm",
          "type": "f32",
          "unit": "Nm"
        },
        {
          "name": "peak_torque_nm",
          "type": "f32",
          "unit": "Nm"
        },
        {
          "name": "maximum_velocity_rad_s",
          "type": "f32",
          "unit": "rad/s"
        },
        {
          "name": "watchdog_us",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "encoder_status",
          "type": "u32",
          "unit": ""
        }
      ],
      "purpose": "Reported configured limits must correspond to qualified revision; encoder status describes absolute/single-turn/unwrapped validity."
    },
    {
      "name": "session_start",
      "service": 20,
      "priority": 6,
      "fields": [
        {
          "name": "session",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "unique_id",
          "type": "bytes16",
          "unit": ""
        },
        {
          "name": "watchdog_us",
          "type": "u32",
          "unit": ""
        }
      ],
      "purpose": "Establish a new nonzero session while disabled; reset sequence state, require valid sync before enable."
    },
    {
      "name": "ack",
      "service": 21,
      "priority": 6,
      "fields": [
        {
          "name": "session",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "sequence",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "request_service",
          "type": "u8",
          "unit": ""
        },
        {
          "name": "result",
          "type": "u16",
          "unit": ""
        },
        {
          "name": "detail",
          "type": "u32",
          "unit": ""
        }
      ],
      "purpose": "Transaction result: 0 success; 1 malformed; 2 state; 3 range; 4 stale; 5 unsupported; 6 integrity; 7 busy."
    },
    {
      "name": "configure",
      "service": 32,
      "priority": 7,
      "fields": [
        {
          "name": "session",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "sequence",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "key",
          "type": "u16",
          "unit": ""
        },
        {
          "name": "operation",
          "type": "u8",
          "unit": ""
        },
        {
          "name": "value",
          "type": "bytes32",
          "unit": ""
        }
      ],
      "purpose": "Disabled-only typed configuration transaction; op 0 read, 1 stage, 2 commit; unknown keys rejected."
    },
    {
      "name": "calibrate",
      "service": 33,
      "priority": 7,
      "fields": [
        {
          "name": "session",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "sequence",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "routine",
          "type": "u16",
          "unit": ""
        },
        {
          "name": "operation",
          "type": "u8",
          "unit": ""
        }
      ],
      "purpose": "Explicit supported calibration routine 0 query, 1 start, 2 abort. Factory interlock required to energize."
    },
    {
      "name": "clear_faults",
      "service": 34,
      "priority": 7,
      "fields": [
        {
          "name": "session",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "sequence",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "mask",
          "type": "u32",
          "unit": ""
        }
      ],
      "purpose": "Clear only eligible faults while disabled; does not re-enable outputs."
    },
    {
      "name": "firmware_begin",
      "service": 48,
      "priority": 7,
      "fields": [
        {
          "name": "session",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "sequence",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "image_bytes",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "image_sha256",
          "type": "bytes32",
          "unit": ""
        },
        {
          "name": "target_slot",
          "type": "u8",
          "unit": ""
        }
      ],
      "purpose": "Disabled-only inactive-slot staging. Image hash is integrity, not authorization; signed manifest verified by bootloader."
    },
    {
      "name": "firmware_chunk",
      "service": 49,
      "priority": 7,
      "fields": [
        {
          "name": "session",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "sequence",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "offset",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "valid_bytes",
          "type": "u8",
          "unit": ""
        },
        {
          "name": "data",
          "type": "bytes32",
          "unit": ""
        }
      ],
      "purpose": "Offset-addressed idempotent chunks, unused bytes zero; ack and retransmission required."
    },
    {
      "name": "firmware_commit",
      "service": 50,
      "priority": 7,
      "fields": [
        {
          "name": "session",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "sequence",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "image_sha256",
          "type": "bytes32",
          "unit": ""
        }
      ],
      "purpose": "Verify complete size, hash, signature, board compatibility and antirollback before slot switch. Fault-tolerant recovery required."
    },
    {
      "name": "enable",
      "service": 35,
      "priority": 3,
      "fields": [
        {
          "name": "session",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "sequence",
          "type": "u32",
          "unit": ""
        },
        {
          "name": "enabled",
          "type": "u8",
          "unit": ""
        }
      ],
      "purpose": "Explicit state transition: 0 disable, 1 request enable. Enabling requires valid sync, fresh valid sensors, hardware readiness and zero latched faults. Never supplies torque by itself."
    }
  ],
  "source_references": [
    "https://www.bosch-semiconductors.com/products/ip-modules/can-protocols/can-fd/",
    "https://www.bosch-semiconductors.com/media/ip_modules/pdf_2/m_can/mcan_users_manual_v331.pdf"
  ],
  "baseline_control_hz": 200,
  "reserved_flags_must_be_zero": true,
  "session_semantics": "Nonzero host epoch, strictly increasing modulo 2^32 within a powered session history; commands and transactions share one sequence domain. No cryptographic authentication is provided by CAN identifiers or session values.",
  "implementation_status": {
    "wire_codecs": "generated_python_and_portable_c",
    "runtime_guard": "host_tested_reference_no_foc_or_board_driver",
    "discovery": "wire_and_slot_algorithm_only_no_persistent_address_backend",
    "configure": "wire_and_disabled_state_gate_only_no_flash_backend",
    "calibrate": "wire_and_disabled_state_gate_only_no_motor_routines",
    "firmware_update": "wire_and_disabled_state_gate_only_no_bootloader_or_signature_verification"
  },
  "configuration_keys": [
    {
      "key": 1,
      "name": "node_id",
      "type": "u8",
      "range": [
        1,
        126
      ],
      "remaining_bytes": "zero"
    },
    {
      "key": 2,
      "name": "watchdog_us",
      "type": "u32",
      "range": [
        1000,
        100000
      ],
      "remaining_bytes": "zero"
    }
  ],
  "lifecycle": {
    "boot": "disabled, no session, no valid sync",
    "session_start": "disabled-only; validates unique ID and newer nonzero epoch; resets sequence and sync state; preserves latched faults",
    "sync": "valid session, strictly newer cycle; establish local-to-host time offset; drift beyond configured bound latches sync fault",
    "enable": "explicit transaction, valid fresh sync and sensors, no latched faults, board readiness; no torque without a separately accepted command",
    "command": "requires enable except disabled mode; validates session, shared sequence, time window, flags, mode and limits; output begins only at execute_us",
    "clear_faults": "disabled-only, valid session/sequence, fresh safe sensors; clear never enables",
    "configure": "only disabled; unsupported until persistent storage backend is supplied",
    "calibrate": "only disabled; unsupported until specific interlocked routines are supplied",
    "firmware_update": "only disabled; unsupported until signed inactive-slot bootloader backend is supplied"
  }
}
