mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-07 12:24:58 +10:00
nano labels
This commit is contained in:
@@ -300,25 +300,44 @@ public abstract class AbstractMakerBoard extends AbstractTransparentComponent<Vo
|
||||
*/
|
||||
protected void drawPinLabels(Graphics2D g2d, double x, double y, double[][] offsets, Color silkColor) {
|
||||
if (offsets == null || offsets.length == 0) return;
|
||||
drawPinLabels(g2d, x, y, offsets, offsets.length / 2, silkColor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Variant for boards whose two pin rows do not take up the whole control point array, such as a
|
||||
* board that carries an ICSP block or a connector after them. Control points past the two rows
|
||||
* are left unlabelled.
|
||||
*
|
||||
* @param g2d Graphics2D context (already transformed for board orientation)
|
||||
* @param x Unrotated top-left pin X coordinate (P0.getX())
|
||||
* @param y Unrotated top-left pin Y coordinate (P0.getY())
|
||||
* @param offsets Array of [x, y] relative offsets for all control points
|
||||
* @param pinsPerRow Number of pins in each of the two rows
|
||||
* @param silkColor Silkscreen text color
|
||||
*/
|
||||
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();
|
||||
int count = offsets.length;
|
||||
int half = count / 2;
|
||||
|
||||
g2d.setColor(silkColor);
|
||||
g2d.setFont(PIN_FONT);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
for (int i = 0; i < 2 * pinsPerRow && i < offsets.length; i++) {
|
||||
String label = getSilkPinLabel(i);
|
||||
if (label == null || label.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
boolean leftRow = i < pinsPerRow;
|
||||
double pinX = x + offsets[i][0];
|
||||
double pinY = y + offsets[i][1];
|
||||
double textX = (i < half) ? (pinX + labelOffset) : (pinX - labelOffset);
|
||||
double textX = leftRow ? (pinX + labelOffset) : (pinX - labelOffset);
|
||||
double textY = pinY;
|
||||
|
||||
// the two rows are mirrored so that each label reads away from the pin it belongs to, the
|
||||
// way a board prints them
|
||||
AffineTransform oldLabelTx = g2d.getTransform();
|
||||
g2d.rotate(Math.PI / 2, textX, textY);
|
||||
g2d.rotate(leftRow ? Math.PI / 2 : -Math.PI / 2, textX, textY);
|
||||
StringUtils.drawCenteredText(g2d, label, textX, textY, HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
|
||||
g2d.setTransform(oldLabelTx);
|
||||
}
|
||||
|
||||
@@ -203,6 +203,42 @@ public class ArduinoNano extends AbstractMakerBoard {
|
||||
"B0", "3.3V", "D13 (~, SCK/GPIO48)"
|
||||
};
|
||||
|
||||
// What the boards print next to the pads, which is shorter than the node name: the two grounds
|
||||
// and the two resets are printed alike, the supply is "3V3", and the function annotations the
|
||||
// node names carry are not on the silkscreen at all. The classic Nano's ICSP block and the R4's
|
||||
// Qwiic socket are printed nowhere, so these arrays cover the two pin rows only.
|
||||
public static final String[] SILK_NAMES = new String[] {
|
||||
// Left row (0..14, top to bottom)
|
||||
"TX1", "RX0", "RST", "GND", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "D10", "D11", "D12",
|
||||
// Right row (15..29, top to bottom)
|
||||
"VIN", "GND", "RST", "5V", "A7", "A6", "A5", "A4", "A3", "A2", "A1", "A0", "AREF", "3V3", "D13"
|
||||
};
|
||||
|
||||
// The RP2040 Connect puts the BOOTSEL pad where the other boards repeat RESET
|
||||
public static final String[] SILK_NAMES_RP2040 = new String[] {
|
||||
// Left row (0..14, top to bottom)
|
||||
"TX1", "RX0", "RST", "GND", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "D10", "D11", "D12",
|
||||
// Right row (15..29, top to bottom)
|
||||
"VIN", "GND", "REC", "5V", "A7", "A6", "A5", "A4", "A3", "A2", "A1", "A0", "AREF", "3V3", "D13"
|
||||
};
|
||||
|
||||
// The R4 uses that same pad for boot mode selection
|
||||
public static final String[] SILK_NAMES_R4 = new String[] {
|
||||
// Left row (0..14, top to bottom)
|
||||
"TX1", "RX0", "RST", "GND", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "D10", "D11", "D12",
|
||||
// Right row (15..29, top to bottom)
|
||||
"VIN", "GND", "BOOT", "5V", "A7", "A6", "A5", "A4", "A3", "A2", "A1", "A0", "AREF", "3V3", "D13"
|
||||
};
|
||||
|
||||
// The Nano ESP32 has the B1 / B0 boot-mode pads where the others carry the second RESET and
|
||||
// AREF, and its 5V pad is fed straight from the USB bus
|
||||
public static final String[] SILK_NAMES_ESP32 = new String[] {
|
||||
// Left row (0..14, top to bottom)
|
||||
"TX1", "RX0", "RST", "GND", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "D10", "D11", "D12",
|
||||
// Right row (15..29, top to bottom)
|
||||
"VIN", "GND", "B1", "VUSB", "A7", "A6", "A5", "A4", "A3", "A2", "A1", "A0", "B0", "3V3", "D13"
|
||||
};
|
||||
|
||||
protected NanoVersion version = NanoVersion.CLASSIC;
|
||||
protected boolean headers = false;
|
||||
|
||||
@@ -246,6 +282,28 @@ public class ArduinoNano extends AbstractMakerBoard {
|
||||
}
|
||||
}
|
||||
|
||||
private String[] getSilkNames() {
|
||||
switch (getVersion()) {
|
||||
case NANO_RP2040_CONNECT:
|
||||
return SILK_NAMES_RP2040;
|
||||
case NANO_ESP32:
|
||||
return SILK_NAMES_ESP32;
|
||||
case NANO_R4:
|
||||
return SILK_NAMES_R4;
|
||||
default:
|
||||
return SILK_NAMES;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSilkPinLabel(int index) {
|
||||
String[] silkNames = getSilkNames();
|
||||
if (index >= 0 && index < silkNames.length) {
|
||||
return silkNames[index];
|
||||
}
|
||||
return super.getSilkPinLabel(index);
|
||||
}
|
||||
|
||||
private UsbPortType getUsbPortType() {
|
||||
switch (getVersion()) {
|
||||
case CLASSIC:
|
||||
@@ -305,9 +363,7 @@ public class ArduinoNano extends AbstractMakerBoard {
|
||||
return "Pin " + (index + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateControlPoints() {
|
||||
Point2D firstPoint = controlPoints[0];
|
||||
private double[][] getRelativeOffsets() {
|
||||
double spacing = PIN_SPACING.convertToPixels(); // 20px (0.10")
|
||||
double rowSpacing = ROW_SPACING.convertToPixels(); // 120px (0.60")
|
||||
|
||||
@@ -332,8 +388,7 @@ public class ArduinoNano extends AbstractMakerBoard {
|
||||
relativeOffsets[30][1] = -BOARD_MARGIN_Y.convertToPixels() + END_PART_OFFSET_Y.convertToPixels()
|
||||
+ QWIIC_LENGTH.convertToPixels() / 2.0;
|
||||
}
|
||||
rotatePoints(firstPoint, relativeOffsets);
|
||||
return;
|
||||
return relativeOffsets;
|
||||
}
|
||||
|
||||
// ICSP header (2x3 pins, 30..35) flush with top edge:
|
||||
@@ -359,7 +414,12 @@ public class ArduinoNano extends AbstractMakerBoard {
|
||||
// Pin 6 (GND_ICSP at col0X, inner row)
|
||||
relativeOffsets[35] = new double[] {col0X, icspInnerY};
|
||||
|
||||
rotatePoints(firstPoint, relativeOffsets);
|
||||
return relativeOffsets;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateControlPoints() {
|
||||
rotatePoints(controlPoints[0], getRelativeOffsets());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -539,6 +599,9 @@ public class ArduinoNano extends AbstractMakerBoard {
|
||||
StringUtils.drawCenteredText(g2d, getVersion().getSilkLabel(), boardX + boardW / 2.0,
|
||||
boardY + new Size(0.50d, SizeUnit.in).convertToPixels() + new Size(1.0d, SizeUnit.mm).convertToPixels(),
|
||||
HorizontalAlignment.CENTER, VerticalAlignment.CENTER);
|
||||
|
||||
// Pad names, printed between the two rows the way they are on the board
|
||||
drawPinLabels(g2d, x, y, getRelativeOffsets(), PINS_PER_ROW, SILK_COLOR);
|
||||
}
|
||||
|
||||
// Castellated pads bite into the board edge, so they are drawn while the board rotation is
|
||||
|
||||
@@ -365,6 +365,51 @@ public class ArduinoNanoTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSilkPinLabels() {
|
||||
Assert.assertEquals(2 * ArduinoNano.PINS_PER_ROW, ArduinoNano.SILK_NAMES.length);
|
||||
Assert.assertEquals(2 * ArduinoNano.PINS_PER_ROW, ArduinoNano.SILK_NAMES_RP2040.length);
|
||||
Assert.assertEquals(2 * ArduinoNano.PINS_PER_ROW, ArduinoNano.SILK_NAMES_R4.length);
|
||||
Assert.assertEquals(2 * ArduinoNano.PINS_PER_ROW, ArduinoNano.SILK_NAMES_ESP32.length);
|
||||
|
||||
ArduinoNano nano = new ArduinoNano();
|
||||
|
||||
// the silkscreen prints what is on the board, not the node name: both grounds and both resets
|
||||
// are printed alike and the annotations are dropped
|
||||
Assert.assertEquals("GND1", nano.getControlPointNodeName(3));
|
||||
Assert.assertEquals("GND2", nano.getControlPointNodeName(16));
|
||||
Assert.assertEquals("GND", nano.getSilkPinLabel(3));
|
||||
Assert.assertEquals("GND", nano.getSilkPinLabel(16));
|
||||
Assert.assertEquals("RST", nano.getSilkPinLabel(2));
|
||||
Assert.assertEquals("RST", nano.getSilkPinLabel(17));
|
||||
Assert.assertEquals("TX1", nano.getSilkPinLabel(0));
|
||||
Assert.assertEquals("D3", nano.getSilkPinLabel(5));
|
||||
Assert.assertEquals("3V3", nano.getSilkPinLabel(28));
|
||||
|
||||
// the pad the classic repeats RESET on carries the boot mode selector on the later boards
|
||||
ArduinoNano rp2040 = new ArduinoNano();
|
||||
rp2040.setVersion(ArduinoNano.NanoVersion.NANO_RP2040_CONNECT);
|
||||
Assert.assertEquals("REC", rp2040.getSilkPinLabel(17));
|
||||
|
||||
ArduinoNano r4 = new ArduinoNano();
|
||||
r4.setVersion(ArduinoNano.NanoVersion.NANO_R4);
|
||||
Assert.assertEquals("BOOT", r4.getSilkPinLabel(17));
|
||||
|
||||
ArduinoNano esp32 = new ArduinoNano();
|
||||
esp32.setVersion(ArduinoNano.NanoVersion.NANO_ESP32);
|
||||
Assert.assertEquals("B1", esp32.getSilkPinLabel(17));
|
||||
Assert.assertEquals("B0", esp32.getSilkPinLabel(27));
|
||||
|
||||
for (ArduinoNano.NanoVersion version : ArduinoNano.NanoVersion.values()) {
|
||||
ArduinoNano board = new ArduinoNano();
|
||||
board.setVersion(version);
|
||||
for (int i = 0; i < board.getControlPointCount(); i++) {
|
||||
Assert.assertNotNull(version + " pin " + i + " should have a silkscreen label",
|
||||
board.getSilkPinLabel(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllVersionsDrawing() {
|
||||
java.awt.image.BufferedImage img =
|
||||
|
||||
Reference in New Issue
Block a user