; KeyStreamsA.asm -- Interrupt driven keyboard handler ; companion file is KeyStreamsB.bcpl ; Copyright Xerox Corporation 1979 ; Last modified March 15, 1979 4:36 PM by Boggs .titl KBHan ; outgoing .ent kbInterrupt ; Interrupt routine .bext CursorLink ; non zero => link the mouse to the cursor .bext kbInterruptReMask .bext kbUserProc .bext kbUserProcStack .bext kbTable ; incoming .bext OsBuffer StkMin = 335 .srel kbInterrupt: .kbInterrupt kbInterruptReMask: 0 CursorLink: -1 ; non zero => link mouse to cursor kbUserProc: 0 ; address of user procedure kbUserProcStack: 0 ; stack for same (non-zero => use proc) kbTable: Transition .nrel mouseX: 424 ; address of mouse x coord mouseY: 425 ; address of mouse y coord cursorX: 426 ; address of cursor x coord cursorY: 427 ; address of cursor y coord XMax: 606.-16. ; maximum X value for mouse YMax: 808.-16. ; maximum Y value for mouse IMASK: kbInterruptReMask .CursorLink: CursorLink kbPC: 0 ; interrupted program's state kbCry: 0 kbAC0: 0 kbAC1: 0 kbAC2: 0 kbAC3: 0 kbActive: 0 .Active: 453 .IntPC: 500 ;---------------------------------------------------------------------------- .kbInterrupt: ; 16.666 ms vertical field interrupt ;---------------------------------------------------------------------------- sta 0 kbAC0 sta 1 kbAC1 sta 2 kbAC2 sta 3 kbAC3 movr 3 3 sta 3 kbCry lda 0 @.IntPC sta 0 kbPC ; save interrupt PC lda 0 @.Active lda 1 @IMASK ; save old active and mask out lower and 0 1 ; priority interrupts while we run. sta 1 @.Active sta 0 kbActive eir ; Update the cursor from the mouse unless CursorLink is 0. lda 0 @.CursorLink snz 0 0 jmp FL0 ; don't update coordinates lda 0 @mouseX ; if mouseX < 0 then mouseX = 0 sp 0 0 mkzero 0 0 lda 1 XMax ; if mouseX > XMax then mouseX = XMax subz# 0 1 snc mov 1 0 sta 0 @cursorX ; store X coordinate for cursor sta 0 @mouseX ; keep mouse incremental modulo screen limits sta 0 userX lda 0 @mouseY ; if mouseY < 0 then mouseY = 0 sp 0 0 mkzero 0 0 lda 1 YMax ; if mouseY > YMax then mouseY = YMax subz# 0 1 snc mov 1 0 sta 0 @cursorY ; store Y coordinate for cursor sta 0 @mouseY ; keep mouse incremental modulo screen limits sta 0 userY ; Now begin keyboard processing FL0: jsr P ; locate ourselves P: lda 2 CM5 ; count of times to go through loop lop: lda 0 @Addrs+4-P,3 ; get keys bits com 0 0 ; 1's imply keys down lda 1 Masks+4-P,3 ; ignore some bits and 1 0 lda 1 State+4-P,3 ; and current view of down keys se 0 1 ; see if they differ jmp dif ; yes neg 3 3 ; move 3 down one com 3 3 inc 2 2 szr ; go around loop 5 times jmp lop jmp NoTrans ; no differences difadr: .blk 1 CM5: -5 ; -------------------- K E Y B O A R D T A B L E -------------------------- ; The format of kbTab through userY is published in SysDefs.d kbTab: jsr 0,3 ; return address Transition: .blk 1 ; transition index + #100000 if going down, ; or #40000 if coming up State: .blk 5 ; 5 words of current keys state userX: .blk 1 ; cursor coordinates userY: .blk 1 Addrs: 177034 ; addresses of keyboard words 177035 kbdAd2: 177036 kbdAd3: 177037 177030 ; keyset and mouse. Masks: 177777 ; 0 => ignore transition for this key 177777 177777 177777 377 downind: 100000 upind: 40000 Dismiss:dir lda 0 kbPC sta 0 @.IntPC lda 0 kbActive sta 0 @.Active lda 0 kbAC0 lda 1 kbAC1 lda 2 kbAC2 lda 3 kbCry movl 3 3 lda 3 kbAC3 bri dif: sta 3 difadr ; remember where we found difference com 2 2 ; neg and then sub 1 (now range 0 to 4) addzl 2 2 ; multiply by 16 addzl 2 2 mov 0 3 ; 1 = old bits; 0 = new bits andzl 1 3 ; xor function: 0 ← 1 xor 0 add 1 0 sub 3 0 subz 3 3 skp ; 0 has 1's where transitions lop2: inc 2 2 ; bump bit index movr 3 3 ; assemble a bit to match movl 0 0 snc ; check for changed bit jmp lop2 ; not found yet ; AC3 = bit that changed ; AC2 = index of bit that changed ; AC1 = old bits (still) 1's = down keys lda 0 downind ; down indicator for transition and# 3 1 szr ; check which way key went sub 3 1 skp ; up - turn off bit add 3 1 skp ; down - turn on bit lda 0 upind ; up - up indicator add 0 2 ; add indication to transition index adc 0 0 ; for return test below lda 3 difadr sta 1 State+4-P,3 ; save new down bits NoTrans: sta 2 Transition ; save transition indication lda 2 @.UserProcStack snz 2 2 jmp irecord ; no procedure -- I record it. lda 0 StkMin ; save bottom of stack word sta 0 StkMinSav mkzero 0 0 sta 0 StkMin jsr kbTab ; get table address mov 3 0 lda 3 @.UserProc jsr 0,3 ; go call him. ac0 => table 1 lda 1 StkMinSav sta 1 StkMin irecord:lda 1 Transition movzl 1 1 szc ; if no down transition snz 0 0 ; or if user returned false, jmp Dismiss ; nothing more to do jsr .+1 Q: movzr 1 1 ; get index back again (sans down bit) add 1 3 ; Get directive about what to do. ; Left byte has shift value; right unshifted value. ; Bit 0 is on if it's a letter. lda 0 .kbTransitionTable-Q,3 snz 0 0 jmp Dismiss ; not a key OS cares about! lda 1 @kbdAd3 lda 2 c200 ; <Lock> and 1 2 szr jmp Shift ; not locked -- check shift movl# 0 0 szc ; send shifted character if it's a letter jmp SendSh Shift: lda 2 c10 ; <Right-Shift> and 1 2 snr jmp SendSh lda 1 @kbdAd2 lda 2 c100 ; <Left-Shift> and 1 2 snr SendSh: movs 0 0 ; send character shifted lda 3 c177 and 3 0 lda 1 @kbdAd2 lda 2 c4000 ; <Control> lda 3 c37 ; control character (0-37B) and 1 2 snr and 3 0 sta 0 char ; save for a moment lda 3 @.OsBuffer ; get pointer to buffer control lda 2 2,3 ; "in" pointer inc 2 1 ; 1 = newIn lda 0 1,3 ; last sne 1 0 lda 1 0,3 ; first lda 0 3,3 ; out sne 1 0 jmp Dismiss ; buffer full lda 0 char sta 0 0,2 ; store item sta 1 2,3 ; new "in" pointer jmp Dismiss .OsBuffer: OsBuffer .UserProc: kbUserProc .UserProcStack: kbUserProcStack StkMinSav: .blk 1 char: .blk 1 c4000: 4000 ; <Control> c200: 200 ; <Lock> c177: 177 c100: 100 ; <Left-Shift> c37: 37 c10: 10 ; <Right-Shift> ;Tables for char code conversion .ent kbTransitionTable .srel kbTransitionTable: .kbTransitionTable .nrel ; structure KBKEY: // in SysDefs.d ; [ ; Letter bit // True if char is a letter (use for lock interp) ; ShiftCode bit 7 // Code to use if shift is on ; NormCode bit 8 // Code to use otherwise ; ] .kbTransitionTable: 45B7+65 ; % 5 177034 44B7+64 ; $ 4 176B7+66 ; ~ 6 1B0+105B7+145 ; E e 46B7+67 ; & 7 1B0+104B7+144 ; D d 1B0+125B7+165 ; U u 1B0+126B7+166 ; V v 51B7+60 ; ) 0 1B0+113B7+153 ; K k 30B7+55 ; ` - 1B0+120B7+160 ; P p 77B7+57 ; ? / 174B7+134 ; | \ 140B7+12 ; ACCENT GRAVE LF 10B7+10 ; BS 43B7+63 ; # 3 177035 100B7+62 ; @ 2 1B0+127B7+167 ; W w 1B0+121B7+161 ; Q q 1B0+123B7+163 ; S s 1B0+101B7+141 ; A a 50B7+71 ; ( 9 1B0+111B7+151 ; I i 1B0+130B7+170 ; X x 1B0+117B7+157 ; O o 1B0+114B7+154 ; L l 74B7+54 ; < , 42B7+47 ; " ' 175B7+135 ; } ] 0 ; blank-middle or FR4 0 ; blank-top or BW 41B7+61 ; ! 1 177036 33B7+33 ; ESCAPE 11B7+11 ; TAB 1B0+106B7+146 ; F f 0 ; CONTROL 1B0+103B7+143 ; C c 1B0+112B7+152 ; J j 1B0+102B7+142 ; B b 1B0+132B7+172 ; Z z 0 ; SHIFT 76B7+56 ; > . 72B7+73 ; : ; 15B7+15 ; CR 136B7+137 ; ↑ ← 177B7+177 ; DEL (FL1) 0 ; FL3 1B0+122B7+162 ; R r 177037 1B0+124B7+164 ; T t 1B0+107B7+147 ; G g 1B0+131B7+171 ; Y y 1B0+110B7+150 ; H h 52B7+70 ; * 8 1B0+116B7+156 ; N n 1B0+115B7+155 ; M m 0 ; LOCK 40B7+40 ; SPACE 173B7+133 ; { [ 53B7+75 ; += 0 ; SHIFT 0 ; blank-bottom or FR1 0 ; FL4 0 ; FR5 .blk 16. ; zeroes for keyset keys .END