// Sw2 Board Characterisation for SilRouteAid
//Interconnection Technology #596P55884A-Type 2 Stitchweld Board
//Last modified October 26, 1982 1:57 PM by TonyWest.PA

//The checking on cable connectors has become tighter, there are more GND and VCC pins
//WARNING: This module is close to the maximum size which the BCPL compiler can compile!

get "route.defs"

manifest
[
//User must fill in the parameters below
//All coordinates are in 25 mil grid units
//Under no circumstances delete any of the parameters listed

MAXics
=212//Maximum number of ICs allowed on the board
MaxYPinCoor
=416//Largest Y-coordinate (used for LevelTransform)

NumEPins
=200 //Number of E pins defined for the board
NumCPins
=87 //Number of C pins defined for the board
NumGNDPins
=401 //Number of GND pins defined for the board
NumVCCPins
=366//Number of VCC pins defined for the board
NumVDDPins
=206 //Number of VDD pins defined for the board
NumVEEPins
=206//Number of VEE pins defined for the board
NumICPins
=4262 //Number of IC pins (Non-trace wired pins) defined for the board

CconnsAreVertical
=true//True if cable connectors are vertical and false if horizontal
//Following coordinates are in X if vertical and Y if horizontal
CableMin
=0//The minimum coordinate a C pin may have
CableMax
=4//The maximum coordinate a C pin may have
EconnsAreVertical
=true//True if edge connectors are vertical and false if horizontal
EdgeMin
=496//The minimum coordinate an E pin may have
EdgeMax
=500//The maximum coordinate an E pin may have

Xorigin
=8 //The X-coor of column 1, row 1 of the pin table
Yorigin
=4 //The Y-coor of column 1, row 1 of the pin table

//Calibration points - these must be a rectangle
CalPt1x
=8//The X-coor of calibration point 1
CalPt1y
=4//The Y-coor of calibration point 1

CalPt2x
=500//The X-coor of calibration point 2
CalPt2y
=4//The Y-coor of calibration point 2

CalPt3x
=500//The X-coor of calibration point 3
CalPt3y
=408//The Y-coor of calibration point 3

CalPt4x
=8//The X-coor of calibration point 4
CalPt4y
=408//The Y-coor of calibration point 4

//End of User Parameters

]

//Check items in bold italic face to see if parameters are that which are desired

manifest
[
VCCPintype=1
VEEPintype=2
VDDPintype=3
GNDPintype=4
ICPintype=5

firstEPin=1//1
firstCPin=firstEPin+NumEPins//201
firstGNDPin=firstCPin+NumCPins//288
firstVCCPin=firstGNDPin+NumGNDPins//689
firstVDDPin=firstVCCPin+NumVCCPins//1055
firstVEEPin=firstVDDPin+NumVDDPins//1261
firstICPin=firstVEEPin+NumVEEPins//1467
maxpin=firstICPin+NumICPins//5729
]

static [ maxICs = MAXics ; boardInterfaceVersion = interfaceVersion ]

let DeclareInitialNets(BuildTWNet, BuildTermNet, BuildConnector) be
[
//if NumEPins ne 0 then
BuildConnector("E",NumEPins, EPinPos)
//if NumCPins ne 0 then
BuildConnector("C",NumCPins, CPinPos)
//if NumGNDPins ne 0 then
BuildTWNet("GND",NumGNDPins,GNDPinPos)
//if NumVCCPins ne 0 then
BuildTWNet("VCC",NumVCCPins,VCCPinPos)
//if NumVDDPins ne 0 then
BuildTWNet("VDD",NumVDDPins,VDDPinPos)
//if NumVEEPins ne 0 then
BuildTWNet("VEE",NumVEEPins,VEEPinPos)
]

and ZeroTablePoint(point) = selecton point into
[
case 0: "596P55884A"
case 1: "Z-1"
case 2: "Z-2"
case 3: "Z-3"
case 4: "Z-4"
default: empty
]

