// ResistInit.bcpl

// Last modified by McCreight June 25, 1984  10:33 AM

get "Resist.decl"
get "Streams.d"
get "AltoDefs.d"
get "SysDefs.d"
get "AltoFileSys.d"

external
[
// outgoing procedures
InitResist

// incoming procedures
OhmsCodeTable
PermAllocate; InitDisplay1; InitDisplay2; FlashWindow
ExpandTemplate; ReportError; Confirm; InitState
CalibrateOhms; SignalOn; TesterInterrupt
LoadRam; InitBcplRuntime; ResistFinish
InitializeInterrupt; FindInterruptMask
SetupReadParam; ReadParam; EvalParam
ConcatenateStrings; ExtractSubstring; StringCompare
WRITEUDT
OpenFile; GetCompleteFa; TruncateDiskStream
Allocate; Free; InitializeZone; AddToZone
PutTemplate; Ws; Wss; Gets; Puts; Resets; Endofs; Closes
Usc; SysErr; CallSwat; MyFrame

// incoming statics
ohmsCodeTab
RamImage
permZone; version; serialNumber; errorTolerance; endInitCode
resStream; exStream; wlStream; outStream; stateStream
resName; outName; mustRename; startLocation
maxNPins; resistSavedUFP; displayInterruptMask; stuffed; restart
sysZone; lvSysZone; dsp; keys; UserName; fpComCm; lvUserFinishProc
stateCFA; outCFA; OsVersion
]

