;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
;	D O R A D O   C o n t r o l   P r o g r a m
;
;		P r e l i m i n a r y   R e s e t   C o d e
;
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

;	filed on DoradoReset.masm
;	E. McCreight
;	last modified November 18, 1981  3:15 PM

	.EXPORT	RebootDorado
	.EXPORT	InterruptPtr
	.EXPORT	UpdateTimer
	.EXPORT	Delay,BootTicksOff,BootPushCount
	.EXPORT	SetProblem,ClearProblem

	.IMPORT	PowerUpMinus5And12,PowerUpAllSupplies,PowerUpDisk
	.IMPORT	DisconnectMufMan,LoadDiskHeads
	.IMPORT	StdClockSpeedH,StdClockSpeedL
	.IMPORT	MidasCall,MidasSetup,TrapEncountered
	.IMPORT	InhibitMidas,EnableMidas
	.IMPORT	InitEnvironment,DoAllConversions,PowerOutOfSpec
	.IMPORT	LoadDoradoCode,SetManifold,Continuous
	.IMPORT	ZCodeVersion,BaseCodeVersion
	.IMPORT	ReadMuffler,DiskHeadsLoadedMuf,TurnOnPwrMuf
	.IMPORT	StopDorado,PacifyWatchdog
	.IMPORT	Timer100ms
	.IMPORT	Problems
	.IMPORT	NormalWait,CurrentPowerProblem,ShutDown
	.IMPORT	MeltDownTemp
	.IMPORT	CheckBootButton

	.SHORT	ZCodeVersion,Timer100ms,Problems

	.PREDEFINE "MCS6502PREDEFS.SR"
	.GETNOLIST	"DoradoIO.mdefs"

;	Reset Pointers

	.LOC	0fffc
	.ADR	Reset
	.ADR	Interrupt

;	V a r i a b l e s

	.LOC	ResetData
	.SHORT	ResetData

InterruptPtr:
	.BLK	2

;	Counters and other stuff

SpareUsecs:	.BLK	2
SubTicks:	.BLK	1	; 50. subticks make a timer tick

OldWorstProblem:	.BLK	1
PlaceInCode:	.BLK	1

EndOfDelay:	.BLK	2

BootSubticksOn:	.BLK	1
BootTicksOn:	.BLK	1
BootSubticksOff:	.BLK	1
BootTicksOff:	.BLK	1
BootPushCount:	.BLK	1

	.LOC	ResetCode

Interrupt:
	CLD
   PHA
	TXA
	PHA
	TSX
	LDAX	StackTop+2	; see if BRK encountered
	ANDI	10
	BEQ	NotBRK

	JMP	TrapEncountered

NotBrk:
	JMP@	InterruptPtr	; can use A and X, must restore from stack

StandardInterruptRoutine:
	LDA	Timer100ms
	PHA

	JSR	UpdateTimer	; this is done every 2 ms.
	JSR	FastKbdBootCheck

	PLA
	CMP	Timer100ms
	BEQ	IntReturn

	CLI	; re-enable interrupts

	JSR	CheckKbdBootButton	; this is done every 100 ms.
	JSR	FlashTheLight

IntReturn:
	PLA
	TAX
	PLA
	RTI

;	Routine that keeps the 2.048 ms subtick count and the
;	102.4 ms timer up to date. This
;	runs with interrupts masked off.

SubTickInUsecs:
	.ADR	2.*1024.

UpdateTimer:
	LDA	580+IntFlags
	ANDI	TimerFlag
	BEQ	UpdateTimerExit

	LDXI	2.	; 2*1024 usec
	LDAI	4	; 4 us dead time between read and reload
	SEC
	SBC	580+Timer
	STX	580+Timer+Div1024+DoTimerInterrupt

	ADC	SpareUsecs
	STA	SpareUsecs
	LDAI	0
	ADC	SpareUsecs+1
	STA	SpareUsecs+1

	BCC	SpareOverflowInCarry

	LDA	SpareUsecs
	SBC	SubTickInUsecs
	STA	SpareUsecs
	LDA	SpareUsecs+1
	SBC	SubTickInUsecs+1
	STA	SpareUsecs+1

SpareOverflowInCarry:
	LDAI	1
	ADC	SubTicks
	STA	SubTicks
	SBCI	50.-1	; actually 50. -- no carry bit means borrow
	BCC	UpdateTimerExit

	STA	SubTicks	; subtick overflowed into timer tick

	LDXI	0

IncNextTimerByte:
	INCX	Timer100ms
	BNE	UpdateTimerExit
	INX
	BNE	IncNextTimerByte	; unconditional

UpdateTimerExit:
	RTS


;	Routines to check the boot button on the keyboard.

;	This first routine is done every 2 ms subtick. It actually looks at
;	the boot button, and maintains two counts: BootSubticksOn and
;	BootSubticksOff. When the boot button has been up for 40 ms or
;	more, BootSubticksOn is reset to 0. Thereafter when it is down
;	for 8 ms, BootPushCount is incremented by 1.

