Using the Clock and Timers

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.

BASIC CLOCK Binary

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.)

Do You Have a Battery-Powered Clock?

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.

Initial Clock Value

When you initially boot the BASIC system, the real-time clock is set to one of these values:

Clock Range and Accuracy

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.

Reading the Clock

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.

Determining the Date and Time of Day

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

Setting the Time, Date, \and Time Zone

BASIC/WS and HP-UX Clock Compatibility

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.)

Setting the Time and Date

The SET TIMEDATE statement is used to set the clock:

 
SET TIMEDATE DATE("1 Oct 1988") + TIME("08:37:30") 
 

The BASIC/UX "Local" Clock

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.

Clock Time Format

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.

Clock Time
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

Setting Only the Time

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.

Setting Only the Date

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.

Using Clock Functions and Example Programs

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.

Day of the Week

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.

Days Between Two Dates

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
 

Interval Timing

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
 

Branching on Clock Events

Several additional branching statements, available with CLOCK, allow end-of-statement branches to be triggered according to the real-time clock's value.

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.

Clock Resolution

The clock resolution is different for two implementations of BASIC:

Cycles and Delays

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).

Time of Day

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.

Priority Restrictions

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.

Branching Restrictions

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.