;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
;
;	D O R A D O   C o n t r o l   P r o g r a m
;
;		C P B u s   I n t e r f a c e   C o d e
;
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *

;	filed on DoradoCPInt.masm
;	E. McCreight
;	last modified April 14, 1981  1:31 PM

	.EXPORT	WaitForCPControl,TryGettingMufManControl
	.EXPORT	ReadBNibble,SetCPReg,SetCPReg~
	.EXPORT	SetCPReg1,SetCPReg0,DoClock,DoControl
	.EXPORT	DoDoradoMicroInst,RunDoradoInstructionStream
	.EXPORT	SetManifold,DatumToManifold
	.EXPORT	SetMufflerAddress,MufflerAddress,ReadMuffler
	.EXPORT	ReadMufflerField
	.EXPORT	Left7,Left6,Left5,Left4,Left3,Left2,Left1

	.EXPORT	Micro,CDatum
	.EXPORT	ToCPReg,ToCPRegH,ToCPRegL
	.EXPORT	StopDorado

	.IMPORT	InhibitMidas,EnableMidas,PacifyWatchdog
	.IMPORT	SetProblem,ClearProblem,CantGetCPControl
	.IMPORT	Timer100ms
	.IMPORT	MufflerTable
	.IMPORT	ProcLTemp,ProcHTemp
	.IMPORT	CBTemp,CATemp
	.IMPORT	MidasInhibitDepth

	.SHORT	ProcLTemp,ProcHTemp
	.SHORT	CBTemp,CATemp
	.SHORT	MidasInhibitDepth

	.PREDEFINE "MCS6502PREDEFS.SR"
	.GETNOLIST	"DoradoIO.mdefs"

;			V a r i a b l e s

	.LOC	CPIntData
	.SHORT	CPIntData

;	Microcode pointer

Micro:	.BLK	2	; points to a 5-byte microinstruction to execute
ShouldSingleStep:	.BLK	1	; 1 if single step, 0 if run

ExtraInstBits:
	.BLK	1	; holds the extra 4 bits during MIR strobing

CDatum:	.BLK	1

ToCPReg:	; data to be put in the Dorado's CP register
ToCPRegL:	.BLK	1
ToCPRegH:	.BLK	1


;	New muffler address: High-order 8 bits in 2nd byte,
;	low-order 4 bits left-justified in first byte.

NextMufflerAddress:
	.BLK	2
MufflerAddress:
	.BLK	2

CPControlDeadline: .BLK	1

	.LOC	CPIntCode

;	Set the CP register from complemented microcomputer locations
;	ToCPRegH and ToCPRegL.

SetCPReg~:
	LDA	ToCPRegH
	EORI	0ff
	JSR	SetCPReg0

	LDA	ToCPRegL
	EORI	0ff
	SEC	; good parity
	JMP	SetCPReg1


;	Set the CP register from microcomputer locations
;	ToCPRegH and ToCPRegL.

SetCPReg:
	LDA	ToCPRegH
	JSR	SetCPReg0

	LDA	ToCPRegL
	SEC	; good parity


;	Execute CP functions. One-byte argument in A. Extra bit (if
;	any) in carry bit. These functions don't verify that we control
;	the CP Bus, so they must only be invoked in contexts where that
;	fact is otherwise assured.

SetCPReg1:
	STA	MCPBusH
	LDAI	ABMux1↑1
	RORA
	BNE	FinishCP

DoClock:
	STA	MCPBusH
	LDAI	Clock
	BNE	FinishCP

SetCPReg0:
	STA	MCPBusH
	LDAI	ABMux0
	BNE	FinishCP

DoControl:
	STA	MCPBusH
	LDAI	Control↑1
	RORA

FinishCP:
	STA	MCPBusL
	INC	MCPBusL	; toggle the strobe bit
	DEC	MCPBusL
	RTS


ReadBNibble:	; nibble address in A [0..7], leaves result in A
	JSR	WaitForCPControl
	ASLA
	ASLA
	ASLA
	ASLA
	ASLA
	STA	MCPBusH
	LDA	CPIBus
	ANDI	CPI
	LSRA
	JMP	EnableMidas

;	Execute Dorado microinstruction subroutine. The instruction
;	is located at @Micro and is 5 bytes long. The five bytes contain:

;		0:	RSTK.0,P015,JCN.7,P1631,0,0,0,0
;		1:	RSTK.1,RSTK.2,RSTK.3,ALUF.0,BLOCK,FF.0,FF.1,FF.2
;		2:	ALUF.1,ALUF.2,ALUF.3,BSEL.0,FF.3,FF.4,FF.5,FF.6
;		3:	BSEL.1,BSEL.2,LC.0,LC.1,FF.7,JCN.0,JCN.1,JCN.2
;		4:	LC.2,ASEL.0,ASEL.1,ASEL.2,JCN.3,JCN.4,JCN.5,JCN.6

