vsmile_ctrl: fix controller not working if buttons are pushed too early

This commit is contained in:
Vas Crabb 2019-01-21 23:33:13 +11:00
parent 979e3bf7f2
commit a16fb19be9
5 changed files with 273 additions and 56 deletions

View File

@ -1,29 +1,42 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
// copyright-holders:Ryan Holtz, Vas Crabb
#include "emu.h"
#include "pad.h"
#include <algorithm>
//#define VERBOSE 1
#include "logmacro.h"
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
DEFINE_DEVICE_TYPE(VSMILE_PAD, vsmile_pad_device, "vsmile_pad", "V.Smile Control Pad")
DEFINE_DEVICE_TYPE(VSMILE_PAD, vsmile_pad_device, "vsmile_pad", "V.Smile Joystick")
//**************************************************************************
// V.Smile control pad
//**************************************************************************
DECLARE_ENUM_BITWISE_OPERATORS(vsmile_pad_device::stale_inputs)
ALLOW_SAVE_TYPE(vsmile_pad_device::stale_inputs);
vsmile_pad_device::vsmile_pad_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock)
: vsmile_ctrl_device_base(mconfig, VSMILE_PAD, tag, owner, clock)
, m_io_joy(*this, "JOY")
, m_io_colors(*this, "COLORS")
, m_io_buttons(*this, "BUTTONS")
, m_idle_timer(nullptr)
, m_ctrl_probe_count(0U)
, m_sent_joy(0x00U)
, m_sent_colors(0x00U)
, m_sent_buttons(0x00U)
, m_stale(STALE_ALL)
, m_active(false)
{
std::fill(std::begin(m_ctrl_probe_history), std::end(m_ctrl_probe_history), 0U);
}
vsmile_pad_device::~vsmile_pad_device()
@ -36,27 +49,104 @@ void vsmile_pad_device::device_start()
m_idle_timer = machine().scheduler().timer_alloc(
timer_expired_delegate(FUNC(vsmile_pad_device::handle_idle), this));
m_idle_timer->adjust(attotime::from_hz(1));
m_idle_timer->adjust(attotime::from_seconds(1));
m_sent_joy = 0x00U;
m_sent_colors = 0x00U;
m_sent_buttons = 0x00U;
m_stale = STALE_ALL;
m_active = false;
save_item(NAME(m_sent_joy));
save_item(NAME(m_sent_colors));
save_item(NAME(m_sent_buttons));
save_item(NAME(m_stale));
save_item(NAME(m_active));
save_item(NAME(m_ctrl_probe_history));
save_item(NAME(m_ctrl_probe_count));
}
void vsmile_pad_device::tx_complete()
{
m_idle_timer->adjust(attotime::from_hz(1));
// update joystick
if ((m_stale & STALE_JOY) != STALE_NONE)
{
m_sent_joy = m_io_joy->read();
if ((m_stale & STALE_UP_DOWN) != STALE_NONE)
{
if (BIT(m_sent_joy, 0))
uart_tx_fifo_push(0x87); // up
else if (BIT(m_sent_joy, 1))
uart_tx_fifo_push(0x8f); // down
else
uart_tx_fifo_push(0x80);
}
if ((m_stale & STALE_LEFT_RIGHT) != STALE_NONE)
{
if (BIT(m_sent_joy, 2))
uart_tx_fifo_push(0xcf); // left
else if (BIT(m_sent_joy, 3))
uart_tx_fifo_push(0xc7); // right
else
uart_tx_fifo_push(0xc0);
}
}
// update colors
if ((m_stale & STALE_COLORS) != STALE_NONE)
{
m_sent_colors = m_io_colors->read();
uart_tx_fifo_push(0x90 | m_sent_colors);
}
// update buttons
if ((m_stale & STALE_BUTTONS) != STALE_NONE)
{
m_sent_buttons = m_io_buttons->read();
if (((m_stale & STALE_OK) != STALE_NONE) && BIT(m_sent_buttons, 0))
uart_tx_fifo_push(0xa1);
if (((m_stale & STALE_QUIT) != STALE_NONE) && BIT(m_sent_buttons, 1))
uart_tx_fifo_push(0xa2);
if (((m_stale & STALE_HELP) != STALE_NONE) && BIT(m_sent_buttons, 2))
uart_tx_fifo_push(0xa3);
if (((m_stale & STALE_ABC) != STALE_NONE) && BIT(m_sent_buttons, 3))
uart_tx_fifo_push(0xa4);
if (!m_sent_buttons)
uart_tx_fifo_push(0xa0);
}
// if nothing happens in the next second we'll queue a keep-alive
if (!m_active)
LOG("entered active state\n");
m_idle_timer->adjust(attotime::from_seconds(1));
m_active = true;
m_stale = STALE_NONE;
}
void vsmile_pad_device::tx_timeout()
{
if (m_active)
{
m_idle_timer->adjust(attotime::from_seconds(1));
m_active = false;
m_stale = STALE_ALL;
LOG("left active state\n");
}
}
void vsmile_pad_device::rx_complete(uint8_t data, bool select)
{
if (select)
{
//printf("%s Receiving: %02x\n", tag(), data);
if ((data >> 4) == 7 || (data >> 4) == 11)
if (((data & 0xf0) == 0x70) || ((data & 0xf0) == 0xb0))
{
m_ctrl_probe_history[0] = m_ctrl_probe_history[1];
m_ctrl_probe_history[1] = data;
const uint8_t response = ((m_ctrl_probe_history[0] + m_ctrl_probe_history[1] + 0x0f) & 0x0f) ^ 0x05;
uint8_t const response = ((m_ctrl_probe_history[0] + m_ctrl_probe_history[1] + 0x0f) & 0x0f) ^ 0x05;
LOG(
"received probe %02X, %02X, sending response %02X\n",
m_ctrl_probe_history[0],
m_ctrl_probe_history[1],
0xb0 | response);
uart_tx_fifo_push(0xb0 | response);
}
}
@ -70,67 +160,109 @@ void vsmile_pad_device::uart_tx_fifo_push(uint8_t data)
TIMER_CALLBACK_MEMBER(vsmile_pad_device::handle_idle)
{
LOG("idle timer expired, sending keep-alive 55\n");
queue_tx(0x55);
}
INPUT_CHANGED_MEMBER(vsmile_pad_device::pad_joy_changed)
{
const uint8_t value = m_io_joy->read();
if (BIT(value, 2))
uart_tx_fifo_push(0xcf);
else if (BIT(value, 3))
uart_tx_fifo_push(0xc7);
else
uart_tx_fifo_push(0xc0);
if (BIT(value, 0))
uart_tx_fifo_push(0x87);
else if (BIT(value, 1))
uart_tx_fifo_push(0x8f);
else
uart_tx_fifo_push(0x80);
if (m_active)
{
if (!is_tx_empty())
{
LOG("joy changed while transmission in progress, marking stale\n");
m_stale |= stale_inputs(uintptr_t(param));
}
else
{
uint8_t const joy = m_io_joy->read();
if ((joy ^ m_sent_joy) & 0x03)
{
if (BIT(joy, 0))
uart_tx_fifo_push(0x87); // up
else if (BIT(joy, 1))
uart_tx_fifo_push(0x8f); // down
else
uart_tx_fifo_push(0x80);
}
if ((joy ^ m_sent_joy) & 0x0c)
{
if (BIT(joy, 2))
uart_tx_fifo_push(0xcf); // left
else if (BIT(joy, 3))
uart_tx_fifo_push(0xc7); // right
else
uart_tx_fifo_push(0xc0);
}
m_sent_joy = joy;
}
}
}
INPUT_CHANGED_MEMBER(vsmile_pad_device::pad_color_changed)
{
uart_tx_fifo_push(0x90 | m_io_colors->read());
if (m_active)
{
if (!is_tx_empty())
{
LOG("colors changed while transmission in progress, marking stale\n");
m_stale |= STALE_COLORS;
}
else
{
m_sent_colors = m_io_colors->read();
uart_tx_fifo_push(0x90 | m_io_colors->read());
}
}
}
INPUT_CHANGED_MEMBER(vsmile_pad_device::pad_button_changed)
{
const uint8_t value = m_io_buttons->read();
const size_t bit = reinterpret_cast<size_t>(param);
if (BIT(value, bit))
if (m_active)
{
uart_tx_fifo_push(0xa1 + (uint8_t)bit);
}
else
{
uart_tx_fifo_push(0xa0);
if (!is_tx_empty())
{
LOG("buttons changed while transmission in progress, marking stale\n");
m_stale |= stale_inputs(uintptr_t(param));
}
else
{
uint8_t const buttons = m_io_buttons->read();
if (BIT((m_sent_buttons ^ buttons) & buttons, 0))
uart_tx_fifo_push(0xa1);
if (BIT((m_sent_buttons ^ buttons) & buttons, 1))
uart_tx_fifo_push(0xa2);
if (BIT((m_sent_buttons ^ buttons) & buttons, 2))
uart_tx_fifo_push(0xa3);
if (BIT((m_sent_buttons ^ buttons) & buttons, 3))
uart_tx_fifo_push(0xa4);
if (!buttons)
uart_tx_fifo_push(0xa0);
m_sent_buttons = buttons;
}
}
}
static INPUT_PORTS_START( vsmile_pad )
PORT_START("JOY")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_joy_changed, 0) PORT_NAME("Joypad Up")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_joy_changed, 0) PORT_NAME("Joypad Down")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_joy_changed, 0) PORT_NAME("Joypad Left")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_joy_changed, 0) PORT_NAME("Joypad Right")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_joy_changed, vsmile_pad_device::STALE_UP_DOWN) PORT_NAME("Joypad Up")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_joy_changed, vsmile_pad_device::STALE_UP_DOWN) PORT_NAME("Joypad Down")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_joy_changed, vsmile_pad_device::STALE_LEFT_RIGHT) PORT_NAME("Joypad Left")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_joy_changed, vsmile_pad_device::STALE_LEFT_RIGHT) PORT_NAME("Joypad Right")
PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("COLORS")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_color_changed, 0) PORT_NAME("Green")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_color_changed, 0) PORT_NAME("Blue")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_color_changed, 0) PORT_NAME("Yellow")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_color_changed, 0) PORT_NAME("Red")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_color_changed, vsmile_pad_device::STALE_COLORS) PORT_NAME("Green")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_color_changed, vsmile_pad_device::STALE_COLORS) PORT_NAME("Blue")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_color_changed, vsmile_pad_device::STALE_COLORS) PORT_NAME("Yellow")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_color_changed, vsmile_pad_device::STALE_COLORS) PORT_NAME("Red")
PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED )
PORT_START("BUTTONS")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_button_changed, 0) PORT_NAME("OK")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_button_changed, 1) PORT_NAME("Quit")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_button_changed, 2) PORT_NAME("Help")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_button_changed, 3) PORT_NAME("ABC")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_button_changed, vsmile_pad_device::STALE_OK) PORT_NAME("OK")
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_button_changed, vsmile_pad_device::STALE_QUIT) PORT_NAME("Quit")
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_button_changed, vsmile_pad_device::STALE_HELP) PORT_NAME("Help")
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_BUTTON8 ) PORT_CHANGED_MEMBER(DEVICE_SELF, vsmile_pad_device, pad_button_changed, vsmile_pad_device::STALE_ABC) PORT_NAME("ABC")
PORT_BIT( 0xf0, IP_ACTIVE_HIGH, IPT_UNUSED )
INPUT_PORTS_END

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
// copyright-holders:Ryan Holtz, Vas Crabb
#ifndef MAME_BUS_VSMILE_PAD_H
#define MAME_BUS_VSMILE_PAD_H
@ -16,10 +16,27 @@
class vsmile_pad_device : public vsmile_ctrl_device_base
{
public:
enum stale_inputs : uint8_t
{
STALE_NONE = 0U,
STALE_LEFT_RIGHT = 1U << 0,
STALE_UP_DOWN = 1U << 1,
STALE_COLORS = 1U << 2,
STALE_OK = 1U << 3,
STALE_QUIT = 1U << 4,
STALE_HELP = 1U << 5,
STALE_ABC = 1U << 6,
STALE_JOY = STALE_LEFT_RIGHT | STALE_UP_DOWN,
STALE_BUTTONS = STALE_OK | STALE_QUIT | STALE_HELP | STALE_ABC,
STALE_ALL = STALE_JOY | STALE_COLORS | STALE_BUTTONS
};
// construction/destruction
vsmile_pad_device(machine_config const &mconfig, char const *tag, device_t *owner, uint32_t clock = 0U);
virtual ~vsmile_pad_device();
// input handlers
DECLARE_INPUT_CHANGED_MEMBER(pad_joy_changed);
DECLARE_INPUT_CHANGED_MEMBER(pad_color_changed);
DECLARE_INPUT_CHANGED_MEMBER(pad_button_changed);
@ -31,6 +48,7 @@ protected:
// vsmile_ctrl_device_base implementation
virtual void tx_complete() override;
virtual void tx_timeout() override;
virtual void rx_complete(uint8_t data, bool cts) override;
private:
@ -44,8 +62,10 @@ private:
emu_timer *m_idle_timer;
uint8_t m_sent_joy, m_sent_colors, m_sent_buttons;
stale_inputs m_stale;
bool m_active;
uint8_t m_ctrl_probe_history[2];
uint8_t m_ctrl_probe_count;
};

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
// copyright-holders:Vas Crabb
#include "emu.h"
#include "vsmile_ctrl.h"
@ -7,6 +7,9 @@
#include <algorithm>
#include <cassert>
//#define VERBOSE 1
#include "logmacro.h"
//**************************************************************************
// GLOBAL VARIABLES
@ -125,6 +128,7 @@ vsmile_ctrl_device_base::vsmile_ctrl_device_base(
: device_t(mconfig, type, tag, owner, clock)
, device_vsmile_ctrl_interface(mconfig, *this)
, m_tx_timer(nullptr)
, m_rts_timer(nullptr)
, m_tx_fifo_head(0U)
, m_tx_fifo_tail(0U)
, m_tx_fifo_empty(true)
@ -144,6 +148,10 @@ void vsmile_ctrl_device_base::device_start()
m_tx_timer = machine().scheduler().timer_alloc(
timer_expired_delegate(FUNC(vsmile_ctrl_device_base::tx_timer_expired), this));
// allocate a timer for RTS timeouts
m_rts_timer = machine().scheduler().timer_alloc(
timer_expired_delegate(FUNC(vsmile_ctrl_device_base::rts_timer_expired), this));
// start with transmit queue empty
m_tx_fifo_head = m_tx_fifo_tail = 0U;
m_tx_fifo_empty = true;
@ -162,7 +170,10 @@ bool vsmile_ctrl_device_base::queue_tx(uint8_t data)
// return false on overrun and drop byte
bool const was_empty(m_tx_fifo_empty);
if (!was_empty && (m_tx_fifo_head == m_tx_fifo_tail))
{
LOG("discarding byte %02X because FIFO is full (length %u, Tx %sactive)\n", data, ARRAY_LENGTH(m_tx_fifo), m_tx_active ? "" : "in");
return false;
}
// queue the byte
m_tx_fifo[m_tx_fifo_tail] = data;
@ -175,9 +186,20 @@ bool vsmile_ctrl_device_base::queue_tx(uint8_t data)
rts_out(1);
if (m_select)
{
LOG("transmitting byte %02X immediately (Tx was %sactive)\n", data, m_tx_active ? "" : "in");
m_tx_active = true;
m_tx_timer->adjust(attotime::from_hz(9600 / 10));
}
else
{
LOG("asserting RTS to transmit byte %02X\n", data);
m_rts_timer->adjust(attotime::from_msec(500));
}
}
else
{
unsigned const fifo_used((m_tx_fifo_tail + ARRAY_LENGTH(m_tx_fifo) - m_tx_fifo_head) % ARRAY_LENGTH(m_tx_fifo));
LOG("queued byte %02X (%u bytes queued, Tx %sactive)\n", data, fifo_used, m_tx_active ? "" : "in");
}
// data was queued
@ -186,16 +208,27 @@ bool vsmile_ctrl_device_base::queue_tx(uint8_t data)
void vsmile_ctrl_device_base::select_w(int state)
{
m_select = bool(state);
if (m_select && !m_tx_fifo_empty && !m_tx_active)
if (bool(state) != m_select)
{
m_tx_active = true;
m_tx_timer->adjust(attotime::from_hz(9600 / 10));
if (state && !m_tx_fifo_empty && !m_tx_active)
{
m_rts_timer->reset();
unsigned const fifo_used((m_tx_fifo_tail + ARRAY_LENGTH(m_tx_fifo) - m_tx_fifo_head) % ARRAY_LENGTH(m_tx_fifo));
LOG("select asserted, starting transmission (%u bytes queued)\n", fifo_used);
m_tx_active = true;
m_tx_timer->adjust(attotime::from_hz(9600 / 10));
}
else
{
LOG("select %sasserted (Tx %sactive)\n", state ? "" : "de", m_tx_active ? "" : "in");
}
m_select = bool(state);
}
}
void vsmile_ctrl_device_base::data_w(uint8_t data)
{
LOG("received byte %02X (select %sasserted, Tx %sactive)\n", data, m_select ? "" : "de", m_tx_active ? "" : "in");
rx_complete(data, m_select);
}
@ -213,21 +246,50 @@ TIMER_CALLBACK_MEMBER(vsmile_ctrl_device_base::tx_timer_expired)
// if queue is drained give implmentation a chance to queue more before dropping RTS
if (m_tx_fifo_empty)
{
LOG("transmitted byte %02X, queue empty (select %sasserted)\n", data, m_select ? "" : "de");
tx_complete();
}
else
{
unsigned const fifo_used((m_tx_fifo_tail + ARRAY_LENGTH(m_tx_fifo) - m_tx_fifo_head) % ARRAY_LENGTH(m_tx_fifo));
LOG("transmitted byte %02X (%u bytes queued, select %sasserted)\n", data, fifo_used, m_select ? "" : "de");
}
// drop RTS if no more data, otherwise keep transmitting if CTS is still high
if (m_tx_fifo_empty)
{
LOG("nothing to transmit, deasserting RTS\n");
m_tx_active = false;
rts_out(0);
}
else if (m_select)
{
LOG("select asserted, transmitting next byte %02X\n", m_tx_fifo[m_tx_fifo_head]);
m_tx_timer->adjust(attotime::from_hz(9600 / 10));
}
else
{
LOG("select deasserted, waiting to transmit\n");
m_tx_active = false;
m_rts_timer->adjust(attotime::from_msec(500));
}
}
TIMER_CALLBACK_MEMBER(vsmile_ctrl_device_base::rts_timer_expired)
{
assert(!m_tx_fifo_empty);
assert(!m_tx_active);
// clear out anything queued and let the implementation deal with it
if (!m_tx_fifo_empty)
{
unsigned const fifo_used((m_tx_fifo_tail + ARRAY_LENGTH(m_tx_fifo) - m_tx_fifo_head) % ARRAY_LENGTH(m_tx_fifo));
LOG("timeout waiting for select after asserting RTS (%u bytes queued)\n", fifo_used);
m_tx_fifo_head = m_tx_fifo_tail = 0U;
m_tx_fifo_empty = true;
tx_timeout();
}
}
@ -236,5 +298,5 @@ TIMER_CALLBACK_MEMBER(vsmile_ctrl_device_base::tx_timer_expired)
void vsmile_controllers(device_slot_interface &device)
{
device.option_add("pad", VSMILE_PAD);
device.option_add("joy", VSMILE_PAD);
}

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Ryan Holtz
// copyright-holders:Vas Crabb
#ifndef MAME_BUS_VSMILE_VSMILE_CTRL_H
#define MAME_BUS_VSMILE_VSMILE_CTRL_H
@ -103,6 +103,7 @@ protected:
virtual void device_start() override;
// UART simulation helpers
bool is_tx_empty() const { return m_tx_fifo_empty; }
bool queue_tx(uint8_t data);
private:
@ -112,12 +113,14 @@ private:
// UART simulation handlers
virtual void tx_complete() = 0;
virtual void tx_timeout() = 0;
virtual void rx_complete(uint8_t data, bool select) = 0;
// internal helpers
TIMER_CALLBACK_MEMBER(tx_timer_expired);
TIMER_CALLBACK_MEMBER(rts_timer_expired);
emu_timer *m_tx_timer;
emu_timer *m_tx_timer, *m_rts_timer;
uint8_t m_tx_fifo[32];
uint8_t m_tx_fifo_head, m_tx_fifo_tail;

View File

@ -435,7 +435,7 @@ void vsmile_state::vsmile(machine_config &config)
m_spg->portc_out().set(FUNC(vsmile_state::portc_w));
m_spg->uart_tx().set(FUNC(vsmile_state::uart_rx));
VSMILE_CTRL_PORT(config, m_ctrl[0], vsmile_controllers, "pad");
VSMILE_CTRL_PORT(config, m_ctrl[0], vsmile_controllers, "joy");
m_ctrl[0]->rts_cb().set(FUNC(vsmile_state::ctrl_rts_w<0>));
m_ctrl[0]->data_cb().set(FUNC(vsmile_state::ctrl_tx_w));