LED board improvements and cleanup

This commit is contained in:
Dniel97 2023-11-25 23:00:05 +01:00
parent d86baab852
commit 8b1d0cfefa
Signed by untrusted user: Dniel97
GPG Key ID: 6180B3C768FB2E08
30 changed files with 1610 additions and 1379 deletions

222
board/led15093-cmd.h Normal file
View File

@ -0,0 +1,222 @@
#pragma once
#include "board/led15093-frame.h"
/* Command IDs */
enum {
LED_15093_CMD_RESET = 0x10,
LED_15093_CMD_SET_TIMEOUT = 0x11,
LED_15093_CMD_UNK1 = 0x12,
LED_15093_CMD_SET_DISABLE_RESPONSE = 0x14,
LED_15093_CMD_SET_ID = 0x18,
LED_15093_CMD_CLEAR_ID = 0x19,
LED_15093_CMD_SET_MAX_BRIGHT = 0x3F, // TODO
LED_15093_CMD_UPDATE_LED = 0x80,
LED_15093_CMD_SET_LED = 0x81,
LED_15093_CMD_SET_IMM_LED = 0x82,
LED_15093_CMD_SET_FADE_LED = 0x83,
LED_15093_CMD_SET_FADE_LEVEL = 0x84,
LED_15093_CMD_SET_FADE_SHIFT = 0x85,
LED_15093_CMD_SET_AUTO_SHIFT = 0x86,
LED_15093_CMD_GET_BOARD_INFO = 0xF0,
LED_15093_CMD_GET_BOARD_STATUS = 0xF1,
LED_15093_CMD_GET_FW_SUM = 0xF2,
LED_15093_CMD_GET_PROTOCOL_VER = 0xF3,
LED_15093_CMD_SET_BOOTMODE = 0xFD,
LED_15093_CMD_FW_UPDATE = 0xFE,
};
/* Response codes */
enum {
LED_15093_STATUS_OK = 0x01,
LED_15093_STATUS_ERR_SUM = 0x02,
LED_15093_STATUS_ERR_PARITY = 0x03,
LED_15093_STATUS_ERR_FRAMING = 0x04,
LED_15093_STATUS_ERR_OVERRUN = 0x05,
LED_15093_STATUS_ERR_BUFFER_OVERFLOW = 0x06,
};
enum {
LED_15093_REPORT_OK = 0x01,
LED_15093_REPORT_WAIT = 0x02,
LED_15093_REPORT_ERR1 = 0x03,
LED_15093_REPORT_ERR2 = 0x04,
};
/* Status bitmasks */
enum {
LED_15093_STATUS_UART_ERR_SUM = 0x01,
LED_15093_STATUS_UART_ERR_PARITY = 0x02,
LED_15093_STATUS_UART_ERR_FRAMING = 0x04,
LED_15093_STATUS_UART_ERR_OVERRUN = 0x08,
LED_15093_STATUS_UART_ERR_BUFFER_OVERFLOW = 0x10,
};
enum {
LED_15093_STATUS_BOARD_ERR_WDT = 0x01,
LED_15093_STATUS_BOARD_ERR_TIMEOUT = 0x02,
LED_15093_STATUS_BOARD_ERR_RESET = 0x04,
LED_15093_STATUS_BOARD_ERR_BOR = 0x08,
};
enum {
LED_15093_STATUS_CMD_ERR_BUSY = 0x01,
LED_15093_STATUS_CMD_ERR_UNKNOWN = 0x02,
LED_15093_STATUS_CMD_ERR_PARAM = 0x04,
LED_15093_STATUS_CMD_ERR_EXE = 0x08,
};
/* Status types for internal use */
enum {
LED_15093_STATUS_TYPE_BOARD = 1,
LED_15093_STATUS_TYPE_UART = 2,
LED_15093_STATUS_TYPE_CMD = 3,
};
/* Request data structures */
struct led15093_req_reset {
struct led15093_req_hdr hdr;
uint8_t cmd;
uint8_t r_type;
};
struct led15093_req_set_timeout {
struct led15093_req_hdr hdr;
uint8_t cmd;
uint8_t count;
};
struct led15093_req_set_disable_response {
struct led15093_req_hdr hdr;
uint8_t cmd;
bool sw;
};
struct led15093_req_set_id {
struct led15093_req_hdr hdr;
uint8_t cmd;
uint8_t id;
};
struct led15093_req_set_led {
struct led15093_req_hdr hdr;
uint8_t cmd;
uint8_t data[198];
};
struct led15093_req_set_fade_level {
struct led15093_req_hdr hdr;
uint8_t cmd;
uint8_t depth;
uint8_t cycle;
};
struct led15093_req_set_fade_shift {
struct led15093_req_hdr hdr;
uint8_t cmd;
uint8_t target;
};
struct led15093_req_set_auto_shift {
struct led15093_req_hdr hdr;
uint8_t cmd;
uint8_t count;
uint8_t target;
};
struct led15093_req_get_board_status {
struct led15093_req_hdr hdr;
uint8_t cmd;
bool clear;
};
union led15093_req_any {
struct led15093_req_hdr hdr;
struct led15093_req_reset reset;
struct led15093_req_set_timeout set_timeout;
struct led15093_req_set_disable_response set_disable_response;
struct led15093_req_set_id set_id;
struct led15093_req_set_led set_led;
struct led15093_req_set_fade_level set_fade_level;
struct led15093_req_set_fade_shift set_fade_shift;
struct led15093_req_set_auto_shift set_auto_shift;
struct led15093_req_get_board_status get_board_status;
uint8_t payload[256];
};
/* Response data structures */
struct led15093_resp_any {
struct led15093_resp_hdr hdr;
uint8_t status;
uint8_t cmd;
uint8_t report;
uint8_t data[32];
};
struct led15093_resp_timeout {
struct led15093_resp_hdr hdr;
uint8_t status;
uint8_t cmd;
uint8_t report;
uint8_t count_upper;
uint8_t count_lower;
};
struct led15093_resp_fw_sum {
struct led15093_resp_hdr hdr;
uint8_t status;
uint8_t cmd;
uint8_t report;
uint8_t sum_upper;
uint8_t sum_lower;
};
struct led15093_resp_board_info_legacy {
struct led15093_resp_hdr hdr;
uint8_t status;
uint8_t cmd;
uint8_t report;
char board_num[8];
uint8_t lf; // 0x0A (ASCII LF)
char chip_num[5];
uint8_t endcode; // Always 0xFF
uint8_t fw_ver;
};
struct led15093_resp_board_info {
struct led15093_resp_hdr hdr;
uint8_t status;
uint8_t cmd;
uint8_t report;
char board_num[8];
uint8_t lf; // 0x0A (ASCII LF)
char chip_num[5];
uint8_t endcode; // Always 0xFF
uint8_t fw_ver;
uint8_t rx_buf;
};
struct led15093_resp_protocol_ver {
struct led15093_resp_hdr hdr;
uint8_t status;
uint8_t cmd;
uint8_t report;
uint8_t mode;
uint8_t major_ver;
uint8_t minor_ver;
};
struct led15093_resp_set_auto_shift {
struct led15093_resp_hdr hdr;
uint8_t status;
uint8_t cmd;
uint8_t report;
uint8_t count;
uint8_t target;
};

View File

