Clock

This file is part of and Timex Sinclair Public Domain Library Tape 1007. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Home

This program implements an analogue clock display, drawing a clock face with numbered hour positions and animating minute and hour hands. The clock face is drawn using trigonometric positioning (COS and SIN with PI) to place digits 1–12 around a circle, switching to FAST mode during rendering. Line-drawing between two points is handled by a Bresenham-style integer line algorithm in the subroutine at line 1000, which uses SGN and ABS to step along the major axis while accumulating error in variable S. The minute hand is erased and redrawn each tick using PLOT/UNPLOT controlled by the variable P, with timing regulated by POKE 16437 and a PEEK busy-wait loop plus PAUSE 219. Time is input in HHMM format, with the hours variable H computed from hundreds digits and incremented at the 15- and 45-minute marks.


Program Analysis

Program Structure

The program is divided into several logical sections:

  1. Initialisation (lines 12–22): Accepts time in HHMM format, decodes hours and minutes, and pre-computes the initial hour-hand position in H.
  2. Clock face drawing (lines 24–65): Clears screen, switches to FAST mode, plots hour digits 1–12 using trigonometry, then returns to SLOW mode. Sets the interrupt counter via POKE 16437,250.
  3. Main animation loop (lines 70–240): Alternates between erasing the old minute-hand position (via GOSUB 1000 with P=0) and drawing the new one (P=1), with the hour hand drawn at each tick via GOSUB 310.
  4. Hour-hand subroutine (lines 310–380): Draws a line from the centre (27,22) to the hour-hand endpoint using the Bresenham subroutine.
  5. Save stub (lines 490–510): CLEAR, SAVE, and RUN for persistence.
  6. Line-drawing subroutine (lines 1000–1260): A general integer Bresenham line-draw routine controllable via P (1=PLOT, 0=UNPLOT).

Time Input and Decoding

Time is entered as a four-digit integer in HHMM format (e.g. 1430 for 2:30 PM). Line 16 extracts hours: H=2*INT(T/100) — note the factor of 2, which converts 12-hour clock hours into half-hour units matching the half-PI step used in the hour-hand calculation. Lines 18–22 strip the hour part, leaving minutes in T, then add 1 to H if past the quarter-hour and again if past the three-quarter mark, giving a coarse hour-hand position in 30-minute increments.

Clock Face Rendering

The hour numerals are positioned using:

  • Row: 10 - 10*COS(D/6*PI)
  • Column: 13 + 10*SIN(D/6*PI)

This maps D=1..12 evenly around a circle using PRINT AT in character coordinates. The clock face is rendered in FAST mode (line 26) to avoid slow screen updates, then SLOW is restored (line 60) before animation begins.

Timing Mechanism

Timing is achieved through a combination of hardware manipulation and busy-waiting. POKE 16437,250 sets the ZX81 frame counter (FRAMES system variable at address 16437) to 250. The loop at line 230 polls PEEK 16437 until it falls below 241, effectively waiting approximately 9 frame intervals (~9/50 s). PAUSE 219 at line 235 then waits a further 219 frames, giving a combined delay approximating one minute per tick of the minute hand — though this is a rough approximation rather than a precise real-time second counter.

Bresenham Line Algorithm (lines 1000–1260)

The subroutine implements a Bresenham-style integer line algorithm. It accepts start point (A,B) implicitly set to (27,22) — the screen centre — and endpoint (C,D). Key variables:

VariableRole
U, Vdx, dy from centre to endpoint
O, LSGN of dx, dy (step direction)
Z, QMajor-axis step (0 or SGN)
M, NMajor and minor axis lengths
SBresenham error accumulator, initialised to M/2
P1 = PLOT, 0 = UNPLOT

The algorithm swaps axes if the vertical span is larger than the horizontal (lines 1080–1120), ensuring it always steps along the longer dimension. Error accumulation occurs at line 1170 (S=S+N), with the diagonal step taken when S≥M.

