home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
mbug
/
mbug097.arc
/
BIOS.MAC
< prev
next >
Wrap
Text File
|
1979-12-31
|
7KB
|
413 lines
;
;
; Header to assemble BIOS keyboard driver file : KEYBOARD.SYS
; (or KBDSTAND.SYS, KBDINT.SYS, KBDEXT.SYS)
;
; Also contains some status line stuff
;
; Written by Peter Broughton.
;
; 1st Dec., 1987
;
; keyboard driver, select the appropriate file
keyboard_driver macro
; include BKBD3870.MAC
include BKBD6545.MAC
endm
true equ -1
false equ not true
; start of keyboard driver in system page
keyboard_start equ 5800h
bios_start equ 0E700h
piob_ctrl equ 3
piob_data equ 2
crtc equ 0Ch
col_port equ 8
window_char equ 0A0h
user_char equ 0A1h
; locations within BIOS
col_mode equ bios_start+129h
al_rev equ bios_start+27Bh+17
click_length equ bios_start+223h
click_tone equ bios_start+224h
fn_active equ bios_start+220h
speed_port equ 9 ; Port to change CPU speed
speed_bit equ 2 ; Bit to do this
fast_cpu equ 0E98Dh ; Flag for fast speed
aseg
org 100h
; usual .SYS header
dw 8000h ; lowest BIOS start ???
dw keyboard_start ; where this file loads to
dw end_marker-keyboard_start ; length of this file
ds 180h-$,0 ; must fill one record
; leave space in system page for flags and BDOS
.phase keyboard_start
; must start with jumps to scn_in and is_closed routines, etc.
jp scn_in
jp is_closed
jp print_s_line
jp set_up_s_line
keyboard_driver
; Key click routine for either keyboard.
;
do_click:
push af
ld a,(click_length)
or a
jr z,no_click
ld b,a
ld a,(fast_cpu) ; 'Halve' bit time if 3.375 MHz
or a
ld a,(click_tone)
jr nz,not_fast
srl a ; Divide by 2
not_fast:
ld d,a
in a,(2)
ld e,a
click_loop:
ld c,d
xor 40h
out (2),a
tone_loop:
ld a,a
ld a,a
ld a,a
ld a,a
dec c
jr nz,tone_loop
djnz click_loop
ld a,e
out (2),a
no_click:
pop af
ret
; Status line routines
vdu equ 8000h
s_line equ 0E700h+58 ;active flag (=25 for on)
sl_table equ 0E700h+2CBh ;pointer to info for line
no_clock equ 0E700h+28Eh ;no clock fitted (unitialised)
sl_msgs equ 0E700h+2CDh ;pointer to messages
get_rtc_addr equ 0E700h+27Dh ;address of rtc routine
; status line positions
status_start equ vdu+(24*80)+2
pjb_sl equ status_start+2
fast_sl equ status_start+16 ; 'fast' message
swap_a_m_sl equ status_start+28 ; pos of 'A<>M' message
lock_sl equ status_start+34 ; pos of lock message
fn_sl equ status_start+43 ; 'fn key' message
fn_on_sl equ status_start+40 ; 'fn active'
clock_sl equ status_start+52 ; pos of time on status line
num_sl_msgs equ 5 ; number of messages on status line
sl_pjb_mes:
db -'(',-'c',-')',-' ',-'P',-'J',-'B'
len_sl_pjb_mes equ $-sl_pjb_mes
; update status line
; must push all but AF and HL
print_s_line:
push bc
push de
push ix
push iy
ld b,num_sl_msgs
ld ix,(sl_table)
ld iy,old_sl_vals
p_sl_loop:
push bc
ld b,0
ld h,(ix+1)
ld l,(ix+0)
ld a,(hl) ; new val
cp (iy) ; old val
jr z,p_sl1 ; no change so goto next one
ld (iy),a ; else update old val
ld hl,null_mes
or a
jr z,p_sl3
ld hl,(sl_msgs)
ld c,(ix+2) ; offset of message
add hl,bc ; points to message
p_sl3:
ld a,(status_start)
cp '['
jp nz,p_sl2 ; no status line so NO printing
ex de,hl
ld hl,status_start
ld c,(ix+3) ; offset on status line
add hl,bc
ex de,hl
ld c,(ix+4) ; length of msg
ldir
p_sl1:
ld c,5
add ix,bc
inc iy
pop bc
djnz p_sl_loop
; clock now, but is it there
ld a,(no_clock)
or a
jr nz,p_sl6 ; wasn't there - make sure no display occurs
ld hl,time_spot
ld e,0 ; read from reg 0
ld b,10 ; 10 regs
call_rtc:
call 0
; update 'old' time and check for change
ld hl,time_spot_o
ld de,time_spot
ld bc,10 shl 8 ; b - counter, c - change flag
p_sl4:
ld a,(de)
cp (hl)
jr z,p_sl5
ld c,true
p_sl5:
ld (hl),a
inc hl
inc de
djnz p_sl4
bit 7,c
jr z,p_sl6
ld a,(status_start)
cp '['
jr nz,p_sl6
; now display it
ld ix,time_spot
ld hl,clock_sl
ld a,(ix+4) ; hours
ld b,'A' ; AM
cp 12h
jr c,dt_1
sub 12h ; Actually PM
daa
ld b,'P'
dt_1:
or a
jr nz,dt_2
ld a,12h ; 12 o'clock
dt_2:
ld c,' ' ; blank leading zero
cp 10h
jr c,dt_3
ld c,'1'
sub 10h
dt_3:
ld (hl),c
inc hl
add a,'0'
ld (hl),a
inc hl
inc hl
ld a,(ix+5) ; min
call print_bcd
inc hl
ld a,(ix+6) ; sec
call print_bcd
inc hl
ld (hl),b ; A/P
inc hl
inc hl
inc hl
inc hl
ld a,(ix+2) ; date
call print_bcd
inc hl
ld a,(ix+1) ; month
call print_bcd
inc hl
ld a,(ix+0) ; year
call print_bcd
p_sl6:
pop iy
pop ix
pop de
pop bc
ret
p_sl2:
pop bc
jr p_sl6
; print bcd num in a to (hl)
print_bcd:
ld e,a
rra
rra
rra
rra
and 0Fh
add a,'0'
ld (hl),a
inc hl
ld a,e
and 0Fh
add a,'0'
ld (hl),a
inc hl
ret
; clear and set up status line
set_up_s_line:
ld hl,(get_rtc_addr)
ld (call_rtc+1),hl
; Must clear status line if it is being used
; Actually assume it is being used to allow compatability with window's
; status line on/off function.
; ld a,(s_line)
; cp 24
; ret z
ld hl,status_start-2
ld b,80
su_sl_1:
ld (hl),' '
inc hl
djnz su_sl_1
ld a,'['
ld (status_start),a
ld a,']'
ld (status_start+75),a
ld hl,sl_pjb_mes
ld de,status_start+2
ld b,len_sl_pjb_mes
sl_l_n:
ld a,(hl)
neg
ld (de),a
inc hl
inc de
djnz sl_l_n
; if not telecomputer
; is the real time clock fitted
ld c,7
ld a,14
out (4),a
in b,(c)
ld a,14
out (4),a
ld a,85
out (6),a
ld a,14
out (4),a
in d,(c)
ld a,14
out (4),a
ld a,b
out (6),a
ld a,d
sub 85
; else
; telecomputer must have clock
; xor a
; endif
ld (no_clock),a ; nz if no rtc present
push af
; fill 'old' status values with impossible code so update occurs immediately
ld hl,time_spot_o ; make sure full status line is printed
ld b,num_old_vals
s_sl1:
ld (hl),55h
inc hl
djnz s_sl1
call print_s_line
pop af
; if no then don't print ':' & '/'
ret nz
ld a,':'
ld (clock_sl+2),a
ld (clock_sl+5),a
ld a,'M'
ld (clock_sl+10),a
ld a,'/'
ld (clock_sl+15),a
ld (clock_sl+18),a
ret
; 'previous' values for status line flags
; do not alter their relative positions
time_spot_o: ds 10,55h
in_fnstr_o: db 55h
al_rev_o: db 55h
fn_active_o: db 55h
swap_a_m_o: db 55h
fast_o: db 55h
num_old_vals equ $-time_spot_o ; number of bytes
old_sl_vals equ in_fnstr_o ; start of above table
null_mes:
db ' '
time_spot:
ds 10 ;10 bytes for time
last_ascii: db 0FFh
rept_flip: ds 1
end_marker equ $
if $ ge 5E00h
error probably ran past window start
diff equ $-keyboard_start+zero
endif
.dephase
end