home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
mbug
/
mbug097.arc
/
BKBD6545.MAC
< prev
next >
Wrap
Text File
|
1979-12-31
|
8KB
|
430 lines
;
; Keyboard scanner for standard MicroBee keyboard.
;
; Modifications for function keys, window key,
; key click, etc. by Peter Broughton.
;
; Last mod. : 1st Jan., 1988
;
; Function keys:
fn_key_1 equ 81h ; value returned by scn_in
fn_str_end equ 0FFh ; end function char
fn_str_pause equ 0FEh ; pause char
window_char equ 0A0h ; value returned by scn_in to get window
window_key equ '9' ; <CTRL> + this key = window
user_char equ 0A1h ; value returned by scn_in to get user program
user_key_1 equ ')' ; <CTRL> + this key = user program call
user_key_2 equ '?' ; ditto... due to ghosting
rom_port equ 11
;
; language options ..
ENGLISH equ 1 ;=1 if english version
DANISH equ 0 ;=1 if danish version
SWEDISH equ 0 ;=1 if swedish version
;
; PIO B bits of interest
BEEP_BIT equ 6
SER_OUT equ 5 ;serial comm. lines
SER_IN equ 4
SER_CTS equ 3 ;printer busy line= clear to send
SER_DTR equ 2 ;DTR output
CASS_OUT equ 1
CASS_IN equ 0 ;cassette bits
;
; the following two are 100Hz multiples (CPU speed independent)
REPT_START equ 100 ;gives 1 second repeat delay
RP_SPEED equ 10 ;gives 10 Hz repeat rate
;
; 6545 register definitions
H_LPEN equ 16
L_LPEN equ 17
H_UPDATE equ 18
L_UPDATE equ 19
DUMMY equ 31
; status bit definitions
RETRACE equ 5
LPEN_FULL equ 6
UPDATE_RDY equ 7
; keyboard row/ column codes
row_val equ 8 ;keyboard no. elements/ column
shift_code equ 7*row_val+7 ;shift key
ctrl_code equ 7*row_val+1 ;control key
; scan normal MicroBee keyboard, return
; Z and char in A
; or NZ if no chars available
scn_in:
push bc
push de
push hl
ld a,(key_down)
cp -1
jr z,none_down
; must wait for previous key to be released (and debounce)
ld b,150 ;75 ;more for new keyboards (and at high Mhz)
debounce:
call is_closed
jr z,try_rept ;try repeat delay
djnz debounce
ld a,-1
ld (key_down),a ;it is now up
jp none_1 ;--- So ZTREK works !!
try_rept:
ld hl,rept_flip
in a,(crtc)
and 1 shl retrace
cp (hl)
jp z,bad_exit ;hasn't changed yet
ld (hl),a ;note the change
ld hl,(rept_count)
dec hl
ld (rept_count),hl
ld a,h
or l
jp nz,bad_exit
; 10 Hz repeat delay
ld hl,rp_speed
ld (rept_count),hl
ld a,(last_ascii)
jp ascii_ret ;return last key pressed
; is there anything pressed at all ?
none_down:
in a,(crtc)
bit lpen_full,a
jp z,bad_exit ;.. not here wasn't
; scan all keys to find main key ..
none_1:
ld a,1
out (rom_port),a ;disable DISEN address
ld a,l_lpen
out (crtc),a
in a,(crtc+1) ;reset lpen full
ld c,crtc ;address register
ld de,dummy*256+l_update
ld hl,0370H ;address of last key on keyboard
scn_1:
ld a,h_update
out (crtc),a
ld a,h
out (crtc+1),a
ld a,l
push hl
ld h,010H ;value to subtract from a
call scan_q ;very fast 16 key scanner
pop hl
ld l,a
; hl=update regs
jr nz,scn_2 ;got a new key
dec h
jp p,scn_1
ld b,7
ld a,38h
check_c_keys:
call is_closed
jr z,new_key
inc a
cp 39h ; avoid the control key
jr nz,c_ck1
inc a
dec b
c_ck1:
djnz check_c_keys
jp bad_exit
; convert hl to key_code ...
scn_2:
add hl,hl
add hl,hl
add hl,hl
add hl,hl
ld a,h
and 03Fh
new_key:
cp 39h
jp z,bad_exit
ld (key_down),a ;must be released next time
; ensure that repeat count starts from correct level for 1 second
ld hl,rept_start
ld (rept_count),hl
; now convert it to good old ascii ..
cond 1-english
ld hl,conv_tab
ld b,kbc_length
cmp_kb:
cp (hl)
inc hl
ld a,(hl)
jr z,asciify
inc hl
ld a,(key_down)
djnz cmp_kb
endc
; is it an alphabetical key ?
asciify:
cp row_val*4
jr c,alpha_key
; it is a numeric/ punctuation key
cp row_val*6
jr c,numer_key
; is it a special key ?
cp row_val*7
jr c,spec_key
jp curs_key
; handle alphabetical keys
alpha_key:
call is_ctrl
jp z,ascii_ret ;code is correct for control
add a,'a'-1
cp '`'
jr z,strange ;special case for at @
cond 1-english
cp '}'+1 ;include extra 3 letters
endc
cond english
cp 'z'+1
endc
jr c,letters
strange:
cp 07FH
jr z,no_al_rev ;delete shifted = underline
res 5,a ;for open sq},]},\|,^~
jr no_al_rev
; check alpha reverse byte
letters:
ld b,a
ld a,(al_rev)
or a
ld a,b
jr z,no_al_rev
xor 1 shl 5
no_al_rev:
call is_shift
jr nz,ascii_ret
xor 1 shl 5
jr ascii_ret
; handle 0-9 and :/* ;/+ and also ,< -= .> /?
numer_key:
cp row_val*5+4
jr c,num_1
set 4,a
num_1:
cp row_val*4 ;a zero
jr z,zero_fix ;if so, don't shift to space
call is_shift
jr z,ascii_ret ;shifted code is correct
zero_fix:
xor 1 shl 4
jr ascii_ret
; handle special keys e.g. cr,lf,brk,lock
spec_key:
ld hl,spec_tab-row_val*6
ld c,a
ld b,0
add hl,bc
ld a,(hl)
or a
jr nz,ascii_ret
; it is the lock key
ld hl,0
ld (rept_count),hl ;very slow
ld hl,al_rev
ld a,1
xor (hl)
ld (hl),a
call do_click
jr bad_exit
; handle premium cursor control keys
; must return value 90h..97h, or 98h..9Fh for shifted key
curs_key:
add a,90h-7*8
ld b,a
call is_shift
ld a,b
jr nz,ascii_ret
add a,8
;
ascii_ret:
; now check for fn keys, etc.
cp 'A'
jr nc,a_r_1 ; Alpha key etc. can't be
ld c,window_char-window_key ; conversion value
cp window_key ; window ?
jr z,convert_code
ld c,user_char-user_key_1
cp user_key_1 ; user 1 ?
jr z,convert_code
ld c,user_char-user_key_2
cp user_key_2 ; user 2 ?
jr z,convert_code
ld c,fn_key_1-'1'
cp '8'+1 ; function key ?
jr nc,a_r_1
cp '1'
jr nc,convert_code
a_r_2:
ld c,fn_key_1+8-'"'
cp '"'
jr c,a_r_1
cp '&'
jr nc,a_r_1
convert_code:
ld b,a ; but only if control is pressed
call is_ctrl
ld a,b
jr nz,a_r_1
add a,c
a_r_1:
call do_click
cp a ;set z flag -> got a key
ld (last_ascii),a ;for repeating purposes
bad1_ret:
push af
ld a,h_lpen ; reset strobe
out (crtc),a
in a,(crtc+1)
xor a ;allow scanning LPENS
out (rom_port),a
pop af
pop hl
pop de
pop bc
ret
bad_exit:
or -1 ;clear z flag (nz exit)
jr bad1_ret ;-> did not get a new key
; DANISH/SWEDISH
; keyboard lookup table ...
cond danish
conv_tab:
db 40+3,24+3
db 0+0,24+4
db 24+3,24+5
db 24+4,40+3
db 24+5,0+0
kbc_length equ 5
endc
cond swedish
conv_tab:
db 40+3,24+4
db 0+0,24+3
db 24+3,24+5
db 24+4,40+3
db 24+5,0+0
kbc_length equ 5
endc
; very fast keyboard scanner for 16 keys at once
scan_q:
out (c),e
out (crtc+1),a
out (c),d
out (crtc+1),a
scan1_q:
in b,(c)
jp p,scan1_q
in b,(c)
bit lpen_full,b
ret nz
sub h
jp nc,scan_q
cp a
ret
is_shift:
push bc
ld b,shift_code
jr close_1
; is the control key being held down ?
is_ctrl:
push bc
ld b,ctrl_code
jr close_1
; return z if key specified in a is closed, else nz
is_closed:
; Make sure key is within range
cp 40h
jr nc,key_too_big
push bc
ld b,a ;save test key-code
close_1:
ld c,a ;save acc.
ld a,h_update
out (crtc),a ;select update high byte
ld a,b
rrca
rrca
rrca
rrca
ld b,a
out (crtc+1),a ;to update high
ld a,l_update
out (crtc),a ;select update lower
ld a,b
out (crtc+1),a ;to update lower byte
ld a,1 ;disallow scan lpens
out (rom_port),a
ld a,h_lpen ;select light pen high byte
out (crtc),a ;reset lpen full strobe
in a,(crtc+1)
ld a,dummy
out (crtc),a ;select dummy register
out (crtc+1),a ;and write to it
; now wait for update to be done ..
updte:
in a,(crtc)
bit update_rdy,a
jr z,updte
; was there a lpen strobe generated ?
in a,(crtc)
cpl
ld b,a ;save 6545 status
xor a
out (rom_port),a ;allow refresh scan
ld a,h_lpen
out (crtc),a
in a,(crtc+1) ;reset lpen strobe
bit lpen_full,b
ld a,c ;restore acc.
pop bc ;restore bc
ret
; Key code not in range so return NZ
key_too_big:
or a
ret
spec_tab:
db 01Bh,08h,09h ;esc,bs,tab
db 0Ah,0Dh,0 ;lf,cr,lock
db 'X'-40h,020h ;break -> ctl X,space
key_down: ds 1 ;records key presently down or -1
rept_count: ds 2 ;counts down to give repeat delay