//D1MicRes.bcpl	Resident code for microcomputer.
//	Last edited: 2 June 1981

get "mcommon.d"
get "d1mic.d"
get "d1.d"
manifest [ get "d1regmem.d" ]

external [
// OS
	Puts

// MIDAS
	MidasSwat

// MINIT0
	MStatus

// MASM
	Wss; Wait

// MDATA
	DWatch

// MOVERLAY
	OverlayZone

// MIOC
	DWns; Wns

// MMPRGN
	UpdateMPDValues

// D1ASM
	@MCXct; @MCXctR; @DoStrobe; LoadCPReg

// D1MICASM
	ConvertMTime; MCWaitCnt

// D1I0
	HWStatus

// Defined here
	MPrintMSTAT; MPrintUPTIME; HWEveryTime; ChangeAltoControl
	PrinVoltage; PrinCurrent; PrinTemperature
]

static [ MicState = 0; MCSlowTimeOut = 20 ]

//Called from MPDEveryTime in MMPRGN.BCPL when OverlayZone eq 0
let HWEveryTime(nil) be
[	test MicState < 4
//Microcomputer requires about 100 msec to update all of its stuff,
//but this is too long for mouse following and such, so split the
//activity into smaller time intervals.
	ifso
	[ MicState = MicState+1
//Give microcomputer muffler/manifold control for 10 msec if the DWATCH
//feature is not being used (Microcomputer can't access muffler/manifold
//system when SetRun is true.).
	  unless MStatus>>MStatus.MachRunning do DoStrobe(Control)
	  if DWatch!1 eq 0 do
	  [ ChangeAltoControl(BAltoControl+BCNoop)
	    Wait(100)
	    ChangeAltoControl(BAltoControl+BCNoop+1)
//UseCPReg true when machine not running, else false
	    DoStrobe((MStatus>>MStatus.MachRunning ? Clock,Clock+UseCPReg))
	  ]
	]
//Power supply info and two temperatures can be updated even when
//SetRun is true, so do this even when machine is running.
	ifnot
	[ MicState = 0
	  UpdateMPDValues(true)
	]
]


//Avoid changing Alto/Baseboard control except when holding microcomputer
//in an interrupt.  Microcomputer avoids acknowledging MCXct until it is in
//a safe state to have Alto/Baseboard control changed.  For normal
//communication, a timeout of 2 msec suffices.  However, a boot takes
//about 1 sec and changing Dorado clock speed about 3 sec, during which
//the baseboard will be unresponsive, and the Alto must not seize control
//lest communication between the baseboard and Dorado be destroyed.  When
//the baseboard controls the CP bus, a load of CPReg by the Alto will affect
//only the register on the baseboard, so the other CPReg is safely useable by
//the baseboard.  The boot will still fail if the user executes any
//non-passive action from Midas during the boot, but we accept that.
and ChangeAltoControl(X) be
[ //3.2 sec timeout if Alto is taking control of CP bus.
	if ((X & 1) ne 0) then MCWaitCnt = MCSlowTimeOut
//If the baseboard fails to acknowlege, switch to a short timeout so that
//Midas won't be inoperable if baseboard can't communicate, but switch back
//to long timeout when communication is restored.
	MCSlowTimeOut = MCXct(BInt+BHoldInt+BCNoop) ? 20,32000
	MCWaitCnt = 20				//Back to 2 msec timeout
	LoadCPReg(X); DoStrobe(Clock+BaseBAtten)
	MCXct(BInt+BCNoop)
]


//MPrintUPTIME used to print the 6-byte UPTIME and TGLITCH registers
//For these the 6-bytes are in reverse order and the time is measured
//in 102.4 msec ticks since the boot button was pushed.
and MPrintUPTIME(S,X,DVec,AVec) be
[	let V,Days,Hours,Minutes,Seconds = vec 3,nil,nil,nil,nil
	ConvertMTime(V,DVec,lv Days,lv Hours,lv Minutes,lv Seconds)
	Wns(S,Days,0,10); Wss(S," days ")
	Wns(S,Hours,0,10); Puts(S,$:)
	Wns(S,Minutes,0,10); Puts(S,$:)
	Wns(S,Seconds,0,10)
]


//Print the voltage as a signed number using 6 characters
and PrinVoltage(S,H,Neg) be
[	let I,R = H/100,H rem 100
	if Neg then I = -I
	DWns(S,lv I,16,0,-10,3); Puts(S,$.)
	DWns(S,lv R,16,0,10,2,$0)
]


//All temperatures converted to degrees K when multiplied by 1.96
//Print degrees C as 6 char group.
and PrinTemperature(S,N) be
[	test N eq 377B
	ifso Wss(S,"    --")	//No board
	ifnot test N eq 0
	  ifso Wss(S,"    ??")	//No thermometer
	  ifnot
	  [ N = ((98*N+25)/50)-273; Wns(S,N,6,-10)
	  ]
]


and PrinCX(S,N) be Wns(S,N,6,10)


//Rational fractions are used below to approximate the decimal multipliers
//supplied by McCreight.  Continued fractions are used to get the best
//approximations with numerators less than 128 to avoid overflow.
and MPrintMSTAT(S,X,DVec,AVec) be
[	let t0,t1,t2,t3 = DVec>>lh,DVec>>rh,(DVec+1)>>lh,(DVec+1)>>rh
	switchon AVec!1 into
	[
case mVOLTS:
case mFVOLTS:
case mMINVOLTS:
case mMAXVOLTS:
	//12v = .0619*t0 approx. 99/16
	  t0 = (99*t0+8)/16; PrinVoltage(S,t0,0)
	//5v = .0262*t1 approx. 76/29
	  t1 = (76*t1+15)/29; PrinVoltage(S,t1,0)
	//-2v = .0101*t2 approx. 101/100
	  t2 = (101*t2+50)/100; PrinVoltage(S,t2,-1)
	//-5v = .0259*t3 approx. 101/39
	  t3 = (101*t3+20)/39; PrinVoltage(S,t3,-1); return

case mAMPS:
case mFAMPS:
case mMINAMPS:
case mMAXAMPS:
//Different power supplies for serial numbers .ls. 30b
	  test HWStatus>>HWStatus.ConnectedMachine < #30
	  ifso
	  [
	  t0 = (67*t0+35)/69		//12v .971 amps/count
	  t1 = (67*t1+35)/69		// 5v .971
	  t2 = (67*t2+35)/69		//-2v .971
	  t3 = (47*t3+6)/11		//-5v 4.29
	  ]
	  ifnot
	  [ t0 = (83*t0+250)/500	//12v .166
	    t1 = (133*t1+25)/50		// 5v 2.66
	    t2 = (51*t2+10)/20		//-2v 2.55
	    t3 = (49*t3+7)/13		//-5v 3.77
	  ]
	  PrinCX(S,t0); PrinCX(S,t1); PrinCX(S,t2); PrinCX(S,t3)
	  return

default:  PrinTemperature(S,t0); PrinTemperature(S,t1)
	  PrinTemperature(S,t2); PrinTemperature(S,t3); return
	]
]