[asm] klawiatura

0

Mam problem z kontrolerem klawiatury.
Kiedy wysyłam do portu 64h wartość 20h, w porcie 60h powinienem odczytać zawartość rejestru kontrolnego. I tak się rzeczywiście dzieje. Problem tkwi w tym, że rejestr stanu, czytany z 64h, pownien pokazywać wtedy zapełnienie bufora wyjściowego (OBF), czyli bit0 rejestru stanu powinien być ustawiony, a tak się nie dzieje. Dlaczego? Sprawdziłem to na dwóch koputerach i jest to samo :-/

in al, 64h ;al ma wtedy wartość wtedy: 00011100, czyli jest ok
mov al, 20h ;rozkaz czytania rejestru kontrolnego (read command byte)
out 64h, al ;przesyłam rozkaz do kontrolera
in al, 64h ;!!! i tu powinienem otrzymac wartość 00011101, a otrymuję dalej 00011100
in al, 60h ;pomimo tego rejestr kontrolny jest w porcie 60h :-/
0

Co to jest ten rejestr kontrolny ?
Znaczy do czego służy, jakie ma znaczenie ?
Czy jesteś pewien że jego kod rozkazowy to 20h ?

Możliwość 1.
Jedyne co moge stwierdzić na pewno to to, że nie odczytałeś zawartości tego rejestru. Właśnie dlatego, że bit0 rejestru stanu jest wyzerowany. Są to prawdopodobnie losowe wartości.

Możliwość 2.
Nie wyłączyłeś przerwań. Ten rejestr kontrolny został wysłany do bufora wyjściowego i ustawiony bit0 Rejestru stanu. Przerwanie obsługi klawiatury odebrało ten bajt po przez in al,60 i w ten sposób został wyzerowany bit0 Rejestru stanu. A dane które były ostatnio w rejestrze wyjściowym możesz odczytywać zawsze.

0

Rejestr kontrolny to bajt, w którym poszczególne bity mówią, czy włączona jest obsługa przerwań klawiatury lub myszy, czy klawiatura lub myszka są włączone, czy nie.

W ogóle o tym można przeczytać tu: http://binboy.sphere.pl/index.php?show=41

Bo tak w ogóle, to zamierzam napisać procedurę obsługującą mysz, ale tylko z użyiem portów.
Jakby ktoś miał gotowy program, byłbym wdzięczny.

A przerwania próbowałem wyłączać i dalej jest to samo. Hm. Jestem pewnien, że kiedyś wszystko było dobrze. :-/

0

Obsługa myszy PS/2, składnia NASM-a.

W tej wersji kod nie jest idiotoodporny. Jeśli myszy nie ma (lub jest na COM lub USB) to program się zawiesi w nieskończoność czekając na odpowiedź od myszy.

Testowane w 32-bitowym trybie chronionym, myślę że bez modyfikacji będzie działało w trybach 16-bitowym i rzeczywistym.

        mysz_ktory db 1
        mysz_bajt1 db ?
        mysz_bajt2 db ?
        mysz_bajt3 db ?


irq_12_proc:
        push eax
	in al,60h
	mov ah,[mysz_ktory]
	cmp ah,3
        je .trzeci
	cmp ah,2
        je .drugi
    .pierwszy:
	mov [mysz_bajt1],al
	inc ah
	mov [mysz_ktory],ah
        jmp .koniec_myszy
    .drugi:
	mov [mysz_bajt2],al
	inc ah
	mov [mysz_ktory],ah
        jmp .koniec_myszy
    .trzeci:
	mov [mysz_bajt3],al
        call zdarzenie_myszy
	mov ah,1
	mov [mysz_ktory],ah
        jmp .koniec_myszy
    .koniec_myszy:
	mov al,20h
        out 0A0h,al
	mov al,20h
        out 20h,al
        pop eax
iret


wait_w:
	push ax
  .full: in al,64h
	and al,2
        jnz .full
	pop ax
ret

wait_r:
	push ax
 .empty: in al,64h
	and al,1
        jz .empty
	pop ax
ret

; zapis do myszy bajtu z AL
write_mouse:
        push ax
        call wait_w
        mov al,0D4h 
        out 64h,al 
        call wait_w
        pop ax
        out 60h,al
	call read_mouse ; odbierz potwierdzenie
ret

; odczyt z myszy bajtu do AL
read_mouse:
	call wait_r
	in al,60h
ret

key_on:
	push ax
	call wait_w
	mov al, 0AEh
	out 64h,al
	pop ax
ret

key_off:
	push ax
	call wait_w
	mov al,0ADh 
        out 64h,al
	pop ax
ret

mouse_int_on:
        call wait_w
        mov al,60h   
	out 64h,al
	call wait_w
	mov al,01000011b
	out 60h,al
ret

mouse_int_off:
	call wait_w
	mov al,60h
	out 64h,al
	call wait_w
	mov al,01000001b
	out 60h,al
ret

