mirror of
https://github.com/bancika/diy-layout-creator
synced 2026-11-13 02:32:09 +10:00
Resistors, capacitors, diodes, ICs, transistors and other PCB parts can be placed on the bottom of the board with the new 'Board Side' property; Gerber export puts their silkscreen on the bottom layer with the text mirrored
This commit is contained in:
@@ -3,9 +3,10 @@
|
||||
Let a component be mounted on the bottom of a PCB, so that its silkscreen goes to the bottom
|
||||
Gerber layers and the canvas shows it as a part on the far side of the board.
|
||||
|
||||
Status: the core Gerber side is done, with tests: `IBoardSideComponent` exists and the export
|
||||
sends a bottom-side part to the bottom layers, but no component implements it yet. Parts can be
|
||||
selected, dragged and stretched through the Underside Display mirror. The next steps below remain.
|
||||
Status: 32 parts have a Board Side property, and Gerber export sends a bottom-side part's
|
||||
silkscreen to the bottom layer with its text mirrored. Parts can be selected, dragged and stretched
|
||||
through the Underside Display mirror. The canvas does not show the side yet, and the Flip to Other
|
||||
Side action does not exist; the next steps below remain.
|
||||
|
||||
## 1. Current state
|
||||
|
||||
@@ -41,6 +42,9 @@ selected, dragged and stretched through the Underside Display mirror. The next s
|
||||
| Flipping a part is an action that sets the side, mirrors the part and sends it back | A part seen from above through the board is a mirror image. Changing the side without mirroring gives a footprint that is wrong for fabrication. |
|
||||
| The Gerber layer is swapped centrally, not inside each component | Components keep emitting their `*Top` layer. One place maps it to the other side. |
|
||||
| Default `_2` (Top), with `null` meaning Top | Fields added to existing classes deserialize as `null` in old files. |
|
||||
| The side is both an editable property and the Flip to Other Side action | The action is the normal way to move a part, because it also mirrors it. The property stays for a part that is already drawn mirrored and only needs its side set. |
|
||||
| Bottom-side text is mirrored centrally in the Gerber output | Parts draw their labels readable from the top, which is backwards on the bottom silkscreen once the board is turned over. While `GerberExporter.drawComponent` draws a bottom-side part, `GerberG2DWrapper.setMirrorText` mirrors each string about the centre of its layout box, so no component changes and the canvas keeps readable labels. |
|
||||
| A `SolderPad` opens the solder mask on its own side | It used to write `SolderMaskBot` whatever its layer, which was wrong for top-layer pads. It now writes `SolderMaskTop` for a pad on `_2`. |
|
||||
|
||||
## 3. Design
|
||||
|
||||
@@ -52,18 +56,28 @@ selected, dragged and stretched through the Underside Display mirror. The next s
|
||||
|
||||
### diylc-library
|
||||
|
||||
- The ~35 classes that use the `SilkscreenTop` default implement `IBoardSideComponent`. Each adds a
|
||||
nullable `PCBLayer boardSide` field and a getter/setter pair, with
|
||||
`@EditableProperty(name = "Board Side")` on the getter. The getter returns `_2` (Top) when the
|
||||
field is `null`. This duplicates the field across classes in the same way the `PCBLayer` field is
|
||||
duplicated today. Where several of these classes share an abstract base
|
||||
(`AbstractRadialComponent`, `AbstractFilmCapacitor`, `AbstractTransistorPackage`, ...), put it on
|
||||
the base.
|
||||
- **Done.** Every part that uses the `SilkscreenTop` default and whose transformer can mirror it
|
||||
implements `IBoardSideComponent`: a nullable `PCBLayer boardSide` field and a getter/setter pair
|
||||
with `@EditableProperty(name = "Board Side")` on the getter, which returns `_2` (Top) when the
|
||||
field is `null`. The key is in every language file.
|
||||
- On a shared base, covering every subclass: `AbstractFilmCapacitor`, `AbstractPotentiometer`,
|
||||
`AbstractRadialComponent`, `PassiveSMDComponent`.
|
||||
- On the class itself: `Resistor`, `HeatSinkResistor`, `AxialElectrolyticCapacitor`,
|
||||
`CrystalOscillator`, `ToroidalInductor`, `DiodePlastic`, `DiodeGlass`, `DIL_IC`, `SIL_IC`,
|
||||
`TransistorTO1`, `TransistorTO92`, `TransistorTO220`, `CliffJack1_4`, `CliffJack1_8`,
|
||||
`ClosedJack1_4`, `MiniToggleSwitch`, `PCBTerminalBlock`. The transistors are not done on
|
||||
`AbstractTransistorPackage` because `TransistorTO126` cannot be mirrored, and a property on the
|
||||
base cannot be hidden from one subclass.
|
||||
- Left out because they cannot be mirrored: `TubeSocket`, `RotarySwitchOpen`,
|
||||
`RotarySwitchSealed`, `RotarySelectorSwitch`, `SlideSwitch`, `PlasticDCJack`,
|
||||
`TactileMicroSwitch`, `MiniRelay`, `AudioTransformer`, `MultiSectionCapacitor`, `MultiwattIC`,
|
||||
`BridgeRectifier`, `TransistorTO126`. Making one of them mirrorable is what it takes to give it
|
||||
a side.
|
||||
- `Label` is left out too: it is text, not a mounted part, and `PCBText` already has a layer.
|
||||
- `BoardSideComponentsTest` checks that every such part starts on Top, takes Bottom, and can be
|
||||
mirrored.
|
||||
- `CopperTrace`, `CurvedTrace`, `GroundFill`, `SolderPad`, `PCBText` and `DrillHole` do **not**
|
||||
implement it. Their `PCBLayer` already says where they are.
|
||||
- Before allowing Bottom on a class, check that its transformer can mirror it
|
||||
(`canMirror`). A class that cannot be mirrored must not offer Bottom, or the footprint would be
|
||||
wrong.
|
||||
|
||||
### diylc-swing
|
||||
|
||||
@@ -115,17 +129,6 @@ order.
|
||||
|
||||
## 4. Open questions
|
||||
|
||||
- **Bottom silkscreen text.** Component labels drawn through `IGerberComponentSimple` have to read
|
||||
correctly once the board is turned over, which means they must look mirrored from the top. Check
|
||||
whether mirroring through the transformer does that for every class, or whether labels are drawn
|
||||
unmirrored regardless. `GerberLayer.mirrored` is currently `false` for every layer, and the
|
||||
exporter output must stay in top view.
|
||||
- **SolderPad solder mask.** `SolderPad` always writes its mask opening to `SolderMaskBot`,
|
||||
whatever its own `PCBLayer`. Confirm whether this is intended for top-layer SMD pads before
|
||||
`GerberLayer.flip()` is introduced next to it.
|
||||
- **Plain property or action only.** A plain editable property lets a user change the side without
|
||||
mirroring. Either keep both (the property for already-mirrored parts) or show the side as
|
||||
read-only and change it only through the action.
|
||||
- **Components that belong to no side.** In mirror stage 3 a jumper, eyelet or wire dropped in the
|
||||
mirror has no side to set. Confirm that placing it at the reflected point unchanged is what users
|
||||
expect, or whether such parts should be refused in the mirror.
|
||||
@@ -153,10 +156,8 @@ order.
|
||||
|
||||
## 6. Next steps
|
||||
|
||||
1. Add the field to the library components, putting it on shared bases where they exist. Settle
|
||||
the silkscreen-text question while doing so.
|
||||
2. Wrap bottom-side painting in `startDrawingSide(getBoardSide())`.
|
||||
3. Add the Flip to Other Side action.
|
||||
4. Split the silkscreen print-out by side.
|
||||
5. Mirror stage 3: placing in the mirror, after Flip to Other Side exists.
|
||||
6. Run the regression suite.
|
||||
1. Wrap bottom-side painting in `startDrawingSide(getBoardSide())`.
|
||||
2. Add the Flip to Other Side action.
|
||||
3. Split the silkscreen print-out by side.
|
||||
4. Mirror stage 3: placing in the mirror, after Flip to Other Side exists.
|
||||
5. Run the regression suite.
|
||||
|
||||
Reference in New Issue
Block a user