IDEAL

MODEL SMALL
RADIX	16

P286
include "tos.inc"

; ------------------------------------------
; Модуль обслуживания клавиатуры
; ------------------------------------------

PUBLIC	_Keyb_int, _Int_30h_Entry, _key_code, _keyb_status
EXTRN	_beep:PROC
DATASEG

	_key_flag 	db	0
	_key_code 	dw	0
	ext_scan	db	0
	_keyb_status	dw	0

CODESEG

PROC	_Keyb_int	 NEAR
	cli

	call	_beep

	push	ax
	mov	al, [ext_scan]
	cmp	al, 0
	jz	normal_scan1
	cmp	al, 0e1h
	jz	pause_key

	in	al, 60h
	cmp	al, 2ah
	jz	intkeyb_exit_1
	cmp	al, 0aah
	jz	intkeyb_exit_1

	mov	ah, [ext_scan]
	call	Keyb_PutQ

	mov	al, 0
	mov	[ext_scan], al
	jmp	intkeyb_exit

pause_key:

	in	al, 60h
	cmp	al, 0c5h
	jz	pause_key1
	cmp	al, 45h
	jz	pause_key1

	jmp	intkeyb_exit

pause_key1:
	mov	ah, [ext_scan]
	call	Keyb_PutQ

	mov	al, 0
	mov	[ext_scan], al
	jmp	intkeyb_exit


normal_scan1:
	in	al, 60h
	cmp	al, 0feh
	jz	intkeyb_exit
	cmp	al, 0e1h
	jz	ext_key
	cmp	al, 0e0h
	jnz	normal_scan

ext_key:
	mov	[ext_scan], al
	jmp	intkeyb_exit


intkeyb_exit_1:
	mov	al, 0
	mov	[ext_scan], al
	jmp	intkeyb_exit

normal_scan:
	mov	ah, 0
	call	Keyb_PutQ

intkeyb_exit:
	in	al, 61h
	mov	ah, al
	or	al, 80h
	out	61h, al
	xchg	ah, al
	out	61h, al
	mov	al,EOI
	out	MASTER8259A,al

	pop	ax
	sti
	iret
	jmp	_Keyb_int
ENDP	_Keyb_int


PROC	Keyb_PutQ	NEAR

	push	ax

	cmp	ax, 002ah	; L_SHIFT down
	jnz	@@kb1
	mov	ax, [_keyb_status]
	or	ax, L_SHIFT
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb1:
	cmp	ax, 00aah	; L_SHIFT up
	jnz	@@kb2
	mov	ax, [_keyb_status]
	and	ax, NL_SHIFT
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb2:
	cmp	ax, 0036h	; R_SHIFT down
	jnz	@@kb3
	mov	ax, [_keyb_status]
	or	ax, R_SHIFT
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb3:
	cmp	ax, 00b6h	; R_SHIFT up
	jnz	@@kb4
	mov	ax, [_keyb_status]
	and	ax, NR_SHIFT
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb4:
	cmp	ax, 001dh	; L_CTRL down
	jnz	@@kb5
	mov	ax, [_keyb_status]
	or	ax, L_CTRL
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb5:
	cmp	ax, 009dh	; L_CTRL up
	jnz	@@kb6
	mov	ax, [_keyb_status]
	and	ax, NL_CTRL
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb6:
	cmp	ax, 0e01dh	; R_CTRL down
	jnz	@@kb7
	mov	ax, [_keyb_status]
	or	ax, R_CTRL
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb7:
	cmp	ax, 0e09dh	; R_CTRL up
	jnz	@@kb8
	mov	ax, [_keyb_status]
	and	ax, NR_CTRL
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb8:
	cmp	ax, 0038h	; L_ALT down
	jnz	@@kb9
	mov	ax, [_keyb_status]
	or	ax, L_ALT
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb9:
	cmp	ax, 00b8h	; L_ALT up
	jnz	@@kb10
	mov	ax, [_keyb_status]
	and	ax, NL_ALT
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb10:
	cmp	ax, 0e038h	; R_ALT down
	jnz	@@kb11
	mov	ax, [_keyb_status]
	or	ax, R_ALT
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb11:
	cmp	ax, 0e0b8h	; R_ALT up
	jnz	@@kb12
	mov	ax, [_keyb_status]
	and	ax, NR_ALT
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb12:
	cmp	ax, 003ah	; CAPS_LOCK up
	jnz	@@kb13
	mov	ax, [_keyb_status]
	xor	ax, CAPS_LOCK
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb13:
	cmp	ax, 00bah	; CAPS_LOCK down
	jnz	@@kb14
	jmp	keyb_putq_exit
@@kb14:
	cmp	ax, 0046h	; SCR_LOCK up
	jnz	@@kb15
	mov	ax, [_keyb_status]
	xor	ax, SCR_LOCK
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb15:
	cmp	ax, 00c6h	; SCR_LOCK down
	jnz	@@kb16
	jmp	keyb_putq_exit
@@kb16:
	cmp	ax, 0045h	; NUM_LOCK up
	jnz	@@kb17
	mov	ax, [_keyb_status]
	xor	ax, NUM_LOCK
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb17:
	cmp	ax, 00c5h	; NUM_LOCK down
	jnz	@@kb18
	jmp	keyb_putq_exit
@@kb18:
	cmp	ax, 0e052h	; INSERT up
	jnz	@@kb19
	mov	ax, [_keyb_status]
	xor	ax, INSERT
	mov	[_keyb_status], ax
	jmp	keyb_putq_exit
@@kb19:
	cmp	ax, 0e0d2h	; INSERT down
	jnz	@@kb20
	jmp	keyb_putq_exit
@@kb20:

	test	ax, 0080h
	jnz	keyb_putq_exit

	mov	[_key_code], ax

	mov	al, 0ffh
	mov	[_key_flag], al
keyb_putq_exit:
	pop	ax
	ret
ENDP	Keyb_PutQ

; Обработчик программного прерывания
; для ввода с клавиатуры. По своим функциям
; напоминает прерывание INT 16 реального
; режима.


PROC	_Int_30h_Entry	 NEAR
	push   ax dx

; Ожидаем прерывание от клавиатуры

keyb_int_wait:
	sti
	nop
	nop
	cli

; Проверяем флаг, который устанавливается
; обработчиком аппаратного прерывания клавиатуры

	mov	al, [_key_flag]
	cmp	al, 0
	jz	keyb_int_wait

; Сбрасываем флаг после прихода прерывания

	mov	al, 0
	mov	[_key_flag], al
	sti
	pop	dx ax
	iret
ENDP   _Int_30h_Entry

END