Realtime Clock On Your Pet Screen
Mark L. Robinson
Editor's Note: In the version of Mr. Robinson's clock routine for 4.0 BASIC, the code has been moved up 38 (decimal) from the Upgrade version of Program I. Add a value of 38 to his POKEs and references for the 4.0 version. — RTM
How many times have you sat down at your computer to fiddle around for a few minutes, returning to the real world hours (or days) later. This is not always a problem and I don't mind being splattered with cold suppers, missing parties, or aggravating my wife. But one night, I had some free moments to ponder the problem of losing track of time. Wouldn't it be great, I thought, if I could always have the correct time on the screen.
I knew that my PET had a 1/60 second counter which is updated during the internal interrupt cycle and some routines to print out the time. I started to study the memory map in Osborne's PET/CBM Personal Computer Guide and found the following items: jiffy memory, clock correction routine and the location of the interrupt addresses.
I figured if I could revector the interrupt through a small machine language program, I could capitalize on all three items – the jiffy clock to keep track of time, the interrupt addresses to return to the correct location and the clock correction routine to make up for the lost time of my program, if necessary.
Some other investigation showed that the routines that print the TIME$ use a lot of processing time and interact with memory locations that Basic uses. I figured it would be best to handle it completely as a separate little program. Then, the more I thought about it, I realized that once the time was set, I could follow it with a simple series of little counters rather than keep having to do long divisions. This also has the advantage of being able to jump back to the normal program whenever there is no carry up to the next most significant clock digit. This saves over 50 percent of the time penalty of the screen clock.
To initialize the clock and load the machine language program, I wrote a small BASIC program. You can follow the explanations in the flowchart and the symbolic listing of the machine language program along with the listing of the BASIC program. The machine language program is short enough to load with pokes rather than entering it using the machine language monitor. You can enter and run this as a normal basic program and, while the clock is running, you can use most BASIC programs. There is a small time penalty to use this while running BASIC, but if you are programming or game playing, it is not critical.
Incidentally, since the program is synchronized with the jiffy counter, you are automatically using the PET's internal correction routine. On a three hour run against a stop watch, the PET gained two seconds (so much for my stop watch). Two words of caution when you are writing programs: first, if you hit return on the line the time is on it will be entered in the listing and, second, if you have to load a program from the cassette, turn the clock off (POKE 144, 46:POKE 145,230), load the program, and start the clock again (POKE 144,74:POKE 145,3). To reset the clock poke the correct time digits to locations 833-838.
Symbolic Listing Real Time on Screen | |
DEFINITIONS | |
LOTB = Least significant time bit— (Jiffy Counter) | |
TL0C1 Temporary holding location | |
TL0C2 Temporary holding location of prior jiffy count | |
BASE 1 - 7 Base of count, 10 or 6 | |
IMAGE 1-7 Location of time in memory | |
SCT1-7 Screen locations of time | |
INITIALIZE | |
LDA LOTB | Initialize prior count set it ahead to next. 1 second. Note 1 |
ADC #05 | |
STATL0C2 | |
LDA#Start | Revector interrupt to start |
STAIRQ Low | |
START | |
LDA #LOTB | Check jiffies see if we've reached next.1 sec |
STATL0C1 | |
CMPTL0C2 | |
ADC #05 | Yes-set TL0C2 for next. 1 sec, make sure that if more than 6 jiffs occurred we do not add too much |
SBC TL0C2 | |
ADCTL0C1 | |
STA TL0C2 | |
INC IMAGE.7 | Increase. 1 sec memory location by 1 |
LDX#07 | Initialize counter routine |
COUNTER | |
LDA IMAGE.X | Check to see if we've reached limit of base which produces a carry |
CMPBASE.X | |
BNE UPDATE INIT | No — then go to Update Init |
LDA #00 | Yes — place 0 in digit position |
STA IMAGE.X | |
DEX | Go to next number in sequence |
BEQ UPDATE INIT | If we have done all 7 digits go to screen update |
INC IMAGE.X | Increment next digit by 1 (result of carry) |
JMPCOUNTER | Go back and check this digit for carry |
UPDATE INIT | |
LDX #07 | Initialize the screen update routine |
UPDATE | |
LDAIMAGE,X | Load time digit |
ADC #$30 | Convert to PET number code |
STASCT,X | Store on screen |
DEX | |
BNE UPDATE | Have we done 7 digits?—no go back to update |
LDA #3A | Yes—load and store colon on screen |
STA SCT,O | |
JMP IRQ | Return to PET IRQ routine |
Note 1: The reason that five is added to the jiffy count and not six (to get the next 6/60 or .1 sec) is that we are incrementing when the prior count location is less than the jiffy count. If the increment occurred on equality then you would add six. The reason for this is that I do not know if the jiffy count can count two sometimes in which case the equality would not occur for up to 12.8 seconds — when the same binary digit again occurred. This is also the reason the program checks for more than six counts. |
Program 1: Upgrade Version
5 REM REAL TIME ON PET SCREEN 6 REM C M. ROBINSON 1980 7 REM OK FOR PERSONAL USE 10 FOR A = 1 TO 100 20 READ B 30 POKE 825+A,B 40 NEXT 100 PRINT"{CLEAR} HHMMSS" 110 INPUT "TIME"; A$ 120 TI$ = A$ 130 FOR A = 1 TO 6 140 D = VAL (MID$ (A$, A, 1)) 150 POKE 832 + A, D 160 NEXT 200 POKE 144, 74: POKE 145, 3 250 NEW 1000 DATA 10, 10, 6, 10, 6, 10 1001 DATA 10, 0, 0, 0, 0, 0 1002 DATA 0, 0, 87, 90, 165, 143 1003 DATA 105, 5, 141, 73, 3, 169 1004 DATA 85, 133, 144, 165, 143, 141 1005 DATA 72, 3, 205, 73, 3, 48 1006 DATA 38, 105, 5, 237, 73, 3 1007 DATA 109, 72, 3, 141, 73, 3 1008 DATA 238, 71, 3, 162, 7, 189 1009 DATA 64, 3, 221, 57, 3, 48 1010 DATA 14, 169, 0, 157, 64, 3 1011 DATA 202, 240, 6, 254, 64, 3 1012 DATA 76, 111, 3, 162, 7, 189 1013 DATA 64, 3, 105, 48, 157, 31 1014 DATA 128, 202, 208, 245, 169, 58 1015 DATA 141, 31, 128, 76, 46, 230 1016 DATA 0, 0, 0, 0, 0, 0
Program 2: 4.0 Version
10 FOR A = 1 TO 100 20 READ B 30 POKE 863 + A, B 40 NEXT 100 PRINT "{CLEAR} HHMMSS" 110 INPUT "TIME";A$ 120 TI$ = A$ 130 FOR A = 1 TO 6 140 D = VAL(MID$(A$, A, 1)) 150 POKE 870 + A, D 160 NEXT 170 POKE144, 112: POKE145, 3 180 NEW 864 DATA 10, 10, 6, 10, 6, 10 870 DATA 10, 0, 0, 0, 0, 0 876 DATA 0, 0, 87, 90, 165, 143 882 DATA 105, 5, 141, 111, 3, 169 888 DATA 123, 133, 144, 165, 143, 141 894 DATA 110, 3, 205, 111, 3, 48 900 DATA 38, 105, 5, 237, 111, 3 906 DATA 109, 110, 3, 141, 111, 3 912 DATA 238, 109, 3, 162, 7, 189 918 DATA 102, 3, 221, 95, 3, 48 924 DATA 14, 169, 0, 157, 102, 3 930 DATA 202, 240, 6, 254, 102, 3 936 DATA 76, 149, 3, 162, 7, 189 942 DATA 102, 3, 105, 48, 157, 31 948 DATA 128, 202, 208, 245, 169, 58 954 DATA 141, 31, 128, 76, 85, 228 960 DATA 0, 0, 0, 0, 0, 0