and LevelTransform(level,x,y,px,py,pName,pPullComponents,pWire,AD;numargs na)=valof
[
DefaultArgs(lv na,-1,0,0,lv na,lv na,lv na,lv na,lv na,false)
switchon level into
[
case TopLevel:
@px = y
@py=
x //if you wish to define the board from the component side, replace this with "@py=y"
@pName = "
Component side"
@pPullComponents =
true //pull components for any disconnects on this side
@pWire =
false
resultis true
case BottomLevel:
test AD
ifso
[ //do level transform for swapped coors
@px=y
@py=MaxYPinCoor-x
]
ifnot
[
@px = MaxYPinCoor-y
@py =
x //if you wish to define the board from the component side, replace this with "@py=MaxYPinCoor-y"
]
@pName = "
Wiring side"
@pPullComponents =
false
@pWire =
true
resultis true
default: resultis false
]
]

and EPinPos(icinst,pin,px,py)=valof
[
if pin gr NumEPins then [ SwatN("E-pin ",pin,0,0); resultis illegal ]

//if you wish to disable any E-pins, add the code:
//
"if pin eq Pnum1 % pin eq Pnum2 ... %pin eq PnumN then resultis illegal"
//replace Pnum1, Pnum2...PnumN with the N E-pin numbers you wish to disable.
//Note that you enter 101 if you wish to disable E101.

//Stop user from wiring to power connectors
if (((pin/10)*10) eq pin) then resultis illegal
switchon pin into
[
case 1:
case 51:
case 101:
case 151:resultis illegal
]

let res=FindConnPos(Econns,pin,px,py)
if res eq illegal then SwatN("E-pin ",pin,0,1)
resultis res
]

and CPinPos(icinst,pin,px,py)=valof
[
if pin gr NumCPins then [ SwatN("C-pin ",pin,0,0); resultis illegal ]

//if you wish to disable any C-pins, add the code:
//
"if pin eq Pnum1 % pin eq Pnum2 ... %pin eq PnumN then resultis illegal"
//replace Pnum1, Pnum2...PnumN with the N C-pin numbers you wish to disable.
//Note that you enter 101 if you wish to disable C101.

//There are two 37-way D-type connectors defined, with pins numbered 1-37 and 51-87
//if (pin gr 37) & (pin ls 51) then resultis illegal


let res=FindConnPos(Cconns,pin,px,py)
if res eq illegal then SwatN("C-pin ",pin,0,0)
resultis res
]

