1
0
mirror of https://github.com/djhackersdev/bemanitools.git synced 2024-11-28 00:10:51 +01:00

feat(p3io-ddr-tool): CLI tool to test and debug a real DDR P3IO

Extensive tool with subcommands to trigger the various
P3IO commands and run the P3IO + EXTIO DDR hardware
combo with a hardware test menu.
This commit is contained in:
icex2 2023-06-11 17:18:22 +02:00 committed by icex2
parent 23ca366f78
commit 3a89502498
5 changed files with 1208 additions and 0 deletions

View File

@ -171,6 +171,7 @@ include src/main/mm/Module.mk
include src/main/p3io/Module.mk
include src/main/p3iodrv/Module.mk
include src/main/p3ioemu/Module.mk
include src/main/p3io-ddr-tool/Module.mk
include src/main/p4iodrv/Module.mk
include src/main/p4ioemu/Module.mk
include src/main/popnhook-util/Module.mk

View File

@ -0,0 +1,16 @@
exes += p3io-ddr-tool \
ldflags_p3io-ddr-tool := \
-lsetupapi \
libs_p3io-ddr-tool := \
extiodrv \
extio \
p3iodrv \
p3io \
hook \
util \
src_p3io-ddr-tool := \
main.c \
mode-test.c \

View File

