文件
phonerail/kicad/scripts/fix_input_connector.py

80 行
3.7 KiB
Python

"""Rotate J1 by 180 degrees and place its mating face at the left board edge."""
import hashlib
import json
import shutil
import pcbnew as pcb
import route_local_r1 as base
from schematic_maintenance import ROOT
OUT = ROOT / 'out/input-connector-r1'
def snapshot(board):
return {f.GetReference(): (f.GetPosition().x, f.GetPosition().y, f.GetOrientationDegrees(),
f.GetLayer(), [(p.GetNumber(), p.GetPosition().x, p.GetPosition().y,
p.GetNetname()) for p in f.Pads()])
for f in board.GetFootprints()}
def copper(board):
return {t.m_Uuid.AsString(): (t.GetStart().x, t.GetStart().y, t.GetEnd().x, t.GetEnd().y,
t.GetLayer(), t.GetWidth(), t.GetNetname()) for t in board.GetTracks()}
def main():
assert not (OUT / 'verification.json').exists(), 'Completed checkpoint exists'
OUT.mkdir(parents=True, exist_ok=True)
base.OUT = OUT
path = base.BOARD
start_hash = hashlib.sha256(path.read_bytes()).hexdigest()
backup = OUT / ('before-' + path.name)
if backup.exists():
assert hashlib.sha256(backup.read_bytes()).hexdigest() == start_hash, 'Source changed since failed attempt'
else:
shutil.copy2(path, backup)
board = pcb.LoadBoard(str(path))
before, tracks = snapshot(board), copper(board)
initial = base.unconnected_count(board)
part = next(f for f in board.GetFootprints() if f.GetReference() == 'J1')
assert part.GetOrientationDegrees() == 90
assert not any(t.GetNetname() in {p.GetNetname() for p in part.Pads()} for t in board.GetTracks()), 'Review existing input copper first'
part.SetOrientationDegrees(270)
part.SetPosition(pcb.VECTOR2I(pcb.FromMM(58.4), pcb.FromMM(67)))
part.Reference().SetTextAngle(pcb.EDA_ANGLE(0, pcb.DEGREES_T))
part.Reference().SetPosition(pcb.VECTOR2I(pcb.FromMM(58.4), pcb.FromMM(59)))
candidate = path.with_name('PhoneRail-Board1-input-candidate.kicad_pcb')
temporary = [candidate.with_suffix(s) for s in ('.kicad_pcb', '.kicad_pro', '.kicad_dru', '.kicad_prl')]
assert all(not p.exists() for p in temporary)
try:
for suffix in ('.kicad_pro', '.kicad_dru'):
shutil.copy2(path.with_suffix(suffix), candidate.with_suffix(suffix))
pcb.SaveBoard(str(candidate), board)
report = base.drc(candidate, 'drc')
assert not report['violations'], report['violations']
reloaded = pcb.LoadBoard(str(candidate))
after = snapshot(reloaded)
assert all(value == after[ref] for ref, value in before.items() if ref != 'J1')
assert copper(reloaded) == tracks
assert base.unconnected_count(reloaded) == initial
assert sorted((p[0], p[3]) for p in before['J1'][4]) == sorted((p[0], p[3]) for p in after['J1'][4])
assert hashlib.sha256(path.read_bytes()).hexdigest() == start_hash
shutil.copy2(candidate, path)
result = {'status': 'PLACEMENT_CORRECTED_NOT_RELEASED', 'reference': 'J1',
'before_position_mm': [63, 67], 'after_position_mm': [58.4, 67],
'before_angle_deg': 90, 'after_angle_deg': 270,
'mating_face': 'Left/outward; nominal outline x=50.25041mm, board edge x=50mm',
'native_drc_violations': 0, 'other_footprints_preserved': len(before)-1,
'existing_track_segments_preserved': len(tracks), 'unconnected_items': initial,
'board_sha256': hashlib.sha256(path.read_bytes()).hexdigest()}
(OUT / 'verification.json').write_text(json.dumps(result, indent=2)+'\n', encoding='utf-8')
print(json.dumps(result))
finally:
for p in temporary:
p.unlink(missing_ok=True)
if __name__ == '__main__':
main()