// RouteUniversal.bcpl
// Route characterization for a board of infinite extent
//  in which all IC locations are non-overlapping.
// Useful for producing node lists for transport to foreign systems.

// Last modified April 13, 1983  5:14 PM by Boggs

get "route.defs"

static
[
maxICs = 500
boardInterfaceVersioon = interfaceVersion

lq
nextX = 0; minX; maxX
nextY = 64; minY; maxY
]

//-----------------------------------------------------------------------------------------
let ZeroTablePoint(point) = selecton point into
//-----------------------------------------------------------------------------------------
   [
   case 0: "Universal"
   case 1: "#TopLeft"
   case 2: "#TopRight"
   case 3: "#BottomRight"
   case 4: "#BottomLeft"
   default: "#?"
   ]

//-----------------------------------------------------------------------------------------
and LevelTransform(level, x, y, pX, pY, pName, pPullComponents, pWire; numargs na) = valof
//-----------------------------------------------------------------------------------------
[
DefaultArgs(lv na, -1, 0, 0, lv na, lv na, lv na, lv na, lv na)
switchon level into
   [
   case TopLevel:
      [
      @pX, @pY = x, y
      @pName = "component side"
      @pPullComponents = true
      @pWire = false
      resultis true
      ]
   case BottomLevel:
      [
      @pX, @pY = x, y
      @pName = "wiring side"
      @pPullComponents = false
      @pWire = true
      resultis true
      ]
   default: resultis false
   ]
]

//-----------------------------------------------------------------------------------------
and DeclareInitialNets(BuildTWNet, BuildTermNet, BuildConnector) be
//-----------------------------------------------------------------------------------------
[
BuildConnector("E", 1000, EPinPos)
BuildConnector("C", 1000, CPinPos)
]

//-----------------------------------------------------------------------------------------
and EPinPos(icinst, pin, pX, pY, pInfo; numargs na) = valof
//-----------------------------------------------------------------------------------------
[
DefaultArgs(lv na, -4, lv na)
@pInfo = noDisconnect+noReconnect+BottomLevel
@pX = (pin & 177b) lshift 2
@pY = (pin & not 177b) rshift 5
resultis absolute
]

//-----------------------------------------------------------------------------------------
and CPinPos(icinst, pin, pX, pY, pInfo; numargs na) = valof
//-----------------------------------------------------------------------------------------
[
DefaultArgs(lv na, -4, lv na)
@pInfo = noDisconnect+noReconnect+BottomLevel
@pX = (pin & 177b) lshift 2
@pY = (pin & not 177b) rshift 5 + 32
resultis absolute
]

//-----------------------------------------------------------------------------------------
and BoardPinCoord(string, icinst, pinNo, pX, pY) = valof
//-----------------------------------------------------------------------------------------
[
structure String [ length byte; char↑1,1 byte ]
structure Loc:
   [
   link word
   x word
   y word
   @String
   ]
manifest lenLoc = size Loc/16

let vop, hop = nil, nil
switchon (Icclass(icinst)>>icclass.PinOffset)(icinst, pinNo, lv vop, lv hop) into
   [
   case absolute: [ @pX, @pY = vop, hop; resultis true ]
   case relative:
      [
      let loc = lq; while loc ne 0 do
         [
         let found = loc>>Loc.length eq string>>String.length
         if found then for i = 1 to loc>>Loc.length do
            if loc>>Loc.char↑i ne string>>String.char↑i then [ found = false; break ]
         if found break
         loc = loc>>Loc.link
         ]
      if loc eq 0 then
         [
         loc = Allocate(SilZone, string>>String.length lshift 1 +lenLoc)
         loc>>Loc.length = string>>String.length
         for i = 1 to loc>>Loc.length do loc>>Loc.char↑i = string>>String.char↑i
         minX, maxX = 0, 0
         for pin = 1 to Npins(icinst) do
            [
            let xOff, yOff = nil, nil
            (Icclass(icinst)>>icclass.PinOffset)(icinst, pin, lv yOff, lv xOff)
            if xOff ls minX then minX = xOff
            if xOff gr maxX then maxX = xOff
            if yOff ls minY then minY = yOff
            if yOff gr maxY then maxY = yOff
            ]
         loc>>Loc.y = nextY
         loc>>Loc.x = nextX - minX
         nextX = nextX + maxX - minX +4
         if nextX gr 900 then	//"carriage return" to avoid coordiantes > 1023
            [
            nextX = 0
            nextY = nextY + maxY - minY +4
            minY, maxY = 0, 0
            ]
         loc>>Loc.link = lq; lq = loc
         ]
      @pY = loc>>Loc.y + vop
      @pX = loc>>Loc.x + hop
      resultis true
      ]
   default: resultis false
   ]
]

//-----------------------------------------------------------------------------------------
and FindIndexFromCoord(x, y, pIcclass, pPinNo; numargs na) = 1
//-----------------------------------------------------------------------------------------

//-----------------------------------------------------------------------------------------
and FindCoordFromString(string, pX, pY, vop, hop; numargs na) = valof
//-----------------------------------------------------------------------------------------
[
DefaultArgs(lv na, -3, 0, 0)
@pX, @pY = hop, vop
resultis absolute
]