Skip to content

Commit

Permalink
tp20k double ds2 (#10)
Browse files Browse the repository at this point in the history
  • Loading branch information
vossstef authored Nov 15, 2024
1 parent 08314d4 commit 8f60a30
Show file tree
Hide file tree
Showing 5 changed files with 128 additions and 58 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ The A2600Nano is a port of the [MiSTer](https://github.com/MiSTer-devel/Atari260
| Board | FPGA | support |Note|
| --- | - | - |-|
| [Tang Nano 20k](https://wiki.sipeed.com/nano20k) | [GW2AR](https://www.gowinsemi.com/en/product/detail/38/) | X |- |
| [Tang Primer 20K Dock ext Board](https://wiki.sipeed.com/hardware/en/tang/tang-primer-20k/primer-20k.html)| [GW2A](https://www.gowinsemi.com/en/product/detail/46/)| X |- |
| [Tang Primer 20K Dock ext Board](https://wiki.sipeed.com/hardware/en/tang/tang-primer-20k/primer-20k.html)| [GW2A](https://www.gowinsemi.com/en/product/detail/46/)| X |double Dualshock |
| [Tang Primer 25K](https://wiki.sipeed.com/hardware/en/tang/tang-primer-25k/primer-25k.html) | [GW5A-25](https://www.gowinsemi.com/en/product/detail/60/) | X |no Dualshock, no retro D9 Joystick |
| [Tang Mega 60k NEO](https://wiki.sipeed.com/hardware/en/tang/tang-mega-60k/mega-60k.html)|[GW5AT-60](https://www.gowinsemi.com/en/product/detail/60/)| X |dual Dualshock |
| [Tang Mega 138k Pro](https://wiki.sipeed.com/hardware/en/tang/tang-mega-138k/mega-138k-pro.html)|[GW5AST-138](https://www.gowinsemi.com/en/product/detail/60/) | X |dual Dualshock |
| [Tang Mega 60k NEO](https://wiki.sipeed.com/hardware/en/tang/tang-mega-60k/mega-60k.html)|[GW5AT-60](https://www.gowinsemi.com/en/product/detail/60/)| X |double Dualshock |
| [Tang Mega 138k Pro](https://wiki.sipeed.com/hardware/en/tang/tang-mega-138k/mega-138k-pro.html)|[GW5AST-138](https://www.gowinsemi.com/en/product/detail/60/) | X |double Dualshock |

This project relies on a [M0S Dock µC](https://wiki.sipeed.com/hardware/en/maixzero/m0s/m0s.html) being connected to the Tang Nano 20K.
Alternately you can use a [Raspberry Pi Pico](https://www.raspberrypi.com/documentation/microcontrollers/pico-series.html) or [esp32-s2](https://www.espressif.com/en/products/socs/esp32-s2)/[s3](https://www.espressif.com/en/products/socs/esp32-s3) and use the [FPGA companion firmware](http://github.com/harbaum/FPGA-Companion).
Expand Down
2 changes: 1 addition & 1 deletion impl/a2600nano_tp20k_process_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
"EXTERNAL_MASTER_CONFIG_CLOCK" : false,
"Enable_DSRM" : false,
"FORMAT" : "binary",
"FREQUENCY_DIVIDER" : "",
"FREQUENCY_DIVIDER" : "1",
"Generate_Constraint_File_of_Ports" : false,
"Generate_IBIS_File" : false,
"Generate_Plain_Text_Timing_Report" : false,
Expand Down
26 changes: 18 additions & 8 deletions src/a2600_top_tp20k.cst
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,24 @@ IO_PORT "tmds_clk_p" IO_TYPE=LVCMOS33D PULL_MODE=NONE DRIVE=4 BANK_VCCIO=3.3;
// 7 MISO A14 / B13
// 9 MOSI A15 / B14
// 11 CSn E15 / D14
IO_LOC "joystick_miso" A14; // B13
IO_PORT "joystick_miso" IO_TYPE=LVCMOS33 PULL_MODE=UP BANK_VCCIO=3.3;
IO_LOC "joystick_mosi" A15; // B14
IO_PORT "joystick_mosi" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8 BANK_VCCIO=3.3;
IO_LOC "joystick_clk" C12; // B12
IO_PORT "joystick_clk" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8 BANK_VCCIO=3.3;
IO_LOC "joystick_cs" E15; // D14
IO_PORT "joystick_cs" IO_TYPE=LVCMOS33 PULL_MODE=UP DRIVE=8 BANK_VCCIO=3.3;
// DualShock 1
IO_LOC "ds_miso" A14;
IO_PORT "ds_miso" IO_TYPE=LVCMOS33 PULL_MODE=UP BANK_VCCIO=3.3;
IO_LOC "ds_mosi" A15;
IO_PORT "ds_mosi" IO_TYPE=LVCMOS33 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=3.3;
IO_LOC "ds_clk" C12;
IO_PORT "ds_clk" IO_TYPE=LVCMOS33 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=3.3;
IO_LOC "ds_cs" E15;
IO_PORT "ds_cs" IO_TYPE=LVCMOS33 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=3.3;
// DualShock 2
IO_LOC "ds2_clk" B12;
IO_PORT "ds2_clk" PULL_MODE=NONE IO_TYPE=LVCMOS33 BANK_VCCIO=3.3;
IO_LOC "ds2_miso" B13;
IO_PORT "ds2_miso" PULL_MODE=UP IO_TYPE=LVCMOS33 BANK_VCCIO=3.3;
IO_LOC "ds2_mosi" B14;
IO_PORT "ds2_mosi" PULL_MODE=NONE IO_TYPE=LVCMOS33 BANK_VCCIO=3.3;
IO_LOC "ds2_cs" D14;
IO_PORT "ds2_cs" PULL_MODE=NONE IO_TYPE=LVCMOS33 BANK_VCCIO=3.3;

//IO_LOC "DDR3_DM[1]" K5;
//IO_PORT "DDR3_DM[1]" IO_TYPE=SSTL15 PULL_MODE=NONE DRIVE=8 BANK_VCCIO=1.5;
Expand Down
22 changes: 11 additions & 11 deletions src/a2600_top_tp20k.sdc
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
create_clock -name clk_27mhz -period 37.037 -waveform {0 5} [get_ports {clk_27mhz}]
create_clock -name ds2_clk -period 8000 -waveform {0 5} [get_nets {gamepad/clk_spi}]
create_clock -name joymiso -period 8000 -waveform {0 20} [get_ports {joystick_miso}]
create_clock -name clk -period 34.722 -waveform {0 5} [get_nets {clk}]
create_clock -name clk_14 -period 70 -waveform {0 5} [get_nets {clk_14}]
create_clock -name clk_cpu -period 279.408 -waveform {0 5} [get_nets {clk_cpu}]
create_clock -name m0s[3] -period 40 -waveform {0 5} [get_ports {m0s[3]}] -add
create_clock -name clk_pixel_x5 -period 6.944 -waveform {0 1.25} [get_nets {clk_pixel_x5}] -add
create_clock -name clk_audio -period 20833.332 -waveform {0 5} [get_nets {video_inst/clk_audio}] -add
report_timing -hold -from_clock [get_clocks {clk*}] -to_clock [get_clocks {clk*}] -max_paths 25 -max_common_paths 1
report_timing -setup -from_clock [get_clocks {clk*}] -to_clock [get_clocks {clk*}] -max_paths 25 -max_common_paths 1
create_clock -name clk_27mhz -period 37.037 -waveform {0 5} [get_ports {clk_27mhz}]
create_clock -name ds_clk -period 8000 -waveform {0 5} [get_nets {gamepad_p1/clk_spi}]
create_clock -name ds2_clk -period 8000 -waveform {0 5} [get_nets {gamepad_p2/clk_spi}]
create_clock -name clk -period 34.722 -waveform {0 5} [get_nets {clk}]
create_clock -name clk_14 -period 70 -waveform {0 5} [get_nets {clk_14}]
create_clock -name clk_cpu -period 279.408 -waveform {0 5} [get_nets {clk_cpu}]
create_clock -name m0s[3] -period 40 -waveform {0 5} [get_ports {m0s[3]}] -add
create_clock -name clk_pixel_x5 -period 6.944 -waveform {0 1.25} [get_nets {clk_pixel_x5}] -add
create_clock -name clk_audio -period 20833.332 -waveform {0 5} [get_nets {video_inst/clk_audio}] -add
report_timing -hold -from_clock [get_clocks {clk*}] -to_clock [get_clocks {clk*}] -max_paths 25 -max_common_paths 1
report_timing -setup -from_clock [get_clocks {clk*}] -to_clock [get_clocks {clk*}] -max_paths 25 -max_common_paths 1
130 changes: 95 additions & 35 deletions src/a2600_top_tp20k.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ entity A2600_top is
reset : in std_logic; -- S2 button
user : in std_logic; -- S1 button
leds_n : out std_logic_vector(5 downto 0);
io : in std_logic_vector(5 downto 0);
io : in std_logic_vector(4 downto 0);

-- SPI interface Sipeed M0S Dock external BL616 uC
m0s : inout std_logic_vector(4 downto 0);
Expand All @@ -31,11 +31,16 @@ entity A2600_top is
sd_dat : inout std_logic_vector(3 downto 0);
ws2812 : out std_logic;

-- Gamepad
joystick_clk : out std_logic;
joystick_mosi : out std_logic;
joystick_miso : inout std_logic;
joystick_cs : inout std_logic
-- Gamepad Dualshock P1
ds_clk : out std_logic;
ds_mosi : out std_logic;
ds_miso : in std_logic;
ds_cs : out std_logic;
-- Gamepad DualShock P2
ds2_clk : out std_logic;
ds2_mosi : out std_logic;
ds2_miso : in std_logic;
ds2_cs : out std_logic
);
end;

Expand All @@ -62,7 +67,8 @@ signal joyDigital : std_logic_vector(15 downto 0);
signal joyNumpad : std_logic_vector(15 downto 0);
signal joyMouse : std_logic_vector(15 downto 0);
signal numpad : std_logic_vector(7 downto 0);
signal joyDS2 : std_logic_vector(15 downto 0);
signal joyDS2_p1 : std_logic_vector(15 downto 0);
signal joyDS2_p2 : std_logic_vector(15 downto 0);
-- joystick interface
signal joyA : std_logic_vector(15 downto 0);
signal joyB : std_logic_vector(15 downto 0);
Expand Down Expand Up @@ -161,6 +167,22 @@ signal key_start : std_logic;
signal key_select : std_logic;
signal key_lstick : std_logic;
signal key_rstick : std_logic;
signal key_r12 : std_logic;
signal key_r22 : std_logic;
signal key_l12 : std_logic;
signal key_l22 : std_logic;
signal key_triangle2 : std_logic;
signal key_square2 : std_logic;
signal key_circle2 : std_logic;
signal key_cross2 : std_logic;
signal key_up2 : std_logic;
signal key_down2 : std_logic;
signal key_left2 : std_logic;
signal key_right2 : std_logic;
signal key_start2 : std_logic;
signal key_select2 : std_logic;
signal key_lstick2 : std_logic;
signal key_rstick2 : std_logic;
---
signal video_r : std_logic_vector(7 downto 0);
signal video_g : std_logic_vector(7 downto 0);
Expand Down Expand Up @@ -287,26 +309,23 @@ begin
spi_io_clk <= m0s(3);
m0s(0) <= spi_io_dout; -- M0 Dock

joystick_cs <= joystick_cs_i;
joystick_miso_i <= joystick_miso;

-- https://store.curiousinventor.com/guides/PS2/
-- https://hackaday.io/project/170365-blueretro/log/186471-playstation-playstation-2-spi-interface

gamepad: entity work.dualshock2
gamepad_p1: entity work.dualshock2
port map (
clk => clk,
rst => system_reset(0) and not pll_locked,
vsync => vsync,
ds2_dat => joystick_miso_i,
ds2_cmd => joystick_mosi,
ds2_att => joystick_cs_i,
ds2_clk => joystick_clk,
ds2_dat => ds_miso,
ds2_cmd => ds_mosi,
ds2_att => ds_cs,
ds2_clk => ds_clk,
ds2_ack => '0',
stick_lx => paddle_1,
stick_ly => paddle_2,
stick_rx => paddle_3,
stick_ry => paddle_4,
stick_rx => open,
stick_ry => open,
key_up => key_up,
key_down => key_down,
key_left => key_left,
Expand All @@ -327,6 +346,40 @@ gamepad: entity work.dualshock2
debug2 => open
);

gamepad_p2: entity work.dualshock2
port map (
clk => clk,
rst => system_reset(0) and not pll_locked,
vsync => vsync,
ds2_dat => ds2_miso,
ds2_cmd => ds2_mosi,
ds2_att => ds2_cs,
ds2_clk => ds2_clk,
ds2_ack => '0',
stick_lx => paddle_3,
stick_ly => paddle_4,
stick_rx => open,
stick_ry => open,
key_up => key_up2,
key_down => key_down2,
key_left => key_left2,
key_right => key_right2,
key_l1 => key_l12,
key_l2 => key_l22,
key_r1 => key_r12,
key_r2 => key_r22,
key_triangle => key_triangle2,
key_square => key_square2,
key_circle => key_circle2,
key_cross => key_cross2,
key_start => key_start2,
key_select => key_select2,
key_lstick => open,
key_rstick => open,
debug1 => open,
debug2 => open
);

led_ws2812: entity work.ws2812
port map
(
Expand Down Expand Up @@ -511,8 +564,7 @@ port map(
);

leds_n <= not leds;
leds(1) <= '0';
leds(5 downto 2) <= "1111" when force_bs > 14 else "0000"; -- indicate unsupported mapper
leds(5 downto 1) <= "11111" when force_bs > 14 else "00000"; -- indicate unsupported mapper

-- 9 pin d-sub joystick pinout:
-- pin 1: up
Expand Down Expand Up @@ -561,30 +613,35 @@ leds(5 downto 2) <= "1111" when force_bs > 14 else "0000"; -- indicate unsupport
-- BTN_SR 9
-- BTN_SELECT 10
-- BTN_START 11
joyDS2 <= key_rstick & key_lstick & key_r2 & key_l2 & key_start & key_select & key_r1 & key_l1 &
joyDS2_p1 <= key_rstick & key_lstick & key_r2 & key_l2 & key_start & key_select & key_r1 & key_l1 &
key_square & key_triangle & key_cross & key_circle & key_up & key_down & key_left & key_right;
joyDigital <= not(x"FF" & "111" & io(0) & io(2) & io(1) & io(4) & io(3));
joyDS2_p2 <= key_rstick2 & key_lstick2 & key_r22 & key_l22 & key_start2 & key_select2 & key_r12 & key_l12 &
key_square2 & key_triangle2 & key_cross2 & key_circle2 & key_up2 & key_down2 & key_left2 & key_right2;
joyDigital <= not(x"FF" & "111" & io(0) & io(2) & io(1) & io(4) & io(3));
joyUsb1 <= extra_button0 & joystick1(7 downto 4) & joystick1(3) & joystick1(2) & joystick1(1) & joystick1(0);
joyUsb2 <= extra_button1 & joystick2(7 downto 4) & joystick2(3) & joystick2(2) & joystick2(1) & joystick2(0);
joyNumpad <= x"00" & "000" & numpad(4) & numpad(3) & numpad(2) & numpad(1) & numpad(0);
joyMouse <= x"0000";

-- send external DB9 joystick port to µC
db9_joy <= not('1' & io(0) & io(1) & io(2) & io(3) & io(4));
db9_joy <= not ('0' & io(0) & io(2) & io(1) & io(4) & io(3));

process(clk)
begin
if rising_edge(clk) then
case port_1_sel is
when "0000" => joyA <= joyDigital;
when "0001" => joyA <= joyUsb1;
when "0010" => joyA <= joyUsb2;
when "0011" => joyA <= joyNumpad;
when "0100" => joyA <= joyDS2;
when "0101" => joyA <= joyMouse;
when "0110" => joyA <= (others => '0');
when others => null;
end case;
when "0000" => joyA <= joyDigital;-- 0
when "0001" => joyA <= joyUsb1; -- 1
when "0010" => joyA <= joyUsb2; -- 2
when "0011" => joyA <= joyNumpad; -- 3
when "0100" => joyA <= joyDS2_p1; -- 4
when "0101" => joyA <= joyMouse; -- 5
when "0110" => joyA <= (others => '0'); --6 Off
when "0111" => joyA <= joyDS2_p2; -- 7
when "1000" => joyA <= (others => '0'); -- 8 R #2 D9 PMOD
when "1001" => joyA <= (others => '0'); -- 9 R #2 D9 ALT
when others => joyA <= (others => '0');
end case;
end if;
end process;

Expand All @@ -596,10 +653,13 @@ begin
when "0001" => joyB <= joyUsb1;
when "0010" => joyB <= joyUsb2;
when "0011" => joyB <= joyNumpad;
when "0100" => joyB <= joyDS2;
when "0100" => joyB <= joyDS2_p1;
when "0101" => joyB <= joyMouse;
when "0110" => joyB <= (others => '0');
when others => null;
when "0111" => joyB <= joyDS2_p2;
when "1000" => joyB <= (others => '0'); -- 8 R #2 D9 PMOD
when "1001" => joyB <= (others => '0'); -- 9 R #2 D9 ALT
when others => joyB <= (others => '0');
end case;
end if;
end process;
Expand All @@ -611,10 +671,10 @@ pd1 <= not paddle_1 when port_1_sel = "0100" else
pd2 <= not paddle_2 when port_1_sel = "0100" else
joystick1_y_pos(7 downto 0) when port_1_sel = "0001" else
x"ff";
pd3 <= not paddle_3 when port_2_sel = "0100" else
pd3 <= not paddle_3 when port_2_sel = "0111" else
joystick2_x_pos(7 downto 0) when port_2_sel = "0010" else
x"ff";
pd4 <= not paddle_4 when port_2_sel = "0100" else
pd4 <= not paddle_4 when port_2_sel = "0111" else
joystick2_y_pos(7 downto 0) when port_2_sel = "0010" else
x"ff";

Expand Down

0 comments on commit 8f60a30

Please sign in to comment.