Mysz PS/2 w asemblerze

PL
Data dodania: 2011-09-15, Autor: bratmn, Dodał: Karol, Wyświetleń: 343
------------------------------------------------------------------------------
|                            OBSŁUGA MYSZY PS/2                                |
 ------------------------------------------------------------------------------
| OPRACOWANIE NAPISANE W RAMACH PROJEKTU Z PRZEDMIOTU OPROGRAMOWANIE SYSTEMOWE,|
|                                                                              |
| prowadzący: dr inż. ANDRZEJ JĘDRUCH                                          |
|                                                                              |
| POLITECHNIKA GDAŃSKA,                                                        |
| WYDZIAŁ ELEKTRONIKI, TELEKOMUNIKACJI I INFORMATYKI,                          |
| KWIECIEŃ 2004r.                                                              |
|                                                                              |
 ------------------------------------------------------------------------------
| opracował:                                                                   |
|                                                                              |
| MICHAŁ NARWOJSZ                                                              |
| INFORMATYKA,                                                                 |
| semestr 04                                                                   |
|                                                                              |
| e-mail: publ@epf.pl                                                           |
|                                                                              |
 ------------------------------------------------------------------------------

NINIEJSZE OPRACOWANIE JEST WYNIKIEM MOICH POSZUKIWAŃ W INTERNECIE I KSIĄŻKACH, A TAKŻE WŁASNYCH PRÓB. NIE UDZIELAM ŻADNEJ GWARANCJI POPRAWNOŚCI ZAWARTYCH W NIM INFORMACJI. UWAGI, SUGESTIE I ZNALEZIONE BŁĘDY ORAZ NIEJASNOŚCI PROSZĘ PRZESYŁAĆ NA PODANY ADRES E-MAIL. DO CZĘŚCI ZAWARTYCH TU INFORMACJI DOSZEDŁEM METODĄ PRÓB I BŁĘDÓW, NIE BĘDĄC PEWNYM ZNACZENIA NIEKTÓRYCH BITÓW ITP. PREZENTUJĘ JE WIĘC NA ZASADZIE "U MNIE DZIAŁAŁO". WERSJĘ TEKSTOWĄ OPRACOWANIA MOŻNA ZNALE¬Ć NA STRONIE WWW.AT.XT.PL

UWAGA! WIĘKSZA CZĘŚĆ NINIEJSZEGO OPRACOWANIA JEST TŁUMACZENIEM MATERIAŁÓW ZAWARTYCH NA PODSTRONACH WITRYNY http://panda.cs.ndsu.nodak.edu/~achapwes/PICmicro/ AUTORSTWA ADAMA CHAPWESKE. MATERIAŁY TE ZOSTAŁY WYKORZYSTANE ZA WIEDZĄ I ZGODĄ AUTORA.


Większość poradników na temat niskopoziomowej obsługi myszy opiera się na DOS - owym sterowniku myszy INT 33h. Jednak nie zawsze mamy dostęp do tego wygodnego sposobu komunikacji z myszą. Niniejsze opracowanie ma na celu wyjaśnienie sposobu obsługi myszy na niższym poziomie, niezależnym od uruchomionych sterowników. Dotyczy ono najpopularniejszych ostatnio modeli myszy, podłączanych do złącza PS/2.

1. Układ 8042.

Od strony płyty głównej za komunikację z myszą odpowiedzialny jest układ 8042, do którego jest także podłączona klawiatura. Opracowanie to dotyczy programowania myszy, zagadnienia dotyczące klawiatury nie będą tu szczegółowo opisywane. Należy więc mieć świadomość, że podany tu opis nie jest kompletny i dotyczy jedynie niektórych właściwości układu. Zainteresowanych bardziej kompletnym opisem odsyłam do źródeł wymienionych na końcu niniejszego opracowania. W zależności od płyty głównej 8042 może pracować w jednym z dwóch trybów: AT-compatible" lub "PS/2-compatible". Obsługa przez płytę myszy PS/2 świadczy o pracy układu w drugim z tych trybów i tylko on będzie tu omawiany.

8042 zawiera cztery jednobajtowe rejestry wewnętrzne:

  • bufor wyjściowy - zawiera dane odebrane od myszy
  • bufor wejściowy - zawiera dane przeznaczone do wysłania do myszy
  • rejestr stanu - tylko do odczytu, zawiera 8 flag statusowych
  • rejestr kontrolny - do odczytu i zapisu, zawiera 7 flag statusowych.

Pierwsze trzy rejestry (wejściowy, wyjściowy i stanu) są bezpośrednio dostępne poprzez porty 60h i 64h. Ostatni rejestr (kontrolny) jest odczytywany za pomocą specjalnego rozkazu "Read command byte" i zapisywany za pomocą rozkazu "Write Command Byte".

Poniższa tabela pokazuje sposób dostępu do rejestrów 8042:

-------------------------------------------------
| Port  |  akcja   |  znaczenie                   |
 -------------------------------------------------
| 60h   |  odczyt  |  odczyt z bufora wyjściowego |
| 60h   |  zapis   |  zapis do bufora wejściowego |
| 64h   |  odczyt  |  odczyt z rejestru stanu     |
| 64h   |  zapis   |  wysłanie rozkazu            |
 -------------------------------------------------

Zapis do portu 64h nie zapisuje żadnego szczególnego rejestru, lecz stanowi rozkaz do interpretacji przez 8042. Jeżeli dany rozkaz wymaga podania jakiegoś parametru, należy go wysłać do portu 60h po wysłaniu rozkazu.

Bufory wyjściowy i wejściowy są wspólne dla klawiatury i myszy. Wysyłając cokolwiek do myszy trzeba więc "powiedzieć" układowi 8042, że dany bajt ma tam właśnie trafić. Służy do tego odpowiedni rozkaz wysyłany do 64h.

Znaczenie flag statusowych rejestru stanu ( odczyt z 64h ):

-------------------------------------------------------
|          rejestr stanu 8042 w trybie PS/2             |
 -------------------------------------------------------
| bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
 -------------------------------------------------------
| PERR |  TO  | MOBF | INH  |  A2  | SYS  | IBF  | OBF  |
 -------------------------------------------------------

(UWAGA! nazewnictwo i przeznaczenie buforów wyjściowego i wejściowego mogą być mylące. Będę do nich podchodził z punktu widzenia programisty: o odczytywaniu danych będę pisał w sytuacji, gdy mysz bądź 8042 wysyła jakieś dane, a my je odczytujemy, natomiast o zapisywaniu - gdy chcemy wysłać coś do myszy lub 8042, więc zapisujemy to do odpowiedniego portu. Dane odczytujemy z bufora wyjściowego, zapisujemy do wejściowego. Odpowiada to schematowi podanemu na str. 751 w [2], [1] podchodzi do zagadnienia jakby odwrotnie)

  • OBF (Output Buffer Full) - Wskaźnik zapełnienie bufora wyjściowego
    • 0: bufor wyjściowy pusty - brak nowych danych do odczytania w porcie 60h
    • 1: bufor wyjściowy pełny - port 60h zawiera dane do odczytania
  • IBF (Input Buffer Full) - Wskaźnik zapełnienia bufora wejściowego
    • 0: bufor wejściowy pusty - można pisać do 60h
    • 1: bufor wejściowy pełny - dane przesłane przez procesor znajdują się jeszcze w buforze
  • SYS (System flag) - źródła nieco różnią się w interpretacji tego bitu.
[1] podaje:
    " Post reads this to determine if power-on reset, or software reset.
    0: Power-up value - System is in power-on reset.
    1: BAT code received - System has already beed initialized."

    natomiast [2]:
    "Wynik autotestu klawiatury
    0: błąd
    1: wynik bezbłędny."

    -----------------------------------------------------------------------
   | Co by to wszystko nie znaczyło, ten bit nie będzie nam potrzebny przy |
   | programowaniu myszy                                                   |
    -----------------------------------------------------------------------
  • A2 (linia adresowa A2) - Używany wewnętrznie przez 8042
    • 0: A2 = 0 - ostatnio zapisany był port 60h
    • 1: A2 = 1 - ostatnio zapisany był port 64h
  • INH (Inhibit flag) - stan blokady klawiatury
    • 0: klawiatura zablokowana
    • 1: klawiatura dostępna
  • MOBF (Mouse Output Buffer Full) - podobny do OBF, dotyczy myszy
    • 0: Output buffer empty - bufor wyjściowy nie zawiera danych od myszy (może natomiast zawierać dane od klawiatury)
    • 1: Output buffer full - bufor wyjściowy zawiera dane od myszy.
---------------------------------------------------------------------------------
  | Tego bitu, w połączeniu z bitem OBF używa się do sprawdzania, czy w porcie 60h  |
  | znajdują się nowe bajty wysłane przez mysz. Jeżeli na OBF i MOBF nie ma jedynek,|
  | nie szukamy w porcie 60h danych wysłanych przez mysz, gdyż ich tam nie ma.      |
   ---------------------------------------------------------------------------------
  • TO (General Timout) - Czas oczekiwania na nadesłanie danych
    • __0:OK __- Klawiatura odebrała i odpowiedziała na ostatni rozkaz.
    • __1:Timeout Error __- czas oczekiwania przekroczony. Brak klawiatury lub klawiatura uszkodzona.
  • PERR (Parity Error) - Błąd parzystości
    • 0: OK
    • 1: Parity Error - wystąpił błąd parzystości w komunikacji z klawiaturą

Rozkazy 8042 używane przy obsłudze myszy (zapis do 64h):

Przed pisaniem do portu 64h lub 60h należy sprawdzić bit IBF w słowie stanu układu. Ustawiony bit IBF oznacza, że nie można jeszcze wysyłać danych do portu. Przykładowy kod sprawdzający możliwość zapisu:

petla:
      in al, 64h
      and al, 10b
      jnz petla

      out 64h, rozkaz

podobnie przed czytaniem portu 60h należy sprawdzić bity OBF i MOBF ( MOBF tylko gdy odczytujemy dane przesłane przez mysz)

petla:
      in al, 64h
      mov bl, al        ; usunąć gdy odczytywane dane nie pochodzą od myszy
      and al, 01b
      jz petla

      and bl, 0100000b  ; MOBF
      jz petla          ; usunąć gdy odczytywane dane nie pochodzą od myszy

      in al, 60h

(UWAGA! [1] używa bitów IBF i OBF odwrotnie niż tu napisałem, jednak faktem jest, że program zgodny z [1] nie działał, a zgodny z powyższą interpretacją działał, ponadto [2] podaje wersję zgodną z opisaną przeze mnie)

Rozkaz wysyłamy wpisując jego kod do portu 64h, ewentualne parametry wpisujemy następnie do 60h. Przed zapisem trzeba sprawdzać IBF! Wartości zwracane przez układ po wykonaniu rozkazu dostępne są w porcie 60h.

  • 20h (Read Command Byte) - Zwraca zawartość rejestru kontrolnego (patrz rozkaz 60h poniżej)
  • 60h (Write Command Byte) - Zapisuje parametr w rejestrze kontrolnym. format słowa kontrolnego:
-------------------------------------------------------
|              słowo kontrolne 8042                     |
 -------------------------------------------------------
| bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
 -------------------------------------------------------
