\************************************************************************* \* * \* MAIN KEYBOARD HANDLER * \* ===================== * \* * \************************************************************************* \ Keyboard input housekeeping \ Jumped to from &F00C, is here to drop through to LED setting \ ------------------------------------------------------------ EEDA LDX #&FF ; EEDC LDA &EC ;get value of most recently pressed key EEDE ORA &ED ;OR it with previous key to check for presses EEE0 BNE &EEE8 ;if A=0 no keys pressed so off you go EEE2 LDA #&81 ;else enable keybd interupt only by writing bit 7 EEE4 STA &FE4E ;and bit 0 of system VIA interupt register EEE7 INX ;set X=0 EEE8 STX &0242 ;reset keyboard semaphore **********: Turn on Keyboard indicators ******************************* EEEB PHP ;save flags EEEC LDA &025A ;read keyboard status; ;Bit 7 =1 shift enabled ;Bit 6 =1 control pressed ;bit 5 =0 shift lock ;Bit 4 =0 Caps lock ;Bit 3 =1 shift pressed EEEF LSR ;shift Caps bit into bit 3 EEF0 AND #&18 ;mask out all but 4 and 3 EEF2 ORA #&06 ;returns &06 if caps lock OFF, &0E if ON EEF4 STA &FE40 ;turn on or off caps light if required EEF7 LSR ;bring shift bit into bit 3 EEF8 ORA #&07 ; EEFA STA &FE40 ;turn on or off shift lock light EEFD JSR &F12E ;set keyboard counter EF00 PLA ;pop flags into A register, setting M from saved M EF01 RTS ;return, A.b7=Control, A.b6=Shift, MI=Control, VS=Shift ************************************************************************* * * * MAIN KEYBOARD HANDLER - ENTRY FROM KEYV * * ======================================= * * * * ENTRY CONDITIONS * * ================ * * VS=Keyboard interupt * * CC=Keypress interupt * * CS=Centisecond keypress poll * * * * VC=Scan keyboard for keypresses * * CC=Test SHIFT and CTRL keys * * CS=Scan full keyboard as with OSBYTE &79/negative INKEY * * * ************************************************************************* EF02 BVC &EF0E ; If V is clear jump to keyscan routines EF04 LDA #&01 ; Disable keyboard interrupts EF06 STA &FE4E ; by writing to VIA interrupt settings EF09 BCS &EF13 ; Jump with timer interupt EF0B JMP &F00F ; Otherwise, jump with keypress interupt EF0E BCC &EF16 ; Jump to test SHIFT and CTRL EF10 JMP &F0D1 ; Otherwise, jump to scan whole keyboard \************************************************************************* \* Keyboard Timer interrupt entry * \* Enters with VS, CS * \************************************************************************* EF13 INC &0242 ; Increment keyboard semaphore (to 0) ; ; Continue through testing state of SHIFT and CTRL keys ************************************************************************* * Keyboard Test Shift and Control Keys entry * * Enters with VC, CC * * Exits with MI=Control, VS=Shift, A.b7=Control, A.b6=Shift * ************************************************************************* EF16 LDA &025A ; Get current keyboard status ;Bit 7 =1 Shift enabled ;Bit 6 =1 Control pressed ;bit 5 =0 Shift Lock ;Bit 4 =0 Caps Lock ;Bit 3 =1 Shift pressed EF19 AND #&B7 ; Clear bits 3 and 6, Shift & Ctrl off EF1B LDX #&00 ; X=&00 to test for Shift key EF1D JSR &F02A ; Interrogate keyboard, does INKEY-(0+1), ie INKEY-1 ; On return X=&80 if key is pressed EF20 STX &FA ; Save SHIFT keypress state EF22 CLV ; Clear V = SHIFT not pressed EF23 BPL &EF2A ; If SHIFT not pressed, if no key press (X=0) then EF2A else EF25 BIT &D9B7 ; Set V = SHIFT is pressed EF28 ORA #&08 ; Set bit 3 to indicate Shift was pressed EF2A INX ; X=&01 or &81 to test for Control key EF2B JSR &F02A ; Interrogate keyboard, does INKEY-(1+1), ie INKEY-2 ; ; On return X=&81 if key is pressed, M set EF2E BCC &EEEB ; If Carry Clear, was entered to test Shift & Control, ; jump to update keyboard lights and return EF30 BPL &EF34 ; If CTRL not pressed, skip past EF32 ORA #&40 ; Set bit 6 to indicate Control pressed EF34 STA &025A ; Update keyboard status byte EF37 LDX &EC ; Get previous keypress EF39 BEQ &EF4D ;if no key previously pressed then EF4D EF3B JSR &F02A ;else check to see if key still pressed EF3E BMI &EF50 ;if so enter repeat routine at EF50 EF40 CPX &EC ;else compare X with last key pressed (set flags) EF42 STX &EC ;store X in last key pressed EF44 BNE &EF4D ;if different from previous (Z clear) then EF4D EF46 LDX #&00 ;else zero EF48 STX &EC ;last key pressed EF4A JSR &F01F ;and reset repeat system EF4D JMP &EFE9 ; ********** REPEAT ACTION ************************************************* EF50 CPX &EC ;if X<>than last key pressed EF52 BNE &EF42 ;then back to EF42 EF54 LDA &E7 ;else get value of AUTO REPEAT COUNTDOWN TIMER EF56 BEQ &EF7B ;if 0 goto EF7B EF58 DEC &E7 ;else decrement EF5A BNE &EF7B ;and if not 0 goto EF7B ;this means that either the repeat system is dormant ;or it is not at the end of its count EF5C LDA &02CA ;next value for countdown timer EF5F STA &E7 ;store it EF61 LDA &0255 ;get auto repeat rate from 0255 EF64 STA &02CA ;store it as next value for Countdown timer EF67 LDA &025A ;get keyboard status EF6A LDX &EC ;get last key pressed EF6C CPX #&D0 ;if not SHIFT LOCK key (&D0) goto EF6E BNE &EF7E ;EF7E EF70 ORA #&90 ;sets shift enabled, & no caps lock all else preserved EF72 EOR #&A0 ;reverses shift lock disables Caps lock and Shift enab EF74 STA &025A ;reset keyboard status EF77 LDA #&00 ;and set timer EF79 STA &E7 ;to 0 EF7B JMP &EFE9 ; EF7E CPX #&C0 ;if not CAPS LOCK EF80 BNE &EF91 ;goto EF91 EF82 ORA #&A0 ;sets shift enabled and disables SHIFT LOCK EF84 BIT &FA ;if bit 7 not set by (EF20) shift NOT pressed EF86 BPL &EF8C ;goto EF8C EF88 ORA #&10 ;else set CAPS LOCK not enabled EF8A EOR #&80 ;reverse SHIFT enabled EF8C EOR #&90 ;reverse both SHIFT enabled and CAPs Lock EF8E JMP &EF74 ;reset keyboard status and set timer \*********** Convert keypress to ASCII and insert in keyboard buffer **** ;on entry X=key pressed internal number EF91 LDA &EFAB,X ;get code from lookup table EF94 BNE &EF99 ;if not zero goto EF99 else TAB pressed EF96 LDA &026B ;get TAB character EF99 LDX &025A ;get keyboard status EF9C STX &FA ;store it in &FA EF9E ROL &FA ;rotate to get CTRL pressed into bit 7 EFA0 BPL &EFA9 ;if CTRL NOT pressed EFA9 EFA2 LDX &ED ;get no. of previously pressed key EFA4 BNE &EF4A ;if not 0 goto EF4A to reset repeat system etc. EFA6 JSR &EABF ;else perform code changes for CTRL EFA9 ROL &FA ;move shift lock into bit 7 EFAB BMI &EFB5 ;if not effective goto EFB5 else EFAD JSR &EA9C ;make code changes for SHIFT EFB0 ROL &FA ;move CAPS LOCK into bit 7 EFB2 JMP &EFC1 ;and Jump to EFC1 EFB5 ROL &FA ;move CAPS LOCK into bit 7 EFB7 BMI &EFC6 ;if not effective goto EFC6 EFB9 JSR &E4E3 ;else make changes for CAPS LOCK on, return with ;C clear for Alphabetic codes EFBC BCS &EFC6 ;if carry set goto EFC6 else make changes for EFBE JSR &EA9C ;SHIFT as above EFC1 LDX &025A ;if shift enabled bit is clear EFC4 BPL &EFD1 ;goto EFD1 EFC6 ROL &FA ;else get shift bit into 7 EFC8 BPL &EFD1 ;if not set goto EFD1 EFCA LDX &ED ;get previous key press EFCC BNE &EFA4 ;if not 0 reset repeat system etc. via EFA4 EFCE JSR &EA9C ;else make code changes for SHIFT EFD1 CMP &026C ;if A<>ESCAPE code EFD4 BNE &EFDD ;goto EFDD EFD6 LDX &0275 ;get Escape key status EFD9 BNE &EFDD ;if ESCAPE returns ASCII code goto EFDD EFDB STX &E7 ;store in Auto repeat countdown timer EFDD TAY ; EFDE JSR &F129 ;disable keyboard EFE1 LDA &0259 ;read Keyboard disable flag used by Econet EFE4 BNE &EFE9 ;if keyboard locked goto EFE9 EFE6 JSR &E4F1 ;put character in input buffer EFE9 LDX &ED ;get previous keypress EFEB BEQ &EFF8 ;if none, go to EFF8 EFED JSR &F02A ;examine to see if key still pressed EFF0 STX &ED ;store result EFF2 BMI &EFF8 ;if pressed goto EFF8 EFF4 LDX #&00 ;else zero X EFF6 STX &ED ;and &ED EFF8 LDX &ED ;get &ED EFFA BNE &F012 ;if not 0 goto F012 EFFC LDY #&EC ;get first keypress into Y EFFE JSR &F0CC ;scan keyboard from &10 (osbyte 122) F001 BMI &F00C ;if exit is negative goto F00C F003 LDA &EC ;else make last key the F005 STA &ED ;first key pressed i.e. rollover F007 STX &EC ;save X into &EC F009 JSR &F01F ;set keyboard repeat delay F00C JMP &EEDA ;go back to EEDA ************************************************************************* * Keyboard Key pressed interrupt * * Enters with VS, CC * ************************************************************************* ;enters with X=key F00F JSR &F02A ; Stop autoscan by testing for a random keypress F012 LDA &EC ; Get previous key press F014 BNE &F00C ; If key currently pressed, back to housekeeping routine F016 LDY #&ED ; Point Y to last keypress location F018 JSR &F0CC ; Scan keyboard for a pressed key F01B BMI &F00C ; If negative, no key found, exit F01D BPL &F007 ; Positive, key press found, store it and prepare autorepeat **************** Set Autorepeat countdown timer ************************** F01F LDX #&01 ;set timer to 1 F021 STX &E7 ; F023 LDX &0254 ;get next timer value F026 STX &02CA ;and store it F029 RTS ; *************** Interrogate Keyboard routine *********************** ; F02A LDY #&03 ;stop Auto scan F02C STY &FE40 ;by writing to system VIA F02F LDY #&7F ;set bits 0 to 6 of port A to input on bit 7 ;output on bits 0 to 6 F031 STY &FE43 ; F034 STX &FE4F ;write X to Port A system VIA F037 LDX &FE4F ;read back &80 if key pressed (M set) F03A RTS ;and return ************************************************************************* * * * KEY TRANSLATION TABLES * * * * 7 BLOCKS interspersed with unrelated code * ************************************************************************* key data block 1 F03B DB 71,33,34,35,84,38,87,2D,5E,8C ; q ,3 ,4 ,5 ,f4,8 ,f7,- ,^ ,rt ************************************************************************* * * * OSBYTE 120 Write KEY pressed Data * * * ************************************************************************* F045 STY &EC ;store Y as latest key pressed F047 STX &ED ;store X as previous key pressed F049 RTS ;and exit key data block 2 F04A DB 80,77,65,74,37,69,39,30,5F,8E ; f0,w ,e ,t ,7 ,i ,9 ,0 ,_ ,lft F055 JMP (&FDFE) ;Jim paged entry vector F058 JMP (&FA) ; key data block 3 F05A DB 31,32,64,72,36,75,6F,70,5B,8F ; 1 ,2 ,d ,r ,6 ,u ,o ,p ,[ ,dn ************************************************************************* * * * Jump to keyboard handler interupt routine * * * ************************************************************************* F065 BIT &D9B7 ; Set V to signal interupt call F068 JMP (&0228) ; Jump via KEYV to keyboard handler key data block 4 F06B DB 01,61,78,66,79,6A,6B,40,3A,0D ; CL,a ,x ,f ,y ,j ,k ,@ ,: ,RETN CL=CAPS LOCK speech routine data F075 DB 00,FF,01,02,09,0A key data block 5 F07B DB 02,73,63,67,68,6E,6C,3B,5D,7F ; SL,s ,c ,g ,h ,n ,l ,; ,] ,DEL SL=SHIFT LOCK ************************************************************************* * * * OSBYTE 131 READ OSHWM (PAGE in BASIC) * * * ************************************************************************* F085 LDY &0244 ;read current OSHWM F088 LDX #&00 ;address is &xx00 F08A RTS ; key data block 6 F08B DB 00 ,7A,20 ,76,62,6D,2C,2E,2F,8B ; TAB,Z ,SPACE,V ,b ,m ,, ,. ,/ ,copy ***** set input buffer number and flush it ***************************** F095 LDX &0241 ;get current input buffer F098 JMP &E1AD ;flush it key data block 7 F09B DB 1B,81,82,83,85,86,88,89,5C,8D ; ESC,f1,f2,f3,f5,f6,f8,f9,\ ,rgt F0A5 JMP (&0220) ;go to eventV handling routine ************************************************************************* * * * OSBYTE 15 FLUSH SELECTED BUFFER CLASS * * * ************************************************************************* ;flush selected buffer ;X=0 flush all buffers ;X>1 flush input buffer F0A8 BNE &F095 ;if X<>1 flush input buffer only F0AA LDX #&08 ;else load highest buffer number (8) F0AC CLI ;allow interrupts F0AD SEI ;briefly! F0AE JSR &F0B4 ;flush buffer F0B1 DEX ;decrement X to point at next buffer F0B2 BPL &F0AC ;if X>=0 flush next buffer ;at this point X=255 ************************************************************************* * * * OSBYTE 21 FLUSH SPECIFIC BUFFER * * * ************************************************************************* ;on entry X=buffer number F0B4 CPX #&09 ;is X<9? F0B6 BCC &F098 ;if so flush buffer or else F0B8 RTS ;exit ************************************************************************* * * * Issue *HELP to ROMS * * * ************************************************************************* F0B9 LDX #&09 ; F0BB JSR &F168 ;send service call 9 to ROMs F0BE JSR &FA4A ;print inline message, corrupting &B8/9, assumes Y<>0 F0C1 DB &0D ;carriage return F0C2 DS 'OS 1.20' ;help message F0C9 DB &0D ;carriage return F0CA BRK ; F0CB RTS ; ************************************************************************* * * * OSBYTE 122 KEYBOARD SCAN FROM &10 (16) * * * ************************************************************************* F0CC CLC ; Clear carry to bypass KEYV and use supplied Y as we ; ; are calling direct from keyboard handler itself F0CD LDX #&10 ; Set X to scan from &10, skipping modifier keys ************************************************************************* * * * OSBYTE 121 KEYBOARD SCAN FROM VALUE IN X * * * ************************************************************************* F0CF BCS &F068 ; If carry set from OSBYTE entry, vector via KEYV ; And thence back to: ************************************************************************* * Scan Keyboard C=1, V=0 entry via KEYV * * X=&00-&7F scan range, X=&80-&FF scan for single keypress * ************************************************************************* F0D1 TXA ;if X is +ve goto F0D9 F0D2 BPL &F0D9 ;&00-&7F, scan for single keypress (INKEY-129 to -256) F0D4 JSR &F02A ;else interrogate keyboard, scan for single keypress F0D7 BCS &F12E ;if carry set from entry, jump to F12E to exit F0D9 PHP ;push flags F0DA BCC &F0DE ;if carry clear, Y already set, skip to LF0DE F0DC LDY #&EE ;set Y so next operation saves to &02CD F0DE STA &01DF,Y ;Store keypress number in &02CB, &02CC or &02CD F0E1 LDX #&09 ;Start with column 9 in X F0E3 JSR &F129 ;select auto scan F0E6 LDA #&7F ;set port A for input on bit 7 others outputs F0E8 STA &FE43 ; F0EB LDA #&03 ;stop auto scan F0ED STA &FE40 ; F0F0 LDA #&0F ;select non-existent keyboard column F (only 0-9 have keys) F0F2 STA &FE4F ; F0F5 LDA #&01 ;cancel keyboard interrupt F0F7 STA &FE4D ; F0FA STX &FE4F ;select column X (9 max) F0FD BIT &FE4D ;if bit 1 =0 there is no keyboard interrupt so F100 BEQ &F123 ;goto F123 F102 TXA ;else put column address in A F103 CMP &01DF,Y ;compare with 1DF+Y F106 BCC &F11E ;if less then F11E F108 STA &FE4F ;else select column again F10B BIT &FE4F ;and if bit 7 is 0 F10E BPL &F11E ;then F11E F110 PLP ;else push and pull flags F111 PHP ; F112 BCS &F127 ;and if carry set goto F127 F114 PHA ;else Push A F115 EOR &0000,Y ;EOR with EC,ED, or EE depending on Y value F118 ASL ;shift left F119 CMP #&01 ;set carry if = or greater than number holds EC,ED,EE F11B PLA ;get back A F11C BCS &F127 ;if carry set F127 F11E CLC ;else clear carry F11F ADC #&10 ;add 16 F121 BPL &F103 ;and do it again if 0=