All HP 9000 Series computers and the HP Measurement Coprocessor provide a volatile real-time clock (the "BASIC clock") that you can set and read to monitor the time of day and date. There are also timers that can interrupt a BASIC program. This chapter describes using the clock- and timer-related functions and statements.
With the BASIC/WS system, many of the statements described in this chapter require the CLOCK binary. This is also true with BASIC/DOS for the HP Measurement Coprocessor. The HP BASIC Language Reference lists which binary (if any) is required to use each statement and function. (The BASIC/UX system is not partitioned into separately loadable binaries.)
All Series 300/400/700 computers have a non-volatile clock (a non-volatile clock is powered by a battery so that it keeps time even when the computer is turned off). However, some Series 200 computers do not have this type of clock. All HP Vectra PCs and most AT-compatible PCs also have a battery-powered clock, which is used in conjunction with the HP Measurement Coprocessor.
If you don't have a non-volatile clock, you may need to determine whether or not the real-time clock is set to the proper time.
When you initially boot the BASIC system, the real-time clock is set to one of these values:
The range of Series 200 volatile and non-volatile clocks is March 1, 1900 through August 4, 2079. The Series 300/400/700 volatile and non-volatile clocks both have a lower limit of March 1, 1900. However, the upper limit of the volatile clock is August 4, 2079, while the upper limit of the non-volatile clock is February 29, 2000. Beginning with version 6.2, BASIC/WS interprets the non-volatile clock differently, so the allowable range for setting the battery backed clock is from Jan 1, 1970 to December 31, 2069.
If you change the system time to a time outside of the non-volatile clock range, a warning will be generated, but the system time will be set - and will count up from there. However, on reboot the time and date will be other than what might have been expected.
The volatile real-time clocks provide an accuracy of +/-5seconds per day. The Series 200 battery-backed "powerfail" (98270) clock maintains time to within +/-2.5 seconds per day. The Series 300/400/700 battery-backed clock maintains time to within +/-5 seconds per day.
The range of the HP Measurement Coprocessor volatile clock is March 1, 1900 through August 4, 2079. The range and accuracy of the non-volatile clock (if present) depends on the PC in which the measurement coprocessor is installed.
Internally, the clock maintains the year, month, day, hour, minute, and second as a single real number. This number is scaled to an arbitrary "dawn of time," thus allowing it to also represent the Julian date. The current value of the clock is returned by the TIMEDATE function.
PRINT TIMEDATE
While the value returned contains all the information necessary to uniquely specify the date and time to the nearest one-hundredth of a second, it needs to be "unpacked" to provide understandable information.
The following functions are available to extract the date and time of day from TIMEDATE.
The DATE$ function extracts the date from the value of TIMEDATE.
PRINT DATE$(TIMEDATE)
Prints: 1 Mar 1900
This is the default power-up date for machines without the battery-backed real-time clock.
The TIME$ function returns the time of day.
PRINT TIME$(TIMEDATE)
Prints: 00:05:27
If you are using a BASIC "Workstation" system (BASIC/WS) and you will be sharing an HFS disk with an HP-UX system, then you will need to use the TIMEZONE IS statement before setting the clock. See the HP BASIC Language Reference entry for TIMEZONE IS for instructions. (Note that with BASIC/UX, you will not need to use TIMEZONE IS.)
The SET TIMEDATE statement is used to set the clock:
SET TIMEDATE DATE("1 Oct 1988") + TIME("08:37:30")
The time and date functions are set the same on a BASIC/UX system as on a BASIC/WS system. However, note that the time and date you are changing are just "offsets" from the HP-UX clock that the BASIC/UX process uses. For instance, if you set the clock to be two hours ahead of what it is now, your "local" clock value will change, but the HP-UX system clock will not.
If it is your intent to change the time of the HP-UX system that BASIC/UX is running on, you need to be logged in as root (the system administrator) and use the HP-UX system commands for changing the time, date, and time zone. See the HP-UX System Administration Tasks manual for instructions.
To minimize the space required to store the date and time, and yet insure a unique value for each point in time, both time and date are combined as a single real number. This value is the Julian date multiplied by the number of seconds in a day. By recalling that there are 86400 seconds in a day, the date and time of day can be extracted from TIMEDATE by the following simple algorithms.
TIMEDATE MOD 86400 returns the time of day
TIMEDATE DIV 86400 returns the Julian date
The time of day is expressed in seconds past midnight and is easily divided into hours, minutes, and seconds. The Julian date requires a bit more processing to extract the month, day, and year but this method insures a unique value for each day over the entire range of the clock.
Year | Clock Value | Hours | Seconds | |
---|---|---|---|---|
1900 | 2.086578144E+11 | 1 | 3600 | |
1910 | 2.089733472E+11 | 2 | 7200 | |
1920 | 2.092888800E+11 | 3 | 10800 | |
1930 | 2.096044992E+11 | 4 | 14400 | |
1940 | 2.099200320E+11 | 5 | 18000 | |
1950 | 2.102356512E+11 | 6 | 21600 | |
1960 | 2.105511840E+11 | 7 | 25200 | |
1970 | 2.108668032E+11 | 8 | 28800 | |
1980 | 2.111823360E+11 | 9 | 32400 | |
1990 | 2.114979552E+11 | 10 | 36000 | |
2000 | 2.118134880E+11 | 11 | 39600 | |
2010 | 2.121291072E+11 | 12 | 43200 | |
2020 | 2.124446400E+11 | 13 | 46800 | |
2030 | 2.127602592E+11 | 14 | 50400 | |
2040 | 2.130757920E+11 | 15 | 54000 | |
2050 | 2.133914112E+11 | 16 | 57600 | |
2060 | 2.137069440E+11 | 17 | 61200 | |
2070 | 2.140225632E+11 | 18 | 64800 | |
2080 | 2.143380960E+11 | 19 | 68400 | |
20 | 72000 | |||
21 | 75600 | |||
22 | 79200 | |||
23 | 82800 | |||
24 | 86400 |
The time of day is changed by SET TIME X, where X is the number of seconds past midnight. The value of X must be in the range: 0 through 86399.99 seconds. The TIME function will convert twenty-four hour formatted time (HH:MM:SS) into the value needed to set the clock.
The TIME function converts an ASCII string representing a time of day, in twenty-four hour format, into the number of seconds past midnight. For example:
SET TIME TIME("15:30:10")
Is equivalent to:
SET TIME 55810
Either of these statements will set the time of day without changing the date. Use the SET TIMEDATE statement to change the date.
To display the new time, the TIME$ function formats the clock's value (TIMEDATE) into hours, minutes, and seconds.
PRINT TIME$(TIMEDATE)
Prints: 15:30:16
Even though TIMEDATE returns a value containing both time of day and the
Julian date, TIME$ performs an internal modulo 86400 on the value passed
to the function and will always return a string in the range:
00:00:00
thru 23:59:59
.
The following program contains the routines to set and display the time of day. The routines are written as user-defined functions that may be appended to your program. Once appended to a program, the routines duplicate the TIME and TIME$ functions available with CLOCK. The formatted time can then be displayed by the following statement.
PRINT FNTime$(TIMEDATE)
Prints: 15:31:05
Given the clock's value, the FNTime$
function returns
the time of day in 24 hour format (HH:MM:SS). The
FNTime
function converts the time of day to seconds and
is used to set the clock.
10 Show_time:DISP FNTime$(TIMEDATE)
20 GOTO Show_time
30 END
40 !
50 ! While the program is running, type:
60 ! SET TIME FNTIME("11:5:30")
70 ! then press <EXECUTE> to show the new time.
80 !
90 !*********************************************************
100 !
110 DEF FNTime$(Now) ! Given 'SECONDS' Return 'hh:mm:ss'
120 !
130 Now=INT(Now) MOD 86400
140 H=Now DIV 3600
150 M=Now MOD 3600 DIV 60
160 S=Now MOD 60
170 OUTPUT T$ USING "#,ZZ,K";H,":",M,":",S
180 RETURN T$
190 FNEND
200 !
210 DEF FNTime(T$) ! Given 'hh:mm:ss' Return 'SECONDS'
220 !
230 ON ERROR GOTO Err
240 ENTER T$;H,M,S
250 RETURN (3600*H+60*M+S) MOD 86400
260 Err:OFF ERROR
270 RETURN TIMEDATE MOD 86400
280 FNEND
After entering the program, follow the instructions at the beginning of the program to verify correct operation. Store this program in a file named "FUNTIME". The functions can be extracted from this program and appended to other programs by the LOADSUB statement.
Note that the FNTime
function requires hours, minutes,
and seconds, while the TIME function only requires hours and minutes.
The date is changed by SET TIMEDATE X, where X is the Julian date multiplied by the number of seconds in a day (86400). The DATE function converts a formatted date (DD MMM YYYY) into the value needed to set the clock. Due to the wide range of values allowed by the DATE function, negative years can be specified, but not when using the function to set the clock.
The following statement will set the clock to the proper date.
SET TIMEDATE DATE("1 Jun 1984")
When programming without CLOCK, the user-defined function
FNDate
can be used.
SET TIMEDATE FNDate("1 Jun 1984")
Both of these statements are equivalent to the following statement.
SET TIMEDATE 2.113216992E+11
The DATE and FNDate
functions convert the accompanying
string (or string expression) into the numeric value needed to set the clock.
To read the clock, the DATE$ and FNDate$
functions format
the clock's value as the day, month, and year. For example, the following
line will print the date.
PRINT DATE$(TIMEDATE)
Prints: 1 Jun 1984
Programs that need to run without CLOCK can use the following user-defined functions appended to the end of the program. These functions simulate the DATE and DATE$ keywords available in CLOCK. The algorithm is valid over the entire range of the clock.
Note the following functions are restricted to values the clock will accept, the DATE and DATE$ functions available with CLOCK allow a much wider range of values (including negative years).
10 Show_date: DISP FNDate$(TIMEDATE)
20 GOTO Show_date
30 END
40 !
50 ! While the program is running, type:
60 ! SET TIMEDATE FNDATE("1 JAN 82") <EXECUTE>
70 !
80 !**********************************************************
90 !
100 DEF FNDate$(Seconds) ! Given 'SECONDS' Return 'dd mmm yyyy'
110 !
120 DATA JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC
130 DIM Month$(1:12)[3]
140 READ Month$(*)
150 !
160 Julian=Seconds DIV 86400-1721119
170 Year=(4*Julian-1) DIV 146097
180 Julian=(4*Julian-1) MOD 146097
190 Day=Julian DIV 4
200 Julian=(4*Day+3) DIV 1461
210 Day=(4*Day+3) MOD 1461
220 Day=(Day+4) DIV 4
230 Month=(5*Day-3) DIV 153 ! Month
240 Day=(5*Day-3) MOD 153
250 Day=(Day+5) DIV 5 ! Day
260 Year=100*Year+Julian ! Year
270 IF Month<10 THEN
280 Month=Month+3
290 ELSE
300 Month=Month-9
310 Year=Year+1
320 END IF
330 OUTPUT D$ USING "#,ZZ,X,3A,X,4Z";Day,Month$(Month),Year
340 RETURN D$
350 FNEND
360 !
370 DEF FNDate(Dmy$) ! Given 'dd mmm yyyy' Return 'SECONDS'
380 !
390 DATA JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC
400 DIM Month$(1:12)[3]
410 READ Month$(*)
420 !
430 ON ERROR GOTO Err
440 I$=Dmy$& " "
450 ENTER I$ USING "DD,4A,5D";Day,M$,Year
460 IF Year<100 THEN Year=Year+1900
470 FOR I=1 TO 12
480 IF POS(M$,Month$(I)) THEN Month=I
490 NEXT I
500 IF Month=0 THEN Err
510 IF Month>2 THEN
520 Month=Month-3
530 ELSE
540 Month=Month+9
550 Year=Year-1
560 END IF
570 Century=Year DIV 100
580 Remainder=Year MOD 100
590 Julian=146097*Century DIV 4+1461*Remainder DIV 4+(153*Month+2) DIV
5+Day+1721119
600 Julian=Julian*86400
610 IF Julian<2.08662912E+11 OR Julian>=2.143252224E+11 THEN Err
620 RETURN Julian ! Return Julian date in SECONDS
630 Err:OFF ERROR ! ERROR in input.
640 RETURN TIMEDATE ! Return current date.
650 FNEND
Store the program in a file named "FUNDATE". Later the functions can be appended to other programs by the LOADSUB statement.
The functions FNDate$
and FNDate
format the date as "DD MMM YYYY", where DD is the day of the month, MMM is
the first three letters of the month, and YYYY is the year. The function
FNDate
will accept the last two digits of the year. See
line 460. Note that the FNDate
function requires two
digits for the day, while the DATE function does not.
Different formats require only slight modification. By changing the following lines, the date is formatted as "MM/DD/YYYY".
330 OUTPUT D$ USING "#,2D,A,2D,A,2D";Month;"/";Day;"/";Year
450 ENTER I$ USING "#,ZZ,K";Month;Day;Year
European date format is obtained by swapping the month and day in the above statements. When changing the format, be sure to switch both functions.
If the all numeric format is chosen, delete the three lines in each function that load the array with the month mnemonics.
The following statements summarize setting and displaying the clock.
SET TIMEDATE FNDate("12 DEC 1981") + FNTime("13:44:15")
SET TIME FNTime("8:30:00")
PRINT FNTime$(TIMEDATE)
DISP FNDate$(TIMEDATE)
It is important to note that SET TIMEDATE
expects a date
and time while the DATE function and the user-defined function
FNDate
return only a date. This effectively sets the
clock to midnight of the date specified.
To keep the functions short, minimal parameter checking is performed. Additional
checking may be incorporated within the functions or within the calling context.
If FNDate
or FNTime
cannot correctly
decode the input, the current value of the clock is returned.
The date and time functions can be used with the following program shell to provide a "friendly" interface to the clock.
10 ! PROGRAM SHELL FOR SETTING TIME AND DATE.
20 !
30 ! REQUIRES THE TIME AND DATE FUNCTIONS.
40 !
50 DIM Day$(0:6)[9]
60 DATA Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday
70 READ Day$(*)
80 !
90 ON ERROR GOTO Nofun ! Test if functions
100 Dmy$=FNDate$(TIMEDATE) ! have been loaded
110 Hms$=FNTime$(TIMEDATE)
120 OFF ERROR
130 Main: ! Get NEW date
140 CLEAR SCREEN
150 F$=CHR$(255)& CHR$(72)
160 !
170 PRINT TABXY(1,14);"Enter the date, and press CONTINUE."
180 OUTPUT 2 USING "#,11A,2A";Dmy$,F$
190 !
200 INPUT Dmy$ ! WAIT for INPUT
210 !
220 ENTER Dmy$ USING "2D,4A,5D";D,M$,Y
230 CLEAR SCREEN
240 !
250 PRINT TABXY(1,14);"Enter the time of day and press CONTINUE"
260 OUTPUT 2 USING "#,11A,2A";Hms$,F$
270 INPUT Hms$
280 ENTER Dmy$ USING "2D,4A,5D";D,M$,Y
290 !
300 SET TIMEDATE FNDate(Dmy$)+FNTime(Hms$)
310 !
320 CLEAR SCREEN
330 W=(TIMEDATE DIV 86400) MOD 7 ! Day of week
340 PRINT TABXY(1,1);"The clock has been set to:"
350 PRINT TABXY(1,3);Day$(W);" ";Dmy$;" ";FNTime$(TIMEDATE)
360 GOTO Quit
370 !
380 ! ************ SUBROUTINES ************
390 !
400 Nofun:PRINT "The TIME & DATE FUNCTIONS must be appended,"
410 PRINT "(via LOADSUB) before program will work."
420 Quit:END
430 !
440 ! ************* FUNCTIONS **************
450 !
460 ! append time and date functions here
The program tests to see if the functions have been loaded by trying to use them. If they are not loaded the program ends with an error message. With the CLOCK binary, this program can still be used. Replace the calls to the user-defined functions with the appropriate keywords. The error trapping can then be deleted.
To append the user-defined functions, execute the following statements while the demonstration program is in memory.
LOADSUB ALL FROM "FUNDATE"
LOADSUB ALL FROM "FUNTIME"
Examine the program to be sure the functions have been loaded.
The program will prompt for the date and time, then set the clock accordingly. A program such as this may be used as the system start up program for applications requiring the date or time.
An advantage of Julian dates is the simplicity of finding the day of the
week. TIMEDATE DIV 86400 MOD 7
returns a number which
represents the day of the week. Monday is represented by zero (0), and the
numbering continues through the week to Sunday which is represented by six
(6). See the previous program for an example of using this routine.
The number of days between two dates is easily calculated as the following program demonstrates.
10 ! Days between two dates
20 INPUT "ENTER THE FIRST DATE (DD MMM YYYY)",D1$
30 INPUT "ENTER THE SECOND DATE (DD MMM YYYY)",D2$
40 Days=(DATE(D2$)-DATE(D1$)) DIV 86400
50 DISP Days;"days between '";D1$;"' and '";D2$;"'"
60 END
Timing a single event of short duration is quite simple.
10 T0=TIMEDATE ! Start
20 FOR J=1 TO 5555
30 !
40 NEXT J
50 T1=TIMEDATE ! Finish
60 !
70 PRINT "It took";DROUND(T1-T0,3);"seconds"
80 END
Programs can and should be written so that they do not change the setting of the clock. A short program, which simulates a stopwatch, allows interval timing without changing the clock.
10 ! Program: STOPWATCH
20 ! Interval timing without changing the clock
30 ON KEY 5 LABEL " START " GOTO Start
40 ON KEY 6 LABEL " STOP " GOTO Hold
50 ON KEY 7 LABEL " RESET " GOTO Reset
60 ON KEY 8 LABEL " LAP " GOSUB Lap
70 !
80 Reset:PRINT CHR$(12) ! form-feed
90 H=0 ! Set all
100 M=0 ! to
110 S=0 ! zero.
120 !
130 Hold:DISP TAB(9);H;":";M;":";S ! Wait til
140 GOTO Hold ! keypress
150 !
160 Lap:PRINT H;":";M;":";S ! Print lap
170 RETURN
180 !
190 Start:Z=3600*H+60*M+S-TIMEDATE ! Elapsed-
200 Loop:T=(TIMEDATE+Z) MOD 86400 ! time
210 T=INT(T*100)/100 ! .01 sec.
220 H=T DIV 3600 ! Hours
230 M=T MOD 3600 DIV 60 ! Minutes
240 S=T MOD 60 ! Seconds
250 DISP TAB(9);H;":";M;":";S ! Show time
260 GOTO Loop ! Do again
270 END
Several additional branching statements, available with CLOCK, allow end-of-statement branches to be triggered according to the real-time clock's value.
ON TIME
enables a branch to be taken when the clock reaches
a specified time of day.
ON DELAY
enables a branch to be taken after a specified
number of seconds has elapsed.
ON CYCLE
enables a recurring branch to be taken with
each passage of a specified number of seconds.
The specified time can range from 0.01 thru 167772.15 seconds for the ON CYCLE and ON DELAY statements and 0 thru 86399.99 seconds for ON TIME. The value specified with ON TIME indicates the time of day (in seconds past midnight) for the branch to occur.
Each of these statements has a corresponding statement to cancel the branch (OFF TIME, OFF DELAY, and OFF CYCLE). A statement is also canceled by executing another ON TIME, ON DELAY, or ON CYCLE statement.
All of the statements use the internal real-time clock. Care should be taken to avoid writing programs that could change the clock's setting during execution. Since only one resource is dedicated to each statement, certain restrictions apply to the use of these statements.
The clock resolution is different for two implementations of BASIC:
Both the ON CYCLE and ON DELAY statements enable a branch to be taken as soon as the specified number of seconds has elapsed. ON CYCLE remains in effect, re-enabling a branch with each passage of time. For example:
10 ON CYCLE 1 GOSUB Five ! Print 5 random numbers every second.
20 ON DELAY 6 GOTO Quit ! After 6 seconds quit.
30 !
40 T: DISP TIME$(TIMEDATE) ! Show the time.
50 GOTO T
60 !
70 Five:FOR I=1 TO 5
80 PRINT RND;
90 NEXT I
100 PRINT
110 RETURN
120 !
130 Quit:END
The program will print five random numbers every second for six seconds and then stop.
Only one ON CYCLE and one ON DELAY statement can be active in a program context. Executing a second ON CYCLE or ON DELAY statement in the same program context deactivates the first ON CYCLE or ON DELAY statement. If a branch is missed, due to priority restrictions or execution of a subprogram, the event is logged and the branch will be taken when the restriction is removed or the original context is restored. If an active ON CYCLE or ON DELAY statement gets canceled in an alternate context (subprogram) the branch is restored when execution returns to the defining context. (See Branching Restrictions for more information about this).
The ON TIME statement allows you to define and enable a branch to be taken when the clock reaches a specified time of day, where time of day is expressed as seconds past midnight. Using the TIME function simplifies setting an ON TIME statement by allowing a formatted time of day to be used. For example:
ON TIME TIME("11:30") GOTO Lunch
Typically, the ON TIME statement is used to cause a branch at a specified time of day. By adding an offset to the current clock value, the ON TIME statement can be used as an interval timer. In the following example, both ON DELAY and ON TIME are used as interval timers.
10 ON DELAY 5 GOSUB Takeoff ! delay 5 seconds
20 ON TIME (TIMEDATE+10) MOD 86400 GOSUB Touchdown ! delay 10 seconds
30 PRINT "STARTING... ",TIME$(TIMEDATE)
40 Clock:DISP TIME$(TIMEDATE)
50 GOTO Clock
60 !
70 Takeoff:PRINT "TAKEOFF at ",TIME$(TIMEDATE)
80 RETURN
90 Touchdown:PRINT "TOUCHDOWN at ",TIME$(TIMEDATE)
100 RETURN
110 END
The starting time is printed when the program is executed. Five seconds later the first subroutine is executed. Ten seconds after the program starts, the second subroutine is executed.
Only one ON TIME statement can be active in a program context. If a branch is missed, due to priority restrictions or execution of a subprogram, the event is logged and the branch will be taken when the restriction is removed or the original context is restored. If an active ON TIME statement gets canceled in an alternate context (subprogram) the branch is restored when execution returns to the defining context. (See Branching Restrictions for more information about this).
Due to the "match an exact time" nature of the ON TIME statement, if the specified time occurs when the statement is temporarily canceled (by an OFF TIME in an alternate context), no branch will be taken when the defining context is restored.
A priority can be assigned to the branch defined by ON CYCLE, ON DELAY, and ON TIME. For example:
ON CYCLE Seconds,Priority GOTO Label
If the system priority is higher than the branch priority at the time specified for the branch, the event will be logged but the branch will not be taken until the system priority falls below the branch priority. An example program follows.
10 COM Start
20 P=0
30 Up:P=P+1
40 IF P>15 THEN Quit ! Priority from 1 thru 15
50 PRINT
60 PRINT "Priority:";P;
70 Start=TIMEDATE ! Save the start-time for subprogram.
80 ON CYCLE 1,P RECOVER Up ! New priority every second if not Busy.
90 ON DELAY .5,6 CALL Busy ! DELAY overrides CYCLE until priority
100 ! (P) is greater than 6.
110 W:GOTO W
120 Quit:END
130 !----------------- SUB has priority of 6 ---------------------
140 SUB Busy
150 COM Start
160 PRINT "SUB";
170 WHILE I<10
180 IF TIMEDATE>Start+1 THEN ! Has ON CYCLE time been exceeded?
190 PRINT "*"; ! YES (only prints if Priority<7)
200 ELSE
210 PRINT "."; ! NO
220 END IF
230 I=I+1 ! Loop ten times
240 WAIT .1
250 END WHILE
260 PRINT "DONE";
270 SUBEND
Once the priority assigned to the ON CYCLE statement is greater than the priority assigned to the ON DELAY statement (6), the subprogram will be interrupted. After running the program, change line 80 in the above program to the following:
80 ON CYCLE 1,P GOTO Up
Running the new version of the program will show that GOTO (or GOSUB) will not interrupt a subprogram regardless of the assigned priority. The branch will be logged but not taken until execution returns to the main program. If you write a program that makes extensive use of subprograms and branching statements, use CALL and RECOVER to insure proper operation.
Certain restrictions apply to the use of ON TIME, ON CYCLE, and ON DELAY because only one resource is dedicated to each statement. Assuming an active branch has been defined in the main program, execution of a subprogram which sets up a new branch will cause the loss of the original time. When the main program context is restored, the original branch will be restored, but at the time defined in the subprogram. The following program will illustrate this effect.
10 COM Counter
20 Counter=0
30 GINIT
40 GRID 1,1 ! Fill graphics raster with grid.
50 DISP Counter
60 ON CYCLE 2 CALL Flash ! Flash graphics every 2 seconds.
70 W: GOTO W
80 END
90 !----------------- SUB to flash graphics raster --------------
100 SUB Flash
110 COM Counter
120 GRAPHICS ON
130 Counter=Counter+1
140 DISP Counter
150 IF Counter=5 THEN ! Change CYCLE value during fifth CALL.
160 ON CYCLE .1,2 CALL Quit ! New value (.1) will replace old (2).
170 ! Flash will end before Quit gets called.
180 END IF
190 GRAPHICS OFF
200 SUBEND
210 !----------------- SUB that won't get called -----------------
220 SUB Quit
230 PRINT "PROGRAM HAS STOPPED"
240 STOP
250 SUBEND
The program starts out by flashing the graphics raster on and off every two seconds. When the subprogram's ON CYCLE statement is activated during the fifth call to the subprogram, the new value (0.1 second) replaces the old value (2.0 seconds) and the program begins flashing the graphics raster at the new rate. Note that the branch to the second subprogram (Quit) is not executed because the first subprogram is finished before the specified time. To see the second subprogram execute, insert the following line.
191 WAIT 1
The delay caused by the WAIT statement allows the subprogram's ON CYCLE statement to branch to the second subprogram and stop execution.
If an active branch defined in the main program is canceled in a subprogram (by OFF TIME, OFF DELAY, or OFF CYCLE) any branch missed during the execution of the subprogram will be lost. When the context containing the original statement is restored, the branch will be reactivated and processing will continue as if no branch was missed.
10 ON DELAY 1 GOTO Done ! GOTO "Done" in one second.
20 CALL Busy ! Call to "Busy" takes two seconds.
30 !
40 PRINT "THIS WON'T BE PRINTED UNLESS BRANCH IS CANCELED BY THE SUB"
50 !
60 Done:PRINT "THIS LINE WILL BE PRINTED EVERY TIME"
70 END
80 ! -----------------------------------------------------------
90 SUB Busy
100 WAIT 2
110 ! OFF DELAY ! RUN then remove the "!" on this line and RUN again.
120 SUBEND
By removing the comment symbol (!) from the beginning of line 110, the OFF DELAY statement will be executed causing any branch that has already been logged to be canceled and allow line 40 to be printed.
Since branches only occur at the end of a line, no branch can be taken during an INPUT or LINPUT statement. The following program shows a method of monitoring the keyboard without preventing branches to be taken.
10 ON KBD GOTO Yes ! If key is pressed go get new value.
20 ON DELAY 3 GOTO Gone ! If no keypress in 3 seconds use defaults
30 DISP "PRESS A KEY"
40 W: GOTO W ! Wait here until keypress or end of delay.
50 !
60 Yes:OFF DELAY ! Someone is there.
70 OFF KBD
80 LINPUT "NEW VALUE?",A$
90 DISP "USING",A$
100 GOTO More
110 !
120 Gone:DISP ! Nobody there.
130 DISP "USING DEFAULTS"
140 !
150 More:WAIT 2
160 DISP "program continues...."
170 END
The program waits a few seconds for a response. Processing continues with default values if no key is pressed. Pressing a key will cause the program to accept the new information.