@ -5,13 +5,13 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include "board/led1509306-frame.h" #include "board/led15093-frame.h"
#include "hook/iobuf.h" #include "hook/iobuf.h"
static void led1509306_frame_sync(struct iobuf *src); static void led15093_frame_sync(struct iobuf *src);
static HRESULT led1509306_frame_accept(const struct iobuf *dest); static HRESULT led15093_frame_accept(const struct iobuf *dest);
static HRESULT led1509306_frame_encode_byte(struct iobuf *dest, uint8_t byte); static HRESULT led15093_frame_encode_byte(struct iobuf *dest, uint8_t byte);
/* Frame structure: /* Frame structure:
@ -34,17 +34,17 @@ static HRESULT led1509306_frame_encode_byte(struct iobuf *dest, uint8_t byte);
0xD0 is an escape byte. Un-escape the subsequent byte by adding 1. */ 0xD0 is an escape byte. Un-escape the subsequent byte by adding 1. */
static void led1509306_frame_sync(struct iobuf *src) static void led15093_frame_sync(struct iobuf *src)
{ {
size_t i; size_t i;
for (i = 0 ; i < src->pos && src->bytes[i] != 0xE0 ; i++); for (i = 0 ; i < src->pos && src->bytes[i] != LED_15093_FRAME_SYNC ; i++);
src->pos -= i; src->pos -= i;
memmove(&src->bytes[0], &src->bytes[i], i); memmove(&src->bytes[0], &src->bytes[i], i);
} }
static HRESULT led1509306_frame_accept(const struct iobuf *dest) static HRESULT led15093_frame_accept(const struct iobuf *dest)
{ {
uint8_t checksum; uint8_t checksum;
size_t i; size_t i;
@ -59,7 +59,7 @@ static HRESULT led1509306_frame_accept(const struct iobuf *dest)
checksum += dest->bytes[i]; checksum += dest->bytes[i];
} }
//dprintf("LED checksum %02x, expected %02x\n", checksum, dest->bytes[dest->pos - 1]); // dprintf("LED checksum %02x, expected %02x\n", checksum, dest->bytes[dest->pos - 1]);
if (checksum != dest->bytes[dest->pos - 1]) { if (checksum != dest->bytes[dest->pos - 1]) {
return HRESULT_FROM_WIN32(ERROR_CRC); return HRESULT_FROM_WIN32(ERROR_CRC);
@ -68,7 +68,7 @@ static HRESULT led1509306_frame_accept(const struct iobuf *dest)
return S_OK; return S_OK;
} }
HRESULT led1509306_frame_decode(struct iobuf *dest, struct iobuf *src) HRESULT led15093_frame_decode(struct iobuf *dest, struct iobuf *src)
{ {
uint8_t byte; uint8_t byte;
bool escape; bool escape;
@ -82,7 +82,7 @@ HRESULT led1509306_frame_decode(struct iobuf *dest, struct iobuf *src)
assert(src->bytes != NULL || src->nbytes == 0); assert(src->bytes != NULL || src->nbytes == 0);
assert(src->pos <= src->nbytes); assert(src->pos <= src->nbytes);
led1509306_frame_sync(src); led15093_frame_sync(src);
dest->pos = 0; dest->pos = 0;
escape = false; escape = false;
@ -96,9 +96,9 @@ HRESULT led1509306_frame_decode(struct iobuf *dest, struct iobuf *src)
hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); hr = HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
} else if (i == 0) { } else if (i == 0) {
dest->bytes[dest->pos++] = byte; dest->bytes[dest->pos++] = byte;
} else if (byte == 0xE0) { } else if (byte == LED_15093_FRAME_SYNC) {
hr = E_FAIL; hr = E_FAIL;
} else if (byte == 0xD0) { } else if (byte == LED_15093_FRAME_ESC) {
if (escape) { if (escape) {
hr = E_FAIL; hr = E_FAIL;
} }
@ -114,7 +114,7 @@ HRESULT led1509306_frame_decode(struct iobuf *dest, struct iobuf *src)
/* Try to accept the packet we've built up so far */ /* Try to accept the packet we've built up so far */
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
hr = led1509306_frame_accept(dest); hr = led15093_frame_accept(dest);
} }
} }
@ -129,7 +129,7 @@ HRESULT led1509306_frame_decode(struct iobuf *dest, struct iobuf *src)
return hr; return hr;
} }
HRESULT led1509306_frame_encode( HRESULT led15093_frame_encode(
struct iobuf *dest, struct iobuf *dest,
const void *ptr, const void *ptr,
size_t nbytes) size_t nbytes)
@ -147,22 +147,24 @@ HRESULT led1509306_frame_encode(
src = ptr; src = ptr;
assert(nbytes >= 3 && src[0] == 0xE0 && src[3] + 4 == nbytes); assert(nbytes >= 3 &&
src[0] == LED_15093_FRAME_SYNC &&
src[3] + 4 == nbytes);
if (dest->pos >= dest->nbytes) { if (dest->pos >= dest->nbytes) {
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
} }
dest->bytes[dest->pos++] = 0xE0; dest->bytes[dest->pos++] = LED_15093_FRAME_SYNC;
checksum = 0; checksum = 0;
// dprintf("%02x ", 0xe0); // dprintf("%02x ", LED_15093_FRAME_SYNC);
for (i = 1 ; i < nbytes ; i++) { for (i = 1 ; i < nbytes ; i++) {
byte = src[i]; byte = src[i];
checksum += byte; checksum += byte;
// dprintf("%02x ", byte); // dprintf("%02x ", byte);
hr = led1509306_frame_encode_byte(dest, byte); hr = led15093_frame_encode_byte(dest, byte);
if (FAILED(hr)) { if (FAILED(hr)) {
return hr; return hr;
@ -170,17 +172,17 @@ HRESULT led1509306_frame_encode(
} }
// dprintf("%02x \n", checksum); // dprintf("%02x \n", checksum);
return led1509306_frame_encode_byte(dest, checksum); return led15093_frame_encode_byte(dest, checksum);
} }
static HRESULT led1509306_frame_encode_byte(struct iobuf *dest, uint8_t byte) static HRESULT led15093_frame_encode_byte(struct iobuf *dest, uint8_t byte)
{ {
if (byte == 0xE0 || byte == 0xD0) { if (byte == LED_15093_FRAME_SYNC || byte == LED_15093_FRAME_ESC) {
if (dest->pos + 2 > dest->nbytes) { if (dest->pos + 2 > dest->nbytes) {
return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER); return HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER);
} }
dest->bytes[dest->pos++] = 0xD0; dest->bytes[dest->pos++] = LED_15093_FRAME_ESC;
dest->bytes[dest->pos++] = byte - 1; dest->bytes[dest->pos++] = byte - 1;
} else { } else {
if (dest->pos + 1 > dest->nbytes) { if (dest->pos + 1 > dest->nbytes) {

34
board/led15093-frame.h Normal file
View File

@ -0,0 +1,34 @@
#pragma once
#include <windows.h>
#include <stddef.h>
#include <stdint.h>
#include "hook/iobuf.h"
enum {
LED_15093_FRAME_SYNC = 0xE0,
LED_15093_FRAME_ESC = 0xD0,
};
struct led15093_req_hdr {
uint8_t sync;
uint8_t dest_adr;
uint8_t src_adr;
uint8_t nbytes;
};
struct led15093_resp_hdr {
uint8_t sync;
uint8_t dest_adr;
uint8_t src_adr;
uint8_t nbytes;
};
HRESULT led15093_frame_decode(struct iobuf *dest, struct iobuf *src);
HRESULT led15093_frame_encode(
struct iobuf *dest,
const void *ptr,
size_t nbytes);

1112
board/led15093.c Normal file

File diff suppressed because it is too large Load Diff

22
board/led15093.h Normal file
View File

@ -0,0 +1,22 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
struct led15093_config {
bool enable;
bool high_baudrate;
unsigned int port_no[2];
char board_number[8];
char chip_number[5];
char boot_chip_number[5];
uint8_t fw_ver;
uint16_t fw_sum;
};
HRESULT led15093_hook_init(
const struct led15093_config *cfg,
unsigned int port_no_0,
unsigned int port_no_1);

View File

@ -1,45 +0,0 @@
#pragma once
#include "board/led1509306-frame.h"
enum {
LED_15093_06_CMD_RESET = 0x10,
LED_15093_06_CMD_SET_TIMEOUT = 0x11,
LED_15093_06_CMD_SET_DISABLE_RESPONSE = 0x14,
LED_15093_06_CMD_SET_LED = 0x82,
LED_15093_06_CMD_SET_LED_COUNT = 0x86,
LED_15093_06_CMD_BOARD_INFO = 0xF0,
LED_15093_06_CMD_BOARD_STATUS = 0xF1,
LED_15093_06_CMD_FW_SUM = 0xF2,
LED_15093_06_CMD_PROTOCOL_VER = 0xF3,
LED_15093_06_CMD_BOOTLOADER = 0xFD,
};
struct led1509306_req_any {
struct led1509306_hdr hdr;
uint8_t cmd;
uint8_t payload[256];
};
struct led1509306_resp_any {
struct led1509306_hdr hdr;
uint8_t status;
uint8_t cmd;
uint8_t report;
uint8_t data[32];
};
struct led1509306_resp_board_info {
struct led1509306_hdr hdr;
uint8_t status;
uint8_t cmd;
uint8_t report;
struct {
char board_num[8];
uint8_t _0a;
char chip_num[5];
uint8_t _ff;
uint8_t fw_ver;
// may be some more data after this that isn't checked
} data;
};

View File

@ -1,26 +0,0 @@
#pragma once
#include <windows.h>
#include <stddef.h>
#include <stdint.h>
#include "hook/iobuf.h"
enum {
LED_15093_06_FRAME_SYNC = 0xE0,
};
struct led1509306_hdr {
uint8_t sync;
uint8_t dest_adr;
uint8_t src_adr;
uint8_t nbytes;
};
HRESULT led1509306_frame_decode(struct iobuf *dest, struct iobuf *src);
HRESULT led1509306_frame_encode(
struct iobuf *dest,
const void *ptr,
size_t nbytes);

View File

@ -20,9 +20,11 @@ board_lib = static_library(
'io3.h', 'io3.h',
'io4.c', 'io4.c',
'io4.h', 'io4.h',
'led1509306-cmd.h', 'led15093-cmd.h',
'led1509306-frame.c', 'led15093-frame.c',
'led1509306-frame.h', 'led15093-frame.h',
'led15093.c',
'led15093.h',
'sg-cmd.c', 'sg-cmd.c',
'sg-cmd.h', 'sg-cmd.h',
'sg-frame.c', 'sg-frame.c',

View File

@ -43,7 +43,7 @@ void slider_config_load(struct slider_config *cfg, const wchar_t *filename)
cfg->enable = GetPrivateProfileIntW(L"slider", L"enable", 1, filename); cfg->enable = GetPrivateProfileIntW(L"slider", L"enable", 1, filename);
} }
void led1509306_config_load(struct led1509306_config *cfg, const wchar_t *filename) void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename)
{ {
assert(cfg != NULL); assert(cfg != NULL);
assert(filename != NULL); assert(filename != NULL);
@ -52,24 +52,56 @@ void led1509306_config_load(struct led1509306_config *cfg, const wchar_t *filena
memset(cfg->board_number, ' ', sizeof(cfg->board_number)); memset(cfg->board_number, ' ', sizeof(cfg->board_number));
memset(cfg->chip_number, ' ', sizeof(cfg->chip_number)); memset(cfg->chip_number, ' ', sizeof(cfg->chip_number));
memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number));
cfg->enable = GetPrivateProfileIntW(L"ledstrip", L"enable", 1, filename); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename);
cfg->fw_ver = GetPrivateProfileIntW(L"ledstrip", L"fw_ver", 0x90, filename); cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo0", 0, filename);
cfg->fw_sum = GetPrivateProfileIntW(L"ledstrip", L"fw_sum", 0xadf7, filename); cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename);
cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaudrate", 0, filename);
cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename);
cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xadf7, filename);
GetPrivateProfileStringW(
L"led15093",
L"boardNumber",
L"15093-06",
tmpstr,
_countof(tmpstr),
filename);
GetPrivateProfileStringW(L"ledstrip", L"board_number", L"15093-06", tmpstr, _countof(tmpstr), filename);
size_t n = wcstombs(cfg->board_number, tmpstr, sizeof(cfg->board_number)); size_t n = wcstombs(cfg->board_number, tmpstr, sizeof(cfg->board_number));
for (int i = n; i < sizeof(cfg->board_number); i++) for (int i = n; i < sizeof(cfg->board_number); i++)
{ {
cfg->board_number[i] = ' '; cfg->board_number[i] = ' ';
} }
GetPrivateProfileStringW(L"ledstrip", L"chip_number", L"6710 ", tmpstr, _countof(tmpstr), filename); GetPrivateProfileStringW(
L"led15093",
L"chipNumber",
L"6710 ",
tmpstr,
_countof(tmpstr),
filename);
n = wcstombs(cfg->chip_number, tmpstr, sizeof(cfg->chip_number)); n = wcstombs(cfg->chip_number, tmpstr, sizeof(cfg->chip_number));
for (int i = n; i < sizeof(cfg->chip_number); i++) for (int i = n; i < sizeof(cfg->chip_number); i++)
{ {
cfg->chip_number[i] = ' '; cfg->chip_number[i] = ' ';
} }
GetPrivateProfileStringW(
L"led15093",
L"bootChipNumber",
L"6709 ",
tmpstr,
_countof(tmpstr),
filename);
n = wcstombs(cfg->boot_chip_number, tmpstr, sizeof(cfg->boot_chip_number));
for (int i = n; i < sizeof(cfg->boot_chip_number); i++)
{
cfg->boot_chip_number[i] = ' ';
}
} }
void chuni_hook_config_load( void chuni_hook_config_load(
@ -87,5 +119,5 @@ void chuni_hook_config_load(
gfx_config_load(&cfg->gfx, filename); gfx_config_load(&cfg->gfx, filename);
chuni_dll_config_load(&cfg->dll, filename); chuni_dll_config_load(&cfg->dll, filename);
slider_config_load(&cfg->slider, filename); slider_config_load(&cfg->slider, filename);
led1509306_config_load(&cfg->led1509306, filename); led15093_config_load(&cfg->led15093, filename);
} }

View File

@ -6,10 +6,10 @@
#include "amex/amex.h" #include "amex/amex.h"
#include "board/sg-reader.h" #include "board/sg-reader.h"
#include "board/led15093.h"
#include "chunihook/chuni-dll.h" #include "chunihook/chuni-dll.h"
#include "chunihook/slider.h" #include "chunihook/slider.h"
#include "chunihook/led1509306.h"
#include "gfxhook/gfx.h" #include "gfxhook/gfx.h"
@ -22,7 +22,7 @@ struct chuni_hook_config {
struct gfx_config gfx; struct gfx_config gfx;
struct chuni_dll_config dll; struct chuni_dll_config dll;
struct slider_config slider; struct slider_config slider;
struct led1509306_config led1509306; struct led15093_config led15093;
}; };
void chuni_dll_config_load( void chuni_dll_config_load(

View File

@ -9,7 +9,6 @@
#include "chunihook/config.h" #include "chunihook/config.h"
#include "chunihook/jvs.h" #include "chunihook/jvs.h"
#include "chunihook/slider.h" #include "chunihook/slider.h"
#include "chunihook/led1509306.h"
#include "chuniio/chuniio.h" #include "chuniio/chuniio.h"
@ -97,7 +96,7 @@ static DWORD CALLBACK chuni_pre_startup(void)
goto fail; goto fail;
} }
hr = led1509306_hook_init(&chuni_hook_cfg.led1509306); hr = led15093_hook_init(&chuni_hook_cfg.led15093, 10, 11);
if (FAILED(hr)) { if (FAILED(hr)) {
goto fail; goto fail;

View File

@ -1,385 +0,0 @@
/*
SEGA 837-15093-06 LED controller emulator
Credits:
somewhatlurker, skogaby
*/
#include <windows.h>
#include <assert.h>
#include <process.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "board/led1509306-cmd.h"
#include "board/led1509306-frame.h"
#include "chunihook/led1509306.h"
#include "hook/iobuf.h"
#include "hook/iohook.h"
#include "hooklib/uart.h"
#include "util/dprintf.h"
#include "util/dump.h"
static HRESULT led1509306_handle_irp(struct irp *irp);
static HRESULT led1509306_handle_irp_locked(int board, struct irp *irp);
static HRESULT led1509306_req_dispatch(int board, const struct led1509306_req_any *req);
static HRESULT led1509306_req_reset(int board, const struct led1509306_req_any *req);
static HRESULT led1509306_req_get_board_info(int board);
static HRESULT led1509306_req_get_fw_sum(int board);
static HRESULT led1509306_req_get_protocol_ver(int board);
static HRESULT led1509306_req_get_board_status(int board);
static HRESULT led1509306_req_set_led(int board, const struct led1509306_req_any *req);
static HRESULT led1509306_req_set_disable_response(int board, const struct led1509306_req_any *req);
static HRESULT led1509306_req_set_timeout(int board, const struct led1509306_req_any *req);
static char led1509306_board_num[8];
static char led1509306_chip_num[5];
static uint8_t led1509306_fw_ver;
static uint16_t led1509306_fw_sum;
static uint8_t led1509306_board_adr = 2;
static uint8_t led1509306_host_adr = 1;
#define led1509306_nboards 2
typedef struct {
CRITICAL_SECTION lock;
struct uart boarduart;
uint8_t written_bytes[520];
uint8_t readable_bytes[520];
bool enable_response;
} _led1509306_per_board_vars;
_led1509306_per_board_vars led1509306_per_board_vars[led1509306_nboards];
HRESULT led1509306_hook_init(const struct led1509306_config *cfg)
{
assert(cfg != NULL);
if (!cfg->enable) {
return S_FALSE;
}
memcpy(led1509306_board_num, cfg->board_number, sizeof(led1509306_board_num));
memcpy(led1509306_chip_num, cfg->chip_number, sizeof(led1509306_chip_num));
led1509306_fw_ver = cfg->fw_ver;
led1509306_fw_sum = cfg->fw_sum;
for (int i = 0; i < led1509306_nboards; i++)
{
_led1509306_per_board_vars *v = &led1509306_per_board_vars[i];
InitializeCriticalSection(&v->lock);
uart_init(&v->boarduart, 10 + i);
v->boarduart.written.bytes = v->written_bytes;
v->boarduart.written.nbytes = sizeof(v->written_bytes);
v->boarduart.readable.bytes = v->readable_bytes;
v->boarduart.readable.nbytes = sizeof(v->readable_bytes);
v->enable_response = true;
}
return iohook_push_handler(led1509306_handle_irp);
}
static HRESULT led1509306_handle_irp(struct irp *irp)
{
HRESULT hr;
assert(irp != NULL);
for (int i = 0; i < led1509306_nboards; i++)
{
_led1509306_per_board_vars *v = &led1509306_per_board_vars[i];
struct uart *boarduart = &v->boarduart;
if (uart_match_irp(boarduart, irp))
{
CRITICAL_SECTION lock = v->lock;
EnterCriticalSection(&lock);
hr = led1509306_handle_irp_locked(i, irp);
LeaveCriticalSection(&lock);
return hr;
}
}
return iohook_invoke_next(irp);
}
static HRESULT led1509306_handle_irp_locked(int board, struct irp *irp)
{
struct led1509306_req_any req;
struct iobuf req_iobuf;
HRESULT hr;
struct uart *boarduart = &led1509306_per_board_vars[board].boarduart;
hr = uart_handle_irp(boarduart, irp);
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
return hr;
}
for (;;) {
#if 0
dprintf("TX Buffer:\n");
dump_iobuf(&boarduart->written);
#endif
req_iobuf.bytes = (byte*)&req;
req_iobuf.nbytes = sizeof(req.hdr) + sizeof(req.cmd) + sizeof(req.payload);
req_iobuf.pos = 0;
hr = led1509306_frame_decode(&req_iobuf, &boarduart->written);
if (hr != S_OK) {
if (FAILED(hr)) {
dprintf("Chunithm LED Strip: Deframe error: %x\n", (int) hr);
}
return hr;
}
#if 0
dprintf("Deframe Buffer:\n");
dump_iobuf(&req_iobuf);
#endif
hr = led1509306_req_dispatch(board, &req);
if (FAILED(hr)) {
dprintf("Chunithm LED Strip: Processing error: %x\n", (int) hr);
}
}
}
static HRESULT led1509306_req_dispatch(int board, const struct led1509306_req_any *req)
{
switch (req->cmd) {
case LED_15093_06_CMD_RESET:
return led1509306_req_reset(board, req);
case LED_15093_06_CMD_BOARD_INFO:
return led1509306_req_get_board_info(board);
case LED_15093_06_CMD_FW_SUM:
return led1509306_req_get_fw_sum(board);
case LED_15093_06_CMD_PROTOCOL_VER:
return led1509306_req_get_protocol_ver(board);
case LED_15093_06_CMD_BOARD_STATUS:
return led1509306_req_get_board_status(board);
case LED_15093_06_CMD_SET_LED:
return led1509306_req_set_led(board, req);
case LED_15093_06_CMD_SET_DISABLE_RESPONSE:
return led1509306_req_set_disable_response(board, req);
case LED_15093_06_CMD_SET_TIMEOUT:
return led1509306_req_set_timeout(board, req);
default:
dprintf("Chunithm LED Strip: Unhandled command %02x\n", req->cmd);
return S_OK;
}
}
static HRESULT led1509306_req_reset(int board, const struct led1509306_req_any *req)
{
dprintf("Chunithm LED Strip: Reset (board %u, type %02x)\n", board, req->payload[0]);
if (req->payload[0] != 0xd9)
dprintf("Chunithm LED Strip: Warning -- Unknown reset type %02x\n", req->payload[0]);
led1509306_per_board_vars[board].enable_response = true;
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_RESET;
resp.report = 1;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_get_board_info(int board)
{
dprintf("Chunithm LED Strip: Get board info (board %u)\n", board);
struct led1509306_resp_board_info resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = sizeof(resp.data) + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_BOARD_INFO;
resp.report = 1;
memcpy(resp.data.board_num, led1509306_board_num, sizeof(resp.data.board_num));
resp.data._0a = 0x0a;
memcpy(resp.data.chip_num, led1509306_chip_num, sizeof(resp.data.chip_num));
resp.data._ff = 0xff;
resp.data.fw_ver = led1509306_fw_ver;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_get_fw_sum(int board)
{
dprintf("Chunithm LED Strip: Get firmware checksum (board %u)\n", board);
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 2 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_FW_SUM;
resp.report = 1;
resp.data[0] = (led1509306_fw_sum >> 8) & 0xff;
resp.data[1] = led1509306_fw_sum & 0xff;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_get_protocol_ver(int board)
{
dprintf("Chunithm LED Strip: Get protocol version (board %u)\n", board);
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 3 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_PROTOCOL_VER;
resp.report = 1;
resp.data[0] = 1;
resp.data[1] = 1;
resp.data[2] = 4;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_get_board_status(int board)
{
dprintf("Chunithm LED Strip: Get board status (board %u)\n", board);
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 4 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_BOARD_STATUS;
resp.report = 1;
resp.data[0] = 0;
resp.data[1] = 0;
resp.data[2] = 0;
resp.data[3] = 0;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_set_led(int board, const struct led1509306_req_any *req)
{
// dprintf("Chunithm LED Strip: Set LED (board %u)\n", board);
if (!led1509306_per_board_vars[board].enable_response)
return S_OK;
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_SET_LED;
resp.report = 1;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_set_disable_response(int board, const struct led1509306_req_any *req)
{
dprintf("Chunithm LED Strip: Disable LED responses (board %u)\n", board);
led1509306_per_board_vars[board].enable_response = !req->payload[0];
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 1 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_SET_DISABLE_RESPONSE;
resp.report = 1;
resp.data[0] = req->payload[0];
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_set_timeout(int board, const struct led1509306_req_any *req)
{
dprintf("Chunithm LED Strip: Set timeout (board %u)\n", board);
// not actually implemented, but respond correctly anyway
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 2 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_SET_TIMEOUT;
resp.report = 1;
resp.data[0] = req->payload[0];
resp.data[1] = req->payload[1];
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}

View File

@ -1,15 +0,0 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
struct led1509306_config {
bool enable;
char board_number[8];
char chip_number[5];
uint8_t fw_ver;
uint16_t fw_sum;
};
HRESULT led1509306_hook_init(const struct led1509306_config *cfg);

View File

@ -30,7 +30,5 @@ shared_library(
'jvs.h', 'jvs.h',
'slider.c', 'slider.c',
'slider.h', 'slider.h',
'led1509306.c',
'led1509306.h',
], ],
) )

View File

@ -71,34 +71,76 @@ void slider_config_load(struct slider_config *cfg, const wchar_t *filename)
cfg->enable = GetPrivateProfileIntW(L"slider", L"enable", 1, filename); cfg->enable = GetPrivateProfileIntW(L"slider", L"enable", 1, filename);
} }
void led1509306_config_load(struct led1509306_config *cfg, const wchar_t *filename) void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename)
{ {
assert(cfg != NULL); assert(cfg != NULL);
assert(filename != NULL); assert(filename != NULL);
wchar_t tmpstr[16]; wchar_t tmpstr[16];
bool cvt_port;
memset(cfg->board_number, ' ', sizeof(cfg->board_number)); memset(cfg->board_number, ' ', sizeof(cfg->board_number));
memset(cfg->chip_number, ' ', sizeof(cfg->chip_number)); memset(cfg->chip_number, ' ', sizeof(cfg->chip_number));
memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number));
cfg->enable = GetPrivateProfileIntW(L"ledstrip", L"enable", 1, filename); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename);
cfg->cvt_port = GetPrivateProfileIntW(L"ledstrip", L"cvt_port", 0, filename); cvt_port = GetPrivateProfileIntW(L"led15093", L"cvtPort", 0, filename);
cfg->fw_ver = GetPrivateProfileIntW(L"ledstrip", L"fw_ver", 0x90, filename);
cfg->fw_sum = GetPrivateProfileIntW(L"ledstrip", L"fw_sum", 0xadf7, filename); if (!cvt_port) {
// SP mode: COM20, COM21
cfg->port_no[0] = 20;
cfg->port_no[1] = 21;
} else {
// CVT mode: COM2, COM3
cfg->port_no[0] = 2;
cfg->port_no[1] = 3;
}
cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaudrate", 0, filename);
cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0x90, filename);
cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xadf7, filename);
GetPrivateProfileStringW(
L"led15093",
L"boardNumber",
L"15093-06",
tmpstr,
_countof(tmpstr),
filename);
GetPrivateProfileStringW(L"ledstrip", L"board_number", L"15093-06", tmpstr, _countof(tmpstr), filename);
size_t n = wcstombs(cfg->board_number, tmpstr, sizeof(cfg->board_number)); size_t n = wcstombs(cfg->board_number, tmpstr, sizeof(cfg->board_number));
for (int i = n; i < sizeof(cfg->board_number); i++) for (int i = n; i < sizeof(cfg->board_number); i++)
{ {
cfg->board_number[i] = ' '; cfg->board_number[i] = ' ';
} }
GetPrivateProfileStringW(L"ledstrip", L"chip_number", L"6710 ", tmpstr, _countof(tmpstr), filename); GetPrivateProfileStringW(
L"led15093",
L"chipNumber",
L"6710 ",
tmpstr,
_countof(tmpstr),
filename);
n = wcstombs(cfg->chip_number, tmpstr, sizeof(cfg->chip_number)); n = wcstombs(cfg->chip_number, tmpstr, sizeof(cfg->chip_number));
for (int i = n; i < sizeof(cfg->chip_number); i++) for (int i = n; i < sizeof(cfg->chip_number); i++)
{ {
cfg->chip_number[i] = ' '; cfg->chip_number[i] = ' ';
} }
GetPrivateProfileStringW(
L"led15093",
L"bootChipNumber",
L"6709 ",
tmpstr,
_countof(tmpstr),
filename);
n = wcstombs(cfg->boot_chip_number, tmpstr, sizeof(cfg->boot_chip_number));
for (int i = n; i < sizeof(cfg->boot_chip_number); i++)
{
cfg->boot_chip_number[i] = ' ';
}
} }
@ -118,5 +160,5 @@ void chusan_hook_config_load(
gfx_config_load(&cfg->gfx, filename); gfx_config_load(&cfg->gfx, filename);
chuni_dll_config_load(&cfg->dll, filename); chuni_dll_config_load(&cfg->dll, filename);
slider_config_load(&cfg->slider, filename); slider_config_load(&cfg->slider, filename);
led1509306_config_load(&cfg->led1509306, filename); led15093_config_load(&cfg->led15093, filename);
} }

