|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
It is would be a straightforward task to make the PS2 keyboard routine, but in this project the timings are too tight to realize the full PS2 communication and, to get things worse, video signal and keyboard packets are totally asynchronous and there is no way to synchronize them. The approach used here is to poll the Clock state at the beginning of each horizontal scan line and fetch Data status if the falling edge was detected. Macro EXTRAJOB does this. Start, parity and stop bits are ignored, and the only synchronization condition is if the pause in clock signal is longer than 3.2 ms. The received data bytes are written into 4-byte buffer KBDSTREAM, where they are waiting for the end of the frame (routine LOWERFRAME) to be analyzed. The keyboard scan codes (set 2) are converted into ASCII codes and written at the location KBDBUF, where it is available for the user's program, located outside of the interrupt routine. Bit FLAG,#1 is used for handshaking: interrupt routine sets it when the key is depressed ("make" scan code detected), and the user's routine has to reset it when the ASCII character is read from KBDBUF. The raw scan codes are written in the 6-byte variable RAW_KEY (4-byte keyboard scan codes in RAW_KEY+0...RAW_KEY+3, and the byte count in RAW_KEY+4). If you uncomment the line call keydata at the beginning of DEMO.INC file, those bytes will be displayed at the top of the screen in hexadecimal form, each time the key is pressed. The fourth 4-digit hex number is ASCII code (or special code, according to the following table) for the pressed key. Uppercase and lowercase codes are automatically affected by the state of the SHIFT key and CAPS LOCK key. Special (non-ASCII) keys have their special codes, which are listed here. Those codes (which are located in table CODES_00 or, if code begins with EO byte, table CODES_E0) do not belong to any standard (excluding BKSP and TAB), they are used only in this project.
There is the special KBDFLAG variable in data memory, which is serviced by the routine so that it contains flags for some special keys. Those flags should only be read, not modified by the user's routine (BREAK codes listed in the previous table are are used by the interrupt routine for KBDFLAG servicing). KBDFLAG,#0
set if the SHIFT key is depressed, reset when
released There is the subroutine GET_KEY, which does most of the job for keyboard interfacing via KBDBUF and FLAG,#1. This is the action: Wait for key pressed (FLAG,#1 set) and get key code from
KBDBUF For most applications, the best way to read keyboard is to call this subroutine and read W0 when it returns. W0 will contain ASCII code of the pressed key or the code from the previous table. All SHIFT and CAPS LOCK variations are covered. If you need just to test if the key is pressed, without looping until it is pressed, and to return to the main program, you have to test the FLAG,#1 and, if it is set, call subroutine CONVERT_KEY, which will clear FLAG,#1, translate KBDBUF content and return ASCII or special code value in W0.
Note 1: In this project, there is no way to pass the parameters (autorepeat timings and LEDs states) to the keyboard. Note 2: The protocol in this routine is simplified, as it is highly optimized for the execution speed. In some cases, when the keyboard sends more scan codes without the pause, it may omit some keys. It makes it theoretically possisible to omit some SHIFT, CTRL and ALT break codes if more keys are pressed at the same time. So, in some rare cases, the false states of KBDFLAG bits may occur, e.g. KBDFLAG,#0 may be set even if the SHIFT key was released. Depressing and releasing SHIFT again will rebuild the correct flag state. The same applies for CTRL, ALT and ENTER bits in variable KBDFLAG. The possible way to solve this problem is to employ some ring buffer which will be loaded by the raw data from the keyboard, even if there was no pause between data streams detected, as the problem is the consequence of waiting for that pause. To improve the keyboard routine, that part of the program must be rearranged, with the larger (but still fast enough) buffer, and the another routine (possibly in the main program) which analyzes the content of that buffer. Note 3: The unit was tested with several PS/2 keyboards and it worked, but it supports only SET 2 codes. Although SET 3 is rarely used, there is still the possibility that you have such keyboard. In that case, you have to rearrange keyboard tables in file TABLES.INC (codes.00 and codes.e0). SET 1 is used only by the obsolete XT keyboard, which is not supported by this project. |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||