Код:
; Set keyboard staus indicators
KBD_SEND_INDICATORS:
ldi temp,0xED ; keyboard command Set status indicators
rcall KBD_SEND ; subroutine send command to keyboard
mov temp,KBD_IND ; indicatoes value
;---------------------------------------------------------------------------------------
; Запись байта в клавиатуру
;---------------------------------------------------------------------------------------
KBD_SEND:
rcall KBD_SEND_BYTE
ret
;-------------------------------------------------------------------------------------------
KBD_SEND_BYTE:
sbi DDRD,0x03 ; set CLK pin as output (=0)
rcall Delay100mS ; Wait 100ms
sbi DDRD,0x02 ; 1->DDRD.2 DATA (=0)
rcall Delay5mS ; 5ms
cbi DDRD,0x03 ; set CLK pin as input (=1)
rcall Delay100uS
; начинается тактирование CLK от клавиатуры
rcall WAIT_CLK0
rcall Delay100uS
; цикл отправки 8 бит данных -------------------------------
ldi cnt,0x08
clr ps2_parity_cnt
rjmp L02A5
READ_LOOP:
rcall WAIT_CLK0
L02A5:
ror temp ; KBD_BYTE>> (сдвиг вправо, выдвинутый бит помещается в C)
brcs SEND_1 ; если C=1
;Отправка бита = 0
sbi DDRD,0x02 ; 1->DDRD.2 (в режим записи, на пине 0, т.к. PortD.2 = 0)
rjmp L02AB
SEND_1: ; Отправка бита = 1
cbi DDRD,0x02 ; 0->DDRD.2 (в режим чтения) вроде как отправляется 1
inc ps2_parity_cnt ; вычисление бита четности
L02AB:
rcall WAIT_CLK1
dec cnt
brne READ_LOOP
; конец цикла отправки ---------------------------------------
; отправка бита четности
rcall WAIT_CLK0
cbi DDRD,0x02
sbrc ps2_parity_cnt,0x00
sbi DDRD,0x02
rcall WAIT_CLK1
; стоповый бит
rcall WAIT_CLK0
cbi DDRD,0x02
rcall WAIT_CLK1
; ACK
rcall WAIT_CLK0
rcall WAIT_CLK1
ret
;---------------------------------------------------------------------------------------
;----------------------------------------------------------------------------------------
; Подпрограммы ожидания смены уровня CLK
;
; Проверка переполнения таймера и CLK: цикл пока таймер не переполнится или CLK не станет равно 1
; Если таймер переполнился, значит таймаут и бит не принят
WAIT_CLK1:
sbis PinD,0x03 ; CLK=1 пропускаем jmp
rjmp WAIT_CLK1 ; loop
ret
; Проверка переполнения таймера и CLK: цикл пока таймер не переполнится или CLK не станет равно 0
WAIT_CLK0:
sbic PinD,0x03 ; CLK=0 пропускаем jmp
rjmp WAIT_CLK0
ret