24 Hour Clock for SYM-1 BASIC
A. M. Mackay
600 Sixth Avenue West,
Owen Sound, Ontario, Canada
N4K 5E7
Load this program in your SYM-1 and enter G 0FB8. It will start a clock, display the memory you should enter to protect the program, then automatically transfer you to BASIC. Be sure to enter the amount of memory shown on the CRT. If you don't, you will lose the program.
The clock sits at the very top of your memory, and will not interfere with your BASIC – in fact, you won't even know it's there unless you call it. But it will be there when you want it for control operations, time delays for games, or whatever. You can even use your CRT as a time-of-day clock. It will keep ticking away until you hit “reset” or turn your SYM off.
As written, it is a 24 hour clock. If you want a 12 hour clock, change the contents of location 0FAD to “C0”.
This clock uses timer 1 of U29 to interrupt the program every 50 ms. “COUNT” totals these interrupts, and after each 20 interrupts one is added to “SECS”. Timer 2 and the input ports of U29 are not affected, and can be used for other purposes.
The program is written for a SYM-1 with 4K memory. It can be relocated upwards by changing all the “0F” bytes to “1F” or whatever. Also, change the bytes in locations 0FF9 to 0FFC. For example, for 8K, change these bytes to 37 35 34 38. The formula is 131 less than the number of free bytes usually displayed after going to BASIC, with a “3” before each digit.
The program as written keeps the time, starting at 0h, 0m, 0s from the time you enter G 0FB8. If you prefer time of day, enter the following (for 4K):
POKE &"0F7D", hour (in 24 hour time), CR POKE &"0F7E", minute, CR POKE &"0F7F", second, then hit CR on the exact second.
To use the clock in a BASIC program, enter the following BASIC command:
10 H = PEEK(&"0F7D"):M = PEEK(&"0F7E"):S = PEEK(&"0F7F")
Then use the variables H, M and S as you require them. To use your CRT as a clock, use the following program:
10 - as in the paragraph above. 20 PRINT CHR$(12) 30 PRINT H;":";M;":";S 40 FOR X = 1 TO 785: NEXT 50 GOTO 10 60 END
If you can turn cursor off, the clock will look much better.
The actual clock program ends at 0FDE. The rest of the program puts out the memory requirements on the CRT. If you don't want to transfer to BASIC, or if you don't have a CRT, put 4C 00 80 in locations 0FDF - 0FE1. You can then access the time by going to M 0F7D (hour), 0F7E (mins) and 0F7F (secs).
If anyone wants it, perhaps I'll write a routine for a future issue that will display the time on the SYM-1 LED readouts.
0010 .BA $0F7C ;THIS PROGRAM STARTS A 0020 ACCESS .DE $8B86 ;24 HOUR CLOCK AND 0030 OUTVEC .DE $A663 ;DISPLAYS THE AMOUNT OF 0040 IRQVEC .DE $A67E ;REMAINING MEMORY TO BE 0050 CLRINT .DE $AC04 ;ENTERED WHEN REQUESTED 0060 T1CH .DE $AC05 ;THEN AUTOMATICALLY 0070 T1LL .DE $AC06 ;TRANFERS TO BASIC. 0080 ACR .DE $AC0B ;TIME IS NOT DISPLAYED UNTIL 0090 IFR .DE $AC0D ;REQUESTED BY BASIC PROGRAM. 0100 IER .DE $AC0E 0110 BASIC .DE $C000 0F7C- 14 0120 COUNT .BY $14 ;SET COUNT TO 20 0F7D- 00 0130 HOUR .BY $00 ;START TIME AT 00 HOURS 0F7E- 00 0140 MINS .BY $00 ; 00 MINUTES 0F7F- 00 0150 SECS .BY $00 ; 00 SECONDS 0170 ;***INTERRUPT ROUTINE*** 0F80- 48 0190 CLOCK PHA 0F81- CE 7C 0F 0200 DEC COUNT ;SEE IF 1 SEC HAS PASSED 0F84- D0 2D 0210 BNE EXIT ;IF NO, EXIT 0F86- A9 14 0220 LDA #20 ;IF YES, - 0F88- 8D 7C 0F 0230 STA COUNT ; RESTORE COUNT AND 0F8B- EE 7F 0F 0240 INC SECS ; ADD 1 TO SECS. 0F8E- AD 7F 0F 0250 LDA SECS ;SEE IF 60 SECS HAS PASSED 0F91- 38 0260 SEC 0F92- E9 3C 0270 SBC #60 0F94- D0 1D 0280 BNE EXIT ;IF NO, EXIT 0F96- 8D 7F 0F 0290 STA SECS ;IF YES RESET SECS TO 0 AND 0F99- EE 7E 0F 0300 INC MINS ;ADD 1 TO MINS 0F9C- AD 7E 0F 0310 LDA MINS ;SEE IF 60 MINS HAS PASSED 0F9F- E9 3C 0320 SBC #60 0FA1- D0 10 0330 BNE EXIT ;IF NO, EXIT 0FA3- 8D 7E 0F 0340 STA MINS ;IF YES RESET MINS TO 0 AND 0FA6- EE 7D 0F 0350 INC HOUR ;ADD 1 TO HOUR 0FA9- AD 7D 0F 0360 LDA HOUR ;SEE IF 24 HOURS HAS PASSED 0FAC- E9 18 0370 SBC #24 ;IF NO, 0FAE- D0 03 0380 BNE EXIT ; EXIT 0FB0- 8D 7D 0F 0390 STA HOUR ;IF YES, RESET HOUR TO 0 0FB3- AD 04 AC 0400 EXIT LDA CLRINT ;ENABLE TIMER INTERRRUPT 0FB6- 68 0410 PLA 0FB7- 40 0420 RTI 0440 ;***INITIATE TIMER*** 0FB8- 20 86 8B 0460 START JSR ACCESS ;DISABLE WRITE PROTECT SYS. RAM 0FBB- A9 80 0470 LDA #$80 ;SET IRQ 0FBD- 8D 7E A6 0480 STA IRQVEC ; VECTOR 0FC0- A9 0F 0490 LDA #$0F ; TO 0FC2- 8D 7F A6 0500 STA IRQVEC+$1 ; "CLOCK" 0FC5- A9 C0 0510 LDA #$C0 ;SET BITS 6 AND 7 0FC7- 8D 0B AC 0520 STA ACR ;FOR FREE-RUNNING MODE 0FCA- 8D 0E AC 0530 STA IER ;AND T1 INTERRUPT ENABLE 0FCD- AD 0D AC 0540 LDA IFR ;CLEAR T1 FLAG BIT 6 BUT 0FD0- 29 BF 0550 AND #$BF ;DON'T DISTURB OTHER 0FD2- 8D 0D AC 0560 STA IFR ;IFR BITS 0FD5- A9 50 0570 LDA #$50 ;SET 0FD7- 8D 06 AC 0580 STA T1LL ; TIMER 0FDA- A9 C3 0590 LDA #$C3 ; FOR 1/20 SEC AND 0FDC- 8D 05 AC 0600 STA T1CH ; START TIMER 0620 ;***BASIC MEMORY OUT*** 0FDF- A2 00 0640 DISPMEM LDX #$00 ;START OF 0FE1- BD F2 0F 0650 OUTMEM LDA TABLE,X ;ROUTINE 0FE4- 20 63 A6 0660 JSR OUTVEC ; 0FE7- E8 0670 INX ; TO 0FE8- C9 04 0680 CMP #$04 ; 0FEA- F0 03 0690 BEQ GOBAS ; DISPLAY 0FEC- 4C E1 0F 0700 JMP OUTMEM ; REMAINING 0FEF- 4C 00 C0 0710 GOBAS JMP BASIC ; MEMORY 0FF2- 0D 0A 4D 0720 TABLE .BY $0D $0A 'MEM. 3965' $0D $0A $04 0FF5- 45 4D 2E 0FF8- 20 33 39 0FFB- 36 35 0D 0FFE- 0A 04 0730 .EN ;END OF PROGRAM