;	The microcomputer must have control of the CPBus. Returns
;	Carry set if the operation didn't work.

RunDoradoInstructionStream:
	JSR	WaitForCPControl	; gain control of the CP bus
	LDAI	0
	JSR	DoClock

	LDAI	0
	BEQ	DoradoMICommon

DoDoradoMicroInst:
	JSR	WaitForCPControl	; gain control of the CP bus
	LDAI	InhibitCAHolds+ClrReady
	JSR	DoClock

	LDAI	1

DoradoMICommon:
	STA	ShouldSingleStep

	LDAI	ClrStop+ClrMIR+ClrCT+Freeze	; clear the Dorado
	CLC	; no SetSS
	JSR	DoControl

	LDAI	0	; undo Clears
	SEC	; do SetSS
	JSR	DoControl

	LDYI	0
	LDA@Y	Micro
	STA	ExtraInstBits
	
	INY
	LDA@Y	Micro
	STA	MCPBusH
	LDAI	MIR0↑1
	ASL	ExtraInstBits
	RORA
	STA	MCPBusL
	INC	MCPBusL	; strobe the byte into MIR0 by toggling the
	DEC	MCPBusL	; strobe bit

	INY
	LDA@Y	Micro
	STA	MCPBusH
	LDAI	MIR1↑1
	ASL	ExtraInstBits
	RORA
	STA	MCPBusL
	INC	MCPBusL	; strobe the byte into MIR1
	DEC	MCPBusL

	INY
	LDA@Y	Micro
	STA	MCPBusH
	LDAI	MIR2↑1
	ASL	ExtraInstBits
	RORA
	STA	MCPBusL
	INC	MCPBusL	; strobe the byte into MIR2
	DEC	MCPBusL

	INY
	LDA@Y	Micro
	STA	MCPBusH
	LDAI	MIR3↑1
	ASL	ExtraInstBits
	RORA
	STA	MCPBusL
	INC	MCPBusL	; strobe the byte into MIR3
	DEC	MCPBusL

	LDA	ShouldSingleStep
	LSRA
	LDAI	SetRun	; single-step the Dorado by setting Run and
	JSR	DoControl

	LDA	ShouldSingleStep
	BEQ	DontStopDorado
	BNE	BasicStopDorado

StopDorado:
	JSR	WaitForCPControl	; gain control of CP bus

BasicStopDorado:
	LDAI	SetRun	; keep SetRun asserted and
	SEC	; assert SetSS
	JSR	DoControl

	LDAI	0	; clear SetRun but don't ClrStop,
	SEC	; keeping SetSS asserted
	JSR	DoControl

DontStopDorado:
	JMP	MufflerSuccess

;	Set manifold subroutine. Called with X indexing a byte
;	table containing manifold contents. Returns NE if
;	the operation worked, EQ if it didn't.

SetManifold:
	LDAX	MufflerTable
	STA	MufflerAddress
	LDAX	MufflerTable+1
	STA	MufflerAddress+1

BasicManifold:
	JSR	SetMufflerAddress
	BCS	MufflerFailure

	LDAI	UseDMD
	JSR	DoClock

	LDAI	0
	JSR	DoClock

MufflerSuccess:
	CLC

MufflerFailure:
	JMP	EnableMidas


;	Another variant of manifold setting subroutine, in which there
;	are 6 bits of data left-justified in CDatum and the manifold
;	address (another 6 bits) right-justified in A.

DatumToManifold:
	STA	MufflerAddress+1
	LDA	CDatum
	ASLA
	ROL	MufflerAddress+1
	ASLA
	ROL	MufflerAddress+1
	STA	MufflerAddress
	JMP	BasicManifold


;	Routine to read a muffled bit. X register indexes the
;	Muffler table, and the bit is left in the low-order bit of
;	the A register.

ReadMuffler:
	LDAX	MufflerTable	; low-order
	STA	MufflerAddress
	LDAX	MufflerTable+1	; high-order
	STA	MufflerAddress+1
	JSR	SetMufflerAddress
	LDAI	DMuxData	; low-order bit
	AND	CPIBus
	JMP	EnableMidas


;	Subroutine to read a Y+1-bit field whose high-order bit is
;	pointed to by the entry offset by X in the muf/man table,
;	and whose successive bits increase by the offset in X+2.

