//D1HWCheck.bcpl -- hardware checkout stuff inappropriate for "Test"
//	19 May 1983

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

external [
// OS
	Zero; DoubleAdd

// MINIT0
	@MBlock; @ACTS

// MIDAS
	MidasSwat

// MASM
	@WssCSS; WssCS1; ResetsCS1; GetField

// MDATA
	@LoopCount; @ShouldBe; DWatch

// MIOC
	SimpleTexttoDVec

// MTXTBUF
	InputTextBuffer

// MRGN
	RemoveFromEveryTimeList; AddToEveryTimeList; UpdateDisplay

// MMENU
	CreateAction; @WsMarkA

// MGO
	@QuitF; @CantContinue

// MCMD
	SetAbort; @CmdAbortAct; QuitCmdOverlay; FormCmdMenu; ErrorExit
	WnsCSS; WnsCS1D

// MPATTERN
	NextData; @PATTERN

// D1I0
	@DMuxTab; @OldDMuxTab; DWrong; HWStatus; @SaveMIR

// D1ACTIONS
	@LongOne

// D1MICASM
	@MCXct

// D1MICRES
	ChangeAltoControl

// D1ASM
	ReadDMux; LoadDWatch; LoadMIR; @D1In; LoadCPReg; @DoStrobe; IMtoMIR

// D1RES
	ReadAllRegs

// D1MEM
	TurnOffRefresh

// D1GO
	OneStep

// Defined here
	HWCheck
]

//Use ACTS!20 for menu control, ACTS!21 and ACTS!22 as counters
let HWCheck(nil,nil) = valof
[	SetAbort(lv HWChkStop,nil)
	Zero(ACTS+20,3)
	QuitF = -1
	Zero(LoopCount,2)
	DefM0(0,lv ReadSignal,"Read-DWATCH-Signal")
	DefM0(1,lv ReadAllDMux,"Read-All-DMux")
	DefM0(2,lv MCConnectDisconnect,"Connect-Disconnect")
	DefM0(3,lv AltoControl,"Alto/MC-control")
	resultis HWChkMenu
]


and DefM0(N,lvProc,Str) be
[	ACTS!N = CreateAction(Str,lvProc,0)
]


and HWChkStop(nil,nil,nil) be
[	if QuitF ge 0 then RemoveFromEveryTimeList(QuitF)
	QuitF = -1
	if (ACTS!20 eq 2) % (ACTS!20 eq 4) do Zero(DWatch,2)
	ReadAllRegs(0); QuitCmdOverlay()
]


and HWChkMenu(S,nil) be
[	WsMarkA(CmdAbortAct)
	switchon ACTS!20 into
	[
case 0:	  WsMarkA(ACTS!0); WsMarkA(ACTS!1); WsMarkA(ACTS!2)
	  WsMarkA(ACTS!3)
case 1:
case 2:
case 3:
case 4:	  endcase
default:  MidasSwat(HWChkMenubug)
	]
]


and ReadSignal(nil,MBunion,nil) be
[	if DWatch!1 eq 0 then ErrorExit("DWATCH must be non-0")
	ACTS!20 = 1
	QuitF = AddToEveryTimeList(ReadSignalLp,nil)
	WssCSS("Reloading DWATCH address and reading DMUX signal ")
	WnsCSS(DWatch!1); WssCSS(" ...")
	FormCmdMenu(); UpdateDisplay()
]


