mirror of
https://github.com/holub/mame
synced 2025-10-06 09:00:04 +03:00
vsmile_ctrl: fix controller not working if buttons are pushed too early
This commit is contained in:
parent
979e3bf7f2
commit
a16fb19be9
@ -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
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user