{T1Thrash.mc, HGM, 13-Feb-85 22:15:16}

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

RegDef[flag, R, 0];
RegDef[address, R, 1];
  RegDef[rhAddr, RH, 1];

RegDef[statusMask, R, 02];

RegDef[length, R, 03];
RegDef[data, R, 04];
RegDef[key, R, 05];
RegDef[wordIncr, R, 06];
RegDef[packetIncr, R, 07];
RegDef[temp, R, 0D];

RegDef[good, U, 40];
RegDef[missedPackets, U, 41];
RegDef[wrongLength, U, 42];
RegDef[wrongData, U, 43];
RegDef[minLength, U, 44];
RegDef[maxLength, U, 45];
RegDef[passCount, U, 46]; {number of good passes}


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: 	good ← 0,						c1;
	missedPackets ← 0,					c2;
	wrongLength ← 0,					c3;

 	wrongData ← 0,						c1;
	Noop,							c2;
	Noop,							c3;

	passCount ← 0, ClrIntErr,				c1;
	ExtCtrl ← 5, {Init Incr, Zero, UnBlank}			c2;
	GOTO[Start],						c3;


{------------------------------------------------------------------------------------}
Start:
	address ← 20,						c1;
	address ← address LRot8 {2080}				c2;
	rhAddr ← 0,						c3;

	Noop,							c1;
	temp ← 080,						c2;
	temp ← temp LRot8, {8000}				c3;
	
	IO ← [rhAddr, address + 2], {control}			c1;
	MDR ← temp, {Reset}					c2;
	Noop,							c3;

CheckSwitches:
	IO ← [rhAddr, address + 3], {Switches}			c1;
	Noop,							c2;
	Q ← MD,							c3;

	[] ← Q xor 000, ZeroBr,					c1;
	BRANCH[$, SwitchesAll0s],				c2;
	temp ← 0FF,						c3;

	[] ← Q xor temp, ZeroBr,				c1;
	BRANCH[$, SwitchesAll1s],				c2;
	Noop,							c3;

BoardSetup:
	temp ← 098,						c1;
	temp ← temp LRot8, {9800}				c2;
	Noop,							c3;
	
	IO ← [rhAddr, address + 2], {control}			c1;
	MDR ← temp, {reset, accept, no int}			c2;
	temp ← 0,						c3;

FilterSetup:
	IO ← [rhAddr, address + 3], {Address Filter RAM}	c1;
	MDR ← temp,						c2;
	Noop,							c3;

	Noop,							c1;
	temp ← temp + 1, PgCarryBr,				c2;
	BRANCH[FilterSetup, $],					c3;

	IO ← [rhAddr, address + 2], {control}			c1;
	MDR ← 0, {go}						c2;
	Noop,							c3;

	Noop,							c1;
	temp ← 030,						c2;
	temp ← temp LRot8, {3000}				c3;

DrainAnotherWord:
	IO ← [rhAddr, address + 0], {data}			c1;
	Noop,							c2;
	Xbus ← MD,						c3;

	Noop,							c1;
	temp ← temp-1, ZeroBr,					c2;
	BRANCH[DrainAnotherWord, $],				c3;

NewLength:
	length ← minLength,					c1;
	Noop,							c2;
	Noop,							c3;

MainLoop:
	IO ← [rhAddr, address + 3], {Switches}			c1;
	Noop,							c2;
	Q ← MD,	{Clear Tran Int}				c3;

	IO ← [rhAddr, address + 2], {status}			c1;
	Noop,							c2;
	Q ← MD,							c3;

	Noop,							c1;
	[] ← Q, NegBr,						c2;
	BRANCH[$, TranAlreadyInterrupting],			c3;

SendPacket:
	IO ← [rhAddr, address + 0], {data}			c1;
	MDR ← temp ← length,					c2;
	data ← key,						c3;

SendAnotherWord:
	IO ← [rhAddr, address + 0], {data}			c1;
	MDR ← data,						c2;
	Noop,							c3;

	data ← data + wordIncr,					c1;
	temp ← temp-1, ZeroBr,					c2;
	BRANCH[SendAnotherWord, $],				c3;

	Noop,							c1;
	temp ← 0,						c2;
	temp ← temp-1, {FFFF}					c3;

SendDally:
	IO ← [rhAddr, address + 2], {status}			c1;
	Noop,							c2;
	Q ← MD,							c3;

	Noop,							c1;
	[] ← Q, NegBr,						c2;
	BRANCH[$, TranInterrupted],				c3;

	Noop,							c1;
	temp ← temp-1, ZeroBr,					c2;
	BRANCH[SendDally, NoTranInterrupt],			c3;

TranInterrupted:
	Noop,							c1;
	temp ← 02,						c2;
	temp ← temp LRot8, {0200}				c3;

TranDally:
	Noop, {Wait for packet to get around}			c1;
	temp ← temp-1, ZeroBr,					c2;
	BRANCH[TranDally, $],					c3;