@ -0,0 +1,774 @@
#define LOG_MODULE "p3io-ddr-tool"
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "extiodrv/extio.h"
#include "p3io/ddr.h"
#include "p3iodrv/ddr.h"
#include "p3iodrv/device.h"
#include "util/log.h"
#include "util/thread.h"
#include "mode-test.h"
enum mode {
MODE_INVALID = 0,
MODE_SCAN = 1,
MODE_VERP3IO = 2,
MODE_INIT = 3,
MODE_VERDDR = 4,
MODE_WATCHDOGON = 5,
MODE_WATCHDOGOFF = 6,
MODE_CABTYPE = 7,
MODE_DIPSW = 8,
MODE_VIDEOFREQ = 9,
MODE_TEST = 10,
MODE_LIGHTOFF = 11,
MODE_POLL = 12,
MODE_SENSORES = 13,
MODE_TOTAL_COUNT = 14,
};
typedef bool (*mode_proc)(HANDLE handle);
static bool _mode_invalid(HANDLE handle);
static bool _mode_scan(HANDLE handle);
static bool _mode_verp3io(HANDLE handle);
static bool _mode_init(HANDLE handle);
static bool _mode_verddr(HANDLE handle);
static bool _mode_watchdogon(HANDLE handle);
static bool _mode_watchdogoff(HANDLE handle);
static bool _mode_cabtype(HANDLE handle);
static bool _mode_dipsw(HANDLE handle);
static bool _mode_videofreq(HANDLE handle);
static bool _mode_test(HANDLE handle);
static bool _mode_lightoff(HANDLE handle);
static bool _mode_poll(HANDLE handle);
static bool _mode_sensores(HANDLE handle);
static mode_proc _mode_procs[MODE_TOTAL_COUNT] = {
_mode_invalid,
_mode_scan,
_mode_verp3io,
_mode_init,
_mode_verddr,
_mode_watchdogon,
_mode_watchdogoff,
_mode_cabtype,
_mode_dipsw,
_mode_videofreq,
_mode_test,
_mode_lightoff,
_mode_poll,
_mode_sensores,
};
static enum log_level _log_level = LOG_LEVEL_FATAL;
static bool _extio_enabled = true;
static const char *_p3io_device_path = "";
static const char *_extio_com_port = "COM1";
static enum mode _mode = MODE_INVALID;
static bool _scan_and_open(HANDLE *handle)
{
HRESULT hr;
char path[MAX_PATH];
log_info("Scanning for p3io...");
hr = p3iodrv_device_scan(path);
if (FAILED(hr)) {
log_warning("Cannot find a connected p3io: %lX", hr);
return false;
}
log_info("Opening p3io: %s", path);
hr = p3iodrv_device_open(path, handle);
if (FAILED(hr)) {
log_warning("Opening p3io failed: %lX", hr);
return false;
}
return true;
}
static bool _close(HANDLE handle)
{
HRESULT hr;
log_info("Closing p3io...");
hr = p3iodrv_device_close(handle);
if (FAILED(hr)) {
log_warning("Closing p3io failed: %lX", hr);
return false;
}
return true;
}
static bool _process_cmd_args(int argc, char **argv)
{
char *mode;
if (argc < 2) {
fprintf(stderr, "DDR P3IO and EXTIO CLI testing tool\n");
fprintf(stderr, "\n");
fprintf(stderr, "Usage: [ARG ...] MODE\n");
fprintf(stderr, "Arguments:\n");
fprintf(
stderr,
" -v Enable additional logging, log level 'warning'\n");
fprintf(
stderr,
" -vv Enable additional logging, log level 'info'\n");
fprintf(
stderr,
" -vvv Enable additional logging, log level 'misc' (very "
"verbose)\n");
fprintf(
stderr,
" -noextio Run the tool without an EXTIO. This also impacts "
"various functionality, e.g. sensor polling, light outputs\n");
fprintf(
stderr,
" -p3io Explicit device path pointing to a P3IO device to "
"open. If not provided, the device will be automatically scanned "
"for.\n");
fprintf(
stderr,
" -extio Explicitly set the COM port the EXTIO is connected "
"to, e.g. COM4. If not provided COM1 is used.\n");
fprintf(stderr, "\n");
fprintf(stderr, "Modes:\n");
fprintf(
stderr,
" scan: Scan for a connected P3IO device. Outputs the full device "
"path to stdout if found.\n");
fprintf(
stderr,
" verp3io: Get and print the P3IO version information to "
"stdout.\n");
fprintf(stderr, " init: Initialize the P3IO (\"DDR mode\").\n");
fprintf(
stderr,
" verddr: Get and print the DDR P3IO specific information to "
"stdout.\n");
fprintf(stderr, " watchdogon: Turn the watchdog on.\n");
fprintf(stderr, " watchdogoff: Turn the watchdog off.\n");
fprintf(
stderr,
" cabtype: Get and print the cabinet type information to "
"stdout.\n");
fprintf(
stderr, " dipsw: Get and print the DIP switch state to stdout.\n");
fprintf(
stderr,
" videofreq: Get and print the detected video frequency to "
"stdout.\n");
fprintf(
stderr,
" test: Run interactive test mode, executes a polling read/write "
"loop to drive the IO and displays the current input states.\n");
fprintf(stderr, " lightoff: Turn all the lights off\n");
fprintf(
stderr,
" poll: Run a simple polling loop that polls data from the JAMMA "
"endpoint with input state output.\n");
fprintf(
stderr,
" sensores: Run cycling individual sensores in a simple polling "
"loop with input state ouptut.\n");
return false;
}
for (int i = 0; i < argc; i++) {
if (!strcmp(argv[i], "-v")) {
_log_level = LOG_LEVEL_WARNING;
} else if (!strcmp(argv[i], "-vv")) {
_log_level = LOG_LEVEL_INFO;
} else if (!strcmp(argv[i], "-vvv")) {
_log_level = LOG_LEVEL_MISC;
} else if (!strcmp(argv[i], "-noextio")) {
_extio_enabled = false;
} else if (!strcmp(argv[i], "-p3io")) {
if (i + 1 < argc) {
_p3io_device_path = argv[++i];
} else {
fprintf(stderr, "Missing value for -p3io argument\n");
}
} else if (!strcmp(argv[i], "-extio")) {
if (i + 1 < argc) {
_extio_com_port = argv[++i];
} else {
fprintf(stderr, "Missing value for -extio argument\n");
}
}
}
mode = argv[argc - 1];
if (!strcmp(mode, "scan")) {
_mode = MODE_SCAN;
} else if (!strcmp(mode, "verp3io")) {
_mode = MODE_VERP3IO;
} else if (!strcmp(mode, "init")) {
_mode = MODE_INIT;
} else if (!strcmp(mode, "verddr")) {
_mode = MODE_VERDDR;
} else if (!strcmp(mode, "watchdogon")) {
_mode = MODE_WATCHDOGON;
} else if (!strcmp(mode, "watchdogoff")) {
_mode = MODE_WATCHDOGOFF;
} else if (!strcmp(mode, "cabtype")) {
_mode = MODE_CABTYPE;
} else if (!strcmp(mode, "dipsw")) {
_mode = MODE_DIPSW;
} else if (!strcmp(mode, "videofreq")) {
_mode = MODE_VIDEOFREQ;
} else if (!strcmp(mode, "test")) {
_mode = MODE_TEST;
} else if (!strcmp(mode, "lightoff")) {
_mode = MODE_LIGHTOFF;
} else if (!strcmp(mode, "poll")) {
_mode = MODE_POLL;
} else if (!strcmp(mode, "sensores")) {
_mode = MODE_SENSORES;
} else {
fprintf(stderr, "Invalid mode '%s'", mode);
return false;
}
return true;
}
static void _init_logging()
{
log_to_writer(log_writer_stderr, NULL);
log_set_level(_log_level);
}
static bool _mode_invalid(HANDLE handle)
{
fprintf(stderr, "Invalid mode");
return false;
}
static bool _mode_scan(HANDLE handle)
{
HRESULT hr;
char path[MAX_PATH];
log_info("Scanning for p3io...");
hr = p3iodrv_device_scan(path);
if (FAILED(hr)) {
log_warning("Cannot find a connected p3io: %lX", hr);
return false;
}
log_info("Found p3io: %s", path);
printf("%s\n", path);
return true;
}
static bool _mode_verp3io(HANDLE handle)
{
HRESULT hr;
char version[P3IODRV_VERSION_MAX_LEN];
memset(version, 0, P3IODRV_VERSION_MAX_LEN);
hr = p3iodrv_device_read_version(handle, version);
if (FAILED(hr)) {
log_warning("Getting version failed: %lX", hr);
return _close(handle);
}
log_info("Version (P3IO): %s", version);
printf("%s\n", version);
return true;
}
static bool _mode_init(HANDLE handle)
{
HRESULT hr;
hr = p3iodrv_ddr_init(handle);
if (FAILED(hr)) {
log_warning("Init failed: %lX", hr);
return false;
}
log_info("Initialized");
return true;
}
static bool _mode_verddr(HANDLE handle)
{
HRESULT hr;
char str[4];
uint32_t major;
uint32_t minor;
uint32_t patch;
hr = p3iodrv_ddr_get_version(handle, str, &major, &minor, &patch);
if (FAILED(hr)) {
log_warning("Getting DDR version failed: %lX", hr);
return false;
}
log_info("Version (DDR): %s %d.%d.%d", str, major, minor, patch);
printf("%s %d.%d.%d\n", str, major, minor, patch);
return true;
}
static bool _mode_watchdogon(HANDLE handle)
{
HRESULT hr;
hr = p3iodrv_ddr_set_watchdog(handle, true);
if (FAILED(hr)) {
log_warning("Enabling watchdog failed: %lX", hr);
return false;
}
log_info("Watchdog on");
return true;
}
static bool _mode_watchdogoff(HANDLE handle)
{
HRESULT hr;
hr = p3iodrv_ddr_set_watchdog(handle, false);
if (FAILED(hr)) {
log_warning("Disabling watchdog failed: %lX", hr);
return false;
}
log_info("Watchdog off");
return true;
}
static bool _mode_cabtype(HANDLE handle)
{
HRESULT hr;
enum p3io_cab_type type;
const char *type_str;
hr = p3iodrv_ddr_get_cab_type(handle, &type);
if (FAILED(hr)) {
log_warning("Getting cab type failed: %lX", hr);
return false;
}
log_info("Cabinet type: %d", type);
switch (type) {
case P3IO_CAB_TYPE_SD:
type_str = "sd";
break;
case P3IO_CAB_TYPE_HD:
type_str = "hd";
break;
default:
type_str = "unknown";
break;
}
printf("%s\n", type_str);
return true;
}
static bool _mode_dipsw(HANDLE handle)
{
HRESULT hr;
uint8_t dip_sw;
hr = p3iodrv_ddr_get_dipsw(handle, &dip_sw);
if (FAILED(hr)) {
log_warning("Getting dip switches failed: %lX", hr);
return false;
}
log_info("Dip switches: 0x%X", dip_sw);
printf("0x%X\n", dip_sw);
return true;
}
static bool _mode_videofreq(HANDLE handle)
{
HRESULT hr;
enum p3io_video_freq video_freq;
const char *video_freq_str;
hr = p3iodrv_ddr_get_video_freq(handle, &video_freq);
if (FAILED(hr)) {
log_warning("Getting video freq failed: %lX", hr);
return false;
}
log_info("Video freq: 0x%X", video_freq);
switch (video_freq) {
case P3IO_VIDEO_FREQ_15KHZ:
video_freq_str = "15khz";
break;
case P3IO_VIDEO_FREQ_31KHZ:
video_freq_str = "31khz";
break;
default:
video_freq_str = "unknown";
break;
}
printf("%s\n", video_freq_str);
return true;
}
static bool _mode_test(HANDLE handle_p3io)
{
HRESULT hr;
HANDLE handle_extio;
bool result;
if (_extio_enabled) {
hr = extiodrv_device_open(_extio_com_port, &handle_extio);
if (FAILED(hr)) {
log_warning(
"Failed opening EXTIO on com port '%s': %lX",
_extio_com_port,
hr);
return false;
}
} else {
handle_extio = INVALID_HANDLE_VALUE;
}
result = mode_test_proc(handle_p3io, handle_extio);
if (_extio_enabled) {
hr = extiodrv_device_close(&handle_extio);
if (FAILED(hr)) {
log_warning("Failed closing EXTIO: %lX", hr);
result = false;
}
}
return result;
}
static bool _mode_lightoff(HANDLE handle_p3io)
{
HRESULT hr;
HANDLE handle_extio;
struct p3io_ddr_output output;
struct extiodrv_extio_pad_lights pad_lights[EXTIO_PAD_LIGHT_MAX_PLAYERS];
bool neons;
memset(&output, 0, sizeof(output));
memset(&pad_lights, 0, sizeof(pad_lights));
neons = false;
if (_extio_enabled) {
hr = extiodrv_device_open(_extio_com_port, &handle_extio);
if (FAILED(hr)) {
log_warning(
"Failed opening EXTIO on com port '%s': %lX",
_extio_com_port,
hr);
return false;
}
} else {
handle_extio = INVALID_HANDLE_VALUE;
}
hr = p3iodrv_ddr_set_outputs(handle_p3io, &output);
if (FAILED(hr)) {
log_warning("Setting outputs failed: %lX", hr);
return false;
}
if (_extio_enabled) {
hr = extiodrv_extio_transfer(
handle_extio,
EXTIODRV_EXTIO_SENSOR_READ_MODE_ALL,
pad_lights,
neons);
if (FAILED(hr)) {
log_warning("extio transfer failed: %lX", hr);
return false;
}
}
if (_extio_enabled) {
hr = extiodrv_device_close(&handle_extio);
if (FAILED(hr)) {
log_warning("Failed closing EXTIO: %lX", hr);
return false;
}
}
return true;
}
static bool _mode_poll(HANDLE handle_p3io)
{
HRESULT hr;
HANDLE handle_extio;
struct p3io_ddr_jamma jamma;
struct p3io_ddr_output output;
struct extiodrv_extio_pad_lights pad_lights[EXTIO_PAD_LIGHT_MAX_PLAYERS];
bool neons;
uint32_t cnt;
memset(&output, 0, sizeof(output));
memset(&pad_lights, 0, sizeof(pad_lights));
neons = false;
if (_extio_enabled) {
hr = extiodrv_device_open(_extio_com_port, &handle_extio);
if (FAILED(hr)) {
log_warning(
"Failed opening EXTIO on com port '%s': %lX",
_extio_com_port,
hr);
return false;
}
} else {
handle_extio = INVALID_HANDLE_VALUE;
}
fprintf(
stderr,
">>> Press enter to start endless polling loop. Press Escape to exit "
"to exit polling loop <<<\n");
if (getchar() != '\n') {
return true;
}
cnt = 0;
while ((GetAsyncKeyState(VK_ESCAPE) & 0x8000) == 0) {
hr = p3iodrv_ddr_set_outputs(handle_p3io, &output);
if (FAILED(hr)) {
log_warning("Setting outputs failed: %lX", hr);
return false;
}
if (_extio_enabled) {
hr = extiodrv_extio_transfer(
handle_extio,
EXTIODRV_EXTIO_SENSOR_READ_MODE_ALL,
pad_lights,
neons);
if (FAILED(hr)) {
log_warning("extio transfer failed: %lX", hr);
return false;
}
}
hr = p3iodrv_ddr_get_jamma(handle_p3io, &jamma);
if (FAILED(hr)) {
log_warning("Reading jamma failed: %lX", hr);
return false;
}
printf(
"%d: %08X %08X %08X\n",
cnt,
*((uint32_t *) &jamma) & 0xFFFFFF00,
jamma.unused,
jamma.unused2);
cnt++;
}
if (_extio_enabled) {
hr = extiodrv_device_close(&handle_extio);
if (FAILED(hr)) {
log_warning("Failed closing EXTIO: %lX", hr);
return false;
}
}
return true;
}
static bool _mode_sensores(HANDLE handle_p3io)
{
HRESULT hr;
HANDLE handle_extio;
struct p3io_ddr_jamma jamma;
struct p3io_ddr_output output;
struct extiodrv_extio_pad_lights pad_lights[EXTIO_PAD_LIGHT_MAX_PLAYERS];
bool neons;
uint32_t cnt;
uint8_t sensor_read;
memset(&output, 0, sizeof(output));
memset(&pad_lights, 0, sizeof(pad_lights));
neons = false;
if (_extio_enabled) {
hr = extiodrv_device_open(_extio_com_port, &handle_extio);
if (FAILED(hr)) {
log_warning(
"Failed opening EXTIO on com port '%s': %lX",
_extio_com_port,
hr);
return false;
}
} else {
handle_extio = INVALID_HANDLE_VALUE;
}
fprintf(
stderr,
">>> Press enter to start endless sensor cycling loop. Press Escape to "
"exit to exit sensor cycling loop <<<\n");
if (getchar() != '\n') {
return true;
}
cnt = 0;
sensor_read = 0;
while ((GetAsyncKeyState(VK_ESCAPE) & 0x8000) == 0) {
hr = p3iodrv_ddr_set_outputs(handle_p3io, &output);
if (FAILED(hr)) {
log_warning("Setting outputs failed: %lX", hr);
return false;
}
if (_extio_enabled) {
hr = extiodrv_extio_transfer(
handle_extio, sensor_read + 1, pad_lights, neons);
if (FAILED(hr)) {
log_warning("extio transfer failed: %lX", hr);
return false;
}
}
hr = p3iodrv_ddr_get_jamma(handle_p3io, &jamma);
if (FAILED(hr)) {
log_warning("Reading jamma failed: %lX", hr);
return false;
}
printf(
"%d (%d): %08X %08X %08X\n",
cnt,
sensor_read,
*((uint32_t *) &jamma) & 0xFFFFFF00,
jamma.unused,
jamma.unused2);
cnt++;
sensor_read++;
if (sensor_read > 3) {
sensor_read = 0;
}
}
if (_extio_enabled) {
hr = extiodrv_device_close(&handle_extio);
if (FAILED(hr)) {
log_warning("Failed closing EXTIO: %lX", hr);
return false;
}
}
return true;
}
int main(int argc, char **argv)
{
HANDLE handle;
bool result;
if (!_process_cmd_args(argc, argv)) {
return -1;
}
_init_logging();
if (_mode != MODE_SCAN) {
if (!_scan_and_open(&handle)) {
result = false;
} else {
result = _mode_procs[_mode](handle);
if (!_close(&handle)) {
result = false;
}
}
} else {
result = _mode_procs[_mode](INVALID_HANDLE_VALUE);
}
return result ? 0 : -1;
}

