Capabilities
Shared Capability Query
- Opcode:
BREAD_OP_GET_CAPS(0x7F) - Requested using CRUMBS reply-query path (
CRUMBS_CMD_SET_REPLY)
Payload Schema v1
Payload bytes:
caps_schema(u8)caps_level(u8)caps_flags(u32, little-endian)
Schema constants:
BREAD_CAPS_SCHEMA_V1 = 0x01BREAD_CAPS_V1_PAYLOAD_LEN = 6
Parsing Rules
Controllers should:
- validate minimum payload length,
- validate/record schema,
- treat
caps_flagsas authoritative for command gating, - treat
caps_levelas a coarse profile hint.
Unknown flags must be ignored.
Legacy Fallback
If capability query is unavailable (timeout/unsupported), assume baseline capabilities for that type. Do not assume optional features.
DCMT Capability Registry
Levels:
DCMT_CAP_LEVEL_1: open-loop + brake baselineDCMT_CAP_LEVEL_2: Level 1 + closed-loop position + PID tuningDCMT_CAP_LEVEL_3: Level 2 + closed-loop speed
Flags:
- bit 0:
DCMT_CAP_OPEN_LOOP_CONTROL—SET_OPEN_LOOPtakes a signed PWM per motor,-DCMT_PWM_MAXtoDCMT_PWM_MAX(255) inclusive. Firmware advertisingDCMT_CAP_REFUSESleaves a PWM outside that unchanged and refuses withBREAD_REFUSE_UNDEFINED_VALUE; older firmware clamps it - bit 1:
DCMT_CAP_BRAKE_CONTROL - bit 2:
DCMT_CAP_CLOSED_LOOP_POSITION - bit 3:
DCMT_CAP_CLOSED_LOOP_SPEED - bit 4:
DCMT_CAP_PID_TUNING - bit 5:
DCMT_CAP_CMD_WATCHDOG— firmware supports the shared bus-liveness command watchdog (BREAD_OP_SET_WATCHDOG/BREAD_OP_GET_WATCHDOG); controllers must not sendBREAD_OP_SET_WATCHDOGunless this flag is advertised - bit 6:
DCMT_CAP_CLEAR_WATCHDOG_TRIP— the watchdog trip latches untilBREAD_OP_CLEAR_WATCHDOG_TRIP, a deliberate local operator command on the slice (firmware-defined, not any serial input), or a reboot;BREAD_OP_SET_WATCHDOGand ordinary frames no longer clear it. Advertised only together withDCMT_CAP_CMD_WATCHDOG. Controllers must not sendBREAD_OP_CLEAR_WATCHDOG_TRIPunless this flag is advertised; on firmware without it,BREAD_OP_SET_WATCHDOGclears the trip - bit 7:
DCMT_CAP_ESTOP_HOLD— a hardware e-stop holds the way a latched watchdog trip does. On a press the firmware sets both brake flags and moves the position setpoints to the encoders. While e-stopped it refusesSET_OPEN_LOOP,SET_SETPOINT,SET_MODEand any brake release withBREAD_REFUSE_ESTOP. Each motor’s position setpoint keeps following its encoder until that motor’s brake is released or a new setpoint for it arrives, through the e-stop release and after a watchdog trip is cleared, so the brake release holds where the shaft is; a setpoint the controller sends stands as sent. Releasing the e-stop moves nothing; the controller resumes withSET_BRAKE(0,0), then setpoints, then the mode. Advertised only together withDCMT_CAP_REFUSES. On firmware without the flag, a release resumes the stored mode and setpoints, including commands sent during the hold - bit 8:
DCMT_CAP_REFUSES— a SET the firmware does not act on in full is refused withcrumbs_refuse()and aBREAD_REFUSE_*reason (bread_refuse.h), so GET_ACK’s applied means every part was acted on as sent. A frame acted on in part applies what it can and is refused with the reason of its first ignored part in payload order; a SET_BRAKE while a hold is in force engages any brake it names and is refused with the hold’s reason (BREAD_REFUSE_WATCHDOG_TRIP, orBREAD_REFUSE_ESTOPon firmware withDCMT_CAP_ESTOP_HOLD) if it asked for a release. After a refusal the controller reads GET_STATE to see what took effect. On firmware without the flag every frame reports applied, including ones the firmware ignored - bit 9:
DCMT_CAP_SETPOINT_LOOP—SET_SETPOINTtakes the 5-byte form[loop:u8][target1:i16][target2:i16], which writes only the named loop’s setpoints (DCMT_PID_LOOP_*), and the 4-byte form writes the position setpoints only. Any other length is refusedBREAD_REFUSE_MALFORMED, an undefined loopBREAD_REFUSE_UNDEFINED_VALUE. A switch into closed-loop speed starts from the speed setpoint, never a position target. Advertised only together withDCMT_CAP_REFUSES. On firmware without the flag the 4-byte form writes both - bit 10:
DCMT_CAP_WATCHDOG_LEASE—SET_WATCHDOGtakes the 3-byte lease form (bread_watchdog.h). WithBREAD_WATCHDOG_FLAG_COMMANDS_ONLYonlySET_OPEN_LOOP,SET_BRAKE,SET_MODE,SET_SETPOINTandSET_WATCHDOGrefresh the watchdog. Advertised only together withDCMT_CAP_CMD_WATCHDOG - bit 11:
DCMT_CAP_FAULTS— stall faults latch per motor (bread_faults.h):BREAD_OP_GET_FAULTSreportsDCMT_FAULT_*andBREAD_OP_CLEAR_FAULTSclears them. While any is latched both motors are braked, andSET_OPEN_LOOP,SET_SETPOINT,SET_MODEand any brake release are refusedBREAD_REFUSE_FAULT. Advertised only together withDCMT_CAP_REFUSES
Baseline flag set:
DCMT_CAP_BASELINE_FLAGS = OPEN_LOOP_CONTROL | BRAKE_CONTROL
RLHT Capability Registry
Levels:
RLHT_CAP_LEVEL_1: baseline RLHT profileRLHT_CAP_LEVEL_2: reservedRLHT_CAP_LEVEL_3: reserved
Flags:
- bit 0:
RLHT_CAP_MODE_CONTROL - bit 1:
RLHT_CAP_SETPOINT_CONTROL - bit 2:
RLHT_CAP_PID_TUNING - bit 3:
RLHT_CAP_PERIOD_CONTROL—SET_PERIODStakes a relay period per heater,RLHT_PERIOD_MIN_MS(100) toRLHT_PERIOD_MAX_MS(10000) ms inclusive. Firmware advertisingRLHT_CAP_REFUSESleaves a period outside that unchanged and refuses withBREAD_REFUSE_UNDEFINED_VALUE; older firmware clamps it - bit 4:
RLHT_CAP_TC_SELECT - bit 5:
RLHT_CAP_OPEN_DUTY_CONTROL—SET_OPEN_DUTYtakes a duty per heater, 0 toRLHT_OPEN_DUTY_MAX_PCT(100) percent of the relay period inclusive. Firmware advertisingRLHT_CAP_REFUSESleaves a duty above that unchanged and refuses withBREAD_REFUSE_UNDEFINED_VALUE; older firmware clamps it - bit 6:
RLHT_CAP_CMD_WATCHDOG— firmware supports the shared bus-liveness command watchdog (BREAD_OP_SET_WATCHDOG/BREAD_OP_GET_WATCHDOG); controllers must not sendBREAD_OP_SET_WATCHDOGunless this flag is advertised - bit 7:
RLHT_CAP_CLEAR_WATCHDOG_TRIP— the watchdog trip latches untilBREAD_OP_CLEAR_WATCHDOG_TRIP, a deliberate local operator command on the slice (firmware-defined, not any serial input), or a reboot;BREAD_OP_SET_WATCHDOGand ordinary frames no longer clear it. Advertised only together withRLHT_CAP_CMD_WATCHDOG. Controllers must not sendBREAD_OP_CLEAR_WATCHDOG_TRIPunless this flag is advertised; on firmware without it,BREAD_OP_SET_WATCHDOGclears the trip - bit 8:
RLHT_CAP_ESTOP_COUNT— the GET_STATE reply appends[estop_count:u8]after its 19 bytes (RLHT_STATE_OFF_ESTOP_COUNT): hardware e-stop presses since boot, wrapping at 255. On firmware without the flag the reply is 19 bytes andrlht_parse_state_payload()reportsestop_count0, which a controller must not read as a count - bit 9:
RLHT_CAP_REFUSES— a SET the firmware does not act on in full is refused withcrumbs_refuse()and aBREAD_REFUSE_*reason (bread_refuse.h), so GET_ACK’s applied means every part was acted on as sent. A frame acted on in part applies what it can and is refused with the reason of its first ignored part in payload order; a SET_TC_SELECT with one channel other than 1 or 2 sets the other channel and is refused withBREAD_REFUSE_UNDEFINED_VALUE. After a refusal the controller reads GET_STATE to see what took effect. On firmware without the flag every frame reports applied, including ones the firmware ignored - bit 10:
RLHT_CAP_ESTOP_HOLD— a hardware e-stop holds the way a latched watchdog trip does. On a press the firmware sets both setpoints and both open-loop on-times to 0 and turns the relays off. While e-stopped it refusesSET_MODE,SET_SETPOINTSandSET_OPEN_DUTYwithBREAD_REFUSE_ESTOP. Releasing the e-stop heats nothing; the controller resumes with setpoints or duties. Advertised only together withRLHT_CAP_REFUSES. On firmware without the flag, commands sent during the hold are stored and heat at the release - bit 11:
RLHT_CAP_WATCHDOG_LEASE—SET_WATCHDOGtakes the 3-byte lease form (bread_watchdog.h). WithBREAD_WATCHDOG_FLAG_COMMANDS_ONLYonlySET_MODE,SET_SETPOINTS,SET_OPEN_DUTYandSET_WATCHDOGrefresh the watchdog. Advertised only together withRLHT_CAP_CMD_WATCHDOG - bit 12:
RLHT_CAP_PID_X1000—SET_PIDtakes the 12-byte form, six u16 gains x1000, beside the 6-byte u8 x10 one, and refuses any other lengthBREAD_REFUSE_MALFORMED - bit 13:
RLHT_CAP_FAULTS— heater faults latch (bread_faults.h): over-temperature in either mode, no rise at near-full output in closed loop, and an open thermocouple.BREAD_OP_GET_FAULTSreportsRLHT_FAULT_*, GET_STATE setsRLHT_FLAG_FAULT, andBREAD_OP_CLEAR_FAULTSclears them. While any is latched both heaters are off, andSET_MODE,SET_SETPOINTSandSET_OPEN_DUTYare refusedBREAD_REFUSE_FAULT. Thresholds are the firmware’s build-time settings. Advertised only together withRLHT_CAP_REFUSES - bit 14:
RLHT_CAP_SETPOINT_LIMITS—SET_SETPOINTSis refusedBREAD_REFUSE_WRONG_MODEin open loop andBREAD_REFUSE_UNDEFINED_VALUEabove the firmware’s ceiling (Slice_RLHT defaults to 500 °C), storing neither. Advertised only together withRLHT_CAP_REFUSES. On firmware without the flag any value is stored in either mode, and one sent in open loop heats at the next switch to closed loop
Baseline flag set:
RLHT_CAP_BASELINE_FLAGS(all currently supported RLHT control features; does not includeRLHT_CAP_CMD_WATCHDOG,RLHT_CAP_CLEAR_WATCHDOG_TRIP,RLHT_CAP_ESTOP_COUNT,RLHT_CAP_REFUSES,RLHT_CAP_ESTOP_HOLDor any later flag)
Extension Policy
Optional features are capability flags; the module major is the
wire-compatibility number (protocol-versioning.md). A new flag is
defined so that its absence means the behaviour before the flag existed,
because old firmware advertises no new bit. Controllers gate features on
flags, never on the module minor or patch.
Capability evolution is additive-only:
- add new flags for optional new behavior,
- preserve semantics of existing flags/opcodes,
- append payload fields only through a new schema version.
Four exceptions change what a controller that predates the flag sees, so
the controller release that understands the flag must ship with or before
such firmware (see controller-compatibility.md):
- Firmware that advertises
DCMT_CAP_CLEAR_WATCHDOG_TRIP/RLHT_CAP_CLEAR_WATCHDOG_TRIPchanges whatBREAD_OP_SET_WATCHDOGdoes, because it no longer clears a watchdog trip. A controller that predates the flag has no remote way to clear a trip on that firmware. - Firmware that advertises
DCMT_CAP_ESTOP_HOLD/RLHT_CAP_ESTOP_HOLDrefuses, while the e-stop is held, commands it used to store and run at the release, and a DCMT stays braked after the release untilSET_BRAKE(0,0). On DCMT the position setpoints also keep following the encoders after a watchdog trip is cleared, until each brake is released or a new setpoint arrives, where they used to stop following at the clear. All three fail safe, but a controller that predates the flag does not expect them. - Firmware that advertises
DCMT_CAP_SETPOINT_LOOPwrites the 4-byteSET_SETPOINTinto the position setpoints only. A controller that predates the flag and relied on it to set a speed target leaves the speed setpoint where it was, so closed-loop speed runs at that target (0 after a hold), not at the value it sent. - Firmware that advertises
RLHT_CAP_SETPOINT_LIMITSrefusesSET_SETPOINTSin open loop and above its ceiling, where it used to store them. A controller that predates the flag sees a refusal, and nothing heats from a stored value.