PAUSE, INKEY$, PEEK
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.
stops computing and displays the picture for n frames of the television (at 50 frames per second in Europe or 60 in America). n can be up to 65535, which gives you just under 22 minutes; if n=0 then it means 'PAUSE for ever'.
A pause can always be cut short by pressing a key (note that a CAPS SHlFTed space will cause a break as well). You have to press the key down after the pause has started.
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
This 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 one a second, but 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 computer clock against a real one, and adjusting line 210 until they agree. (You can't do this very accurately; an adjustment of one frame in one second is 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. Chapter 25 explains what we're looking at in detail. The expression used is
(65536*PEEK 23674+256*PEEK 23673+PEEK 23672)/50
This gives the number of seconds since the computer was turned on (up to about 3 days and 21 hours, when 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()=lNT (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 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 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 methcd uses should be accurate to about .01% as long as the computer is just running its program, or 10 seconds per day; but it stops temporarily whenever you do BEEP, or a cassette tape operation, or use the printer or any of the other extra pieces of equipment you can use with the computer. All these will make it lose time.
The numbers PEEK 23674, PEEK 23673 and PEEK 23672 are held inside the computer 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 most often is PEEK 23672. Every 1/50 second it increases by 1. When it is at 255, the next increase takes it to 0, and at the same time it nudges PEEK 23673 by up to 1. When (every 256/50 seconds) PEEK 23673 is nudged from 255 to 0, it in turn nudges PEEK 23674 up by 1. This should be enough to explain why the expression above works.
Now, consider 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
(65536*0+256*255+255)/50= 1 31 0.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 computer would evaluate PEEK 23674 as 0, but then change the other two to 0 before it can peek them. The answer would then be
which is hopelessly wrong.
A simple rule to avoid this problem is evaluate the expression twice in succession and take the larger answer. If you look carefully at the program above you can see that it does this implicitly.
Here is a trick to apply the rule. Define 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, right
You can change the three counter numbers so that they give the real time instead of the time since the computer was switched on. For instance, to set the time at 10.00am, you work out that this is 10*60*60*50=1800000 fiftieths of a second, and that
To set the three numbers to 27, 119 and 64, you do
POKE 23674,27: POKE 23673,119: POKE 23672,64
In countries with mains frequencies of 60 Hertz these programs must replace '50' by '60' where appropriate.
The function INKEY$ (which has no argument) reads the keyboard. If you are pressing exactly one key (or a SHIFT key and just one other key) then the result is the character that that key gives in L mode; otherwise the result is the 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 INKEYS; 40 GO TO 10
Here line 10 waits for you to lift your finger off the keyboard and line 20 waits for you to press a new key.
Remember that unlike INPUT, INKEY$ doesn't wait for you. So you don't type ENTER, but on the other hand if you don't type anything at all then you've missed your chance.
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?
10 IF INKEY$ ="" THEN GO TO 10 20 PRINT AT 11,14;"0UCH!" 30 IF INKEYS <>"" THEN GO TO 30 40 PRINT AT 11,14;" " 50 GO TO 10