and FindConnPos(cv,pin,px,py)=valof
[
if cv>>Cspecs.NumOfSpecs eq 0 then resultis illegal
for i=1 to cv>>Cspecs.NumOfSpecs do
[ //look at each defined connector
let cp=Conns>>Cdescs.Num↑(cv>>Cspecs.ConnNum↑i) //points to connector descriptor
let MinCol1Num=cv>>Cspecs.Pin1Col1Num↑i
let NumsConsec=cp>>Cdesc.NumsConsec
let MaxCol1Num=MinCol1Num+((cp>>Cdesc.NumPinsCol1-1)*(NumsConsec ? 1,2)*(cp>>Cdesc.NumsDescending ? -1,1))
if cp>>Cdesc.NumsDescending then
[ //nums are descending, swap to get right
let swap=MaxCol1Num
MaxCol1Num=MinCol1Num
MinCol1Num=swap
]
if (pin ge MinCol1Num) & (pin le MaxCol1Num) & ((NumsConsec) % (((pin-MinCol1Num) rem 2) eq 0)) then
[ //pin is in this connector
@px=cv>>Cspecs.Xcoor↑i
@py=cv>>Cspecs.Ycoor↑i
let off=0
test cp>>Cdesc.NumsDescending
ifso [ off=(MaxCol1Num-pin)*cp>>Cdesc.DispBetPins ]
ifnot [ off=(pin-MinCol1Num)*cp>>Cdesc.DispBetPins ]
if not NumsConsec then off=off/2 //every other pin number
test cp>>Cdesc.ConnIsVert
ifso [ @py=@py+off ]
ifnot [ @px=@px+off ]
resultis absolute
] //end pin is in this connector
let MinCol2Num=cv>>Cspecs.Pin1Col2Num↑i
let MaxCol2Num=MinCol2Num+((cp>>Cdesc.NumPinsCol2-1)*(NumsConsec ? 1,2)*(cp>>Cdesc.NumsDescending ? -1,1))
if cp>>Cdesc.NumsDescending then
[ //nums are descending, swap to get right
let swap=MaxCol2Num
MaxCol2Num=MinCol2Num
MinCol2Num=swap
]
if (pin ge MinCol2Num) & (pin le MaxCol2Num) & ((NumsConsec) % (((pin-MinCol2Num) rem 2) eq 0)) then
[ //pin is in this connector
@px=cv>>Cspecs.Xcoor↑i
@py=cv>>Cspecs.Ycoor↑i
let off=0
test cp>>Cdesc.NumsDescending
ifso [ off=(MaxCol2Num-pin)*cp>>Cdesc.DispBetPins ]
ifnot [ off=(pin-MinCol2Num)*cp>>Cdesc.DispBetPins ]
if not NumsConsec then off=off/2 //every other pin number
off=off+(cp>>Cdesc.DispNeg ? -cp>>Cdesc.Disp4sec, cp>>Cdesc.Disp4sec)
test cp>>Cdesc.ConnIsVert
ifso [ @px=@px+cp>>Cdesc.DispBetRC; @py=@py+off ]
ifnot [ @py=@py+cp>>Cdesc.DispBetRC; @px=@px+off ]
resultis absolute
] //end pin is in this connector
] //end look at each defined connector
resultis illegal //pin not defined
] //end FindConnPos
//The following defines the parameters used to describe information associated with each trace-wired net:
//noDisconnect means a disconnection is not needed when using this pin as a signal pin. Use Disconnect if the opposite is desired
//noReconnect means on a rework, do not fix (ie. solder) a previously cut (disconnected) trace-wired pin, rather, go to the nearest existing pin of this type. Use Reconnect if the opposite is desired
//TopLevel means this trace wiring is on the side defined as TopLevel in LevelTransform...Usually the component side
//BottomLevel means this trace wiring is on the side defined as TopLevel in LevelTransform...Usually the component side

and VCCPinPos(icinst,pin,px,py,pInfo; numargs na) = valof
[
DefaultArgs(lv na, -4,lv na)
@pInfo =
Disconnect+noReconnect+TopLevel
if (pin le 0) % (pin gr NumVCCPins) then
[
SwatN("VCC pin",pin,0,0)
resultis illegal
]
GetXY4Pin(VCCPins,pin,VCCPintype,px,py)
resultis absolute
]

and VEEPinPos(icinst,pin,px,py,pInfo; numargs na) = valof
[
DefaultArgs(lv na, -4,lv na)
@pInfo =
noDisconnect+noReconnect+TopLevel
if (pin le 0) % (pin gr NumVEEPins) then
[
SwatN("VCC pin",pin,0,0)
resultis illegal
]
GetXY4Pin(VEEPins,pin,VEEPintype,px,py)
resultis absolute
]

and VDDPinPos(icinst,pin,px,py,pInfo; numargs na) = valof
[
DefaultArgs(lv na, -4,lv na)
@pInfo =
noDisconnect+noReconnect+TopLevel
if (pin le 0) % (pin gr NumVDDPins) then
[
SwatN("VDD pin",pin,0,0)
resultis illegal
]
GetXY4Pin(VDDPins,pin,VDDPintype,px,py)
resultis absolute
]

and GNDPinPos(icinst,pin,px,py,pInfo; numargs na) = valof
[
DefaultArgs(lv na, -4,lv na)
@pInfo =
Disconnect+noReconnect+BottomLevel
if (pin le 0) % (pin gr NumGNDPins) then
[
SwatN("VEE pin",pin,0,0)
resultis illegal
]
GetXY4Pin(GndPins,pin,GNDPintype,px,py)
resultis absolute
]

and BoardPinCoord(string,icinst,pinNo,px,py) = valof
[
let vop1,hop1 = nil,nil
let numpins = Npins(icinst)
switchon (Icclass(icinst)>>icclass.PinOffset)(icinst,pinNo,lv vop1,lv hop1) into
[
case absolute:
@px = vop1
@py = hop1
resultis true
case relative:
resultis (FindCoordFromString(string,px,py,vop1,hop1,numpins) eq absolute)
default: resultis false
]
]