View File

@ -0,0 +1,406 @@
#define LOG_MODULE "mode-test"
#include <stdio.h>
#include <stdlib.h>
#include "extiodrv/extio.h"
#include "p3io/ddr.h"
#include "p3iodrv/ddr.h"
#include "p3iodrv/device.h"
#include "util/log.h"
#include "mode-test.h"
struct mode_test_output_state {
struct p3io_ddr_output output;
struct extiodrv_extio_pad_lights pad_lights[EXTIO_PAD_LIGHT_MAX_PLAYERS];
bool neons;
};
struct mode_test_input_state {
struct p3io_ddr_jamma jamma[4];
};
static bool _check_input_state_change(
const struct mode_test_input_state *cur_state,
const struct mode_test_input_state *prev_state)
{
return !memcmp(cur_state, prev_state, sizeof(struct mode_test_input_state));
}
static void _input_state_swap(
struct mode_test_input_state **cur_state,
struct mode_test_input_state **prev_state)
{
struct mode_test_input_state *tmp;
tmp = *cur_state;
*cur_state = *prev_state;
*prev_state = tmp;
}
static bool _update_io_frame(
HANDLE handle_p3io,
HANDLE handle_extio,
bool polling_mode,
struct mode_test_input_state *input,
const struct mode_test_output_state *output)
{
HRESULT hr;
hr = p3iodrv_ddr_set_outputs(handle_p3io, &output->output);
if (FAILED(hr)) {
log_warning("Setting outputs failed: %lX", hr);
return false;
}
if (polling_mode) {
hr = extiodrv_extio_transfer(
handle_extio,
EXTIODRV_EXTIO_SENSOR_READ_MODE_ALL,
output->pad_lights,
output->neons);
if (FAILED(hr)) {
log_warning("extio transfer failed: %lX", hr);
return false;
}
hr = p3iodrv_ddr_get_jamma(handle_p3io, &input->jamma[0]);
if (FAILED(hr)) {
log_warning("Reading jamma failed: %lX", hr);
return false;
}
} else {
for (uint8_t i = 0; i < 4; i++) {
hr = extiodrv_extio_transfer(
handle_extio, i + 1, output->pad_lights, output->neons);
if (FAILED(hr)) {
log_warning("extio transfer failed: %lX", hr);
return false;
}
hr = p3iodrv_ddr_get_jamma(handle_p3io, &input->jamma[i]);
if (FAILED(hr)) {
log_warning("Reading jamma failed: %lX", hr);
return false;
}
}
}
return true;
}
static void _set_outputs_on_inputs(
const struct mode_test_input_state *input,
struct mode_test_output_state *output)
{
memset(&output->pad_lights, 0, sizeof(output->pad_lights));
output->output.cabinet.p1_menu_buttons = 0;
output->output.cabinet.p2_menu_buttons = 0;
for (uint8_t i = 0; i < 4; i++) {
output->pad_lights[0].up |= input->jamma[i].p1.pad_up ? 1 : 0;
output->pad_lights[0].down |= input->jamma[i].p1.pad_down ? 1 : 0;
output->pad_lights[0].left |= input->jamma[i].p1.pad_left ? 1 : 0;
output->pad_lights[0].right |= input->jamma[i].p1.pad_right ? 1 : 0;
output->pad_lights[1].up |= input->jamma[i].p2.pad_up ? 1 : 0;
output->pad_lights[1].down |= input->jamma[i].p2.pad_down ? 1 : 0;
output->pad_lights[1].left |= input->jamma[i].p2.pad_left ? 1 : 0;
output->pad_lights[1].right |= input->jamma[i].p2.pad_right ? 1 : 0;
output->output.cabinet.p1_menu_buttons |=
(input->jamma[i].p1.menu_left || input->jamma[i].p1.menu_right ||
input->jamma[i].p1.menu_start) ?
1 :
0;
output->output.cabinet.p2_menu_buttons |=
(input->jamma[i].p2.menu_left || input->jamma[i].p2.menu_right ||
input->jamma[i].p2.menu_start) ?
1 :
0;
}
}
static void _render_main(
uint8_t cnt, bool polling_mode, const struct mode_test_input_state *state)
{
printf("Counter: %d\n", cnt);
printf("Polling mode: %d\n", polling_mode);
printf("Player 1 Player 2\n");
printf("\n");
printf("Pad\n");
if (polling_mode) {
printf(
"Up: %d Up: %d\n",
state->jamma[0].p1.pad_up,
state->jamma[0].p2.pad_up);
printf(
"Down: %d Down: %d\n",
state->jamma[0].p1.pad_down,
state->jamma[0].p2.pad_down);
printf(
"Left: %d Left: %d\n",
state->jamma[0].p1.pad_left,
state->jamma[0].p2.pad_left);
printf(
"Right: %d Right: %d\n",
state->jamma[0].p1.pad_right,
state->jamma[0].p2.pad_right);
} else {
printf(
"Up: %c%c%c%c Up: %c%c%c%c\n",
state->jamma[0].p1.pad_up ? 'U' : '_',
state->jamma[1].p1.pad_up ? 'D' : '_',
state->jamma[2].p1.pad_up ? 'L' : '_',
state->jamma[3].p1.pad_up ? 'R' : '_',
state->jamma[0].p2.pad_up ? 'U' : '_',
state->jamma[1].p2.pad_up ? 'D' : '_',
state->jamma[2].p2.pad_up ? 'L' : '_',
state->jamma[3].p2.pad_up) ?
'R' :
'_';
printf(
"Down: %c%c%c%c Down: %c%c%c%c\n",
state->jamma[0].p1.pad_down ? 'U' : '_',
state->jamma[1].p1.pad_down ? 'D' : '_',
state->jamma[2].p1.pad_down ? 'L' : '_',
state->jamma[3].p1.pad_down ? 'R' : '_',
state->jamma[0].p2.pad_down ? 'U' : '_',
state->jamma[1].p2.pad_down ? 'D' : '_',
state->jamma[2].p2.pad_down ? 'L' : '_',
state->jamma[3].p2.pad_down ? 'R' : '_');
printf(
"Left: %c%c%c%c Left: %c%c%c%c\n",
state->jamma[0].p1.pad_left ? 'U' : '_',
state->jamma[1].p1.pad_left ? 'D' : '_',
state->jamma[2].p1.pad_left ? 'L' : '_',
state->jamma[3].p1.pad_left ? 'R' : '_',
state->jamma[0].p2.pad_left ? 'U' : '_',
state->jamma[1].p2.pad_left ? 'D' : '_',
state->jamma[2].p2.pad_left ? 'L' : '_',
state->jamma[3].p2.pad_left ? 'R' : '_');
printf(
"Right: %c%c%c%c Right: %c%c%c%c\n",
state->jamma[0].p1.pad_right ? 'U' : '_',
state->jamma[1].p1.pad_right ? 'D' : '_',
state->jamma[2].p1.pad_right ? 'L' : '_',
state->jamma[3].p1.pad_right ? 'R' : '_',
state->jamma[0].p2.pad_right ? 'U' : '_',
state->jamma[1].p2.pad_right ? 'D' : '_',
state->jamma[2].p2.pad_right ? 'L' : '_',
state->jamma[3].p2.pad_right ? 'R' : '_');
}
printf("\n");
printf("Menu\n");
printf(
"Start: %d Start: %d\n",
state->jamma[0].p1.menu_start,
state->jamma[0].p2.menu_start);
printf(
"Up: %d Up: %d\n",
state->jamma[0].operator.p1_menu_up,
state->jamma[0].operator.p2_menu_up);
printf(
"Down: %d Down: %d\n",
state->jamma[0].operator.p1_menu_down,
state->jamma[0].operator.p2_menu_down);
printf(
"Left: %d Left: %d\n",
state->jamma[0].p1.menu_left,
state->jamma[0].p2.menu_left);
printf(
"Right: %d Right: %d\n",
state->jamma[0].p1.menu_right,
state->jamma[0].p2.menu_right);
printf("\n");
printf("Operator\n");
printf(
"Test: %d Service: %d Coin: %d\n",
state->jamma[0].operator.test,
state->jamma[0].operator.service,
state->jamma[0].operator.coin);
}
static void
_render_menu(bool *continue_loop, struct mode_test_output_state *output)
{
printf(
"Menu options:\n"
" 0: Exit menu and continue loop\n"
" 1: Exit\n"
" 2: Set neon state\n"
" 3: Top lamp state\n"
" 4: Set all lights on\n"
" 5: Set all lights off\n"
"Waiting for input: ");
char c = getchar();
// Keyboard input debounce
Sleep(10);
switch (c) {
case '1': {
*continue_loop = false;
break;
}
case '2': {
int state;
int n;
printf("Enter neon state (0/1): ");
n = scanf("%d", &state);
if (n > 0) {
output->neons = state > 0;
}
break;
}
case '3': {
char buf[4];
int n;
printf("Enter top lamp state, chain of 0/1s: ");
n = scanf("%8s", buf);
if (n > 0) {
output->output.cabinet.top_p1_upper = buf[0] == '1';
output->output.cabinet.top_p1_lower = buf[1] == '1';
output->output.cabinet.top_p2_upper = buf[2] == '1';
output->output.cabinet.top_p2_lower = buf[3] == '1';
}
break;
}
case '4': {
output->output.cabinet.top_p1_upper = 1;
output->output.cabinet.top_p1_lower = 1;
output->output.cabinet.top_p2_upper = 1;
output->output.cabinet.top_p2_lower = 1;
output->output.cabinet.p1_menu_buttons = 1;
output->output.cabinet.p2_menu_buttons = 1;
output->neons = true;
output->pad_lights[0].up = true;
output->pad_lights[0].down = true;
output->pad_lights[0].left = true;
output->pad_lights[0].right = true;
output->pad_lights[1].up = true;
output->pad_lights[1].down = true;
output->pad_lights[1].left = true;
output->pad_lights[1].right = true;
break;
}
case '5': {
output->output.cabinet.top_p1_upper = 0;
output->output.cabinet.top_p1_lower = 0;
output->output.cabinet.top_p2_upper = 0;
output->output.cabinet.top_p2_lower = 0;
output->output.cabinet.p1_menu_buttons = 0;
output->output.cabinet.p2_menu_buttons = 0;
output->neons = false;
output->pad_lights[0].up = false;
output->pad_lights[0].down = false;
output->pad_lights[0].left = false;
output->pad_lights[0].right = false;
output->pad_lights[1].up = false;
output->pad_lights[1].down = false;
output->pad_lights[1].left = false;
output->pad_lights[1].right = false;
break;
}
case '0':
default:
break;
}
}
bool mode_test_proc(HANDLE handle_p3io, HANDLE handle_extio)
{
struct mode_test_input_state state[2];
struct mode_test_input_state *cur_input_state;
struct mode_test_input_state *prev_input_state;
struct mode_test_output_state output_state;
bool polling_mode;
bool loop;
uint8_t cnt;
memset(&state, 0, sizeof(state));
cur_input_state = &state[0];
prev_input_state = &state[1];
memset(&output_state, 0, sizeof(output_state));
polling_mode = true;
loop = true;
cnt = 0;
fprintf(stderr, ">>> Press enter to start running test mode <<<\n");
if (getchar() != '\n') {
return true;
}
while (loop) {
if ((GetAsyncKeyState(VK_ESCAPE) & 0x8000) != 0) {
system("cls");
_render_menu(&loop, &output_state);
} else {
_input_state_swap(&cur_input_state, &prev_input_state);
memset(cur_input_state, 0, sizeof(struct mode_test_input_state));
if (!_update_io_frame(
handle_p3io,
handle_extio,
polling_mode,
cur_input_state,
&output_state)) {
return false;
}
_set_outputs_on_inputs(cur_input_state, &output_state);
if (_check_input_state_change(cur_input_state, prev_input_state)) {
system("cls");
_render_main(cnt, polling_mode, cur_input_state);
}
}
/* avoid CPU banging */
Sleep(1);
++cnt;
}
return true;
}

View File

@ -0,0 +1,11 @@
#ifndef P3IO_DDR_TOOL_MODE_TEST_H
#define P3IO_DDR_TOOL_MODE_TEST_H
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
bool mode_test_proc(HANDLE handle_p3io, HANDLE handle_extio);
#endif