from pathlib import Path
import csv,json,hashlib,xml.etree.ElementTree as E
import wx,pcbnew
app=wx.App(False);quiet=wx.LogNull()
p=Path(__file__).resolve().parent;b=p.parent;root=b.parent.parent
cam=root/'work/camera_evb_a0-metadata-sync-candidate.nosync/camera_evb_a0.kicad_pcb'
# Locate the workspace independently of invocation cwd.
workspace=b.parents[1]
cam=workspace/'work/camera_evb_a0-metadata-sync-candidate.nosync/camera_evb_a0.kicad_pcb'
table=workspace/'work/ai-display-interface-decision-2026-10-09.nosync/Core1106-RGB666-112pad-pinmap-v0.1.csv'
rows=list(csv.DictReader(table.open()))
r=E.parse(p/'camera-current.xml').getroot();power=E.parse(p/'power-current.xml').getroot()
def nets(r):
 d={}
 for n in r.findall('./nets/net'):
  for node in n.findall('node'):d[(node.get('ref'),node.get('pin'))]=n.get('name').lstrip('/')
 return d
cn=nets(r);pn=nets(power)
lp=next(x for x in r.findall('./libparts/libpart') if x.get('part')=='Core1106')
pins={x.get('num'):x.get('name') for x in lp.findall('./pins/pin')}
board=pcbnew.LoadBoard(str(cam));u=next(f for f in board.GetFootprints() if f.GetReference()=='U1');pads={x.GetNumber():x for x in u.Pads()}
assert len(rows)==22 and {int(x['module_pad']) for x in rows}==set(range(90,112))
for x in rows:
 pad=x['module_pad'];name=pins[pad]
 assert x['module_signal'] in name.split('/') and x['soc_lcdc_function'] in name.split('/')
 net=cn['U1',pad];bp=pads[pad];bn=bp.GetNetname().lstrip('/')
 assert net.startswith('unconnected-') and (bn==net or bn=='')
 x['saved_schematic_net']=net;x['saved_pcb_net']=bn;x['status']='EXPLICIT_NC_DISPLAY_NOT_IMPLEMENTED'
 x['direct_copper_objects']=sum(1 for t in board.GetTracks() if bp.GetNetCode()!=0 and t.GetNetCode()==bp.GetNetCode())
 assert x['direct_copper_objects']==0
with (p/'current-display-pad-audit.csv').open('w',newline='') as f:
 w=csv.DictWriter(f,fieldnames=list(rows[0]));w.writeheader();w.writerows(rows)
assert pn['J4','1']=='SYS_5V0_ALWAYS_ON' and pn['J4','2']=='GND'
assert cn['J3','1']=='VCC5V0_SYS_IN' and cn['J3','2']=='GND'
assert pn['J3','1']=='VLED_GUARDED'
assert cn['U1','16']=='CAM_I2C4_SCL_1V8' and cn['U1','17']=='CAM_I2C4_SDA_1V8'
report={'status':'AUDIT_PASS_DISPLAY_IMPLEMENTATION_MISSING','display_pads_checked':22,'display_pads_explicit_NC':22,'display_tracks':0,'camera_i2c_physical_pads':[16,17],'rgb_data8_9_physical_pads':[102,103],'physical_pin_collision':False,'pinmux_modes_not_verified':True,'power_harness':{'source':'A70 J4','sink':'camera EVB J3','pin1_source':'SYS_5V0_ALWAYS_ON','pin1_sink':'VCC5V0_SYS_IN','pin2':'GND','voltage_current_physical_validation':False},'manufacturing_release':False}
report['source_sha256']={str(x):hashlib.sha256(x.read_bytes()).hexdigest() for x in [cam,table,p/'camera-current.xml',p/'power-current.xml']}
(p/'audit.json').write_text(json.dumps(report,indent=2)+'\n');print(json.dumps({k:v for k,v in report.items() if k!='source_sha256'}))
