Slice Firmware Conventions

What every BREADS Slice’s firmware does the same way, whatever its function. bread-slice-core implements it. Wire semantics (opcodes, refusals, the command watchdog) live in bread-crumbs-contracts, not here. How the firmware pieces depend on each other is in Firmware Layering.

Each rule below is what Slice_DCMT and Slice_RLHT do today, unless it is marked Not yet met, which names the boards and libraries that fall short.

Status LED

A Slice with the BREADS status LED (one WS2812B on D5) shows:

State Colour
Booting, through the boot wait blue
Running green
E-stop held red
A firmware hold: a command-watchdog trip, or a latched fault such as an over-temperature amber

Red wins over amber: with the e-stop held and a trip latched, the LED is red. Red means the hardware line needs attention; amber means the Slice is holding on its own, and is cleared at the console or by the controller (CLEAR_WATCHDOG_TRIP, CLEAR_FAULTS).

The LED is written only from the main loop, and only when its colour changes.

Not yet met: bread-slice-core 0.1 has no amber state, so a trip or a fault shows green today (feastorg/bread-slice-core#3).

E-stop Input

  • Sampling. Sampled once per main-loop pass, not by interrupt. A single asserted sample asserts the stop. Release needs the line released continuously for the debounce time. The press count increments once per stop.
  • Boot. For the first second after reset, the firmware samples the e-stop continuously. A line held at power-up is asserted before the first loop pass.
  • Loop bound. No loop pass may block. The e-stop latency is one pass.
  • What a stop does is defined per family and published in the contracts’ docs/capabilities.md.

E-stop Polarity

Design Constraints requires the interlock chain to be wired so that “open state” means e-stop: a broken wire, an unplugged connector or an unseated Slice must stop, not run. The e-stop line is bus pin 6. To meet the rule:

  • The chain sources the run level. +5V feeds the line through the chain’s normally closed contacts in series; a pull-down on the Loaf holds the line LOW when any contact opens or the chain is unplugged.
  • A Slice asserts e-stop on LOW, as today, and reads the line with no internal pull-up. With several Slices on the bus, their pull-ups in parallel (20 to 50 kOhm each on the ATmega328P and ATmega4809) would hold an open line HIGH against the pull-down.
  • Anything else that stops the system, such as a controller, pulls the line LOW, as the contracts’ controller-compatibility.md describes.

Not yet met. From the schematics (netlists exported from each repo’s hardware/ on 2026-10-25), today’s boards read an open line as released:

Board E-stop line
Loaf_x004 E_STOP_5V passes bus pin 6 between the chain connectors (J2, J7) and the four Slice sockets, with no pull resistor
Loaf_ESPT E_STOP_5V has a 10 kOhm pull-up to +5V (R4), and a BSS138 level shifter (Q1) lets the ThingPlus pull it LOW
Slice_DCMT, Slice_RLHT bus pin 6 goes straight to the Nano’s D2; the firmware enables the internal pull-up

So the line idles HIGH and stops only when driven LOW; an open chain reads as released on every Slice (#20; the Slice side is feastorg/bread-slice-core#3).

Boot

  • Outputs are driven to their safe state before the main loop starts.
  • The hardware watchdog (WDT) is enabled after the boot wait.

Through reset and the bootloader, before firmware runs, every pin is a high-impedance input. So every output that can actuate a load has a defined safe level from reset without firmware: an external resistor to the level that leaves the load off, or a load that is off when its pin is high-impedance.

Slice_RLHT meets this: each relay output drives an optocoupler LED (TCMT1100) through 180 Ohm, and an undriven pin lights nothing. Slice_DCMT does not yet: the PWM, DIRECTION and BRAKE inputs of both LMD18200 drivers connect only to Nano pins, with no resistor, so they float until the firmware drives them (feastorg/Slice_DCMT#83).

Command Watchdog

The timer and trip latch behave the same in every Slice: a trip latches until cleared, and clearing resumes nothing. What refreshes the watchdog is defined in the contracts (bread_watchdog.h). The trip action is per family.

Serial Console

  • Numeric arguments are parsed strictly. The whole token must parse, values must be finite and in range, and anything else is refused with no change.
  • A serial command never bypasses a check that the CRUMBS path applies.
  • Each main-loop pass handles at most one serial line.

Strict parsing and one line per pass are true in both Slices (Slice_DCMT#60 and #49, Slice_RLHT#51 and #39). The second rule is not yet: some commands are still implemented separately for serial and CRUMBS (feastorg/.github#3).