mirror of
https://github.com/MiSTer-devel/GameAndWatch_MiSTer.git
synced 2026-05-24 03:03:25 +00:00
222 lines
6.5 KiB
Systemverilog
222 lines
6.5 KiB
Systemverilog
import types::*;
|
|
|
|
module input_config (
|
|
input wire clk,
|
|
|
|
input system_config sys_config,
|
|
|
|
input wire [3:0] cpu_id,
|
|
|
|
// Input selection
|
|
input wire [7:0] output_shifter_s,
|
|
input wire [3:0] output_r,
|
|
|
|
// Input
|
|
input wire button_a,
|
|
input wire button_b,
|
|
input wire button_x,
|
|
input wire button_y,
|
|
input wire button_trig_l,
|
|
input wire button_trig_r,
|
|
input wire button_start,
|
|
input wire button_select,
|
|
input wire dpad_up,
|
|
input wire dpad_down,
|
|
input wire dpad_left,
|
|
input wire dpad_right,
|
|
|
|
// MPU Input
|
|
output reg [3:0] input_k = 0,
|
|
output reg input_wake = 0,
|
|
|
|
output reg input_beta = 0,
|
|
output reg input_ba = 0,
|
|
output reg input_acl = 0
|
|
);
|
|
localparam INACTIVE_CONFIG_ROW = 32'h7F7F_7F7F;
|
|
|
|
function [31:0] s_config_by_index(reg [2:0] index);
|
|
case (index)
|
|
0: return sys_config.input_s0_config;
|
|
1: return sys_config.input_s1_config;
|
|
2: return sys_config.input_s2_config;
|
|
3: return sys_config.input_s3_config;
|
|
4: return sys_config.input_s4_config;
|
|
5: return sys_config.input_s5_config;
|
|
6: return sys_config.input_s6_config;
|
|
7: return sys_config.input_s7_config;
|
|
endcase
|
|
endfunction
|
|
|
|
function row_has_action([31:0] input_config, [6:0] action);
|
|
return input_config[ 6: 0] == action ||
|
|
input_config[14: 8] == action ||
|
|
input_config[22:16] == action ||
|
|
input_config[30:24] == action;
|
|
endfunction
|
|
|
|
wire has_start2_config =
|
|
row_has_action(sys_config.input_s0_config, 7'd14) ||
|
|
row_has_action(sys_config.input_s1_config, 7'd14) ||
|
|
row_has_action(sys_config.input_s2_config, 7'd14) ||
|
|
row_has_action(sys_config.input_s3_config, 7'd14) ||
|
|
row_has_action(sys_config.input_s4_config, 7'd14) ||
|
|
row_has_action(sys_config.input_s5_config, 7'd14) ||
|
|
row_has_action(sys_config.input_s6_config, 7'd14) ||
|
|
row_has_action(sys_config.input_s7_config, 7'd14);
|
|
|
|
// Map from config value to control
|
|
function input_mux([7:0] config_value);
|
|
reg out;
|
|
|
|
case (config_value[6:0])
|
|
0: out = dpad_up;
|
|
1: out = dpad_down;
|
|
2: out = dpad_left;
|
|
3: out = dpad_right;
|
|
|
|
// Buttons 1-4
|
|
4: out = button_b;
|
|
5: out = button_a;
|
|
6: out = button_y;
|
|
7: out = button_x;
|
|
|
|
// Buttons 5-8 unhandled
|
|
// Select is Time. If the package has no Game B/start2 action, also let
|
|
// controller Start trigger Game A/start1 for single-start handhelds.
|
|
12: out = button_trig_l;
|
|
13: out = button_select || (!has_start2_config && button_start);
|
|
14: out = button_start;
|
|
|
|
// Service1 unhandled
|
|
// Service 2 is Alarm
|
|
16: out = button_trig_r;
|
|
|
|
// Left joystick
|
|
17: out = dpad_up;
|
|
18: out = dpad_down;
|
|
19: out = dpad_left;
|
|
20: out = dpad_right;
|
|
|
|
// Right joystick
|
|
21: out = button_x;
|
|
22: out = button_b;
|
|
23: out = button_y;
|
|
24: out = button_a;
|
|
|
|
// Explicit MAME IPT_CUSTOM mappings that fit the existing controller
|
|
// layout. Generic custom/keypad wiring remains unhandled.
|
|
30: out = dpad_up || dpad_down;
|
|
31: out = button_b;
|
|
|
|
// This input is unused
|
|
7'h7F: out = 0;
|
|
// Other values unhandled
|
|
|
|
default: out = 0;
|
|
endcase
|
|
|
|
// High bit is active low flag
|
|
return config_value[7] ? ~out : out;
|
|
endfunction
|
|
|
|
function [3:0] build_k([31:0] input_config);
|
|
return {
|
|
input_mux(input_config[31:24]),
|
|
input_mux(input_config[23:16]),
|
|
input_mux(input_config[15:8]),
|
|
input_mux(input_config[7:0])
|
|
};
|
|
endfunction
|
|
|
|
function wake_input_mux([7:0] config_value);
|
|
if (config_value[6:0] == 7'h7F) begin
|
|
return 1'b0;
|
|
end
|
|
|
|
return input_mux(config_value);
|
|
endfunction
|
|
|
|
function [3:0] build_wake_k([31:0] input_config);
|
|
return {
|
|
wake_input_mux(input_config[31:24]),
|
|
wake_input_mux(input_config[23:16]),
|
|
wake_input_mux(input_config[15:8]),
|
|
wake_input_mux(input_config[7:0])
|
|
};
|
|
endfunction
|
|
|
|
// Always active config
|
|
reg [31:0] grounded_input_config = INACTIVE_CONFIG_ROW;
|
|
|
|
reg [ 3:0] main_input_k = 0;
|
|
|
|
always @(posedge clk) begin
|
|
reg [3:0] temp_k;
|
|
|
|
temp_k = 0;
|
|
grounded_input_config <= INACTIVE_CONFIG_ROW;
|
|
|
|
if (sys_config.grounded_port_config == 4'h0) begin
|
|
// Disabled
|
|
grounded_input_config <= INACTIVE_CONFIG_ROW;
|
|
end else begin
|
|
reg [3:0] temp;
|
|
temp = sys_config.grounded_port_config - 4'h1;
|
|
|
|
grounded_input_config <= s_config_by_index(temp[2:0]);
|
|
end
|
|
|
|
case (cpu_id)
|
|
4: begin
|
|
// SM5a
|
|
if (output_r[1]) temp_k = build_k(sys_config.input_s0_config);
|
|
if (output_r[2]) temp_k = temp_k | build_k(sys_config.input_s1_config);
|
|
if (output_r[3]) temp_k = temp_k | build_k(sys_config.input_s2_config);
|
|
end
|
|
default: begin
|
|
// SM510/SM510 Tiger
|
|
if (output_shifter_s[0]) temp_k = build_k(sys_config.input_s0_config);
|
|
if (output_shifter_s[1]) temp_k = temp_k | build_k(sys_config.input_s1_config);
|
|
if (output_shifter_s[2]) temp_k = temp_k | build_k(sys_config.input_s2_config);
|
|
if (output_shifter_s[3]) temp_k = temp_k | build_k(sys_config.input_s3_config);
|
|
if (output_shifter_s[4]) temp_k = temp_k | build_k(sys_config.input_s4_config);
|
|
if (output_shifter_s[5]) temp_k = temp_k | build_k(sys_config.input_s5_config);
|
|
if (output_shifter_s[6]) temp_k = temp_k | build_k(sys_config.input_s6_config);
|
|
if (output_shifter_s[7]) temp_k = temp_k | build_k(sys_config.input_s7_config);
|
|
end
|
|
endcase
|
|
|
|
main_input_k <= temp_k;
|
|
|
|
input_wake <= (
|
|
build_wake_k(sys_config.input_s0_config) |
|
|
build_wake_k(sys_config.input_s1_config) |
|
|
build_wake_k(sys_config.input_s2_config) |
|
|
build_wake_k(sys_config.input_s3_config) |
|
|
build_wake_k(sys_config.input_s4_config) |
|
|
build_wake_k(sys_config.input_s5_config) |
|
|
build_wake_k(sys_config.input_s6_config) |
|
|
build_wake_k(sys_config.input_s7_config)
|
|
) != 4'd0;
|
|
end
|
|
|
|
always @(posedge clk) begin
|
|
reg [3:0] grounded_input_k;
|
|
|
|
grounded_input_k = {
|
|
input_mux(grounded_input_config[31:24]),
|
|
input_mux(grounded_input_config[23:16]),
|
|
input_mux(grounded_input_config[15:8]),
|
|
input_mux(grounded_input_config[7:0])
|
|
};
|
|
|
|
input_k <= main_input_k | grounded_input_k;
|
|
|
|
input_beta <= input_mux(sys_config.input_b_config);
|
|
input_ba <= input_mux(sys_config.input_ba_config);
|
|
input_acl <= input_mux(sys_config.input_acl_config);
|
|
end
|
|
|
|
endmodule
|