View File

@ -3,6 +3,7 @@
#include <stddef.h> #include <stddef.h>
#include "board/config.h" #include "board/config.h"
#include "board/led15093.h"
#include "hooklib/dvd.h" #include "hooklib/dvd.h"
@ -12,7 +13,6 @@
#include "chusanhook/chuni-dll.h" #include "chusanhook/chuni-dll.h"
#include "chusanhook/slider.h" #include "chusanhook/slider.h"
#include "chusanhook/led1509306.h"
struct chusan_hook_config { struct chusan_hook_config {
struct platform_config platform; struct platform_config platform;
@ -22,7 +22,7 @@ struct chusan_hook_config {
struct gfx_config gfx; struct gfx_config gfx;
struct chuni_dll_config dll; struct chuni_dll_config dll;
struct slider_config slider; struct slider_config slider;
struct led1509306_config led1509306; struct led15093_config led15093;
}; };
void chuni_dll_config_load( void chuni_dll_config_load(

View File

@ -11,7 +11,6 @@
#include "chusanhook/config.h" #include "chusanhook/config.h"
#include "chusanhook/io4.h" #include "chusanhook/io4.h"
#include "chusanhook/slider.h" #include "chusanhook/slider.h"
#include "chusanhook/led1509306.h"
#include "chuniio/chuniio.h" #include "chuniio/chuniio.h"
@ -100,7 +99,7 @@ static DWORD CALLBACK chusan_pre_startup(void)
goto fail; goto fail;
} }
hr = led1509306_hook_init(&chusan_hook_cfg.led1509306); hr = led15093_hook_init(&chusan_hook_cfg.led15093, 20, 21);
if (FAILED(hr)) { if (FAILED(hr)) {
goto fail; goto fail;

View File

@ -1,397 +0,0 @@
/*
SEGA 837-15093-06 LED controller emulator
Credits:
somewhatlurker, skogaby
*/
#include <windows.h>
#include <assert.h>
#include <process.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "board/led1509306-cmd.h"
#include "board/led1509306-frame.h"
#include "chusanhook/led1509306.h"
#include "hook/iobuf.h"
#include "hook/iohook.h"
#include "hooklib/uart.h"
#include "util/dprintf.h"
#include "util/dump.h"
static HRESULT led1509306_handle_irp(struct irp *irp);
static HRESULT led1509306_handle_irp_locked(int board, struct irp *irp);
static HRESULT led1509306_req_dispatch(int board, const struct led1509306_req_any *req);
static HRESULT led1509306_req_reset(int board, const struct led1509306_req_any *req);
static HRESULT led1509306_req_get_board_info(int board);
static HRESULT led1509306_req_get_fw_sum(int board);
static HRESULT led1509306_req_get_protocol_ver(int board);
static HRESULT led1509306_req_get_board_status(int board);
static HRESULT led1509306_req_set_led(int board, const struct led1509306_req_any *req);
static HRESULT led1509306_req_set_disable_response(int board, const struct led1509306_req_any *req);
static HRESULT led1509306_req_set_timeout(int board, const struct led1509306_req_any *req);
static char led1509306_board_num[8];
static char led1509306_chip_num[5];
static uint8_t led1509306_fw_ver;
static uint16_t led1509306_fw_sum;
static uint8_t led1509306_board_adr = 2;
static uint8_t led1509306_host_adr = 1;
#define led1509306_nboards 2
typedef struct {
CRITICAL_SECTION lock;
struct uart boarduart;
uint8_t written_bytes[520];
uint8_t readable_bytes[520];
bool enable_response;
} _led1509306_per_board_vars;
_led1509306_per_board_vars led1509306_per_board_vars[led1509306_nboards];
HRESULT led1509306_hook_init(const struct led1509306_config *cfg)
{
assert(cfg != NULL);
if (!cfg->enable) {
return S_FALSE;
}
memcpy(led1509306_board_num, cfg->board_number, sizeof(led1509306_board_num));
memcpy(led1509306_chip_num, cfg->chip_number, sizeof(led1509306_chip_num));
led1509306_fw_ver = cfg->fw_ver;
led1509306_fw_sum = cfg->fw_sum;
int com_ports[2];
if (!cfg->cvt_port) {
// SP mode: COM20, COM21
com_ports[0] = 20;
com_ports[1] = 21;
} else {
// CVT mode: COM2, COM3
com_ports[0] = 2;
com_ports[1] = 3;
}
for (int i = 0; i < led1509306_nboards; i++)
{
_led1509306_per_board_vars *v = &led1509306_per_board_vars[i];
InitializeCriticalSection(&v->lock);
uart_init(&v->boarduart, com_ports[i]);
v->boarduart.written.bytes = v->written_bytes;
v->boarduart.written.nbytes = sizeof(v->written_bytes);
v->boarduart.readable.bytes = v->readable_bytes;
v->boarduart.readable.nbytes = sizeof(v->readable_bytes);
v->enable_response = true;
}
return iohook_push_handler(led1509306_handle_irp);
}
static HRESULT led1509306_handle_irp(struct irp *irp)
{
HRESULT hr;
assert(irp != NULL);
for (int i = 0; i < led1509306_nboards; i++)
{
_led1509306_per_board_vars *v = &led1509306_per_board_vars[i];
struct uart *boarduart = &v->boarduart;
if (uart_match_irp(boarduart, irp))
{
CRITICAL_SECTION lock = v->lock;
EnterCriticalSection(&lock);
hr = led1509306_handle_irp_locked(i, irp);
LeaveCriticalSection(&lock);
return hr;
}
}
return iohook_invoke_next(irp);
}
static HRESULT led1509306_handle_irp_locked(int board, struct irp *irp)
{
struct led1509306_req_any req;
struct iobuf req_iobuf;
HRESULT hr;
struct uart *boarduart = &led1509306_per_board_vars[board].boarduart;
hr = uart_handle_irp(boarduart, irp);
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
return hr;
}
for (;;) {
#if 0
dprintf("TX Buffer:\n");
dump_iobuf(&boarduart->written);
#endif
req_iobuf.bytes = (byte*)&req;
req_iobuf.nbytes = sizeof(req.hdr) + sizeof(req.cmd) + sizeof(req.payload);
req_iobuf.pos = 0;
hr = led1509306_frame_decode(&req_iobuf, &boarduart->written);
if (hr != S_OK) {
if (FAILED(hr)) {
dprintf("Chunithm LED Strip: Deframe error: %x\n", (int) hr);
}
return hr;
}
#if 0
dprintf("Deframe Buffer:\n");
dump_iobuf(&req_iobuf);
#endif
hr = led1509306_req_dispatch(board, &req);
if (FAILED(hr)) {
dprintf("Chunithm LED Strip: Processing error: %x\n", (int) hr);
}
}
}
static HRESULT led1509306_req_dispatch(int board, const struct led1509306_req_any *req)
{
switch (req->cmd) {
case LED_15093_06_CMD_RESET:
return led1509306_req_reset(board, req);
case LED_15093_06_CMD_BOARD_INFO:
return led1509306_req_get_board_info(board);
case LED_15093_06_CMD_FW_SUM:
return led1509306_req_get_fw_sum(board);
case LED_15093_06_CMD_PROTOCOL_VER:
return led1509306_req_get_protocol_ver(board);
case LED_15093_06_CMD_BOARD_STATUS:
return led1509306_req_get_board_status(board);
case LED_15093_06_CMD_SET_LED:
return led1509306_req_set_led(board, req);
case LED_15093_06_CMD_SET_DISABLE_RESPONSE:
return led1509306_req_set_disable_response(board, req);
case LED_15093_06_CMD_SET_TIMEOUT:
return led1509306_req_set_timeout(board, req);
default:
dprintf("Chunithm LED Strip: Unhandled command %02x\n", req->cmd);
return S_OK;
}
}
static HRESULT led1509306_req_reset(int board, const struct led1509306_req_any *req)
{
dprintf("Chunithm LED Strip: Reset (board %u, type %02x)\n", board, req->payload[0]);
if (req->payload[0] != 0xd9)
dprintf("Chunithm LED Strip: Warning -- Unknown reset type %02x\n", req->payload[0]);
led1509306_per_board_vars[board].enable_response = true;
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_RESET;
resp.report = 1;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_get_board_info(int board)
{
dprintf("Chunithm LED Strip: Get board info (board %u)\n", board);
struct led1509306_resp_board_info resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = sizeof(resp.data) + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_BOARD_INFO;
resp.report = 1;
memcpy(resp.data.board_num, led1509306_board_num, sizeof(resp.data.board_num));
resp.data._0a = 0x0a;
memcpy(resp.data.chip_num, led1509306_chip_num, sizeof(resp.data.chip_num));
resp.data._ff = 0xff;
resp.data.fw_ver = led1509306_fw_ver;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_get_fw_sum(int board)
{
dprintf("Chunithm LED Strip: Get firmware checksum (board %u)\n", board);
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 2 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_FW_SUM;
resp.report = 1;
resp.data[0] = (led1509306_fw_sum >> 8) & 0xff;
resp.data[1] = led1509306_fw_sum & 0xff;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_get_protocol_ver(int board)
{
dprintf("Chunithm LED Strip: Get protocol version (board %u)\n", board);
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 3 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_PROTOCOL_VER;
resp.report = 1;
resp.data[0] = 1;
resp.data[1] = 1;
resp.data[2] = 4;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_get_board_status(int board)
{
dprintf("Chunithm LED Strip: Get board status (board %u)\n", board);
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 4 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_BOARD_STATUS;
resp.report = 1;
resp.data[0] = 0;
resp.data[1] = 0;
resp.data[2] = 0;
resp.data[3] = 0;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_set_led(int board, const struct led1509306_req_any *req)
{
// dprintf("Chunithm LED Strip: Set LED (board %u)\n", board);
if (!led1509306_per_board_vars[board].enable_response)
return S_OK;
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_SET_LED;
resp.report = 1;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_set_disable_response(int board, const struct led1509306_req_any *req)
{
dprintf("Chunithm LED Strip: Disable LED responses (board %u)\n", board);
led1509306_per_board_vars[board].enable_response = !req->payload[0];
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 1 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_SET_DISABLE_RESPONSE;
resp.report = 1;
resp.data[0] = req->payload[0];
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_set_timeout(int board, const struct led1509306_req_any *req)
{
dprintf("Chunithm LED Strip: Set timeout (board %u)\n", board);
// not actually implemented, but respond correctly anyway
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 2 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_SET_TIMEOUT;
resp.report = 1;
resp.data[0] = req->payload[0];
resp.data[1] = req->payload[1];
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}

View File

@ -28,7 +28,5 @@ shared_library(
'io4.h', 'io4.h',
'slider.c', 'slider.c',
'slider.h', 'slider.h',
'led1509306.c',
'led1509306.h',
], ],
) )

View File

@ -38,6 +38,10 @@ monitor=0
; Leave empty if you want to use Segatools built-in keyboard input. ; Leave empty if you want to use Segatools built-in keyboard input.
path= path=
[led15093]
; 837-15093-06 LED strip emulation setting.
enable=1
[chuniio] [chuniio]
; To use a custom Chunithm IO DLL enter its path here. ; To use a custom Chunithm IO DLL enter its path here.
; Leave empty if you want to use Segatools built-in keyboard input. ; Leave empty if you want to use Segatools built-in keyboard input.

View File

@ -44,7 +44,7 @@ enable=1
; LAN Install: If multiple machines are present on the same LAN then set ; LAN Install: If multiple machines are present on the same LAN then set
; this to 1 on exactly one machine and set this to 0 on all others. ; this to 1 on exactly one machine and set this to 0 on all others.
dipsw1=1 dipsw1=1
; Monitor type: 0 = 120FPS, 1 = 60FPS ; Monitor type: 0 = 120FPS (SP), 1 = 60FPS (CVT)
dipsw2=1 dipsw2=1
; Aime reader hardware type: 0 = SP, 1 = CVT ; Aime reader hardware type: 0 = SP, 1 = CVT
dipsw3=1 dipsw3=1
@ -57,6 +57,18 @@ framed=1
; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen) ; Select the monitor to run the game on. (Fullscreen only, 0 =primary screen)
monitor=0 monitor=0
[led15093]
; 837-15093-06 LED strip emulation setting.
enable=1
; Set to 1 if running game in 60FPS (CVT) mode.
cvtPort=0
[chuniio]
; Uncomment this if you have custom chuniio implementation.
; x86 chuniio to path32, x64 to path64. Both are necessary.
;path32=
;path64=
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
; Input settings ; Input settings
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
@ -79,18 +91,12 @@ coin=0x33
; Set to 0 for enable separate ir control. Deafult is space key. ; Set to 0 for enable separate ir control. Deafult is space key.
ir=0x20 ir=0x20
[io4] [ir]
enable=1 ; Uncomment and complete the following sequence of settings to configure a
; custom ir-cappable controller if you have one.
[ledstrip] ;ir6=0x53
; Set to 1 if running game in CVT mode. ; ... etc ...
cvt_port=0 ;ir1=0x53
[chuniio]
; Uncomment this if you have custom chuniio implementation.
; x86 chuniio to path32, x64 to path64. Both are necessary.
;path32=
;path64=
[slider] [slider]
; Enable slider emulation. If you have real AC slider, set this to 0. ; Enable slider emulation. If you have real AC slider, set this to 0.
@ -116,10 +122,3 @@ cvt_port=0
; Enable slider LED serial output. This follows OpeNITHM Serial LED Protocol. ; Enable slider LED serial output. This follows OpeNITHM Serial LED Protocol.
; eg. COM5 ; eg. COM5
;ledport= ;ledport=
[ir]
; Uncomment and complete the following sequence of settings to configure a
; custom ir-cappable controller if you have one.
;ir6=0x53
; ... etc ...
;ir1=0x53

View File

@ -58,10 +58,14 @@ enable=1
[ftdi] [ftdi]
; FTDI serial to usb adapter emulation for CABINET LED. ; FTDI serial to usb adapter emulation for CABINET LED.
enable=1 enable=1
; COM port number where the LED board is connected to.
portNo=17
[ledstrip] [led15093]
; 837-15093-06 LED strip emulation setting. ; 837-15093-06 LED board emulation setting.
enable=1 enable=1
; COM port number for the first LED board. Has to be the same as the FTDI port.
portNo0=17
; ----------------------------------------------------------------------------- ; -----------------------------------------------------------------------------
; Input settings ; Input settings

View File

@ -32,10 +32,10 @@ void ftdi_config_load(struct ftdi_config *cfg, const wchar_t *filename)
assert(filename != NULL); assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"ftdi", L"enable", 1, filename); cfg->enable = GetPrivateProfileIntW(L"ftdi", L"enable", 1, filename);
cfg->port_no = GetPrivateProfileIntW(L"ftdi", L"port", 17, filename); cfg->port_no = GetPrivateProfileIntW(L"ftdi", L"portNo", 0, filename);
} }
void led1509306_config_load(struct led1509306_config *cfg, const wchar_t *filename) void led15093_config_load(struct led15093_config *cfg, const wchar_t *filename)
{ {
assert(cfg != NULL); assert(cfg != NULL);
assert(filename != NULL); assert(filename != NULL);
@ -44,25 +44,56 @@ void led1509306_config_load(struct led1509306_config *cfg, const wchar_t *filena
memset(cfg->board_number, ' ', sizeof(cfg->board_number)); memset(cfg->board_number, ' ', sizeof(cfg->board_number));
memset(cfg->chip_number, ' ', sizeof(cfg->chip_number)); memset(cfg->chip_number, ' ', sizeof(cfg->chip_number));
memset(cfg->boot_chip_number, ' ', sizeof(cfg->boot_chip_number));
cfg->enable = GetPrivateProfileIntW(L"ledstrip", L"enable", 1, filename); cfg->enable = GetPrivateProfileIntW(L"led15093", L"enable", 1, filename);
cfg->port_no = GetPrivateProfileIntW(L"ledstrip", L"port", 17, filename); cfg->port_no[0] = GetPrivateProfileIntW(L"led15093", L"portNo0", 0, filename);
cfg->fw_ver = GetPrivateProfileIntW(L"ledstrip", L"fw_ver", 0xA0, filename); cfg->port_no[1] = GetPrivateProfileIntW(L"led15093", L"portNo1", 0, filename);
cfg->fw_sum = GetPrivateProfileIntW(L"ledstrip", L"fw_sum", 0xaa53, filename); cfg->high_baudrate = GetPrivateProfileIntW(L"led15093", L"highBaudrate", 0, filename);
cfg->fw_ver = GetPrivateProfileIntW(L"led15093", L"fwVer", 0xA0, filename);
cfg->fw_sum = GetPrivateProfileIntW(L"led15093", L"fwSum", 0xaa53, filename);
GetPrivateProfileStringW(
L"led15093",
L"boardNumber",
L"15093-06",
tmpstr,
_countof(tmpstr),
filename);
GetPrivateProfileStringW(L"ledstrip", L"board_number", L"15093-06", tmpstr, _countof(tmpstr), filename);
size_t n = wcstombs(cfg->board_number, tmpstr, sizeof(cfg->board_number)); size_t n = wcstombs(cfg->board_number, tmpstr, sizeof(cfg->board_number));
for (int i = n; i < sizeof(cfg->board_number); i++) for (int i = n; i < sizeof(cfg->board_number); i++)
{ {
cfg->board_number[i] = ' '; cfg->board_number[i] = ' ';
} }
GetPrivateProfileStringW(L"ledstrip", L"chip_number", L"6710A", tmpstr, _countof(tmpstr), filename); GetPrivateProfileStringW(
L"led15093",
L"chipNumber",
L"6710A",
tmpstr,
_countof(tmpstr),
filename);
n = wcstombs(cfg->chip_number, tmpstr, sizeof(cfg->chip_number)); n = wcstombs(cfg->chip_number, tmpstr, sizeof(cfg->chip_number));
for (int i = n; i < sizeof(cfg->chip_number); i++) for (int i = n; i < sizeof(cfg->chip_number); i++)
{ {
cfg->chip_number[i] = ' '; cfg->chip_number[i] = ' ';
} }
GetPrivateProfileStringW(
L"led15093",
L"bootChipNumber",
L"6709 ",
tmpstr,
_countof(tmpstr),
filename);
n = wcstombs(cfg->boot_chip_number, tmpstr, sizeof(cfg->boot_chip_number));
for (int i = n; i < sizeof(cfg->boot_chip_number); i++)
{
cfg->boot_chip_number[i] = ' ';
}
} }
void fgo_deck_config_load( void fgo_deck_config_load(
@ -90,6 +121,6 @@ void fgo_hook_config_load(
printer_config_load(&cfg->printer, filename); printer_config_load(&cfg->printer, filename);
fgo_deck_config_load(&cfg->deck, filename); fgo_deck_config_load(&cfg->deck, filename);
ftdi_config_load(&cfg->ftdi, filename); ftdi_config_load(&cfg->ftdi, filename);
led1509306_config_load(&cfg->led1509306, filename); led15093_config_load(&cfg->led15093, filename);
fgo_dll_config_load(&cfg->dll, filename); fgo_dll_config_load(&cfg->dll, filename);
} }

View File

@ -3,6 +3,7 @@
#include <stddef.h> #include <stddef.h>
#include "board/config.h" #include "board/config.h"
#include "board/led15093.h"
#include "hooklib/dvd.h" #include "hooklib/dvd.h"
#include "hooklib/touch.h" #include "hooklib/touch.h"
@ -10,7 +11,6 @@
#include "fgohook/deck.h" #include "fgohook/deck.h"
#include "fgohook/ftdi.h" #include "fgohook/ftdi.h"
#include "fgohook/led1509306.h"
#include "fgohook/fgo-dll.h" #include "fgohook/fgo-dll.h"
#include "platform/config.h" #include "platform/config.h"
@ -24,7 +24,7 @@ struct fgo_hook_config {
struct printer_config printer; struct printer_config printer;
struct deck_config deck; struct deck_config deck;
struct ftdi_config ftdi; struct ftdi_config ftdi;
struct led1509306_config led1509306; struct led15093_config led15093;
struct fgo_dll_config dll; struct fgo_dll_config dll;
}; };

View File

@ -90,13 +90,13 @@ static DWORD CALLBACK fgo_pre_startup(void)
goto fail; goto fail;
} }
hr = ftdi_hook_init(&fgo_hook_cfg.ftdi); hr = ftdi_hook_init(&fgo_hook_cfg.ftdi, 17);
if (FAILED(hr)) { if (FAILED(hr)) {
goto fail; goto fail;
} }
hr = led1509306_hook_init(&fgo_hook_cfg.led1509306); hr = led15093_hook_init(&fgo_hook_cfg.led15093, 17, 0);
if (FAILED(hr)) { if (FAILED(hr)) {
goto fail; goto fail;

View File

@ -121,7 +121,7 @@ static const struct hook_symbol reg_syms[] = {
static HANDLE ftdi_fd; static HANDLE ftdi_fd;
static char port_name[8]; static char port_name[8];
HRESULT ftdi_hook_init(const struct ftdi_config *cfg) { HRESULT ftdi_hook_init(const struct ftdi_config *cfg, unsigned int port_no) {
HRESULT hr; HRESULT hr;
assert(cfg != NULL); assert(cfg != NULL);
@ -130,6 +130,10 @@ HRESULT ftdi_hook_init(const struct ftdi_config *cfg) {
return S_FALSE; return S_FALSE;
} }
if (cfg->port_no != 0) {
port_no = cfg->port_no;
}
hook_table_apply( hook_table_apply(
NULL, NULL,
"setupapi.dll", "setupapi.dll",
@ -156,7 +160,7 @@ HRESULT ftdi_hook_init(const struct ftdi_config *cfg) {
return hr; return hr;
} }
sprintf(port_name, "COM%d", cfg->port_no); sprintf(port_name, "COM%d", port_no);
dprintf("FTDI: Hook enabled.\n"); dprintf("FTDI: Hook enabled.\n");
return S_OK; return S_OK;

View File

@ -18,4 +18,4 @@ DEFINE_GUID(
0x11D0, 0x11D0,
0x9C, 0xE4, 0x08, 0x00, 0x3E, 0x30, 0x1F, 0x73); 0x9C, 0xE4, 0x08, 0x00, 0x3E, 0x30, 0x1F, 0x73);
HRESULT ftdi_hook_init(const struct ftdi_config *cfg); HRESULT ftdi_hook_init(const struct ftdi_config *cfg, unsigned int port_no);

View File

@ -1,387 +0,0 @@
/*
SEGA 837-15093-06 LED controller emulator
Credits:
somewhatlurker, skogaby
*/
#include <windows.h>
#include <assert.h>
#include <process.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
#include "board/led1509306-cmd.h"
#include "board/led1509306-frame.h"
#include "fgohook/led1509306.h"
#include "hook/iobuf.h"
#include "hook/iohook.h"
#include "hooklib/uart.h"
#include "util/dprintf.h"
#include "util/dump.h"
static HRESULT led1509306_handle_irp(struct irp *irp);
static HRESULT led1509306_handle_irp_locked(int board, struct irp *irp);
static HRESULT led1509306_req_dispatch(int board, const struct led1509306_req_any *req);
static HRESULT led1509306_req_reset(int board, const struct led1509306_req_any *req);
static HRESULT led1509306_req_get_board_info(int board);
static HRESULT led1509306_req_get_fw_sum(int board);
static HRESULT led1509306_req_get_protocol_ver(int board);
static HRESULT led1509306_req_get_board_status(int board);
static HRESULT led1509306_req_set_led(int board, const struct led1509306_req_any *req);
static HRESULT led1509306_req_set_disable_response(int board, const struct led1509306_req_any *req);
static HRESULT led1509306_req_set_timeout(int board, const struct led1509306_req_any *req);
static char led1509306_board_num[8];
static char led1509306_chip_num[5];
static uint8_t led1509306_fw_ver;
static uint16_t led1509306_fw_sum;
static uint8_t led1509306_board_adr = 2;
static uint8_t led1509306_host_adr = 1;
#define led1509306_nboards 2
typedef struct {
CRITICAL_SECTION lock;
struct uart boarduart;
uint8_t written_bytes[520];
uint8_t readable_bytes[520];
bool enable_response;
} _led1509306_per_board_vars;
_led1509306_per_board_vars led1509306_per_board_vars[led1509306_nboards];
HRESULT led1509306_hook_init(const struct led1509306_config *cfg)
{
assert(cfg != NULL);
if (!cfg->enable) {
return S_FALSE;
}
memcpy(led1509306_board_num, cfg->board_number, sizeof(led1509306_board_num));
memcpy(led1509306_chip_num, cfg->chip_number, sizeof(led1509306_chip_num));
led1509306_fw_ver = cfg->fw_ver;
led1509306_fw_sum = cfg->fw_sum;
for (int i = 0; i < led1509306_nboards; i++)
{
_led1509306_per_board_vars *v = &led1509306_per_board_vars[i];
InitializeCriticalSection(&v->lock);
uart_init(&v->boarduart, cfg->port_no + i);
v->boarduart.written.bytes = v->written_bytes;
v->boarduart.written.nbytes = sizeof(v->written_bytes);
v->boarduart.readable.bytes = v->readable_bytes;
v->boarduart.readable.nbytes = sizeof(v->readable_bytes);
v->enable_response = true;
}
dprintf("LED Strip: hook enabled.\n");
return iohook_push_handler(led1509306_handle_irp);
}
static HRESULT led1509306_handle_irp(struct irp *irp)
{
HRESULT hr;
assert(irp != NULL);
for (int i = 0; i < led1509306_nboards; i++)
{
_led1509306_per_board_vars *v = &led1509306_per_board_vars[i];
struct uart *boarduart = &v->boarduart;
if (uart_match_irp(boarduart, irp))
{
CRITICAL_SECTION lock = v->lock;
EnterCriticalSection(&lock);
hr = led1509306_handle_irp_locked(i, irp);
LeaveCriticalSection(&lock);
return hr;
}
}
return iohook_invoke_next(irp);
}
static HRESULT led1509306_handle_irp_locked(int board, struct irp *irp)
{
struct led1509306_req_any req;
struct iobuf req_iobuf;
HRESULT hr;
struct uart *boarduart = &led1509306_per_board_vars[board].boarduart;
hr = uart_handle_irp(boarduart, irp);
if (FAILED(hr) || irp->op != IRP_OP_WRITE) {
return hr;
}
for (;;) {
#if 0
dprintf("TX Buffer:\n");
dump_iobuf(&boarduart->written);
#endif
req_iobuf.bytes = (byte*)&req;
req_iobuf.nbytes = sizeof(req.hdr) + sizeof(req.cmd) + sizeof(req.payload);
req_iobuf.pos = 0;
hr = led1509306_frame_decode(&req_iobuf, &boarduart->written);
if (hr != S_OK) {
if (FAILED(hr)) {
dprintf("LED Strip: Deframe error: %x\n", (int) hr);
}
return hr;
}
#if 0
dprintf("Deframe Buffer:\n");
dump_iobuf(&req_iobuf);
#endif
hr = led1509306_req_dispatch(board, &req);
if (FAILED(hr)) {
dprintf("LED Strip: Processing error: %x\n", (int) hr);
}
}
}
static HRESULT led1509306_req_dispatch(int board, const struct led1509306_req_any *req)
{
switch (req->cmd) {
case LED_15093_06_CMD_RESET:
return led1509306_req_reset(board, req);
case LED_15093_06_CMD_BOARD_INFO:
return led1509306_req_get_board_info(board);
case LED_15093_06_CMD_FW_SUM:
return led1509306_req_get_fw_sum(board);
case LED_15093_06_CMD_PROTOCOL_VER:
return led1509306_req_get_protocol_ver(board);
case LED_15093_06_CMD_BOARD_STATUS:
return led1509306_req_get_board_status(board);
case LED_15093_06_CMD_SET_LED:
return led1509306_req_set_led(board, req);
case LED_15093_06_CMD_SET_DISABLE_RESPONSE:
return led1509306_req_set_disable_response(board, req);
case LED_15093_06_CMD_SET_TIMEOUT:
return led1509306_req_set_timeout(board, req);
default:
dprintf("LED Strip: Unhandled command %02x\n", req->cmd);
return S_OK;
}
}
static HRESULT led1509306_req_reset(int board, const struct led1509306_req_any *req)
{
dprintf("LED Strip: Reset (board %u, type %02x)\n", board, req->payload[0]);
if (req->payload[0] != 0xd9)
dprintf("LED Strip: Warning -- Unknown reset type %02x\n", req->payload[0]);
led1509306_per_board_vars[board].enable_response = true;
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_RESET;
resp.report = 1;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_get_board_info(int board)
{
dprintf("LED Strip: Get board info (board %u)\n", board);
struct led1509306_resp_board_info resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = sizeof(resp.data) + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_BOARD_INFO;
resp.report = 1;
memcpy(resp.data.board_num, led1509306_board_num, sizeof(resp.data.board_num));
resp.data._0a = 0x0a;
memcpy(resp.data.chip_num, led1509306_chip_num, sizeof(resp.data.chip_num));
resp.data._ff = 0xff;
resp.data.fw_ver = led1509306_fw_ver;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_get_fw_sum(int board)
{
dprintf("LED Strip: Get firmware checksum (board %u)\n", board);
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 2 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_FW_SUM;
resp.report = 1;
resp.data[0] = (led1509306_fw_sum >> 8) & 0xff;
resp.data[1] = led1509306_fw_sum & 0xff;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_get_protocol_ver(int board)
{
dprintf("LED Strip: Get protocol version (board %u)\n", board);
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 3 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_PROTOCOL_VER;
resp.report = 1;
resp.data[0] = 1;
resp.data[1] = 1;
resp.data[2] = 4;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_get_board_status(int board)
{
dprintf("LED Strip: Get board status (board %u)\n", board);
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 4 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_BOARD_STATUS;
resp.report = 1;
resp.data[0] = 0;
resp.data[1] = 0;
resp.data[2] = 0;
resp.data[3] = 0;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_set_led(int board, const struct led1509306_req_any *req)
{
// dprintf("LED Strip: Set LED (board %u)\n", board);
if (!led1509306_per_board_vars[board].enable_response)
return S_OK;
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_SET_LED;
resp.report = 1;
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_set_disable_response(int board, const struct led1509306_req_any *req)
{
dprintf("LED Strip: Disable LED responses (board %u)\n", board);
led1509306_per_board_vars[board].enable_response = !req->payload[0];
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 1 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_SET_DISABLE_RESPONSE;
resp.report = 1;
resp.data[0] = req->payload[0];
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}
static HRESULT led1509306_req_set_timeout(int board, const struct led1509306_req_any *req)
{
dprintf("LED Strip: Set timeout (board %u)\n", board);
// not actually implemented, but respond correctly anyway
struct led1509306_resp_any resp;
memset(&resp, 0, sizeof(resp));
resp.hdr.sync = LED_15093_06_FRAME_SYNC;
resp.hdr.dest_adr = led1509306_host_adr;
resp.hdr.src_adr = led1509306_board_adr;
resp.hdr.nbytes = 2 + 3;
resp.status = 1;
resp.cmd = LED_15093_06_CMD_SET_TIMEOUT;
resp.report = 1;
resp.data[0] = req->payload[0];
resp.data[1] = req->payload[1];
return led1509306_frame_encode(&led1509306_per_board_vars[board].boarduart.readable, &resp, sizeof(resp.hdr) + resp.hdr.nbytes);
}

View File

@ -1,16 +0,0 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
struct led1509306_config {
bool enable;
unsigned int port_no;
char board_number[8];
char chip_number[5];
uint8_t fw_ver;
uint16_t fw_sum;
};
HRESULT led1509306_hook_init(const struct led1509306_config *cfg);

View File

@ -30,7 +30,5 @@ shared_library(
'deck.h', 'deck.h',
'ftdi.c', 'ftdi.c',
'ftdi.h', 'ftdi.h',
'led1509306.c',
'led1509306.h',
], ],
) )