;---------------------------------------------------------------------------- 
;  24.10.88   Батьковский  М.Б. 
;---------------------------------------------------------------------------- 
;  29.10.88 - проверка повторного вхождения 
;  14.02.89 - дополнительные скан_коды (начинаются на 0E0H:c8,cb,cd,d0) 
;---------------------------------------------------------------------------- 
; --  таблица клавиш для ИНТЕК ( по новому  ГОСТу ) 
;             бит 7 - признак необходимости инвертирования SHIFT 
;---------------------------------------------------------------------------- 
; ------------нет спецсимволов--- SHIFT1 ----SHIFT2-----позиция в матрице-- 
;                                                      ИНТЕК              ПОИСК 
LN_KEY1 DB        80H+09H,           04H,   80H+29H    ; 1/12       1      4/7 
        DB            34H,       80H+08H,   80H+33H    ; 4/1        2      2/9 
        DB        80H+0CH,       80H+09H,   80H+34H    ; 4/2        3      2/10 
        DB        80H+0AH,           0DH,       28H    ; 4/6        4  .   8/7 
        DB        80H+28H,       80H+05H,   80H+1AH    ; 4/10       5      8/11 
        DB            0CH,       80H+03H,   80H+03H    ; 5/4        6      8/1 
        DB        80H+0BH,       80H+02H,   80H+08H    ; 5/5        7      8/5 
        DB            35H,       80H+04H,   80H+07H    ; 5/9        8      8/12 
        DB        80H+27H,       80H+06H,   80H+1BH    ; 5/11       9      4/9 
        DB            33H,       80H+07H,       2BH    ; 5/12      10  .   4/10 
        DB        80H+06H,       80H+0BH,       1AH    ; 8/1       11  .   1/11 
        DB        80H+35H,       80H+0AH,   80H+2BH    ; 8/2       12      1/9 
        DB            27H,           05H,       29H    ; 8/10      12  .   2/5 
        DB            35H,           37H,       00     ; 8/11      14 
        DB        80H+02H,       80H+0DH,       1BH    ; 8/12      15  .   2/1 
 
 
;---------------------------------------------------------------------- 
;       опрос матрицы клавиатуры, формирование кода сканирования 
;       и запись скан - кода в порт 60H 
;----------------------------------------------------------------------- 
 
SCANINT PROC	NEAR 
 
        STI 
	PUSH	AX 
	PUSH	DS 
	MOV	AX,DATA 
	MOV	DS,AX 
;------ проверка состояния клавиатуры в целом 
 
	MOV	AL,0FFH	       ;выбор всех линий матрицы 
	OUT	LINE_SEL,AL 
	IN	AX,COL_READ	;чтение состояния колонок 
        OR      AH,0F0H         ;установка едениц в 4-ре старших бита 
        INC     AX              ;проверка на все еденицы (пусто) 
        JNZ     SC1            ;если не пусто 
;       новое состояние пусто  AX=0 
        MOV     LAST,AX         ;не прверять на повторение 
        CMP     AX,EMPTY        ; 
        JNZ      SC1 
SC0:    JMP      SC_RET1        ;если старое состояние "пусто" 
 
SC1: 
;--------   обработка клавиш, изменивших положение 
        ;   AX - новое интегральное состояние клавиатуры 
        ;        00     -    пусто 
        ;        другое - не пусто 
 
;------ проверка на повторное вхждение в прерывание 
        CMP     W_SCAN,TRUE 
        JZ      SC0 
        MOV     W_SCAN,TRUE       ; установка признака "работа" 
 
        PUSH    BX 
        PUSH    CX 
        PUSH    DX 
        PUSH    DI 
        PUSH    SI 
 
        MOV     EMPTY,AX        ; запись нового состояния клавиатуры 
 
        MOV     BX,offset KB_STAT ; адрес предидущего состояния клавиатуры 
        MOV     DI,offset LINE1+KB_KEY-1   ; адрес анализируемой клавиши 
        MOV     DL,KB_STAT_S          ; код для опроса линии 
 
        ;------------------- начало цикла SC2 / SC2E 
SC2:    MOV     AL,DL           ; установка линейного кода опроса линии 
        OUT     LINE_SEL,AL     ; опрос линии 
        IN      AX,COL_READ 
        OR      AH,0F0H 
        NOT     AX              ; перевод из инверсного кода 
        CMP     AX,[BX]         ; сравнение нового состояния со старым 
        JNZ     SC21            ; если состояния не совпали 
        ;------ состояние линии изменилось 
        SUB     DI,KB_L_KEY     ; переход к новой линии в табл скан кодов 
        JMP     SC2E 
        ;------ зафиксировано изменение состояние клавиши в линии 
 
        ;------ определение клавиш изменивших состояние 
        ;       проверка в цикле 
