Make Your Atari Keyboard A Little Friendlier
If you've ever been typing on the Atari computer and hit the inverse video key instead of the shift key, cleared the screen inadvertently, or locked the keyboard into character graphics mode when you only meant to move the cursor right one space, then this article is for you.
Although I do use assembly language to tame the Atari down a bit, don't worry if you don't know a thing about programming in assembly because I've included a version of my code written in BASIC. And for those of you who are old pros at tickling the insides of your machines, you'll find a listing of the original source code with notes on how it works.
This code does two main things. First, it speeds up the initial delay you encounter while waiting for the auto-repeat to engage. Normally there is a pause of about ¾ of a second after pressing a key before it starts to repeat. This seems a bit too long to me. It gets to be aggravating, especially when moving the cursor around the screen for editing. You can adjust this speed to suit yourself, or even shut the auto-repeat off altogether if you like.
The Right Pinkie's Burden
The second main thing this code does is to give you an audible signal when you press the inverse video key, the clearscreen key, caps/lower key, or the shift-delete key. The burden of finding all these keys plus a number of others is dumped completely on the right hand's little pinky, making it all too easy to make a mistake. For example, when typing a long mathematical formula, it has been quite frustrating to me when, instead of hitting the final right parenthesis, I'd accidentally press the clear-screen, leaving me to start all over. This happened to me so many times that I decided to do something about it. Now, instead of the screen going blank, I get the sound of five quick keyclicks letting me know my little pinky is off target. If I really want the screen cleared, I just hold the key down a bit longer than usual for the key to be activated. This short wait seems a small price to pay compared to the time that can be lost in correcting mistakes.
Whether you know assembly or not, if you have a disk drive and DOS 2, you can create an "AUTORUN" file so that, when you turn your computer on, the keyboard will behave itself automatically. If you're using DOS 1 or a cassette only system, you'll have to run the BASIC program each time you power up. Of course, those of you without DOS 2 running the assembler cartridge will have to load in the necessary object code after powering up.
A special note to anyone using a cassette, with or without disk drives: If you want to use your cassette in addition to taming your keyboard down, you'll have to switch the two values at the beginning of the BASIC version of the program. I'll try to explain:
There are 256 bytes of memory (referred to as Page 6) available for use any way you see fit located at address 600 hex, or 1536 decimal. The computer's operating system doesn't use them, nor does any typical BASIC program. Still, many BASIC programs, with a need for high-speed assembly language subroutines, do use Page 6. In my own programming, I frequently make use of this area of memory and wanted to put the keyboard code someplace else which was safe from unfriendly programs. There are 131 bytes of memory similar to Page 6, located at address 3FD hex, 1021 decimal, unused for anything but conversations between the computer and the cassette. Since I rarely use my cassette, I appropriated this area of memory to hold the new keyboard code. Since this forfeits your ability to use the cassette, you may wish to forfeit use of Page 6 instead by switching the two previously mentioned values at the beginning of the program. The initialization code can pretty much go anywhere, since it's only used once when the program is run, but the keyboard code has to have a permanent place to reside. If neither Page 6 nor the cassette buffer will work for you, you'll have to find some other place for the code. But when you do, you'll only have to change the values at lines 190 and 200 to the new addresses where you want the code placed since it is position independent.
For those of you using a cassette only, or those of you with DOS 1, just run the BASIC program that follows. I suggest first saving a copy of the program before running it though, since, as with any assembly program, if you make a mistake, your computer may very well "lock-up," requiring you to turn it off and back on. Hopefully you will find this program useful and a timesaver. Once it has been run, it is no longer needed in memory and is transparent to normal operations of the computer.
This paragraph is for those of you using DOS 2. Run the BASIC program that follows and see how your keyboard acts afterwards. Then, call up the DOS menu and type "K" for the binary save option. If you already have an AUTORUN file on your disk, respond with "D1 : AUTORUN, SYS/A, 3FD, 47F". If you don't already have an AUTORUN file on the disk leave the "/A" off the filename. This will save or append the cassette buffer area containing the new keyboard instructions. Again type "K", and now respond with "D1: AUTORUN.SYS/A, 600, 60B, 601". Don't forget the "/A". This will append the initialization code along with the proper initialization address. That's it Now, whenever you turn the computer on with this AUTORUN file present, your keyboard will be ready to go automatically.
Changing The Auto-repeat Speed
As I mentioned before, the delay before the auto-repeat engages can be changed, and I've shortened it to suit my typing habits. Decreasing the second number in the data list at line 520, which is now 15, will decrease the length of time before the auto-repeat starts. I doubt you will want to decrease it, but increasing this number will slow the repeat down if you end up typing things like "LLISSTT." You can turn the auto-repeat off altogether by changing this number to a zero. If you should want to disable the new keyboard characteristics (to use the cassette for example) just press the System Reset key. It'll restore the keyboard to normal.
After careful study of the operating system source code, I regret to report that two desirable changes are not feasible. It does not look possible to change the speed of the auto-repeat once it has begun. Nor does it look feasible to shut off the keyclick with software. The keyclick got on my nerves when I first got my computer and, for what it's worth, I dicsovered that the bottom cover of the computer is easily removed (at the expense of voiding your warrenty) and the speaker can be unplugged. However, you lose use of the warning bell or buzzer, so I chose to solder a 200 ohm resister in series with the speaker to soften the volume of the keyclick without losing the bell.
How It Works
At the heart of the Atari computer is a 6502 microprocessor chip. It's always running some kind of program and always in the only language it understands, 6502 machine code. Whenever you use the BAS1C cartridge, you're really running a machine language program called "BASIC," which waits for you to tell it to do something, such as to run a program you've typed into memory with its assistance. This program then "interprets" your instructions and sends the 6502 off to execute various machine code subroutines which collectively, and in the proper sequence, accomplish what you told the BASIC "interpreter" you wanted to have done. So, any time your computer is on, the 6502 is always executing machine code instructions.
It is possible to "tap the computer on the shoulder," asking it to stop what it's doing and take care of something else. This is called an interrupt. Regardless of whether the computer was busy drawing on the screen, trying to figure out a BASIC program, or whatever, it'll take note of what it was doing so that it can pick up again where it left off after it finishes taking care of the interruption.
There are all kinds of things that can cause an interrupt. One of them is pressing a key on the keyboard. Whenever a key is pressed, the 6502 gets "tapped on the shoulder," and it goes to a subroutine located in the operating system ROM. This subroutine does some checking around and finds out that a key was pressed. Then it looks at memory location 208 hex, which is called VKEYBD, short for Keyboard Vector. Now, vector is just a fancy word for pointer and normally, this memory location contains the starting address of another subroutine in ROM which takes care or saving information about the particular key that was pressed so that, at some time later on, yet another subroutine can do something with it (like print the letter on the screen). The initialization code at the end of assembly language listing changes the value contained in the keyboard vector VKEYBD so that the 6502 will follow our instructions on what to do when a key is pressed. In fact, we'll tell the 6502 to figure out if the key pressed is one of those that our little pinky hits by mistake so often.
Most of the assembly code is fairly self-explanatory, but a few things are worth discussing. AT line 500 of the assembly language listing a check is done first to make sure that the computer wasn't interrupted while it was in the middle of doing something where timing is critical, such as talking to the disk drive. Lines 610–650 take care of key-bounce, caused by the vibration of the switch contacts inside the keys.
It is also worth noting that this whole routine is executed only in response to a key being pressed. Holding a key down for the auto-repeat does not generate any further interrupts, and repetition of the key is accomplished at a later time during another type of interrupt, the Vertical Blank period. This interrupt occurs sixty times a second during the time between pictures on your TV screen. The instructions executed during this interrupt are located in an area of the operating system that does not appear to be bypassable. This is also where the keyclicks are generated, making it impossible to shut them off or change the auto-repeat speed itself.
Although it is possible to intercept the vertical blank interrupt, it does not look feasible to replace the operating system ROM routines which take care of these things. If anyone has information to the contrary I'd be very interested in hearing from you. The reason the initial repeat speed can be altered is that the auto-repeat timer, SRTIMR, is initialized during the key-pressed interrupt.
At line 810 bits 6 and 7 of the key code are set to zero since these bits indicate the shift or control key was pressed which is no importance in the case of these two keys. The keycodes themselves have no relation to the ASCII or ATASCII codes. Only the engineers who designed the keyboard could tell you why they created it the way they did, (like why the little pinky got stuck with so many keys to deal with). Anyway, if you want to alter the program to warn you about your own problem keys, you can easily determine their codes with the following one-line BASIC program:
10 PRINT PEEK(53769): GOTO 10
At lines 1210–1260 you may notice a slightly curious bit of code. VCOUNT is a hardware register which can be read to determine the current scan line being drawn on the TV screen. This value will be zero, sixty times each second, and provides a quick and easy way to obtain a do-nothing loop without tying up any memory locations for counting. Of course, you might wonder why I didn't just use one of the system timers. There are two big reasons why not. One is that I wanted my routine to be as transparent to normal computer operations as possible and tying up a timer could conflict with another program. But a bigger reason is that the system timers are themselves maintained during an interrupt cycle, the old vertical blank period.
Thus, whenever pressing a key causes an interrupt, all other low priority interrupts are temporarily ignored, meaning that the system timers stop. They remain frozen during the time that this program code is being executed and resume counting afterwards. If having the timers lose accuracy is a problem for your application, I suggest adding a little more code which would make an appropriate correction to the timer values. I didn't do this because there is no way the extra code would fit into the cassette buffer. It is being packed to the very last byte already.
Finally, at lines 1400–1430 of the assembly listing, bit 3 of the memory-mapped hardware register named SKSTAT (Serial Port/Keyboard Status) is selected with a logical AND command. This bit indicates whether the last key pressed is still depressed, and is the determining factor as to whether one of those problem keys is actually wanted. May you never know the agony of delete (or clearscreen) again!