TI-99/4AにPS/2日本語キーボードをつなぐ

TI-99/4A本体を手に入れても、キーボードが故障していることが多いです。

情報収集していると「Creating a complete UK101 on a low-cost FPGA board」を見つけました。

http://searle.hostei.com/grant/uk101FPGA/index.html

PS/2をキーボードマトリクスに変換しているVHDLがあるので利用させて頂きます。

http://www.geocities.jp/parallel_computer_inc/develop.html

TI-99/4A側は15ピンコネクタなのですが、以下のピンアサインのようです。

http://www.mainbyte.com/ti99/keyboard/keyboard.html

TI-99/4A    A-C4E6
PIN 1 INT5   PIN_30
PIN 2 INT6   PIN_28
PIN 3 INT8   PIN_32
PIN 4 INT4   PIN_31
PIN 5 INT3   PIN_34
PIN 6   P5   PIN_52
PIN 7 INT7   PIN_33
PIN 8  1Y1   PIN_42
PIN 9  1Y0   PIN_43
PIN10 INT9   PIN_39
PIN11 INT10  PIN_38
PIN12  2Y0   PIN_44
PIN13  2Y1   PIN_46
PIN14  2Y2   PIN_49
PIN15  2Y3   PIN_50

キーボードマトリクス部分のVHDLをA-C4E6で上記の通りに工作して動作確認します。

http://www.aliexpress.com/store/product/E10-Free-shipping-altera-fpga-board-altera-board-fpga-development-board-EP4CE10E22C8N/620372_32670541876.html

UK101keyboard.vhd

-- ZX Spectrum for Altera DE1
--
-- Copyright (c) 2009-2011 Mike Stirling
--
-- All rights reserved
--
-- Redistribution and use in source and synthezised forms, with or without
-- modification, are permitted provided that the following conditions are met:
--
-- * Redistributions of source code must retain the above copyright notice,
--   this list of conditions and the following disclaimer.
--
-- * Redistributions in synthesized form must reproduce the above copyright
--   notice, this list of conditions and the following disclaimer in the
--   documentation and/or other materials provided with the distribution.
--
-- * Neither the name of the author nor the names of other contributors may
--   be used to endorse or promote products derived from this software without
--   specific prior written agreement from the author.
--
-- * License is granted for non-commercial use only.  A fee may not be charged
--   for redistributions as source code or in synthesized/hardware form without 
--   specific prior written agreement from the author.
--
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-- POSSIBILITY OF SUCH DAMAGE.
--

-- PS/2 scancode to Spectrum matrix conversion
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity UK101keyboard is
port (
	CLK			:	in	std_logic;
	nRESET		:	in	std_logic;

	-- PS/2 interface
	PS2_CLK		:	in	std_logic;
	PS2_DATA	:	in	std_logic;
	
	-- select bus
	A			:	in	std_logic_vector(7 downto 0);
	-- matrix return
	KEYB		:	out	std_logic_vector(7 downto 0)
	);
end UK101keyboard;

architecture rtl of UK101keyboard is

-- PS/2 interface
component ps2_intf is
generic (filter_length : positive := 8);
port(
	CLK			:	in	std_logic;
	nRESET		:	in	std_logic;
	
	-- PS/2 interface (could be bi-dir)
	PS2_CLK		:	in	std_logic;
	PS2_DATA	:	in	std_logic;
	
	-- Byte-wide data interface - only valid for one clock
	-- so must be latched externally if required
	DATA		:	out	std_logic_vector(7 downto 0);
	VALID		:	out	std_logic;
	ERROR		:	out	std_logic
	);
end component;

-- Interface to PS/2 block
signal keyb_data	:	std_logic_vector(7 downto 0);
signal keyb_valid	:	std_logic;
signal keyb_error	:	std_logic;

