master
John Lauer Add Fusion 24-net crossover routing, shared vias, and captioned demo b3f148d 1mo ago
"""Calculate Fusion's 24-net crossover from the requested permutation, no router."""
import copy
import json
from pathlib import Path
import xml.etree.ElementTree as E
ROOT=Path(__file__).resolve().parent

def make():
    root=E.Element('eagle',version='9.6.2');drawing=E.SubElement(root,'drawing')
    E.SubElement(drawing,'settings')
    E.SubElement(drawing,'grid',distance='0.1',unitdist='mm',unit='mm',style='lines',multiple='1',display='no',altdistance='0.01',altunitdist='mm',altunit='mm')
    layers=E.parse(ROOT.parents[2]/'examples/ADS8588SIPM.fusion.lbr').find('drawing/layers')
    drawing.append(copy.deepcopy(layers));board=E.SubElement(drawing,'board');plain=E.SubElement(board,'plain')
    corners=[(38,24),(132,24),(132,133),(38,133)]
    for a,b in zip(corners,corners[1:]+corners[:1]):
        E.SubElement(plain,'wire',x1=str(a[0]),y1=str(a[1]),x2=str(b[0]),y2=str(b[1]),width='0',layer='20')
    def label(text,x,y,size=1.3):E.SubElement(plain,'text',x=str(x),y=str(y),size=str(size),layer='21').text=text
    label('ADOM / 24-NET CROSSOVER',48,129,2)
    label('ASTRA > ADOM BRIDGE > FUSION',49,26,1.3)
    label('24 NETS / 72 PADS / 2 LAYERS',63,118,1.3)
    libs=E.SubElement(board,'libraries');lib=E.SubElement(libs,'library',name='FusionCrossbarFixture');pkgs=E.SubElement(lib,'packages')
    elements=E.SubElement(board,'elements');signals=E.SubElement(board,'signals')
    packages={}
    for ref in ['J1','J2','J3']:
        packages[ref]=E.SubElement(pkgs,'package',name=ref)
        E.SubElement(elements,'element',name=ref,library='FusionCrossbarFixture',package=ref,value='CROSSBAR_TEST',x='0',y='0')
    plans=[]
    for i in range(24):
        j=7*i%24;x=round(65+j*2.54,6);y=round(52+i*2.54,6);net=f'CH_{i+1:02d}'
        pads=[('J1',i+1,45,y),('J2',j+1,x,35),('J3',j+1,x,125)]
        signal=E.SubElement(signals,'signal',name=net)
        for ref,n,px,py in pads:
            attrs={'name':str(n),'x':str(px),'y':str(py)}
            if ref=='J3':E.SubElement(packages[ref],'pad',**attrs,drill='0.8',diameter='1.5',shape='round')
            else:E.SubElement(packages[ref],'smd',**attrs,dx='1.5',dy='1.5',layer='1',roundness='20')
            E.SubElement(signal,'contactref',element=ref,pad=str(n))
        plans.append({'net':net,'layer':1,'width':.3,'viaDiameter':.6,'viaDrill':.3,'paths':[
            [{'pad':f'J1.{i+1}'},[55,y],{'x':x,'y':y,'layer':16},{'x':x,'y':42,'layer':1},{'pad':f'J2.{j+1}'}],
            [{'x':x,'y':y,'layer':16},{'pad':f'J3.{j+1}'}]]})
    # EAGLE child order is significant; put rules/classes before elements/signals.
    board.remove(elements);board.remove(signals)
    E.SubElement(board,'attributes');E.SubElement(board,'variantdefs')
    E.SubElement(E.SubElement(board,'classes'),'class',number='0',name='default',width='.3',drill='.3')
    rules=E.SubElement(board,'designrules',name='FusionCrossbarFixture')
    for name,value in {'layerSetup':'(1*16)','mdWireWire':'0.2mm','mdWirePad':'0.2mm','mdWireVia':'0.2mm','msWidth':'0.2mm','msDrill':'0.3mm','mdCopperDimension':'0.5mm'}.items():E.SubElement(rules,'param',name=name,value=value)
    board.append(elements);board.append(signals);E.indent(root)
    (ROOT/'fusion-crossbar-24.brd').write_text('<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE eagle SYSTEM "eagle.dtd">\n'+E.tostring(root,encoding='unicode'))
    (ROOT/'plan.json').write_text(json.dumps(plans,indent=2)+'\n')
    return board,plans
if __name__=='__main__':
    b,p=make();print('Calculated 24 nets, 72 pads: j=(7*i) mod 24')