SC21: 
        MOV     SI,AX 
        XOR     SI,[BX]         ; SI содержит единицы в отличающихся битах 
        MOV     [BX],AX         ; запоминание текущего состояния линии 
        MOV     CX,KB_STAT_C    ; номер начальной колонки в линейном коде 
 
        ;       AX - новое состояние текущей линии 
        ;       BX - адрес линии в массиве KB_STAT 
        ;       CX - номер колонки 
        ;       DL - номер линии 
        ;       DI - адрес скан-кода проверяемой клавиши 
        ;       SI - содержит еденицы в битах изменившихся клавиш 
 
        ;------------------- начало цикла SC22 / SC22E 
 
SC22: 
        TEST    SI,CX            ; выделение колонки 
        JZ      SC22E            ; если колонки не отличаются 
        ;------- клавиши изменили свое сотояние 
        TEST    [BX],CX 
        JZ      SC222           ; новое состояние "пусто"? 
        ;-------- новая клавиша нажата 
        MOV     LAST,DI         ; номер нажатой клавиши 
        MOV     TIME,FIRST_TIME ; новая уставка времени ожидания 
        CALL    SEND_CODE       ; отработка  нажатой клавиш 
        JMP     SC22E 
        ;-------  новая клавиша отжата 
SC222:  CMP     DI,LAST 
        JNZ     SC2221          ; если отжата не повторяющаяся клавиша 
        MOV     LAST,0          ; сброс клавиши повторения 
SC2221: MOV     AL,CS:[DI]      ; получение скан кода клавиши 
        CMP     AL,SHIFT2_KEY+80H 
        JNZ     NO_SH2 
        ;SHIFT2 
        NOT     SHIFT2 
        NOT     RUSS 
NO_SH2: 
        MOV     AH,80H          ; признак отжатой клавиши 
        CALL    C_OUT60         ; вывод в 60 порт + INT9 
        ;----------------- конец цикла SC22/ SC22E 
SC22E: 
        DEC     DI               ; адрес нового скан-кода 
        SHR     CX,1             ; переход к следующей колонке 
        JNC     SC22 
 
SC2E:   ADD     BX,2            ; переход к следующей линии 
        SHR     DL,1            ; модификация линейного кода 
                                ;(счетчик цикла) 
        JNC     SC2 
        ;-----------------------------------конец цикла SC2/ SC2E 
 
;------проверка отсутствия новой нажатой клавиши 
        MOV     DI,LAST 
        OR      DI,DI 
        JZ      SC_RET 
;------проверка длительного нажатия клавиш 
        MOV     BX, offset TIME 
        DEC     byte ptr [BX]   ; проверка окончания интервала тповторения 
        JNZ     SC_RET 
        MOV     [BX],byte ptr SECOND_TIME ; повторная установка интервала 
        CALL    SEND_CODE      ; формирование скан-кода 
 
SC_RET: 
        MOV     W_SCAN,FALSE   ; сьрос признака работа 
        POP     SI 
        POP     DI 
        POP     DX 
        POP     CX 
        POP     BX 
SC_RET1: 
        CLI 
        MOV     AL,20H         ; контроллер прерываний 
        OUT     20H,AL 
        POP     DS 
        POP     AX 
        IRET 
 
SCANINT ENDP 
 
;------------------------------------------------- 
;       формирование кода нажатой сканирования 
;------------------------------------------------- 
;       DI - адрес скан-кода клавиши 
;------------------------------------------------- 
 
SEND_CODE      PROC	NEAR 
 
        MOV     AL,CS:[DI]     ; первичный скан-код 
	CMP	AL,62		;SCODE - F4 
	JNZ	NO_FBEEP 
	NOT	FBEEP 
NO_FBEEP: 
;------ проверка на особые клавиши ( по новому ГОСТу ) 
        CMP     AL,255-16 
        JNC     SEND1          ; если особая клавиша 
;------ проверка на часто длительно нажатые клавиши 
;       AND     AL,7FH 
;       TEST    byte ptr CS:[DI],80H 
        CMP     AL,80H         ; повека на особые клавиши  
        JB      SEND1          ; если обычная клавиша 
 
        CMP     AL,48H+80H     ; повека диапазона клавиш 0C8..0D0 
        JB      SEND01 
        CMP     AL,50H+80H 
        JBE     SEND1   
 
SEND01: CMP     TIME,SECOND_TIME 
        JZ      SEND2 
SEND1: 
        CMP     FBEEP,TRUE 
	JNZ	SEND1A             ; если звук подавлен 
 
;-------- звуковой сигнал по нажатию клавиши 
        PUSH    BX 
        MOV     BX,0101H 
        CALL    BEEP 
        POP     BX 
