Skocz do zawartości

Pomocna odpowiedź

Napisano
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity KEY_S1 is
    Port ( Clk : in  STD_LOGIC;
		   Reset : in  STD_LOGIC;
           PS2_D : inout  STD_LOGIC;
           PS2_C : inout  STD_LOGIC;
           Kbwe : out  STD_LOGIC;
           KbD : out  STD_LOGIC_VECTOR (7 downto 0)
			  );
end KEY_S1;

architecture Behavioral of KEY_S1 is

	signal D : std_logic_vector (9 downto 0) ;
	signal Din : std_logic_vector (7 downto 0) ;
	signal Cnt : std_logic_vector (7 downto 0) ;
	signal Cnt1 : std_logic_vector (13 downto 0) ;
	signal Clk1 : std_logic;
	signal KbWE : std_logic;
	
	signal PS2_Cin : std_logic;
	signal PS2_Cout : std_logic;
	signal PS2_Dout : std_logic;

	signal Brake : std_logic;
	signal Caps : std_logic;
	signal Num : std_logic;
	signal Scroll : std_logic;
	signal Ack : std_logic;
	signal ParityGen : std_logic_vector (6 downto 0);
	signal Parity : std_logic;
	
   type PS2State_type is (idle, datain, sel, we, we1, rts, rts1, rts2, dataout); 
   signal PS2State : PS2State_type;


begin
		
		process(Clk, PS2_C)								--oczekiwanie na stabilny sygnał zegarowy z klawiatury
		begin
			if PS2_C = '1' then
				Cnt <= (others => '0');
				PS2_Cin <= '1';
			else
				if Clk'event and Clk = '0' then
					if PS2_C = '0' then
						if Cnt = "11111111" then
							PS2_Cin <= '0';
						else
							Cnt <= Cnt + 1;
						end if;
					end if;
				end if;
			end if;
		end process;
		
		with PS2State select
			Clk1 <= Clk when rts,
					  Clk when rts1,
					  Clk when sel,
					  Clk when we,
					  Clk when we1,
					  PS2_Cin when others;
		
		with PS2State select
	  PS2_Dout <= '0' when rts1,
					  '0' when rts2,
					  D(0) when dataout,
					  '1' when others;
		
		with PS2State select
	  PS2_Cout <= '0' when rts,
					  '0' when rts1,
					  '1' when others;
		
		process(Clk1, Reset, PS2State, PS2_D)		--wysłanie, odbieranie danych z klawiatury w maszynie stanów
		begin
			if Reset = '0' then
				D <= "1000000000";
				Din <= "00000000";
				KbD <= "00000000";
				KbWE <= '0';
				Cnt1 <= (others => '0');
				PS2State <= idle;
			else
				if Clk1'event and Clk1 = '0' then
					case PS2State is
					
					when idle =>
								D <= "1000000000";
								PS2State <= datain;
					
					when datain =>
							if D(0) = '1' then
								D <= "1000000000";
								Din <= D(8 downto 1);
								PS2State <= sel;
							else
								D <= PS2_D & D(9 downto 1);
							end if;
					
					when sel =>
							if Din = X"F0" then
								Brake <= '1';
								PS2State <= idle;
						elsif ((Din = X"58") and (Brake <= '0') and (Ack = '0')) then
								Din <= X"ED";
								Caps <= not Caps;
								PS2State <= rts;
						elsif ((Din = X"77") and (Brake <= '0') and (Ack = '0')) then
								Din <= X"ED";
								Num <= not Num;
								PS2State <= rts;
						elsif ((Din = X"7E") and (Brake <= '0') and (Ack = '0')) then
								Din <= X"ED";
								Scroll <= not Scroll;
								PS2State <= rts;
						elsif ((Din = X"FA") and (Brake = '0') and (Ack = '0')) then
								Din <= "00000" & Caps & Num & Scroll;
								Ack <= '1';
								PS2State <= rts;
						elsif Brake = '1' then
								Brake <= '0';
								PS2State <= idle;
						elsif Ack = '1' then
								Ack <= '0';
								PS2State <= idle;
							else
								KbD <= Din;
								PS2State <= we;
							end if;
					
					when we =>
								KbWE <= '1';
								PS2State <= we1;
					
					when we1 =>
								KbWE <= '0';
								PS2State <= idle;
					
					when rts =>	 --reqest to send
							if Cnt1 = "11111100000000" then
								Cnt1 <= (others => '0');
								PS2State <= rts1;
							else
								Cnt1 <= Cnt1 + 1;
							end if;
					
					when rts1 =>	 --reqest to send
							if Cnt1 = "00000100000000" then
								Cnt1 <= (others => '0');
								PS2State <= rts2;
							else
								Cnt1 <= Cnt1 + 1;
							end if;
							
					when rts2 =>	 --reqest to send
								D <= '1' & Parity & Din;
								PS2State <= dataout;
							
					when dataout => --przesył danych do klawiatury
							if D = "0000000001" then
								PS2State <= idle;
							else
								D <= '0' & D(9 downto 1);
							end if;
							
					end case;
				end if;
			end if;
		end process;
		
		ParityGen(0) <= Din(0) xor Din(1);			--generator parztstości
		ParityGen(1) <= Din(2) xor Din(3);
		ParityGen(2) <= Din(4) xor Din(5);
		ParityGen(3) <= Din(6) xor Din(7);
		ParityGen(4) <= ParityGen(0) xor ParityGen(1);
		ParityGen(5) <= ParityGen(2) xor ParityGen(3);
		ParityGen(6) <= ParityGen(4) xor ParityGen(5);
		Parity <= not ParityGen(6);
		
		PS2_C <= 'Z' when PS2_Cout = '1' else '0';	--zmiana portów komunikacyjnych klawiatury z wejściowych na wyjściowe
		PS2_D <= 'Z' when PS2_Dout = '1' else '0';

