/ Technical Reference Manual
/ Chapter 10
System timing is controlled by two interrupts:
1. The NMI interrupt handles the real-time clock and auto-switch off
2. The KEYBOARD INTERRUPT provides a frame-counter and handles
keyboard delays and display timing etc.
10.1 REAL TIME CLOCK
The clock time is stored in binary in 6 fields from $20C5 to $20CA:
VARIABLE ADDRESS DESCRIPTION RANGE
======== ======= =========== =====
TMB_YEAR $20C5 YEAR 0 - 99
TMB_MONS $20C6 MONTH 0 - 11
TMB_DAYS $20C7 DATE OF MONTH 0 - 31
TMB_HOUR $20C8 HOUR 0 - 23
TMB_MINS $20C9 MINUTES 0 - 59
TMB_SECS $20CA SECONDS 0 - 59
1. A month of 0 represents JANUARY and a date of 0 represents the 1st
day of the month.
2. On a cold start only, the clock is initialised to 1 JAN 1987
3. The real-time clock should not be read directly from these
variables because it may be being updated by an NMI. Instead
system service TM$TGET should be used to get a valid time.
Similarly these variables should not be written to without
checking for an NMI.
10.1.1 KEEPING TIME WITH NMI ON
An NMI interrupt is generated from the semi-custom chip every second
to provide an accurate real-time clock. When the machine is on, the NMI
interrupt updates the time by 1 second, see TM$UPDT.
10.1.2 KEEPING TIME WITH NMI OFF
When NMIs are switched off the processor, (e.g. when the machine is
switched off) an internal counter in the semi-custom chip is connected to
the NMI line so that NMIs can still be counted, enabling the time to be
updated when restoring NMIs to the processor.
The counter has 11 bits, so the maximum time it can store is 2048 secs.
When the counter reaches this value, the ACOUT bit of PORT 5 goes high and
the machine switches on. Hence the machine can be forced to switch on
automatically at any time up to 34mins 8secs after switching off, be
pre-counting the counter. This is done when an alarm is due.
Whenever the machine switches on it updates the real-time clock by the
amount in the counter (less any pre-counting). If ACOUT is high, and no
alarm was due, the machine switches back off immediately after updating the
clock. This can be seen as the screen flashes on for an instant, every 34
mins and 8 secs while the machine is off.
To disable NMIs and keep the time, system services BT$NOF and BT$NON should
be used, see sections 5.7.3 and 5.7.4.
10.1.3 AUTO-SWITCH-OFF TIME OUT
The following three variables control the auto-switch-off:
VARIABLE ADDRESS DESCRIPTION
======== ======= ===========
TMB_SWOF $007C AUTO-SWITCH-OFF FLAG
TMW_TOUT $007D,$007E TIME LEFT BEFORE SWITCH OFF
TMW_TCNT $20CD,$20CE DEFAULT NUMBER OF SECONDS TO
The time before the machine switches off (in secs) is stored in TMW_TCNT
and is set to $012C on cold start (5 mins). The contents of TMW_TCNT are
copied into TMW_TOUT whenever a key is pressed or KB$GETK is called and
TMW_TOUT is decremented until zero by the NMI routine every second. If
TMW_TOUT is found to be zero in KB$TEST, the machine will switch off.
The contents of TMW_TCNT can be changed at any time to alter the
auto-switch-off time, up to a maximum of 65535 seconds (18 hours, 12 mins
and 15 secs). If it is set to less than 15, the machine will still
stay on for 15 secs.
To disable the auto-switch-off completely, TMB_SWOF should be set to zero.
This will inhibit the NMI from decrementing TMW_TOUT and prevent KB$TEST
10.2 KEYBOARD INTERRUPT TIMERS
The timer 1 compare interrupt is used to scan the keyboard to allow
keyboard buffering and to provide a timing service. The time between
interrupts is controlled by the variable KBW_TDEL which is initialised on
cold start to be $B3DD. This value makes the KI interrupt occur exactly
every 50 milliseconds and is used extensively by the operating system for
TMW_FRAM is incremented by 1 on each keyboard interrupt. When $ffff
is reached, it wraps back to $0000. It can be read at any time and used
for accurate timing.
DPW_REDY is decremented by 1 on each keyboard interrupt until zero is
reached. It can be used to provide delays (e.g. TM$WAIT stores D in
DPW_REDY and waits for it to reach zero - see below).
10.3 SYSTEM SERVICES
This section describes the operating system calls available for system
Note that TM$DAYV and TM$UPDT work from any buffer pointed to by X
containing a 6 byte time representation exactly like the real-time clock
(TMB_YEAR...). These routine should not operate on the real-time clock
itself if an NMI is imminent, so NMIs must be checked for or TM$TGET should
be used to copy the time to another buffer.
VECTOR NUMBER: 105
INPUT PARAMETERS: X register - Address of time buffer.
OUTPUT VALUES: B register - numeric value of day.
X register - address of 3 byte day name.
Calculates the day of the week for a given date between 1 JAN 1900
and 31 DEC 1999. X must point to the time buffer containing the
particular date in the standard format.
The numeric value of the day (0 to 6) is returned in the B register (0
represents MONDAY, 1 TUESDAY, etc) and X will point to the
corresponding 3 byte day name in ascii (MON,TUE,WED,THU,FRI,SAT or
The following routine will calculate and print the day for 2 JAN 1963:
LDX #BUFFER ;POINT TO TIME BUFFER
LDD #$3F00 ;YEAR 1963, MONTH JANUARY
LDA A,#$01 ;DATE 2ND
OS TM$DAYV ;CALCULATE DAY
LDA A, 3
PSH A ;DAY NAME LENGTH
PSHX ;ADDRESS OF DAY STRING
.BYTE D_FF ;CLEAR DISPLAY
.ASCIZ /%b/ ;PRINT DAY
VECTOR NUMBER: 106
INPUT PARAMETERS: X register - Address of 6 byte buffer to store
OUTPUT VALUES: None.
REGISTERS PRESERVED: X
Get a copy of the real-time clock into a buffer at x. It is not
possible to read the clock directly in case it is being updated by an
LDX #BUFFER ;X POINTS TO A 6 BYTE BUFFER
OS TM$TGET ;COPY TIME INTO BUFFER AT X
VECTOR NUMBER: 107
INPUT PARAMETERS: A register - Number of minutes to update.
B register - Number of seconds to update.
X register - Address of 6 byte buffer containing
OUTPUT VALUES: None.
Updates the time pointed to by X by A minutes and B seconds. A
and B must be in the range 0 - 59. X must point to the year field of
the 6 byte time buffer in standard format.
LDX #BUFFER ;POINT TO 6 BYTE BUFFER
OS TM$TGET ;GET REALTIME. PRESERVES X
LDD #$003B ;UPDATE BY 0 MINS 59 SECS.
OS TM$UPDT ;ADD 59 SECS TO TIME IN BUFFER
VECTOR NUMBER: 108
INPUT PARAMETERS: D register - Time to pause in ticks.
OUTPUT VALUES: None.
Waits for D ticks (1 tick is the interval between keyboard
interrupts, controlled by KBW_TDEL and set to 50ms by default). If
interrupts are disabled (I mask set) then this routine waits for D
LDD #20 ;20 x 50ms
OS TM$WAIT ;PAUSE FOR 1 SEC