and FindCoordFromString(s,px,py,vop1,hop1,numpins; numargs na) = valof
[
// vop1 is the "vertical offset" from pin 1, that is, the offset along the 0.1’
// spacing: hop1 is the :horizontal offset: from 1. In a standard 16-pin DIP,
// for pin 2 vop1=4 and hop1=0 and for pin 16, vop1=0 and hop1=12. For this
// board, vop1 grow in the -x direction hop1 in the +y direction.

// s can be of form <lower-case letter><number> or
// <number>s (meaning vertically offset <number>*0.1 or
// ↑<number>s (meaning vertically offset <number>*0.1) or
// ←<number>s (meaning horizontal offset <number>*0.1) or
// #s a special form "Z-s" is for ZeroTable point
// %s for insert IC upside down
DefaultArgs(lv na,3,0,0,20)
let zchar = s>>str.char↑1
let znum = s>>str.char↑3
if zchar eq $Z do
[
if znum eq $1 do [ @px= CalPt1x ; @py = CalPt1y ]
if znum eq $2 do [ @px= CalPt2x ; @py = CalPt2y ]
if znum eq $3 do [ @px = CalPt3x ; @py = CalPt3y ]
if znum eq $4 do [ @px = CalPt4x ; @py = CalPt4y ]
resultis absolute
]
let bpVOffset,bpHOffset = 0,0
let i,c,offsetIsVertical = 0,$#,nil
while i le s>>str.length & (c ls $a %c gr $z) do
[
if c eq $↑ % c eq $← % c eq $# % c eq $% then
[
offsetIsVertical = not(c eq $←)
//to disengage code to allow ICs to be inserted upside down, remove all code that is bold italic face

if c eq $% then
[ //code to insert IC upside down
vop1=numpins*2-4-vop1
hop1=((hop1 eq 0)?(numpins le 20?12,24),0)
]
i = i+1
c = s>>str.char↑i
loop
]
if (c ge $0) & (c le $9) then
[
let bpOffset = 0
while i le s>>str.length & c ge $0 & c le $9 do
[
bpOffset = 10*bpOffset+c-$0
i = i+1
c = s>>str.char↑i
]
@(offsetIsVertical? lv bpVOffset, lv bpHOffset) = bpOffset
offsetIsVertical = true
loop
]
resultis illegal
]

vop1 = vop1-4*bpVOffset //Vertical displacement currently in the -y direction...change sign to + if +y direction is desired

hop1 = hop1+4*bpHOffset //horizontal displacement is currently in the +x direction...change sign to - if -x direction is desired

// IC position of the form <letter><number>

if (i gr s>>str.length) % (c ls $a) % (c gr $z) then resultis illegal
let alph,num = c,0
while i ls s>>str.length do
[
i = i+1 ; let c = s>>str.char↑i
if (c ls $0)%(c gr $9) then resultis illegal
num = 10*num+(c-$0)
]

//change alpha to numeric
alph=alph-$a+1
if (alph gr NumDipRows) % (num ls 1) % (num gr NumDipCols) then resultis illegal

//find dip descriptor
let DescPtr=DipColVec>>DipCols.ColDescPtr↑num
let DipNum=DescPtr>>DipRow.DipDescNum↑alph
if DipNum eq 0 then resultis illegal //not a dip site
let DipPtr=DipDesc>>DipVec.DipDnum↑DipNum

//DipPtr points to the dip configurations at this site...see if this site allows the dip
//specified and if so, check the x-y offsets. If all is OK then stuff the coordinates
//in the x-y

let Ycoor=4*DescPtr>>DipRow.Ycoor↑alph //put in 25 mil grid coor
let Xcoor=2*DipColVec>>DipCols.Xcoor↑num

for i=1 to MaxDips do
[ //check for the number of pins allowed
if DipPtr>>DipDesc.NumPins↑i eq numpins then
[ //valid dip site for this number of pins
vop1=vop1+4*DipPtr>>DipDesc.Yoffset↑i
hop1=hop1+4*DipPtr>>DipDesc.Xoffset↑i
if (vop1 gr (DipPtr>>DipDesc.MaxYoffset*4)) % (vop1 ls 0) then resultis illegal
if (hop1 gr (DipPtr>>DipDesc.MaxXoffset*4)) % (hop1 ls 0) then resultis illegal
@px=Xcoor+hop1+Xorigin-2
@py=Ycoor+vop1+Yorigin-4
resultis absolute
]
]

//if we get this far, dip with numpins not allowed at this site
resultis illegal

]