Note that lines 1040 (LET Z=SGN U) and 1130 (absent — the label after the conditional block) reveal a minor structural issue: line 1040 initialises Z to SGN U, but this is immediately overridden by line 1090 (LET Z=0) if the vertical span dominates, so the initialisation at 1040 is only effective when M≤N is false — which is correct behaviour. However, there is no line 1130 in the listing (the FOR loop at 1150 follows directly), indicating the GOTO 1130 at line 1080 jumps to line 1140 as the next available line — a standard ZX81 BASIC behaviour where GO TO targets the nearest line at or above the specified number.

Hand Erase-Redraw Cycle

The animation loop erases the previous minute-hand position before drawing the new one. At line 80, P is set to 0 (UNPLOT mode) and the old endpoint (X,Y) is used to call the line subroutine, erasing the hand. Then P=1 and the new endpoint is computed and plotted. The hour hand (subroutine at line 310) is drawn after each minute update but is never explicitly erased, relying on the clock-face redraw (GOTO 24 at line 260) when the hour changes.

Notable Idioms and Anomalies

  • The factor of 2 in H=2*INT(T/100) and the use of H/12*PI for the hour-hand angle means the hour hand completes a half-turn (PI radians) per 12 increments of H — correctly placing it at the top (12 o’clock) when H=0 and at the bottom (6 o’clock) when H=12.
  • The minute-hand angle uses T/30*PI, mapping 0–59 minutes to 0–~2PI correctly.
  • Lines 140 and 260 handle the quarter-hour increments of the hour hand: at T=16 or T=46 (just past the quarter and three-quarter marks), the program jumps to line 250, increments H, and redraws the full clock face.
  • The CLEAR at line 490 before the SAVE is unusual; it would erase all variables before saving, meaning the saved program starts fresh on load.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10294-10335.

Related Products

Related Articles

Related Content

Image Gallery

Clock

Source Code

  12 PRINT "  INPUT TIME"
  14 INPUT T
  16 LET H=2*INT (T/100)
  18 LET T=T-100*INT (T/100)
  20 IF T>15 THEN LET H=H+1
  22 IF T>45 THEN LET H=H+1
  24 CLS 
  26 FAST 
  30 FOR D=1 TO 12
  40 PRINT AT 10-10*COS (D/6*PI),13+10*SIN (D/6*PI);D
  50 NEXT D
  60 SLOW 
  65 POKE 16437,250
  70 GOTO 150
  80 LET P=0
  90 LET C=X
 100 LET D=Y
 110 GOSUB 1000
 120 LET T=T+1
 130 IF T=60 THEN LET T=0
 140 IF T=16 OR T=46 THEN GOTO 250
 150 LET P=1
 160 LET L=T/30*PI
 170 LET X=27+18*SIN L
 180 LET Y=22+18*COS L
 190 LET C=X
 200 LET D=Y
 210 GOSUB 1000
 220 GOSUB 310
 230 IF PEEK 16437>241 THEN GOTO 230
 235 PAUSE 219
 240 GOTO 80
 250 LET H=H+1
 260 GOTO 24
 310 LET P=1
 320 LET A=27
 330 LET B=22
 340 LET G=H/12*PI
 350 LET C=27+12*SIN G
 360 LET D=22+12*COS G
 370 GOSUB 1000
 380 RETURN 
 490 CLEAR 
 500 SAVE "1031%8"
 510 RUN 
\n1000 LET A=27
\n1002 LET B=22
\n1008 LET U=C-A
\n1010 LET V=D-B
\n1020 LET O=SGN U
\n1030 LET L=SGN V
\n1040 LET Z=SGN U
\n1050 LET Q=0
\n1060 LET M=ABS U
\n1070 LET N=ABS V
\n1080 IF M>N THEN GOTO 1130
\n1090 LET Z=0
\n1100 LET Q=SGN V
\n1110 LET M=ABS V
\n1120 LET N=ABS U
\n1140 LET S=INT (M/2)
\n1150 FOR I=0 TO M
\n1160 IF P=1 THEN PLOT A,B
\n1165 IF P=0 THEN UNPLOT A,B
\n1170 LET S=S+N
\n1180 IF S<M THEN GOTO 1230
\n1190 LET S=S-M
\n1200 LET A=A+O
\n1210 LET B=B+L
\n1220 GOTO 1250
\n1230 LET A=A+Z
\n1240 LET B=B+Q
\n1250 NEXT I
\n1260 RETURN 

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top