|  --  | XLAT | _EN2 | _EN  |  --  | SYS  | INT2 | INT  |
 -------------------------------------------------------
 - INT (Input Buffer Full Interrupt) - ustawiony oznacza wywoływanie IRQ1 przez klawiaturę
     - 0: IBF Interrupt Disabled - nadesłanie danych przez klawiaturę nie wywołuje przerwania
     - 1: IBF Interrupt Enabled - nadesłanie danych przez klawiaturę wywołuje przerwanie IRQ1
 - INT2 (Mouse Input Buffer Full Interrupt) - ustawiony oznacza wywoływania IRQ12 przez mysz
     - 0: Auxillary IBF Interrupt Disabled - mysz nie wywołuje przerwania
     - 1: Auxillary IBF Interrupt Enabled - nadesłanie bajtu przez mysz wywołuje przerwanie IRQ12
 - SYS (System Flag) - Używany do ręcznego ustawiania flagi SYS w rejestrze stanu tu będziemy wstawiać 1 ; znaczenie bitu - patrz [1]
 - EN (Disable keyboard) - włącza/wyłącza interfejs klawiatury
     - 0: Enable - klawiatura włączona
     - 1: Disable - klawiatura niedostępna
 - EN2 (Disable Mouse) - włącza/wyłącza interfejs myszy
     - 0: Enable - mysz włączona
     - 1: Disable - mysz wyłączona
 - XLAT (Translate Scan Codes) - tu wstawiamy 1; znaczenie bitu - patrz [1]

- 0A7h (Disable mouse interface) - ustawia bit5 słowa kontrolnego, wyłącza interfejs myszy - 0A8h (Enable mouse interface) - zeruje bit5 słowa kontrolnego, włącza interfejs myszy - 0A9h (Mouse interface test) - kontroluje łącze myszy i zwraca w porcie 60h wynik: - 00h: wynik kontroli pozytywny - 01h: sygnał zegarowy stale na niskim poziomie logicznym - 02h: sygnał zegarowy stale na wysokim poziomie logicznym - 03h: linia danych stale na niskim poziomie logicznym - 04h: linia danych stale na wysokim poziomie logicznym - 0FFh: brak myszy - 0ADh (Disable keyboard interface) - ustawia bit4 słowa kontrolnego, wyłącza interfejs klawiatury - 0AEh (Enable keyboard interface) - zeruje bit4 słowa kontrolnego, włącza interfejs klawiatury - 0D4h (Write mouse Device) - parametr będzie wysłany do myszy.

-----------------------------------------------------------------------
       | podstawowy rozkaz używany przy programowaniu myszy. Wszelkie rozkazy  |
       | myszy (patrz dalsza część opracowania) muszą być wysyłane przy pomocy |
       | tego rozkazu                                                          |
        -----------------------------------------------------------------------

pozostałe rozkazy - patrz [1] i [2]

2. MYSZ

Standardowa mysz PS/2 obsługuje trzy klawisze i przesuwanie poziome (X) oraz pionowe (Y). Odpowiednio zainicjowana mysz przy każdym naciśnięciu lub zwolnieniu klawisza i przy każdym przesunięciu wysyła 3 - bajtowy pakiet danych zgodnie z niżej podanym formatem. Jeżeli odpowiedni bit ze słowa kontrolnego 8042 (bit1) jest ustawiony, nadejście każdego z trzech bajtów pakietu wywołuje przerwanie IRQ12. Bajty pakietu odczytujemy z portu 60h.

Pakiet danych myszy:

-------------------------------------------------------
|                         bajt 1                        |
|                                                       |
| bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
 .......................................................
| NA_Y | NA_X | ZN_Y | ZN_X |  1   | P_ŚR |  P_P | P_L  |
 -------------------------------------------------------
|                 bajt2 - przesunięcie X                |
 -------------------------------------------------------
|                 bajt3 - przesunięcie Y                |
 -------------------------------------------------------
  • NA_Y - nadmierne przesunięcie Y. Wewnętrzne rejestry myszy pozwalają na zarejestrowanie przesunięcia z zakresu -255 do +255. Przekroczenie tych wartości powoduje ustawienie tego bitu.
    • 0: nadmiar nie wystąpił
    • 1: nadmiar wystąpił
  • NA_X - nadmierne przesunięcie X.
    • 0: nadmiar nie wystąpił
    • 1: nadmiar wystąpił
  • ZN_Y - bit znaku przesunięcia Y.
    • 0: przesunięcie w górę
    • 1: przesunięcie w dół
  • ZN_X - bit znaku przesunięcia X.
    • 0: przesunięcie w prawo
    • 1: przesunięcie w lewo
  • P_ŚR - przycisk środkowy.
    • 0: przycisk zwolniony
    • 1: przycisk wciśnięty
  • P_P - przycisk prawy.
    • 0: przycisk zwolniony
    • 1: przycisk wciśnięty
  • P_L - przycisk lewy.
    • 0: przycisk zwolniony
    • 1: przycisk wciśnięty

Bajty przesunięcia informują o wielkości przesunięcia myszy od czasu wysłania ostatniego pakietu danych. Po wysłaniu pakietu wewnętrzne rejestry przesunięcia są zerowane.

Wewnętrzne rejestry przesunięcia myszy są 9 - bitowe, przesunięcie zapisywane jest w kodzie U2, najstarsze bity są wystawiane w bajcie 1 pakietu jako bity znaku przesunięcia. Zastosowanie kodu U2 powoduje szczególny sposób aktualizacji współrzędnych kursora. Po odebraniu pakietu, w przypadku przesunięcia w prawo lub w górę bajty 2 i 3 są normalnymi dodatnimi wielkościami binarnymi oznaczającymi wartości przesunięć poziomego i pionowego. Przesunięcie w lewo lub w dół mysz odczytuje jako ujemne. W takim przypadku, aby uzyskać binarną wartość przesunięcia do odjęcia (dla przesunięcia poziomego) lub do dodania (dla przesunięcia pionowego) do położenia kursora, należy od odpowiedniego bajtu z pakietu wysłanego przez mysz odjąć jeden (chodzi tu o potraktowanie bajtu jako liczby binarnej i arytmetyczne odjęcie wartości "1" ) i następnie zanegować wszystkie jego bity.

Wewnętrzne rejestry (liczniki) przesunięcia myszy są zerowane po każdym udanym wysłaniu pakietu danych do hosta ( hostem będę tu nazywał komputer, do którego jest podłączona mysz ) i po odebraniu jakiegokolwiek rozkazu ( oprócz rozkazu "Resend" - 0FEh ) od hosta.

