Tandy/PCJr Joystick Support

Provides two 2-button analog joysticks usable at all three cpu frequencies.
Can choose between Analog input or DPAD input.
This commit is contained in:
Flandango
2022-08-23 14:10:27 -04:00
parent 514a402ec7
commit 22f16ecb6f
5 changed files with 130 additions and 2 deletions

18
PCXT.sv
View File

@@ -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),

View File

@@ -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),

View File

@@ -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;

View File

@@ -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 ]
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 ]

View File

@@ -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