{ClockTest.mc, HGM,  4-Nov-84  2:29:29}

	Reserve[0F5F, 0FFF]; {section used by the CP Kernel }
	SetTask[0]; StartAddress[Go];

RegDef[LoopCount, R, 0];
RegDef[address, R, 1];
  RegDef[rhAddr, RH, 1];
RegDef[found, R, 4];
RegDef[status, R, 5];

RegDef[oldClockLo, R, 06];
RegDef[oldClockHi, R, 07];
RegDef[clockLo, R, 08];
RegDef[clockHi, R, 09];
RegDef[clockP, R, 0A];
RegDef[ticks, R, 0B];
RegDef[ints, R, 0C];

RegDef[temp, R, 0D];
RegDef[LSB, R, 0E];

RegDef[oldLSB, U, 00];

RegDef[u16, U, 016];
RegDef[u17, U, 017];
RegDef[u18, U, 018];
RegDef[u19, U, 019];


Trap:	temp ← RRot1 ErrnIBnStkp, ClrIntErr, CANCELBR[$, 0F],	c1, at[0];
	Xbus ← temp LRot0, XwdDisp,				c2;
	DISP2[TrapType],					c3;
	
Parity:	GOTO[GoToGo],						c1, at[0,4,TrapType];
Init:	GOTO[GoToGo],						c1, at[1,4,TrapType];
Stack:	GOTO[GoToGo],						c1, at[2,4,TrapType];
IB:	GOTO[GoToGo],						c1, at[3,4,TrapType];

GoToGo:
	Noop,							c2;
	Noop, GOTO[Go],						c3;

Go:     rhAddr ← 4, {Timers}					c1;
	address ← 90,						c2;
	address ← address LRot8 {9000},				c3;

Restart:
	LoopCount ← 0, ClrIntErr,				c1;
	ExtCtrl ← 5, {Init Incr, Zero, UnBlank}			c2;
	GOTO[MainLoop],						c3;


MainLoop:
	ticks ← 0,						c1;
	Noop,							c2;
	ExtCtrl ← 5, {Init Incr, Zero, UnBlank}			c3;

	IO ← [rhAddr, address + 0], {Master Interrupt Control}	c1;
	MDR ← 0, {UnReset}					c2;
	temp ← address + 10,					c3;

	IO ← [rhAddr, address + 0], {Master Interrupt Control}	c1;
	MDR ← 0, {UnReset}					c2;
	temp ← address + 10,					c3;

	IO ← [rhAddr, temp + 06], {Cnt1 MSB}			c1;
	MDR ← 0,						c2;
	Noop,							c3;

	IO ← [rhAddr, temp + 07], {Cnt1 LSB}			c1;
	MDR ← 0,						c2;
	Noop,							c3;

	IO ← [rhAddr, temp + 08], {Cnt2 MSB}			c1;
	MDR ← 0,						c2;
	Noop,							c3;

	IO ← [rhAddr, temp + 09], {Cnt2 LSB}			c1;
	MDR ← 0,						c2;
	Noop,							c3;