Sposobem pracy myszy sterują parametry (ustalane odp. rozkazami):

  • częstotliwość próbkowania: maksymalna ilość pakietów danych, jaką mysz może wysłać do hosta w ciągu sekundy. Domyślnie - 100.

  • rozdzielczość: wielkość, o jaką zmienia się stan rejestrów (liczników przesunięcia) myszy przy przesunięciu o 1mm; domyślnie - 4.

  • skalowanie: parametr ten nie wpływa na zawartość rejestrów myszy, a jedynie na wartości przesyłane do hosta. Przy skalowaniu 1:1 mysz przesyła hostowi nie zmienione wartości, a przy skalowaniu 2:1 wartości ustalane są następująco:

---------------------------------------------------
          | Licznik przesunięcia  |  wartość wysłana do hosta |
           ---------------------------------------------------
          |           0           |            0              |
          |           1           |            1              |
          |           2           |            1              |
          |           3           |            3              |
          |           4           |            6              |
          |           5           |            9              |
          |         N > 5         |          2 * N            |
           ---------------------------------------------------

parametr ten dotyczy jedynie danych przesyłanych automatycznie w trybie stream.

  • przesyłanie danych: może być uruchomione ( gdy mysz pracuje w trybie stream, wysyła dane do hosta po wykryciu przesunięcia lub zmiany stanu przycisków) lub zablokowane.

Mysz może pracować w kilku różnych trybach i przyjmuje kilkanaście różnych rozkazów. Aby wysłać rozkaz do myszy należy wysłać do układu 8042 ( port 64h ) rozkaz 0D4h i jako jego parametr ( port 60h ) odpowiedni kod rozkazu myszy. Jeżeli rozkaz myszy dodatkowo wymaga parametru (np. rozkaz 0E8h, patrz niżej), ponownie wysyłamy do portu 64h rozkaz 0D4h i dopiero teraz wpisujemy ten parametr do portu 60h. Odpowiedzi myszy dostępne są w porcie 60h.


Mysz ma cztery standardowe tryby pracy:

  • Reset - Mysz wchodzi w tryb Reset po włączeniu zasilania bądź odebraniu rozkazu "Reset" ( 0FFh ).

  • Stream - Jest to domyślny tryb pracy myszy ( po zakończeniu procedur resetowania ), używany przez większość programów. Jeżeli host uprzednio przełączył mysz w tryb "Remote", może przełączyć ją ponownie w tryb "Stream" wysyłając rozkaz "Set Stream Mode" (0EAh).

  • Remote - Tryb ten jest użyteczny w niektórych przypadkach i można go uruchomić rozkazem "Set Remote Mode" (0F0h)

  • Wrap - Ten tryb nie jest specjalnie użyteczny, jedynie do testowania połączenia pomiędzy myszą a hostem. W tryb ten wprowadzamy mysz używając rozkazu "Set Wrap Mode" (0EEh). Wyjście z trybu "Wrap" następuje po odebraniu przez mysz rozkazów "Reset" (0FFh) lub "Reset Wrap Mode" (0ECh). Rozkaz "Reset" przełącza mysz w tryb "Reset", rozkaz "Reset Wrap Mode" w tryb poprzedzający włączenie trybu "Wrap".

Niektóre myszy mogą także pracować w pewnych "rozszerzonych" trybach ( np. z obsługą rolek itp. ), jednak nie należą one już do standardu. Więcej informacji na ten temat w [1] .

Tryb reset:

Mysz wchodzi w tryb reset po włączeniu zasilania lub po odebraniu rozkazu "Reset" (0FFh). Po wejściu w tryb reset mysz przeprowadza diagnostyczny test swoich układów oznaczany jako BAT (Basic Assurance Test) i ustawia następujące domyślne wartości:

  • Częstotliwość próbkowania - 100 próbek/sek.,
  • Rozdzielczość - 4 /mm,
  • Skalowanie - 1:1,
  • Wyłączone przesyłanie danych;

następnie wysyła kod wyjściowy BAT : 0AAh (BAT przeprowadzono pomyślnie) lub 0FCh (błąd).

Po kodzie wyjściowym BAT ( 0AAh lub 0FCh ) wysyłany jest device ID myszy 00h. Kod ten odróżnia mysz standardową od klawiatury lub myszy w trybie "rozszerzonym" (niestandardowym, np. z obsługą rolek).

Po przesłaniu kodu device ID mysz przechodzi w tryb Stream. Zwróć uwagę, że jedną z domyślnych wartości jest "Wyłączone przesyłanie danych" - oznacza to, że mysz nie wyśle żadnego pakietu danych dopóki nie otrzyma rozkazu "włącz przesyłanie danych" (0F4h).

Tryb Stream:

W trybie stream mysz wysyła pakiety danych gdy wykryje przesunięcie lub zmianę stanu jednego lub więcej przycisków. Maksymalna częstość, z jaką pakiety mogą się pojawić, nazywana jest częstotliwością próbkowania. Parametr ten zmienia się w zakresie 10 - 200 próbek / sek. Domyślną wartością jest 100 próbek/sek., host może zmienić tę wartość wysyłając rozkaz "ustaw częstotliwość próbkowania" (0F3h). Tryb Stream jest domyślnym trybem pracy myszy.

Tryb Remote:

W trybie tym mysz odczytuje dane o przesunięciu i stanie przycisków, aktualizuje swoje rejestry i flagi, ale wysyła dane do hosta tylko po odebraniu rozkazu "czytaj dane" (0EBh). Po odebraniu tego rozkazu mysz wyśle pakiet danych i wyzeruje swoje rejestry.

Tryb Wrap:

W trybie tym mysz odsyła do hosta każdy bajt, który otrzyma. Nawet, jeśli jest to poprawny rozkaz, mysz nie odpowie na niego, a jedynie odeśle z powrotem otrzymany bajt. Wyjątek stanowią tu jedynie rozkazy "Reset" (0FFh) i "Reset wrap mode" (0ECh). Są one traktowane jako rozkazy i mysz nie odsyła ich kodów hostowi.

