230 lines
5.0 KiB
C
230 lines
5.0 KiB
C
// clang-format off
|
|
// Don't format because the order is important here
|
|
#include <windows.h>
|
|
#include <setupapi.h>
|
|
#include <stdlib.h>
|
|
// clang-format on
|
|
|
|
#include "aciomgr/manager.h"
|
|
|
|
#include "cconfig/cconfig-main.h"
|
|
|
|
#include "bemanitools/jbio.h"
|
|
|
|
#include "jbio-p4io/config-h44b.h"
|
|
#include "jbio-p4io/h44b.h"
|
|
|
|
#include "p4iodrv/device.h"
|
|
|
|
#include "util/log.h"
|
|
|
|
static struct p4iodrv_ctx *p4io_ctx;
|
|
static uint16_t jb_io_panels;
|
|
static uint8_t jb_io_sys_buttons;
|
|
|
|
static bool lights_present;
|
|
static struct ac_io_h44b_output jb_io_lights;
|
|
static struct ac_io_h44b_output jb_io_new_lights;
|
|
|
|
static bool coin_blocked;
|
|
|
|
void jb_io_set_loggers(
|
|
log_formatter_t misc,
|
|
log_formatter_t info,
|
|
log_formatter_t warning,
|
|
log_formatter_t fatal)
|
|
{
|
|
aciomgr_set_loggers(misc, info, warning, fatal);
|
|
|
|
log_to_external(misc, info, warning, fatal);
|
|
}
|
|
|
|
bool jb_io_init(
|
|
thread_create_t thread_create,
|
|
thread_join_t thread_join,
|
|
thread_destroy_t thread_destroy)
|
|
{
|
|
struct cconfig *config;
|
|
struct h44b_config config_h44b;
|
|
|
|
config = cconfig_init();
|
|
|
|
jbio_config_h44b_init(config);
|
|
|
|
if (!cconfig_main_config_init(
|
|
config,
|
|
"--h44b-config",
|
|
"jbio-h44b.conf",
|
|
"--help",
|
|
"-h",
|
|
"jbio-h44b",
|
|
CCONFIG_CMD_USAGE_OUT_STDOUT)) {
|
|
cconfig_finit(config);
|
|
exit(EXIT_FAILURE);
|
|
}
|
|
|
|
jbio_config_h44b_get(&config_h44b, config);
|
|
|
|
cconfig_finit(config);
|
|
|
|
p4io_ctx = p4iodrv_open();
|
|
if(!p4io_ctx) {
|
|
return false;
|
|
}
|
|
|
|
// some people use p4io just for inputs and have no lights. Soft fail when
|
|
// h44b is not able to be connected instead of returning false
|
|
lights_present = jb_io_h44b_init(config_h44b.port, config_h44b.baud);
|
|
if(!lights_present) {
|
|
log_warning("Could not connect to H44B, lights disabled");
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void jb_io_fini(void)
|
|
{
|
|
p4iodrv_close(p4io_ctx);
|
|
}
|
|
|
|
static const uint32_t jb_io_panel_mappings[] = {
|
|
(1 << 5),
|
|
(1 << 1),
|
|
(1 << 13),
|
|
(1 << 9),
|
|
(1 << 6),
|
|
(1 << 2),
|
|
(1 << 14),
|
|
(1 << 10),
|
|
(1 << 7),
|
|
(1 << 3),
|
|
(1 << 15),
|
|
(1 << 11),
|
|
(1 << 16),
|
|
(1 << 4),
|
|
(1 << 20),
|
|
(1 << 12),
|
|
};
|
|
|
|
static const uint32_t jb_io_sys_button_mappings[] = {
|
|
(1 << 28),
|
|
(1 << 25),
|
|
};
|
|
|
|
bool jb_io_read_inputs(void)
|
|
{
|
|
uint32_t jamma[4];
|
|
if(!p4iodrv_read_jamma(p4io_ctx, jamma)) {
|
|
return false;
|
|
}
|
|
|
|
jb_io_panels = 0;
|
|
jb_io_sys_buttons = 0;
|
|
|
|
// panel is active low
|
|
uint32_t panel_in = ~jamma[0];
|
|
|
|
for (uint8_t i = 0; i < 16; i++) {
|
|
if (panel_in & jb_io_panel_mappings[i]) {
|
|
jb_io_panels |= 1 << i;
|
|
}
|
|
}
|
|
|
|
// sys is active high
|
|
for (uint8_t i = 0; i < 2; i++) {
|
|
if (jamma[0] & jb_io_sys_button_mappings[i]) {
|
|
jb_io_sys_buttons |= 1 << i;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool jb_io_write_lights(void)
|
|
{
|
|
if(lights_present && memcmp(&jb_io_lights, &jb_io_new_lights, sizeof(jb_io_lights))) {
|
|
memcpy(&jb_io_lights, &jb_io_new_lights, sizeof(jb_io_lights));
|
|
return jb_io_h44b_write_lights(&jb_io_lights);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
uint8_t jb_io_get_sys_inputs(void)
|
|
{
|
|
return jb_io_sys_buttons;
|
|
}
|
|
|
|
uint16_t jb_io_get_panel_inputs(void)
|
|
{
|
|
return jb_io_panels;
|
|
}
|
|
|
|
bool jb_io_set_panel_mode(enum jb_io_panel_mode mode)
|
|
{
|
|
struct p4io_req_panel_mode panel_mode = {0};
|
|
|
|
panel_mode.is_single = 1;
|
|
|
|
switch(mode) {
|
|
case JB_IO_PANEL_MODE_ALL:
|
|
panel_mode.is_single = 0;
|
|
panel_mode.mode = 0;
|
|
break;
|
|
case JB_IO_PANEL_MODE_TOP_LEFT:
|
|
panel_mode.mode = 0x0001;
|
|
break;
|
|
case JB_IO_PANEL_MODE_TOP_RIGHT:
|
|
panel_mode.mode = 0x0000;
|
|
break;
|
|
case JB_IO_PANEL_MODE_BOTTOM_LEFT:
|
|
panel_mode.mode = 0x0101;
|
|
break;
|
|
case JB_IO_PANEL_MODE_BOTTOM_RIGHT:
|
|
panel_mode.mode = 0x0100;
|
|
break;
|
|
}
|
|
|
|
return p4iodrv_cmd_portout(p4io_ctx, (uint8_t*)&panel_mode);
|
|
}
|
|
|
|
void jb_io_set_rgb_led(enum jb_io_rgb_led unit, uint8_t r, uint8_t g, uint8_t b)
|
|
{
|
|
uint8_t *light;
|
|
|
|
switch(unit) {
|
|
case JB_IO_RGB_LED_FRONT:
|
|
light = jb_io_new_lights.front_rgb;
|
|
break;
|
|
case JB_IO_RGB_LED_TOP:
|
|
light = jb_io_new_lights.top_rgb;
|
|
break;
|
|
case JB_IO_RGB_LED_LEFT:
|
|
light = jb_io_new_lights.left_rgb;
|
|
break;
|
|
case JB_IO_RGB_LED_RIGHT:
|
|
light = jb_io_new_lights.right_rgb;
|
|
break;
|
|
case JB_IO_RGB_LED_TITLE:
|
|
light = jb_io_new_lights.title_rgb;
|
|
break;
|
|
case JB_IO_RGB_LED_WOOFER:
|
|
light = jb_io_new_lights.woofer_rgb;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
light[0] = r;
|
|
light[1] = g;
|
|
light[2] = b;
|
|
}
|
|
|
|
bool jb_io_set_coin_blocker(bool blocked) {
|
|
coin_blocked = blocked;
|
|
|
|
uint8_t coin[4] = {0};
|
|
coin[0] = coin_blocked ? 0x00 : 0x20;
|
|
return p4iodrv_cmd_coinstock(p4io_ctx, coin);
|
|
}
|