init_mouse:
        call key_off      ; wyłączenie klawiatury
        mov al,0FFh       
        call write_mouse  ; <-- reset myszy
        call read_mouse   ; --> kod wyjściowy BAT
        call read_mouse   ; --> device ID
        mov al,0F4h       
        call write_mouse  ; <-- zgoda na wysyłanie danych przez mysz
	call key_on       ; włączenie klawiatury
        call mouse_int_on ; zezwolenie na przerwanie od myszy
ret

done_mouse:
	call key_off
        call wait_w
        mov al,0D4h 
        out 64h,al 
        call wait_w
	mov al,0F5h
        out 60h,al         ; <-- zabronienie wysyłania danych przez mysz
	call mouse_int_off ; zabronienie przerwania od myszy
	call key_on
ret

Aby to działało, należy ustawić procedurę irq_12_proc jako obsługę przerwania IRQ 12, i wykonać

call init_mouse

a po zakończeniu programu

call done_mouse

i przywrócić stare przerwanie. Jeśli myszy nie wyłączymy, może być problem z ponowną jej inicjacją, albo dojdzie do zablokowania klawiatury.

Powyższy kod tylko odbiera dane nadchodzące od myszy i wywołuje procedurę zdarzenie_myszy. Procedura ta powinna analizować te dane (zmienne mysz_bajt, mysz_bajt2, mysz_bajt3) zgodnie z protokołem myszy PS/2.

Oto przykładowa procedurka zdarzenie_myszy ? mysz_ppm, spm, lpm są ustawiane na 0 albo 1.
mysz_kx i mysz_ky to współrzędne kursora przeliczone do trybu tekstowego 80x25.

Zaznaczone jest miejsce, gdzie powinien być dodany kod do rysowania i kasowania kursora.

    ; zmienne do wykorzystania na zewnątrz:

	mysz_ppm db 0
	mysz_spm db 0
	mysz_lpm db 0
        mysz_kx db 0
        mysz_ky db 0

    ; zmienne wewnętrzne
        mysz_x dw 0
        mysz_y dw 49*16
        mysz_starekx db 0
        mysz_stareky db 0

zdarzenie_myszy:
        pushad

  ; obliczenie nowej pozycji kursora myszki
 	push bx
	xor bx,bx
        mov bl,[mysz_bajt2]
        mov al,[mysz_bajt1]
	and al,16
        cmp al,16
        jne .xplus
	mov bh,0FFh
       .xplus:
        mov ax,[mysz_x]
	add ax,bx
        mov [mysz_x],ax
	xor bx,bx
        mov bl,[mysz_bajt3]
        mov al,[mysz_bajt1]
	and al,32
	cmp al,32
        jne .yplus
    	mov bh,0FFh
       .yplus:
        mov ax,[mysz_y]
	add ax,bx
        mov [mysz_y],ax

        mov al,[mysz_ky]
        mov [mysz_stareky],al
        mov al,[mysz_kx]
        mov [mysz_starekx],al

        mov ax,[mysz_x]
        shr ax,4
        cmp al,0
        jl .xmin
        cmp al,79
        jg .xmax
        jmp .xok
       .xmin:
        xor al,al
        xor bx,bx
        mov [mysz_x],bx
        jmp .xok
       .xmax:
        mov al,79
        mov bx,79*16
        mov [mysz_x],bx
       .xok:
        mov [mysz_kx],al

        mov ax,[mysz_y]
        shr ax,4
        cmp al,0
        jl .ymin
        cmp al,49
        jg .ymax
        jmp .yok
       .ymin:
        xor al,al
        xor bx,bx
        mov [mysz_y],bx
        jmp .yok
       .ymax:
        mov al,49
        mov bx,49*16
        mov [mysz_y],bx
       .yok:
        neg al
        add al,49
        mov [mysz_ky],al

	pop bx

  ; czy zmiana pozycji kursora?
        mov al,[mysz_starekx]
        mov ah,[mysz_kx]
        cmp al,ah
        jne .ruch
        mov al,[mysz_stareky]
        mov ah,[mysz_ky]
        cmp al,ah
        jne .ruch
        jmp .bezruchu
     .ruch:

	; #### - skasuj kursor z pozycji [mysz_starekx]:[mysz_stareky]

        ; #### - narysuj kursor na pozycji [mysz_kx]:[mysz_ky]

     .bezruchu:
      
  ; sprawdzenie przycisku lewego
        mov al,[mysz_bajt1]
        and al,1
	mov [mysz_lpm],al
 ; sprawdzenie przycisku prawego
        mov al,[mysz_bajt1]
	and al,2
	shr al,1
	mov [mysz_ppm],al
 ; sprawdzenie przycisku środkowego
        mov al,[mysz_bajt1]
	and al,4
	shr al,2
	mov [mysz_spm],al

	popad
ret
0

Dzięki.
Właściwie nie chciałem używać przerwania 12h, ale bez niego chyba sobie nie poradzę. Nie wychodzi mi, gdy używam samych portów.

1 użytkowników online, w tym zalogowanych: 0, gości: 1