Lista rozkazów myszy:

Jeżeli mysz pracuje w trybie Stream, host powinien zablokować przesyłanie danych przez mysz (rozkaz 0F5h) przed wysyłaniem innych rozkazów.

  • 0FFh (Reset) - Mysz odpowiada na ten rozkaz bajtem potwierdzenia (0FAh) i przechodzi w tryb Reset.

  • 0FEh (Resend) - Host wysyła ten rozkaz gdy otrzyma od myszy błędne dane. Mysz odpowiada wysyłając ponownie ostatnio wysłany do hosta pakiet.

  • 0F6h (Set Defaults) - Mysz odpowiada bajtem potwierdzenia (0FAh) i ustala następujące wartości: częstotliwość próbkowanie: 100, rozdzielczość: 4/mm, skalowanie: 1:1, wyłączone przesyłanie danych. Następnie zerowane są rejestry myszy i przechodzi ona w tryb stream.

  • 0F5h (Disable Data Reporting) - Mysz odpowiada bajtem potwierdzenia (0FAh), wyłącza przesyłanie danych i resetuje swoje rejestry. Rozkaz ten zatrzymuje jedynie przesyłanie danych w trybie Stream i nie blokuje sprawdzania przez mysz położenia i stanu przycisków. Po odebraniu tego rozkazu tryb stream staje się identyczny z trybem remote.

  • 0F4h (Enable Data Reporting) - Mysz odpowiada bajtem potwierdzenia (0FAh) , uruchamia przesyłanie danych i resetuje swoje rejestry. Rozkaz ten wpływa jedynie na przesyłanie danych w trybie Stream.

  • 0F3h (Set Sample Rate) - Mysz odpowiada bajtem potwierdzenia (0FAh) i odbiera jeszcze jeden bajt od hosta. Mysz zapisuje ten bajt jako nową częstotliwość próbkowania. Po odebraniu częstotliwości próbkowania mysz ponownie wysyła bajt potwierdzenia i resetuje swoje rejestry. Poprawnymi wartościami częstotliwości są 10, 20, 40, 60, 70, 100 i 200 próbek/sek.

  • 0F2h (Get Device ID) - Mysz odpowiada bajtem potwierdzenia (0FAh) i przesyła swój kod device ID (00h dla standardowej myszy PS/2). Mysz powinna również zresetować swoje rejestry.

  • 0F0h (Set Remote Mode) - Mysz odpowiada bajtem potwierdzenia (0FAh), resetuje swoje rejestry i przechodzi w tryb remote.

  • 0EEh (Set Wrap Mode) - Mysz odpowiada bajtem potwierdzenia (0FAh), resetuje swoje rejestry i przechodzi w tryb wrap.

  • 0ECh (Reset Wrap Mode) - Mysz odpowiada bajtem potwierdzenia (0FAh), resetuje swoje rejestry i przechodzi w tryb, w którym była przed przełączeniem w tryb wrap.

  • 0EBh (Read Data) - Mysz odpowiada bajtem potwierdzenia (0FAh) i wysyła pakiet danych. Jest to jedyny sposób czytania danych w trybie remote. Po zakończonym powodzeniem wysłaniu pakietu mysz resetuje swoje rejestry.

  • 0EAh (Set Stream Mode) - Mysz odpowiada bajtem potwierdzenia (0FAh), resetuje swoje rejestry i przechodzi w tryb stream.

  • 0E9h (Status Request) - Mysz odpowiada bajtem potwierdzenia (0FAh) i wysyła następujący 3- bajtowy pakiet statusowy (następnie resetuje swoje rejestry):

-------------------------------------------------------
        |                       bajt 1                          |
         -------------------------------------------------------
        | bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
         -------------------------------------------------------
        |  0   | TRYB |  EN  | SKLW |  0   | LEWY |  ŚR  | PRW  |
         -------------------------------------------------------
        Bajt 2:
                Rozdzielczość

        Bajt 3:
                Częstotliwość próbkowania
 - LEWY, ŚR, PRW = 1 gdy odp. przycisk wciśnięty; 0 gdy nie wciśnięty.
 - SKLW          = 1 gdy skalowanie 2:1; 0 gdy skalowanie 1:1. (patrz rozkazy 0E7h, 0E6h)
 - EN            = 1 gdy przesyłanie danych włączone; 0 gdy przesyłanie danych zablokowane. (patrz rozkazy 0F5h i 0F4h)
 - TRYB          = 1 gdy mysz w trybie remote; 0 gdy mysz w trybie stream. (patrz rozkazy 0F0h i 0EAh)
  • 0E8h (Set Resolution) - Mysz odpowiada bajtem potwierdzenia (0FAh), odbiera jeszcze jeden bajt od hosta i ponownie wysyła bajt potwierdzenia (0FAh); następnie resetuje swoje rejestry. Bajt odebrany od hosta ustala rozdzielczość w sposób następujący:
--------------------------------
        | odebrany bajt | rozdzielczość  |
         --------------------------------
        |      000      |     1 /mm      |
        |      001      |     2 /mm      |
        |      002      |     4 /mm      |
        |      003      |     8 /mm      |
         --------------------------------
  • 0E7h (Set Scaling 2:1) - Mysz odpowiada bajtem potwierdzenia (0FAh) i ustawia skalowanie 2:1 (skalowanie zostało omówione wcześniej)

  • 0E6h (Set Scaling 1:1) - Mysz odpowiada bajtem potwierdzenia (0xFA) i ustawia skalowanie 1:1 (skalowanie zostało omówione wcześniej)

O rolkach słów kilka:

(INFORMACJE ZAWARTE W TEJ CZĘŚCI NIE ZOSTAŁY PRZEZE MNIE W ŻADEN SPOSÓB SPRAWDZONE, JEST TO JEDYNIE SWOBODNE TŁUMACZENIE FRAGMENTU [1])

