aboutsummaryrefslogtreecommitdiff
path: root/fix-pcb.py
diff options
context:
space:
mode:
authorFredrik Thulin <fredrik@thulin.net>2017-09-25 15:10:51 +0200
committerFredrik Thulin <fredrik@thulin.net>2017-09-25 15:10:51 +0200
commit19a36f254fe1007827d6e83a90250d625bb7ae2e (patch)
tree8836ea63a1c8fe403b613fb5e4f02dfec0dd7558 /fix-pcb.py
parentdd7530da716c431eb7586545dc205ba92d5ac28c (diff)
fix more layers
Diffstat (limited to 'fix-pcb.py')
-rwxr-xr-xfix-pcb.py160
1 files changed, 160 insertions, 0 deletions
diff --git a/fix-pcb.py b/fix-pcb.py
new file mode 100755
index 0000000..d04d7a5
--- /dev/null
+++ b/fix-pcb.py
@@ -0,0 +1,160 @@
+#!/usr/bin/python
+
+import sys
+import pcbnew
+
+
+def remove_tracks(board, layer):
+ """
+ The tracks on Layer four are actually where there *should not* be copper.
+ L4 is an inverted layer, but that information actually isn't in the files -
+ it is specified in an excel sheet sent to the PCB house.
+
+ By removing them and then setting some parameters carefully on the zones
+ on that layer, we get a close-to-perfect (but no longer inverted) result
+ in KiCAD.
+ """
+ for this in [x for x in board.GetTracks() if x.GetLayerName() == layer]:
+ print('Removing track {}'.format(this))
+ board.Delete(this)
+
+#def set_tracks_width(board, layer, width):
+# for this in [x for x in board.GetTracks() if x.GetLayerName() == layer]:
+# this.SetWidth(width)
+#
+#def move_tracks(board, from_layer, to_layer):
+# for this in [x for x in board.GetTracks() if x.GetLayerName() == from_layer]:
+# this.SetLayer(board.GetLayerID(to_layer))
+
+
+def hide_layers_except(board, layers):
+ """
+ As a convenience when working on getting a particular layer right, hide other layers.
+ """
+ lset = board.GetVisibleLayers()
+ print('Layer set: {} / {}'.format(lset, lset.FmtHex()))
+ #help(lset)
+ mask = 0
+ for x in lset.Seq():
+ name = board.GetLayerName(x)
+ print(' {} {}'.format(x, name))
+ if name in layers:
+ mask |= 1 << x
+ hexset = '{0:013x}'.format(mask)
+ visible_set = pcbnew.LSET()
+ visible_set.ParseHex(hexset, len(hexset))
+ board.SetVisibleLayers(visible_set)
+
+
+def layer_zone_fixes(board, layer, gnd_clearance=0.25):
+ for i in range(board.GetAreaCount()):
+ area = board.GetArea(i)
+ if area.GetLayerName() != layer:
+ continue
+ print('Area {} {}'.format(area, area.GetNetname()))
+ # This makes sharp edges matching Altium Designer
+ # 0.0255 is the minimum KiCad wants in order to allow changes to the zone inside KiCad
+ area.SetMinThickness(int(2 * 0.0255 * 1000000))
+ # 0.25 works better for the distance between zones in the bottom half of layer 4,
+ # but does not allow copper between the vias under the FPGA
+ #area.SetZoneClearance(int(0.25 * 1000000))
+ #
+ # Values below 0.15 or somewhere there does not seem to make a difference at all
+ area.SetZoneClearance(int(0.15 * 1000000))
+ if area.GetNetname() == 'GND':
+ area.SetPriority(50)
+ # 0.25 clearance on the 'background' GND zone keeps the distance to the island
+ # zones in the bottom half of layer 4, matching the clearance between the areas
+ # but creating a bit more clearance around vias in KiCAD plot than in Altium
+ area.SetZoneClearance(int(gnd_clearance * 1000000))
+ area.SetThermalReliefCopperBridge(int(0.5 * 1000000))
+ #help(area)
+
+
+def fix_layer_4(board):
+ """
+
+ Layer 4 is a layer with large polygons (GND and Power). In Altium, this was made
+ like an inverted layer with drawn lines separating polygons. Issues were with
+ line thickness in Kicad, clearance parameters preventing copper to flow in between
+ vias under the FPGA and the fact that KiCAD doesn't do inverted layers so the
+ lines had to be removed and zone clearances adjusted to create the same result.
+
+ Compare with
+
+ $ gerbv 'rev03-KiCad/GerberOutput/Cryptech Alpha-In4.Cu.gbr' /path/to/CrypTech.GP3
+ """
+ remove_tracks(board, 'In4.Cu')
+ #set_tracks_width(board, 'In4.Cu', int(0.15 * 1000000))
+ #move_tracks(board, 'In4.Cu', 'Eco2.User')
+ layer_zone_fixes(board, 'In4.Cu', gnd_clearance=0.25)
+
+
+def fix_layer_6(board):
+ """
+ Layer 6 has a GND polygon that needs a little less clearance in order to fill in between
+ the vias of the FPGA.
+
+ Compare with
+
+ $ gerbv 'rev03-KiCad/GerberOutput/Cryptech Alpha-In6.Cu.gbr' /path/to/CrypTech.GP4
+ """
+ layer_zone_fixes(board, 'In6.Cu', gnd_clearance=0.15)
+
+
+def fix_layer_bottom(board):
+ """
+ There is one small segment that ends up on Net 1 instead of GND (Net 7) for some reason:
+
+ #Tracks#3898: 200C000500FFFFFFFFFFFFFFFF41A799058A60450341A7990561AE4803E50106000000000000000000FFFF0001
+ - (segment (start 38.75 -74.875) (end 38.75 -75.425) (width 1) (layer B.Cu) (net 1))
+ + (segment (start 38.75 -74.875) (end 38.75 -75.425) (width 1) (layer B.Cu) (net 7))
+
+ I'm guessing the surrounding GND polygon somehow has priority in Altium so this small
+ bug is not visible there. This is a segment connected to one of the seven stiching vias
+ for the GND polygon under and to the right of U14 (bottom left one of the four grouped together).
+
+ The OSHW logo is lost, but I think we can live with that.
+
+ The copper print saying PCB rev.03 is messed up, but I don't think we can expect the fonts
+ to be similar in Altium and KiCAD anyways, so might as well just redo that.
+
+ Compare with
+
+ $ gerbv 'rev03-KiCad/GerberOutput/Cryptech Alpha-B.Cu.gbr' /path/to/CrypTech.GBL
+ """
+ for this in [x for x in board.GetTracks() if x.GetLayerName() == 'B.Cu']:
+ if tuple(this.GetStart()) == (38750000, -74875000):
+ print('Moving track to net GND: {}'.format(this))
+ this.SetNet(board.FindNet('GND'))
+
+ layer_zone_fixes(board, 'B.Cu', gnd_clearance=0.15)
+
+
+def main(in_fn='rev03-KiCad/convert.kicad_pcb', out_fn='rev03-KiCad/Cryptech Alpha.kicad_pcb'):
+ board = pcbnew.LoadBoard(in_fn)
+ pcbnew.SaveBoard(in_fn + '.before-fix-layer-4', board)
+
+ fix_layer_4(board)
+ fix_layer_6(board)
+ fix_layer_bottom(board)
+
+ hide_layers_except(board, ['B.Cu'])
+
+ # Only show Through Via while working on Layer 4
+ board.SetVisibleElements(0x7FFC0009)
+
+ pcbnew.SaveBoard(out_fn, board)
+ return True
+
+if __name__ == '__main__':
+ try:
+ if len(sys.argv) != 3:
+ sys.stderr.write('Syntax: fix-layer-4.py infile.kicad_pcb outfile.kicad_pcb\n')
+ sys.exit(1)
+ res = main(sys.argv[1], sys.argv[2])
+ if res:
+ sys.exit(0)
+ sys.exit(1)
+ except KeyboardInterrupt:
+ pass