diff --git a/PCXT.sv b/PCXT.sv index 2624ea1..e0cc6bc 100644 --- a/PCXT.sv +++ b/PCXT.sv @@ -242,6 +242,9 @@ localparam CONF_STR = { "P3-;", "P3OB,Lo-tech 2MB EMS,Enabled,Disabled;", "P3OCD,EMS Frame,A000,C000,D000;", + "P3ON,Joystick 1, Analog, Digital;", + "P3OO,Joystick 2, Analog, Digital;", + "P3OP,Swap Joysticks,No,Yes;", "P3-;", "-;", "ON,Ignore Model on Reset,No,Yes;", @@ -249,6 +252,7 @@ localparam CONF_STR = { "F2,ROM,Load XTIDE (EC00);", "-;", "R0,Reset and close OSD;", + "J,Fire 1, Fire 2;", "V,v",`BUILD_DATE }; @@ -292,6 +296,9 @@ wire clk_uart; wire [21:0] gamma_bus; wire adlibhide = status[10]; +wire [31:0] joy0, joy1; +wire [15:0] joya0, joya1; + hps_io #(.CONF_STR(CONF_STR), .PS2DIV(2000), .PS2WE(1)) hps_io ( .clk_sys(clk_chipset), @@ -327,6 +334,10 @@ hps_io #(.CONF_STR(CONF_STR), .PS2DIV(2000), .PS2WE(1)) hps_io // .ps2_mouse_data_out (ps2_mouse_data_in), //.ps2_key(ps2_key), + .joystick_0(joy0), + .joystick_1(joy1), + .joystick_l_analog_0(joya0), + .joystick_l_analog_1(joya1), //ioctl .ioctl_download(ioctl_download), @@ -600,6 +611,7 @@ end .cpu_clock (clk_cpu), .clk_sys (clk_chipset), .peripheral_clock (pclk), + .turbo_mode (status[18:17]), .color (screen_mode == 3'd0), .reset (reset_cpu), .sdram_reset (reset), @@ -658,6 +670,12 @@ end .ps2_data (device_data), .ps2_clock_out (ps2_kbd_clk_out), .ps2_data_out (ps2_kbd_data_out), + .joy0_type (status[23]), + .joy1_type (status[24]), + .joy0 (status[25] ? joy1 : joy0), + .joy1 (status[25] ? joy0 : joy1), + .joya0 (status[25] ? joya1 : joya0), + .joya1 (status[25] ? joya0 : joya1), .clk_en_44100 (cen_44100), .dss_covox_en (status[6]), .lclamp (AUDIO_L), diff --git a/rtl/KFPC-XT/HDL/Chipset.sv b/rtl/KFPC-XT/HDL/Chipset.sv index c2e59f5..d53243d 100644 --- a/rtl/KFPC-XT/HDL/Chipset.sv +++ b/rtl/KFPC-XT/HDL/Chipset.sv @@ -7,6 +7,7 @@ module CHIPSET ( input logic cpu_clock, input logic clk_sys, input logic peripheral_clock, + input logic [1:0] turbo_mode, input logic color, input logic reset, input logic sdram_reset, @@ -77,6 +78,13 @@ module CHIPSET ( input logic ps2_data, output logic ps2_clock_out, output logic ps2_data_out, + input logic joy0_type, + input logic joy1_type, + input logic [31:0] joy0, + input logic [31:0] joy1, + input logic [15:0] joya0, + input logic [15:0] joya1, + // SOUND input logic clk_en_44100, // COVOX/DSS clock enable input logic dss_covox_en, @@ -229,6 +237,7 @@ module CHIPSET ( .clk_uart (clk_uart), .peripheral_clock (peripheral_clock), .color (color), + .turbo_mode (turbo_mode), .reset (reset), .interrupt_to_cpu (interrupt_to_cpu), .interrupt_acknowledge_n (interrupt_acknowledge_n), @@ -247,7 +256,7 @@ module CHIPSET ( .VGA_B (VGA_B), .VGA_HSYNC (VGA_HSYNC), .VGA_VSYNC (VGA_VSYNC), - .VGA_HBlank (VGA_HBlank), + .VGA_HBlank (VGA_HBlank), .VGA_VBlank (VGA_VBlank), .address (address), .internal_data_bus (internal_data_bus), @@ -271,6 +280,12 @@ module CHIPSET ( .port_c_io (port_c_io), .ps2_clock (ps2_clock), .ps2_data (ps2_data), + .joy0_type (joy0_type), + .joy1_type (joy1_type), + .joy0 (joy0), + .joy1 (joy1), + .joya0 (joya0), + .joya1 (joya1), .ps2_clock_out (ps2_clock_out), .ps2_data_out (ps2_data_out), .clk_en_44100 (clk_en_44100), diff --git a/rtl/KFPC-XT/HDL/Peripherals.sv b/rtl/KFPC-XT/HDL/Peripherals.sv index 25b0c3e..0252a18 100644 --- a/rtl/KFPC-XT/HDL/Peripherals.sv +++ b/rtl/KFPC-XT/HDL/Peripherals.sv @@ -8,6 +8,7 @@ module PERIPHERALS #( input logic clock, input logic clk_sys, input logic peripheral_clock, + input logic [1:0] turbo_mode, input logic color, input logic reset, // CPU @@ -59,6 +60,12 @@ module PERIPHERALS #( input logic ps2_data, output logic ps2_clock_out, output logic ps2_data_out, + input logic joy0_type, + input logic joy1_type, + input logic [31:0] joy0, + input logic [31:0] joy1, + input logic [15:0] joya0, + input logic [15:0] joya1, // SOUND input logic clk_en_44100, // COVOX/DSS clock enable input logic dss_covox_en, @@ -132,6 +139,8 @@ module PERIPHERALS #( wire timer_chip_select_n = iorq && chip_select_n[2]; wire ppi_chip_select_n = iorq && chip_select_n[3]; assign dma_page_chip_select_n = iorq && chip_select_n[4]; + + wire joystick_select = (iorq && ~address_enable_n && address[15:3] == (16'h0200 >> 3)); // 0x200 .. 0x207 wire tandy_chip_select_n = ~(iorq && ~address_enable_n && address[15:3] == (16'h00c0 >> 3)); // 0xc0 - 0xc7 wire opl_chip_select_n = ~(iorq && ~address_enable_n && address[15:1] == (16'h0388 >> 1)); // 0x388 .. 0x389 @@ -868,8 +877,25 @@ module PERIPHERALS #( .video_g (video_g), .video_b (video_b) ); + */ + logic [7:0] joy_data; + + tandy_pcjr_joy joysticks + ( + .clk (clock), + .reset (reset), + .en (joystick_select && ~io_write_n), + .turbo_mode (turbo_mode), + .joy0_type (joy0_type), + .joy1_type (joy1_type), + .joy0 (joy0), + .joy1 (joy1), + .joya0 (joya0), + .joya1 (joya1), + .d_out (joy_data) + ); // // data_bus_out // @@ -934,6 +960,10 @@ module PERIPHERALS #( data_bus_out_from_chipset <= 1'b1; data_bus_out <= {1'bx, dss_full, 6'bxxxxxx}; end + else if (joystick_select && ~io_read_n) begin + data_bus_out_from_chipset <= 1'b1; + data_bus_out <= joy_data; + end else begin data_bus_out_from_chipset <= 1'b0; data_bus_out <= 8'b00000000; diff --git a/rtl/common/common.qip b/rtl/common/common.qip index 6e085e5..cebcb88 100644 --- a/rtl/common/common.qip +++ b/rtl/common/common.qip @@ -2,4 +2,5 @@ set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) ram.v ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) clk_div3.v ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) bios.v ] set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) soundwave.v ] -set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sndfifo.v ] \ No newline at end of file +set_global_assignment -name VERILOG_FILE [file join $::quartus(qip_path) sndfifo.v ] +set_global_assignment -name SYSTEMVERILOG_FILE [file join $::quartus(qip_path) tandy_pcjr_joy.sv ] diff --git a/rtl/common/tandy_pcjr_joy.sv b/rtl/common/tandy_pcjr_joy.sv new file mode 100644 index 0000000..efdc1dc --- /dev/null +++ b/rtl/common/tandy_pcjr_joy.sv @@ -0,0 +1,64 @@ +// Tandy/PCJr 2 Button Analog Joysticks +// Flandango + +module tandy_pcjr_joy +( + input logic clk, //50Mhz Anything else and the pulse_div values must be adjusted + input logic reset, + input logic en, //Active High. Triggers reading of joystics and generates pulse + input logic [1:0] turbo_mode, //0 - 4.77Mhz 1 - 7.16Mhz 2 - 14.38Mhz + input logic joy0_type, //0 - Use Analog Input 1 - Use DPad Input + input logic joy1_type, //0 - Use Analog Input 1 - Use DPad Input + input logic [31:0] joy0, + input logic [31:0] joy1, + input logic [15:0] joya0, + input logic [15:0] joya1, + output logic [7:0] d_out //Format Bit 7 down to 0: P2Btn2, P2Btn1, P1Btn2, P1Btn1, P2-Y_Axis, P2-X_Axis, P1-Y_Axis, P1-X_Axis +); + + logic [7:0] joy0_x_r; //Pulse width of X Axis - P1 + logic [7:0] joy1_x_r; //Pulse width of X Axis - P2 + logic [7:0] joy0_y_r; //Pulse width of Y Axis - P1 + logic [7:0] joy1_y_r; //Pulse width of Y Axis - P2 + logic [9:0] joy0_x; //Current Joystick input values adjusted for 0-255 range and +/- 15 deadzone + logic [9:0] joy1_x; + logic [9:0] joy0_y; + logic [9:0] joy1_y; + logic [7:0] counter; //Clock cycle counter + logic [7:0] pulse_div; //# of clock cycles in each pulse segment according to cpu freq (turbo_mode). + // 4.77Mhz ~ 185, 7.16Mhz ~ 106 and 14.38Mhz ~ 70. + // These values may need some tweaking to keep joysticks centered. + // The Frogger games has a decent joystick calibration test + + assign joy0_x = joy0_type ? (joy0[0] ? 8'hFF : joy0[1] ? 8'h00 : 8'h80 ) : 8'd128 + joya0[7:0]; + assign joy1_x = joy1_type ? (joy1[0] ? 8'hFF : joy1[1] ? 8'h00 : 8'h80 ) : 8'd128 + joya1[7:0]; + assign joy0_y = joy0_type ? (joy0[2] ? 8'hFF : joy0[3] ? 8'h00 : 8'h80 ) : 8'd128 + joya0[15:8]; + assign joy1_y = joy1_type ? (joy1[2] ? 8'hFF : joy1[3] ? 8'h00 : 8'h80 ) : 8'd128 + joya1[15:8]; + + + assign pulse_div = turbo_mode == 1 ? 8'd106 : turbo_mode == 2 ? 8'd70 : 8'd185; + + always @(posedge clk) begin + if(reset) begin + counter <= 8'h0; + end + else if (en) begin + joy0_x_r <= joy0_x[7:0] < 8'h70 || joy0_x[7:0] > 8'h90 ? joy0_x[7:0] : 8'h80; + joy1_x_r <= joy1_x[7:0] < 8'h70 || joy1_x[7:0] > 8'h90 ? joy1_x[7:0] : 8'h80; + joy0_y_r <= joy0_y[7:0] < 8'h70 || joy0_y[7:0] > 8'h90 ? joy0_y[7:0] : 8'h80; + joy1_y_r <= joy1_y[7:0] < 8'h70 || joy1_y[7:0] > 8'h90 ? joy1_y[7:0] : 8'h80; + counter <= 8'h0; + end + else if(counter == pulse_div) begin // 8 (185) - 4.77 4 (106) - 7.16 (70) - 14.318 + if(joy0_x_r != 0) joy0_x_r <= joy0_x_r - 1'b1; + if(joy1_x_r != 0) joy1_x_r <= joy1_x_r - 1'b1; + if(joy0_y_r != 0) joy0_y_r <= joy0_y_r - 1'b1; + if(joy1_y_r != 0) joy1_y_r <= joy1_y_r - 1'b1; + counter <= 8'h0; + end + else counter <= counter + 1'b1; + end + + assign d_out = {~joy1[5],~joy1[4],~joy0[5],~joy0[4],|joy1_y_r,|joy1_x_r,|joy0_y_r,|joy0_x_r}; + +endmodule