and ReadSignalLp(nil) be
[	for I = 0 to 300 do
	[ DoubleAdd(LoopCount,LongOne)
	  LoadDWatch()
	  test ((rv D1In) & #4000) ne 0
	  ifso ACTS!21 = ACTS!21+1
	  ifnot ACTS!22 = ACTS!22+1
	]
	ResetsCS1(); WnsCS1D(ACTS!21); WssCS1(" ones, ")
	WnsCS1D(ACTS!22); WssCS1(" zeroes")
]


and ReadAllDMux(nil,MBunion,nil) be
[	ACTS!20 = 2
	ACTS!21 = -1
	PATTERN = 4	//Random pattern
	CantContinue = CantContinue % didTest
	Zero(DWrong,DMUXlen)
	TurnOffRefresh()
	QuitF = AddToEveryTimeList(ReadDMuxLp,nil)
	WssCSS("Random instruction DMux signal stability test...")
	DWatch!1 = 1	//Disable microcomputer
	ReadDMux()
	FormCmdMenu(); UpdateDisplay()
]


//Execute a random MIR instruction and then read the DMux 4 times, checking
//each readout for consistency with the last.  Errors are accumulated in
//DWrong.  Works like SimTest.  Legitimately unstable signals, such as the
//Ethernet mufflers aren't reported.
and ReadDMuxLp(nil) be
[	for I = 0 to 20 do
	[ [ NextData()
	    switchon GetField(22B,10B,ShouldBe) into	//FF
	    [
case 36B:	//OUTPUT← (avoid activating io devices
case 101B:	//TEST← (avoid Testing and Mar←Pcf)
case 140B:	//USEDMD
case 141B:	//MIDASSTROBE←
	      loop
default:      break
	    ]
	  ] repeat
	  IMtoMIR(SaveMIR,ShouldBe); LoadMIR(SaveMIR)
	  DoStrobe(Clock); OneStep(Control+SetRun+SetSS)
	  ReadDMux()
	  MBlock(OldDMuxTab,DMuxTab,DMUXlen)
	  DoubleAdd(LoopCount,LongOne)
	  for J = 0 to 2 do
	  [ ReadDMux()
	    for I = 0 to DMUXlen-1 do
	    [ DWrong!I = DWrong!I % (OldDMuxTab!I xor DMuxTab!I)
	    ]
	  ]
	]
//These Ethernet muffler signals change legitimately (PDNew, PDOld,
//PDCnt[0:1], 2133, RxState[1:2], PDCarrier, RxSRFull', and RxCRCReset).
//Don't report them as inconsistencies.
	DWrong!dERX0 = DWrong!dERX0 & 7757B
	DWrong!dERX1 = DWrong!dERX1 & 113357B
	let NWrong = 0
	for I = 0 to DMUXlen-1 do
	[ let Bad = DWrong!I
	  while Bad ne 0 do
	  [ NWrong = NWrong+1; Bad = Bad-(Bad & -Bad)
	  ]
	]
	if ACTS!21 ne NWrong do
	[ ACTS!21 = NWrong
	  ResetsCS1(); WnsCS1D(NWrong); WssCS1(" inconsistencies")
	]
]


and MCConnectDisconnect(nil,MBunion,nil) be
[	ACTS!20 = 3
	ACTS!21,ACTS!22 = 0,0
	let Num = vec 1
	if InputTextBuffer!0 ne 0 then
	  if SimpleTexttoDVec(InputTextBuffer,16,Num) do
	  [ if Num>>lh ne 0 then
		ErrorExit("Unreasonable serial number")
	    WssCSS("Repeatedly connecting to/disconnecting from serial #")
	    WnsCSS(Num>>rh); WssCSS(" ...")
	    HWStatus>>HWStatus.ConnectedMachine = -1
	    QuitF = AddToEveryTimeList(MCConnectDisconnectLp,Num>>rh)
	    FormCmdMenu(); UpdateDisplay(); return
	  ]
	ErrorExit("Type serial number first")
]


and MCConnectDisconnectLp(N) be
[	for I = 0 to 20 do
	[ LoadCPReg(BSelD+BCNoop+N); DoStrobe(Clock+BaseBAtten)
	  test MCXct(BInt+BCNoop) eq 0
	  ifso ACTS!22 = ACTS!22+1
	  ifnot ACTS!21 = ACTS!21+1
	  LoadCPReg(BSelD+BCNoop+(N xor #377))
	  DoStrobe(Clock+BaseBAtten)
	]
	ResetsCS1(); WnsCS1D(ACTS!22); WssCS1(" OK connections, ")
	WnsCS1D(ACTS!21); WssCS1(" failed connections")
]


and AltoControl(nil,MBunion,nil) be
[	ACTS!20 = 4
	DWatch!1 = 1	//Disable HWEveryTime stuff
	if HWStatus>>HWStatus.ConnectedMachine eq -1 then
		ErrorExit("Not connected to any machine")
	WssCSS("Alternating Alto and MC muffler control for scoping ...")
	QuitF = AddToEveryTimeList(AltoControlLp,nil)
	FormCmdMenu(); UpdateDisplay()
]


and AltoControlLp(nil) be
[	for I = 0 to 40 do
	[ ChangeAltoControl(BAltoControl+BCNoop)	//MC controls
	  ChangeAltoControl(BAltoControl+BCNoop+1)	//Alto controls
	  DoubleAdd(LoopCount,LongOne)
	]
]