logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Obsługa PS/2 w ATMega328 - problem z odczytem stanu klawiatury

andrzejlisek 23 Kwi 2019 01:41 558 1
REKLAMA
  • #1 17921027
    andrzejlisek
    Poziom 31  
    Chciałbym zrobić symulację naciśnięć klawiszy na klawiaturze PS/2 wykorzystując ATMega328 z rezonatorem kwarcowym 16MHz i interfejs PS/2 na USB.

    Posiłkowałem się tym opisem PS/2.

    https://www.avrfreaks.net/sites/default/files/PS2%20Keyboard.pdf
    Z opisu wynika, że urządzenie PS/2 (wspomniana klawiatura) musi być w każdej chwili przygotowane do odbioru danych z komputera, nawet, jak jest w trakcie transmisji do komputera.

    Dodatkowo znalazłem https://bohr.wlu.ca/nznotinas/pc319/lectures/PS2_mouse.pdf co prawda opisuje myszkę, ale zakładam, że ogólne zasady komunikacji są te same.

    Jeśli chodzi o komunikację w ATMega328, to pomyślałem, że najprościej stan niski zrealizować poprzez wymuszenie stanu niskiego, a stan wysoki zrealizować poprzez stan wysokiej impedancji z podciągnięciem do 5V (wtedy można wychwycić spadek do stanu niskiego z inicjatywy komputera).

    Linia zegara PS/2 jest podłączona do B5, a linia danych do B4. Obsługę zrobiłem w przerwaniu z timera, które jest wyzwalane z częstotliwością 50kHz, czyli na jeden cykl zegara z częstotliwością 12,5kHz przypadają 4 wyzwolenia przerwania, co umożliwia realizację działań nie tylko przy narastającym i opadającym zboczu sygnału zegara, ale również w połowie czasu trwania jednego ze stanów. Zegar ma docelowo służyć też do innych celów, dlatego nie robię tego przez przerwanie wyzwalane przez opadające zbocze.

    Jestem na etapie odczytu. Program działa prawie dobrze, ale jest jeszcze jakiś problem, bo jak komputer ma coś wysłać (na przykład wciskam Num lock i Caps lock na klawiaturze USB), to interfejs PS/2 wyłącza się na ok. sekundę i włącza z powrotem (system Windows odtwarza te same dźwięki, jak przy podłączaniu i odłączaniu pendrive). Mam podłączony tekstowy wyświetlacz LCD i zaraz po podłączeniu wyświetla "A*A*", po ok. sekundzie restartuje się interfejs i dopisuje się "A*A". Jak wcisną Caps lock, to dopisuje się "*", a po restarcie PS/2 dopisuje się "A*A". Z tego wynika, że program wisi w stanie 2 jeśli chodzi o odbiór i czeka na spełnienie się warunku "((PS2Clock()) && (!PS2Data(10)))". W stanie spoczynkowym, spełnienie tego warunku nigdy nie nastąpi, dopóki komputer czegoś nie wyśle, a i tak proces odbioru nie będzie przebiegać prawidłowo. Jeszcze nie próbowałem dekodować danych, bo uznałem, że nie ma to sensu, skoro sam odbiór nie działa dobrze.

    Zamieszczam kod programu, usunąłem fragmenty nieistotne z punktu widzenia opisanego problemu.

    Moim zdaniem pewnie jest jakiś drobiazg, tylko gdzie? Transmisja jest opisana na stronie 6 dokumentu PDF i na slajdzie 9 z drugiego linku.

    Wygląda na to, jakby wysyłanie stanu niskiego na wyjściu zegarowym powodowało te problemy, ponieważ to samo się działo, jak nie wysyłałem ACK (ujemny impuls na linii danych po odebraniu wszystkich bitów). Może ja robię to nieprawidłowo?

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Dodano po 19 [godziny] 7 [minuty]:

    To, że założyłem nowy temat i napisałem zapytanie wcale nie znaczy, że zaprzestałem samodzielnych działań.

    Znalazłem jeszcze to: http://www.kbdbabel.org/signaling/index.html i opis transmisji wydaje się być taki sam, jak ten w PDF.
    Dodatkowo, poszukałem znaczenia komunikatów przychodzących:
    http://pcbheaven.com/wikipages/The_PS2_protocol/?p=1

    Przerobiłem swój program tak, że realizuje on koncepcję podobną do automatu skończonego, czyli jest pewien zbiór możliwych stanów i dla każdego jest zdefiniowane bezwarunkowe przejście do następnego stanu bądź są zapisane warunki przejścia do innego stanu, a przy braku spełnienia warunków pozostaje w tym samym stanie. Do tego, dorobiłem wyświetlanie komunikatów danych.

    Teraz, podczas pracy wyświetla się na przemian 1 i 4, czyli program balansuje między stanami 0 i 1, czyli tak, jakby linia CLK cały czas zmieniała swój stan. W rzeczywistości na linii CLK jest przebieg prostokątny z wypełnieniem 50Hz o okresie ok. 17ms i wypełnieniu 50%, co zgadzałoby się z działaniem programu.

    Jak podczas pracy naciskam Num lock lub Caps lock to program odbiera bajt 0xED, interfejs USB się wyłącza, po sekundzie się włącza i odbiera bajt 0xF2, podobnie jest zaraz po podłączeniu interfejsu do komputera. Według dokumentacji, za bajtem 0xED powinien przyjść jeszcze jeden bajt, którego wartość zależy od stanu diod klawiatury i z tym jest problem. Bajt 0xF2 jest komunikatem jednobajtowym i nie wymaga odpowiedzi, jednak klawiatura może odpowiedzieć, ale nie musi (wtedy jest traktowana jako XT).

    Zamieszczam aktualny kod, obsługa wyświetlacza jest pominięta, żeby nie zaciemniać kodu.

    Tu jeszcze jest coś nie tak, przede wszystkim jest problem z odbiorem komunikatów dwubajtowych. Jak to powinno wyglądać?

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • REKLAMA
  • #2 17931819
    andrzejlisek
    Poziom 31  
    Problem udało się rozwiązać samodzielnie. Po odebraniu każdego bajtu należy wysłać bajt 0xFA, niewysłanie bajtu 0xFA powodował te problemy.
REKLAMA