labeling improvement

This commit is contained in:
Bane Stojkovic
2026-09-09 17:03:24 +02:00
parent de5bfd43f8
commit 3fbcd3eaa9
4 changed files with 146 additions and 5 deletions
@@ -279,6 +279,14 @@ public abstract class AbstractMakerBoard extends AbstractTransparentComponent<Vo
return getDisplayPinLabel(getControlPointNodeName(index));
}
/**
* Gap between a pad and the name printed next to it. Boards that silkscreen their pad names
* tighter than the Arduino convention override this.
*/
protected Size getPinLabelOffset() {
return PIN_LABEL_OFFSET;
}
/**
* Helper to draw rotated control point / pin names next to the pins for dual-row DIP/header boards.
*
@@ -308,7 +316,7 @@ public abstract class AbstractMakerBoard extends AbstractTransparentComponent<Vo
protected void drawPinLabels(Graphics2D g2d, double x, double y, double[][] offsets,
int pinsPerRow, Color silkColor) {
if (offsets == null || offsets.length == 0) return;
double labelOffset = PIN_LABEL_OFFSET.convertToPixels();
double labelOffset = getPinLabelOffset().convertToPixels();
g2d.setColor(silkColor);
g2d.setFont(PIN_FONT);
@@ -99,6 +99,8 @@ public class RaspberryPiPico extends AbstractMakerBoard {
public static Size BOOTSEL_OFFSET_X = new Size(3.5d, SizeUnit.mm);
public static Size BOOTSEL_OFFSET_Y = new Size(10.0d, SizeUnit.mm);
public static Size BOOTSEL_LABEL_OFFSET = new Size(1.3d, SizeUnit.mm);
// measured from the top edge of the chip up to the middle of the model name
public static Size MODEL_LABEL_OFFSET = new Size(2.5d, SizeUnit.mm);
public static Size DEBUG_PAD_OFFSET_X = new Size(7.38d, SizeUnit.mm);
public static Size DEBUG_PAD_OFFSET_Y = new Size(19.8d, SizeUnit.mm);
@@ -326,6 +328,13 @@ public class RaspberryPiPico extends AbstractMakerBoard {
: boardY + new Size(23.0d, SizeUnit.mm).convertToPixels();
MakerBoardPainter.drawChip(g2d, chipX, chipY, chipSize, chipSize, isV2() ? "RP2350" : "RP2040");
// Model name, in the gap the board leaves between the BOOTSEL button and the chip
g2d.setColor(Color.WHITE);
g2d.setFont(SILK_FONT);
StringUtils.drawCenteredText(g2d, getVersion().toString(), boardX + boardW / 2.0,
chipY - MODEL_LABEL_OFFSET.convertToPixels(), HorizontalAlignment.CENTER,
VerticalAlignment.CENTER);
if (isW()) {
double spacing = PIN_SPACING.convertToPixels();
double midDebugX = boardX + boardW - DEBUG_PAD_OFFSET_X.convertToPixels();
@@ -84,6 +84,9 @@ public class Teensy extends AbstractMakerBoard {
public static Color PAD_COLOR = GOLD_COLOR;
public static Size HOLE_SIZE = new Size(0.7d, SizeUnit.mm);
// PJRC prints the pad names tighter to the pads than the Arduino boards do
public static Size SILK_LABEL_OFFSET = new Size(1.6d, SizeUnit.mm);
// ===== Teensy 4.0 dimensions (PJRC dimensions_teensy40.png) =====
// 35.56 mm x 17.78 mm (1.4" x 0.7")
public static Size BOARD_WIDTH_40 = new Size(17.78d, SizeUnit.mm);
@@ -125,6 +128,20 @@ public class Teensy extends AbstractMakerBoard {
"VUSB"
};
// What the board prints between the two rows, which is shorter than the node name: the
// alternate functions the node names carry are not silkscreened at all, and the pads of the
// bottom cluster and the severable VUSB pad are printed on the underside, so these arrays cover
// the two pin rows only.
//
// The compact boards leave three of them blank because there is no room for them: the two bottom
// pads sit level with the five-hole cluster and the right ground with the VUSB pad.
public static final String[] SILK_NAMES_40 = new String[] {
// Left row (0..13)
"GND", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "",
// Right row (14..27)
"VIN", "", "3.3V", "23", "22", "21", "20", "19", "18", "17", "16", "15", "14", ""
};
// ===== Teensy 4.1 Pinout (65 pins total) =====
// Left row (0..23, top to bottom): GND, 0..12, 3.3V, 24..32
// Right row (24..47, top to bottom): VIN, GND, 3.3V, 23..13, GND, 41..33
@@ -155,6 +172,15 @@ public class Teensy extends AbstractMakerBoard {
"VUSB"
};
public static final String[] SILK_NAMES_41 = new String[] {
// Left row (0..23)
"GND", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "3.3V", "24",
"25", "26", "27", "28", "29", "30", "31", "32",
// Right row (24..47)
"VIN", "GND", "3.3V", "23", "22", "21", "20", "19", "18", "17", "16", "15", "14", "13",
"GND", "41", "40", "39", "38", "37", "36", "35", "34", "33"
};
// ===== Teensy 3.2 Pinout (34 pins total) =====
// Same edge-pin layout as the 4.0: two 1x14 rows, a 5-hole cluster on the bottom edge and the
// severable VUSB pad next to Vin. Labels follow the PJRC Teensy 3.2 pinout card.
@@ -172,6 +198,16 @@ public class Teensy extends AbstractMakerBoard {
"VUSB"
};
// Sharing the 4.0's outline, the 3.2 has the same three pads it cannot print. The one it brings
// out to the header in their place is the analog ground, one pin below Vin, and that is the pad
// the VUSB pad sits level with.
public static final String[] SILK_NAMES_32 = new String[] {
// Left row (0..13)
"GND", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "",
// Right row (14..27)
"VIN", "", "3.3V", "23", "22", "21", "20", "19", "18", "17", "16", "15", "14", ""
};
private TeensyVersion version = TeensyVersion.Teensy_4_0;
protected boolean headers = false;
@@ -232,6 +268,21 @@ public class Teensy extends AbstractMakerBoard {
}
}
private String[] getSilkNames() {
switch (getVersion()) {
case Teensy_4_1:
return SILK_NAMES_41;
case Teensy_3_2:
return SILK_NAMES_32;
default:
return SILK_NAMES_40;
}
}
private int getPinsPerRow() {
return isCompact() ? 14 : 24;
}
@Override
public String getControlPointNodeName(int index) {
String[] names = getPinNames();
@@ -242,8 +293,20 @@ public class Teensy extends AbstractMakerBoard {
}
@Override
protected void updateControlPoints() {
Point2D firstPoint = controlPoints[0];
protected String getSilkPinLabel(int index) {
String[] silkNames = getSilkNames();
if (index >= 0 && index < silkNames.length) {
return silkNames[index];
}
return super.getSilkPinLabel(index);
}
@Override
protected Size getPinLabelOffset() {
return SILK_LABEL_OFFSET;
}
private double[][] getRelativeOffsets() {
double spacing = PIN_SPACING.convertToPixels();
double rowSpacing = ROW_SPACING.convertToPixels();
@@ -272,7 +335,7 @@ public class Teensy extends AbstractMakerBoard {
relativeOffsets[33][0] = rowSpacing - spacing;
relativeOffsets[33][1] = spacing;
rotatePoints(firstPoint, relativeOffsets);
return relativeOffsets;
} else {
double[][] relativeOffsets = new double[PIN_NAMES_41.length][2];
@@ -320,10 +383,15 @@ public class Teensy extends AbstractMakerBoard {
relativeOffsets[64][0] = rowSpacing - spacing;
relativeOffsets[64][1] = spacing;
rotatePoints(firstPoint, relativeOffsets);
return relativeOffsets;
}
}
@Override
protected void updateControlPoints() {
rotatePoints(controlPoints[0], getRelativeOffsets());
}
@Override
public Shape getBodyShape() {
Point2D p0 = controlPoints[0];
@@ -426,6 +494,9 @@ public class Teensy extends AbstractMakerBoard {
? chipY + chipH + new Size(2.5d, SizeUnit.mm).convertToPixels()
: chipY + chipH + new Size(3.0d, SizeUnit.mm).convertToPixels();
StringUtils.drawCenteredText(g2d, silkText, centerX, textY, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
// Pad names, printed between the two rows the way they are on the board
drawPinLabels(g2d, x, y, getRelativeOffsets(), getPinsPerRow(), SILK_COLOR);
}
drawingObserver.stopTracking();
@@ -323,5 +323,58 @@ public class TeensyTest {
Assert.assertEquals(Teensy.BOARD_LENGTH_40.convertToPixels(), bounds.getHeight(), 0.1);
}
@Test
public void testSilkPinLabels() {
// the silkscreen covers the two pin rows only; the bottom cluster and the VUSB pad are
// printed on the underside of the board
Assert.assertEquals(28, Teensy.SILK_NAMES_40.length);
Assert.assertEquals(48, Teensy.SILK_NAMES_41.length);
Assert.assertEquals(28, Teensy.SILK_NAMES_32.length);
Teensy teensy = new Teensy();
// the silkscreen carries what is printed on the board, which is not the node name: the
// alternate functions are dropped and the supply pads are spelled out
Assert.assertEquals("0 (RX1/CS1/CRX2)", teensy.getControlPointNodeName(1));
Assert.assertEquals("0", teensy.getSilkPinLabel(1));
Assert.assertEquals("GND", teensy.getSilkPinLabel(0));
Assert.assertEquals("VIN", teensy.getSilkPinLabel(14));
Assert.assertEquals("3.3V", teensy.getSilkPinLabel(16));
Assert.assertEquals("23", teensy.getSilkPinLabel(17));
// the three pads the compact boards have no room to print sit level with the five-hole cluster
// and the VUSB pad
Assert.assertEquals("", teensy.getSilkPinLabel(13));
Assert.assertEquals("", teensy.getSilkPinLabel(15));
Assert.assertEquals("", teensy.getSilkPinLabel(27));
Teensy teensy41 = new Teensy();
teensy41.setVersion(Teensy.TeensyVersion.Teensy_4_1);
// the longer board prints all of its pads, none of them being level with the cluster
Assert.assertEquals("12", teensy41.getSilkPinLabel(13));
Assert.assertEquals("GND", teensy41.getSilkPinLabel(25));
Assert.assertEquals("3.3V", teensy41.getSilkPinLabel(14));
Assert.assertEquals("32", teensy41.getSilkPinLabel(23));
Assert.assertEquals("VIN", teensy41.getSilkPinLabel(24));
Assert.assertEquals("33", teensy41.getSilkPinLabel(47));
Teensy teensy32 = new Teensy();
teensy32.setVersion(Teensy.TeensyVersion.Teensy_3_2);
Assert.assertEquals("AGND", teensy32.getControlPointNodeName(15));
Assert.assertEquals("", teensy32.getSilkPinLabel(13));
Assert.assertEquals("", teensy32.getSilkPinLabel(15));
Assert.assertEquals("", teensy32.getSilkPinLabel(27));
Assert.assertEquals("14", teensy32.getSilkPinLabel(26));
for (Teensy.TeensyVersion version : Teensy.TeensyVersion.values()) {
Teensy board = new Teensy();
board.setVersion(version);
for (int i = 0; i < board.getControlPointCount(); i++) {
Assert.assertNotNull(version + " pin " + i + " should have a silkscreen label",
board.getSilkPinLabel(i));
}
}
}
private static final double PIN_SPACING_PX = new Size(0.1d, SizeUnit.in).convertToPixels();
}