mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-07 12:24:58 +10:00
Added 1.8" sd
This commit is contained in:
@@ -5049,6 +5049,14 @@
|
||||
<defaultFlag>false</defaultFlag>
|
||||
<createdOn>2026-10-11T00:00:00.0000000</createdOn>
|
||||
</org.diylc.core.Template>
|
||||
<org.diylc.core.Template>
|
||||
<name>1.8" ST7735 128x160 (SD)</name>
|
||||
<values>
|
||||
<entry><string>Controller</string><diylc.displays.TFTDisplay_-Controller>ST7735_1_8_SD</diylc.displays.TFTDisplay_-Controller></entry>
|
||||
</values>
|
||||
<defaultFlag>false</defaultFlag>
|
||||
<createdOn>2026-10-11T00:00:00.0000000</createdOn>
|
||||
</org.diylc.core.Template>
|
||||
<org.diylc.core.Template>
|
||||
<name>1.54" ST7789 240x240</name>
|
||||
<values>
|
||||
|
||||
@@ -85,6 +85,16 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
public static final String[] PIN_NAMES_SD =
|
||||
new String[] {"SD_CS", "SD_MOSI", "SD_MISO", "SD_SCK"};
|
||||
|
||||
/**
|
||||
* The SD row drops the prefix its node names carry: the default label strips at the underscore
|
||||
* and would print four pins all reading "SD", and the full forms are 24 to 29 px against the
|
||||
* 20 px the 0.1" pitch allows. MOSI and MISO are 19 px and just fit, so this row prints them
|
||||
* where the main row has to fall back on the board's own SDI and SDO. Nothing but the row's
|
||||
* position says these four belong to the card socket, which is also all the board itself says
|
||||
* once the prefix is off.
|
||||
*/
|
||||
public static final String[] SILK_NAMES_SD = new String[] {"CS", "MOSI", "MISO", "SCK"};
|
||||
|
||||
/**
|
||||
* The eight-pin row the 1.8" and the 1.54" share, and the same lines the 0.96" brings out. Two
|
||||
* different controllers behind one header: what a board of this size exposes is the four-wire SPI
|
||||
@@ -157,10 +167,16 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
|
||||
@Override
|
||||
protected String getSilkPinLabel(int index) {
|
||||
if (getController().getPinNames() == PIN_NAMES_ILI9341 && index >= 0
|
||||
Controller controller = getController();
|
||||
if (controller.getPinNames() == PIN_NAMES_ILI9341 && index >= 0
|
||||
&& index < SILK_NAMES_ILI9341.length) {
|
||||
return SILK_NAMES_ILI9341[index];
|
||||
}
|
||||
int secondaryIndex = index - controller.getPinNames().length;
|
||||
if (controller.getSecondaryPinNames() == PIN_NAMES_SD && secondaryIndex >= 0
|
||||
&& secondaryIndex < SILK_NAMES_SD.length) {
|
||||
return SILK_NAMES_SD[secondaryIndex];
|
||||
}
|
||||
return super.getSilkPinLabel(index);
|
||||
}
|
||||
|
||||
@@ -177,9 +193,9 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
}
|
||||
|
||||
/**
|
||||
* Top edge of the board. Most variants carry their main header on the bottom edge and stand above
|
||||
* control point zero, so the offset is measured up from the bottom; the 0.96" has its row on the
|
||||
* top edge and hangs below it instead.
|
||||
* Top edge of the board. A board headed at the bottom stands above control point zero, so its
|
||||
* offset is measured up from the bottom edge; the three headed at the top hang below their row
|
||||
* instead.
|
||||
*/
|
||||
private double getBoardY(double y) {
|
||||
Controller controller = getController();
|
||||
@@ -298,17 +314,18 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
|
||||
if (controller.hasMountingHoles()) {
|
||||
double holeInset = px(controller.getHoleInsetMm());
|
||||
double sideInset = px(controller.getHoleSideInsetMm());
|
||||
double headerSideInset = px(controller.getHeaderSideHoleInsetMm());
|
||||
double holeSize = px(controller.getHoleSizeMm());
|
||||
// The deeper inset, where a board has one, belongs to the pair sharing the header's edge.
|
||||
double topInset = controller.isHeaderAtTop() ? headerSideInset : holeInset;
|
||||
double bottomInset = controller.isHeaderAtTop() ? holeInset : headerSideInset;
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + holeInset, boardY + topInset, holeSize);
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + boardW - holeInset, boardY + topInset,
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + sideInset, boardY + topInset, holeSize);
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + boardW - sideInset, boardY + topInset,
|
||||
holeSize);
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + holeInset, boardY + boardH - bottomInset,
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + sideInset, boardY + boardH - bottomInset,
|
||||
holeSize);
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + boardW - holeInset,
|
||||
MakerBoardPainter.drawMountingHole(g2d, boardX + boardW - sideInset,
|
||||
boardY + boardH - bottomInset, holeSize);
|
||||
bandTop = boardY + topInset;
|
||||
bandBottom = boardY + boardH - bottomInset;
|
||||
@@ -334,8 +351,11 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
Glass glass = controller.getGlass();
|
||||
double glassH = px(glass.getLengthMm());
|
||||
double glassW = glass.spansTheBoard() ? boardW : px(glass.getWidthMm());
|
||||
double glassX = glass.spansTheBoard() ? boardX
|
||||
: boardX + boardW - px(glass.getRightInsetMm()) - glassW;
|
||||
// A panel as wide as its board and one centred across it come out at the same place, so
|
||||
// only the 0.96", which is pushed into one side, needs the other branch.
|
||||
double glassX = glass.isPlacedFromTheRightEdge()
|
||||
? boardX + boardW - px(glass.getRightInsetMm()) - glassW
|
||||
: boardX + (boardW - glassW) / 2.0;
|
||||
double glassY = bandCentre - glassH / 2.0;
|
||||
g2d.setColor(GLASS_COLOR);
|
||||
g2d.fill(new Rectangle2D.Double(glassX, glassY, glassW, glassH));
|
||||
@@ -343,9 +363,9 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
// The lit area belongs to the panel rather than to the board, so it is centred in the
|
||||
// glass -- which is the same thing as centring it on the board for every variant whose
|
||||
// glass spans the board, and is not for the 0.96", whose panel is pushed to one side.
|
||||
// It is centred vertically too unless the variant measured it, which the 2.4" does: its
|
||||
// panel carries the driver's bonding region along the bottom, so the lit area sits high
|
||||
// in the frame and centring it would drop it 5 mm.
|
||||
// It is centred vertically too unless the variant states its own figure, which the two
|
||||
// ILI9341s and the 1.8" do: their panels carry the driver's bonding region along the
|
||||
// bottom, so the lit area sits high in the frame and centring it would drop it.
|
||||
screenX = glassX + (glassW - screenW) / 2.0;
|
||||
screenY = controller.hasMeasuredScreenTop() ? boardY + px(controller.getScreenTopMm())
|
||||
: glassY + (glassH - screenH) / 2.0;
|
||||
@@ -376,15 +396,16 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
|
||||
// The names go in the strip between the pin row and the panel, lying flat along the row as
|
||||
// the Nokia's do: the strip is 3.5 mm deep on the two smallest boards and a label stood on
|
||||
// end needs 4.7 mm. The row is on the bottom edge on every variant, so the strip, and the
|
||||
// names in it, are above the pins on a board headed at the bottom and below them on the
|
||||
// 0.96", which is headed at the top.
|
||||
//
|
||||
// Only the primary row is named. The SD row has the glass a couple of millimetres from it and
|
||||
// nothing but board edge on its other side, so there is no strip to print in; those four pins
|
||||
// are left to their tooltips, as the matrix's covered rows are.
|
||||
drawFlatRowPinLabels(g2d, x, y, getRelativeOffsets(), 0, controller.getPinNames().length,
|
||||
// end needs 4.7 mm. Each row prints into the board rather than off its own edge, so the
|
||||
// names are above the pins on a row along the bottom edge and below them on one along the
|
||||
// top -- the 0.96"'s main row and, where there is one, the SD row facing the main header.
|
||||
double[][] offsets = getRelativeOffsets();
|
||||
drawFlatRowPinLabels(g2d, x, y, offsets, 0, controller.getPinNames().length,
|
||||
controller.isHeaderAtTop(), SILK_COLOR);
|
||||
if (controller.hasSecondaryHeader()) {
|
||||
drawFlatRowPinLabels(g2d, x, y, offsets, controller.getPinNames().length,
|
||||
controller.getSecondaryPinNames().length, !controller.isHeaderAtTop(), SILK_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
g2d.setTransform(oldTx);
|
||||
@@ -417,55 +438,84 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
}
|
||||
|
||||
public enum Controller {
|
||||
// The constants run from the smallest diagonal to the largest, which is the order the part's
|
||||
// controller list offers them in; a new variant goes in at its place in that run rather than
|
||||
// at the end.
|
||||
//
|
||||
// Each board is dimensioned from its module outline, and its main header sits centred on the
|
||||
// short bottom edge at the offset recorded here -- every board in this family is drawn that
|
||||
// way round, so the board grows upwards from its pin row and switching variants never turns a
|
||||
// drawing end for end. Active areas are the nominal diagonal taken at the
|
||||
// panel's aspect ratio -- 2.8" at 4:3 gives 43.2 x 57.6, 1.8" at 4:5 gives 28.56 x 35.7, the
|
||||
// square 1.54" gives 27.66 either way and the round 1.28" a 32.5 mm lit circle -- which makes
|
||||
// them derivations rather than measurements, noted so they are not built upon. A glass length
|
||||
// of zero means the module has no separate dark panel wider than its own lit area, so only the
|
||||
// screen is drawn, and a hole size of zero means the board has no mounting holes at all.
|
||||
// drawing end for end. Active areas are the nominal diagonal taken at the panel's aspect ratio
|
||||
// -- the square 1.54" gives 27.66 either way and the round 1.28" a 32.5 mm lit circle -- which
|
||||
// makes those derivations rather than measurements, noted so they are not built upon. The two
|
||||
// ILI9341 boards and the 1.8" are measured throughout, and the 2.8"'s 43.2 x 57.6 lit area
|
||||
// happens to be what 4:3 would have given anyway. A glass length of zero
|
||||
// means the module has no separate dark panel wider than its own lit area, so only the screen
|
||||
// is drawn, and a hole size of zero means the board has no mounting holes at all.
|
||||
// The round board is described by the same two outline figures as the others: its width is the
|
||||
// disc diameter and its length runs from the tab's outer edge to the far side of the disc, so
|
||||
// the tab's projection is the difference between them and is not carried separately.
|
||||
//
|
||||
// The 2.8"'s micro-SD socket comes out on a four-pin row of its own, the way the 2.4"'s does,
|
||||
// on the top edge opposite the main header. It keeps the board's own 3 mm offset rather than
|
||||
// the 2.4"'s 2 mm, each board putting its second row as far in as its first.
|
||||
ILI9341_2_8("2.8\" ILI9341 240x320 (Touch + SD)", 50.0d, 86.0d, 43.2d, 57.6d, new Glass(69.1d),
|
||||
3.0d, 3.0d, 3.0d, 0d, PIN_NAMES_ILI9341, 0d, PIN_NAMES_SD, 3.0d, 3.0d, false),
|
||||
// Four of the six are headed at the top; the two ILI9341s and the round board are not. There is
|
||||
// no default to fall back on, so every constant states its own edge -- see the plan's 12.2.3.
|
||||
// The one board here measured rather than derived throughout, and the only one with a second
|
||||
// header. Four of its figures do not behave like the others': the 14-pin row is on the bottom
|
||||
// edge, the lit area is measured 9.26 mm down from the top rather than centred in the glass,
|
||||
// the SD row stands 2 mm in from the opposite edge, and the two holes nearest the pin row are
|
||||
// 6.92 mm in rather than sharing the 3 mm of the other pair -- at 3 mm they would sit on the
|
||||
// row. The glass keeps the family's rule, centred between the hole rows, which the deeper pair
|
||||
// puts at 6.50 to 66.76 mm: 2.76 mm of frame above the lit area and 8.54 mm below it, the
|
||||
// asymmetry being the driver's bonding region along the bottom of the panel.
|
||||
ILI9341_2_4("2.4\" ILI9341 240x320 (Touch + SD)", 42.72d, 77.18d, 36.72d, 48.96d,
|
||||
new Glass(60.26d), 2.0d, 3.0d, 3.0d, 0d, PIN_NAMES_ILI9341, 9.26d, PIN_NAMES_SD, 2.0d,
|
||||
6.92d, false),
|
||||
// The one board in the family whose header is on the top edge, and the only one whose panel
|
||||
// does not span the board: a 23.7 x 12.8 mm bezel pushed into the right-hand side, 2 mm from
|
||||
// that edge and 4.3 mm from the other, with the driver's circuitry filling the bare L the
|
||||
// offset leaves. Its lit area is landscape where every other board's is portrait, it is
|
||||
// measured rather than derived, and it is centred in the bezel with a 1 mm frame all round.
|
||||
// The bezel is offset only across the board; down it, it keeps the family's rule and sits
|
||||
// centred, which on a board whose holes share one inset is the same as centred in the PCB.
|
||||
// Three of the six are headed at the top and three at the bottom. There is no default to fall
|
||||
// back on, so every constant states its own edge -- see the plan's 12.2.3.
|
||||
//
|
||||
// The only board in the family whose panel does not span it: a 23.7 x 12.8 mm bezel pushed
|
||||
// into the right-hand side, 2 mm from that edge and 4.3 mm from the other, with the driver's
|
||||
// circuitry filling the bare L the offset leaves. Its lit area is landscape where every other
|
||||
// board's is portrait, it is measured rather than derived, and it is centred in the bezel with
|
||||
// a 1 mm frame all round. The bezel is offset only across the board; down it, it keeps the
|
||||
// family's rule and sits centred, which on a board whose holes share one inset is the same as
|
||||
// centred in the PCB.
|
||||
ST7735_0_96("0.96\" ST7735 80x160", 30.0d, 24.0d, 21.7d, 10.8d,
|
||||
new Glass(12.8d, 23.7d, 2.0d), 1.44d, 2.0d, 2.0d, 0d, PIN_NAMES_SPI_8PIN, 0d, null, 0d,
|
||||
2.0d, true),
|
||||
ST7735_1_8("1.8\" ST7735 128x160", 34.0d, 45.8d, 28.56d, 35.7d, null, 1.5d, 3.0d, 3.0d, 0d,
|
||||
PIN_NAMES_SPI_8PIN, true),
|
||||
ST7789_1_54("1.54\" ST7789 240x240", 32.0d, 43.72d, 27.66d, 27.66d, new Glass(33.7d), 1.5d,
|
||||
2.5d, 2.0d, 0d, PIN_NAMES_SPI_8PIN, true),
|
||||
GC9A01_1_28("1.28\" GC9A01 240x240 Round", 38.0d, 45.5d, 32.5d, 32.5d, null, 1.76d, 0d, 0d,
|
||||
22.9d,
|
||||
new String[] {"RST", "CS", "DC", "SDA", "SCL", "GND", "VCC"}, false);
|
||||
|
||||
new String[] {"RST", "CS", "DC", "SDA", "SCL", "GND", "VCC"}, false),
|
||||
ST7789_1_54("1.54\" ST7789 240x240", 32.0d, 43.72d, 27.66d, 27.66d, new Glass(33.7d), 1.5d,
|
||||
2.5d, 2.0d, 0d, PIN_NAMES_SPI_8PIN, true),
|
||||
// Measured throughout, and the second board whose bezel is narrower than the PCB -- 33 mm of
|
||||
// a 35 mm board -- but centred across it rather than pushed to one side as the 0.96"'s is.
|
||||
// Down the board the centring rule puts the bezel 5.09 mm from the top edge, which is the
|
||||
// 5.1 mm the board measures to within the width of the line it is drawn with. The lit area
|
||||
// sits 2 mm above the middle of the bezel, as the ILI9341s' do, which is the 8.5 mm here;
|
||||
// move the bezel and it has to be rederived.
|
||||
ST7735_1_8("1.8\" ST7735 128x160", 35.0d, 56.0d, 28.0d, 35.0d, new Glass(45.83d, 33.0d), 1.41d,
|
||||
2.5d, 2.0d, 0d, PIN_NAMES_SPI_8PIN, 8.5d, null, 0d, 2.5d, true),
|
||||
// The same panel on a longer board that brings its micro-SD socket out the way the ILI9341s
|
||||
// do, which turns the module round: the 8-pin row leaves by the bottom edge and the SD row by
|
||||
// the top. It is the one board whose holes are not the same distance in from every edge --
|
||||
// 2.75 mm from the sides and 3 mm from the ends, which is what holds them 28.5 mm apart across
|
||||
// a 34 mm board and 52 mm apart down a 58 mm one -- and the first to need the side figure
|
||||
// stated apart from the shared one. Its bezel is the plain 1.8"'s, so the lit area keeps the
|
||||
// same 2 mm above the middle of it, which on this board's hole rows is 9.5 mm from the top
|
||||
// edge. Both rows stand 2.5 mm off their own edge, which puts the 8-pin row alongside the
|
||||
// holes on its edge rather than clear of them; they pass either side of it.
|
||||
ST7735_1_8_SD("1.8\" ST7735 128x160 (SD)", 34.0d, 58.0d, 28.0d, 35.0d,
|
||||
new Glass(45.83d, 33.0d), 2.5d, 3.0d, 2.0d, 0d, PIN_NAMES_SPI_8PIN, 9.5d, PIN_NAMES_SD,
|
||||
2.5d, 3.0d, 2.75d, false),
|
||||
// Measured rather than derived throughout, as the 2.8" is, and laid out the same way round:
|
||||
// the 14-pin row on the bottom edge, the SD row in from the opposite one, a lit area measured
|
||||
// from the top rather than centred in the glass, and a deeper pair of holes beside the pin
|
||||
// row. Each board's figures are its own: 2 mm to the SD row, 9.26 mm to the lit area and
|
||||
// 6.92 mm to that pair -- at 3 mm the holes would sit on the row, its 14 pins spanning 33 mm
|
||||
// of a 42.72 mm board. The glass keeps the family's rule, centred between the hole rows, which
|
||||
// the deeper pair puts at 6.50 to 66.76 mm: 2.76 mm of frame above the lit area and 8.54 mm
|
||||
// below it, the asymmetry being the driver's bonding region along the bottom of the panel.
|
||||
ILI9341_2_4("2.4\" ILI9341 240x320 (Touch + SD)", 42.72d, 77.18d, 36.72d, 48.96d,
|
||||
new Glass(60.26d), 2.0d, 3.0d, 3.0d, 0d, PIN_NAMES_ILI9341, 9.26d, PIN_NAMES_SD, 2.0d,
|
||||
6.92d, false),
|
||||
// The 2.8"'s micro-SD socket comes out on a four-pin row of its own, the way the 2.4"'s does,
|
||||
// on the top edge opposite the main header, 2.5 mm in from it. Its own 14-pin row is 2 mm
|
||||
// from the bottom edge, and the pair of holes sharing that edge is 6.50 mm in, well clear of
|
||||
// the row rather than level with it as a 3 mm pair would be. Carrying that pair up the board
|
||||
// carries the panel with it, the glass being centred between the hole rows: 1.75 mm for the
|
||||
// 3.50 mm the holes moved. The 50 x 69.2 mm bezel spans the board and the centring rule puts
|
||||
// it 6.65 mm from the top edge; the 43.2 x 57.6 mm lit area is measured 3.05 mm below the
|
||||
// bezel's own top edge, which is the 9.70 mm recorded here, and leaves 8.55 mm of frame below
|
||||
// it for the driver's bonding region. Move the hole rows and that 9.70 has to be rederived.
|
||||
ILI9341_2_8("2.8\" ILI9341 240x320 (Touch + SD)", 50.0d, 86.0d, 43.2d, 57.6d, new Glass(69.2d),
|
||||
2.0d, 3.0d, 3.0d, 0d, PIN_NAMES_ILI9341, 9.70d, PIN_NAMES_SD, 2.5d, 6.50d, false);
|
||||
private final String label;
|
||||
private final double boardWidthMm;
|
||||
private final double boardLengthMm;
|
||||
@@ -481,6 +531,7 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
private final String[] secondaryPinNames;
|
||||
private final double secondaryHeaderOffsetMm;
|
||||
private final double headerSideHoleInsetMm;
|
||||
private final double holeSideInsetMm;
|
||||
private final boolean headerAtTop;
|
||||
|
||||
/** For a board whose lit area is centred and whose pins all leave on one row. */
|
||||
@@ -491,11 +542,22 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
holeInsetMm, holeSizeMm, tabWidthMm, pinNames, 0d, null, 0d, holeInsetMm, headerAtTop);
|
||||
}
|
||||
|
||||
/** For a board whose holes are the same distance in from every edge they are near. */
|
||||
Controller(String label, double boardWidthMm, double boardLengthMm, double screenWidthMm,
|
||||
double screenLengthMm, Glass glass, double headerOffsetMm, double holeInsetMm,
|
||||
double holeSizeMm, double tabWidthMm, String[] pinNames, double screenTopMm,
|
||||
String[] secondaryPinNames, double secondaryHeaderOffsetMm, double headerSideHoleInsetMm,
|
||||
boolean headerAtTop) {
|
||||
this(label, boardWidthMm, boardLengthMm, screenWidthMm, screenLengthMm, glass, headerOffsetMm,
|
||||
holeInsetMm, holeSizeMm, tabWidthMm, pinNames, screenTopMm, secondaryPinNames,
|
||||
secondaryHeaderOffsetMm, headerSideHoleInsetMm, holeInsetMm, headerAtTop);
|
||||
}
|
||||
|
||||
Controller(String label, double boardWidthMm, double boardLengthMm, double screenWidthMm,
|
||||
double screenLengthMm, Glass glass, double headerOffsetMm, double holeInsetMm,
|
||||
double holeSizeMm, double tabWidthMm, String[] pinNames, double screenTopMm,
|
||||
String[] secondaryPinNames, double secondaryHeaderOffsetMm, double headerSideHoleInsetMm,
|
||||
double holeSideInsetMm, boolean headerAtTop) {
|
||||
this.label = label;
|
||||
this.boardWidthMm = boardWidthMm;
|
||||
this.boardLengthMm = boardLengthMm;
|
||||
@@ -511,6 +573,7 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
this.secondaryPinNames = secondaryPinNames;
|
||||
this.secondaryHeaderOffsetMm = secondaryHeaderOffsetMm;
|
||||
this.headerSideHoleInsetMm = headerSideHoleInsetMm;
|
||||
this.holeSideInsetMm = holeSideInsetMm;
|
||||
this.headerAtTop = headerAtTop;
|
||||
}
|
||||
|
||||
@@ -527,14 +590,23 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
|
||||
/**
|
||||
* Inset of a mounting hole from each of the two edges nearest it. It is every hole's figure
|
||||
* except where {@link #getHeaderSideHoleInsetMm()} overrides the pin row's pair.
|
||||
* except where {@link #getHeaderSideHoleInsetMm()} overrides the pin row's pair down the
|
||||
* board or {@link #getHoleSideInsetMm()} overrides every hole's across it.
|
||||
*/
|
||||
public double getHoleInsetMm() { return holeInsetMm; }
|
||||
|
||||
/**
|
||||
* Inset of the two holes on the header's edge. It is deeper than the shared figure only on the
|
||||
* 2.4", whose 14-pin row is wide enough for its pads to reach a hole drilled at the other
|
||||
* pairs' 3 mm; every other board's row passes between them and keeps one inset throughout.
|
||||
* Inset of every hole from the side of the board it is near. It differs from the shared
|
||||
* figure only on the 1.8" with the SD socket, whose holes are drilled closer to the sides
|
||||
* than to the ends.
|
||||
*/
|
||||
public double getHoleSideInsetMm() { return holeSideInsetMm; }
|
||||
|
||||
/**
|
||||
* Inset of the two holes on the header's edge. It is deeper than the shared figure on both
|
||||
* ILI9341 boards: the 2.4"'s 14-pin row is wide enough for its pads to reach a hole drilled at
|
||||
* the other pairs' 3 mm, and the 2.8" stands its pair clear of a row it would otherwise sit
|
||||
* level with. Every other board's row passes between them and keeps one inset throughout.
|
||||
*/
|
||||
public double getHeaderSideHoleInsetMm() { return headerSideHoleInsetMm; }
|
||||
|
||||
@@ -543,9 +615,9 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
public boolean hasGlass() { return glass != null; }
|
||||
|
||||
/**
|
||||
* True where the main row leaves by the top edge, so the board hangs below it. Four of the six
|
||||
* do; see the plan's section 12.2.3 for why the family is not uniform and why no constant may
|
||||
* leave this to a default.
|
||||
* True where the main row leaves by the top edge, so the board hangs below it. Three of the
|
||||
* six do; see the plan's section 12.2.3 for why the family is not uniform and why no constant
|
||||
* may leave this to a default.
|
||||
*/
|
||||
public boolean isHeaderAtTop() { return headerAtTop; }
|
||||
|
||||
@@ -575,10 +647,11 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
/**
|
||||
* The dark panel bonded to the front of the board, which is not the same thing as the lit area:
|
||||
* it is the glass the lit area sits in, and the frame it leaves around it is what a reader sees
|
||||
* as the display's border. Every panel is centred between its board's mounting holes, so what
|
||||
* varies is how far across the board it reaches. Carried as an object rather than as more figures
|
||||
* on {@link Controller} because only one board so far needs more than its height, and a
|
||||
* constructor that already takes fifteen arguments should not take seventeen.
|
||||
* as the display's border. Every panel is centred between its board's mounting holes, and
|
||||
* across the board unless it measures an inset from the right edge, so what varies is how far
|
||||
* across the board it reaches and from which side that is taken. Carried as an object rather
|
||||
* than as more figures on {@link Controller} because only two boards so far need more than its
|
||||
* height, and a constructor that already takes fifteen arguments should not take seventeen.
|
||||
*
|
||||
* @author Branislav Stojkovic
|
||||
*/
|
||||
@@ -593,6 +666,12 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
this(lengthMm, 0d, 0d);
|
||||
}
|
||||
|
||||
/** A panel narrower than its board, centred across it. */
|
||||
public Glass(double lengthMm, double widthMm) {
|
||||
this(lengthMm, widthMm, 0d);
|
||||
}
|
||||
|
||||
/** A panel narrower than its board and pushed towards the right edge. */
|
||||
public Glass(double lengthMm, double widthMm, double rightInsetMm) {
|
||||
this.lengthMm = lengthMm;
|
||||
this.widthMm = widthMm;
|
||||
@@ -608,5 +687,8 @@ public class TFTDisplay extends AbstractMakerBoard {
|
||||
public double getRightInsetMm() { return rightInsetMm; }
|
||||
|
||||
public boolean spansTheBoard() { return widthMm <= 0; }
|
||||
|
||||
/** True for a narrower panel placed from the right edge rather than centred on the board. */
|
||||
public boolean isPlacedFromTheRightEdge() { return rightInsetMm > 0; }
|
||||
}
|
||||
}
|
||||
|
||||
+121
-34
@@ -21,9 +21,11 @@
|
||||
*/
|
||||
package org.diylc.components.displays;
|
||||
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -93,6 +95,7 @@ public class TFTDisplayTest {
|
||||
Assert.assertEquals(14, Controller.ILI9341_2_4.getPinNames().length);
|
||||
Assert.assertEquals(8, Controller.ST7735_0_96.getPinNames().length);
|
||||
Assert.assertEquals(8, Controller.ST7735_1_8.getPinNames().length);
|
||||
Assert.assertEquals(8, Controller.ST7735_1_8_SD.getPinNames().length);
|
||||
Assert.assertEquals(8, Controller.ST7789_1_54.getPinNames().length);
|
||||
Assert.assertEquals(7, Controller.GC9A01_1_28.getPinNames().length);
|
||||
|
||||
@@ -100,6 +103,8 @@ public class TFTDisplayTest {
|
||||
of(Controller.ILI9341_2_4).getControlPointCount());
|
||||
Assert.assertEquals("the 2.8\" carries the same second row", 18,
|
||||
of(Controller.ILI9341_2_8).getControlPointCount());
|
||||
Assert.assertEquals("the 1.8\" with the socket carries one too", 12,
|
||||
of(Controller.ST7735_1_8_SD).getControlPointCount());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,6 +119,39 @@ public class TFTDisplayTest {
|
||||
Controller.ILI9341_2_4.getPinNames().length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Both rows are printed, and neither may print a name the default would have mangled. The touch
|
||||
* pins and the SD pins share a prefix apiece, and the default label keeps what stands before the
|
||||
* underscore: left to it, five pins would read "T" and four would read "SD". The widths are the
|
||||
* other half of it -- a flat label has the 0.1" pitch and no more -- and are asserted against
|
||||
* the font the row is drawn in rather than taken from the comment that records them.
|
||||
*/
|
||||
@Test
|
||||
public void everyPrintedPinNameIsDistinctAndFitsThePitch() {
|
||||
FontMetrics metrics = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB).createGraphics()
|
||||
.getFontMetrics(AbstractMakerBoard.PIN_ROW_FLAT_FONT);
|
||||
double pitch = AbstractMakerBoard.PIN_SPACING.convertToPixels();
|
||||
|
||||
for (Controller controller : Controller.values()) {
|
||||
TFTDisplay display = of(controller);
|
||||
Set<String> rowNames = new HashSet<String>();
|
||||
int primaryCount = controller.getPinNames().length;
|
||||
|
||||
for (int i = 0; i < display.getControlPointCount(); i++) {
|
||||
if (i == primaryCount) {
|
||||
rowNames.clear();
|
||||
}
|
||||
String label = display.getSilkPinLabel(i);
|
||||
Assert.assertTrue(controller + " pin " + i + " prints nothing",
|
||||
label != null && !label.isEmpty());
|
||||
Assert.assertTrue(controller + " prints " + label + " twice on one row",
|
||||
rowNames.add(label));
|
||||
Assert.assertTrue(controller + " " + label + " is wider than the pitch",
|
||||
metrics.stringWidth(label) <= pitch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Eighteen pins on one part, so a repeated name would reach the netlist as one node. */
|
||||
@Test
|
||||
public void everyNodeNameIsUnique() {
|
||||
@@ -136,8 +174,8 @@ public class TFTDisplayTest {
|
||||
*/
|
||||
@Test
|
||||
public void theSmallBoardsShareOnePinArray() {
|
||||
Controller[] small =
|
||||
{Controller.ST7735_0_96, Controller.ST7735_1_8, Controller.ST7789_1_54};
|
||||
Controller[] small = {Controller.ST7735_0_96, Controller.ST7735_1_8,
|
||||
Controller.ST7735_1_8_SD, Controller.ST7789_1_54};
|
||||
String[] expected = new String[] {"GND", "VCC", "SCL", "SDA", "RES", "DC", "CS", "BLK"};
|
||||
|
||||
for (Controller controller : small) {
|
||||
@@ -213,7 +251,7 @@ public class TFTDisplayTest {
|
||||
// It shares its edge with a pair of mounting holes, and unlike the long row it is short
|
||||
// enough to pass between them. That is why the top pair keeps the shared inset where the
|
||||
// 2.4"'s header-side pair could not.
|
||||
double holeRim = controller.getHoleInsetMm() + controller.getHoleSizeMm() / 2.0;
|
||||
double holeRim = controller.getHoleSideInsetMm() + controller.getHoleSizeMm() / 2.0;
|
||||
Assert.assertTrue(controller + " SD row runs into the holes on its edge",
|
||||
mm(firstSd.getX() - board.getX()) > holeRim);
|
||||
Assert.assertTrue(controller + " SD row runs into the holes on its edge",
|
||||
@@ -292,16 +330,17 @@ public class TFTDisplayTest {
|
||||
TFTDisplay display = of(controller);
|
||||
Rectangle2D board = display.getBodyShape().getBounds2D();
|
||||
double inset = px(controller.getHoleInsetMm());
|
||||
double sideInset = px(controller.getHoleSideInsetMm());
|
||||
double headerSide = px(controller.getHeaderSideHoleInsetMm());
|
||||
double size = px(controller.getHoleSizeMm());
|
||||
double topInset = controller.isHeaderAtTop() ? headerSide : inset;
|
||||
double bottomInset = controller.isHeaderAtTop() ? inset : headerSide;
|
||||
|
||||
Rectangle2D[] holes = new Rectangle2D[] {
|
||||
hole(board.getX() + inset, board.getY() + topInset, size),
|
||||
hole(board.getMaxX() - inset, board.getY() + topInset, size),
|
||||
hole(board.getX() + inset, board.getMaxY() - bottomInset, size),
|
||||
hole(board.getMaxX() - inset, board.getMaxY() - bottomInset, size)};
|
||||
hole(board.getX() + sideInset, board.getY() + topInset, size),
|
||||
hole(board.getMaxX() - sideInset, board.getY() + topInset, size),
|
||||
hole(board.getX() + sideInset, board.getMaxY() - bottomInset, size),
|
||||
hole(board.getMaxX() - sideInset, board.getMaxY() - bottomInset, size)};
|
||||
|
||||
for (int i = 0; i < display.getControlPointCount(); i++) {
|
||||
Point2D p = display.getControlPoint(i);
|
||||
@@ -377,17 +416,20 @@ public class TFTDisplayTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* The 2.4" is the only board whose lit area is a measurement rather than a derivation, and the
|
||||
* reason is worth asserting rather than only commenting: its panel carries the driver's bonding
|
||||
* region along the bottom, so the lit area sits high in the glass and the family's centring rule
|
||||
* would drop it 4.85 mm. The assertion is that the two disagree -- if a later correction ever
|
||||
* makes them agree, the field has stopped earning its place.
|
||||
* Three boards state their own lit area rather than take the centred one, and the reason is
|
||||
* worth asserting rather than only commenting: their panels carry the driver's bonding region
|
||||
* along the bottom, so the lit area sits high in the glass and the family's centring rule would
|
||||
* drop it 4.85 mm on the 2.4", 2.75 mm on the 2.8" and 2 mm on the 1.8". The assertion is that
|
||||
* the two disagree -- if a later correction ever makes them agree, the field has stopped earning
|
||||
* its place.
|
||||
*/
|
||||
@Test
|
||||
public void theLitAreaIsMeasuredOnlyWhereCentringWouldBeWrong() {
|
||||
for (Controller controller : Controller.values()) {
|
||||
Assert.assertEquals(controller + " measured lit area",
|
||||
controller == Controller.ILI9341_2_4, controller.hasMeasuredScreenTop());
|
||||
controller == Controller.ILI9341_2_4 || controller == Controller.ILI9341_2_8
|
||||
|| controller == Controller.ST7735_1_8 || controller == Controller.ST7735_1_8_SD,
|
||||
controller.hasMeasuredScreenTop());
|
||||
if (!controller.hasMeasuredScreenTop()) {
|
||||
continue;
|
||||
}
|
||||
@@ -401,24 +443,42 @@ public class TFTDisplayTest {
|
||||
screenTop + controller.getScreenLengthMm() <= glassTop + glassH);
|
||||
Assert.assertTrue(controller + " is measured where centring would have done",
|
||||
Math.abs(screenTop - (glassTop + (glassH - controller.getScreenLengthMm()) / 2.0)) > 1d);
|
||||
|
||||
// Each figure is stored from the board's top edge but was arrived at against the bezel, so
|
||||
// it only holds while the glass stays where the hole rows put it. Move a hole row and these
|
||||
// are the assertions that say the stored figure has to be rederived. What was arrived at
|
||||
// differs by board: the ILI9341s were measured as a frame below the top of the bezel, the
|
||||
// 1.8" as a lift off the position the centring rule gives.
|
||||
if (controller == Controller.ST7735_1_8 || controller == Controller.ST7735_1_8_SD) {
|
||||
Assert.assertEquals(controller + " lift off the centred lit area", 2.0d,
|
||||
glassTop + (glassH - controller.getScreenLengthMm()) / 2.0 - screenTop, 0.01d);
|
||||
} else {
|
||||
double frameAbove = controller == Controller.ILI9341_2_4 ? 2.76d : 3.05d;
|
||||
Assert.assertEquals(controller + " frame above the lit area", frameAbove,
|
||||
screenTop - glassTop, 0.01d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The 0.96" is the only board whose panel does not span its width: a 23.7 mm bezel on a 30 mm
|
||||
* board, pushed to the right so that the driver's circuitry has the bare L it leaves. That offset
|
||||
* is across the board only -- down it the bezel is centred like every other variant's -- and it
|
||||
* is a measurement rather than a derivation, since centring it across the board too would move it
|
||||
* 1.15 mm. The lit area is centred inside it with a 1 mm frame on all four sides, which the
|
||||
* drawing gets for free once the glass is placed, and which would silently break if the lit area
|
||||
* went back to being centred on the board.
|
||||
* Two boards carry a bezel narrower than their PCB, and only the 0.96" has it off centre: a
|
||||
* 23.7 mm bezel on a 30 mm board, pushed to the right so that the driver's circuitry has the
|
||||
* bare L it leaves. That offset is across the board only -- down it the bezel is centred like
|
||||
* every other variant's -- and it is a measurement rather than a derivation, since centring it
|
||||
* across the board too would move it 1.15 mm. The lit area is centred inside it with a 1 mm
|
||||
* frame on all four sides, which the drawing gets for free once the glass is placed, and which
|
||||
* would silently break if the lit area went back to being centred on the board.
|
||||
*/
|
||||
@Test
|
||||
public void theOffsetPanelIsPlacedFromTheRightEdge() {
|
||||
for (Controller controller : Controller.values()) {
|
||||
Assert.assertEquals(controller + " panel spans the board",
|
||||
controller != Controller.ST7735_0_96,
|
||||
boolean narrower = controller == Controller.ST7735_0_96
|
||||
|| controller == Controller.ST7735_1_8 || controller == Controller.ST7735_1_8_SD;
|
||||
Assert.assertEquals(controller + " panel spans the board", !narrower,
|
||||
!controller.hasGlass() || controller.getGlass().spansTheBoard());
|
||||
Assert.assertEquals(controller + " panel is placed from the right edge",
|
||||
controller == Controller.ST7735_0_96,
|
||||
controller.hasGlass() && controller.getGlass().isPlacedFromTheRightEdge());
|
||||
}
|
||||
|
||||
Controller controller = Controller.ST7735_0_96;
|
||||
@@ -453,18 +513,19 @@ public class TFTDisplayTest {
|
||||
|
||||
/**
|
||||
* Each board's holes are one drill at one inset from each of the two edges nearest them, but the
|
||||
* figures are the board's own rather than the package's: the two rectangular SPI boards are 3 mm
|
||||
* at 3 mm and the 1.54" is 2 mm at 2.5 mm. The 2.8" board had a deeper inset on its header-side
|
||||
* pair and a narrower 2.5 mm drill for a while, and this guards against either coming back --
|
||||
* the 2.4" really does have a deeper pair, which is asserted beside this rather than within it
|
||||
* so that the two cases cannot be confused for each other again.
|
||||
* figures are the board's own rather than the package's: the two ILI9341s are 3 mm at 3 mm, the
|
||||
* 0.96" is 2 mm at 2 mm, and the 1.8" and the 1.54" are 2 mm at 2.5 mm. The 2.8" had a narrower
|
||||
* 2.5 mm drill for a while and this guards against it coming back. Both ILI9341 boards hold their
|
||||
* header-side pair deeper than their other one, by their own figure and for their own reason,
|
||||
* which is asserted beside this rather than within it so the two cannot be read as one rule.
|
||||
*/
|
||||
@Test
|
||||
public void mountingHoleFiguresAreEachBoardsOwn() {
|
||||
double[][] expected =
|
||||
{{3.0d, 3.0d}, {3.0d, 3.0d}, {2.0d, 2.0d}, {3.0d, 3.0d}, {2.5d, 2.0d}};
|
||||
double[][] expected = {{3.0d, 3.0d}, {3.0d, 3.0d}, {2.0d, 2.0d}, {2.5d, 2.0d}, {3.0d, 2.0d},
|
||||
{2.5d, 2.0d}};
|
||||
Controller[] withHoles = {Controller.ILI9341_2_8, Controller.ILI9341_2_4,
|
||||
Controller.ST7735_0_96, Controller.ST7735_1_8, Controller.ST7789_1_54};
|
||||
Controller.ST7735_0_96, Controller.ST7735_1_8, Controller.ST7735_1_8_SD,
|
||||
Controller.ST7789_1_54};
|
||||
for (int i = 0; i < withHoles.length; i++) {
|
||||
Assert.assertEquals(withHoles[i] + " inset", expected[i][0], withHoles[i].getHoleInsetMm(),
|
||||
0.01d);
|
||||
@@ -473,11 +534,28 @@ public class TFTDisplayTest {
|
||||
}
|
||||
|
||||
for (Controller controller : Controller.values()) {
|
||||
double expectedHeaderSide =
|
||||
controller == Controller.ILI9341_2_4 ? 6.92d : controller.getHoleInsetMm();
|
||||
double expectedHeaderSide = controller.getHoleInsetMm();
|
||||
if (controller == Controller.ILI9341_2_4) {
|
||||
expectedHeaderSide = 6.92d;
|
||||
} else if (controller == Controller.ILI9341_2_8) {
|
||||
expectedHeaderSide = 6.50d;
|
||||
}
|
||||
Assert.assertEquals(controller + " header-side inset", expectedHeaderSide,
|
||||
controller.getHeaderSideHoleInsetMm(), 0.01d);
|
||||
|
||||
double expectedSide = controller == Controller.ST7735_1_8_SD ? 2.75d
|
||||
: controller.getHoleInsetMm();
|
||||
Assert.assertEquals(controller + " side inset", expectedSide,
|
||||
controller.getHoleSideInsetMm(), 0.01d);
|
||||
}
|
||||
|
||||
// The one board whose holes are not square to the outline was given as two hole-to-hole
|
||||
// spans rather than as insets, so those are what the three figures have to come back to.
|
||||
Controller sd = Controller.ST7735_1_8_SD;
|
||||
Assert.assertEquals("1.8\" SD holes across", 28.5d,
|
||||
sd.getBoardWidthMm() - 2 * sd.getHoleSideInsetMm(), 0.01d);
|
||||
Assert.assertEquals("1.8\" SD holes down", 52.0d,
|
||||
sd.getBoardLengthMm() - sd.getHoleInsetMm() - sd.getHeaderSideHoleInsetMm(), 0.01d);
|
||||
}
|
||||
|
||||
/** Without this the BOM collapses every variant of the part into a single row. */
|
||||
@@ -490,13 +568,21 @@ public class TFTDisplayTest {
|
||||
of(Controller.ST7735_1_8).getValueForDisplay());
|
||||
}
|
||||
|
||||
/** The 2.8" and 1.54" modules carry a dark panel wider than their lit area; the others do not. */
|
||||
/**
|
||||
* Every module but the round one carries a dark panel wider than its lit area. The 1.8" is the
|
||||
* board whose bezel was measured down the board as well as across it, 5.1 mm from the top edge,
|
||||
* and the family's centring rule is what places it: the two have to keep agreeing, so the
|
||||
* measured figure is asserted here rather than left to the rule to reproduce unwatched.
|
||||
*/
|
||||
@Test
|
||||
public void glassPanelFollowsTheModule() {
|
||||
Assert.assertTrue(Controller.ILI9341_2_8.hasGlass());
|
||||
Assert.assertTrue(Controller.ST7789_1_54.hasGlass());
|
||||
Assert.assertFalse(Controller.ST7735_1_8.hasGlass());
|
||||
Assert.assertTrue(Controller.ST7735_1_8.hasGlass());
|
||||
Assert.assertFalse(Controller.GC9A01_1_28.hasGlass());
|
||||
|
||||
Assert.assertEquals("1.8\" bezel from the top edge", 5.1d,
|
||||
mm(panelTopOf(Controller.ST7735_1_8)), 0.02d);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -598,6 +684,7 @@ public class TFTDisplayTest {
|
||||
Assert.assertFalse("2.8\"", Controller.ILI9341_2_8.isHeaderAtTop());
|
||||
Assert.assertFalse("2.4\"", Controller.ILI9341_2_4.isHeaderAtTop());
|
||||
Assert.assertFalse("1.28\" round", Controller.GC9A01_1_28.isHeaderAtTop());
|
||||
Assert.assertFalse("1.8\" with the socket", Controller.ST7735_1_8_SD.isHeaderAtTop());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user