feat(extiodrv): Add (DDR) EXTIO driver

Initial version that supports the most important
features to operate a DDR SD cabinet with all
inputs and outputs working.

Note that the individual sensor cycling modes are
currently broken. The driver will always set the
sensor read mode to all for now.
This commit is contained in:
icex2
2023-06-25 13:24:07 +02:00
committed by icex2
parent 2bbbfccd13
commit db2d71e13c
5 changed files with 399 additions and 0 deletions
+110
View File
@@ -0,0 +1,110 @@
#define LOG_MODULE "extiodrv-extio"
#include "extio.h"
#include "util/log.h"
// static uint8_t _extiodrv_extio_sensor_read_mode_map[5] = {
// 1, // all
// 2, // up
// 3, // down
// 4, // left
// 5, // right
// };
HRESULT extiodrv_extio_transfer(
HANDLE handle,
enum extiodrv_extio_sensor_read_mode sensor_read_mode,
const struct extiodrv_extio_pad_lights
pad_lights[EXTIO_PAD_LIGHT_MAX_PLAYERS],
bool neons)
{
HRESULT hr;
struct extio_cmd_write write;
struct extio_cmd_read read;
size_t bytes_written;
size_t bytes_read;
const uint8_t *raw;
log_assert(handle != INVALID_HANDLE_VALUE);
memset(&write, 0, sizeof(write));
// TODO this doesn't seem to work, yet
// write.sensor_read_mode =
// 0;//_extiodrv_extio_sensor_read_mode_map[sensor_read_mode]; 0 = all 1 =
// mess? 2 = mess? 3 = mess? 4 = mess? 5 = mess? 6 = right sensor only 7 =
// right sensor only 8 = right sensor only
write.sensor_read_mode = 0;
for (uint8_t i = 0; i < EXTIO_PAD_LIGHT_MAX_PLAYERS; i++) {
write.pad_lights[i].up = pad_lights[i].up ? 1 : 0;
write.pad_lights[i].down = pad_lights[i].down ? 1 : 0;
write.pad_lights[i].left = pad_lights[i].left ? 1 : 0;
write.pad_lights[i].right = pad_lights[i].right ? 1 : 0;
}
write.neons = neons ? 1 : 0;
// This MUST be set but only on the p1 packet
// Not setting it or also setting it on the p2 packet results in the EXTIO
// not responding at all
write.pad_lights[0].unknown_80 = 1;
write.checksum = extio_cmd_checksum(&write);
raw = (uint8_t *) &write;
log_misc("Raw write paket: %X %X %X %X", raw[0], raw[1], raw[2], raw[3]);
hr = extiodrv_device_write(handle, &write, sizeof(write), &bytes_written);
if (FAILED(hr)) {
log_warning("Writing extio device failed");
return hr;
}
if (bytes_written != sizeof(write)) {
log_warning(
"Writing extio device failed, expected bytes %d != actual bytes %d",
(uint32_t) sizeof(write),
(uint32_t) bytes_written);
return HRESULT_FROM_WIN32(ERROR_BAD_LENGTH);
}
// Read loop to keep reading until a full message is read
// There are various occasions, especially if polling from the host side is
// faster than the device can put the response to the wire. this can result
// in empty reads
while (true) {
hr = extiodrv_device_read(handle, &read, sizeof(read), &bytes_read);
if (FAILED(hr)) {
log_warning("Reading extio device failed");
return hr;
}
if (bytes_read < sizeof(read)) {
log_misc("Empty read, retry read");
continue;
}
if (bytes_read != sizeof(read)) {
log_warning(
"Reading extio device failed, expected bytes %d != actual "
"bytes %d",
(uint32_t) sizeof(read),
(uint32_t) bytes_read);
return HRESULT_FROM_WIN32(ERROR_BAD_LENGTH);
}
break;
}
if (read.status != EXTIO_STATUS_OK) {
log_warning("Status not ok: 0x%X", read.status);
return HRESULT_FROM_WIN32(ERROR_GEN_FAILURE);
}
return S_OK;
}