Popularnym rozszerzeniem standardu PS/2 jest standard Microsoft Intellimouse. Zawiera on obsługę do 5 przycisków i trzech kierunków ruchu ( prawo-lewo, góra-dół i rolka ). Dodatkowe właściwości wymagają użycia 4 - bajtowego pakietu danych, zamiast 3 - bajtowego. Dopóki nie zostanie przełączona w rozszerzony tryb pracy, Mysz Intellimouse pracuje dokładnie jak standardowa mysz PS/2. Oznacza to, że niedostępne są dodatkowe przyciski ani rolka, a pakiety danych są 3 - bajtowe, zgodne z wcześniejszym opisem. Dzięki temu możliwe staje się zastosowanie myszy Intellimouse także na komputerach wyposażonych jedynie w standardowe sterowniki.

Tak więc mamy mysz Intellimouse, która zachowuje się dokładnie jak zwykła mysz PS/2: używa 3 - bajtowego pakietu danych, odpowiada na rozkazy tak samo, jak mysz standardowa, zwraca kod DeviceID 00h. Aby przełączyć mysz w tryb pracy rozszerzonej z rolką, należy użyć następującej sekwencji rozkazów:

Set sample rate (0F3h)  200
Set sample rate         100
Set sample rate         80

następnie wysyłamy rozkaz "Get device ID" (0F2h) i czekamy na odpowiedź. Jeżeli mamy mysz standardową (nie Intellimouse), wyśle nam ona DeviceID 00h. W tym przypadku wiemy, że mamy jedynie mysz standardową, nie wyposażoną w rolkę ani dodatkowe przyciski. Natomiast mysz Intellimouse wyśle nam DeviceID 03h. Wiemy teraz, że mamy do czynienia z myszą Intellimouse i od teraz należy spodziewać się 4 - bajtowych pakietów danych:

-------------------------------------------------------
|                         bajt 1                        |
|                                                       |
| bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
 .......................................................
| NA_Y | NA_X | ZN_Y | ZN_X |  1   | P_ŚR |  P_P | P_L  |
 -------------------------------------------------------
|                 bajt2 - przesunięcie X                |
 -------------------------------------------------------
|                 bajt3 - przesunięcie Y                |
 -------------------------------------------------------
|                 bajt4 - przesunięcie Z                |
 -------------------------------------------------------

Znaczenie bajtów 1 - 3 jak w myszy standardowej, natomiast przesunięcie Z jest liczbą U2 reprezentującą ruch rolki od czasu wysłania poprzedniego pakietu. Poprawnymi wartościami przesunięcia Z są liczby z zakresu -8 do +7. Oznacza to, że przesunięcie zapisane jest jedynie na 4 najmłodszych bitach, starsze 4 bity są jedynie bitami znaku.

Tryb rozszerzony z rolką i 5 przyciskami uruchamia sekwencja rozkazów:

Set sample rate 200
Set sample rate 200
Set sample rate 80

Następnie wysyłamy rozkaz "Get device ID" (0F2h) oczekując na odpowiedź. Mysz Intellimouse wyśle bajt 04h i od tej pory będzie używać 4 - bajtowego formatu pakietu danych:

-------------------------------------------------------
|                         bajt 1                        |
|                                                       |
| bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
 .......................................................
| NA_Y | NA_X | ZN_Y | ZN_X |  1   | P_ŚR |  P_P | P_L  |
 -------------------------------------------------------
|                 bajt2 - przesunięcie X                |
 -------------------------------------------------------
|                 bajt3 - przesunięcie Y                |
 -------------------------------------------------------
|                         bajt 4                        |
|                                                       |
| bit7 | bit6 | bit5 | bit4 | bit3 | bit2 | bit1 | bit0 |
 .......................................................
|   0  |   0  |  P_5 |  P_4 |  Z3  |  Z2  |  Z1  |  Z0  |
 -------------------------------------------------------
  • Bajty 1 - 3 jak w myszy standardowej,

  • P_5:

    • 1 - piąty przycisk myszy wciśnięty,
    • 0 - piąty przycisk myszy nie jest wciśnięty.
  • P_4:

    • 1 - czwarty przycisk myszy wciśnięty
    • 0 - czwarty przycisk myszy nie jest wciśnięty.
  • Z0-Z3 - liczba w kodzie U2 oznaczająca ruch rolki od czasu wysłania ostatniego pakietu danych. Poprawny zakres wartości: od -8 do +7.