{PClk = 400ns.  Counter runs off PClk/2.  50ms => count should be 62500 = F424.}
	IO ← [rhAddr, temp + 0A], {Cnt3 MSB}			c1;
	MDR ← 0F4,						c2;
	Noop,							c3;

	IO ← [rhAddr, temp + 0B], {Cnt3 LSB}			c1;
	MDR ← 24,						c2;
	Noop,							c3;

	IO ← [rhAddr, temp + 0C], {Cnt 1 Mode}			c1;
	MDR ← 0A0, {Ext In, Pulse}				c2;
	Noop,							c3;

	IO ← [rhAddr, temp + 0D], {Cnt 2 Mode}			c1;
	MDR ← 080, {Pulse}					c2;
	Noop,							c3;

	IO ← [rhAddr, temp + 0E], {Cnt 3 Mode}			c1;
	MDR ← 080, {Pulse}					c2;
	temp ← address + 20,					c3;

	IO ← [rhAddr, temp + 0B], {Port B Direction}		c1;
	MDR ← 0FF, {All in}					c2;
	temp ← address + 10,					c3;

	IO ← [rhAddr, address + 06], {Port C Direction}		c1;
	MDR ← 0F, {All in.  Beware of Boot'}			c2;
	Noop,							c3;

	IO ← [rhAddr, address + 1], {Master Config Control}	c1;
	MDR ← 0F3, {Enables, Link Timers}			c2;
	Noop,							c3;

	IO ← [rhAddr, address + 0A], {Counter 1 Cntrl}		c1;
	MDR ← 06, {Trgr}					c2;
	Noop,							c3;

	IO ← [rhAddr, address + 0B], {Counter 2 Cntrl}		c1;
	MDR ← 06, {Trgr}					c2;
	Noop,							c3;

	IO ← [rhAddr, address + 0C], {Counter 3 Cntrl}		c1;
	MDR ← 0C6, {Set IE, Trgr}				c2;
	Noop,							c3;

	IO ← [rhAddr, address + 0], {Master Interrupt Control}	c1;
	MDR ← 080, {MIE}					c2;
	temp ← address + 10,					c3;

LoadOldClock:
	IO ← [rhAddr, address + 0B], {Counter 2 Cntrl}		c1;
	MDR ← 0C, {RCC and GCB}					c2;
	oldClockLo ← found,					c3;

	IO ← [rhAddr, temp + 02], {Cnt 2 MSB}			c1;
	Noop,							c2;
	found ← MD,						c3;

	IO ← [rhAddr, temp + 03], {Cnt 2 LSB}			c1;
	found ← found LRot8,					c2;
	found ← found or MD,					c3;

	Noop,							c1;
	Noop,							c2;
	clockHi ← found,					c3;

WaitForTick:
{Ouch, this isn't needed at 16MHZ, but it is at 10.}
	IO ← [rhAddr, address + 0C], {Counter 3 Cntrl}		c1;
	MDR ← 0A4, {Reset IP, GCB}				c2;
	Noop,							c3;

	IO ← [rhAddr, address + 0A], {Counter 1 Cntrl}		c1;
	MDR ← 0C, {RCC and GCB}					c2;
	Noop,							c3;
	
	IO ← [rhAddr, temp + 00], {Cnt 1 MSB}			c1;
	Noop,							c2;
	found ← MD,						c3;

	IO ← [rhAddr, temp + 01], {Cnt 1 LSB}			c1;
	found ← found LRot8,					c2;
	found ← found or MD,					c3;

	Noop,							c1;
	Noop,							c2;
	oldClockLo ← found,					c3;

	IO ← [rhAddr, address + 0B], {Counter 2 Cntrl}		c1;
	MDR ← 0C, {RCC and GCB}					c2;
	Noop,							c3;

	IO ← [rhAddr, temp + 02], {Cnt 2 MSB}			c1;
	Noop,							c2;
	found ← MD,						c3;

	IO ← [rhAddr, temp + 03], {Cnt 2 LSB}			c1;
	found ← found LRot8,					c2;
	found ← found or MD,					c3;

	Noop,							c1;
	Noop,							c2;
	oldClockHi ← found,					c3;

	Noop,							c1;
	[] ← clockHi - oldClockHi, ZeroBr,			c2;
	BRANCH[$, WaitForTick],					c3;

	Noop,							c1;
	Noop,							c2;
	Noop,							c3;

ClockLoop:
	IO ← [rhAddr, address + 0A], {Counter 1 Cntrl}		c1;
	MDR ← 0C, {RCC and GCB}					c2;
	Noop,							c3;

	IO ← [rhAddr, temp + 00], {Cnt 1 MSB}			c1;
	Noop,							c2;
	found ← MD,						c3;

	IO ← [rhAddr, temp + 01], {Cnt 1 LSB}			c1;
	found ← found LRot8,					c2;
	found ← found or MD,					c3;

	IO ← [rhAddr, address + 0B], {Counter 2 Cntrl}		c1;
	MDR ← 0C, {RCC and GCB}					c2;
	clockLo ← found,					c3;

	IO ← [rhAddr, temp + 01], {Cnt 1 LSB}			c1;
	Noop,							c2;
	LSB ← MD,						c3;

	IO ← [rhAddr, temp + 02], {Cnt 2 MSB}			c1;
	Noop,							c2;
	found ← MD,						c3;

	IO ← [rhAddr, temp + 03], {Cnt 2 LSB}			c1;
	found ← found LRot8,					c2;
	found ← found or MD,					c3;

	Noop,							c1;
	Noop,							c2;
	clockHi ← found,					c3;

	IO ← [rhAddr, address + 0C], {Counter 3 Cntrl}		c1;
	MDR ← 0C, {RCC and GCB}					c2;
	Noop,							c3;

	IO ← [rhAddr, temp + 04], {Cnt 3 MSB}			c1;
	Noop,							c2;
	found ← MD,						c3;

	IO ← [rhAddr, temp + 05], {Cnt 3 LSB}			c1;
	found ← found LRot8,					c2;
	found ← found or MD,					c3;

	IO ← [rhAddr, address + 0C], {Counter 3 Status}		c1;
	clockP ← found,						c2;
	found ← MD,						c3;


CheckClock:
	Noop,							c1;
	[] ← oldClockLo - clockLo, ZeroBr,			c2;
	BRANCH[$, ClockLoDidntTick],				c3;

	Q ← oldClockLo - clockLo,				c1;
	[] ← Q and ~07, NZeroBr,				c2;
	BRANCH[$, ClockLoBackwards],				c3;

	Q ← oldClockHi - clockHi,				c1;
	[] ← Q and ~01, NZeroBr,				c2;
	BRANCH[$, ClockHiBackwards],				c3;

	oldLSB ← LSB,						c1;
	oldClockLo ← clockLo,					c2;
	oldClockHi ← clockHi,					c3;
	
	LoopCount ← LoopCount + 1,				c1;
	MesaIntBr,						c2;
	ints ← ExtStat, BRANCH[ClockLoop, ClockInt],		c3;

ClockInt:
	IO ← [rhAddr, address + 0C], {Counter 3 Cntrl}		c1;
	MDR ← 0A4, {Reset IP, GCB}				c2;
	ticks ← ticks + 1,					c3;

{Beware: If the ClrIntErr happens too soon, we will get 2 interrupts on each tick.}
	ExtCtrl ← 3, {Gets Bumped on rising edge} 		c1;
	ExtCtrl ← 7,						c2;
	ClrIntErr, GOTO[ClockLoop],				c3;
{------------------------------------------------------------------------------------}

ClockSpin:
	IO ← [rhAddr, temp + 01], {Cnt 1 LSB}			c1;
	ExtCtrl ← 5, {Init Incr, Zero, UnBlank}			c2;
	clockLo ← MD,						c3;

ClockSpinAgain:
	IO ← [rhAddr, address + 0A], {Counter 1 Cntrl}		c1;
	MDR ← 0C, {RCC and GCB}					c2;
	Noop,							c3;
	
	IO ← [rhAddr, temp + 01], {Cnt 1 LSB}			c1;
	oldClockLo ← clockLo,					c2;
	clockLo ← MD,						c3;

	Noop, c1;  Noop, c2;  Noop, c3;
	Noop, c1;  Noop, c2;  Noop, c3;
	Noop, c1;  Noop, c2;  Noop, c3;
	Noop, c1;  Noop, c2;  Noop, c3;
	Noop, c1;  Noop, c2;  Noop, c3;
	
	Noop, c1;  Noop, c2;  Noop, c3;
	Noop, c1;  Noop, c2;  Noop, c3;
	Noop, c1;  Noop, c2;  Noop, c3;
	Noop, c1;  Noop, c2;  Noop, c3;
	Noop, c1;  Noop, c2;  Noop, c3;
	
	Noop,							c1;
	Q ← oldClockLo - clockLo, ZeroBr,			c2;
	Q ← Q and 0FF, BRANCH[$, ClockSpinAgain],		c3;

	Noop,							c1;
	[] ← Q and ~7, NZeroBr,					c2;
	BRANCH[$, ClockSpinQuirk],				c3;

ClockSpinTicked:
	Noop, 							c1;
	Noop,							c2;
	LoopCount ← LoopCount + 1, GOTO[ClockSpinAgain],	c3;

ClockSpinQuirk:
	ExtCtrl ← 3, {Gets Bumped on rising edge} 		c1;
	ExtCtrl ← 7,						c2;
	LoopCount ← 0, GOTO[ClockSpinAgain],			c3;

{------------------------------------------------------------------------------------}

ClockLoDidntTick:
	LoopCount ← 0,						c1;
	ExtCtrl ← 5, {Init Incr, Zero, UnBlank}			c2;
	GOTO[LoadOldClock],					c3;

ClockLoBackwards:
	LoopCount ← 0,						c1;
	ExtCtrl ← 5, {Init Incr, Zero, UnBlank}			c2;
	GOTO[LoadOldClock],					c3;

ClockHiBackwards:
	LoopCount ← 0,						c1;
	ExtCtrl ← 5, {Init Incr, Zero, UnBlank}			c2;
	GOTO[LoadOldClock],					c3;

RCCAlreadySet:
	LoopCount ← 0,						c1;
	ExtCtrl ← 5, {Init Incr, Zero, UnBlank}			c2;
	GOTO[LoadOldClock],					c3;

RCCNotSet:
	LoopCount ← 0,						c1;
	ExtCtrl ← 5, {Init Incr, Zero, UnBlank}			c2;
	GOTO[LoadOldClock],					c3;

SnarfGoodies:
	IO ← [rhAddr, temp + 06], {Cnt1 MSB}			c1;
	Noop,							c2;
	Q ← MD,							c3;

	IO ← [rhAddr, temp + 07], {Cnt1 LSB}			c1;
	u16 ← Q,						c2;
	Q ← MD,							c3;

	IO ← [rhAddr, temp + 08], {Cnt2 MSB}			c1;
	u17 ← Q,						c2;
	Q ← MD,							c3;

	IO ← [rhAddr, temp + 09], {Cnt2 LSB}			c1;
	u18 ← Q,						c2;
	Q ← MD,							c3;

	Noop,							c1;
	u19 ← Q,						c2;
	Noop,							c3;

SnarfedGoodies:
	Noop,							c1;
	Noop,							c2;
	GOTO[Restart],						c3;

ResetTheChip:
	IO ← [rhAddr, address + 0], {Master Interrupt Control}	c1;
	MDR ← 1, {Reset}					c2;
	temp ← address + 10,					c3;

	IO ← [rhAddr, address + 0], {Master Interrupt Control}	c1;
	MDR ← 0, {UnReset}					c2;
	GOTO[Restart],						c3;

{------------------------------------------------------------------------------------}