and FindIndexFromCoord(x,y,picclass,pPinNo; numargs na) = valof
[
static [ hotIndex = -1; maxpin = 0]

DefaultArgs(lv na, -2,lv na , lv na)

if maxpin eq 0 then maxpin = FIFC(-1,-1)
let result = FIFC(x,y,picclass,pPinNo)
if result ls 0 % result gr maxpin then SwatN("index..",result,x,y)
if result eq hotIndex then CallSwat("Hot index computed...")
resultis result
]

and FIFC(x,y,picclass,pPinNo;numargs na) = valof
[
// Given coordinates x,y return pin index.
// picclass is set to the icclass describing the trace wire net
// and pPinNo is set to the number of the pin within the trace
// wire net.
if x eq -1 & y eq -1 then resultis maxpin
DefaultArgs(lv na, -2, lv na, lv na)
@picclass = empty

// Test for C connector
if (CconnsAreVertical & x le CableMax & x ge CableMin) % ((not CconnsAreVertical) & y le CableMax & y ge CableMin) then
[
resultis FIFC4conn(Cconns,x,y,firstCPin)
]

// Test for edge connector
if (EconnsAreVertical & x le EdgeMax & x ge EdgeMin) % ((not EconnsAreVertical) & y le EdgeMax & y ge EdgeMin) then
[
resultis FIFC4conn(Econns,x,y,firstEPin)
]

let dx=x-Xorigin
if (dx rem 2) ne 0 then resultis 0
dx=(dx/2)+1 //column number
let dy=y-Yorigin
if (dy rem 4) ne 0 then resultis 0
dy=(dy/4)+1 //row number

if dy le 0 % dx le 0 % dy gr NumPinRows % dx gr NumPinCols then resultis 0

let DescPtr=PinCols>>Cols.Cnum↑dx
if DescPtr eq 0 then resultis 0
if not GetBit(DescPtr,dy) then resultis 0

//count number of defined pins to this one in the column descriptor
let cnt=0
for i=1 to dy do
[
if GetBit(DescPtr,i) then cnt=cnt+1
]

let Ptype=DescPtr>>ColDesc.Ptype↑cnt
if Ptype ne ICPintype then
[ //trace wired pin
let Pnum=DescPtr>>ColDesc.Pnum↑cnt
let resultval=0
let ptr=0

switchon Ptype into
[
case VCCPintype:
[ @picclass=MustFindNamee("VCC",typeIcclass)
resultval=firstVCCPin
ptr=VCCPins
]; endcase
case VEEPintype:
[ @picclass=MustFindNamee("VEE",typeIcclass)
resultval=firstVEEPin
ptr=VEEPins
]; endcase
case VDDPintype:
[ @picclass=MustFindNamee("VDD",typeIcclass)
resultval=firstVDDPin
ptr=VDDPins
]; endcase
case GNDPintype:
[ @picclass=MustFindNamee("GND",typeIcclass)
resultval=firstGNDPin
ptr=GndPins
]; endcase
] //end cases
for j=1 to ptr>>PinCol.NumCols do
[ //add all prior pins to get pin # within class
if ptr>>PinCol.Cnum↑j eq dx then break
Pnum=Pnum+ptr>>PinCol.NumPins↑j
]
@pPinNo=Pnum

resultis (resultval+Pnum-1)
] //end tracewired pin
//IC pin
let Pnum=ICPins>>Cols.Cnum↑dx+DescPtr>>ColDesc.Poffset↑cnt
resultis firstICPin+Pnum-1
]

