Part 18
Timing

Subjects covered...

	PAUSE, PEEK, INKEY$

Quite often you will want to make the program take a specified length
of time, and for this you will find the PAUSE statement useful.

	PAUSE n

...stops computing and displays the picture for n frames of the TV
(there are 50 frames per second in Europe and 60 in USA). The value of
n can be up to 65535, which gives you a pause of just under 22
minutes. If n=0 then it means 'pause indefinitely'.

A pause can always be cut short by pressing a key.

This program works the second hand of a clock...

	 10 REM first we draw the clock face
	 20 FOR n=1 TO 12
	 30 PRINT AT 10-10* COS (n/6* PI ),16+10* SIN (n/6* PI );n
	 40 NEXT n
	 50 REM now we start the clock
	 60 FOR t=0 TO 200000: REM t is the time in seconds
	 70 LET a=t/30* PI: REM a is the angle of the second hand in
	 	radians
	 80 LET sx=80* SIN a: LET sy=80* COS a
	200 PLOT 128,88: DRAW OVER 1;sx,sy: REM draw second hand
	210 PAUSE 42
	220 PLOT 128,88: DRAW OVER 1;sx,sy: REM erase second hand
	400 NEXT t

The clock will run down after about 55.5 hours because of line 60, but
you can easily make it run longer. Note how the timing is controlled
by line 210. You might expect 'PAUSE 50' to make it tick once per
second, however, the computing takes a bit of time as well and has to
be allowed for. This is best done by trial and error, timing the +3
clock against a real one, and adjusting line 210 until they agree. You
can't do this very accurately - an adjustment of one frame per second
is equal to 2% (or half an hour in a day).

There is a much more accurate way of measuring time. This uses the
contents of certain memory locations. The data stored is retrieved by
using PEEK. Part 25 of this chapter explains what we're looking at in
detail. Type in the expression...

	PRINT (65536* PEEK 23674+256* PEEK 23673+ PEEK 23672)/50

This prints the number of seconds since the +3 was turned on (up to
about 3 days and 21 hours, after which it goes back to 0).

Here is a revised clock program to make use of this...

	 10 REM first we draw the clock face
	 20 FOR n=1 TO 12
	 30 PRINT AT 10-10* COS (n/6* PI ),16+10* SIN (n/6* PI );n
	 40 NEXT n
	 50 DEF FN t()= INT ((65536* PEEK 23674+256* PEEK 23673+ PEEK
	 	23672)/50): REM number of seconds since start
	100 REM now we start the clock
	110 LET t1= FN t()
	120 
	120 LET a=t1/30* PI: REM a is the angle of the second hand in
	 	radians
	130 LET sx=72* SIN a: LET sy=72* COS a
	140 PLOT 131,91: DRAW OVER 1;sx,sy: REM draw hand
	200 LET t= FN t()
	210 IF t<=t1 THEN GO TO 200: REM will wait until time for next
		hand
	220 PLOT 131,91: DRAW OVER 1;sx,sy: REM rub out old hand
	230 LET t1=t: GO TO 120

The internal clock that this method uses should be accurate to about
0.01% (approx 10 seconds per day) so long as the +3 is simply running
the program. However, when you use the BEEP statement (described in
part 19 of this chapter) or operate the disk drive or any peripheral
attached to the +3 (e.g. a printer or second disk drive), the internal
clock stops temporarily, losing time.

The numbers 'PEER 23674', 'PEEK 23673', and 'PEEK 23672' are held
inside the +3 and used for counting in 50ths of a second. Each is
between 0 and 255 and they gradually increase through all the numbers
from 0 to 255; after 255 they drop straight back to 0.

The one that increases the most often is 'PEEK 23672' - every 1/50
second it increases by 1. When it is at 255, the next increase
'nudges' it to 0, and at the same time it increments 'PEEK 23673' up
by 1. When (every 256/50 seconds) 'PEEK 23673' is nudged from 255 to
0, it in turn increments 'PEEK 23674' up by 1. This should be enough
to explain why the expression above works.

Now, consider this carefully: suppose our three numbers are 0 (for
'PEEK 23674'), 255 (for 'PEEK 23673') and 255 (for 'PEEK 23672'). This
means that it is about 21 minutes after switch on. Our expression
ought to yield (65536x0+256x255+255)/50 which is equal to 1310.7.

But there is a hidden danger - the next time there is a 1/50 second
count, the three numbers will change to 1, 0 and 0. Every so often,
this will happen when you are half way through evaluating the
expression - the +3 would evaluate 'PEEK 23674' as 0, but then change
the other two to 0 before it can PEEK them. The answer would then be
(65536x0+256x0+0)/50 which is equal to 0, which is obviously wrong.

A simple way of avoiding this problem is to evaluate the expression
twice in succession and take the larger answer.

Now if you look carefully at the previous program, you can see that it
does this implicitly.

Here is a trick to apply the rule. Define the functions...

	10 DEF FN m(x,y)=(x+y+ ABS (x-y))/2: REM the larger of x and y
	20 DEF FN u()=(65536* PEEK 23674+256* PEEK 23673+PEEK
		23672)/50: REM time (may be wrong)
	30 DEF FN t()= FN m( FN u(), FN u()): REM time (correct)

You can change the three counter numbers so that they give the real
time instead of the time since the +3 was switched on. For instance,
to set the time at 10.00am, you work out that this is 10 x 60 x 60 x
50 which is equal to 1800000 fiftieths of a second (and 1800000 is
equal to 65536 x 27 + 256 x 119 + 64 x 1).

To set the three numbers to 27, 119 and 64, you type...

	POKE 23674,27: POKE 23673,119: POKE 23672,64

In countries with mains frequencies of 60 Hz (cycles per second),
these programs must replace 50 by 60 where appropriate.

The function INKEY$ (which has no argument) reads the keyboard. If you
are pressing just one key, (or say, CAPS SHIFT and just one other
key), then the result is the character which that key gives normally,
otherwise the result is an empty string.

Try this program, which works like a typewriter.

	10 IF INKEY$ <> "" THEN GO TO 10
	20 IF INKEY$ ="" THEN GO TO 20
	30 PRINT INKEY$ ;
	40 GO TO 10

Here line 10 waits for you to life your finger off the keyboard, and
line 20 waits for you to press a new key.

Unlike INPUT, INKEY$ doesn't wait for you, so you don't have to press
ENTER.


Exercises...

1. What happens if you miss out line 10 in the 'typewriter' program?

2. Another way of using INKEY$ is in conjunction with PAUSE, as in
this alternative 'typewriter' program...

	10 PAUSE 0
	20 PRINT INKEY$ ;
	30 GO TO 10

To make this work, why is it essential that a pause should not finish
if it finds you already pressing a key when it starts?

3. Adapt the 'clock second hand' program so that it also shows minute
and hour hands, re-drawing them every minute. If you're feeling
ambitious, arrange so that every quarter of an hour, it puts on some
kind of show - perhaps you could produce the 'Big Ben' chimes using
PLAY (described in part 19 of this chapter).
[Back] [Contents] [Next]