Istnieją także myszy z dwiema rolkami: poziomą i pionową. One także używają opisanego powyżej formatu 4 - bajtowego pakietu danych. Gdy rolka pionowa jest przewijana w górę, licznik Z jest zwiększany o 1, a gdy jest przewijana w dół, licznik Z jest zmniejszany o 1. Jest to normalne działanie rolki. Jednakże, gdy przewijamy poziomą rolkę w prawo, licznik Z jest zwiększany o 2, natomiast gdy kręcimy nią w lewo - licznik Z zmniejsza się o 2. Wygląda to dosyć dziwacznie, ale działa tak długo, jak długo ułożenie rolek nie pozwala na poruszanie obydwoma jednocześnie. (Gdyby ktoś chciał oszukać komputer i poruszać dwiema rolkami równocześnie, rolka pozioma zostanie zignorowana.

TROCHĘ PRAKTYKI

( PODANE TU ROZWIĄZANIA NIE SĄ DOSKONAŁE ANI JEDYNE MOŻLIWE. ZAPRASZAM WSZYSTKICH DO PISANIA LEPSZYCH, BARDZIEJ WYDAJNYCH PROCEDUR)

Przydałoby się zebrać trochę podane informacje w jedną całość i napisać, jak właściwie obsługuje się tę całą mysz. Otóż do obsługi myszy będziemy potrzebowali następujących składników:

  • procedura obsługi przerwania myszy
  • procedura przechwytująca przerwanie myszy
  • procedura inicjalizująca mysz
  • procedura przywracająca pierwotną obsługę przerwania myszy.

Nie będę tu umieszczał kompletnych listingów procedur, jedynie trochę uwag pomocnych przy ich realizacji. Mam nadzieję, że będą one użyteczne i zaoszczędzą Czytelnikom tych nieprzespanych nocy, które ja spędziłem przy komputerze próbując dojść do tego, "o co właściwie tu chodzi".

1. Procedura obsługi przerwania myszy.

Po odpowiednim zaprogramowaniu układu 8042 ( patrz: procedura inicjalizująca mysz ) każdy bajt nadesłany przez mysz wywołuje przerwanie sprzętowe IRQ12. Przerwanie to należy przechwycić (patrz: procedura przechwytująca przerwanie myszy), aby jego obsługą zajmowała się procedura, która będzie właśnie opisywana. Zakładam tu, że mysz pracuje w trybie standardowym, więc wysyła 3 - bajtowe pakiety danych. Odpowiednie zmiany dla myszy Intellimouse Czytelnik wprowadzi sam.

Ponieważ przysłanie każdego z trzech bajtów pakietu wywołuje przerwanie, wewnątrz procedury musimy rozróżniać, który z nich właśnie przyszedł. Stworzymy w tym celu odpowiednią zmienną w pamięci.

db ktory 1

i zmienne dla każdego z trzech bajtów:

db bajt1
        db bajt2
        db bajt3

Będziemy też chcieli zapamiętać położenie kursora myszy, więc piszemy:

dw kursor_x
        dw kursor_y

Bardzo ważne jest odpowiednie zakończenie procedury obsługi przerwania: otóż przerwania sprzętowe w komputerze PC są generowane przez dwa połączone kaskadowo układy 8259 - mamy układ master i slave. Każda procedura obsługi przerwania na końcu musi posiadać instrukcje informujące układy 8259 o zakończeniu przerwania. Przerwanie myszy (IRQ12) generowane jest przez układ 8259 Slave (dotyczy to przerwań z zakresu IRQ8 - IRQ15). W przypadku tych przerwań informację o zakończeniu obsługi przerwania wysyłamy do [u]OBYDWU[/u] układów 8259. Robimy to wysyłając odpowiednie bajty do właściwych portów:

koniec:
        mov     al, 20H
        out     0a0H, al   ; do układu slave

        mov     al, 20H
        out     20H, al    ; do układu master
        
        pop ...            ; wyczyszczenie stosu
            ...
            
        iret

Dla przerwań z zakresu IRQ0 - IRQ7 bajt zakończenia wysyłamy tylko do układu master:

mov     al, 20H
        out     20H, al    ; do układu master

        pop ...            ; wyczyszczenie stosu
            ...

        iret

Przejdźmy do samej procedury. Na początku sprawdzamy, czy jest odebrany bajt (prawdopodobnie nie jest to konieczne, ale nie zawadzi):

nie_ma:
        in al, 64               ; czekaj na skompletowanie odbieranego bajtu w buforze
        and al, 00000001b
        jz nie_ma

i odczytujemy kolejny bajt pakietu:

in al, 60h              ; odebranie bajtu wysłanego przez mysz

Teraz sprawdzamy, który bajt pakietu odebraliśmy. W tym celu utworzyliśmy zmienną ktory. Inicjalnie zawiera ona wartość 1. Jeżeli w momencie odebrania bajtu ktory == 1, to wiemy, że odebraliśmy pierwszy bajt pakietu. Zapisujemy go do zmiennej bajt1, zwiększamy o 1 zmienną ktory i skaczemy do końca obsługi przerwania.

Podobnie, gdy ktory == 2. Zapisujemy odebrany bajt do zmiennej bajt2, zwiększamy zmienną ktory i skaczemy do końca obsługi przerwania.

Jeżeli ktory == 3, to wiemy, że odebraliśmy trzeci i ostatni bajt pakietu przesłanego przez mysz. W takim przypadku zapisujemy go do zmiennej bajt3, a do ktory wstawiamy 1. teraz jednak nie skaczemy do końca obsługi przerwania, gdyż mamy już kompletny pakiet danych myszy i możemy przystąpić do jego interpretacji.

Analizując odpowiednie bity bajtu1 znamy stan przycisków myszy i kierunek przesunięcia. Jeżeli mysz przesunęła się w prawo, do zmiennej kursor_x dodajemy bajt2. Jeżeli mysz przesunęła się do góry, od zmiennej kursor_y odejmujemy bajt3. Gdy mysz przesunęła się w lewo, robimy trochę inaczej:

  • od bajtu2 odejmujemy 1
  • negujemy bity bajtu2
  • tak przetworzony bajt2 odejmujemy od zmiennej kursor_x.

Podobnie przy przesunięciu do dołu:

  • od bajtu3 odejmujemy 1
  • negujemy bity bajtu3
  • tak przetworzony bajt3 dodajemy do zmiennej kursor_y.

Pozostaje już tylko sprawdzić, czy zmienne kursor_x i kursor_y nie wykroczyły poza wymiary naszego ekranu i w razie potrzeby odpowiednio je skorygować. Mając nowe położenie kursora i stan przycisków możemy wykorzystać je do sobie znanych celów i zakończyć obsługę przerwania.

2. Procedura przechwytująca przerwanie myszy

Przypuśćmy, że mamy segment dane, w którym mamy zmienne 16- bitowe offs i segm oznaczające offset i segment pierwotnej funkcji obsługi przerwania IRQ12

mov ax, SEG dane
        mov ds, ax

Tablica wektorów przerwań w pamięci rozpoczyna się począwszy od adresu 0000:0000

mov ax, 0
        mov es, ax

IRQ12 związany jest z wektorem 116 tablicy wektorów przerwań:

mov bx, es:[116*4]      ; zapamiętuje offset poprzedniego adresu
        mov ds:[offs], bx       ; procedury obsługi przerwania

        mov bx, es:[116*4+2]    ; zapamiętuje segment poprzedniego adresu
        mov ds:[segm], bx       ; procedury obsługi przerwania

Załóżmy, że nasza nowa procedura obsługi przerwania nazywa się PROC_IRQ12 i znajduje się w segmencie KOD:

mov bx, offset PROC_IRQ12

        cli                     ; w czasie zamiany adresów nie przyjmuj przerwań

        mov es:[116*4], bx      ; offset nowej procedury obsługi IRQ12

        mov bx, SEG KOD

        mov es:[116*4+2], bx    ; segment nowej procedury obsługi IRQ12

        sti                     ; odblokuj przyjmowanie przerwań

3. Procedura inicjalizująca mysz

Będą nam przydatne dwie niewielkie procedurki, które będą oczekiwały na możliwość zapisu lub odczytu z układu 8042 (patrz wcześniejszy opis układu):

;---- czeka na możliwość zapisu do 8042-------

czekaj_wr:
        push ax
pelne:
        in al, 64h               ; czekaj na możliwość wysłania bajtu do 8042
        and al, 00000010b
        jnz pelne

        pop ax
        ret
;---------------------------------------------
;----czeka na możliwość odczytu z 8042--------

czekaj_rd:
        push ax
puste:
        in al, 64h              ; czekaj skompletowanie bajtu w buforze
        and al, 00000001b
        jz puste

        pop ax
        ret

Podczas moich prób okazało się, że inicjalizacja myszy w ogóle nie chce działać, jeżeli na czas jej trwania nie zablokujemy klawiatury. Piszemy więc:

call czekaj_wr

        mov al, 0adh            ; blokada klawiatury
        out 64h, al

uaktywniamy interfejs myszy w układzie 8042:

call czekaj_wr

        mov al, 0a8h
        out 64h, al

Teraz już możemy przystąpić do komunikacji z myszą. Resetujemy ją:

call czekaj_wr

        mov al, 0d4h            ; następny bajt wysłany do 60h idzie do myszy
        out 64h, al

        call czekaj_wr

        mov al, 0ffh            ; RESET myszy
        out 60h, al

        call czekaj_rd          ; potwierdzenie przyjęcia rozkazu RESET
        in al, 60h

        call czekaj_rd          ; kod wyjściowy BAT
        in al, 60h
        
        call czekaj_rd          ; deviceID
        in al, 60h

Odbieranie bajtów potwierdzenia wysyłanych przez mysz może nie być konieczne. Zachęcam do eksperymentowania.

Możemy poustawiać parametry myszy, jak np. częstotliwość odświeżania:

call czekaj_wr

        mov al, 0d4h            ; następny bajt wysłany do 60h idzie do myszy
        out 64h, al

        call czekaj_wr

        mov al, 0f3h            ; ustawia częstotliwość odświeżania
        out 60h, al

        call czekaj_rd          ; potwierdzenie przyjęcia rozkazu
        in al, 60h

        call czekaj_wr

        mov al, 0d4h            ; następny bajt wysłany do 60h idzie do myszy
        out 64h, al

        call czekaj_wr

        mov al, 10              ; częstotliwość 10 / sek.
        out 60h, al
        
        call czekaj_rd          ; potwierdzenie przyjęcia bajtu
        in al, 60h

Po ustawieniu parametrów możemy odblokować przesyłanie danych przez mysz:

mov al, 0d4h            ; następny bajt wysłany do 60h idzie do myszy
        out 64h, al

        call czekaj_wr

        mov al, 0f4h            ; zgoda na wysyłanie danych przez mysz
        out 60h, al

        call czekaj_rd          ; potwierdzenie przyjęcia rozkazu
        in al, 60h

Nie zapomnijmy przywrócić klawiatury:

call czekaj_wr

        mov al, 0aeh            ; przywrócenie klawiatury
        out 64h, al

Pozostaje nam jeszcze zaprogramować układ 8042, aby mysz wywoływała przerwanie IRQ12:

call czekaj_wr

        mov al, 60h             ; zapisz słowo kontrolne w nast. przesłaniu do 60h
        out 64h, al
;........................

        call czekaj_wr

        mov al, 01000011b       ; opis poszczególnych bitów: patrz wcześniejsza
                                ; część opracowania
        out 60h, al             ; wpisanie słowa kontrolnego do 8042

W moim programie dodatkowo na czas inicjalizacji myszy zablokowałem przyjmowanie przerwań rozkazem CLI. Być może nie jest to wcale konieczne - ponownie zachęcam do eksperymentowania.

4. Procedura przywracająca pierwotną funkcję obsługi przerwania IRQ12:

Należy zapisać do wektora przerwań zapamiętane wcześniej wartości adresu pierwotnej procedury. Nie zapomnijmy zablokować na ten czas przyjmowania przerwań przy pomocy rozkazu CLI. Przed przywróceniem pierwotnej procedury obsługi przerwania warto też pamiętać o zablokowaniu interfejsu myszy:

mov al, 0A7h
out 64h, al

BIBLIOGRAFIA

Pisząc to opracowanie pełnymi garściami czerpałem z następujących wspaniałych Źródeł:

  • [1] http://panda.cs.ndsu.nodak.edu/%7Eachapwes/PICmicro/
  • [2] Piotr Metzger, "Anatomia PC", wyd. VIII, wydawnictwo Helion, 2003r.

 


Aby dodawać komentarze musisz być zalogowany!


Kontakt

Jeśli chcesz się z nami skontaktować napisz na adres: info(at)binboy.org lub odwiedź nasz profil na Facebooku!

O Nas

Serwis binboy.org to kopalnia wiedzy dla wszystkich z branży IT, w szczególności dla programistów i webmasterów. To duży zbiór kursów programowania, tutoriali, darmowych ebooków, setki kodów źródłowych itp.

Bądź w kontakcie

Panel użytkownika

Zaloguj się do panelu użytkownika.
Nie masz konta? Zarejestruj się!
Zapomniałeś hasła?