-- Internal signals
type key_matrix is array (7 downto 0) of std_logic_vector(7 downto 0);
signal keys		:	key_matrix;
signal release	:	std_logic;
signal extended	:	std_logic;
signal shiftPressed : std_logic;
begin	

	ps2 : ps2_intf port map (
		CLK, nRESET,
		PS2_CLK, PS2_DATA,
		keyb_data, keyb_valid, keyb_error
		);

	shiftPressed <= keys(0)(2) or keys(0)(1);
		
	-- Output addressed matrix row/col
	-- Original monitor scans for more than one row at a time, so more than one address may be low !
	KEYB(0) <= (keys(0)(0) or A(0)) and (keys(1)(0) or A(1)) and (keys(2)(0) or A(2)) and (keys(3)(0) or A(3)) and (keys(4)(0) or A(4)) and (keys(5)(0) or A(5)) and (keys(6)(0) or A(6)) and (keys(7)(0) or A(7));
	KEYB(1) <= (keys(0)(1) or A(0)) and (keys(1)(1) or A(1)) and (keys(2)(1) or A(2)) and (keys(3)(1) or A(3)) and (keys(4)(1) or A(4)) and (keys(5)(1) or A(5)) and (keys(6)(1) or A(6)) and (keys(7)(1) or A(7));
	KEYB(2) <= (keys(0)(2) or A(0)) and (keys(1)(2) or A(1)) and (keys(2)(2) or A(2)) and (keys(3)(2) or A(3)) and (keys(4)(2) or A(4)) and (keys(5)(2) or A(5)) and (keys(6)(2) or A(6)) and (keys(7)(2) or A(7));
	KEYB(3) <= (keys(0)(3) or A(0)) and (keys(1)(3) or A(1)) and (keys(2)(3) or A(2)) and (keys(3)(3) or A(3)) and (keys(4)(3) or A(4)) and (keys(5)(3) or A(5)) and (keys(6)(3) or A(6)) and (keys(7)(3) or A(7));
	KEYB(4) <= (keys(0)(4) or A(0)) and (keys(1)(4) or A(1)) and (keys(2)(4) or A(2)) and (keys(3)(4) or A(3)) and (keys(4)(4) or A(4)) and (keys(5)(4) or A(5)) and (keys(6)(4) or A(6)) and (keys(7)(4) or A(7));
	KEYB(5) <= (keys(0)(5) or A(0)) and (keys(1)(5) or A(1)) and (keys(2)(5) or A(2)) and (keys(3)(5) or A(3)) and (keys(4)(5) or A(4)) and (keys(5)(5) or A(5)) and (keys(6)(5) or A(6)) and (keys(7)(5) or A(7));
	KEYB(6) <= (keys(0)(6) or A(0)) and (keys(1)(6) or A(1)) and (keys(2)(6) or A(2)) and (keys(3)(6) or A(3)) and (keys(4)(6) or A(4)) and (keys(5)(6) or A(5)) and (keys(6)(6) or A(6)) and (keys(7)(6) or A(7));
	KEYB(7) <= (keys(0)(7) or A(0)) and (keys(1)(7) or A(1)) and (keys(2)(7) or A(2)) and (keys(3)(7) or A(3)) and (keys(4)(7) or A(4)) and (keys(5)(7) or A(5)) and (keys(6)(7) or A(6)) and (keys(7)(7) or A(7));

--	KEYB <= keys(0) when A(0) = '0' else
--		keys(1) when A(1) = '0' else
--		keys(2) when A(2) = '0' else
--		keys(3) when A(3) = '0' else
--		keys(4) when A(4) = '0' else
--		keys(5) when A(5) = '0' else
--		keys(6) when A(6) = '0' else
--		keys(7) when A(7) = '0' else
--		(others => '1');

	process(nRESET,CLK)
	begin
		if nRESET = '0' then
			release <= '0';
			extended <= '0';
			
			keys(0) <= "11111110";
			keys(1) <= (others => '1');
			keys(2) <= (others => '1');
			keys(3) <= (others => '1');
			keys(4) <= (others => '1');
			keys(5) <= (others => '1');
			keys(6) <= (others => '1');
			keys(7) <= (others => '1');
		elsif rising_edge(CLK) then
			if keyb_valid = '1' then
				if keyb_data = X"e0" then
					-- Extended key code follows
					extended <= '1';
				elsif keyb_data = X"f0" then
					-- Release code follows
					release <= '1';
				else
					-- Cancel extended/release flags for next time
					release <= '0';
					extended <= '0';
				
					case keyb_data is					
					
