Apple_II_vhdl/src/PS2/KeyboardMapper.vhd

166 lines
4.0 KiB
VHDL

-- (C) Rui T. Sousa from http://sweet.ua.pt/~a16360
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity KeyboardMapper is
port (
Clock : in std_logic;
Reset : in std_logic;
PS2Busy : in std_logic;
PS2Error : in std_logic;
DataReady : in std_logic;
DataByte : in std_logic_vector(7 downto 0);
Send : out std_logic;
Command : out std_logic_vector(7 downto 0);
CodeReady : out std_logic;
ScanCode : out std_logic_vector(9 downto 0)
);
end KeyboardMapper;
-- ScanCode(9) = 1 -> Extended
-- = 0 -> Regular (Not Extended)
-- ScanCode(8) = 1 -> Break
-- = 0 -> Make
-- ScanCode(7 downto 0) -> Key Code
architecture Behavioral of KeyboardMapper is
type StateType is (ResetKbd, ResetAck, WaitForBAT, Start, Extended, ExtendedBreak, Break, LEDs, CheckAck);
signal State : StateType := Start;
signal CapsLock : STD_LOGIC;
signal NumLock : STD_LOGIC;
signal ScrollLock : STD_LOGIC;
-- signal PauseON : STD_LOGIC;
begin
process(Reset, PS2Error, Clock)
begin
if Reset = '1' or PS2Error = '1' then
CapsLock <= '0';
NumLock <= '0';
ScrollLock <= '0';
-- PauseON <= '0';
Send <= '0';
Command <= (others => '0');
CodeReady <= '0';
ScanCode <= (others => '0');
State <= Start;
elsif rising_edge(Clock) then
case State is
when ResetKbd =>
if PS2Busy = '0' then
Send <= '1';
Command <= x"FF";
State <= ResetAck;
end if;
when ResetAck =>
Send <= '0';
if Dataready = '1' then
if DataByte = x"FA" then
State <= WaitForBAT;
else
State <= ResetKbd;
end if;
end if;
when WaitForBAT =>
if DataReady = '1' then
if DataByte = x"AA" then -- BAT(self test) completed successfully
State <= Start;
else
State <= ResetKbd;
end if;
end if;
when Start =>
CodeReady <= '0';
if DataReady = '1' then
case DataByte is
when x"E0" =>
State <= Extended;
when x"F0" =>
State <= Break;
when x"FA" => --Acknowledge
null;
when x"AA" =>
State <= Start;
when x"FC" =>
State <= ResetKbd;
when x"58" =>
Send <= '1';
Command <= x"ED";
CapsLock <= not CapsLock;
ScanCode <= "00" & DataByte;
CodeReady <= '1';
State <= LEDs;
when x"77" =>
Send <= '1';
Command <= x"ED";
NumLock <= not NumLock;
ScanCode <= "00" & DataByte;
CodeReady <= '1';
State <= LEDs;
when x"7E" =>
Send <= '1';
Command <= x"ED";
ScrollLock <= not ScrollLock;
ScanCode <= "00" & DataByte;
CodeReady <= '1';
State <= LEDs;
when others =>
ScanCode <= "00" & DataByte;
CodeReady <= '1';
State <= Start;
end case;
end if;
when Extended =>
if DataReady = '1' then
if DataByte = x"F0" then
State <= ExtendedBreak;
else
ScanCode <= "10" & DataByte;
CodeReady <= '1';
State <= Start;
end if;
end if;
when ExtendedBreak =>
if DataReady = '1' then
ScanCode <= "11" & DataByte;
CodeReady <= '1';
State <= Start;
end if;
when Break =>
if DataReady = '1' then
ScanCode <= "01" & DataByte;
CodeReady <= '1';
State <= Start;
end if;
when LEDs =>
Send <= '0';
CodeReady <= '0';
if Dataready = '1' then
if DataByte = x"FA" then
Send <= '1';
Command <= "00000" & CapsLock & NumLock & ScrollLock;
State <= CheckAck;
elsif DataByte = x"FE" then
Send <= '1';
end if;
end if;
when CheckAck =>
Send <= '0';
if Dataready = '1' then
if DataByte = x"FA" then
State <= Start;
elsif DataByte = x"FE" then
Send <= '1';
end if;
end if;
when others => null;
end case;
end if;
end process;
end Behavioral;