Files
diy-layout-creator/diylc/docs/plans/maker-board-roadmap.md
T
Bane Stojkovic 89ce96b6c8 Controllers (#1068)
* initial

* more components

* fixes

* Update TreePanel.java

* fix boost converter

* Improve wrapping of component names

* Update ULN2003Driver.java

* Update NRF24L01Transceiver.java

* imp

* updates

* improvements

* more components

* arduino

* uno

* icon

* cleanup

* mega

* mega

* improveent

* nano

* esp boards

* esp

* esp32

* esp32

* Update ESP8266NodeMCU.java

* d1

* Update WemosD1Mini.java

* pi

* consolidate esp32

* pi pico updates

* pi zero

* Update RaspberryPiZero.java

* pi pico

* cleanup

* pi improvements

* consolidate pins

* antenna consolidation

* improve solder pads

* teensy

* headers

* teensy fix, test cleanup

* s3

* Update ESP32DevKit.java

* usb standardization

* pico w

* button standardization

* arduino improvements

* Update AbstractMakerBoard.java

* Update RaspberryPiZero.java

* Update RaspberryPi.java

* pi 3

* pi 5 improvements

* Update RaspberryPiZero.java

* fix tests

* esp pinout fix

* Update ESP32DevKit.java

* pin name improvements

* Create tier-1-modern-boards.md

* new versions

* pinouts

* nano improvements

* sanitize node names

* label improvements

* minima fixes

* arduino uno labels

* nano labels

* Update ArduinoNano.java

* mega

* mega

* comment out future stuff

* release prep

* Update RaspberryPiPico.java

* Refactor abstract class

* labeling improvement

* label offset fixes

* Update Teensy.java

* consolidate tests

* micro variants

* Update RaspberryPi.java
2026-09-11 11:08:15 +02:00

457 lines
27 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
clau# Maker Board Roadmap
Closing the gap between `org.diylc.components.micro` and what people building with
microcontroller boards today actually reach for.
Status: proposed
Scope: `diylc-library`, package `org.diylc.components.micro`
Supersedes: `tier-1-modern-boards.md`
## 1. Goal
The `micro` package models 10 board classes across roughly 16 selectable variants. The
scaffolding in `AbstractMakerBoard` — USB connector types, PCB meander antenna, castellated
and through-hole pads, terminal blocks, FPC connectors, mounting holes, vendor logos — is
complete enough that **adding a board is mostly pin arrays and a draw branch**. The expensive
part is already paid for.
This document inventories what is modelled, lists what a modern maker cannot draw today, and
sorts the additions into three tiers by how often their absence would actually block someone.
## 2. Decisions that govern this roadmap
| # | Decision | Choice | Rationale |
|---|---|---|---|
| D1 | How coverage grows | **Named boards, drawn faithfully.** No generic/parametric "configurable dev board" component. | A parametric board would cover more of the long tail per hour, but the palette entry a maker searches for is the product name, and accurate silk/connectors/logos are the point of these components. One was built and reverted; the question is settled. |
| D2 | New class vs. new `Version` constant | **Form factor decides.** Same outline and pin positions → append a `Version` enum constant. Different footprint → new class. | Already the established paradigm (`ArduinoUno`, `RaspberryPiPico`, `RaspberryPiZero`, `ESP32DevKit`). Keeps the palette short without forcing unrelated geometry into one draw method. |
| D3 | Where pin data lives | **Hardcoded `String[]` arrays in the component class.** | Matches every existing board. An external pin-definition resource and per-pin type metadata (`POWER_5V`, `GND`, `ADC`, `I2C_SDA`…) were both considered and declined; no pin-data infrastructure is introduced here. |
| D4 | Package boundary | **`micro` only.** | Adjacent gaps (Qwiic/STEMMA QT/Grove connectors, shields and HATs, stackable headers) are real but belong to `connectivity` / `electromechanical` and are out of scope for this document. |
| D5 | Backward compatibility | Append-only enums, unchanged defaults, unchanged control-point counts for existing variants. | `.diy` files are a public contract; see §4.3. No file-format migration is needed anywhere in this roadmap. |
### Explicitly out of scope
- A configurable catch-all board component (D1).
- Pin-type metadata and any electrical rule check built on it (D3).
- Shields, HATs, stacking, and the Qwiic/STEMMA QT/Grove connector family (D4).
- Bumping the project version, packaging, and the deployment build.
## 3. Current coverage
| Class | Variants | Notes |
|---|---|---|
| `ArduinoUno` | R3, R4 WiFi, **R4 Minima**, **Leonardo** | |
| `ArduinoMega` | — | |
| `ArduinoNano` | **classic, Every, 33 IoT, 33 BLE, 33 BLE Sense, RP2040 Connect, Nano ESP32** | |
| `ESP32DevKit` | V1 30-pin, DevKitC V4 38-pin, S3 DevKitC-1 44-pin, **C3 DevKitM-1 30-pin**, **C6 DevKitC-1 32-pin** | per-version pin arrays, geometry and draw branches |
| `ESP8266NodeMCU` | — | |
| `WemosD1Mini` | — | hardcodes `SILK_PIN_NAMES_LEFT/RIGHT` instead of `drawPinLabels` |
| `RaspberryPi` | 3B+, 4B, 5 | |
| `RaspberryPiZero` | Zero, Zero W, **Zero 2 W** | |
| `RaspberryPiPico` | Pico, Pico W, **Pico 2**, **Pico 2 W** | castellated pad rendering |
| `Teensy` | 4.0, 4.1, **Teensy 3.2** | |
Variants in bold landed with this roadmap; everything in §5.1 and §5.2 is now **done**. All ten are
`category = "Controllers"`, `bomPolicy = SHOW_ONLY_TYPE_NAME`, `enableCache = true`, and extend
`AbstractMakerBoard`.
## 4. Shared mechanics
Applies to every item in every tier.
### 4.1 Component discovery
Components are found by classpath annotation scan in `ComponentProcessor.getComponentTypes()`
(Reflections, `TypesAnnotated`, `includePackage("org.diylc.components")`). **Any class carrying
`@ComponentDescriptor` is picked up automatically** — there is no manifest or registry to edit.
Adding enum constants to an existing class needs nothing. Adding a *new* class needs nothing for
discovery, but should be added to the hand-maintained list in
`org.diylc.components.maker.MakerComponentsTest#allMakerComponentClasses`.
### 4.2 Version property pattern
```java
public enum XxxVersion { A("Label A"), B("Label B"); ... toString() returns label; }
protected XxxVersion version = XxxVersion.A; // default initializer
@EditableProperty(name = "Version")
public XxxVersion getVersion() {
if (version == null) version = XxxVersion.A; // null-guard for old files
return version;
}
public void setVersion(XxxVersion version) {
this.version = version;
updateControlPoints(); // only if geometry changes
invalidateCache(); // required: enableCache = true
}
```
XStream serializes enum constants **by name** — `.diy` files contain `<orientation>_90</orientation>`
and the like, and no custom enum converter is registered — so adding constants and reordering them
are both backward compatible. **Removing or renaming one is not.** Ordinals are used only by the
rotation transformers (`Orientation`, `OrientationHV`, `Orientation45`), never by a `Version` enum,
so a version enum may be sorted for a tidy drop-down; `ArduinoNano.NanoVersion` is ordered by label
for exactly that reason. Keep the default constant and the null-guard so existing files deserialize
unchanged.
### 4.3 Serialization safety checklist (per changed class)
- `serialVersionUID` stays `1L`.
- The default `version` field value is unchanged, so old files keep their look.
- **Control-point count must not change for existing variants.** If a new variant has a
different pin count, `updateControlPoints()` must size the array from the per-version pin list
(as `ESP32DevKit` already does), and any code assuming a fixed `PIN_NAMES.length` must switch
on version.
- `drawIcon()` reflects only the default variant — leave it alone unless the default changes.
### 4.4 Test pattern
Each board has a `*Test.java` under `diylc-library/src/test/java/org/diylc/components/micro/`:
- `testControlPointCountAndNames()` — count, every name non-empty, spot checks
- `testDimensionsAndPinGeometry()` — `getBodyShape().getBounds2D()` against expected mm, and
control-point offsets from board edges
- `testVersionProperty()` — default, `toString()` labels, round-trip through the setter
- a `*Drawing` smoke test — `draw()` in NORMAL / SELECTED / outline, headers on and off, against
a `BufferedImage` with a no-op `IDrawingObserver`
Extend these in place; add one geometry test and one draw smoke test per new variant.
### 4.5 Sourcing dimensions and pin names
Every dimension constant and every pin array below must be cross-checked against vendor
documentation before it is committed. Where this document states a size or a pin count without
naming a source, it is an estimate to scope the work, not a datasheet citation.
What actually works as a source:
- **Arduino** — `docs.arduino.cc/resources/pinouts/<SKU>-full-pinout.pdf` is canonical for PWM
tildes and silkscreen names; `docs.arduino.cc/resources/datasheets/<SKU>-datasheet.pdf` carries
the numbered header tables. The HTML product and cheat-sheet pages render client-side and yield
nothing to a fetch.
- **Espressif** — the `esp-dev-kits` user guides carry complete J1/J3 header tables as HTML.
- **PJRC** — pinout cards, not yet used for the Teensy 3.2 bottom cluster (see §5.1 item 4).
Note that these PDFs need downloading and text extraction; a plain fetch returns binary. Do not
assume variants of one board share a pinout — across the Nano family the PWM sets, the bus
annotations and the power pins all differ per variant.
### 4.6 Build and verify
```bash
cd diylc
mvn -pl diylc-library -am test
```
Rendering-regression fixtures live in `../diylc-regression-data/` but are not wired into the
library test run, so new variants do not break it. When those baselines are next regenerated,
add sample placements for the new variants.
---
## 5. Tier 1
Boards a maker is very likely to reach for and cannot draw today.
### 5.1 Enum appends to existing classes — **done**
The cheapest fidelity wins in the whole roadmap — the geometry is already correct, so each is a
pin array, a silk label and a few draw branches.
| # | Board | Host class | Change |
|---|---|---|---|
| 1 | Raspberry Pi Pico 2 / Pico 2 W (RP2350) | `RaspberryPiPico` | 2 constants |
| 2 | Raspberry Pi Zero 2 W | `RaspberryPiZero` | 1 constant |
| 3 | Arduino Uno R4 Minima | `ArduinoUno` | 1 constant |
| 4 | Teensy 3.2 | `Teensy` | 1 constant + pin array |
| 5 | Arduino Leonardo | `ArduinoUno` | 1 constant + pin array |
**Item 1 — Pico 2 / Pico 2 W.** The Pico 2 is pin-, size- and connector-identical to the Pico
(21 × 51 mm, 2×20 castellated plus through-hole, 3-pad SWD, micro-USB, BOOTSEL). The visible
differences: the SoC silk reads `RP2350` instead of `RP2040`, and Pico 2 W carries the same
Infineon CYW43439 radio in the same position as Pico W, so its 3-pad SWD block sits at the
Pico W offset.
1. `PicoVersion`: append `PICO_2("Pi Pico 2")`, `PICO_2_W("Pi Pico 2 W")`.
2. Add helpers so the existing checks stay readable:
```java
private boolean isW() { return version == PicoVersion.PICO_W || version == PicoVersion.PICO_2_W; }
private boolean isV2() { return version == PicoVersion.PICO_2 || version == PicoVersion.PICO_2_W; }
```
3. In `updateControlPoints()`, `getBodyShape()`, `drawCastellatedPads()` and `draw()`, replace
`getVersion() == PicoVersion.PICO_W` with `isW()`.
4. The chip label becomes `isV2() ? "RP2350" : "RP2040"`.
5. `PIN_NAMES` is unchanged and shared across all four variants.
6. `drawIcon()` unchanged (default is still `PICO`).
Tests: extend `testVersionProperty()`; add `testPico2GeometryMatchesPico()` asserting identical
body bounds and control-point count for `PICO`/`PICO_2` and `PICO_W`/`PICO_2_W`; draw smoke test
for `PICO_2_W`. **~2–3 h, minimal risk.**
**Item 2 — Pi Zero 2 W.** Identical 65 × 30 mm outline, identical 40-pin GPIO position, identical
connector layout (mini-HDMI, 2× micro-USB, CSI FPC on the right edge, 4 mounting holes). The SoC
is the RP3A0 package-on-package with integrated radio — physically a ~12 mm square where the
drawing already places a 12 mm chip. Silk and label only.
1. `ZeroVersion`: append `PI_ZERO_2_W("Pi Zero 2 W")`.
2. No geometry change; pin arrays untouched.
3. `draw()` already prints `"Raspberry " + getVersion()` — verify the longer string still fits
inside `hdrBoxW`; if not, drop to `SILK_FONT` or print `getVersion().toString()` alone for
this case.
4. Optional cosmetic touch: draw the SoC as a plain dark PoP square with no Broadcom split.
Tests: extend `testVersionProperty()`; geometry-equivalence assertion against `PI_ZERO_W`; draw
smoke test. **~1–2 h, minimal risk — only watch the label width.**
**Item 3 — Uno R4 Minima.** `ArduinoUno` models R3 and R4 WiFi but not the Minima, which shares
the R4 WiFi board outline and header positions and differs in silk (no ESP32-S3 radio module, no
LED matrix) and in the absence of the WiFi can. Append `R4_MINIMA("UNO R4 Minima")` and branch the
draw code that places the radio module and matrix.
**Item 4 — Teensy 3.2.** Same 1.4 × 0.7" outline and 2×14 header positions as Teensy 4.0, so this
is a pin array plus silk. Implemented with 34 control points — the two 1×14 edge rows, the
five-hole bottom cluster and the severable VUSB pad — and an `isCompact()` helper that groups the
3.2 with the 4.0 against the longer 4.1. **The bottom-cluster labels (`VBAT`, `3.3V`, `GND`,
`Program`, `A14/DAC`) are the one part not taken from a primary source and are worth checking
against the PJRC pinout card.**
**Item 5 — Arduino Leonardo.** Shares the Uno R3 shield footprint and header positions exactly.
Differences are the ATmega32U4 silk, micro-USB in place of USB-B (`drawMicroUsb` instead of
`drawUsbB`), and no separate USB-serial chip. Pin names are the R3 map with the native-USB
annotations.
### 5.2 Version retrofit and new pin arrays — **done**
**Item 6 — Modern Arduino Nano family.** `ArduinoNano` has no version property; Tier 1 introduces
one and adds the current lineup. All share the classic 0.73 × 1.70" outline and the 2×15 pin
positions, but **only the classic Nano populates the 2×3 ICSP block** — on every later board that
end of the PCB carries the radio module or USB bridge instead. So the classic keeps its 36 control
points and the modern variants have 30. Serialization is safe because the classic is the default
and is untouched; the shorter counts belong to enum constants no shipped file references.
```java
public enum NanoVersion {
CLASSIC("Nano (ATmega328)"), // default; current behavior
EVERY("Nano Every"),
NANO_33_IOT("Nano 33 IoT"),
NANO_33_BLE("Nano 33 BLE"),
NANO_33_BLE_SENSE("Nano 33 BLE Sense"),
NANO_RP2040_CONNECT("Nano RP2040 Connect"),
NANO_ESP32("Nano ESP32");
}
```
What varies by version:
| Aspect | CLASSIC | EVERY | 33 IoT | 33 BLE / Sense | RP2040 Connect | Nano ESP32 |
|---|---|---|---|---|---|---|
| Separate MCU package | `m328P` (rot. 45°) | `m4809` | `SAMD21` | — (in module) | `RP2040` | — (in module) |
| Part at the far end | ICSP 2×3 header | `SAMD11` bridge | `NINA-W102` can | `NINA-B306` can | `NINA-W102` can | `NORA-W106` can |
| USB | Mini-B | Micro-B | Micro-B | Micro-B | Micro-B | **USB-C** |
| Pin-name array | classic | modern | modern | modern | modern | modern + `GPIOxx` |
| Control points | 36 | 30 | 30 | 30 | 30 | 30 |
The enum carries the silk label, the MCU marking and the end-module marking, so `draw()` branches
only on USB type, whether the MCU package is drawn separately (it is not when the die sits inside
the module) and whether the end part is a shielded can or a bare QFN.
`drawMiniUsb`, `drawMicroUsb`, `drawUsbC`, `drawMetalConnector` and `drawChip` all already exist
in `AbstractMakerBoard`.
Pin arrays: `PIN_NAMES` keeps the classic 36 entries. Each later board gets **its own 30-entry
array**, transcribed from its official Arduino pinout diagram (`docs.arduino.cc/resources/pinouts/
<SKU>-full-pinout.pdf`) rather than assumed from the classic. A single shared "modern" array was
wrong: the PWM sets and the power pins genuinely differ.
| Version | PWM pins | Position 17 | Position 18 | Position 27 |
|---|---|---|---|---|
| CLASSIC | D3 D5 D6 D9 D10 D11 | RST2 | 5V | AREF |
| EVERY | D3 D5 D6 D9 D10 | RST2 | 5V | AREF |
| NANO_33_IOT | D2 D3 D5 D6 D9 D10 | RST2 | 5V | AREF |
| NANO_33_BLE / _SENSE | D2–D13 (all) | RST2 | 5V | AREF |
| NANO_RP2040_CONNECT | D2–D13 (all) | **REC** (BOOTSEL) | 5V | AREF |
| NANO_ESP32 | D0–D13 and A0–A7 | **B1** | **VUSB** | **B0** |
| NANO_R4 | D3 D5 D6 D9 D10 D11 | **BOOT** | 5V | AREF |
The Nano R4 (ABX00142, Renesas RA4M1) additionally annotates D4/D5 as the CAN pins, A0 as the DAC
and A1–A3 as the on-chip OPAMP inputs and output, and its end-of-board part is the **Qwiic**
JST-SH socket rather than a radio module — drawn with `drawFpcConnector`, since it is a connector
and not a shielded can.
`PIN_NAMES_ESP32` additionally dual-labels with the Espressif GPIO number, e.g. `D2 (~, GPIO5)`;
those numbers are taken from the ABX00083 pinout diagram.
`draw()` gains version switches for the MCU chip label (and whether it is drawn rotated 45° like
the classic TQFP or axis-aligned like a QFN), the end module, and the USB connector helper. Board
outline and mounting holes are unchanged. Because the pin count is now version-dependent,
`setVersion()` must call `updateControlPoints()` — it previously only invalidated the cache, which
was harmless while the geometry was fixed.
The `5V` / `3V3` logic-level silk from the original plan was dropped: the Nano draws no pin labels
at all, so a lone voltage annotation would be invented silkscreen rather than what is on the board.
The modern Nanos also have **castellated edges** rather than plain through-holes: the outline is
notched at every pin and the pads run out to the board edge, exactly as on the Pico. That rendering
now lives in `AbstractMakerBoard` as `drawCastellatedPads` (one column of pads toward a given edge)
and `subtractCastellationNotches` (the matching bites out of the outline), with
`getCastellatedPadSize` / `HoleSize` / `NotchSize` / `PadColor` as the per-board overrides.
`RaspberryPiPico` was refactored onto the same pair — its own method survives only as the wrapper
that places the two columns and draws the SWD pads, so its rendering is unchanged. Any future
castellated board (the ESP32 SuperMini and XIAO in §5.3 / §6) should reuse these rather than copy
the geometry a third time.
Tests: `testVersionProperty()` (default `CLASSIC`, labels, round-trip);
`testPinNamesPerVersion()` over all seven versions asserting no empty names, the `A4 (SDA)`
annotation on a modern version and the GPIO dual-label on `NANO_ESP32`;
`testGeometryIsVersionIndependent()` and `testModernVersionsHaveNoIcspBlock()` pinning the 36/30
split and the outline; draw smoke test looping all versions × headers on/off. **The value is
entirely in getting the labels and per-board silk right; the rendering scaffold is a light touch.**
**Item 7 — ESP32-C3 DevKitM-1 and ESP32-C6 DevKitC-1.** The heaviest enum-style item, because
`ESP32DevKit` gives every variant its own pin array and its own branch in `getRelativeOffsets()`,
`getBodyShape()` and `draw()`. The C3 is a genuinely different board (single RISC-V core,
ESP32-C3-MINI-1 module, one addressable RGB LED), not a re-label.
Both pin arrays were transcribed from the Espressif `esp-dev-kits` user guides (the J1/J3 header
tables), not from memory — see D3's note in §4.5.
- **ESP32-C3-DevKitM-1**: two 1×15 headers (**30 pins**) on 0.1" pitch, row spacing 22.86 mm
(0.9"), ESP32-C3-MINI-1 module with PCB antenna at the top, a **single micro-USB** port at the
bottom, `BOOT` + `RST` buttons.
- **ESP32-C6-DevKitC-1**: two 1×16 headers (**32 pins**, the last position on each is `NC`) on the
same 0.9" body, ESP32-C6-WROOM-1 module, **two USB-C** connectors (USB-to-UART and native).
Espressif publishes these outlines only as dimension drawings, so `BOARD_WIDTH_RISCV` (25.4 mm) and
the row spacing are taken from the shared DevKitC form factor and the body length is *derived* as
top margin + pin field + bottom margin using the same margins as the S3 DevKitC-1. That derivation
is called out in a comment on the constants and is the thing to check if a board ever measures
wrong.
1. `DevKitVersion`: append `ESP32_C3_DevKitM_1("ESP32-C3 DevKitM-1 (32-Pin)")` and
`ESP32_C6_DevKitC_1("ESP32-C6 DevKitC-1 (32-Pin)")`.
2. Add `PIN_NAMES_C3` and `PIN_NAMES_C6`.
3. Add `BOARD_WIDTH_C3` / `BOARD_LENGTH_C3` (and `_C6`) plus module and antenna sizes; the C3
module is smaller than WROOM-32, so `SHIELD_*_S3` is the better starting point.
4. `getControlPointNodeName(int)`: two new branches.
5. `getRelativeOffsets()`: two branches. Both are the simple two-straight-columns layout — copy
the 30-pin branch and change the loop bounds and row-spacing constant.
6. `getBodyShape()`: rounded rectangle plus PCB-antenna notch at the top, as the 30-pin and S3
cases already do.
7. `draw()`: module shield labelled `ESP32-C3-MINI-1` / `ESP32-C6-WROOM-1` via
`drawMetalConnector`, PCB antenna via `drawPcbAntenna`, `BOOT`/`RST` via `drawButton`, USB via
`drawMicroUsb` ×2 (C3) or `drawUsbC` ×2 (C6), one RGB LED dot.
8. `drawIcon()` unchanged (default stays 30-pin V1).
Tests mirror the existing per-version blocks. **~1 day, moderate risk** — geometry constants need
datasheet cross-checking, but the change is contained entirely within `ESP32DevKit`.
### 5.3 New classes
Genuinely different footprints, so per D2 each gets its own class.
| # | Board | Shape | Why Tier 1 |
|---|---|---|---|
| 8 | **ESP32-CAM** | ~40 × 27 mm, 2×8 headers, OV2640 camera FPC, microSD slot | After the DevKit, the most-used ESP32 board in hobby projects. Nothing close exists. |
| 9 | **ESP32 SuperMini** | ~22.5 × 18 mm, 2×8 castellated, PCB antenna. One class, `Version` {C3, S3} | Now the default cheap ESP32 board. Model on `RaspberryPiPico`'s castellated pad rendering. |
| 10 | **Arduino Pro Micro** | ~33 × 18 mm, 2×12, ATmega32U4, micro-USB | The HID and custom-keyboard staple; no equivalent in the set. |
| 11 | **Arduino Pro Mini** | ~33 × 18 mm, 2×12 + 6-pin FTDI header. `Version` {5V 16 MHz, 3.3V 8 MHz} | Still ubiquitous on breadboards. Identical outline between the two variants; differs in silk and regulator. |
| 12 | **STM32 Pill** | ~53 × 22 mm, 2×20 on 0.1". `Version` {Blue Pill F103, Black Pill F401, Black Pill F411} | Cheapest ARM path, still everywhere. Shared outline makes this one class. |
Item 9 replaces the "Tier 2, note only" treatment the SuperMini had in the superseded document:
it is a different footprint from the DevKit (so a separate class, per D2) and is common enough now
to belong in Tier 1.
---
## 6. Tier 2
Whole ecosystems worth a deliberate push. Each is one class plus a `Version` enum where the vendor
standardised a footprint, and separate classes where they did not.
| Board / family | Structure | Notes |
|---|---|---|
| **Seeed XIAO** | one class, `Version` {ESP32-C3, ESP32-S3, RP2040, nRF52840, SAMD21} | Seeed standardised a ~21 × 17.5 mm castellated footprint across the family — a textbook single-class case under D2. |
| **Adafruit Feather** | one class, `Version` {M0 Express, M4 Express, ESP32-S3, RP2040} | Standardised 0.9 × 2.0" outline. |
| **Adafruit QT Py / ItsyBitsy** | one class each | Different footprints from Feather and from each other. |
| **BBC micro:bit** | one class, `Version` {v1, v2} | Enormous in education. The gold edge connector is genuinely new drawing work, which is why it is not Tier 1. |
| **Arduino MKR** | one class, `Version` {WiFi 1010, Zero, NB 1500} | Shared ~25 × 61.5 mm outline. |
| **Heltec WiFi LoRa 32** | one class, `Version` {V2, V3} | LoRa + OLED. The Meshtastic community is large and entirely unserved today. |
| **LilyGO T-Display-S3** | one class | ESP32-S3 with an integrated TFT. |
| **TTGO LoRa32** | one class | Distinct footprint from the Heltec boards. |
| **M5Stack** | `M5StackCore` (Core2), `M5StickC` (Plus / Plus2), `M5Atom` (Atom / StampS3) | Four distinct form factors; group by footprint, not by brand. |
| **Waveshare RP2040-Zero** | one class | ~18 × 23.5 mm castellated. |
| **Pimoroni Tiny 2040** | one class | Sibling footprint to RP2040-Zero but not identical. |
| **Pi-compatible SBCs** | `OrangePiZero`, `RadxaZero`, `LePotato` | Same 40-pin header, different outlines, so named classes rather than one shared one (D1, D2). |
---
## 7. Tier 3
Long tail and specialty. Add on request or when a specific project needs one.
- **Pro / industrial Arduino** — Giga R1, Portenta H7, Nicla Sense, Due, Zero, Micro.
- **Raspberry Pi variants** — CM4 / CM5 plus IO board, Pi 400 / 500.
- **AI accelerators** — Jetson Orin Nano, Google Coral Dev Board.
- **Other SBCs and RISC-V** — BeagleBone Black, Milk-V Duo, ESP32-P4, CH32V003.
- **Legacy** — Teensy LC, Teensy 2.0++, Digispark ATtiny85, Wemos D1 R32.
- **Bare modules for custom-PCB work** — ESP-01, ESP-12F, ESP32-WROOM-32, nRF52840 module. These
are footprints rather than dev boards; if they are ever added, check whether they belong in
`micro` at all or alongside the SMD packages.
---
## 8. Cross-cutting fixes
Small, independent, and worth folding into whichever Tier 1 item is done first.
1. **`Teensy` z-order.** `Teensy.java:54` declares `zOrder = IDIYComponent.BOARD`, while every
other breadboard-friendly board in the package (`ArduinoNano`, `RaspberryPiPico`,
`ESP32DevKit`, `ESP8266NodeMCU`, `WemosD1Mini`) uses `COMPONENT`. `Breadboard` is also `BOARD`,
so a Teensy dropped on a breadboard renders in placement order rather than reliably on top.
Looks like an oversight; changing it affects only draw order, not serialization.
2. **`Version` never reaches the BOM.** `getValue()` returns `null` and every board uses
`bomPolicy = SHOW_ONLY_TYPE_NAME`, so a Uno R3 and a Uno R4 WiFi both print as "Arduino Uno".
A maker's BOM is a shopping list and the variant is the part they buy. Worth deciding on a
uniform approach before the roadmap roughly triples the number of variants.
3. **Editable-property set drifts across the family.** `Headers` exists on `ArduinoNano` and
`RaspberryPiZero` but not on `ArduinoUno`, `Teensy` or `ESP32DevKit`; there is no "show pin
labels" toggle anywhere; `WemosD1Mini` hardcodes `SILK_PIN_NAMES_LEFT` / `SILK_PIN_NAMES_RIGHT`
instead of using the shared `drawPinLabels`. Settling a uniform Version / Headers / Show Labels
/ Board Color set now stops ten more boards inheriting the inconsistency.
4. **Pin-name conventions differ.** `ESP32DevKit` uses `GND_1`, `ArduinoNano` uses `GND1`. And
`AbstractMakerBoard.getDisplayPinLabel` truncates at the first `_` and `(`, so `ArduinoNano`'s
`D3 (~)` silently loses its PWM marker on the silkscreen. Pick one convention before adding
more arrays.
Items 1 and 4 are behavioural changes small enough to carry their own regression-suite run;
items 2 and 3 are decisions to make before the bulk of the roadmap lands.
## 9. Suggested sequencing
1. ~~**§5.1 enum appends**~~ — **done**: Pico 2 / 2 W, Zero 2 W, Uno R4 Minima, Leonardo,
Teensy 3.2.
2. ~~**§5.2 Item 6, modern Nano**~~ and ~~**Item 7, ESP32-C3 / C6**~~ — **done**.
3. **Cross-cutting fixes** (§8) — cheap, and fix 4 is better done before more pin arrays exist.
4. **§5.3 new classes** — ESP32-CAM and SuperMini first; they close the largest remaining gaps.
5. **Tier 2** — one family at a time, each an independent commit.
Each item is an independent commit; none depends on another except where sequencing is noted.
## 10. Open decisions
1. **BOM treatment of `Version`** (§8.2). Options: leave as-is; switch these boards to a BOM
policy that includes the variant; or expose the variant through a value-like property. Affects
every board in the package, so worth deciding once.
2. **Uniform property set** (§8.3). Which of `Headers` and a new "Show Pin Labels" toggle should
exist on all boards, and whether retrofitting `Headers` onto `ArduinoUno` / `Teensy` /
`ESP32DevKit` is wanted. New boolean fields deserialize as `false` in old files, so the default
must be chosen to preserve the current look.
3. **ESP32-C6 in the same pass as C3?** §5.2 Item 7 is written for both since they share a body.
If time-boxing, ship C3 first and add C6 as a one-branch follow-up.
4. **Nano pin-label verbosity** (§5.2 Item 6). Recommendation as written: annotate bus pins on all
modern variants, add the GPIO number only for `NANO_ESP32`.
5. **i18n.** Component display names in `@ComponentDescriptor` are not currently in
`diylc-swing/src/main/resources/lang/*.txt` for these boards, and the enum labels are plain
strings shown in the property editor. No translation work is required by this roadmap; noted
for a future i18n pass.