mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-07 12:24:58 +10:00
displays
This commit is contained in:
@@ -50,7 +50,7 @@ import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
import org.diylc.utils.Constants;
|
||||
|
||||
@ComponentDescriptor(name = "Character LCD (16x2 / 20x4)", category = "Displays & Outputs",
|
||||
@ComponentDescriptor(name = "Character LCD", category = "Displays & Outputs",
|
||||
author = "Branislav Stojkovic", description = "HD44780-Compatible Character LCD Display (Parallel / I2C Backpack)",
|
||||
instanceNamePrefix = "LCD", zOrder = IDIYComponent.COMPONENT,
|
||||
bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME,
|
||||
@@ -61,22 +61,33 @@ public class CharacterLCD extends AbstractMakerBoard {
|
||||
|
||||
public enum LCDSize {
|
||||
// Labels stay short because they reach the BOM's value column; the dimensions are carried by
|
||||
// the fields beside them, not by the text.
|
||||
_16x2("16x2", 16, 2, 80.0, 36.0),
|
||||
_20x4("20x4", 20, 4, 98.0, 60.0);
|
||||
// the fields beside them, not by the text. The bezel and the lit area are measured off the
|
||||
// module and are sizes in their own right -- deriving them as margins off the board made the
|
||||
// window grow with the board instead of staying the size of the part.
|
||||
_16x2("16x2", 16, 2, 80.0, 35.0, 72.2, 24.1, 64.5, 14.5),
|
||||
_20x4("20x4", 20, 4, 98.0, 60.0, 96.8, 39.3, 77.0, 25.2);
|
||||
|
||||
private final String label;
|
||||
private final int cols;
|
||||
private final int rows;
|
||||
private final double widthMm;
|
||||
private final double heightMm;
|
||||
private final double bezelWidthMm;
|
||||
private final double bezelHeightMm;
|
||||
private final double displayWidthMm;
|
||||
private final double displayHeightMm;
|
||||
|
||||
LCDSize(String label, int cols, int rows, double widthMm, double heightMm) {
|
||||
LCDSize(String label, int cols, int rows, double widthMm, double heightMm, double bezelWidthMm,
|
||||
double bezelHeightMm, double displayWidthMm, double displayHeightMm) {
|
||||
this.label = label;
|
||||
this.cols = cols;
|
||||
this.rows = rows;
|
||||
this.widthMm = widthMm;
|
||||
this.heightMm = heightMm;
|
||||
this.bezelWidthMm = bezelWidthMm;
|
||||
this.bezelHeightMm = bezelHeightMm;
|
||||
this.displayWidthMm = displayWidthMm;
|
||||
this.displayHeightMm = displayHeightMm;
|
||||
}
|
||||
|
||||
@Override public String toString() { return label; }
|
||||
@@ -84,6 +95,10 @@ public class CharacterLCD extends AbstractMakerBoard {
|
||||
public int getRows() { return rows; }
|
||||
public double getWidthMm() { return widthMm; }
|
||||
public double getHeightMm() { return heightMm; }
|
||||
public double getBezelWidthMm() { return bezelWidthMm; }
|
||||
public double getBezelHeightMm() { return bezelHeightMm; }
|
||||
public double getDisplayWidthMm() { return displayWidthMm; }
|
||||
public double getDisplayHeightMm() { return displayHeightMm; }
|
||||
}
|
||||
|
||||
public enum LCDInterface {
|
||||
@@ -95,8 +110,19 @@ public class CharacterLCD extends AbstractMakerBoard {
|
||||
@Override public String toString() { return label; }
|
||||
}
|
||||
|
||||
// clearance from the top edge to the pin row
|
||||
// clearance from the top edge to the parallel pin row
|
||||
public static Size HEADER_OFFSET = new Size(2.54d, SizeUnit.mm);
|
||||
// The parallel row is not centred on the board: its leftmost pin starts this far in from the
|
||||
// left edge.
|
||||
public static Size PARALLEL_HEADER_INSET = new Size(10.0d, SizeUnit.mm);
|
||||
// The I2C backpack brings its four pins out as a vertical column standing against the left edge,
|
||||
// this far in from it and centred on the board's height.
|
||||
public static Size I2C_HEADER_INSET = new Size(2.5d, SizeUnit.mm);
|
||||
// Hole centre inset from each edge, measured. The diameter beside it is not: it is still the raw
|
||||
// 20 px it replaced, which open decision 11.8 in docs/plans/maker-peripherals.md records as the
|
||||
// last unsourced figure in this class.
|
||||
public static Size MOUNTING_HOLE_INSET = new Size(2.5d, SizeUnit.mm);
|
||||
public static Size MOUNTING_HOLE_SIZE = new Size(2.54d, SizeUnit.mm);
|
||||
|
||||
public static Color PCB_GREEN = Color.decode("#1B5E20");
|
||||
public static Color SCREEN_BG = Color.decode("#1E88E5");
|
||||
@@ -185,13 +211,26 @@ public class CharacterLCD extends AbstractMakerBoard {
|
||||
return new Size(lcdSize.getHeightMm(), SizeUnit.mm).convertToPixels();
|
||||
}
|
||||
|
||||
/** Left edge of the board, derived so that the pin row sits centred on the top edge. */
|
||||
/**
|
||||
* Left edge of the board. Neither header is centred on it: the parallel row starts a fixed
|
||||
* distance in from the left, and the I2C column stands against that same edge.
|
||||
*/
|
||||
private double getBoardX(double x) {
|
||||
double spacing = PIN_SPACING.convertToPixels();
|
||||
return x - (getBoardWidth() - (getPinCount() - 1) * spacing) / 2.0;
|
||||
Size inset =
|
||||
lcdInterface == LCDInterface.I2C_Backpack ? I2C_HEADER_INSET : PARALLEL_HEADER_INSET;
|
||||
return x - inset.convertToPixels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Top edge of the board. The parallel row hangs below it by a fixed clearance; the I2C column is
|
||||
* centred on the board's height instead, so the board starts back from the first pin by half of
|
||||
* the height the column does not occupy.
|
||||
*/
|
||||
private double getBoardY(double y) {
|
||||
if (lcdInterface == LCDInterface.I2C_Backpack) {
|
||||
double columnSpan = (getPinCount() - 1) * PIN_SPACING.convertToPixels();
|
||||
return y - (getBoardLength() - columnSpan) / 2.0;
|
||||
}
|
||||
return y - HEADER_OFFSET.convertToPixels();
|
||||
}
|
||||
|
||||
@@ -199,11 +238,13 @@ public class CharacterLCD extends AbstractMakerBoard {
|
||||
protected void updateControlPoints() {
|
||||
Point2D firstPoint = controlPoints[0];
|
||||
double spacing = PIN_SPACING.convertToPixels();
|
||||
// the backpack's header stands on end against the left edge; the parallel row lies along the top
|
||||
boolean vertical = lcdInterface == LCDInterface.I2C_Backpack;
|
||||
|
||||
double[][] relativeOffsets = new double[getPinCount()][2];
|
||||
for (int i = 0; i < relativeOffsets.length; i++) {
|
||||
relativeOffsets[i][0] = i * spacing;
|
||||
relativeOffsets[i][1] = 0;
|
||||
relativeOffsets[i][0] = vertical ? 0 : i * spacing;
|
||||
relativeOffsets[i][1] = vertical ? i * spacing : 0;
|
||||
}
|
||||
|
||||
rotatePoints(firstPoint, relativeOffsets);
|
||||
@@ -251,28 +292,32 @@ public class CharacterLCD extends AbstractMakerBoard {
|
||||
g2d.draw(boardShape);
|
||||
|
||||
if (!outlineMode) {
|
||||
// 4 Mounting holes in corners
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + 20, boardY + 20, 20);
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + 20, boardY + boardH - 20, 20);
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + boardW - 20, boardY + 20, 20);
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + boardW - 20, boardY + boardH - 20, 20);
|
||||
// One mounting hole per corner.
|
||||
double holeInset = MOUNTING_HOLE_INSET.convertToPixels();
|
||||
double holeSize = MOUNTING_HOLE_SIZE.convertToPixels();
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + holeInset, boardY + holeInset, holeSize);
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + holeInset, boardY + boardH - holeInset,
|
||||
holeSize);
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + boardW - holeInset, boardY + holeInset,
|
||||
holeSize);
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + boardW - holeInset,
|
||||
boardY + boardH - holeInset, holeSize);
|
||||
|
||||
// Metal Bezel around screen
|
||||
double bezelMarginX = (lcdSize == LCDSize._16x2) ? 45 : 40;
|
||||
double bezelW = boardW - 2 * bezelMarginX;
|
||||
double bezelX = boardX + bezelMarginX;
|
||||
double bezelY = boardY + 45;
|
||||
double bezelH = boardH - 65;
|
||||
// The metal bezel, centred on the board. Its size is the module's own, not a margin taken
|
||||
// off the board, so it stays put when the board changes.
|
||||
double bezelW = new Size(lcdSize.getBezelWidthMm(), SizeUnit.mm).convertToPixels();
|
||||
double bezelH = new Size(lcdSize.getBezelHeightMm(), SizeUnit.mm).convertToPixels();
|
||||
double bezelX = boardX + (boardW - bezelW) / 2.0;
|
||||
double bezelY = boardY + (boardH - bezelH) / 2.0;
|
||||
|
||||
g2d.setColor(BEZEL_COLOR);
|
||||
g2d.fill(new RoundRectangle2D.Double(bezelX, bezelY, bezelW, bezelH, 6, 6));
|
||||
|
||||
// LCD Screen area
|
||||
double screenMargin = 12;
|
||||
double screenW = bezelW - 2 * screenMargin;
|
||||
double screenH = bezelH - 2 * screenMargin;
|
||||
double screenX = bezelX + screenMargin;
|
||||
double screenY = bezelY + screenMargin;
|
||||
// The lit area, centred within the bezel and likewise measured rather than derived.
|
||||
double screenW = new Size(lcdSize.getDisplayWidthMm(), SizeUnit.mm).convertToPixels();
|
||||
double screenH = new Size(lcdSize.getDisplayHeightMm(), SizeUnit.mm).convertToPixels();
|
||||
double screenX = bezelX + (bezelW - screenW) / 2.0;
|
||||
double screenY = bezelY + (bezelH - screenH) / 2.0;
|
||||
|
||||
g2d.setColor(screenColor);
|
||||
g2d.fill(new Rectangle2D.Double(screenX, screenY, screenW, screenH));
|
||||
|
||||
+126
-24
@@ -71,7 +71,10 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
* until someone reads a datasheet or measures a part.
|
||||
*/
|
||||
public enum DisplayType {
|
||||
SingleDigit_10Pin("1-Digit 0.56\"", 12.6d, 19.0d, 8.1d, 14.2d, 0d, 15.24d, true),
|
||||
// The parts these model: 5161AS for the single digit, 3641AS for the 0.36 inch four-digit
|
||||
// package and 5641AS for the 0.56 inch one. The two four-digit parts differ in size but share
|
||||
// a pinout, which is why one array serves both.
|
||||
SingleDigit_10Pin("1-Digit 0.56\"", 12.7d, 19.0d, 8.1d, 14.2d, 0d, 15.24d, true),
|
||||
FourDigit_0_36_12Pin("4-Digit 0.36\"", 30.0d, 14.0d, 5.2d, 9.14d, 7.5d, 10.16d, true),
|
||||
FourDigit_0_56_12Pin("4-Digit 0.56\"", 50.3d, 19.0d, 8.1d, 14.2d, 12.7d, 15.24d, true),
|
||||
TM1637_Module_4Pin("4-Digit TM1637 Module", 42.0d, 24.0d, 5.5d, 9.2d, 7.62d, 0d, false);
|
||||
@@ -115,6 +118,40 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
public boolean isDualRow() { return dualRow; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Which electrode the digits share. Both kinds are sold side by side and are identical in pinout,
|
||||
* package and dimensions -- they differ only in internal polarity, so this changes nothing that
|
||||
* is drawn and reaches only the BOM.
|
||||
*/
|
||||
public enum Common {
|
||||
Cathode("Common Cathode"),
|
||||
Anode("Common Anode");
|
||||
|
||||
private final String label;
|
||||
Common(String label) { this.label = label; }
|
||||
@Override public String toString() { return label; }
|
||||
}
|
||||
|
||||
/**
|
||||
* What the package carries besides the digits themselves. These are sold in every combination,
|
||||
* and on a twelve-pin part they are not independent of each other: A-G plus DP and four digit
|
||||
* commons already account for all twelve pins, so a colon has to share the decimal point's line
|
||||
* or replace it. The property therefore describes the face of the part, not a fifth pin.
|
||||
*/
|
||||
public enum Punctuation {
|
||||
None("No Punctuation"),
|
||||
DecimalPoints("Decimal Points"),
|
||||
Colon("Colon"),
|
||||
Both("Colon + Decimal Points");
|
||||
|
||||
private final String label;
|
||||
Punctuation(String label) { this.label = label; }
|
||||
@Override public String toString() { return label; }
|
||||
|
||||
public boolean hasDecimalPoints() { return this == DecimalPoints || this == Both; }
|
||||
public boolean hasColon() { return this == Colon || this == Both; }
|
||||
}
|
||||
|
||||
public static Color BODY_BLACK = Color.decode("#1C1C1C");
|
||||
public static Color FACE_BLACK = Color.decode("#111111");
|
||||
public static Color FACE_BORDER = Color.decode("#333333");
|
||||
@@ -133,6 +170,11 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
* millimetre -- so a faithful drawing has the pins sitting on the digit. This is a deliberate
|
||||
* departure from the measurements for legibility, which is why it is a separate factor rather
|
||||
* than smaller digit sizes on {@link DisplayType}: those stay as the package measures.
|
||||
*
|
||||
* <p>Concretely it draws the 0.56 inch packages' 14.2 mm digit at 12.5 mm, so what reaches the
|
||||
* canvas is about half an inch. That is intended, and it is not a disagreement with the part:
|
||||
* the package is still a 0.56 inch one and the BOM still says so. Worth knowing before changing
|
||||
* this number to chase an exact drawn size, because it is shared and would move every package.
|
||||
*/
|
||||
public static double DIGIT_DRAW_SCALE = 0.88d;
|
||||
|
||||
@@ -147,7 +189,8 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
};
|
||||
|
||||
/**
|
||||
* Shared by both bare four-digit packages, which differ in size but not in pin function.
|
||||
* Shared by both bare four-digit packages: the 3641AS and the 5641AS differ in size but not in
|
||||
* pin function, confirmed by the maintainer.
|
||||
*
|
||||
* <p>This was previously transcribed in reading order -- top row left to right, then bottom row
|
||||
* left to right -- rather than in DIP order, which put every segment and digit common on the
|
||||
@@ -164,6 +207,8 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
public static Color PCB_BLUE = Color.decode("#004488");
|
||||
|
||||
private DisplayType displayType = DisplayType.SingleDigit_10Pin;
|
||||
private Common common = Common.Cathode;
|
||||
private Punctuation punctuation = Punctuation.DecimalPoints;
|
||||
private Color ledColor = LED_RED;
|
||||
private Color boardColor = PCB_BLUE;
|
||||
|
||||
@@ -184,10 +229,54 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
invalidateCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Common cathode and common anode parts share a pinout, a package and a set of dimensions, so no
|
||||
* drawing path reads this -- it exists to split the two in the BOM, which is the only place the
|
||||
* difference costs anyone anything. Defaulted in the getter rather than the field so that a
|
||||
* project saved before this property existed still loads.
|
||||
*/
|
||||
@EditableProperty(name = "Common")
|
||||
public Common getCommon() {
|
||||
if (common == null) {
|
||||
common = Common.Cathode;
|
||||
}
|
||||
return common;
|
||||
}
|
||||
|
||||
public void setCommon(Common common) {
|
||||
this.common = common;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlike {@link #getCommon()} this one is visible: it decides whether the decimal points and the
|
||||
* colon are drawn at all. The colon is meaningless on the single-digit package and is ignored
|
||||
* there, in the same way the board colour is ignored on the bare packages.
|
||||
*/
|
||||
@EditableProperty(name = "Punctuation")
|
||||
public Punctuation getPunctuation() {
|
||||
if (punctuation == null) {
|
||||
punctuation = Punctuation.DecimalPoints;
|
||||
}
|
||||
return punctuation;
|
||||
}
|
||||
|
||||
public void setPunctuation(Punctuation punctuation) {
|
||||
this.punctuation = punctuation;
|
||||
invalidateCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getVariantLabel() {
|
||||
DisplayType displayType = getDisplayType();
|
||||
return displayType == null ? null : displayType.toString();
|
||||
if (displayType == null) {
|
||||
return null;
|
||||
}
|
||||
// The module drives the digits itself and brings out no common pins, so polarity is not part
|
||||
// of what you order -- but which punctuation it carries still is.
|
||||
if (displayType == DisplayType.TM1637_Module_4Pin) {
|
||||
return displayType + ", " + getPunctuation();
|
||||
}
|
||||
return displayType + ", " + getCommon() + ", " + getPunctuation();
|
||||
}
|
||||
|
||||
@EditableProperty(name = "LED Color")
|
||||
@@ -357,7 +446,9 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
* DIGIT_DRAW_SCALE;
|
||||
double dx = boardX + (boardW - dw) / 2.0 - 0.5 * SEGMENT_THICKNESS.convertToPixels();
|
||||
double dy = boardY + (boardH - dh) / 2.0;
|
||||
drawSevenSegmentDigit(g2d, dx, dy, dw, dh, "8.", ledColor);
|
||||
// no colon on a single digit, so only the decimal point is in question here
|
||||
drawSevenSegmentDigit(g2d, dx, dy, dw, dh, "8.", ledColor,
|
||||
getPunctuation().hasDecimalPoints());
|
||||
|
||||
} else if (isFourDigitBare()) {
|
||||
// the recessed window is a shade of the moulding, so it follows the body colour
|
||||
@@ -379,19 +470,23 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
double firstCenterX = boardX + boardW / 2.0 - 1.5 * pitch;
|
||||
double dy = boardY + (boardH - dh) / 2.0;
|
||||
|
||||
Punctuation punctuation = getPunctuation();
|
||||
for (int d = 0; d < 4; d++) {
|
||||
double centerX = firstCenterX + d * pitch;
|
||||
double dx = centerX - dw / 2.0 - 0.5 * SEGMENT_THICKNESS.convertToPixels();
|
||||
drawSevenSegmentDigit(g2d, dx, dy, dw, dh, "8.", ledColor);
|
||||
drawSevenSegmentDigit(g2d, dx, dy, dw, dh, "8.", ledColor,
|
||||
punctuation.hasDecimalPoints());
|
||||
}
|
||||
|
||||
// Colon between the middle pair, sized off the glyph grid like the decimal point is, so it
|
||||
// tracks the digit instead of staying a fixed few pixels across.
|
||||
double colonX = boardX + boardW / 2.0;
|
||||
double dotD = dw / GLYPH_WIDTH * 2.0;
|
||||
g2d.setColor(ledColor);
|
||||
g2d.fill(new Ellipse2D.Double(colonX - dotD / 2.0, dy + dh * 0.35 - dotD / 2.0, dotD, dotD));
|
||||
g2d.fill(new Ellipse2D.Double(colonX - dotD / 2.0, dy + dh * 0.65 - dotD / 2.0, dotD, dotD));
|
||||
if (punctuation.hasColon()) {
|
||||
// Colon between the middle pair, sized off the glyph grid like the decimal point is, so
|
||||
// it tracks the digit instead of staying a fixed few pixels across.
|
||||
double dotD = dw / GLYPH_WIDTH * 2.0;
|
||||
double colonX = boardX + boardW / 2.0 - dotD / 2.0;
|
||||
g2d.setColor(ledColor);
|
||||
g2d.fill(new Ellipse2D.Double(colonX, dy + dh * 0.35 - dotD / 2.0, dotD, dotD));
|
||||
g2d.fill(new Ellipse2D.Double(colonX, dy + dh * 0.65 - dotD / 2.0, dotD, dotD));
|
||||
}
|
||||
|
||||
} else if (displayType == DisplayType.TM1637_Module_4Pin) {
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + 14, boardY + 14, 12);
|
||||
@@ -419,18 +514,22 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
double firstCenterX = bezelX + (bezelW - 3 * pitch) / 2.0;
|
||||
double dy = bezelY + (bezelH - dh) / 2.0;
|
||||
|
||||
Punctuation punctuation = getPunctuation();
|
||||
for (int d = 0; d < 4; d++) {
|
||||
double centerX = firstCenterX + d * pitch;
|
||||
double dx = centerX - dw / 2.0 - 0.5 * SEGMENT_THICKNESS.convertToPixels() * 0.65;
|
||||
drawSevenSegmentDigit(g2d, dx, dy, dw, dh, "8.", ledColor);
|
||||
drawSevenSegmentDigit(g2d, dx, dy, dw, dh, "8.", ledColor,
|
||||
punctuation.hasDecimalPoints());
|
||||
}
|
||||
|
||||
// same colon treatment as the bare packages: sized and placed off the digit, not in pixels
|
||||
double colonX = bezelX + bezelW / 2.0;
|
||||
double dotD = dw / GLYPH_WIDTH * 2.0;
|
||||
g2d.setColor(ledColor);
|
||||
g2d.fill(new Ellipse2D.Double(colonX - dotD / 2.0, dy + dh * 0.35 - dotD / 2.0, dotD, dotD));
|
||||
g2d.fill(new Ellipse2D.Double(colonX - dotD / 2.0, dy + dh * 0.65 - dotD / 2.0, dotD, dotD));
|
||||
if (punctuation.hasColon()) {
|
||||
// same colon treatment as the bare packages: sized off the digit, not in pixels
|
||||
double dotD = dw / GLYPH_WIDTH * 2.0;
|
||||
double colonX = bezelX + bezelW / 2.0 - dotD / 2.0;
|
||||
g2d.setColor(ledColor);
|
||||
g2d.fill(new Ellipse2D.Double(colonX, dy + dh * 0.35 - dotD / 2.0, dotD, dotD));
|
||||
g2d.fill(new Ellipse2D.Double(colonX, dy + dh * 0.65 - dotD / 2.0, dotD, dotD));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,7 +601,8 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
* silhouette, then the lit ones, and finally every segment is outlined in the face colour so
|
||||
* that neighbours which share a vertex still read as separate segments.
|
||||
*/
|
||||
private void drawSevenSegmentDigit(Graphics2D g2d, double x, double y, double w, double h, String charToDisplay, Color onColor) {
|
||||
private void drawSevenSegmentDigit(Graphics2D g2d, double x, double y, double w, double h,
|
||||
String charToDisplay, Color onColor, boolean showDecimalPoint) {
|
||||
AffineTransform orig = g2d.getTransform();
|
||||
|
||||
g2d.translate(x, y);
|
||||
@@ -536,7 +636,8 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
g2d.fill(segments[i]);
|
||||
}
|
||||
}
|
||||
if ((mask & SEG_DP) == 0 && !charToDisplay.contains(".")) {
|
||||
// a package without a decimal point has no dot at all, lit or unlit, so this is gated too
|
||||
if (showDecimalPoint && (mask & SEG_DP) == 0 && !charToDisplay.contains(".")) {
|
||||
g2d.fill(dpShape);
|
||||
}
|
||||
|
||||
@@ -547,7 +648,7 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
g2d.fill(segments[i]);
|
||||
}
|
||||
}
|
||||
if ((mask & SEG_DP) != 0 || charToDisplay.contains(".")) {
|
||||
if (showDecimalPoint && ((mask & SEG_DP) != 0 || charToDisplay.contains("."))) {
|
||||
g2d.fill(dpShape);
|
||||
}
|
||||
|
||||
@@ -570,7 +671,8 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
g2d.setColor(Color.DARK_GRAY);
|
||||
g2d.draw(new RoundRectangle2D.Double(6, 3, width - 12, height - 6, 3, 3));
|
||||
|
||||
// Draw single stylized '8'
|
||||
drawSevenSegmentDigit(g2d, 9, 5, width - 18, height - 10, "8.", LED_RED);
|
||||
// Draw single stylized '8'. The toolbox icon stands for the component type rather than for any
|
||||
// one configured instance, so it keeps its decimal point whatever Punctuation is set to.
|
||||
drawSevenSegmentDigit(g2d, 9, 5, width - 18, height - 10, "8.", LED_RED, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
import org.diylc.utils.Constants;
|
||||
|
||||
@ComponentDescriptor(name = "NeoPixel Ring (WS2812B)", category = "Displays & Outputs",
|
||||
@ComponentDescriptor(name = "NeoPixel Ring", category = "Displays & Outputs",
|
||||
author = "Branislav Stojkovic", description = "Addressable RGB WS2812B NeoPixel Ring (12/16/24 LEDs)",
|
||||
instanceNamePrefix = "LED", zOrder = IDIYComponent.COMPONENT,
|
||||
bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME,
|
||||
|
||||
@@ -46,7 +46,7 @@ import org.diylc.core.measures.Size;
|
||||
import org.diylc.core.measures.SizeUnit;
|
||||
import org.diylc.utils.Constants;
|
||||
|
||||
@ComponentDescriptor(name = "NeoPixel Stick (8x WS2812B)", category = "Displays & Outputs",
|
||||
@ComponentDescriptor(name = "NeoPixel Stick", category = "Displays & Outputs",
|
||||
author = "Branislav Stojkovic", description = "8-LED Addressable RGB WS2812B NeoPixel Stick",
|
||||
instanceNamePrefix = "LED", zOrder = IDIYComponent.COMPONENT,
|
||||
bomPolicy = BomPolicy.SHOW_ONLY_TYPE_NAME, keywordPolicy = KeywordPolicy.SHOW_TYPE_NAME,
|
||||
|
||||
@@ -47,7 +47,7 @@ Seven classes, all `category = "Displays & Outputs"`, all `bomPolicy = SHOW_ONLY
|
||||
|---|---|---|
|
||||
| `SevenSegmentDisplay` | 1-digit 10-pin, 4-digit 12-pin, TM1637 module | **Best-*written* file in the set**, which is not the same as the best-sourced one. The segment-mask table is genuinely good, the 10-pin structure is corroborated, and the glyph itself is now the standard unit-grid construction: an upright 10 × 18 box with segments two units thick, mitred at 45 degrees so neighbours meet at a shared vertex, each outlined in the face colour so that they still read as separate segments. That replaced a set of hand-tuned polygons and retired both `SEGMENT_GAP` (the construction separates by outline rather than by gap) and `SLANT_DEGREES` (it is drawn upright, as the source is). What remains unchecked is everything *around* the glyph. The per-package dimensions now live on the `DisplayType` constants rather than in scattered branches, and the enum has been split so that the two bare four-digit packages — 0.36" and 0.56" — are separate variants sharing one pin array. The 0.56" set is what this class has always carried and remains unverified; the 0.36" set is now largely maintainer-supplied — body 30 × 14 mm, 7.5 mm digit pitch, 0.4" row spacing — leaving only its digit width inferred. See §11.10 and §11.11. |
|
||||
| `WS2812BRing` | 12 / 16 / 24 LED | **Good.** Genuine polar maths, mm-based OD/ID per size, LED count driving the rendering, `drawSolderPads` rather than a header — correct for a ring. Its diameters, pad count and pad placement have all since been corrected from Adafruit's pages and the maintainer's measurements; the pads now sit on their own radius near the rim, each in one of the real uneven gaps between LEDs (§11.9). The LED packages are the real 5 mm 5050 part, shared with the Stick as `AbstractMakerBoard.RGB_LED_SIZE` — they had been drawn at a clamped 8-15 px, barely 1-2 mm — and the ring renders lit, in a continuous yellow-orange-red-purple-blue-green gradient with a palette per variant. |
|
||||
| `CharacterLCD` | 16x2 / 20x4, I2C backpack / 16-pin parallel | Correct HD44780 and PCF8574 pin data, correct 80 × 36 and 98 × 60 mm bodies. All screen and bezel geometry in raw pixels, including an eyeballed `bezelMarginX = (16x2) ? 45 : 40`. Allocates a `Font` inside `draw()`. |
|
||||
| `CharacterLCD` | 16x2 / 20x4, I2C backpack / 16-pin parallel | Correct HD44780 and PCF8574 pin data. The bodies are now maintainer-given at 80 × 35 and 98 × 60 mm — the 16x2 height had been 36, so "correct bodies" was never true of it. The screen geometry was raw pixels — an eyeballed `bezelMarginX = (16x2) ? 45 : 40` and a window derived as a margin off the board — and is now measured: a 72.2 × 24.1 mm bezel around a 64.5 × 14.5 mm lit area on the 16x2, 77 × 25.5 around 70.4 × 20.4 on the 20x4, carried on `LCDSize` and centred rather than subtracted. Headers are placed from measurements too (§3.2 item 7). No pixel literal survives in `draw()`; only the mounting holes remain unsourced (§11.8). The `Font` it once allocated inside `draw()` went with the demo text in item 7; the one that remains is in `drawIcon`, which runs per toolbox icon rather than per repaint. |
|
||||
| `OLEDDisplay` | I2C 4-pin / SPI 7-pin | Correct pin names and a correct 27 mm square body, but **the glass is drawn near-square** when the 0.96" SSD1306 active area is a roughly 2:1 letterbox. No size variants. |
|
||||
| `LEDMatrix8x8` | none | Plausible single MAX7219 module with correct cascade headers, but a hardcoded `-44 mm` output-header offset and pixel-placed matrix and chip. **Missing the 4-in-1 32x8 module.** |
|
||||
| `TFTDisplay` | none | **Weakest file.** No variant enum. Name and descriptor say 240x320 while the on-screen silk says `320x240`. See the footprint bug below. |
|
||||
@@ -103,6 +103,15 @@ ground is almost certainly wrong.
|
||||
and only its vertical offset was a raw pixel value. This is the visible face of D7, and it
|
||||
resolves when the geometry is re-derived from `Size` constants in item 6.
|
||||
|
||||
**`CharacterLCD` has since been given its real header placement, and it is not centred at all.**
|
||||
The 16-pin parallel row starts 10 mm in from the left edge, and the I2C backpack brings its four
|
||||
pins out as a *vertical* column standing against the left edge, 2.5 mm in and centred on the
|
||||
board's height. For this class the item was therefore wrong twice over: the geometry was not
|
||||
merely off-centre by accident, and centring was never the right answer. `PARALLEL_HEADER_INSET`
|
||||
and `I2C_HEADER_INSET` are measurements of where the connectors actually are, not a correction
|
||||
applied to a drawing that had drifted. `TFTDisplay`'s centred header still stands as described
|
||||
above, so the item holds for it.
|
||||
|
||||
8. **The Ring's pad arc and LED arc coincide** — **resolved, with §11.9.** Both the solder pads and
|
||||
the LEDs were placed on the mid-radius circle, so the four pads sat on top of LEDs at the bottom
|
||||
of the ring. Nothing was hidden — `drawSolderPads` runs last, after the transform is restored, so
|
||||
@@ -174,11 +183,11 @@ Ordered by risk, not by file size. None of these is a compatibility concern (D6)
|
||||
| 3 | Re-derive the `TFTDisplay` footprint from the module drawing: outline, header edge, screen aspect, SD-slot position (§3.1) — **done**: portrait 50 × 86 mm, header centred on the short edge, screen derived from the glass, four holes placed from the vendor drawing and the glass centred between them. The front-face SD slot was removed rather than moved, because the reader is on the back | 1 | 3-4 h |
|
||||
| 4 | Fix `WS2812BStick` pad names and count from the product drawing; rebuild its geometry from `Size` constants (§3.1) — **done**, with one correction to the premise: the **count was already right**. Four pads per end is what the board has, and the doubled ground is real hardware on one net. Only the *order* was wrong, so the pads were reordered to GND, data, power, GND and renamed `GND_1`…`GND_4` for uniqueness. Board corrected to 51.1 × 10.22 mm with real 5 mm packages | 1 | 2-3 h |
|
||||
| 5 | Fix the `OLEDDisplay` glass aspect to the real active area — **done**: panel 26.7 × 19.3 mm centred between the hole rows, with the 21.744 × 10.864 mm lit area drawn inside it | 1 | 1 h |
|
||||
| 6 | Replace raw pixel geometry with `Size` constants (D7) — **done for `OLEDDisplay`, `TFTDisplay`, `LEDMatrix8x8` and `WS2812BStick`; blocked for `CharacterLCD`**, see §11.8 | `CharacterLCD`, `OLEDDisplay`, `TFTDisplay`, `LEDMatrix8x8`, `WS2812BStick` | 4-6 h |
|
||||
| 6 | Replace raw pixel geometry with `Size` constants (D7) — **done for all five.** `CharacterLCD` was the last holdout and was unblocked by maintainer figures for its bezel, lit area and header placement; its window is now the part's own size rather than a margin off the board, and no pixel literal is left in `draw()`. One caveat worth keeping separate: its mounting-hole inset and diameter are *named* constants but still the draft's guessed 2.54 mm, so D7 is satisfied while §11.8's sourcing question is not | `CharacterLCD`, `OLEDDisplay`, `TFTDisplay`, `LEDMatrix8x8`, `WS2812BStick` | 4-6 h |
|
||||
| 7 | Replace demo screen text with a neutral panel (D4) — **done**: all three now draw an unpowered panel, and `CharacterLCD`'s `SCREEN_TEXT` colour went with its lettering | `CharacterLCD`, `OLEDDisplay`, `TFTDisplay` | 1-2 h |
|
||||
| 8 | Route silk labels through `getSilkPinLabel` / `drawPinLabels` — **done**: the Stick's now come from `getSilkPinLabel` and the Ring's are dropped; removing the Ring's inline `new Font(...)` also settles half of item 9 | `WS2812BStick`, `WS2812BRing` | 1-2 h |
|
||||
| 9 | `zOrder` to `COMPONENT` on `CharacterLCD` and `TFTDisplay`; cache the two `draw()` fonts; strip non-ASCII; drop the unused import — **done**: all seven are `COMPONENT`, both `draw()` fonts left with items 7 and 8, `SevenSegmentDisplay`'s degree signs were the last non-ASCII, and the orphaned imports plus `CharacterLCD.SCREEN_TEXT` are gone. The three surviving `new Font(...)` calls are all in `drawIcon`, which runs per toolbox icon rather than per repaint, so they are deliberately left | 5 | 1 h |
|
||||
| 10 | Cross-check every surviving dimension and pin array against vendor documentation — **partly done.** Closed: `TFTDisplay` (outline, active area, header edge, hole positions, glass placement), `WS2812BStick` (board, 5050 package, pad count and order), `OLEDDisplay` (panel, lit area, and a 24 mm centre-to-centre hole pattern in both directions, modelled as spacing rather than an edge inset since that is how it is specified and what a builder drills), `WS2812BRing`'s diameters — **all six of which were wrong**, see §3.2 item 10 — and that same class's pad count, naming and arrangement (§11.9, maintainer-supplied, which also closed §3.2 item 8). Open: `SevenSegmentDisplay`'s pin arrays (§11.10), `CharacterLCD`'s part identity (§11.8), and `LEDMatrix8x8`'s silk placement (§3.2 item 9) | all 7 | the bulk of the slice |
|
||||
| 10 | Cross-check every surviving dimension and pin array against vendor documentation — **partly done.** Closed: `TFTDisplay` (outline, active area, header edge, hole positions, glass placement), `WS2812BStick` (board, 5050 package, pad count and order), `OLEDDisplay` (panel, lit area, and a 24 mm centre-to-centre hole pattern in both directions, modelled as spacing rather than an edge inset since that is how it is specified and what a builder drills), `WS2812BRing`'s diameters — **all six of which were wrong**, see §3.2 item 10 — and that same class's pad count, naming and arrangement (§11.9, maintainer-supplied, which also closed §3.2 item 8), `SevenSegmentDisplay`'s pin arrays and part identities (§11.10 — 5161AS, 3641AS and 5641AS, with the two four-digit parts confirmed to share a pinout), and `CharacterLCD`'s bodies, bezel, lit area, header placement and hole inset (§11.8). Closed by decision rather than by measurement: `SevenSegmentDisplay`'s digit widths, accepted as inferences because they size only the drawn glyph, which already departs from the package deliberately (§11.11). Open: `CharacterLCD`'s hole diameter (§11.8) and `LEDMatrix8x8`'s silk placement (§3.2 item 9) | all 7 | the bulk of the slice |
|
||||
|
||||
Items 1 and 2 have landed. The five shared 5050-package colours now live on `AbstractMakerBoard` as
|
||||
`RGB_LED_*`, and the duplicated copies are gone from both NeoPixel classes along with two dead
|
||||
@@ -504,8 +513,8 @@ gate the displays.
|
||||
7. **i18n** — component display names and enum labels are plain strings, absent from
|
||||
`diylc-swing/src/main/resources/lang/*.txt`, as they are for the shipped boards. No translation
|
||||
work is required here; noted for a future pass.
|
||||
8. **`CharacterLCD`'s geometry cannot be sourced consistently** — which is why item 6 is done for
|
||||
every other file and blocked for this one. "1602" names a character format, not a mechanical
|
||||
8. **`CharacterLCD`'s geometry could not be sourced consistently** — **now resolved except the
|
||||
mounting holes.** This is why item 6 was done for every other file and blocked for this one. "1602" names a character format, not a mechanical
|
||||
part, and vendors ship several outlines under it: the enum encodes an 80 × 36 mm module, while
|
||||
Raystar's RC1602A is 84 × 44 mm. The display window is worse, because sources quote different
|
||||
features under similar names — 64.5 × 16 mm and 66.0 × 16 mm as "viewing area" against
|
||||
@@ -516,6 +525,31 @@ gate the displays.
|
||||
specific part — as the TFT slice settled on the MSP2807 — and taking the outline, window and
|
||||
hole positions from that one drawing, rather than assembling them from whichever vendor answers
|
||||
a search first.
|
||||
|
||||
**The outlines are now maintainer-given: 80 × 35 mm for the 16x2, 98 × 60 mm for the 20x4.**
|
||||
That settles the first of the three figures this item needs, correcting the 16x2's height by a
|
||||
millimetre and confirming the 20x4 exactly as stored. It does **not** unblock prep item 6. The
|
||||
window and the mounting holes are still raw pixels with no source behind them: the bezel is
|
||||
derived as `boardH - 65` px, which on the corrected board still fills about 76% of its height
|
||||
when a 16 mm window on a 35 mm board should be under half. A one-millimetre change to the board
|
||||
cannot fix a bezel whose size does not come from the board at all. What is still wanted is the
|
||||
display window and the hole positions, ideally from one named part.
|
||||
|
||||
**The window figures have since landed.** The 16x2 carries a 72.2 × 24.1 mm bezel around a
|
||||
64.5 × 14.5 mm lit area; the 20x4 a 77 × 25.5 mm bezel around 70.4 × 20.4 mm. Both are fields on
|
||||
`LCDSize` now, drawn centred on the board and within the bezel respectively. That is the actual
|
||||
fix rather than a retuning: the window is the part's own size instead of a margin subtracted
|
||||
from the board, so it no longer grows when the board does — which is why the earlier 1 mm board
|
||||
correction could not have helped it.
|
||||
|
||||
**The hole inset has since been measured: 2.5 mm from each edge.** Note that this was a
|
||||
correction rather than a confirmation — the constant held the draft's 2.54 mm, inherited from
|
||||
the raw `20` px, and 2.54 is a suspiciously convenient number to inherit because it is exactly
|
||||
0.1", so it had the shape of a value chosen for the grid rather than for the part.
|
||||
|
||||
**What stays open is the hole diameter alone**, still 2.54 mm and still a guess. It is the only
|
||||
unsourced figure left in `CharacterLCD`, and it is a cosmetic detail rather than a placement
|
||||
error, so the class is otherwise finished.
|
||||
9. **How many pads does a NeoPixel Ring have?** — **decided, from the maintainer: four on the
|
||||
12-LED ring, six on the 16 and the 24.** The guess recorded here, that the 2014 "extra ground and
|
||||
power breakout" made six universal, was half right — the two larger rings gained the extra pair
|
||||
@@ -550,17 +584,27 @@ gate the displays.
|
||||
both were misreading the board's own anti-aliased edge, which registers at every angle rather
|
||||
than only at the pads. Magnifying the tightest pad on each variant 12× showed unbroken board
|
||||
between every pad and the rim.
|
||||
10. **`SevenSegmentDisplay`'s pin arrays are unverified, and one of them is suspect.** The 10-pin
|
||||
structure is corroborated — a 0.56" single digit such as the 5161AS has ten pins, two of them
|
||||
common — but no source consulted would give an *ordered* pin list, so `PIN_NAMES_1DIGIT` and
|
||||
`PIN_NAMES_4DIGIT` remain unchecked. The specific worry is the 12-pin array: it follows the
|
||||
3641AS, which is a **0.36-inch** part, while `DIGIT_HEIGHT` declares 14.2 mm, i.e. 0.56". The
|
||||
0.56" four-digit equivalent is the 5641AS, and if its pinout differs then the component pairs
|
||||
one part's pins with another part's dimensions. Four attempts failed to settle it: both xlitx
|
||||
HTML pages carry only electro-optical tables, and both linked datasheets are image-encoded PDFs
|
||||
of the kind that also defeated the MSP2807 manual. **With §11.9 settled this is the last unsourced
|
||||
geometry in the set, and the worse one to leave** — a wrong dimension is a wrong picture, a wrong pin array is a
|
||||
wrong netlist, and it is silent. Closing it needs a readable datasheet or a part in hand.
|
||||
10. **`SevenSegmentDisplay`'s pin arrays** — **decided: the maintainer confirms they are correct.**
|
||||
Three questions closed together. The arrays are right as they stand; the two bare four-digit
|
||||
packages **share a pinout**; and each variant is now pinned to a named part — **5161AS** for the
|
||||
single digit, **3641AS** for the 0.36" four-digit package and **5641AS** for the 0.56" one.
|
||||
|
||||
That also retires the suspicion recorded here before. The worry had been that the 12-pin array
|
||||
followed a 0.36" part while the dimensions described a 0.56" one, pairing one part's pins with
|
||||
another part's body. Since the two parts share pins, that pairing was never the error it looked
|
||||
like — though the dimensions themselves are a separate question, still open in §11.11.
|
||||
|
||||
Worth being precise about what kind of confirmation this is. The order was corrected earlier
|
||||
from the maintainer's own reading of the parts, after it was found transcribed in reading order
|
||||
rather than DIP order, which had put every segment and digit common on the wrong pin. It has now
|
||||
been confirmed as correct. No datasheet was ever obtained — both xlitx pages carry only
|
||||
electro-optical tables and both linked PDFs are image-encoded — so this rests on the
|
||||
maintainer's word rather than on a published pinout. That is good enough to close the item, and
|
||||
it is a different claim from "verified against a datasheet".
|
||||
|
||||
Naming the parts matters beyond this item. It is the move that settled the TFT on the MSP2807,
|
||||
it is what §11.8 still needs for `CharacterLCD`, and it turns the gap left in §11.11 from
|
||||
unanswerable into merely unmeasured.
|
||||
|
||||
Note that replacing the digit glyph with the standard unit-grid construction did **not** touch
|
||||
this. The glyph governs how a lit segment is shaped; the pin arrays govern which physical pin
|
||||
@@ -576,14 +620,46 @@ gate the displays.
|
||||
11. **What the enum split left unsourced.** The split itself is sound; what follows is geometry that
|
||||
should not be mistaken for measurement.
|
||||
|
||||
*A second round of maintainer figures has since landed.* The 5161AS body is 12.7 × 19.0 mm, a
|
||||
0.1 mm correction to the stored width; the 5641AS body (50.3 × 19.0 mm) and digit pitch
|
||||
(12.7 mm) are confirmed exactly as stored; and the TM1637 module's dimensions are confirmed as a
|
||||
set. That leaves a narrower gap than before but not an empty one: **every digit width is still
|
||||
unmeasured** — 5.2 mm on the 0.36" part and 8.1 mm on both 0.56" ones — and the 5.2 mm is still
|
||||
the only figure in the file invented outright rather than merely unchecked.
|
||||
|
||||
*The apparent height conflict is resolved, and was never about the part.* The 5161AS is a
|
||||
0.56" part, the enum's 14.2 mm stands and so does the label. The 12.7 mm figure is the size the
|
||||
digit is deliberately **drawn** at, held under the true one so the glyph keeps clear of the
|
||||
pins — the same trade `DIGIT_DRAW_SCALE` exists for.
|
||||
|
||||
**No value changed, because the existing mechanism already does it.** At a scale of 0.88 a
|
||||
14.2 mm digit draws at 12.50 mm, within 0.2 mm of the half inch intended. Forcing 12.7 exactly
|
||||
would mean either raising the scale, which is global and would grow the 0.36" and TM1637 digits
|
||||
too, or writing 12.7 into `digitHeight`, which would apply the shrink twice and draw at 11.2 mm.
|
||||
The separation the class already draws — `DisplayType` holds what the package measures,
|
||||
`DIGIT_DRAW_SCALE` holds the departure from it — is exactly the distinction the conflict
|
||||
collapsed, which is why reading the drawing code dissolved it rather than deciding it.
|
||||
|
||||
*The 0.36" variant is now mostly sourced.* Its body (30 × 14 mm), digit pitch (7.5 mm) and row
|
||||
spacing (0.4", 10.16 mm) all came from the maintainer, and its digit height is definitional,
|
||||
because 9.14 mm is what 0.36 inches means. **One figure remains invented: the digit width
|
||||
(5.2 mm)**, derived by applying the 0.56" part's 8.1 : 14.2 ratio to a 9.14 mm digit — and those
|
||||
0.56" figures are themselves unverified, so it rests on an unchecked foundation. It is at least
|
||||
(5.2 mm)**, derived by applying the 0.56" part's 8.1 : 14.2 ratio to a 9.14 mm digit — and the
|
||||
0.56" digit figures it borrowed from are themselves still unmeasured, so it rests on an
|
||||
unchecked foundation. It is at least
|
||||
not contradicted by the rest: four digits on 7.5 mm centres span 22.5 mm, which with one digit
|
||||
width leaves about 1.15 mm clear at each end of a 30 mm body. Worth replacing with a measurement
|
||||
rather than leaving as an inference.
|
||||
rather than leaving as an inference — and cheaper to settle now that §11.10 has pinned this
|
||||
variant to the 3641AS and the 0.56" one to the 5641AS, so there is a specific part to measure
|
||||
rather than a generic four-digit display.
|
||||
|
||||
**Decided: left as inferences, deliberately.** The digit widths are not being measured. They
|
||||
size the drawn glyph and nothing else, and the glyph is already a declared departure from the
|
||||
package at `DIGIT_DRAW_SCALE` 0.88, so an error here is cosmetic and bounded — unlike a wrong
|
||||
pin array, which is silent and wrong in the netlist, or a wrong outline, which is wrong against
|
||||
the board around it. The three figures stand as recorded: 5.2 mm inferred for the 0.36" part
|
||||
and 8.1 mm unverified for both 0.56" ones. They stay flagged here precisely so that a later
|
||||
reader does not mistake them for measurements and build something on top of them, which is how
|
||||
the 5.2 mm came to exist in the first place.
|
||||
|
||||
For the record, the values this replaced were mine and were fitted rather than measured — a
|
||||
30.2 × 14.0 body, an 8.0 mm pitch, and a 12.7 mm row spacing chosen only so the rows would sit
|
||||
@@ -595,3 +671,53 @@ gate the displays.
|
||||
edge, vertical**, which would mean laying the single-row case out vertically rather than
|
||||
horizontally — a larger change that was considered and not made. The centring predated the
|
||||
split; what made it visible was rendering each variant rather than only the default one.
|
||||
12. **Common cathode vs common anode** — **decided: a `Common` property, reaching the BOM only.**
|
||||
Both kinds are sold side by side and are identical in pinout, package and dimensions; the
|
||||
difference is internal polarity. So the property changes nothing that is drawn and nothing in
|
||||
the netlist — it exists to split two genuinely different parts into two BOM rows, which is
|
||||
exactly what §11.1's `getVariantLabel()` hook was built for. A cell now reads
|
||||
`1-Digit 0.56", Common Cathode`, following the comma pattern `CharacterLCD` already uses for its
|
||||
two-property variant.
|
||||
|
||||
Three details settled with it. The default is **cathode**, matching the AS-suffixed parts named
|
||||
in §11.10. The **TM1637 omits it**, because the module drives the digits itself and brings out
|
||||
no common pins, so polarity is not part of what you order and its cell stays
|
||||
`4-Digit TM1637 Module`. And the **pin names are untouched**: `COM1`/`COM2` and `D1`-`D4` are
|
||||
physical designations identical on both polarities, so renaming them by polarity would have
|
||||
left the single-digit and four-digit parts labelling their pins on different principles for no
|
||||
gain.
|
||||
|
||||
One thing deliberately not done: putting the part number in the value. That would be the most
|
||||
directly orderable form — `3641AS` against `3641BS` — but it rests on `AS` meaning cathode and
|
||||
`BS` meaning anode for this family, which has **not** been confirmed from a datasheet. Spelling
|
||||
the polarity out carries the same information without depending on an unverified convention.
|
||||
|
||||
Adding the field now rather than after 6.7.0 is deliberate: the class has not shipped, so a new
|
||||
serialized field costs nothing in file-format terms. It is still defaulted in the getter rather
|
||||
than only at the field, per the house rule for fields that may deserialize as null.
|
||||
13. **Decimal points and the colon** — **decided: a `Punctuation` property, drawn and in the BOM.**
|
||||
The parts are sold in every combination, and the component had been drawing one fixed
|
||||
combination — a decimal point on every digit *and* a colon — on all four variants at once.
|
||||
|
||||
That combination is not merely a default, it is one a twelve-pin package cannot have. `A`-`G`
|
||||
plus `DP` is eight segment lines and `D1`-`D4` is four commons, which accounts for all twelve
|
||||
pins confirmed in §11.10, leaving nothing to drive a colon independently: on a real part the
|
||||
colon shares the decimal point's line or replaces it. So the drawing depicted a part that its
|
||||
own pinout rules out. The property describes the face of the package rather than a fifth pin,
|
||||
which is why it does not touch `PIN_NAMES_4DIGIT`.
|
||||
|
||||
`Punctuation` has four values — none, decimal points, colon, both — defaulting to decimal
|
||||
points, which is what the committed twelve-pin array describes. It is **not** switched
|
||||
automatically when `DisplayType` changes, for the reason recorded in §11.2: per-variant
|
||||
defaults applied from a variant setter silently discard a choice the user has already made.
|
||||
The colon is ignored on the single-digit package, following `boardColor` on the bare packages
|
||||
and `Common` on the TM1637.
|
||||
|
||||
One implementation trap worth recording. Suppressing a decimal point is **not** a matter of
|
||||
passing `"8"` instead of `"8."`: the glyph routine draws an *unlit* dot whenever no lit one is
|
||||
asked for, so the obvious change leaves a grey dot behind and looks correct at a glance. Both
|
||||
the lit and the unlit path are gated on the new flag.
|
||||
|
||||
It reaches the BOM for the same reason `Common` does — it changes which part you order — so a
|
||||
cell now reads `4-Digit 0.36", Common Cathode, Colon`. That is three tokens, and the value
|
||||
column is getting long; worth revisiting if a fourth ever appears.
|
||||
|
||||
Reference in New Issue
Block a user