FastKbdBootCheck:
	LDA	MiscByte
	ANDI	Boot'
	BNE	BootNotPushed

	LDAI	0
	STA	BootTicksOff
	STA	BootSubticksOff

	LDA	BootSubticksOn
	CMPI	3.
	BNE	NotANewPush

	INC	BootPushCount

NotANewPush:
	CMPI	4.
	BPL	DontIncrementSubticks
	INC	BootSubticksOn

DontIncrementSubticks:
	RTS

BootNotPushed:
	LDA	BootSubticksOff
	CMPI	20. ; 40. ms up means really up
	BPL	BootSolidlyUp
	INC	BootSubticksOff
	RTS

BootSolidlyUp:
	LDAI	0
	STA	BootTicksOn
	STA	BootSubticksOn
	RTS


;	This routine is done once every 100 ms tick. It takes its cue from
;	BootSubticksOn and maintains the counts
;	BootTicksOn and BootTicksOff. If BootTicksOn ever gets to
;	2 seconds, BootPushCount is reset to 0.

CheckKbdBootButton:
	LDA	BootSubticksOn
	CMPI	1.
	BMI	BootNotRecognized

	LDA	BootTicksOn
	CMPI	20.	; 2 sec
	BPL	ClearPushCount	; user says he made a mistake

	INC	BootTicksOn
	RTS

ClearPushCount:
	LDAI	0
	STA	BootPushCount
	RTS

BootNotRecognized:
	LDA	BootTicksOff
	CMPI	100.	; hold count at 10 seconds
	BPL	DontIncrementTicks
	INC	BootTicksOff

DontIncrementTicks:
	RTS

;	Subroutine to flash the light in response to the highest-
;	priority current problem.

FlashTheLight:
	JSR	FindWorstProblem
	TXA
	BEQ	NoProblems	; 0 means no problems
	CPX	OldWorstProblem
	BMI	OldProblemWasWorse
	STX	OldWorstProblem

OldProblemWasWorse:
	INC	PlaceInCode
	BMI	TurnLightOff	; still pausing before code
	LDA	PlaceInCode
	LSRA
	LSRA
	BCS	TurnLightOff	; space between bits of unary code
	CMP	OldWorstProblem
	BMI	TurnLightOn	; next bit of unary code

StartNewCode:
	JSR	FindWorstProblem
	STX	OldWorstProblem
	LDAI	-13.	; 1.5-second delay between code bursts
	STA	PlaceInCode

TurnLightOff:
	LDAI	LampOff
	ORA	MiscByte
	STA	MiscByte
	RTS

NoProblems:
	STX	OldWorstProblem
	LDAI	-13.	; 1.5-second delay between code bursts
	STA	PlaceInCode

TurnLightOn:
	LDAI	-1-LampOff
	AND	MiscByte
	STA	MiscByte
	RTS


;	Puts the index of the
;	highest-priority problem in X. 0 is no problems,
;	1 means Problems=1000 0000, 2 means Problems=x100 0000,
;	..., 8 means Problems=xxxx xxx1.

FindWorstProblem:	; 0 thru 8: 0 means no problems, 8 is highest priority
	LDXI	0
	SEC
	LDA	Problems
	SBCI	1
	EORI	0ff
	AND	Problems	; Problems & ~(Problems-1)
	BEQ	WorstProblemInX

TryNextProblem:
	INX
	ASLA
	BNE	TryNextProblem

WorstProblemInX:
	RTS


;	This is the reset code that gets run whenever the circuit
;	breakers are turned on or the little button on the front
;	panel is pushed.

Reset:
	CLD	; initiate binary arithmetic

;	Clear all the bytes in page 0.

   LDXI	0
	LDAI	0

ClearMoreBytes:
	STAX	0
	DEX
	BNE	ClearMoreBytes

;	Put the code version number in a conspicuous place

	LDAI	BaseCodeVersion
	STA	ZCodeVersion

;	Set up the stack and prepare for interrupts.

	LDXI	0ff
	TXS
	LDAI	StandardInterruptRoutine,#LowAddrByte
	STA	InterruptPtr
	LDAI	StandardInterruptRoutine,#HighAddrByte
	STA	InterruptPtr+1
	JSR	MidasSetup

;	Set the data direction registers in the I/O ports, after first
;	setting some output registers so their critical bits will
;	remain high

	LDXI	0ff	; set for all output bits
	STX	DAC+DDR
	STX	MCPBusH+DDR

	INX	; set for all input bits
	STX	CPRegL+DDR
	STX	CPRegH+DDR

	LDXI	ISel	; set for mixtures
	STX	Comparators+DDR

	LDXI	MASync+Trap'
	STX	CPIBus+DDR

	LDXI	LampOff
	STX	MiscByte
	STX	MiscByte+DDR

	LDXI	80+MCPABus+MCPStrobe
	STX	MCPBusL+DDR

	LDXI	WatchdogDDRValue
	STX Watchdog+DDR

	LDAI	(50.+273.)*25/49	; 50 degrees C, at 1.96 counts/deg K
	STA	MeltDownTemp

