//D1Speed.bcpl -- set clock speed.
//	Last edited: 20 November 1979

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

external [
// MASM
	@WssCSS; PutsCSS; WssCS1; Wait

// MDISP
	Blink

// MRGN
	UpdateDisplay

// MMENU
	@WsMarkA; CreateAction

// MCMD
	WnsCSS; WnsCSSD; QuitCmdOverlay; CmdAbort; SetAbort; ErrorExit
	@CmdAbortAct; CmdCommentStream; CmdCS1; LoadDone

// MGO
	@CantContinue

// MINIT0
	@ACTS

// D1I0
	@DMuxTab; HWStatus

// D1ASM
	@DoStrobe; @Xct; @XctR16; LoadDMD; ReadDMux; @SetALUF

// D1MEM
	SaveALUFM0; SaveALUFM16

// D1RES
	ReadAllRegs

// Defined here
	D1ClockSpeed
]

let D1ClockSpeed(nil,nil) = valof
[	SetAbort(lv CmdAbort,nil)
//LoadDMD value = 2000./T
	DefSpeed("20",144B,0); DefSpeed("21",137B,1)
	DefSpeed("22",133B,2); DefSpeed("23",127B,3)
	DefSpeed("24",123B,4); DefSpeed("25",120B,5)
	DefSpeed("26",115B,6); DefSpeed("27",112B,7)
	DefSpeed("28",107B,8); DefSpeed("29",105B,9)
	DefSpeed("30",103B,10); DefSpeed("31",101B,11)
	DefSpeed("32",77B,12); DefSpeed("33",75B,13)
	DefSpeed("34",73B,14); DefSpeed("35",71B,15)
	DefSpeed("40",62B,16); DefSpeed("45",55B,17)
	DefSpeed("50",50B,18); DefSpeed("55",44B,19)
	DefSpeed("60",41B,20)
	resultis D1ClkMenu
]


and DefSpeed(String,X,I) be
[	ACTS!I = CreateAction(String,lv SetSpeed,X)
]


and D1ClkMenu(S,nil) be
[	WssCSS("Change clock rate from ")
	PrinClkRate((DMuxTab+dCLKRUN)>>lh)
	WssCSS(" to:")
	WsMarkA(CmdAbortAct)
	for I = 0 to 20 do WsMarkA(ACTS!I)
]


and SetSpeed(X,nil,nil) be
[	let OldRate = (DMuxTab+dCLKRUN)>>lh
//Keep IOReset on during speed change and restore afterwards.
//**CantContinue because of IOReset.
//	let T = HWStatus>>HWStatus.RunControl &
//		(EnRefreshPeriodx+RunRefresh)
//Turn on ECLup while preserving old values of EnRefreshPeriod' and
//RunRefresh.  IOReset is true during transient.
//	LoadDMD(RunEnable+ECLup+T)
	LoadDMD(ClkRate0+(X<<nib2))
	LoadDMD(ClkRate1+(X<<nib3))
	HWStatus>>HWStatus.ClkRate = X
	CantContinue = CantContinue % didSetClock
	LoadDone = false
//	DoStrobe(Control)
	Wait(5000)
//	LoadDMD(RunEnable+ECLup+IOResetx+T)
	let oldSaveALUFM0,oldSaveALUFM16 = SaveALUFM0,SaveALUFM16
	ReadDMux(); ReadAllRegs(1)
	SaveALUFM0,SaveALUFM16 = oldSaveALUFM0,oldSaveALUFM16
	let SomeError = false
	let ActRate = (DMuxTab+dCLKRUN)>>lh
	if ActRate ne X do
	[ WssCSS("DMux read clock rate as "); WnsCSS(ActRate)
	  WssCSS(", but should be "); WnsCSS(X)
	  SomeError = true
	]
	unless SomeError do
	[ WssCSS("Changed clock from "); PrinClkRate(OldRate)
	  WssCSS(" to "); PrinClkRate(ActRate)
	]
//	let ActEnables = (DMuxTab+dCLKRUN)>>nib2
//	if ActEnables ne (ECLup+IOResetx+T) do
//	[ WssCSS(" Run enables wrong"); SomeError = true
//	]
	let DVec,DVec1 = vec 2,vec 2
	Xct(TFAF0); XctR16(RT,DVec)
	Xct(SetALUF(TFAF0,16B)); XctR16(RT,DVec1)
	if DVec>>rh ne 25B do
	[ SomeError = true
	  WssCS1("Failed to load ALUFM[0] ")
	]
	if DVec1>>rh ne 1B do
	[ SomeError = true
	  WssCS1("Failed to load ALUFM[16] ")
	]
	if SomeError then ErrorExit("")
	QuitCmdOverlay()
]


and PrinClkRate(Rate) be
[	let T = 20000/Rate; WnsCSSD(T/10); PutsCSS($.)
	WnsCSSD(T rem 10); WssCSS(" ns")
]