VIC Ringer
Thomas Henry, Mankato, MN
VIC Ringer is a utility that should be in any programmer's bag of tricks. Those who are used to wide screen computers will find it especially helpful in working with VIC's screen wraparound.
The Commodore VIC-20 computer has got to be one of the most pleasant computers to program. However, you might find the 22-column screen a little disconcerting, especially if you were brought up on other computers. Of course, the VIC-20 does have screen wraparound, meaning that your BASIC lines can be a full 88 characters wide, including the line numbers. A BASIC line can actually occupy four normal screen display lines. This is a great scheme, but if your mind is on programming you may forget to watch for the end of this four-line limit. This is especially true if you are adding a line and the screen is already full of other statements.
Let's add an end-of-the-line bell. This bell should ring when the cursor is within, say, eight spaces of the end of a BASIC line. This gives enough warning so that you can finish up the line or make the necessary changes to start a new line. The Commodore CBM-8032 has such a bell, and so does every typewriter; why shouldn't the VIC-20?
"VIC Ringer" is written in machine language and sits at the top of memory. The top of memory pointers at $37 and $38 are automatically adjusted so that they point just below the Ringer. Thus the program is "locked in" and safe from BASIC program interference. It can then peacefully coexist with any other programs you may care to enter in.
The principle of operation is quite simple. On the VIC-20 every 1/60 of a second, the computer stops doing whatever it may have been doing and goes to an Interrupt Request service routine. This routine scans the keyboard for key closures, refreshes the display, updates the realtime clock, and so forth. The VIC Ringer program is inserted into this Interrupt Request routine. Essentially, when the computer receives the interrupt signal, it will jump to the VIC Ringer routine and check to see if the cursor is at the 80th position on a BASIC line. If it is, and if this is the first time the 80th position has been found, then the bell rings. The computer then jumps to the normal Interrupt Request routine. If the cursor is not on the 80th position, the bell ringer routine is skipped.
A Carefully Designed Sound
Locations $0314 and $0315 contain the address (hexadecimal, low byte and high byte) of the normal Interrupt Request entry point. These are modified by the program to point at the start of the VIC Ringer.
A great deal of attention was given to the actual bell subroutine. The bell had to be noticeable, but not objectionable. The low voice of the VIC-20 was used (location $900A), but it is used in its very highest range. To make the bell stand out, it is made to go through a series of tones quite rapidly. The result is a "tweedle-tweedle" sound not unlike the bell in a Commodore CBM-8032.
The bell subroutine has been written so that if the programmer is already using the various voices for something, he won't tamper with their amplitudes. The value in location $900E which specifies the volume or amplitude of the voices is pushed into the stack and saved. This value is restored when the bell is through ringing. This helps make the VIC Ringer transparent to the computer. Just load it and forget about it!
The program is written as a BASIC loader. This loader automatically compensates for any memory attachments, making the program suitable for VICs with any amount of memory. In addition, the SYS command in line number 300 initializes the program. So, you can use the quick load feature (shift [RUN] key) to put the VIC Ringer into memory.
The location at which the bell rings can be modified, if desired, by changing the 80 in line 330 to any number between 0 and 88. Most typewriters ring when they're five spaces from the end. If this is desired, change the number to 83.
200 PRINT "WAIT A FEW MOMENTS…" 210 T = 256 * PEEK(56) + PEEK (55) : X = T - 1 220 GOSUB 310 : T(1) = L : T (2) = H% 230 X = T - 71 240 GOSUB 310 : T(3) = L : T (4) = H% 250 POKE 55, T(3) : POKE 56,T (4) 260 FORA = T - 84TOT - 1 270 READD$ : IFLEFT$ (D$, 1) = "T" THENS = VAL (RIGHTS(D$, 1)) : D = T (S) : GOTO290 280 D = VAL(D$) 290 POKEA, D : NEXT 300 SYS (T–84) : NEW 310 H% = X/256:L = X - 256 * H% : RETURN 320 DATA 120, 169, T3, 141, 20, 3, 169, T4, 141, 21, 3, 88, 96, 72, 138, 72 330 DATA 152, 72, 165, 211, 208, 5, 162, 248, 142, T1, T2, 201, 80, 208, 44, 173 340 DATA T1, T2, 240, 39, 173, 14, 144, 72, 169, 15, 141, 14, 144, 173, T1, T2 350 DATA 41, 254, 141, 10, 144, 162, 16, 160, 255, 136, 208, 253, 202, 208, 248, 238 360 DATA T1, T2, 208, 233, 142, 10, 144, 104, 141, 14, 144, 104, 168, 104, 170, 104 370 DATA 76, 191, 234, 170