;	Now begin timer interrupts.

	LDAI	1
	STA	580+Timer+DoTimerInterrupt
	CLI

;	Now initialize the voltage, current, and temperature vectors.

	JSR	InitEnvironment

;	See whether the debugging jumper is installed on the backpanel
;	or if power has already been commanded on. If so, start up
;	immediately.

	LDA	MCPBusL
	ANDI	SkipDiskWait'
	BEQ	RebootDorado
	LDXI	TurnOnPwrMuf
	JSR	ReadMuffler
	BNE	RebootDorado

;	Power up only after the user presses his terminal boot button
;	at least once.

   LDAI	ShutDown
	JSR	SetProblem

WaitForInitialBoot:
	JSR	CheckBootButton
	JSR	DoAllConversions
	JMP	WaitForInitialBoot

;	Power sequencing. First make sure our own supply is in spec.

RebootDorado:
	JSR	PacifyWatchdog

	LDAI	NormalWait
	JSR	SetProblem

	LDAI	-1-NormalWait
	JSR	ClearProblem

	JSR	DoAllConversions

CheckVCC:
	LDXI DisconnectMufMan
	JSR	SetManifold	; force IO reset

	JSR	StopDorado

	LDA	PowerOutOfSpec
	ANDI	44	; +5v supply
	BEQ	VCCOK

	JSR	PacifyWatchdog

	JSR	InitEnvironment
	LDAI	CurrentPowerProblem
	JSR	SetProblem
	JMP	CheckVCC


;	Now figure out whether the disk heads are already
;	loaded (Sequence0' is asserted). If not, start the disk
;	and wait for 20 seconds. Then command the heads to load
;	and wait for another 20 seconds. All this waiting can be skipped
;	if SkipDiskWait' is asserted.

VCCOK:
	LDAI	CurrentPowerProblem
	JSR	ClearProblem

	LDXI	DiskHeadsLoadedMuf	
	JSR	ReadMuffler
	BEQ	DiskOK

	LDXI	PowerUpDisk
	JSR	SetManifold
	LDXI	20.	; about 20 seconds
	JSR	DiskWait

	LDXI	LoadDiskHeads
	JSR	SetManifold
	LDXI	20.	; about 20 seconds
	JSR	DiskWait


;	Now start up the Ecl supplies and wait
;	until they all measure OK.

DiskOK:
	JSR	DoAllConversions
	LDA	PowerOutOfSpec
	BEQ	SuppliesAllUp

	LDXI	PowerUpMinus5And12
	JSR	SetManifold

	LDXI	4.
	JSR	Delay

	LDXI	PowerUpAllSupplies
	JSR	SetManifold

CheckAllSupplies:
	LDA	PowerOutOfSpec
	BEQ	SuppliesAllUp

	JSR	PacifyWatchdog

	JSR	InitEnvironment
	LDAI	CurrentPowerProblem
	JSR	SetProblem
	JMP	CheckAllSupplies

SuppliesAllUp:
	LDAI	CurrentPowerProblem
	JSR	ClearProblem

	LDXI	1.
	JSR	Delay

;	Set the standard clock speed

	LDXI	StdClockSpeedH
	JSR	SetManifold
	LDXI	StdClockSpeedL
	JSR	SetManifold

;	Now wait for two seconds for the clock to settle.

	LDXI	2.
	JSR	Delay

;	Now bootstrap-load the Dorado processor and get it running.

	JSR	LoadDoradoCode

;	Now do whatever we do in steady-state.

	LDAI	NormalWait
	JSR	ClearProblem
	JMP	Continuous

;	Delay X sec only if SkipDiskWait' is high.

DiskWait:
	LDA	MCPBusL
	ANDI	SkipDiskWait'
	BEQ	DelayFinished

;	Delay X sec.

Delay:
	SEI
	LDA	Timer100ms
	LDY	Timer100ms+1
	CLI
	STA	EndOfDelay
	STY	EndOfDelay+1

	LDYI	10.-1	; multiply seconds by 10 to get 102.4 ms "ticks"

MpySeconds:
	TXA
	CLC
	ADC	EndOfDelay
	STA	EndOfDelay
	LDAI	0
	ADC	EndOfDelay+1
	STA	EndOfDelay+1
	DEY
	BPL	MpySeconds
	
DelayLoop:
	JSR	PacifyWatchdog
	LDA	Timer100ms+1
	CMP	EndOfDelay+1
	BMI	DelayLoop
	BNE	DelayFinished
	LDA	Timer100ms
	CMP	EndOfDelay
	BCC	DelayLoop	; borrow

DelayFinished:
	RTS


;	Add the problems in A to the current problems.

SetProblem:
	ORA	Problems
	STA	Problems
	RTS

;	Remove the problems in A from the current problems.

ClearProblem:
	EORI	0ff
	AND	Problems
	STA	Problems
	RTS

	.END