:TITLE[Timer]; *Last edited: 13 January 1981 by Fiala %OTHER TASKS USING TIMERS MUST GUARANTEE 6 CYCLES FROM WAKEUP TO LOADTIMER/ADDTOTIMER AND 8 CYCLES AFTER LOADTIMER/ADDTOTIMER BEFORE TASKING FOR THE REASONS GIVEN BELOW. Occurrences of LoadTimer and AddToTimer must be separated by 14 cycles, and branch conditions are illegal with LoadToTimer and AddToTimer. Here we fulfill the 14 cycle requirement by guaranteeing 6 cycles before LoadTimer/AddToTimer and 8 cycles after. Refresh must cycle fast enough to maintain storage. 16k ic's specification is a refresh period of 2 ms at maximum operating temperature (80 deg C). The leakage phenomenon which necessitates refresh is exponential in absolute temperature, about exp(-44*(300/T)) so required refresh rate goes up by a factor of 2 for every increase of 5 degrees C. Refresh at a 2 ms period is undesirable because about 4 percent of all cycles would be consumed by the timer task; the code below presently implements a refresh period of 8 ms, which gives up about 10 degrees in temperature margin, possibly requiring a few more marginal ic's to be replaced. In LoadTimer/AddToTimer, 0:3 are the new state, 4:11 new data, and 12:15 are the slot number. Setup the constant for a simple timer in slot 17b for refresh and realtime clock update (clock constant must be even). Clock period given below is for a cycle time of 100 ns (values larger than 16 ms require a double timer). Refresh period Clock constant RTimer value Clock period 2 ms 154b 50257b 64 us 4 ms 330b 50517b 128 us 8 ms 656b 51217b 256 us 16 ms 1534b 52417b 512 us The clock constant above is chosen so that when we add it to RTCLOW every tick, a carry will be produced at the same rate as the Alto clock. For the 64 us timer round, a carry every 65536/108 = 606.8 iterations. 606.8 * 64 = 38836 us; equivalent Alto number is 39009.5 us, so the clock will run slightly fast; for 256 us and slower periods, this is corrected to about 39016 us, almost the same as the Alto. % SetTask[TTask]; *Initialize Notifies here to set up timers (this is throwaway code) InitTimers: TimerTemp _ 100000C, At[TimerInitLoc]; ClrTimers: TimerTemp _ (LoadTimer[TimerTemp]) + 1; RSImage _ T _ 0C; REFR _ RS232 _ T; *Zap RS232, setup refresh pointer TimerBasehi _ T, ResetMemErrs; *Clear any pending memory errors *initialize high base register RTCLOW _ 1C; *Make RTCLOW odd so that clock updating won't *start until after memory initialization. RConstant _ 256C; RConstant _ (RConstant) or (400C); RTimer _ 51000C; *Set up the Refresh time LU _ (TimerTemp) and (17C); *clear 20b timers RTimer _ (RTimer) or (217C), Goto[ClrTimers,ALU#0]; LU _ Timer, LoadPage[TimerPage]; *read to clear pending wakeups LoadTimer[RTimer], GotoP[TimerSetTPC]; *load refresh timer OnPage[TimerPage]; TimerSetTPC: TimerBase _ 400C, Call[TimerRet]; *initialize low base register TimerWakeup: *Timer wakeups come here Dispatch[Timer,14,4]; *Since Refresh timer has the greatest effect on performance, do something *useful for it in this mi. T _ RConstant, Disp[.+1]; *Timer dispatch table for task 16 (not all entries are used) Refresh[REFR], Goto[RefreshNext], At[TimerTable,0] ;*slot 17 **NOTE: TimerTable 1, 3, 5, 6, 7, 10, 20, and 21 are overwritten by **Jasmine scanner microcode** SetFault, Goto[.], At[TimerTable,1]; *slot 16 SetFault, Goto[.], At[TimerTable,2]; *slot 15 SetFault, Goto[.], At[TimerTable,3]; *slot 14 SetFault, Goto[.], At[TimerTable,4]; *slot 13 SetFault, Goto[.], At[TimerTable,5]; *slot 12 SetFault, Goto[.], At[TimerTable,6]; *slot 11 SetFault, Goto[.], At[TimerTable,7]; *slot 10 SetFault, Goto[.], 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]; SetFault, Goto[.], At[TimerTable,12]; *slot 5 SetFault, Goto[.], At[TimerTable,13]; *slot 4 SetFault, Goto[.], At[TimerTable,14]; *slot 3 **Temporarily commented out for Audio.Mc debugging * SetFault, Goto[.], At[TimerTable,15]; *slot 2 * SetFault, Goto[.], At[TimerTable,16]; *slot 1 * SetFault, Goto[.], At[TimerTable,17]; *slot 0 *Reserve locations that can be overwritten by non-resident overlays which *use timers (reserve TimerTable 20 and 21 here; since 22 to 24 are used, *25 is the next one available if more are needed). IMReserve[0,Add[TimerTable,20],2]; *Notify for Ethernet output (Only one copy required) TEONotify: *Notify Ethernet output task, don't restart timer TimerTemp _ (TimerTemp) or (And[377,EOTimerDoneLoc]C); APCTask&APC _ TimerTemp; TimerRet: Return, At[TimerTable,24]; *Must be MouseHalt+1 for proper restarting. RefreshNext: AddToTimer[RTimer]; RTCLOW _ (RTCLOW) + T, Skip[R Even]; RTCLOW _ (Zero) + 1; *RTC has not been started yet. :IF[WithMidas]; ******************************* T _ (FFault) and (10000C), Goto[RTCUpd,Carry]; LU _ (Printer) and T; Skip[ALU#0]; *Skip if Midas present & mouse halt RTCRet: REFR _ (REFR) + (20C), Return; *increment the refresh address *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). MouseHalt: SetFault, Goto[.], At[TimerTable,23]; *Note: MC1 is busy for 20 cycles after Refresh, so the PFetch1 below will be *held for 11 cycles; when we take this path, we postpone checking for *Midas present and mouse halt until the next iteration. RTCUpd: T _ 30C; :ELSE; **************************************** T _ 30C, Goto[.+3,Carry]; Nop; *Ensure 8 cycles after AddToTimer RTCRet: REFR _ (REFR) + (20C), Return; :ENDIF; *************************************** PFetch1[TimerBase,TimerTemp]; *Increment VM 430 TimerTemp _ (TimerTemp) + 1; PStore1[TimerBase,TimerTemp], Goto[RTCRet]; SetTask[0]; OnPage[XMiscPage]; *Common subroutine for Mesa/Alto ReadClock. Takes 430b in T, returns *(VM 430) in RTemp, RTCLOW in T. MXRClk: PFetch1[MDS,RTemp]; RTemp1 _ IP[RTCLOW]C; T _ (SStkP&NStkP) xor (377C); StkP _ RTemp1, RTemp1 _ T, NoRegILockOK; T _ (Stack) and not (77C); *Return Most Significant 10d bits RestSP: StkP _ RTemp1, Return; *Restore StkP :END[Timer];(1795)\1651f8 141f0 2055f1 21f0 24f1 1f0 680f1 132f0