CheckPacket:
	IO ← [rhAddr, address + 0], {data}			c1;
	flag ← 0,						c2;
	Q ← MD, {Should be 8xxx}				c3;

	Noop,							c1;
	[] ← Q, NegBr,						c2;
	BRANCH[BuffferNotEmpty, $],				c3;

	IO ← [rhAddr, address + 0], {data}			c1;
	Noop,							c2;
	Q ← MD,	{Should be length+1}				c3;

	Q ← Q and ~statusMask,					c1;
	[] ← Q, NegBr,						c2;
	BRANCH[$, MissedThePacket],				c3;

	Q ← Q - 1,						c1;
	[] ← Q xor length, ZeroBr,				c2;
	BRANCH[WrongLength, $],					c3;

	Noop,							c1;
	data ← key,						c2;
	temp ← length,						c3;

CheckData:
	IO ← [rhAddr, address + 0], {data}			c1;
	Noop,							c2;
	Q ← MD,	{Should be data}				c3;

	Noop,							c1;
	[] ← Q xor data, ZeroBr,				c2;
	BRANCH[WrongData, $],					c3;

WrongDataRestart:
	data ← data + wordIncr,					c1;
	temp ← temp-1, ZeroBr,					c2;
	BRANCH[CheckData, $],					c3;

CheckCrc:
	IO ← [rhAddr, address + 0], {data}			c1;
	Noop,							c2;
	Xbus ← MD, {Discard CRC}				c3;

{Delay to keep SUN boards happy}
	Noop,							c1;
	Noop,							c2;
	Noop,							c3;

CheckEmptyAgain:
	IO ← [rhAddr, address + 0], {data}			c1;
	Noop,							c2;
	Q ← MD,							c3;

	Noop,							c1;
	[] ← Q, NegBr,						c2;
	BRANCH[BuffferNotEmptyAgain, $],			c3;

	Noop,							c1;
	[] ← flag, ZeroBr,					c2;
	BRANCH[WrongDataThisPacket, $],				c3;

	Q ← good,						c1;
	Q ← Q + 1,						c2;
	good ← Q,						c3;

	Noop,							c1;
	Q ← Q and 0F0,				 		c2;
	ExtCtrl ← Q or 7, {DP ← good/16}	 		c3;

	Q ← maxLength,				 		c1;
	[] ← length - Q, ZeroBr,				c2;
	length ← length + 1, BRANCH[MainLoop, $],		c3;

	Q ← key,				 		c1;
	Q ← Q + packetIncr,					c2;
	key ← Q,						c3;

	Q ← passCount,				 		c1;
	Q ← Q + 1,						c2;
	passCount ← Q,						c3;

	Noop,							c1;
	ExtCtrl ← 3, {Gets Bumped on rising edge} 		c2;
	ExtCtrl ← 7, GOTO[NewLength],				c3;
	
WrongDataThisPacket:
	ExtCtrl ← 5, {Init Incr, Zero, UnBlank} 		c1;
	Noop,							c2;
	GOTO[MainLoop],						c3;
	

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

SwitchesAll0s:
	GOTO[Restartc1],					c3;
	
SwitchesAll1s:
	GOTO[Restartc1],					c3;
	
TranAlreadyInterrupting:
	GOTO[Restartc2],					c1;
	
NoTranInterrupt:
	GOTO[Restartc2],					c1;
	
NoRecvInterrupt:
	GOTO[Restartc2],					c1;
	
BuffferNotEmpty:
	GOTO[Restartc2],					c1;
	
MissedThePacket:
	Q ← missedPackets,					c1;
	Q ← Q + 1,						c2;
	missedPackets ← Q, GOTO[Restartc1],			c3;
	
WrongLength:
	Q ← wrongLength,					c1;
	Q ← Q + 1,						c2;
	wrongLength ← Q, GOTO[Restartc1],			c3;
	
WrongData:
	Q ← wrongData,						c1;
	Q ← Q + 1,						c2;
	wrongData ← Q,						c3;
	
	Noop,							c1;
	Noop,							c2;
	flag ← 1, GOTO[WrongDataRestart],			c3;
	
BuffferNotEmptyAgain:
	GOTO[Restartc2],					c1;
	
Restartc2:
	Noop,							c2;
Restartc3:
	Noop,							c3;
	
Restartc1:
	Q ← 0FF,						c1;
	Noop,							c2;
RestartLoop:
	Noop,							c3;

	Q ← Q - 1, ZeroBr,					c1;
	BRANCH[RestartLoop, $],					c2;
	ExtCtrl ← 5, GOTO[Start], {Init Incr, Zero, UnBlank}	c3;

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

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

BufferEmptyLoop:
	IO ← [rhAddr, address + 0], {data}			c1;
	Noop,							c2;
	Q ← MD, {Should be 8xxx}				c3;

	temp ← temp + 1,					c1;
	[] ← Q, NegBr,						c2;
	BRANCH[$, BufferEmptyLoop],				c3;

BufferEmptyBug:
	temp ← 0,						c1;
	ExtCtrl ← 3, {Gets Bumped on rising edge} 		c2;
	ExtCtrl ← 7, GOTO[BufferEmptyLoop],			c3;
{------------------------------------------------------------------------------------}