:TITLE[Timer];

SetTask[TTask];
OnPage[TimerInitPage];
*Initialize Notifies here to set up timers (this is throwaway code)
InitTimers:
TimerTemp ← (100000C), at[TimerInitLoc];
ClrTimers:
LoadTimer[TimerTemp]; *Clear out all Timers
RSImage ← T ← 0C;
RS232 ← T; *Zap RS232
RTimer ← (50000C);*Set up the Refresh time
RTimer ← (RTimer) OR (257C);*simple timer,value 10d,slot 17b
TimerTemp ← (TimerTemp) + 1, ResetMemErrs; *Clear any pending memory errors
LU ← (TimerTemp) AND (17C);*there are 16d timers
REFR ← T ← (0C), dblgoto[InitDone, ClrTimers, ALU=0];
InitDone:
LU ← Timer; *read to clear pending wakeups
LOADTIMER[RTimer]; *load refresh timer
TimerBasehi ← T, loadpage[TimerPage]; *initialize high base register
RTCLOW ← 1c, gotop[TimerSetTPC]; *RTCLOW is made odd so that timer updating won’t start
*until the memory has been initialized.

Onpage[TimerPage];
TimerSetTPC: call[TimerRet];
*Timer wakeups come here
TimerWakeup:
*Timer wakeups come here
Dispatch[Timer,14,4];
TimerBase ← 400c, DISP[Timers]; *initialize low base register

*Timer dispatch table for task 16 (all entries are not used)
Timers:
Refresh[REFR], goto[RefreshNext], AT[TimerTable,00] ;*slot 17
goto[BadTimerWake], T ← 16c, AT[TimerTable,01]; *slot 16
goto[BadTimerWake], T ← 15c, AT[TimerTable,02]; *slot 15
goto[BadTimerWake], T ← 14c, AT[TimerTable,03]; *slot 14
goto[BadTimerWake], T ← 13c, AT[TimerTable,04]; *slot 13
goto[BadTimerWake], T ← 12c, AT[TimerTable,05]; *slot 12
goto[BadTimerWake], T ← 11c, AT[TimerTable,06]; *slot 11
goto[BadTimerWake], T ← 10c, AT[TimerTable,07]; *slot 10
goto[BadTimerWake], T ← 7c, AT[TimerTable,10]; *slot 7
*Ethernet Output Notify slot (Add copies with EOTask1, EOTask2 ... if multiple controllers).
TimerTemp ← OR[lshift[EOTask,14],AND[7400,EOTimerDoneLoc]]C, GOTO[TEONotify], AT[TimerTable,11];
goto[BadTimerWake], T ← 5c, AT[TimerTable,12]; *slot 5
goto[BadTimerWake], T ← 4c, AT[TimerTable,13]; *slot 4
goto[BadTimerWake], T ← 3c, AT[TimerTable,14]; *slot 3
goto[BadTimerWake], T ← 2c, AT[TimerTable,15]; *slot 2
goto[BadTimerWake], T ← 1c, AT[TimerTable,16]; *slot 1
goto[BadTimerWake], T ← 0c, AT[TimerTable,17]; *slot 0

*Wrong value in timer dispatch comes here with channel number in T:
BadTimerWake: Breakpoint, return;

*Notify for Ethernet output (Only one copy required)
TEONotify:
TimerTemp ← (TimerTemp) or (AND[0377, EOTimerDoneLoc]C); * Low 8 bits of APC
APC&APCTask ← TimerTemp; *Notify Ethernet output task, don’t restart timer
TimerRet:return, AT[TimerTable,24]; *Must be MouseHalt+1 for proper restarting.

*Refresh has been started.
RefreshNext:
AddToTimer[RTIMER]; *load the refresh timer

* check for Midas halt
CheckMidas:
T ← (FFAULT) and (10000c);* check for Midas present and mouse halt
lu ← (PRINTER) and (T);
dblgoto[MouseHalt,CheckRTC,ALU#0];


MouseHalt:
goto[.], SETFAULT, AT[TimerTable,23]; *Midas mouse halt is a task 16 breakpoint that was
*not set by the user. Midas continues by going to location 7004 (which contains a return).

CheckRTC:
RTCLOW ← (RTCLOW) + (154c), dblgoto[RTCOff,UpdateRTC, ROdd];


RTCOff:
RTCLOW ← 1c, goto[RTCRet]; *RTC has not been started yet.

*Check for RTC update required.
*The real time clock is set up for 100nsec main clock rate, i.e. 64us/timer round.
*Each tick, we add 108d (154b) to RTCLOW, which will cause it to carry every
*65536/108 = 606.8 times the code is run. 606.8 * 64 = 38836us. The equivalent
*Alto number is 39009.5us, so the clock will run slightly fast.

UpdateRTC:

T ← 30c, skip[carry]; *RTCLOW overflowed. Increment VM 430
RTCRet:
REFR ← (REFR) + (20C), return; *increment the refresh address
PFetch1[TimerBase,TimerTemp]; *Increment VM 430
TimerTemp ← (TimerTemp)+1;
PStore1[TimerBase,TimerTemp], goto[RTCRet];

:END[Timer];