mirror of https://github.com/zxdos/zxuno.git
367 lines
20 KiB
VHDL
367 lines
20 KiB
VHDL
library ieee;
|
||
use ieee.std_logic_1164.all;
|
||
use ieee.numeric_std.all;
|
||
library work;
|
||
use work.mapa_es.all;
|
||
|
||
entity ps2k is port (
|
||
clk : in std_logic;
|
||
ps2clk : in std_logic;
|
||
ps2data : in std_logic;
|
||
rows : in std_logic_vector(7 downto 0);
|
||
cols : out std_logic_vector(4 downto 0);
|
||
joy : out std_logic_vector(4 downto 0);
|
||
scancode: out std_logic_vector(7 downto 0);
|
||
rst : out std_logic;
|
||
nmi : out std_logic;
|
||
mrst : out std_logic);
|
||
end ps2k;
|
||
|
||
architecture behavioral of ps2k is
|
||
|
||
type key_matrix is array (7 downto 0) of std_logic_vector(4 downto 0);
|
||
signal keys : key_matrix;
|
||
signal pressed : std_logic;
|
||
signal isctrl : std_logic;
|
||
signal isshift : std_logic;
|
||
signal isalt : std_logic;
|
||
signal isextend : std_logic;
|
||
signal lastclk : std_logic_vector(4 downto 0);
|
||
signal bit_count : unsigned (3 downto 0);
|
||
signal shiftreg : std_logic_vector(8 downto 0);
|
||
signal parity : std_logic;
|
||
|
||
begin
|
||
process (clk)
|
||
begin
|
||
if rising_edge(clk) then
|
||
rst <= '1';
|
||
nmi <= '1';
|
||
mrst <= '1';
|
||
lastclk <= lastclk(3 downto 0) & ps2clk;
|
||
if lastclk="11100" and ps2clk='0' then -- detector de flanco de bajada de PS2CLK
|
||
if bit_count=0 then
|
||
parity <= '0';
|
||
if ps2data='0' then
|
||
bit_count <= bit_count + 1;
|
||
end if;
|
||
else
|
||
if bit_count<10 then
|
||
bit_count <= bit_count + 1;
|
||
shiftreg <= ps2data & shiftreg(8 downto 1);
|
||
parity <= parity xor ps2data;
|
||
elsif ps2data='1' then
|
||
bit_count <= (others => '0');
|
||
if parity = '1' then -- nueva pulsacion completa en shiftreg.
|
||
pressed <= '1';
|
||
scancode <= shiftreg(7 downto 0);
|
||
if isextend='1' and shiftreg(7 downto 0)=KEY_RELEASED then -- procesar la secuencia E0 F0 key
|
||
isextend <= '1';
|
||
else
|
||
isextend <= '0';
|
||
end if;
|
||
case shiftreg(7 downto 0) is -- detectar secuencias especiales: tecla soltada y tecla extendida
|
||
when KEY_RELEASED => pressed <= '0';
|
||
when KEY_EXTENDED => isextend <= '1';
|
||
when others => null;
|
||
end case;
|
||
if isextend='0' then -- teclas no extendidas
|
||
case shiftreg(7 downto 0) is
|
||
when KEY_LSHIFT |
|
||
KEY_RSHIFT => isshift <= pressed;
|
||
when KEY_ALTI => isalt <= pressed;
|
||
joy(4) <= pressed; -- dato entregado por el joystick
|
||
when KEY_CTRLI => keys(0)(0) <= pressed; -- Ctrl izquierdo: (CAPS SHIFT)
|
||
isctrl <= pressed;
|
||
joy(4) <= pressed; -- dato entregado por el joystick
|
||
when KEY_Z => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(0)(1) <= pressed; -- Z
|
||
when KEY_X => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(0)(2) <= pressed; -- X
|
||
when KEY_C => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(0)(3) <= pressed; -- C
|
||
when KEY_V => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(0)(4) <= pressed; -- V
|
||
when KEY_A => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(1)(0) <= pressed; -- A
|
||
when KEY_S => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(1)(1) <= pressed; -- S
|
||
when KEY_D => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(1)(2) <= pressed; -- D
|
||
when KEY_F => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(1)(3) <= pressed; -- F
|
||
when KEY_G => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(1)(4) <= pressed; -- G
|
||
when KEY_Q => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(2)(0) <= pressed; -- Q
|
||
when KEY_W => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(2)(1) <= pressed; -- W
|
||
when KEY_E => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(2)(2) <= pressed; -- E
|
||
when KEY_R => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(2)(3) <= pressed; -- R
|
||
when KEY_T => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(2)(4) <= pressed; -- T
|
||
when KEY_1 => if isshift='0' then
|
||
keys(3)(0) <= pressed; -- 1
|
||
else
|
||
keys(7)(1) <= pressed;
|
||
keys(3)(0) <= pressed; -- !
|
||
end if;
|
||
when KEY_2 => if isshift='0' then
|
||
keys(3)(1) <= pressed; -- 2
|
||
else
|
||
keys(7)(1) <= pressed;
|
||
keys(5)(0) <= pressed; -- "
|
||
end if;
|
||
when KEY_3 => if isshift='0' then
|
||
keys(3)(2) <= pressed; -- 3
|
||
else
|
||
keys(7)(1) <= pressed;
|
||
keys(3)(2) <= pressed; -- #
|
||
end if;
|
||
when KEY_4 => if isshift='0' then
|
||
keys(3)(3) <= pressed; -- 4
|
||
else
|
||
keys(7)(1) <= pressed;
|
||
keys(3)(3) <= pressed; -- $
|
||
end if;
|
||
when KEY_5 => if isshift='0' then
|
||
keys(3)(4) <= pressed; -- 5
|
||
else
|
||
keys(7)(1) <= pressed;
|
||
keys(3)(4) <= pressed; -- $
|
||
end if;
|
||
when KEY_0 => if isshift='0' then
|
||
keys(4)(0) <= pressed; -- 0
|
||
else
|
||
keys(7)(1) <= pressed;
|
||
keys(6)(1) <= pressed; -- =
|
||
end if;
|
||
when KEY_9 => if isshift='0' then
|
||
keys(4)(1) <= pressed; -- 9
|
||
else
|
||
keys(7)(1) <= pressed;
|
||
keys(4)(1) <= pressed; -- )
|
||
end if;
|
||
when KEY_8 => if isshift='0' then
|
||
keys(4)(2) <= pressed; -- 8
|
||
else
|
||
keys(7)(1) <= pressed;
|
||
keys(4)(2) <= pressed; -- (
|
||
end if;
|
||
when KEY_7 => if isshift='0' then
|
||
keys(4)(3) <= pressed; -- 7
|
||
else
|
||
keys(7)(1) <= pressed;
|
||
keys(0)(4) <= pressed; -- /
|
||
end if;
|
||
when KEY_6 => if isshift='0' then
|
||
keys(4)(4) <= pressed; -- 6
|
||
else
|
||
keys(7)(1) <= pressed;
|
||
keys(4)(4) <= pressed; -- &
|
||
end if;
|
||
when KEY_P => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(5)(0) <= pressed; -- P
|
||
when KEY_O => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(5)(1) <= pressed; -- O
|
||
when KEY_I => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(5)(2) <= pressed; -- I
|
||
when KEY_U => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(5)(3) <= pressed; -- U
|
||
when KEY_Y => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(5)(4) <= pressed; -- Y
|
||
when KEY_ENTER => keys(6)(0) <= pressed; -- ENTER
|
||
when KEY_L => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(6)(1) <= pressed; -- L
|
||
when KEY_K => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(6)(2) <= pressed; -- K
|
||
when KEY_J => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(6)(3) <= pressed; -- J
|
||
when KEY_H => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(6)(4) <= pressed; -- H
|
||
when KEY_SPACE => keys(7)(0) <= pressed; -- SPACE
|
||
when KEY_M => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(7)(2) <= pressed; -- M
|
||
when KEY_N => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(7)(3) <= pressed; -- N
|
||
when KEY_B => if isshift='1' then
|
||
keys(0)(0) <= pressed;
|
||
end if;
|
||
keys(7)(4) <= pressed; -- B
|
||
when KEY_BKSP => keys(0)(0) <= pressed; -- Backspace (Caps 0)
|
||
keys(4)(0) <= pressed;
|
||
if isctrl='1' and isalt='1' then
|
||
mrst <= '0';
|
||
end if;
|
||
when KEY_CPSLK => keys(0)(0) <= pressed; -- Caps lock (Caps 2)
|
||
keys(3)(1) <= pressed;
|
||
when KEY_ESC => keys(0)(0) <= pressed; -- Break (Caps Space)
|
||
keys(7)(0) <= pressed;
|
||
when KEY_F2 => keys(0)(0) <= pressed;
|
||
keys(3)(0) <= pressed; -- EDIT
|
||
when KEY_BL => keys(7)(1) <= pressed;
|
||
keys(1)(2) <= pressed; -- usado con EXT, da \
|
||
when KEY_APOS => keys(7)(1) <= pressed;
|
||
if isshift='0' then
|
||
keys(4)(3) <= pressed; -- apostrofe '
|
||
else
|
||
keys(0)(3) <= pressed; -- tecla ?
|
||
end if;
|
||
when KEY_TAB => keys(0)(0) <= pressed;
|
||
keys(7)(1) <= pressed; -- modo extendido
|
||
when KEY_CORCHA => keys(7)(1) <= pressed;
|
||
keys(6)(4) <= pressed; -- simbolo ^
|
||
when KEY_CORCHC => keys(7)(1) <= pressed;
|
||
if isshift='0' then
|
||
keys(6)(2) <= pressed; -- simbolo +
|
||
else
|
||
keys(7)(4) <= pressed; -- simbolo *
|
||
end if;
|
||
when KEY_LLAVA => keys(7)(1) <= pressed;
|
||
keys(1)(3) <= pressed; -- llave abierta, con EXT
|
||
when KEY_LLAVC => keys(7)(1) <= pressed;
|
||
keys(5)(0) <= pressed; -- copyright
|
||
when KEY_LT => keys(7)(1) <= pressed;
|
||
if isshift='0' then
|
||
keys(2)(3) <= pressed; -- s<>mbolo <
|
||
else
|
||
keys(2)(4) <= pressed; -- s<>mbolo >
|
||
end if;
|
||
when KEY_COMA => keys(7)(1) <= pressed;
|
||
if isshift='0' then
|
||
keys(7)(3) <= pressed; -- s<>mbolo ,
|
||
else
|
||
keys(5)(1) <= pressed; -- s<>mbolo ;
|
||
end if;
|
||
when KEY_PUNTO => keys(7)(1) <= pressed;
|
||
if isshift='0' then
|
||
keys(7)(2) <= pressed; -- s<>mbolo .
|
||
else
|
||
keys(0)(1) <= pressed; -- s<>mbolo :
|
||
end if;
|
||
when KEY_MENOS => keys(7)(1) <= pressed;
|
||
if isshift='0' then
|
||
keys(6)(3) <= pressed; -- s<>mbolo -
|
||
else
|
||
keys(4)(0) <= pressed; -- tecla _ (guion bajo)
|
||
end if;
|
||
when KEY_F5 => if isctrl='1' and isalt='1' then
|
||
nmi <= '0'; -- NMI
|
||
end if;
|
||
when KEY_F10 => keys(0)(0) <= pressed;
|
||
keys(4)(1) <= pressed; -- Modo gr<67>fico, para pulsar F10 en la BIOS
|
||
when KEY_KPPUNTO => if isctrl='1' and isalt='1' then
|
||
rst <= '0'; -- reset al hacer ctrl-alt-supr
|
||
end if;
|
||
when KEY_KP4 => joy(1) <= pressed; -- dato entregado por el joystick: izquierda
|
||
when KEY_KP6 => joy(0) <= pressed; -- dato entregado por el joystick: derecha
|
||
when KEY_KP8 => joy(3) <= pressed; -- dato entregado por el joystick: arriba
|
||
when KEY_KP5 => joy(2) <= pressed; -- dato entregado por el joystick: abajo
|
||
when KEY_KP7 => joy(1) <= pressed;
|
||
joy(3) <= pressed; -- dato entregado por el joystick: arriba izquierda
|
||
when KEY_KP9 => joy(0) <= pressed;
|
||
joy(3) <= pressed; -- dato entregado por el joystick: arriba derecha
|
||
when KEY_KP1 => joy(1) <= pressed;
|
||
joy(2) <= pressed; -- dato entregado por el joystick: abajo izquierda
|
||
when KEY_KP3 => joy(0) <= pressed;
|
||
joy(2) <= pressed; -- dato entregado por el joystick: abajo derecha
|
||
when others=> null;
|
||
end case;
|
||
else -- process extended keys
|
||
case shiftreg(7 downto 0) is
|
||
when KEY_CTRLD => keys(7)(1) <= pressed; -- Ctrl derecho -> symbol shift
|
||
isctrl <= pressed;
|
||
joy(4) <= pressed; -- dato entregado por el joystick
|
||
when KEY_ALTGR => keys(0)(0) <= pressed;
|
||
keys(4)(1) <= pressed; -- Modo gr<67>fico
|
||
isalt <= '1';
|
||
joy(4) <= pressed; -- dato entregado por el joystick
|
||
when KEY_LEFT => keys(0)(0) <= pressed; -- Left (Caps 5)
|
||
keys(3)(4) <= pressed;
|
||
when KEY_DOWN => keys(0)(0) <= pressed; -- Down (Caps 6)
|
||
keys(4)(4) <= pressed;
|
||
when KEY_UP => keys(0)(0) <= pressed; -- Up (Caps 7)
|
||
keys(4)(3) <= pressed;
|
||
when KEY_RIGHT => keys(0)(0) <= pressed; -- Right (Caps 8)
|
||
keys(4)(2) <= pressed;
|
||
when KEY_SUP => if isctrl='1' and isalt='1' then
|
||
rst <= '0'; -- reset al hacer ctrl-alt-supr
|
||
end if;
|
||
when others => null;
|
||
end case;
|
||
end if;
|
||
end if;
|
||
else
|
||
bit_count <= (others => '0');
|
||
end if;
|
||
end if;
|
||
end if;
|
||
end if;
|
||
end process;
|
||
|
||
process (keys, rows)
|
||
variable tmp: std_logic;
|
||
begin
|
||
for i in 0 to 4 loop
|
||
tmp:= '0';
|
||
for j in 0 to 7 loop
|
||
tmp:= tmp or (keys(j)(i) and not rows(j));
|
||
end loop;
|
||
cols(i) <= not tmp;
|
||
end loop;
|
||
end process;
|
||
|
||
end architecture;
|