// ResistMeasure.bcpl -- board tester hardware operation

// Last modified July 7, 1980  6:21 PM

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

external
[
// outgoing procedures
MeasureOhms; CalibrateOhms; PulseChannel; Wait; SignalOn; TesterInterrupt

// incoming procedures

// incoming statics
OsBuffer
]

static
[
ohmsOffset; ohmsScale; testerOut; ticks
signalOn = false
signalState = false
signalTimer = 0
lastSwitchState = 1
signalOnInterval = 3  // times 17 milliseconds
signalOffInterval = 20
]

// ---------------------------------------------------------------------------
let MeasureOhms(channel) = valof
// ---------------------------------------------------------------------------
// Returns the resistance for channel in ohms.
// Returns the special value "open" if off-scale.
[
let dac = SampleChannel(channel)
resultis dac eq 255? open, ohmsOffset + (128*dac)/ohmsScale
]

// ---------------------------------------------------------------------------
and CalibrateOhms() = valof
// ---------------------------------------------------------------------------
// Calibrates the ohmmeter using the built-in 0- and 100-ohm resistors, and
// then returns the result of measuring the 50-ohm resistor.
[
let sample0 = SampleChannel(chanCal0)
let sample100 = SampleChannel(chanCal100)
ohmsScale = (128*(sample100-sample0))/100
ohmsOffset = -(128*sample0)/ohmsScale
resultis MeasureOhms(chanCal50)
]

// ---------------------------------------------------------------------------
and SampleChannel(channel) = valof
// ---------------------------------------------------------------------------
[
testerOut<<TesterOut.channel = channel
let dac = 128
let delta = 64

   [ // repeat
   testerOut<<TesterOut.dac = dac
   @utilOut = not testerOut  // output bits are inverted
   for i = 1 to 10 do loop  // 100 microseconds or so
   test (@utilIn)<<TesterIn.comparator ne 0
      ifso dac = dac - delta
      ifnot dac = dac + delta
   delta = delta rshift 1
   ] repeatuntil delta eq 0

resultis dac
]

// ---------------------------------------------------------------------------
and PulseChannel(channel, time) be
// ---------------------------------------------------------------------------
// Sends high-frequency pulses out channel for specified time (17 ms units).
// At the end, leaves channel deselected (precisely, leaves the 0-ohm
// calibration channel selected instead).
// This is to aid use of an external current tracer.
[
testerOut<<TesterOut.dac = 128  // any constant value
let endTime = ticks+time
let chan = chanCal0
until ticks-endTime gr 0 & chan eq chanCal0 do
   [
   chan = chan eq chanCal0? channel, chanCal0
   testerOut<<TesterOut.channel = chan
   @utilOut = not testerOut  // output bits are inverted
   ]
]

// ---------------------------------------------------------------------------
and Wait(time) be
// ---------------------------------------------------------------------------
// Busy-waits for time*17 ms.
[
let endTime = ticks+time
until ticks-endTime gr 0 do loop
]

// ---------------------------------------------------------------------------
and SignalOn(value) be
// ---------------------------------------------------------------------------
// Turns on or off the audible signal
[
if value ne signalOn then
   [
   signalOn = value
   signalTimer = 1
   ]
]

// ---------------------------------------------------------------------------
and TesterInterrupt() be
// ---------------------------------------------------------------------------
[
ticks = ticks+1
if signalTimer gr 0 then
   [
   signalTimer = signalTimer-1
   if signalTimer eq 0 then
      test signalOn
         ifso
            [
            signalState = not signalState
            testerOut<<TesterOut.signal = signalState
            signalTimer = signalState? signalOnInterval, signalOffInterval
            ]
         ifnot
            [
            testerOut<<TesterOut.signal = false
            signalState = false
            ]
   @utilOut = not testerOut
   ]

let switchState = (@utilIn)<<TesterIn.switch
if switchState ne lastSwitchState then
   [
   lastSwitchState = switchState
   if switchState eq 0 then CramKeyboardCharacter($*s)
   ]
]

// ---------------------------------------------------------------------------
and CramKeyboardCharacter(char) be
// ---------------------------------------------------------------------------
[
let newIn = OsBuffer>>OsBUF.In+1
if newIn eq OsBuffer>>OsBUF.Last then newIn = OsBuffer>>OsBUF.First
if newIn ne OsBuffer>>OsBUF.Out then
   [
   @(OsBuffer>>OsBUF.In) = char
   OsBuffer>>OsBUF.In = newIn
   ]
]