;--------------------- 
SEND1A: 
        ; проверка нажатия клавиши RUS 
        CMP	AL,RUS_KEY+80H 
        JZ      YES_RUS                 ; инверсия режима РУС/ЛАТ 
        CMP     AL,SHIFT2_KEY+80H 
        JNZ     NO_SHIFT2 
        ;SHIFT2 
        NOT     SHIFT2 
YES_RUS:NOT     RUSS 
        RET 
NO_SHIFT2: 
SEND2: 
        XOR     AH,AH                ; признак нажатия клавиши 
        CALL    C_OUT60              ; вывод в 60 порт + INT9 
SEND_E: 
	RET 
 
SEND_CODE ENDP 
 
;------------------------------------------------------------------- 
;         вывод в порт 60 и вызов INT9 
;             AL - код сканирования (первичный) клавиши 
;                  255-250  - ссылка на другую таблицу 
;             AH - 00  - клавиша нажата 
;                  80H - клавиша отжата 
;------------------------------------------------------------------- 
 
C_OUT60 PROC NEAR 
 
;------ проверка на особые клавиши ( по новому ГОСТу ) 
        CMP     AL,255-16 
        JNC     C_OUT1 
;------ проверка на клавиши отличные от клавиатуры IBM 
        CMP      AL,RUS_KEY+80H 
        JNC      NO_INT9 
;------ проверка на дополнительные скан_коды       ; 14.02.89 
        CMP      AL,48H+80H 
        JC       C_OUT60A 
        PUSH     AX         ; дополнительные скан_коды 
        MOV      AL,0E0H 
        CALL     C_INT9 
        POP      AX 
;------ обычные скан коды 
C_OUT60A: 
        AND     AL,7FH 
        OR      AL,AH 
        CALL    C_INT9; 
NO_INT9: 
        RET 
;------ особые клавиши ( по новому ГОСТу ) 
 
C_OUT1: PUSH    DI 
        PUSH    SI 
        PUSH    BX 
 
        MOV     BX,AX 
        XOR     AH,AH 
        NOT     AL         ; AX - номер строки в таблице LN_KEY1 
        MOV     SI,AX 
;------ проверка на нажатие отжатие 
        TEST    BH,80H 
        JZ      C_OUT1A     ; если нажата 
;------- клавиша  отжата 
        MOV     AL,MEM_KEY[SI]  ; код сканирования нажатой клавиши 
        OR      AL,BH           ; добавление признака " отжато" 
        CALL    C_INT9 
        JMP     C_OUT32 
;------- клавиша нажата 
C_OUT1A: 
        MOV     DI,AX 
        ADD     DI,AX 
        ADD     DI,AX      ; DI - смещение  в таблице LN_KEY1 
        MOV     AH,LEFT_KEY+80H ; состояние SHIFT1 
        TEST    KB_FLAG,3H  ; проверка  клавиш SHIFT1 
        JNZ     C_OUT2 
        CMP     SHIFT2,FALSE  ; проверка  клавиш SHIFT1 
        JZ      C_OUT3      ; клавиши SHIFT1 и SHIFT2 не нажаты 
        ; клавиша SHIFT2 нажата 
        INC     DI 
        INC     DI 
        JMP     C_OUT3 
C_OUT2: ; клавиша SHIFT1 нажата 
        AND     AH,7FH 
        INC     DI 
;------- вывод модифицированного скан-кода 
C_OUT3: 
        MOV     BL,CS:LN_KEY1[DI] 
        TEST    BL,80H         ; проверка необходимости смены SHIFT1 
        JZ      C_OUT31 
        ;  переключение SHIFT1 
        MOV     AL,AH 
        XOR     AL,80H          ; Инвертирование старшего бита 
        CALL    C_INT9          ; выдача обратного кода для SHIFT1 
 
C_OUT31:; скан код нажатой клавиши 
        MOV     AL,BL 
        AND     AL,7FH 
        MOV     MEM_KEY[SI],AL ; запоминание скан-кода нажатой клавиши 
        CALL    C_INT9 
        ;  восстановление SHIFT1 
        TEST    BL,80H 
        JZ      C_OUT32 
        MOV     AL,AH 
        CALL    C_INT9          ;  восстановление состояния SHIFT 
 
C_OUT32:POP      BX 
        POP      SI 
        POP      DI 
        RET 
 
C_OUT60 ENDP 
 
;-------------------------------------------------------------- 
C_INT9  PROC NEAR 
;       AX - код сканирования 
;       CALL   DISP_AX     ; !!!!!!!! 
        OUT    LINE_SEL,AL 
        INT    KEY_INT 
        RET 
C_INT9  ENDP 
;--------------------------------------------------------------- 
 
