mirror of
https://github.com/djhackersdev/bemanitools.git
synced 2024-11-24 06:40:11 +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:
parent
23ca366f78
commit
3a89502498
@ -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
|
||||
|
16
src/main/p3io-ddr-tool/Module.mk
Normal file
16
src/main/p3io-ddr-tool/Module.mk
Normal 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 \
|
774
src/main/p3io-ddr-tool/main.c
Normal file
774
src/main/p3io-ddr-tool/main.c
Normal 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;
|
||||
}
|
406
src/main/p3io-ddr-tool/mode-test.c
Normal file
406
src/main/p3io-ddr-tool/mode-test.c
Normal 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;
|
||||
}
|
11
src/main/p3io-ddr-tool/mode-test.h
Normal file
11
src/main/p3io-ddr-tool/mode-test.h
Normal 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
|
Loading…
Reference in New Issue
Block a user