--					when X"0e" => keys(0)(0) <= release; -- pipe
					when X"16" => keys(7)(2) <= release; -- 1
					when X"1e" => keys(4)(2) <= release; -- 2
					when X"26" => keys(3)(2) <= release; -- 3
					when X"25" => keys(2)(2) <= release; -- 4
					when X"2e" => keys(6)(2) <= release; -- 5			
					when X"36" => keys(6)(6) <= release; -- 6
					when X"3d" => keys(2)(6) <= release; -- 7
					when X"3e" => keys(3)(6) <= release; -- 8
					when X"46" => keys(4)(6) <= release; -- 9
					when X"45" => keys(7)(6) <= release; -- 0
					when X"4e" => keys(5)(3) <= release; -- -
--					when X"55" => keys(5)(3) <= release; -- =
--					when X"66" => keys(6)(2) <= release; -- Backspace
					
--					when X"0d" => keys(0)(0) <= release; -- TAB
					when X"15" => keys(7)(1) <= release; -- Q
					when X"1d" => keys(4)(1) <= release; -- W
					when X"24" => keys(3)(1) <= release; -- E
					when X"2d" => keys(2)(1) <= release; -- R
					when X"2c" => keys(6)(1) <= release; -- T				
					when X"35" => keys(6)(7) <= release; -- Y
					when X"3c" => keys(2)(7) <= release; -- U
					when X"43" => keys(3)(7) <= release; -- I
					when X"44" => keys(4)(7) <= release; -- O
					when X"4d" => keys(7)(7) <= release; -- P
--					when X"54" => keys(5)(4) <= release; -- [
--					when X"5b" => keys(0)(0) <= release; -- ]
					when X"5a" => keys(5)(7) <= release; -- ENTER
					
					when X"58" => 
					if release = '0' then
						keys(0)(2) <= not (keys(0)(2)); -- Caps lock
					end if;
					when X"1c" => keys(7)(5) <= release; -- A
					when X"1b" => keys(4)(5) <= release; -- S
					when X"23" => keys(3)(5) <= release; -- D
					when X"2b" => keys(2)(5) <= release; -- F
					when X"34" => keys(6)(5) <= release; -- G
					when X"33" => keys(6)(4) <= release; -- H
					when X"3b" => keys(2)(4) <= release; -- J
					when X"42" => keys(3)(4) <= release; -- K
					when X"4b" => keys(4)(4) <= release; -- L
					when X"4c" => keys(7)(4) <= release; -- ;
--					when X"52" => keys(6)(1) <= release; -- '
--					when X"5d" => keys(6)(1) <= release; -- #

					when X"12" => keys(5)(5) <= release; -- Left shift
					when X"1a" => keys(7)(0) <= release; -- Z
					when X"22" => keys(4)(0) <= release; -- X
					when X"21" => keys(3)(0) <= release; -- C
					when X"2a" => keys(2)(0) <= release; -- V
					when X"32" => keys(6)(0) <= release; -- B
					when X"31" => keys(6)(3) <= release; -- N
					when X"3a" => keys(2)(3) <= release; -- M
					when X"41" => keys(3)(3) <= release; -- ,
					when X"49" => keys(4)(3) <= release; -- .
					when X"4a" => keys(7)(3) <= release; -- /
					when X"59" => keys(5)(2) <= release; -- Right shift
					
--					when X"76" => keys(0)(0) <= release; -- Escape
					when X"29" => keys(5)(4) <= release; -- SPACE
					when X"14" => keys(5)(1) <= release; -- CTRL
					
					-- Cursor keys - these are actually extended (E0 xx), but
					-- the scancodes for the numeric keypad cursor keys are
					-- are the same but without the extension, so we'll accept
					-- the codes whether they are extended or not
--					when X"6B" => keys(0)(0) <= release; -- Left
--					when X"72" => keys(0)(0) <= release; -- Down
--					when X"75" => keys(0)(0) <= release; -- Up
--					when X"74" => keys(0)(0) <= release; -- Right
					
					when others =>
						null;
					end case;
				end if;
			end if;
		end if;
	end process;

end architecture;