mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-07 12:24:58 +10:00
displays
This commit is contained in:
@@ -551,7 +551,7 @@
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
<description>OLED Display - 0.96 inch SSD1306, 0.91 inch SSD1306, 1.3 inch SH1106, in I2C and SPI</description>
|
||||
<description>OLED Display - 0.96 inch SSD1306, 0.91 inch SSD1306, 1.3 inch SH1106, in I2C, 7-pin SPI and 6-pin SPI</description>
|
||||
</org.diylc.appframework.update.Change>
|
||||
<org.diylc.appframework.update.Change>
|
||||
<changeType>NEW_FEATURE</changeType>
|
||||
|
||||
@@ -84,7 +84,7 @@ public class CharacterLCD extends AbstractMakerBoard {
|
||||
|
||||
public static final String[] PIN_NAMES_I2C = new String[] {"GND", "VCC", "SDA", "SCL"};
|
||||
public static final String[] PIN_NAMES_PARALLEL = new String[] {
|
||||
"VSS (GND)", "VDD (+5V)", "V0 (Contrast)", "RS", "RW", "E",
|
||||
"VSS (GND)", "VCC (+5V)", "VEE (Contrast)", "RS", "RW", "E",
|
||||
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7",
|
||||
"A (Backlight +)", "K (Backlight -)"
|
||||
};
|
||||
@@ -93,7 +93,7 @@ public class CharacterLCD extends AbstractMakerBoard {
|
||||
// the backlight pins carry their function in the node name instead, where a label lying along a
|
||||
// 0.1" pitch has no room for it.
|
||||
public static final String[] SILK_NAMES_PARALLEL = new String[] {
|
||||
"VSS", "VDD", "V0", "RS", "RW", "E",
|
||||
"VSS", "VCC", "VEE", "RS", "RW", "E",
|
||||
"D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "A", "K"
|
||||
};
|
||||
|
||||
|
||||
@@ -68,7 +68,26 @@ public class OLEDDisplay extends AbstractMakerBoard {
|
||||
public static Color PIXEL_BLUE = Color.decode("#00D4FF");
|
||||
|
||||
public static final String[] PIN_NAMES_I2C = new String[] {"GND", "VCC", "SCL", "SDA"};
|
||||
public static final String[] PIN_NAMES_SPI = new String[] {"GND", "VCC", "D0 (CLK)", "D1 (MOSI)", "RES", "DC", "CS"};
|
||||
|
||||
/**
|
||||
* The same two pads carry the clock and the data line in both interfaces -- the module's BS
|
||||
* jumpers decide which protocol the controller speaks on them, not which pins it uses -- so they
|
||||
* keep the names the I2C row gives them rather than the SPI aliases. Module silk disagrees with
|
||||
* itself here more than anywhere else on these boards: the SSD1306 datasheet calls the pair D0
|
||||
* and D1, SPI-labelled boards print SCK or CLK and MOSI, and I2C-labelled ones print SCL and SDA.
|
||||
* All three name the same two pins.
|
||||
*/
|
||||
public static final String[] PIN_NAMES_SPI =
|
||||
new String[] {"GND", "VCC", "SCL", "SDA", "RES", "DC", "CS"};
|
||||
|
||||
/**
|
||||
* The same row without the chip select, which some makers tie low on the board instead of
|
||||
* bringing out. It is a different board rather than a different silkscreen -- the display is then
|
||||
* permanently selected and cannot share its bus with anything else -- which is why it is a
|
||||
* variant and the clock and data naming is not.
|
||||
*/
|
||||
public static final String[] PIN_NAMES_SPI_NO_CS =
|
||||
new String[] {"GND", "VCC", "SCL", "SDA", "RES", "DC"};
|
||||
|
||||
private Version version = Version.SSD1306_0_96;
|
||||
private OLEDInterface oledInterface = OLEDInterface.I2C_4Pin;
|
||||
@@ -324,12 +343,14 @@ public class OLEDDisplay extends AbstractMakerBoard {
|
||||
}
|
||||
|
||||
public enum OLEDInterface {
|
||||
// Labels stay short because they reach the BOM's value column through getVariantLabel; the pin
|
||||
// legend they used to carry is already in the node names. The pin array belongs here rather
|
||||
// than on the board, because all three sizes bring the same lines out in the same order and
|
||||
// only the interface decides which set that is.
|
||||
// Labels stay short because they reach the BOM's value column through getVariantLabel and are
|
||||
// printed on the lit area, which the 0.91" has little of: "SPI, 7-pin" and "SPI, 6-pin" were
|
||||
// tried and the glass stopped printing anything at all. The pin array belongs here rather than
|
||||
// on the board, because all three sizes bring the same lines out in the same order and only the
|
||||
// interface decides which set that is.
|
||||
I2C_4Pin("I2C", PIN_NAMES_I2C),
|
||||
SPI_7Pin("SPI", PIN_NAMES_SPI);
|
||||
SPI_7Pin("SPI", PIN_NAMES_SPI),
|
||||
SPI_6Pin("SPI-6", PIN_NAMES_SPI_NO_CS);
|
||||
|
||||
private final String label;
|
||||
private final String[] pinNames;
|
||||
@@ -396,6 +417,12 @@ public class OLEDDisplay extends AbstractMakerBoard {
|
||||
public double getActiveLengthMm() { return activeLengthMm; }
|
||||
public double getActiveLeftInPanelMm() { return activeLeftInPanelMm; }
|
||||
|
||||
/**
|
||||
* The two SPI headers share a board. That is a derivation rather than a measurement: a 6-pin
|
||||
* module is a PCB of its own with one fewer pad, and only its outline would say whether it
|
||||
* matches the 7-pin board it is modelled on. The header is centred on the width either way, so
|
||||
* the shorter row sits correctly on the board it borrows.
|
||||
*/
|
||||
public Layout getLayout(OLEDInterface oledInterface) {
|
||||
return oledInterface == OLEDInterface.I2C_4Pin ? i2cLayout : spiLayout;
|
||||
}
|
||||
|
||||
+146
-80
@@ -179,9 +179,9 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
if (displayType == null) {
|
||||
return null;
|
||||
}
|
||||
// The module drives the digits itself and brings out no common pins, so polarity is not part
|
||||
// A 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) {
|
||||
if (displayType.isModule()) {
|
||||
return displayType + ", " + getPunctuation();
|
||||
}
|
||||
return displayType + ", " + getCommon() + ", " + getPunctuation();
|
||||
@@ -222,20 +222,8 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
return super.getBodyColor();
|
||||
}
|
||||
|
||||
/**
|
||||
* True for the two bare four-digit packages. They differ in size but not in pin function, so they
|
||||
* share a pin array and differ only in what they measure.
|
||||
*/
|
||||
private boolean isFourDigitBare() {
|
||||
return displayType == DisplayType.FourDigit_0_36_12Pin
|
||||
|| displayType == DisplayType.FourDigit_0_56_12Pin;
|
||||
}
|
||||
|
||||
private String[] getPinNames() {
|
||||
if (displayType == DisplayType.SingleDigit_10Pin) {
|
||||
return PIN_NAMES_1DIGIT;
|
||||
}
|
||||
return isFourDigitBare() ? PIN_NAMES_4DIGIT : PIN_NAMES_TM1637;
|
||||
return displayType.getPinNames();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -247,6 +235,36 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
return "Pin " + (index + 1);
|
||||
}
|
||||
|
||||
private static double px(double millimetres) {
|
||||
return new Size(millimetres, SizeUnit.mm).convertToPixels();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a colon has anywhere to go. It sits in the gap between the two middle digits, which
|
||||
* only exists on an even count; a single digit has no gap and an odd count has a digit where the
|
||||
* colon would be.
|
||||
*/
|
||||
private boolean hasMiddlePair() {
|
||||
int digitCount = displayType.getDigitCount();
|
||||
return digitCount >= 2 && digitCount % 2 == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the package's digits on their own pitch, centred on {@code rowCentreX}. Both the bare
|
||||
* packages and the modules come through here, differing only in the figures they pass: the count
|
||||
* is the variant's, which is what lets a two-, six- or eight-digit part be a constant rather than
|
||||
* a branch.
|
||||
*/
|
||||
private void drawDigitRow(Graphics2D g2d, double rowCentreX, double dy, double dw, double dh,
|
||||
double pitch, double nudge, boolean decimalPoints) {
|
||||
int digitCount = displayType.getDigitCount();
|
||||
double firstCentreX = rowCentreX - (digitCount - 1) * pitch / 2.0;
|
||||
for (int d = 0; d < digitCount; d++) {
|
||||
double dx = firstCentreX + d * pitch - dw / 2.0 - nudge;
|
||||
drawSevenSegmentDigit(g2d, dx, dy, dw, dh, "8.", ledColor, decimalPoints);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateControlPoints() {
|
||||
Point2D firstPoint = controlPoints[0];
|
||||
@@ -326,8 +344,7 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
Composite oldComposite = applyAlpha(g2d, componentState);
|
||||
|
||||
// the outline is the board on a module and the moulding on a bare package
|
||||
Color outlineFill =
|
||||
displayType == DisplayType.TM1637_Module_4Pin ? boardColor : bodyColor;
|
||||
Color outlineFill = displayType.isModule() ? boardColor : bodyColor;
|
||||
|
||||
drawingObserver.startTracking();
|
||||
g2d.setColor(outlineMode ? Constants.TRANSPARENT_COLOR : outlineFill);
|
||||
@@ -339,7 +356,7 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
g2d.draw(boardShape);
|
||||
|
||||
if (!outlineMode) {
|
||||
if (displayType == DisplayType.SingleDigit_10Pin) {
|
||||
if (!displayType.isModule()) {
|
||||
// the recessed window is a shade of the moulding, so it follows the body colour
|
||||
g2d.setColor(bodyColor.darker());
|
||||
g2d.fill(new RoundRectangle2D.Double(boardX + 3, boardY + 3, boardW - 6, boardH - 6, 3, 3));
|
||||
@@ -347,64 +364,48 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
|
||||
g2d.draw(new RoundRectangle2D.Double(boardX + 3, boardY + 3, boardW - 6, boardH - 6, 3, 3));
|
||||
|
||||
// one digit, drawn slightly under size so it keeps clear of the pins
|
||||
double dw = new Size(displayType.getDigitWidthMm(), SizeUnit.mm).convertToPixels()
|
||||
* DIGIT_DRAW_SCALE;
|
||||
double dh = new Size(displayType.getDigitHeightMm(), SizeUnit.mm).convertToPixels()
|
||||
* DIGIT_DRAW_SCALE;
|
||||
double dx = boardX + (boardW - dw) / 2.0 - 0.5 * SEGMENT_THICKNESS.convertToPixels();
|
||||
double dy = boardY + (boardH - dh) / 2.0;
|
||||
// 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
|
||||
g2d.setColor(bodyColor.darker());
|
||||
g2d.fill(new RoundRectangle2D.Double(boardX + 3, boardY + 3, boardW - 6, boardH - 6, 3, 3));
|
||||
g2d.setColor(FACE_BORDER);
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
|
||||
g2d.draw(new RoundRectangle2D.Double(boardX + 3, boardY + 3, boardW - 6, boardH - 6, 3, 3));
|
||||
|
||||
// Four digits on the package's real centre-to-centre pitch, each drawn slightly under size
|
||||
// so they keep clear of the pins. The pitch is unscaled, so the digits stay on their true
|
||||
// Digits on the package's real centre-to-centre pitch, each drawn slightly under size so
|
||||
// they keep clear of the pins. The pitch is unscaled, so the digits stay on their true
|
||||
// centres and only the gaps between them widen, and the row is centred on the body rather
|
||||
// than measured from its left edge, so it stays put across packages of different widths.
|
||||
double dw = new Size(displayType.getDigitWidthMm(), SizeUnit.mm).convertToPixels()
|
||||
* DIGIT_DRAW_SCALE;
|
||||
double dh = new Size(displayType.getDigitHeightMm(), SizeUnit.mm).convertToPixels()
|
||||
* DIGIT_DRAW_SCALE;
|
||||
double pitch = new Size(displayType.getDigitPitchMm(), SizeUnit.mm).convertToPixels();
|
||||
double firstCenterX = boardX + boardW / 2.0 - 1.5 * pitch;
|
||||
// A single-digit package is the same construction with a count of one, which leaves its
|
||||
// pitch unused -- that is why the one-digit and four-digit cases are one branch.
|
||||
double dw = px(displayType.getDigitWidthMm()) * DIGIT_DRAW_SCALE;
|
||||
double dh = px(displayType.getDigitHeightMm()) * DIGIT_DRAW_SCALE;
|
||||
double pitch = px(displayType.getDigitPitchMm());
|
||||
double dy = boardY + (boardH - dh) / 2.0;
|
||||
double rowCentreX = boardX + boardW / 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,
|
||||
punctuation.hasDecimalPoints());
|
||||
}
|
||||
drawDigitRow(g2d, rowCentreX, dy, dw, dh, pitch, 0.5 * SEGMENT_THICKNESS.convertToPixels(),
|
||||
punctuation.hasDecimalPoints());
|
||||
|
||||
if (punctuation.hasColon()) {
|
||||
if (punctuation.hasColon() && hasMiddlePair()) {
|
||||
// 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.
|
||||
// it tracks the digit instead of staying a fixed few pixels across. The row is centred,
|
||||
// so the gap between the two middle digits is the body's centre line.
|
||||
double dotD = dw / GLYPH_WIDTH * 2.0;
|
||||
double colonX = boardX + boardW / 2.0 - dotD / 2.0;
|
||||
double colonX = rowCentreX - 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);
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + 14, boardY + boardH - 14, 12);
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + boardW - 14, boardY + 14, 12);
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + boardW - 14, boardY + boardH - 14, 12);
|
||||
} else {
|
||||
Module module = displayType.getModule();
|
||||
double holeInset = px(module.getHoleInsetMm());
|
||||
double holeSize = px(module.getHoleSizeMm());
|
||||
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);
|
||||
|
||||
// Display Bezel (Center)
|
||||
double bezelW = new Size(30.0d, SizeUnit.mm).convertToPixels();
|
||||
double bezelH = new Size(14.0d, SizeUnit.mm).convertToPixels();
|
||||
// the display module itself, centred on the board it is mounted on
|
||||
double bezelW = px(module.getBezelWidthMm());
|
||||
double bezelH = px(module.getBezelLengthMm());
|
||||
double bezelX = boardX + (boardW - bezelW) / 2.0;
|
||||
double bezelY = boardY + (boardH - bezelH) / 2.0;
|
||||
|
||||
@@ -415,22 +416,17 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
|
||||
g2d.draw(new RoundRectangle2D.Double(bezelX, bezelY, bezelW, bezelH, 4, 4));
|
||||
|
||||
// digits from the package's own figures, as the other two branches already do
|
||||
double dw = new Size(displayType.getDigitWidthMm(), SizeUnit.mm).convertToPixels();
|
||||
double dh = new Size(displayType.getDigitHeightMm(), SizeUnit.mm).convertToPixels();
|
||||
double pitch = new Size(displayType.getDigitPitchMm(), SizeUnit.mm).convertToPixels();
|
||||
double firstCenterX = bezelX + (bezelW - 3 * pitch) / 2.0;
|
||||
// digits from the package's own figures, as the bare branch does, but at full size: the
|
||||
// module's digits sit on a bezel rather than between pin rows, so nothing crowds them
|
||||
double dw = px(displayType.getDigitWidthMm());
|
||||
double dh = px(displayType.getDigitHeightMm());
|
||||
double pitch = px(displayType.getDigitPitchMm());
|
||||
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,
|
||||
punctuation.hasDecimalPoints());
|
||||
}
|
||||
|
||||
if (punctuation.hasColon()) {
|
||||
drawDigitRow(g2d, bezelX + bezelW / 2.0, dy, dw, dh, pitch,
|
||||
0.5 * SEGMENT_THICKNESS.convertToPixels() * 0.65, punctuation.hasDecimalPoints());
|
||||
if (punctuation.hasColon() && hasMiddlePair()) {
|
||||
// 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;
|
||||
@@ -598,10 +594,14 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
// 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);
|
||||
SingleDigit_10Pin("1-Digit 0.56\"", 12.7d, 19.0d, 8.1d, 14.2d, 0d, 15.24d, true, 1,
|
||||
PIN_NAMES_1DIGIT, null),
|
||||
FourDigit_0_36_12Pin("4-Digit 0.36\"", 30.0d, 14.0d, 5.2d, 9.14d, 7.5d, 10.16d, true, 4,
|
||||
PIN_NAMES_4DIGIT, null),
|
||||
FourDigit_0_56_12Pin("4-Digit 0.56\"", 50.3d, 19.0d, 8.1d, 14.2d, 12.7d, 15.24d, true, 4,
|
||||
PIN_NAMES_4DIGIT, null),
|
||||
TM1637_Module_4Pin("4-Digit TM1637 Module", 42.0d, 24.0d, 5.5d, 9.2d, 7.62d, 0d, false, 4,
|
||||
PIN_NAMES_TM1637, new Module(30.0d, 14.0d, 1.778d, 1.524d));
|
||||
|
||||
private final String label;
|
||||
private final double bodyWidthMm;
|
||||
@@ -611,9 +611,13 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
private final double digitPitchMm;
|
||||
private final double rowSpacingMm;
|
||||
private final boolean dualRow;
|
||||
private final int digitCount;
|
||||
private final String[] pinNames;
|
||||
private final Module module;
|
||||
|
||||
DisplayType(String label, double bodyWidthMm, double bodyLengthMm, double digitWidthMm,
|
||||
double digitHeightMm, double digitPitchMm, double rowSpacingMm, boolean dualRow) {
|
||||
double digitHeightMm, double digitPitchMm, double rowSpacingMm, boolean dualRow,
|
||||
int digitCount, String[] pinNames, Module module) {
|
||||
this.label = label;
|
||||
this.bodyWidthMm = bodyWidthMm;
|
||||
this.bodyLengthMm = bodyLengthMm;
|
||||
@@ -622,6 +626,9 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
this.digitPitchMm = digitPitchMm;
|
||||
this.rowSpacingMm = rowSpacingMm;
|
||||
this.dualRow = dualRow;
|
||||
this.digitCount = digitCount;
|
||||
this.pinNames = pinNames;
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -640,6 +647,27 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
|
||||
/** True for the DIP packages, which carry their pins in two rows rather than one. */
|
||||
public boolean isDualRow() { return dualRow; }
|
||||
|
||||
/**
|
||||
* How many digits the part shows. Carried rather than inferred from the variant's identity,
|
||||
* which is what the drawing used to do: a two-, six- or eight-digit part is then a constant
|
||||
* beside these rather than another branch through {@code draw}.
|
||||
*/
|
||||
public int getDigitCount() { return digitCount; }
|
||||
|
||||
/**
|
||||
* The part's pins in DIP order. The two bare four-digit packages share one array because they
|
||||
* differ in size but not in pin function, which the test asserts by identity.
|
||||
*/
|
||||
public String[] getPinNames() { return pinNames; }
|
||||
|
||||
/**
|
||||
* The board a driven module is built on, or {@code null} for a bare package. A module carries
|
||||
* its own driver, so it brings out no common pins and its polarity is not something you order.
|
||||
*/
|
||||
public Module getModule() { return module; }
|
||||
|
||||
public boolean isModule() { return module != null; }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -675,4 +703,42 @@ public class SevenSegmentDisplay extends AbstractMakerBoard {
|
||||
public boolean hasDecimalPoints() { return this == DecimalPoints || this == Both; }
|
||||
public boolean hasColon() { return this == Colon || this == Both; }
|
||||
}
|
||||
|
||||
/**
|
||||
* The circuit board a driven module is built on: the display itself is a bezel mounted on it,
|
||||
* with mounting holes at the corners. A bare package has none of this -- it is a moulding with
|
||||
* pins in it -- which is why {@link DisplayType#getModule()} is null for those.
|
||||
*
|
||||
* <p>The hole figures are the pixel offsets this class drew before they were figures at all,
|
||||
* converted at the canvas scale rather than measured off a part: 14 and 12 pixels are exactly
|
||||
* 1.778 and 1.524 mm, which is to say 0.07 and 0.06 inches. The exact conversions are used rather
|
||||
* than two-decimal roundings so that the drawing is unchanged to the pixel -- the roundings moved
|
||||
* the holes by a fiftieth of a pixel, which antialiasing turned into a visible difference. They
|
||||
* are unsourced in the way the digit widths are.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
public static class Module {
|
||||
|
||||
private final double bezelWidthMm;
|
||||
private final double bezelLengthMm;
|
||||
private final double holeInsetMm;
|
||||
private final double holeSizeMm;
|
||||
|
||||
public Module(double bezelWidthMm, double bezelLengthMm, double holeInsetMm,
|
||||
double holeSizeMm) {
|
||||
this.bezelWidthMm = bezelWidthMm;
|
||||
this.bezelLengthMm = bezelLengthMm;
|
||||
this.holeInsetMm = holeInsetMm;
|
||||
this.holeSizeMm = holeSizeMm;
|
||||
}
|
||||
|
||||
public double getBezelWidthMm() { return bezelWidthMm; }
|
||||
public double getBezelLengthMm() { return bezelLengthMm; }
|
||||
|
||||
/** Centre of a corner hole, from each of the two edges nearest it. */
|
||||
public double getHoleInsetMm() { return holeInsetMm; }
|
||||
|
||||
public double getHoleSizeMm() { return holeSizeMm; }
|
||||
}
|
||||
}
|
||||
|
||||
+31
-3
@@ -120,21 +120,47 @@ public class OLEDDisplayTest {
|
||||
@Test
|
||||
public void controlPointsAreTheSpiPinsInOrder() {
|
||||
OLEDDisplay display = of(Version.SSD1306_0_96, OLEDInterface.SPI_7Pin);
|
||||
String[] expected = new String[] {"GND", "VCC", "D0 (CLK)", "D1 (MOSI)", "RES", "DC", "CS"};
|
||||
String[] expected = new String[] {"GND", "VCC", "SCL", "SDA", "RES", "DC", "CS"};
|
||||
Assert.assertEquals(expected.length, display.getControlPointCount());
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
Assert.assertEquals("pin " + i, expected[i], display.getControlPointNodeName(i));
|
||||
}
|
||||
}
|
||||
|
||||
/** Every size is sold in both interfaces, so no size may carry a shorter pin array. */
|
||||
/** Every size is sold in every interface, so no size may carry a shorter pin array. */
|
||||
@Test
|
||||
public void bothInterfacesExistAtEverySize() {
|
||||
public void everyInterfaceExistsAtEverySize() {
|
||||
for (Version version : Version.values()) {
|
||||
Assert.assertEquals(version + " I2C", 4,
|
||||
of(version, OLEDInterface.I2C_4Pin).getControlPointCount());
|
||||
Assert.assertEquals(version + " SPI", 7,
|
||||
of(version, OLEDInterface.SPI_7Pin).getControlPointCount());
|
||||
Assert.assertEquals(version + " SPI-6", 6,
|
||||
of(version, OLEDInterface.SPI_6Pin).getControlPointCount());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The 6-pin board is the 7-pin one with the chip select tied low on the PCB instead of brought
|
||||
* out, so its row is the other's without that single pin and in the same order -- anything else
|
||||
* would be a different part rather than the same part sold two ways. It borrows the 7-pin board's
|
||||
* outline, which is a derivation and not a measurement, so that is asserted here rather than left
|
||||
* to be discovered.
|
||||
*/
|
||||
@Test
|
||||
public void theSixPinBoardDropsOnlyTheChipSelect() {
|
||||
String[] seven = OLEDInterface.SPI_7Pin.getPinNames();
|
||||
String[] six = OLEDInterface.SPI_6Pin.getPinNames();
|
||||
|
||||
Assert.assertEquals("one pin fewer", seven.length - 1, six.length);
|
||||
Assert.assertEquals("CS is the pin that goes", "CS", seven[seven.length - 1]);
|
||||
for (int i = 0; i < six.length; i++) {
|
||||
Assert.assertEquals("pin " + i, seven[i], six[i]);
|
||||
}
|
||||
|
||||
for (Version version : Version.values()) {
|
||||
Assert.assertSame(version + " shares the SPI board",
|
||||
version.getLayout(OLEDInterface.SPI_7Pin), version.getLayout(OLEDInterface.SPI_6Pin));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,6 +173,8 @@ public class OLEDDisplayTest {
|
||||
Assert.assertEquals(7, display.getControlPointCount());
|
||||
display.setVersion(Version.SSD1306_0_91);
|
||||
Assert.assertEquals(7, display.getControlPointCount());
|
||||
display.setOledInterface(OLEDInterface.SPI_6Pin);
|
||||
Assert.assertEquals(6, display.getControlPointCount());
|
||||
display.setOledInterface(OLEDInterface.I2C_4Pin);
|
||||
Assert.assertEquals(4, display.getControlPointCount());
|
||||
}
|
||||
|
||||
+42
@@ -113,6 +113,48 @@ public class SevenSegmentDisplayTest {
|
||||
large.getControlPointNodeName(i));
|
||||
}
|
||||
Assert.assertNotEquals(small.getBodyShape().getBounds2D(), large.getBodyShape().getBounds2D());
|
||||
Assert.assertSame("shared by identity, not by two matching copies",
|
||||
DisplayType.FourDigit_0_36_12Pin.getPinNames(),
|
||||
DisplayType.FourDigit_0_56_12Pin.getPinNames());
|
||||
}
|
||||
|
||||
/**
|
||||
* The digit count is the variant's own figure rather than something the drawing works out from
|
||||
* which constant it is looking at. That is what lets a two-, six- or eight-digit part be a
|
||||
* constant beside these, so it is worth asserting that every variant answers and that the
|
||||
* answer is the one the label advertises.
|
||||
*/
|
||||
@Test
|
||||
public void digitCountComesFromThePackage() {
|
||||
Assert.assertEquals(1, DisplayType.SingleDigit_10Pin.getDigitCount());
|
||||
Assert.assertEquals(4, DisplayType.FourDigit_0_36_12Pin.getDigitCount());
|
||||
Assert.assertEquals(4, DisplayType.FourDigit_0_56_12Pin.getDigitCount());
|
||||
Assert.assertEquals(4, DisplayType.TM1637_Module_4Pin.getDigitCount());
|
||||
|
||||
for (DisplayType displayType : DisplayType.values()) {
|
||||
Assert.assertTrue(displayType + " shows no digits", displayType.getDigitCount() >= 1);
|
||||
Assert.assertEquals(displayType + " pin count", displayType.getPinNames().length,
|
||||
of(displayType).getControlPointCount());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A driven module brings out no common pins, so its polarity is not something you order -- which
|
||||
* is why the BOM line omits it. Asked of the variant rather than of its identity, and paired with
|
||||
* the pin arrangement so that the two cannot quietly become one question: they agree on all four
|
||||
* variants today, but a single-in-line bare package or a module in a DIP outline would separate
|
||||
* them.
|
||||
*/
|
||||
@Test
|
||||
public void onlyModulesCarryABoard() {
|
||||
for (DisplayType displayType : DisplayType.values()) {
|
||||
Assert.assertEquals(displayType + " module", displayType == DisplayType.TM1637_Module_4Pin,
|
||||
displayType.isModule());
|
||||
Assert.assertEquals(displayType + " board figures", displayType.isModule(),
|
||||
displayType.getModule() != null);
|
||||
Assert.assertNotEquals(displayType + " row arrangement", displayType.isModule(),
|
||||
displayType.isDualRow());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+246
-1896
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user