// ---------------------------------------------------------------------------
let InitResist() be
// ---------------------------------------------------------------------------
[
if OsVersion ls 17 then CallSwat("OS version 17 or newer is required")
if LoadRam(RamImage) eq 0 then InitBcplRuntime()
@#335 = LoadRam
endInitCode = LoadRam

manifest stackNeeds = 1200
let freeLen = FixedLeft() - stackNeeds
if Usc(freeLen, 77776B) gr 0 then freeLen = 77776B
sysZone = InitializeZone(GetFixed(freeLen), freeLen, SysErr, 0)
@lvSysZone = sysZone
freeLen = FixedLeft() - stackNeeds
if freeLen gr 20 then AddToZone(sysZone, GetFixed(freeLen), freeLen)

permZone = Allocate(sysZone, lenPermZone)
permZone>>PermZone.Allocate = PermAllocate
permZone>>PermZone.Free = SysErr
permZone>>PermZone.underlyingZone = sysZone
permZone>>PermZone.wordsLeft = 0
permZone>>PermZone.threshold = permThreshold

SignalOn(false)
displayInterruptMask = InitializeInterrupt(Allocate(sysZone, 50), 50,
 FindInterruptMask(200B), TesterInterrupt)
@displayInterrupt = @displayInterrupt % displayInterruptMask
@resistSavedUFP = @lvUserFinishProc
@lvUserFinishProc = ResistFinish

InitDisplay1()
PutTemplate(dsp, "*n$S", version)
ohmsCodeTab = OhmsCodeTable()

   [ // repeat
   let calOhms = CalibrateOhms()
   if calOhms le 50+unstuffedErrorTolerance &
    calOhms ge 50-unstuffedErrorTolerance break
   Ws("*nOhmmeter calibration failed:")
   PutTemplate(dsp, "*n50-ohm resistor measured value was $D ohms", calOhms)
   Ws("*nType C to continue, R to retry, A to abort.")
   FlashWindow(dsp)
   switchon Gets(keys) into
      [
      case $C: case $c: break
      case $A: case $a: abort
      ]
   Resets(dsp)
   ] repeat

let stringVec = Allocate(sysZone, 256)
let switchVec = stringVec+128
SetupReadParam(stringVec, switchVec)
for i = 1 to switchVec!0 do
   switchon switchVec!i into
      [
      case $S: case $s:
         stuffed = true; endcase
      case $U: case $u:
         stuffed = false; endcase
      case $R: case $r:
         restart = true; endcase
      default:
         ReportError("Undefined global switch /$C", switchVec!i)
      ]

let fileName = vec 20

   [ // repeat
   if ReadParam(0, 0, 0, 0, true) eq -1 then break
   if restart then
      [ ReportError("Illegal to give parameters during restart"); abort ]
   switchon switchVec!0 into
      [
      case 0:
         if resStream ne 0 then
            [ ReportError("More than one input file."); abort ]
         resStream = EvalParam(stringVec, $I, "Input file: ", fileName)
         endcase
      case 1:
         switchon switchVec!1 into
            [
            case $L: case $l:
               startLocation = Allocate(sysZone, stringVec!0 rshift 1 +1)
               EvalParam(stringVec, $P, 0, startLocation)
               endcase
            case $T: case $t:
               errorTolerance = EvalParam(stringVec, $D,
                "Error tolerance (percent): ")
               endcase
            case $S: case $s:
               serialNumber = EvalParam(stringVec, $D,
                "Board serial number: ")
               endcase
            case $P: case $p:
               maxNPins = EvalParam(stringVec, $D,
                "Maximum number of pins per IC: ")
               endcase
            default:
               ReportError("Incorrect local switch: $US/$US",
                stringVec, switchVec)
               abort
            ]
         endcase
      case 2:
         ReportError("Too many local switches: $US/$US",
          stringVec, switchVec)
         abort
      ]
   ] repeat

test restart
   ifso
      [
      InitState(true)
      resStream = OpenFile(resName, ksTypeReadOnly, charItem)
      ]
   ifnot
      [
      while resStream eq 0 do
         [  // Careful: ReadParam($I, ...) causes stack overflow
         ReadParam($P, "Resist file name: ", fileName)
         resStream = OpenFile(fileName, ksTypeReadOnly, charItem)
         ]
      resName = ExtractSubstring(fileName)
      ]

let len = resName>>String.length
for i = 1 to len do
   if resName>>String.char↑i eq $. then len = i-1
let iSN = 0
for i = 1 to len do
   if resName>>String.char↑i eq $- & i le len-3 &
    StringCompare(resName, "-SN-", i, i+3) eq 0 then iSN = i+4
if iSN ne 0 then
   [
   let sn = 0
   for i = iSN to len do
      [
      let digit = resName>>String.char↑i - $0
      if digit ls 0 % digit gr 9 then
         [
         if resName>>String.char↑i eq $- & i eq len-1 then
            switchon resName>>String.char↑len into
               [
               case $S: case $s:
                  stuffed = true; break
               case $U: case $u:
                  stuffed = false; break
               ]
         ReportError("Input file name has incorrect syntax."); abort
         ]
      sn = 10*sn + digit
      ]
   if serialNumber ne 0 & sn ne serialNumber then
      [ ReportError("Input file has wrong serial number."); abort ]
   serialNumber = sn
   len = iSN-5
   ]

let wlName = ConcatenateStrings(
 ExtractSubstring(resName, 1, len), ".wl", true)
wlStream = OpenFile(wlName, ksTypeReadOnly, charItem)
if wlStream eq 0 then
   [ ReportError("Can't open wire list file $S.", wlName); abort ]
Free(sysZone, wlName)

if serialNumber eq 0 then
   serialNumber = ReadParam($D, "Board serial number: ")

if stuffed eq 1 then
   [ Ws("*nIs the board stuffed?"); stuffed = Confirm() ]

if errorTolerance eq 0 then
   errorTolerance = stuffed? stuffedErrorTolerance, unstuffedErrorTolerance

// **** All parameters to be saved in the state file must have been collected
// **** by this point.
unless restart do InitState(false)

Free(sysZone, stringVec)
InitDisplay2()

let exName = ConcatenateStrings(ExtractSubstring(resName, 1, len),
 (stuffed? "-S.exceptions", "-U.exceptions"), true)
exStream = OpenFile(exName, ksTypeReadOnly, charItem)
Free(sysZone, exName)

outName = ConcatenateStrings(
 ExtractSubstring(resName, 1, len),
 ExpandTemplate("-SN-$4F0D-$C.defects", serialNumber, (stuffed? $S, $U)),
 true, true)
mustRename = StringCompare(resName, outName) eq 0
outStream = OpenFile((mustRename? "Resist.temp$", outName),
 ksTypeWriteOnly, charItem)

PutTemplate(dsp, "*n$S ← $S", outName, resName)
PutTemplate(outStream, "; $S ← $S*n", outName, resName)
PutTemplate(outStream, "; $S board tested by $S at $P.*n",
 (stuffed? "Stuffed", "Unstuffed"), UserName, WRITEUDT, 0)
PutTemplate(outStream, "; $S*n", version)
PutTemplate(outStream, "; Error tolerance is $D percent.*n", errorTolerance)
let comCmStream = OpenFile("Com.cm", ksTypeReadOnly, charItem, 0, fpComCm)
if comCmStream ne 0 then
   [
   Wss(outStream, "; ")
   until Endofs(comCmStream) do Puts(outStream, Gets(comCmStream))
   Closes(comCmStream)
   Puts(outStream, $*n)
   ]
Free(sysZone, resName)

stateCFA = Allocate(sysZone, lCFA)
GetCompleteFa(stateStream, stateCFA)
unless restart do TruncateDiskStream(stateStream)
Closes(stateStream)

outCFA = Allocate(sysZone, lCFA)
GetCompleteFa(outStream, outCFA)
Wss(outStream, "*n; Test interrupted -- this file is not valid.*n")
Closes(outStream)
]

// ---------------------------------------------------------------------------
and GetFixed(nWords) = valof
// ---------------------------------------------------------------------------
[
let result = @#335
@#335 = @#335 + nWords
resultis result
]

// ---------------------------------------------------------------------------
and FixedLeft() = MyFrame() - @#335
// ---------------------------------------------------------------------------