end Behavioral;

Witam.

Załączam kod programu obsługującego klawiaturę ps2. Kod pisany dla układu z generatorem 100MHz.

Sygnał ack wysyłany z klawiatury jest nieodczytywany, sygnał brake wysyłany z klawiatury jest ignorowany.

Klawiatura po włączeniu wysyła kod X"AA" i ustawia się w tryb scan-code-set 2. (ustawienia fabryczne)

Można wiele ustawień zmienić lecz trzeba pamiętać że zmiana scan-code-set na 1 lub 3 zmienia także kody podpisane pod przyciski.

Naciśnięcie przycisków ( caps, num, scroll ) jest odczytywane i zostaje wysłany kod który zapala lub gasi naprzemiennie odpowiednie kontrolki na klawiaturze.

Dane z pozostałych klawiszy są wysyłane do wyjścia KbD i potwierdzane sygnałem KbWE (stan wysoki) trwającym jeden cykl zegara.

Do wyjścia podawany jest kod make, a brake jest ignorowany. Niektóre przyciski mają podwójny kod zaczynający się X"E0" a przycisk pause zaczyna się jako jedyny X"E1", X"E0" ...(scan-code-set 2).

Może się komuś przyda...

Pozdrawiam

 

  • Lubię! 1
(edytowany)

Signal KbWE : std_logic  trzeba usunąć. Zapomniałem

Edytowano przez kroszkanorber
Błąd w zapisie
  • Lubię! 1
  • 4 tygodnie później...

@FlyingDutch

Hej.

Czy próbowałeś uruchomić mysz ps2 na układzie FPGA?

Po podaniu kodu do zezwolenia na przesył danych x"f4" brak okcetptacji myszy. Wysyła kod x"fc" zamiast x"fa". Tylko kod reset x"ff" jest akceptowany i mysz wysyła w trzecim kodzie poprawny identyfikator. Reszta kodów nie działa. Nie mam pojęcia jak ten temat podjąć...

W wolnej chwili wstawię kod programu i otworzę nowy temat.

  • Lubię! 1

@FlyingDutch Hej.

Udało mi się uruchomić wysyłanie pakietów danych z myszy i odczytuje je na wyświetlaczu LED 7 segmentowym. W internecie różne rzeczy piszą i trzeba samemu próbować. Jak uda mi się poprawnie rozkodować dane to wstawię post. Kod który wstawiłem na początku działa na klawiaturze lecz mysz ma większe wymagania co do przebiegu sygnałów CLK i dat . 

Pozdrawiam

  • Lubię! 1
  • 2 tygodnie później...

Witam.

Przedstawiony kod ps2_keyboard ma pewne wady.

1 kod nie posiada weryfikacji danych przychodzących z klawiatury pod względem błędów transmisji. ( Nigdy nie wystąpiły ze strony urządzenia, ale mogłoby się zdarzyć...)

2 gdy użyć chcemy kontrolera zewnętrznego który ma za zadanie inicjować urządzenie ps2 musimy przepisać kod co jest trudniejsze jak napisać go od początku. Rozwiązaniem jest kod który podałem w ps2_mouse część 2. Kod ten składa się z trzech czesci, a część tx służy do wysłania polecenia do urządzenia ps2.

Kod ps2 który opisałem w 2 części jest moim zdaniem uniwersalny pod względem obsługi urządzeń. Działa równie dobrze z myszą i klawiaturą ps2.

Pozdrawiam 

  • Lubię! 1

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...