Skip to content

Commit

Permalink
USB Mouse support as Paddle (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
vossstef authored Dec 17, 2024
1 parent d4ff492 commit 8208ef1
Show file tree
Hide file tree
Showing 8 changed files with 310 additions and 116 deletions.
2 changes: 1 addition & 1 deletion INSTALLATION_WINDOWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ should see following screen:**
| Type | TN20k | TP20k |TP25k | TM138k |TM60k | |
| FPGA bitstream | 0x000000 | 0x000000 | 0x000000 | 0x000000 |0x000000|ROM size |

For the TN9k there might be an older version of the programmer SW be needed.
You might need to use an older version of the Gowin Programmer [SW](https://dl.sipeed.com/shareURL/TANG/programmer) for the GW1NR device.<br>

**shell / command line Programming alternative**

Expand Down
50 changes: 23 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,16 @@ Features:
* Cartridge type autodetect
* NTSC / PAL region autodetct
* Superchip autodetct
* USB Keyboard via µC
* [USB Joystick](https://en.wikipedia.org/wiki/Joystick) via µC
* [USB Gamepad](https://en.wikipedia.org/wiki/Gamepad) Stick via µC as paddle emulation<br>
* [USB Keyboard](https://en.wikipedia.org/wiki/Computer_keyboard) USB Keyboard
* [USB Joystick](https://en.wikipedia.org/wiki/Joystick)
* [USB Gamepad](https://en.wikipedia.org/wiki/Gamepad) Stick as paddle emulation<br>
* [USB Mouse](https://en.wikipedia.org/wiki/Computer_mouse) as paddle emulation
* [legacy D9 Joystick](https://en.wikipedia.org/wiki/Atari_CX40_joystick) (Atari / Commodore digital type) [MiSTeryNano shield](https://github.com/harbaum/MiSTeryNano/tree/main/board/misteryshield20k/README.md)<br>
* Joystick emulation on Keyboard [Numpad](https://en.wikipedia.org/wiki/Numeric_keypad)<br>
* [Dualshock 2 Controller Gamepad](https://en.wikipedia.org/wiki/DualShock) Keys & Stick as Joystick<br>
* [Dualshock 2 Controller Gamepad](https://en.wikipedia.org/wiki/DualShock) Sticks as paddle emulation (analog mode)<br>
* Cartridge ROM loader [boot default is homebrew 'Hunchy' Chris Walton](https://videogamehomebrew.fandom.com/wiki/Chris_Walton)

Planned features:
* ROM mapper control override via file extension
* Mouse as paddle support

> [!IMPORTANT]
> PROJECT IS STILL WORK IN PROGRESS!
Expand Down Expand Up @@ -71,9 +68,9 @@ The installation of A2600Nano on the Tang Nano 20k board can be done using a Lin
ROM can be loaded via OSD file selection.<br>

### Supported mappers
* Auto detected (00 F8 F6 FE E0 3F F4 P2 FA CV 2K UA E7 F0 32)<br>
* Auto detected (F8 F6 FE E0 3F F4 P2 FA CV 2K UA E7 F0 32)<br>

LED 2 to 4 are activated as hint in case an unsupported game (mapper) detected<br>
LED 1 to 5 are activated as hint in case an unsupported game (mapper) detected<br>

### single Button Joystick
* Button ```Trigger```
Expand All @@ -92,9 +89,9 @@ LED 2 to 4 are activated as hint in case an unsupported game (mapper) detected<b
* Gamepad Button ```SELECT``` as core function **SELECT**<br>

### Paddle
* DualShock 2 or USB Gamepad.<br>
* DualShock 2, USB Gamepad or USB Mouse.<br>

Core switches to paddle mode if paddle ```Trigger B``` or ```Trigger X``` is pressed. <br>
Core switches to paddle mode if paddle ```Trigger B``` or ```Trigger X``` is pressed respectively ```left Mouse Button``` or ```right Mouse Button```.<br>
Can be reverted by pressing Gamepad Button ```Trigger Y```.

### Keyboard
Expand Down Expand Up @@ -146,24 +143,24 @@ or Keyboard Numpad. OSD: **Numpad**<br>
|-|2<br>Down|-|

or Mouse. OSD: **Mouse**<br>
not supported yet
```left Mouse Button``` and ```right Mouse Button``` as Trigger for Paddle 1 or 2.<br>

or Dualshock2 Gamepad left stick as Paddle. OSD: **DS #1 Paddle** or **DS #2 Paddle**<br>
**cross / triangle** Trigger<br>
You have first to set the DS2 Sticks into analog mode by pressing the DS2 ANALOG button.<br> Mode indicated by red light indicator.<br>Configure DIGITAL mode (press ANALOG button again) when using the **Joystick** mode again.<br>

## LED UI

| LED | function | TN20K | TP20K | TP25K | TM60K |TM138k|
| --- | - | - |- | - | - | - |
| 0 |Cartridge selected| x |x | x | x | x |
| 1 | reserved | x |x | x | x | x |
| 2 | Game unsupported | x |x | - | x | - |
| 3 | Game unsupported | x |x | - | x | - |
| 4 | Game unsupported | x |x | - | x | - |
| 5 | Game unsupported | x |x | - | x | - |
| LED | function |TN9K|TN20K|TP20K|TP25K|TM60K|TM138k|
| --- | - |- |- |- | - | - | - |
| 0 |Cartridge selected|x |x |x | x | x | x |
| 1 | Game unsupported |x |x |x | x | x | x |
| 2 | Game unsupported |x |x |x | - | - | x |
| 3 | Game unsupported |x |x |x | - | - | x |
| 4 | Game unsupported |x |x |x | - | - | x |
| 5 | Game unsupported |x |x |x | - | - | x |

LED 1..4 are activated as hint in case an unsupported game (mapper) detected<br>
LED 1..5 are activated as hint in case an unsupported game (mapper) detected<br>

**Multicolor RGB LED**
* **<font color="green">green</font>**&ensp;&thinsp;&ensp;&thinsp;&ensp;&thinsp;all fine and ready to go<br>
Expand Down Expand Up @@ -217,11 +214,12 @@ Alternatively use the command line build script **gw_sh.exe** build_tn20k.tcl<br
In order to use this Design the following things are needed:

[Sipeed M0S Dock](https://wiki.sipeed.com/hardware/en/maixzero/m0s/m0s.html) or Raspberry Pi Pico RP2040 or ESP32-S2/S3<br>
[Sipeed Tang Nano 20k](https://wiki.sipeed.com/nano20k) <br>
[Tang Nano 20k](https://wiki.sipeed.com/nano20k) <br>
or [Tang Primer 20K with Dock ext Board](https://wiki.sipeed.com/hardware/en/tang/tang-primer-20k/primer-20k.html)<br>
and [M0S PMOD adapter](https://github.com/harbaum/MiSTeryNano/tree/main/board/m0s_pmod/README.md).<br>
and [PMOD DS2x2](https://wiki.sipeed.com/hardware/en/tang/tang-PMOD/FPGA_PMOD.html#PMOD_DS2x2)<br>
or [Sipeed Tang Primer 25k](https://wiki.sipeed.com/hardware/en/tang/tang-primer-25k/primer-25k.html)<br>
or [Tang Nano 9k](https://wiki.sipeed.com/hardware/en/tang/Tang-Nano-9K/Nano-9K.html)<br>
or [Tang Primer 25k](https://wiki.sipeed.com/hardware/en/tang/tang-primer-25k/primer-25k.html)<br>
and [PMOD DVI](https://wiki.sipeed.com/hardware/en/tang/tang-PMOD/FPGA_PMOD.html#PMOD_DVI)<br>
and [PMOD TF-CARD V2](https://wiki.sipeed.com/hardware/en/tang/tang-PMOD/FPGA_PMOD.html#PMOD_TF-CARD)<br>
and [PMOD SDRAM](https://wiki.sipeed.com/hardware/en/tang/tang-PMOD/FPGA_PMOD.html#TANG_SDRAM)<br>
Expand All @@ -230,16 +228,14 @@ and [M0S PMOD adapter](https://github.com/harbaum/MiSTeryNano/tree/main/board/m0
or [Tang Mega 60K NEO](https://wiki.sipeed.com/hardware/en/tang/tang-mega-60k/mega-60k.html)<br>
and [PMOD DS2x2](https://wiki.sipeed.com/hardware/en/tang/tang-PMOD/FPGA_PMOD.html#PMOD_DS2x2)<br>
and [M0S PMOD adapter](https://github.com/harbaum/MiSTeryNano/tree/main/board/m0s_pmod/README.md)<br>
or [Sipeed Tang Mega 138k Pro](https://wiki.sipeed.com/hardware/en/tang/tang-mega-138k/mega-138k-pro.html)<br>
or [Tang Mega 138k Pro](https://wiki.sipeed.com/hardware/en/tang/tang-mega-138k/mega-138k-pro.html)<br>
and [PMOD DS2x2](https://wiki.sipeed.com/hardware/en/tang/tang-PMOD/FPGA_PMOD.html#PMOD_DS2x2)<br>
and [M0S PMOD adapter](https://github.com/harbaum/MiSTeryNano/tree/main/board/m0s_pmod/README.md)<br>

TM138k add
microSD or microSDHC card FAT/exFAT formatted<br>
TFT Monitor with HDMI Input and Speaker<br>
<br>

| HID and Gamecontrol Hardware option | TN20k needs | alternative option |Primer 25K|Mega 60K|Mega 138K|
| HID and Gamecontrol Hardware option | TN20k needs | alternative option |Primer 25K|Mega 60K|Mega 138K Pro|
| ----------- | --- | --- | --- | - | - |
| USB Keyboard | [USB-C to USB-A adapter](https://www.aliexpress.us/item/3256805563910755.html) | [4 port mini USB hub HS8836A](https://a.aliexpress.com/_EIidgjH) |x|x|x|
| [USB Joystick(s)](https://www.speedlink.com/en/COMPETITION-PRO-EXTRA-USB-Joystick-black-red/SL-650212-BKRD)| [4 port mini USB hub HS8836A](https://a.aliexpress.com/_EIidgjH) | - |x|x|x|
Expand Down
65 changes: 50 additions & 15 deletions src/a2600_top_tm138k_pro.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@ signal pot4 : std_logic_vector(7 downto 0);
signal pd1,pd2 : std_logic_vector(7 downto 0);
signal pd3,pd4 : std_logic_vector(7 downto 0);
signal p1,p2,p3,p4 : std_logic_vector(7 downto 0);
signal mouse_x_pos : signed(10 downto 0);
signal mouse_y_pos : signed(10 downto 0);
signal mx : signed(8 downto 0);
signal my : signed(8 downto 0);
signal pal : std_logic;
signal system_video_std : std_logic_vector(1 downto 0);
signal hsync : std_logic;
Expand Down Expand Up @@ -521,7 +521,7 @@ 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";
joyMouse <= extra_button0 & "0" & mouse_btns & "0" & "0000";

-- send external DB9 joystick port to µC
db9_joy <= not ('0' & io(0) & io(2) & io(1) & io(4) & io(3));
Expand Down Expand Up @@ -566,35 +566,70 @@ end process;

-- paddle pins
pd1 <= not paddle_1 when port_1_sel = "0100" else
joystick1_x_pos(7 downto 0) when port_1_sel = "0001" else
joystick1_x_pos when port_1_sel = "0001" else
std_logic_vector(not mx(7) & mx(6 downto 0)) when port_1_sel = "0101" else
x"ff";
pd2 <= not paddle_2 when port_1_sel = "0100" else
joystick1_y_pos(7 downto 0) when port_1_sel = "0001" else
std_logic_vector(not my(7) & my(6 downto 0)) when port_1_sel = "0101" else
x"ff";
pd3 <= not paddle_3 when port_2_sel = "0111" else
pd3 <= not paddle_3 when port_2_sel = "0100" else
joystick2_x_pos(7 downto 0) when port_2_sel = "0010" else
std_logic_vector(not mx(7) & mx(6 downto 0)) when port_2_sel = "0101" else
x"ff";
pd4 <= not paddle_4 when port_2_sel = "0111" else
pd4 <= not paddle_4 when port_2_sel = "0100" else
joystick2_y_pos(7 downto 0) when port_2_sel = "0010" else
std_logic_vector(not my(7) & my(6 downto 0)) when port_2_sel = "0101" else
x"ff";

process(clk, system_reset(0))
variable mov_x: signed(6 downto 0);
variable mov_y: signed(6 downto 0);
variable mdx: signed(8 downto 0);
variable mdx2: signed(8 downto 0);
variable nmx: signed(8 downto 0);
variable mdy: signed(8 downto 0);
variable mdy2: signed(8 downto 0);
variable nmy: signed(8 downto 0);
begin
if system_reset(0) = '1' then
mx <= to_signed(0,mx'length);
my <= to_signed(0,my'length);
joystick1_x_pos <= x"ff";
joystick1_y_pos <= x"ff";
joystick2_x_pos <= x"ff";
joystick2_y_pos <= x"ff";
elsif rising_edge(clk) then
if joystick_strobe = '1' then
joystick1_x_pos <= std_logic_vector(joystick0ax(7 downto 0));
joystick1_y_pos <= std_logic_vector(joystick0ay(7 downto 0));
joystick2_x_pos <= std_logic_vector(joystick1ax(7 downto 0));
joystick2_y_pos <= std_logic_vector(joystick1ay(7 downto 0));
end if;
elsif rising_edge(clk) then
mdx := resize(mouse_x, mdx'length);
if mdx > 10 then
mdx2:= to_signed(10,mdx2'length);
elsif mdx < -10 then
mdx2:= to_signed(-10,mdx2'length);
else
mdx2 := mdx;
end if;
nmx := mx + mdx2;
mdy := resize(mouse_y, mdy'length);
if mdy > 10 then
mdy2:= to_signed(10,mdy2'length);
elsif mouse_x < -10 then
mdy2:= to_signed(-10,mdy2'length);
else
mdy2 := mdy;
end if;
nmy := my + mdy2;
if mouse_strobe = '1' then
mx <= to_signed(-128, mx'length) when nmx < -128
else to_signed(127, mx'length) when nmx > 127
else nmx;
my <= to_signed(-128, my'length) when nmy < -128
else to_signed(127, my'length) when nmy > 127
else nmy;
elsif joystick_strobe = '1' then
joystick1_x_pos <= std_logic_vector(joystick0ax(7 downto 0));
joystick1_y_pos <= std_logic_vector(joystick0ay(7 downto 0));
joystick2_x_pos <= std_logic_vector(joystick1ax(7 downto 0));
joystick2_y_pos <= std_logic_vector(joystick1ay(7 downto 0));
end if;
end if;
end process;

mcu_spi_inst: entity work.mcu_spi
Expand Down
65 changes: 50 additions & 15 deletions src/a2600_top_tm60k.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,8 @@ signal pot4 : std_logic_vector(7 downto 0);
signal pd1,pd2 : std_logic_vector(7 downto 0);
signal pd3,pd4 : std_logic_vector(7 downto 0);
signal p1,p2,p3,p4 : std_logic_vector(7 downto 0);
signal mouse_x_pos : signed(10 downto 0);
signal mouse_y_pos : signed(10 downto 0);
signal mx : signed(8 downto 0);
signal my : signed(8 downto 0);
signal pal : std_logic;
signal system_video_std : std_logic_vector(1 downto 0);
signal hsync : std_logic;
Expand Down Expand Up @@ -523,7 +523,7 @@ 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";
joyMouse <= extra_button0 & "0" & mouse_btns & "0" & "0000";

-- send external DB9 joystick port to µC
db9_joy <= not ('0' & io(0) & io(2) & io(1) & io(4) & io(3));
Expand Down Expand Up @@ -568,35 +568,70 @@ end process;

-- paddle pins
pd1 <= not paddle_1 when port_1_sel = "0100" else
joystick1_x_pos(7 downto 0) when port_1_sel = "0001" else
joystick1_x_pos when port_1_sel = "0001" else
std_logic_vector(not mx(7) & mx(6 downto 0)) when port_1_sel = "0101" else
x"ff";
pd2 <= not paddle_2 when port_1_sel = "0100" else
joystick1_y_pos(7 downto 0) when port_1_sel = "0001" else
std_logic_vector(not my(7) & my(6 downto 0)) when port_1_sel = "0101" else
x"ff";
pd3 <= not paddle_3 when port_2_sel = "0111" else
pd3 <= not paddle_3 when port_2_sel = "0100" else
joystick2_x_pos(7 downto 0) when port_2_sel = "0010" else
std_logic_vector(not mx(7) & mx(6 downto 0)) when port_2_sel = "0101" else
x"ff";
pd4 <= not paddle_4 when port_2_sel = "0111" else
pd4 <= not paddle_4 when port_2_sel = "0100" else
joystick2_y_pos(7 downto 0) when port_2_sel = "0010" else
std_logic_vector(not my(7) & my(6 downto 0)) when port_2_sel = "0101" else
x"ff";

process(clk, system_reset(0))
variable mov_x: signed(6 downto 0);
variable mov_y: signed(6 downto 0);
variable mdx: signed(8 downto 0);
variable mdx2: signed(8 downto 0);
variable nmx: signed(8 downto 0);
variable mdy: signed(8 downto 0);
variable mdy2: signed(8 downto 0);
variable nmy: signed(8 downto 0);
begin
if system_reset(0) = '1' then
mx <= to_signed(0,mx'length);
my <= to_signed(0,my'length);
joystick1_x_pos <= x"ff";
joystick1_y_pos <= x"ff";
joystick2_x_pos <= x"ff";
joystick2_y_pos <= x"ff";
elsif rising_edge(clk) then
if joystick_strobe = '1' then
joystick1_x_pos <= std_logic_vector(joystick0ax(7 downto 0));
joystick1_y_pos <= std_logic_vector(joystick0ay(7 downto 0));
joystick2_x_pos <= std_logic_vector(joystick1ax(7 downto 0));
joystick2_y_pos <= std_logic_vector(joystick1ay(7 downto 0));
end if;
elsif rising_edge(clk) then
mdx := resize(mouse_x, mdx'length);
if mdx > 10 then
mdx2:= to_signed(10,mdx2'length);
elsif mdx < -10 then
mdx2:= to_signed(-10,mdx2'length);
else
mdx2 := mdx;
end if;
nmx := mx + mdx2;
mdy := resize(mouse_y, mdy'length);
if mdy > 10 then
mdy2:= to_signed(10,mdy2'length);
elsif mouse_x < -10 then
mdy2:= to_signed(-10,mdy2'length);
else
mdy2 := mdy;
end if;
nmy := my + mdy2;
if mouse_strobe = '1' then
mx <= to_signed(-128, mx'length) when nmx < -128
else to_signed(127, mx'length) when nmx > 127
else nmx;
my <= to_signed(-128, my'length) when nmy < -128
else to_signed(127, my'length) when nmy > 127
else nmy;
elsif joystick_strobe = '1' then
joystick1_x_pos <= std_logic_vector(joystick0ax(7 downto 0));
joystick1_y_pos <= std_logic_vector(joystick0ay(7 downto 0));
joystick2_x_pos <= std_logic_vector(joystick1ax(7 downto 0));
joystick2_y_pos <= std_logic_vector(joystick1ay(7 downto 0));
end if;
end if;
end process;

mcu_spi_inst: entity work.mcu_spi
Expand Down
Loading

0 comments on commit 8208ef1

Please sign in to comment.