and FIFC4conn(cv,x,y,FirstPin)=valof
[
for i=1 to cv>>Cspecs.NumOfSpecs do
[ //check each defined connector
let cp=Conns>>Cdescs.Num↑(cv>>Cspecs.ConnNum↑i) //ptr to connector descriptor
let Ycoor=cv>>Cspecs.Ycoor↑i
let Xcoor=cv>>Cspecs.Xcoor↑i
if not cp>>Cdesc.ConnIsVert then
[ //conn is horizontal...swap coors so tests can be made with same code
let temp=x
x=y
y=temp
temp=Xcoor
Xcoor=Ycoor
Ycoor=temp
]
let DispBetPins=cp>>Cdesc.DispBetPins
if x eq Xcoor then
[ //maybe in column 1
let maxY=Ycoor+(DispBetPins*(cp>>Cdesc.NumPinsCol1-1))
if (y ge Ycoor) & (y le maxY) & (((y-Ycoor) rem DispBetPins) eq 0) then
[ //is in this conn
resultis FirstPin+cv>>Cspecs.Pin1Col1Num↑i+(((y-Ycoor)/DispBetPins) * (cp>>Cdesc.NumsConsec ? 1,2) * (cp>>Cdesc.NumsDescending ? -1,1))-1
]
loop //not in col 1 of this conn
] //end maybe in column 1
if x eq (Xcoor+cp>>Cdesc.DispBetRC) then
[ //maybe in column 2
Ycoor=Ycoor+(cp>>Cdesc.DispNeg ? -cp>>Cdesc.Disp4sec, cp>>Cdesc.Disp4sec)
let maxY=Ycoor+(DispBetPins*(cp>>Cdesc.NumPinsCol2-1))
if (y ge Ycoor) & (y le maxY) & (((y-Ycoor) rem DispBetPins) eq 0) then
[ //is in this conn
resultis FirstPin+cv>>Cspecs.Pin1Col2Num↑i+(((y-Ycoor)/DispBetPins) * (cp>>Cdesc.NumsConsec ? 1,2) * (cp>>Cdesc.NumsDescending ? -1,1))-1
]
//not in col 2 of this conn
] //end maybe in column 2
] //end check each defined connector
resultis 0 //not found
]

and GetXY4Pin(PinVec,PinNum,Pintype,px,py) be
[
let NumCols=PinVec>>PinCol.NumCols
let cnt=0
for i=1 to NumCols do
[
let oldcnt=cnt
cnt=cnt+PinVec>>PinCol.NumPins↑i
if (PinNum gr oldcnt) & (PinNum le cnt) then
[ //found column with this pin
let column=PinVec>>PinCol.Cnum↑i
let DescPtr=PinCols>>Cols.Cnum↑column
let typecnt=oldcnt
for j=1 to NumPinRows do
[ //find the pin
if Pintype eq DescPtr>>ColDesc.Ptype↑j then typecnt=typecnt+1
if (PinNum eq typecnt) then
[ //found the pin now determine the row
let row=0
let Icnt=0
until Icnt eq j do
[ //loop until we find the jth defined pin
row=row+1
if GetBit(DescPtr,row) then Icnt=Icnt+1
]
@px=(column*2)+Xorigin-2
@py=(row*4)+Yorigin-4
break
] //end found the pin now determine the row
] //end find the pin
break
] //end found column with this pin
] //end for i
] //end GetXY4Pin

and SwatN(f1,f2,f3,f4) be
[ let f5 = vec 40 ; f5>>str.length = 0
AppndS(f5,"Illegal "); AppndS(f5,f1) ; AppndN(f5,f2) ; AppndS(f5," ")
AppndN(f5,f3) ; AppndS(f5," ") ; AppndN(f5,f4)
CallSwat(f5)
]

and AppndS(f1,f2) be
[ let i,j=1,f1>>str.length+1
while i le f2>>str.length do [ f1>>str.char↑j = f2>>str.char↑i ; i = i+1 ; j = j+1 ]
f1>>str.length = j-1
]

and AppndN(f1,f2) be
[ let i,j,m=f1>>str.length+1,nil,10000
for j = 1 to 5 do
[ f1>>str.char↑i = f2/m +$0 ; i = i+1 ; f2 = f2-(f2/m)*m
m=m/10
]
f1>>str.length = i-1
]