ReadMufflerField:
	JSR	TryGettingMufManControl
	BCS	MufflerFailure

	LDAX	MufflerTable
	STA	NextMufflerAddress
	LDAX	MufflerTable+1
	STA	NextMufflerAddress+1
	LDAI	0

ReadFieldLoop:
	PHA	; the current field
	CLC
	LDA	NextMufflerAddress
	STA	MufflerAddress
	ADCX	MufflerTable+2
	STA	NextMufflerAddress
	LDA	NextMufflerAddress+1
	STA	MufflerAddress+1
	ADCX	MufflerTable+3
	STA	NextMufflerAddress+1

	JSR	BasicSetMufflerAddress
	LDA	CPIBus	; DMuxData is low-order bit
	LSRA
	PLA
	ROLA
	DEY
	BPL	ReadFieldLoop

	CLC
	JMP	EnableMidas


;	Setup muffler address subroutine. Bits are left-justified in
;	MufflerAddress, which is clobbered. Leaves us in control
;	of the CP bus, and Midas interrupts inhibited. Returns
;	Carry set if Dorado is running so we couldn't really
;	use the muffler system. All registers are saved.

SetMufflerAddress:
	JSR	TryGettingMufManControl
	BCS	SetMufflerFailed

BasicSetMufflerAddress:
	PHA	; save all registers
	TYA
	PHA
	LDAI	Clock
	STA	MCPBusL
	LDYI	7

SetHiMufflerBit:
	ASL	MufflerAddress+1
	JSR	AnotherMufAddrBit
	DEY
	BPL	SetHiMufflerBit

	LDYI	3

SetLoMufflerBit:
	ASL	MufflerAddress
	JSR	AnotherMufAddrBit
	DEY
	BPL	SetLoMufflerBit
	PLA
	TAY
	PLA
	CLC

SetMufflerFailed:
	RTS


AnotherMufAddrBit:
	LDAI	ShiftDMD↑1
	RORA	; rotate in data bit from Carry
	STA	MCPBusH	; prepare new address bit
	INC	MCPBusL	; strobe it
	DEC	MCPBusL

	ANDI	0ff-ShiftDMD
	STA	MCPBusH	; clock it into muffler address S/R
	INC	MCPBusL	; strobe it
	DEC	MCPBusL

	RTS

;	Subroutine to guarantee that the Dorado is not running and
;	the CP bus is controlled by the microcomputer, until
;	the EnableMidas subroutine is called.
;	Returns carry set if attempt failed because Dorado was
;	running. Carry is clear if success.

TryGettingMufManControl:
	PHA	; save all registers
	JSR	SetDeadline
	JSR	InhibitMidas
	LDA	MCPBusL
	ANDI	SetRunIn
	BEQ	SeeWhosInCharge

	SEC	; we failed because the Dorado was running
	PLA
	RTS

;	Subroutine to guarantee control of the CP bus until
;	the EnableMidas subroutine is called. This only
;	works with the co-operation of Midas, which promises
;	only to change the CP bus controller while the microcomputer
;	is being held inside the Midas communication code. Thus
;	once we have disabled Midas communication while we control
;	the CP bus, it remains ours for as long as we want it.

WaitForCPControl:	; demands control even if Dorado running
	PHA	; save all registers
	JSR	SetDeadline
	JMP	MaybeCPAvailNow

WaitForAltoToRelease:
	JSR	EnableMidas

	JSR	PacifyWatchdog

	LDA	CPControlDeadline
	CMP	Timer100ms
	BNE	DontComplainYet

	LDAI	CantGetCPControl
	JSR	SetProblem

DontComplainYet:
	LDA	MidasInhibitDepth

AltoWillNeverRelease:
	BNE	AltoWillNeverRelease

MaybeCPAvailNow:
	JSR	InhibitMidas

SeeWhosInCharge:
	LDA	CPRegH
	ANDI	AHasCP
	BNE	WaitForAltoToRelease

	LDAI	CantGetCPControl
	JSR	ClearProblem

	CLC
	PLA
	RTS


SetDeadline:
	LDA	Timer100ms
	CLC
	ADCI	10.	; complain after 1 second
	STA	CPControlDeadline
	RTS

;	Subroutines for left-shifting the 16-bit quantity CDatum,A

Left7:
	ASLA
	ROL	CDatum
Left6:
	ASLA
	ROL	CDatum
Left5:
	ASLA
	ROL	CDatum
Left4:
	ASLA
	ROL	CDatum
Left3:
	ASLA
	ROL	CDatum
Left2:
	ASLA
	ROL	CDatum
Left1:
	ASLA
	ROL	CDatum
	RTS

	.END