|
| 1 | + |
| 2 | +import json |
| 3 | +import re |
| 4 | +import math |
| 5 | +from pathlib import Path |
| 6 | +import sys |
| 7 | + |
| 8 | +# Setup paths to use the project's internal parser |
| 9 | +PROJECT_ROOT = Path('/home/mario/Documents/GitHub/KB_PLATE_VALIDATOR') |
| 10 | +sys.path.append(str(PROJECT_ROOT)) |
| 11 | +from scripts.build_plate import parse_kle, U1 |
| 12 | + |
| 13 | +# The KLE layout provided by the user |
| 14 | +kle_text = [ |
| 15 | + ["~\n`","!\n1","@\n2","#\n3","$\n4","%\n5","^\n6","&\n7","*\n8","(\n9",")\n0","_\n-","+\n=",{"w":2},"Backspace"], |
| 16 | + [{"w":1.5},"Tab","Q","W","E","R","T","Y","U","I","O","P","{\n[","}\n]",{"w":1.5},"|\n\\"], |
| 17 | + [{"w":1.75},"Caps Lock","A","S","D","F","G","H","J","K","L",":\n;","\"\n'",{"w":2.25},"Enter"], |
| 18 | + [{"w":2},"Shift","Z","X","C","V","B","N","M","<\n,",">\n.","?\n/","Del","Up","Home"], |
| 19 | + [{"w":1.25},"Ctrl",{"w":1.25},"Win",{"w":1.25},"Alt",{"a":7,"w":6.25},"","Alt","Ctrl","Left","Down","Right"] |
| 20 | +] |
| 21 | + |
| 22 | +keys, w_mm, h_mm = parse_kle(kle_text) |
| 23 | + |
| 24 | +# KiCad v6+ S-expression template |
| 25 | +pcb_content = [ |
| 26 | + '(kicad_pcb (version 20211014) (generator pcbnew)', |
| 27 | + ' (general (thickness 1.6))', |
| 28 | + ' (setup (stackup (layer "F.Cu" (type "copper") (thickness 0.035)) (layer "F.Paste" (type "solderpaste"))))', |
| 29 | + ' (layers (0 "F.Cu" signal) (31 "B.Cu" signal) (44 "Edge.Cuts" user))', |
| 30 | + '' |
| 31 | +] |
| 32 | + |
| 33 | +# Add footprints |
| 34 | +for i, k in enumerate(keys): |
| 35 | + # KLE parser returns coordinates relative to top-left of the board |
| 36 | + # In KiCad, we'll place them exactly there. |
| 37 | + x, y = k['cx_u'] * U1, k['cy_u'] * U1 |
| 38 | + |
| 39 | + # We use the naming pattern 'SW_MX' which the validator regex looks for |
| 40 | + fp = f' (footprint "Button_Switch_Keyboard:SW_MX_1.00u" (layer "F.Cu") (at {x:.4f} {y:.4f})\n' |
| 41 | + fp += f' (tstamp {i:08x}-0000-0000-0000-000000000000)\n' |
| 42 | + fp += ' )' |
| 43 | + pcb_content.append(fp) |
| 44 | + |
| 45 | +# Add a simple rectangle outline on Edge.Cuts |
| 46 | +pad = 2.0 |
| 47 | +outline = [ |
| 48 | + f' (gr_line (start {-pad} {-pad}) (end {w_mm+pad} {-pad}) (layer "Edge.Cuts") (width 0.1))', |
| 49 | + f' (gr_line (start {w_mm+pad} {-pad}) (end {w_mm+pad} {h_mm+pad}) (layer "Edge.Cuts") (width 0.1))', |
| 50 | + f' (gr_line (start {w_mm+pad} {h_mm+pad}) (end {-pad} {h_mm+pad}) (layer "Edge.Cuts") (width 0.1))', |
| 51 | + f' (gr_line (start {-pad} {h_mm+pad}) (end {-pad} {-pad}) (layer "Edge.Cuts") (width 0.1))' |
| 52 | +] |
| 53 | +pcb_content.extend(outline) |
| 54 | +pcb_content.append(')') |
| 55 | + |
| 56 | +output_path = PROJECT_ROOT / 'custom_65.kicad_pcb' |
| 57 | +output_path.write_text('\n'.join(pcb_content)) |
| 58 | +print(f"PCB generated at: {output_path}") |
| 59 | +print(f"Stats: {len(keys)} keys, Dimensions: {w_mm:.2f} x {h_mm:.2f} mm") |
0 commit comments