"1" "2" "3" "4" "5" "6" "7" "8" "9" "0" 24 1C 14 0C 04 03 0B 13 1B 23 "Q" "W" "E" "R" "T" "Y" "U" "I" "O" "P" 25 1D 15 0D 05 02 0A 12 1A 22 "A" "S" "D" "F" "G" "H" "J" "K" "L" ENTER 26 1E 16 0E 06 01 09 11 19 21 "Z" "X" "C" "V" "B" "N" "M" E-MOD SPACE 1F 17 0F 07 00 08 10 18 20 If_no_key is being pressed, the key value is FF. A separate_shift_byte is also returned: FF for_no_shift, 27h for _caps_shift, 18h for_symbol_shift; see shift keys. NB 2. Keyboard_delay_period; also discussed under 02BF KEYBOARD When a main code has been obtained by 031E K TEST, it ischecked for its_repeat_status by 02D1 K CH SET against the firstbyte of each set in 5C00 KSTATE. If it matches either, this is akey repeat; if not, it is a new key, and the main code is put inthe first byte of whichever set is free. A "new key" value won't be accepted from the keyboard by02D1 K CH SET until one of the four-byte sets in 5C00 KSTATE is free; the_five-call_counter in each of these sets is decrementedin 02C6 K ST LOOP on each interrupt, and it takes five interrupts, 0.1 second, to free the set, counted from the last keystroke but one. A repeat key won't be accepted until the value in 5C09 REPDEL has been counted down in 0310 K REPEAT for the first repeat, or the value in 5C0A REPPER for any further repeats. They are in units of 1/50th second interrupts. 5C09 REPDEL and 5C0A REPPER are set on start-up or NEW in 1219 RAM SET, 5C09 REPDEL at 23h/35d interrupts = 0.7 secs and 5C0A REPPER at five interrupts = 0.1 sec; they can be changed by POKing the system variables, but they aren't otherwise changed by ROM. The new key delay can be changed from m/c, but it is more difficult: poke FF into 5C00 KSTATE0 and 5C04 KSTATE4, freeing both sets, to abolish the delay, or poke some other number than 5 into 5C01 KSTATE1 and 5C05 KSTATE5 if they are free. These pokes must be done every time KEYBOARD is called. For a repeat keystroke, the five-call counter is reset to five on each interrupt, so it isn't decremented. NB 3. Conversion of main code to_final_code; also discussed under K DECODE 0333 K DECODE uses the five_key_tables starting at 022C - not table (a), main keys, which is used by 032C K MAIN in 031EK TEST - to convert from the initial key value to the final codefor all characters except 21h, 23h -> 29h, 40h, 5Fh (digits with symbol shift); 80h -> 8Fh (graphics forms); 90h -> A4h (user-defined graphics); 10h -> 17h (the embedded colour controls); E6h -> FFh (tokens, NEW -> COPY); 0Dh, 0Eh, 20h (ENTER, E mode and SPACE). These exceptions are calculated directly from the initial key values in various parts of the routine starting at 0333 K DECODE. Introduction general description; only form of input 0038 MASK INT keyboard scanning on each interrupt 0048 KEY INT calls KEYBOARD to scan keyboard 028E KEY SCAN returns key number 00 -> 27h 0296 KEY LINE half-line (five keys) checked on each loop 029F KEY 3KEYS no action if three keys pressed 02A1 KEY BITS check for two or three keys 02AB KEY DONE ok for one key or two with shift 02BF KEYBOARD get key value and decode to final code 02D1 K CH SET key held down gives repeat 02F1 K NEW ready to decode main code 0308 K END final code into LAST K 0310 K REPEAT key repeat timing 031E K TEST decodes key number to main code 032C KEY MAIN main code found from table (a) 0333 K DECODE decodes main code to final code 0341 K E LET checks shift to choose table (b) or (c) 034A K LOOK UP indexes into table for final code 034F K KLC LET letters with sym shift, or main codes 0364 K TOKENS tokens are main code + A5h 0367 K DIGIT picks table (f) for digits with sym shift 0389 K GRA DGT table (d) for GRAPHICS and DELETE 039D K KLC DGT digit main codes decoded to final code 0970 SA CONTRL awaits keystroke 0C88 PO SCR 2 keystroke fetched by 15D4 WAIT KEY 0D6E CLS LOWER bit 5 TV FLAG: no clear after keystroke 0F38 ED LOOP loop to handle each keystroke 0F6C ED CONTR second code fetched 10A8 KEY INPUT new code fetched and signalled 10FA KEY CODE handles control codes 1219 RAM SET initialises delay mechanisms 1303 MAIN 4 resets FLAGS/5 to signal ready for new key 15DE WAIT KEY1 flags for no-key 1F3A PAUSE checks FLAGS for keystroke 1F49 PAUSE 2 checks bit 5 of FLAGS 1F4F PAUSE END resets bit 5, no keystroke now 2089 INPUT assigns values entered from keyboard 2634 S INKEY$ gets key value and decodes it 3645 read-in gets code from input other than keyboard KEYBOARD SUBROUTINE In the cross-headings of the notes, "KEYBOARD ROUTINES" and "KEYBOARD SCANNING SUBROUTINE" are at 028E KEY SCAN, "KEYBOARD SUBROUTINE" is at 02BF KEYBOARD. KEY CHAN 1113 (10A8 KEY INPUT) Jumps from: 1105 KEY DATA key codes see KEYBOARD SCANNING In the notes it is usually the final code which is meant. KEY CONTR 10FA (10A8 KEY INPUT) Jumps from: 10A8 KEY INPUT KEY DATA 1105 (10A8 KEY INPUT) Jumps from: 10A8 KEY INPUT 10FA KEY CONTR KEY DONE 02AB (028E KEY SCAN) (This heading is duplicated at 02AB and 111B) Exit from: 0296 KEY LINE (028E KEY SCAN) KEY DONE 111B (10A8 KEY INPUT) Exit from: 10A8 KEY INPUT, direct and through 1113 KEY CHAN KEY FLAG 10F4 (10A8 KEY INPUT) Exit from: 10A8 KEY INPUT through one of: 10DB KEY=M&CL 10E6 KEY MODE KEY INPUT subroutine 10A8 Not part of the KEYBOARD SCANNING system, except that itchecks if a new key has been pressed and reads its code from 5C08 LAST K. There is no direct call or jump in ROM, but it is the normal input address for channel K. Channel K input is called by15E6 INPUT AD every fraction of a second from the 15DE WAIT KEY1loop, around which the execution endlessly circles while it is awaiting a new keystroke. Apart from a few calls where any keystroke at all is accepted, eg after "start tape and press anykey", the only calls to 15D4 WAIT KEY are from ED LOOP and ED CONTR in the 0F2C EDITOR routine, for the input of BASIC lines and expressions. The final key codes as found in 5C08 LAST K and read by this subroutine are: 00 BRIGHT off, 01 BRIGHT on, 02 FLASH off, 03 FLASH on, 04 INVERSE off, 05 INVERSE on. It converts these to a pair of codes, the first being 12h plus half the 5C08 LAST K value, ie 12h BRIGHT, 13h FLASH, 14h INVERSE, and the second the final bit, ie 00 for off and 01 for on 06 CAPS LOCK; it implements this immediately. The PRINT comma, which is also code 06, cannot be input as such by any keystroke. 07 EDIT, 08 -> 0B the cursor moves, 0C DELETE, 0D ENTER; it leaves these unchanged 0E E mode or 0F GRAPHICS mode; it changes the mode flag in 5C41 MODE to E/G mode or back to L mode as required. Again, the number marker, which is also code 0E, cannot be input by a keystroke. 10h -> 17h PAPER colours and 18h -> 1Fh INK colours; it outputs two codes, 10h for INK or 11h for PAPER and then the colour parameter 20h and upwards, the characters and tokens; it makes no change. Input parameters: none. Action: check bit 3 of TV FLAG; the "copy editing" flag. The notes call this bit a "mode flag", which is a little misleading, because the flag is set by 15D4 WAIT KEY whenever the waiting loop is entered, whether there has been a mode change or not, to signal "recopy input to lower screen" - if it is set call 111D ED COPY to recopy the editing or input BASIC to the lower screen - read FLAGS bit 5; the "new key" flag - if no new key has been pressed return - (new key pressed) read 5C08 LAST K and reset the "new key" flag - if TV FLAG bit 5 is set call 0D6E CLS LOWER to clear the lower screen; the "clear lower screen" flag. This is quite unusual, 111D ED COPY completely overwrites the lower screen display and doesn't require the rather slow screen clearing - if the key code is 20h or more jump on to KEY DONE; all characters, including space and tokens - (control codes) if it is 10h -> 1F jump on to KEY CONTR; INK and PAPER colours - if it is 06 -> 0F jump on to KEY M&CL; editing controls - (00/01 BRIGHT, 02/03 FLASH and 04/05 INVERSE) make an on/off byte, zero/off for the even codes and one/on for the odd - halve the 5C08 LAST K value; making 00 BRIGHT, 01 FLASH, 02 INVERSE - add 12h/18d; 12h/18d BRIGHT, 13h/19d FLASH, 14h/20d INVERSE, which are the correct control codes - jump on to KEY DATA. _10DB_K_M&CL (06 -> 0F): if the code isn't 06 CAPS LOCK, jump on to KEY MODE - XOR FLAGS2 bit 3 with 00001000b/08; flop the CAPS LOCKflag - jump on to KEY FLAG. _10E6_KEY_MODE (07 -> 0F): if the code is less than 0E return; 07 EDIT -> 0D ENTER are left alone - subtract 0D to reduce 0E E mode to 01 and 0F GRAPHICS to 02 - compare the result with the MODE flag in 5C41 MODE; they are the values for E and G modes - load the result into 5C41 MODE anyway - if the comparison showed a change in MODE jump on to KEY FLAG - if there was no change load zero into 5C41 MODE; E andG modes are both on/off switches, so if the mode is already E mode, make it L mode, and similarly for G. _10F4_KEY_FLAG: set bit 3 of TV FLAG and return with NC; the "copy edit" flag will make KEY INPUT recopy the input line on the next turn of the loop to show the new cursor. _10FA_KEY_CONTR (code 10h -> 17h for a PAPER colour or 18h -> 1Fh for an INK colour): AND the code with 00000111b/07; to separate off the last three bits, which are the colour number - make a control code byte 10h; INK - if bit 3 of the given code is set jump on to KEY DATA;18 -> 1Fh INK - (10 -> 17h PAPER) make the control code byte 11h. _1105_KEY_DATA (whether execution came from KEY INPUT or KEY CONTR, the A register holds a colour control code 10h INK ->15h OVER and the C register its parameter): park the control code in 5C0D K DATA for the moment - make a new input address KEY NEXT - jump on to KEY CHAN, which makes KEY NEXT temporarily the input address of the current channel K; 15D4 WAIT KEY will return with the control code in A. 0F38 ED LOOP, when it finds this code, immediately calls WAIT KEY again for the parameter: this time 15E6 INPUT AD will jump to the temporary input addressKEY NEXT. _110D_KEY_NEXT (the label is only used for the temporary input address put in channel K by KEY CHAN) recover the parameter code from 5C0D K DATA - make the normal input address 10A8 KEY INPUT to be putback in the channel. _1113_KEY_CHAN: put a pointer on the channel input address - load it with either KEY NEXT supplied by KEY DATA, or KEY INPUT supplied by KEY NEXT. [For the double somersault performed with the input channel address in KEY DATA and following, cf the similar acrobatics with the output address in 0A75 PO 2 OPER and 0A7A PO 1 OPER.] _111B_KEY_DONE: return with carry; so as to escape from the WAIT KEY1 loop. Exit: RET, from KEY INPUT, KEY FLAG or KEY DONE. Output parameters: A holds the final code from 5C08 LAST K, adjusted if necessary for control codes - 5C41 MODE has been changed if appropriate - bit 5 of FLAGS is zero; showing "not dealing with new key" - the carry flag indicates "new code found", except whenno key has been pressed or when only the cursor has changed. Set in channel K by: 0D94 CL CHAN 110D KEY NEXT 1219 RAM SET (from 15AF initial channel information) Rems: 101E ED IGNORE skips two inputs - ineffective 1105 KEY DATA temporarily changes input address KEY INT 0048 (0038 MASK INT) Exit from: 0038 MASK INT (twice) KEY LINE 0296 (028E KEY SCAN) Jumps from: 02AB KEY DONE KEY MODE 10E6 (10A8 KEY INPUT) Exit from: 10DB KEY M&CL (10A8 KEY INPUT) KEY NEXT 110D (10A8 KEY INPUT) No calls or jumps from ROM; temporarily set as the inputaddress of channel K by 1105 KEY DATA; the effect is that two character codes are input on one scan of the keyboard. key number, key repeat period, key repeats see KEYBOARD SCANNING KEY SCAN subroutine 028E Called fifty times per second by the KEYBOARD SCANNING system to scan the keyboard by reading the eight key input ports; if any keys are being pressed it picks up the key bits and converts them to a key value. See the summary under KEYBOARDSCANNING, especially NB 1. The byte input from the port has ones in its last five bits indicating keys which aren't being pressed in the corresponding half-line, and zeroes corresponding to pressed keys. Reverse the byte - zeroes to ones and vice versa - and ANDit with 00011111b/1Fh; this makes zero if all the key bits were ones, but if not, at least one key is being pressed and the non-zero key bits indicate the position of pressed keys in this half-line. Each port is read with an initial key value, 2F for the first port, decreasing by one for each successive port. Take 08 from the initial key value; rotate the key bits right and take away 08 again, and repeat till a set bit is found, correspondingto a zero bit in the original key bits. This reduces an initial key value