summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author MooglyGuy <therealmogminer@gmail.com>2019-12-26 19:03:37 +0100
committer MooglyGuy <therealmogminer@gmail.com>2019-12-26 19:03:37 +0100
commitdee55a8f5a05877e65cdc59d54a9325c93a612c9 (patch)
treef4ce6b2a6856118cdb0fd3a37b6c125045337133
parent33b51348633f0016a6afaababd3db016a7d7f73e (diff)
-cdimono2: Improved SPI emulation in the 68hc05 core, better hookup of /SS lines, nw
-rw-r--r--src/devices/cpu/m6805/m68hc05.cpp78
-rw-r--r--src/devices/cpu/m6805/m68hc05.h4
-rw-r--r--src/devices/machine/scc68070.cpp2
-rw-r--r--src/mame/drivers/cdi.cpp75
-rw-r--r--src/mame/includes/cdi.h11
5 files changed, 148 insertions, 22 deletions
diff --git a/src/devices/cpu/m6805/m68hc05.cpp b/src/devices/cpu/m6805/m68hc05.cpp
index cab71263867..fa7eb82bc42 100644
--- a/src/devices/cpu/m6805/m68hc05.cpp
+++ b/src/devices/cpu/m6805/m68hc05.cpp
@@ -36,7 +36,7 @@ determines both the COP watchdog timeout and the real-time interrupt rate
#define LOG_UART (1U << 5)
#define LOG_SPI (1U << 6)
-#define VERBOSE (LOG_GENERAL | LOG_INT | LOG_IOPORT | LOG_COP | LOG_UART | LOG_SPI)
+#define VERBOSE (LOG_GENERAL | LOG_INT | LOG_COP | LOG_UART | LOG_SPI)
//#define LOG_OUTPUT_FUNC printf
#include "logmacro.h"
@@ -273,14 +273,23 @@ u8 m68hc05_device::spcr_spr_divider() const
READ8_MEMBER(m68hc05_device::spcr_r)
{
+ LOGSPI("%s: read SPCR: %02x\n", machine().describe_context(), m_spcr);
return m_spcr;
}
WRITE8_MEMBER(m68hc05_device::spcr_w)
{
+ if (spsr_modf())
+ {
+ m_spsr &= ~0x10;
+ if (!spcr_spie() || !spsr_spif())
+ {
+ m_pending_interrupts &= ~M68HC05_INT_SPI;
+ }
+ }
data &= 0xdf;
m_spcr = data;
- LOGSPI("write SPCR: SPIE=%u SPE=%u MSTR=%u CPOL=%u CPHA=%u SPR=%u (divider %u)\n",
+ LOGSPI("%s: write SPCR: SPIE=%u SPE=%u MSTR=%u CPOL=%u CPHA=%u SPR=%u (divider %u)\n", machine().describe_context(),
spcr_spie(), spcr_spe(), spcr_mstr(), spcr_cpol(), spcr_cpha(), spcr_spr(), spcr_spr_divider());
if (m_spi_tx_clocks == ~0U)
{
@@ -290,6 +299,7 @@ WRITE8_MEMBER(m68hc05_device::spcr_w)
READ8_MEMBER(m68hc05_device::spsr_r)
{
+ LOGSPI("%s: read SPSR: %02x\n", machine().describe_context(), m_spsr);
return m_spsr;
}
@@ -300,14 +310,19 @@ WRITE8_MEMBER(m68hc05_device::spsr_w)
READ8_MEMBER(m68hc05_device::spdr_r)
{
- LOGSPI("%s: read SPDR: %02x\n", machine().describe_context(), m_spdr);
+ LOGSPI("%s: read SPDR: %02x\n", machine().describe_context(), m_sprr);
m_spsr &= ~0xd0;
- return m_spdr;
+ return m_sprr;
}
WRITE8_MEMBER(m68hc05_device::spdr_w)
{
LOGSPI("%s: write SPDR: %02x\n", machine().describe_context(), data);
+ if (spcr_mstr() && spsr_spif())
+ {
+ LOGSPI("%s: SPDR write inhibited due to MSTR and SPIF both set\n", machine().describe_context());
+ return;
+ }
m_spdr = data;
if (spcr_spe())
{
@@ -327,6 +342,11 @@ WRITE8_MEMBER(m68hc05_device::spdr_w)
WRITE_LINE_MEMBER(m68hc05_device::sck_in)
{
+ if (!spcr_mstr() && m_ss)
+ {
+ LOGSPI("sck_in (ignored due to high SS and non-master): %d\n", state);
+ return;
+ }
LOGSPI("sck_in: %d\n", state);
u8 old = m_sck;
m_sck = state;
@@ -342,6 +362,7 @@ WRITE_LINE_MEMBER(m68hc05_device::sck_in)
m_spi_rx_cnt++;
if (m_spi_rx_cnt == 8)
{
+ m_sprr = m_spdr;
m_spi_rx_cnt = 0;
m_spsr |= 0x80;
if (spsr_spif() && spcr_spie())
@@ -359,10 +380,34 @@ WRITE_LINE_MEMBER(m68hc05_device::sck_in)
WRITE_LINE_MEMBER(m68hc05_device::sda_in)
{
+ if (!spcr_mstr() && m_ss)
+ {
+ LOGSPI("sda_in (ignored due to high SS and non-master): %d\n", state);
+ return;
+ }
LOGSPI("sda_in: %d\n", state);
m_sda = state;
}
+WRITE_LINE_MEMBER(m68hc05_device::ss_in)
+{
+ LOGSPI("ss_in: %d\n", state);
+ u8 old = m_ss;
+ m_ss = state;
+ if (old != m_ss)
+ {
+ if (spcr_mstr() && state)
+ {
+ m_spsr |= 0x10;
+ m_spcr &= ~0x50;
+ if (spcr_spie())
+ {
+ m_pending_interrupts |= M68HC05_INT_SPI;
+ }
+ }
+ }
+}
+
u8 m68hc05_device::baud_scp_count() const
{
static const uint32_t s_prescale_values[4] = { 1, 3, 4, 13 };
@@ -407,12 +452,16 @@ WRITE8_MEMBER(m68hc05_device::sccr2_w)
sccr2_tie(), sccr2_tcie(), sccr2_rie(), sccr2_ilie(), sccr2_te(), sccr2_re(), sccr2_rwu(), sccr2_sbk());
if (sccr2_te() && m_tdr_pending)
{
- m_uart_tx_clocks = 32 * baud_scp_count() * baud_scr_count();
+ m_uart_tx_clocks = 10 * 32 * baud_scp_count() * baud_scr_count();
}
if (sccr2_re() && m_rdr_pending)
{
- m_uart_rx_clocks = 32 * baud_scp_count() * baud_scr_count();
+ m_uart_rx_clocks = 10 * 32 * baud_scp_count() * baud_scr_count();
}
+ if (m_scsr & m_sccr2 & 0xf0)
+ m_pending_interrupts |= M68HC05_INT_SCI;
+ else
+ m_pending_interrupts &= ~M68HC05_INT_SCI;
}
READ8_MEMBER(m68hc05_device::scsr_r)
@@ -679,12 +728,14 @@ void m68hc05_device::device_start()
save_item(NAME(m_spcr));
save_item(NAME(m_spsr));
save_item(NAME(m_spdr));
+ save_item(NAME(m_sprr));
save_item(NAME(m_spi_rx_cnt));
save_item(NAME(m_spi_tx_cnt));
save_item(NAME(m_spi_tx_clocks));
save_item(NAME(m_spi_run_clocks));
save_item(NAME(m_sck));
save_item(NAME(m_sda));
+ save_item(NAME(m_ss));
// save timer/counter
save_item(NAME(m_tcap_state));
@@ -722,12 +773,14 @@ void m68hc05_device::device_start()
m_spcr = 0x00;
m_spsr = 0x00;
m_spdr = 0x00;
+ m_sprr = 0x00;
m_spi_rx_cnt = 0;
m_spi_tx_cnt = 0;
m_spi_tx_clocks = ~0U;
m_spi_run_clocks = 0;
m_sck = 0x00;
m_sda = 0x00;
+ m_ss = 0x01;
// timer state unaffected by reset
m_tcap_state = false;
@@ -765,6 +818,7 @@ void m68hc05_device::device_reset()
m_spi_run_clocks = 0;
m_sck = 0x00;
m_sda = 0x00;
+ m_ss = 0x01;
// timer reset
m_tcr &= 0x02;
@@ -960,8 +1014,8 @@ void m68hc05_device::burn_cycles(unsigned count)
// run SPI Tx
if (m_spi_tx_clocks != ~0U)
{
- m_spi_run_clocks += count * ps_opt;
- while (m_spi_run_clocks > m_spi_tx_clocks && m_spi_tx_cnt > 0)
+ m_spi_run_clocks += count << ps_opt;
+ while (m_spi_run_clocks >= m_spi_tx_clocks && m_spi_tx_cnt > 0)
{
m_spi_run_clocks -= m_spi_tx_clocks;
@@ -993,9 +1047,9 @@ void m68hc05_device::burn_cycles(unsigned count)
// run UART Tx
if (m_uart_tx_clocks != ~0U)
{
- if (m_uart_tx_clocks > count * ps_opt)
+ if (m_uart_tx_clocks > count)
{
- m_uart_tx_clocks -= count * ps_opt;
+ m_uart_tx_clocks -= count;
}
else
{
@@ -1014,9 +1068,9 @@ void m68hc05_device::burn_cycles(unsigned count)
// run UART Rx
if (m_uart_rx_clocks != ~0U && sccr2_re())
{
- if (m_uart_rx_clocks > count * ps_opt)
+ if (m_uart_rx_clocks > count)
{
- m_uart_rx_clocks -= count * ps_opt;
+ m_uart_rx_clocks -= count;
}
else
{
diff --git a/src/devices/cpu/m6805/m68hc05.h b/src/devices/cpu/m6805/m68hc05.h
index 8fccb87e7c7..dd8d5c8427d 100644
--- a/src/devices/cpu/m6805/m68hc05.h
+++ b/src/devices/cpu/m6805/m68hc05.h
@@ -48,6 +48,7 @@ public:
auto sda_out() { return m_sda_out_cb.bind(); }
DECLARE_WRITE_LINE_MEMBER(sck_in);
DECLARE_WRITE_LINE_MEMBER(sda_in);
+ DECLARE_WRITE_LINE_MEMBER(ss_in);
protected:
// state index constants
@@ -187,6 +188,7 @@ private:
u8 spcr_spr_divider() const;
bool spsr_spif() const { return BIT(m_spsr, 7); }
+ bool spsr_modf() const { return BIT(m_spsr, 4); }
bool tcr_icie() const { return BIT(m_tcr, 7); }
bool tcr_ocie() const { return BIT(m_tcr, 6); }
@@ -226,12 +228,14 @@ private:
u8 m_spcr;
u8 m_spsr;
u8 m_spdr;
+ u8 m_sprr;
u8 m_spi_rx_cnt;
u8 m_spi_tx_cnt;
u32 m_spi_tx_clocks;
u32 m_spi_run_clocks;
u8 m_sck;
u8 m_sda;
+ u8 m_ss;
devcb_write_line m_sck_out_cb;
devcb_write_line m_sda_out_cb;
diff --git a/src/devices/machine/scc68070.cpp b/src/devices/machine/scc68070.cpp
index 4dcf3ae4965..ead49f483fc 100644
--- a/src/devices/machine/scc68070.cpp
+++ b/src/devices/machine/scc68070.cpp
@@ -34,7 +34,7 @@ TODO:
#define LOG_UNKNOWN (1 << 7)
#define LOG_ALL (LOG_I2C | LOG_UART | LOG_TIMERS | LOG_DMA | LOG_MMU | LOG_IRQS | LOG_UNKNOWN)
-#define VERBOSE (LOG_UART)
+#define VERBOSE (0)
#include "logmacro.h"
diff --git a/src/mame/drivers/cdi.cpp b/src/mame/drivers/cdi.cpp
index 8b05dd51648..2180d42cd8c 100644
--- a/src/mame/drivers/cdi.cpp
+++ b/src/mame/drivers/cdi.cpp
@@ -168,7 +168,6 @@ WRITE8_MEMBER(cdimono2_state::slave_glue_w)
WRITE8_MEMBER(cdimono2_state::controller_tx)
{
logerror("%s: controller_tx: %02x\n", machine().describe_context(), data);
- m_slave->uart_rx(0x55);
}
/*************************
@@ -335,6 +334,15 @@ void cdimono2_state::machine_start()
save_item(NAME(m_portb_data));
save_item(NAME(m_portc_data));
save_item(NAME(m_portd_data));
+ save_item(NAME(m_disdat));
+ save_item(NAME(m_disclk));
+ save_item(NAME(m_disen));
+ save_item(NAME(m_disdata));
+ save_item(NAME(m_disbit));
+ save_item(NAME(m_mouse_buffer));
+ save_item(NAME(m_mouse_idx));
+
+ m_mouse_timer = timer_alloc(0);
}
void cdi_state::machine_reset()
@@ -351,6 +359,14 @@ void cdimono2_state::machine_reset()
m_portb_data = 0x00;
m_portc_data = 0xfc;
m_portd_data = 0x20;
+ m_disdat = 0x00;
+ m_disclk = 0x01;
+ m_disen = 0x00;
+ m_disdata = 0x00;
+ m_disbit = 0x00;
+ m_mouse_idx = 0x00;
+ m_mouse_timer->adjust(attotime::never);
+ m_servo->ss_in(0);
}
void quizard_state::machine_start()
@@ -645,7 +661,7 @@ READ8_MEMBER(cdimono2_state::slave_portb_r)
READ8_MEMBER(cdimono2_state::slave_portc_r)
{
- logerror("%s: slave_portc_r: %02x & %02x\n", machine().describe_context(), m_portc_data, mem_mask);
+ //logerror("%s: slave_portc_r: %02x & %02x\n", machine().describe_context(), m_portc_data, mem_mask);
return (m_portc_data & mem_mask) & 0x7f;
}
@@ -661,6 +677,20 @@ WRITE8_MEMBER(cdimono2_state::slave_porta_w)
m_porta_data = data;
}
+void cdimono2_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+{
+ if (id == 0)
+ {
+ m_slave->uart_rx(m_mouse_buffer[m_mouse_idx]);
+ m_mouse_idx++;
+ if (m_mouse_idx == 6)
+ {
+ m_mouse_idx = 0;
+ m_mouse_timer->adjust(attotime::never);
+ }
+ }
+}
+
WRITE8_MEMBER(cdimono2_state::slave_portb_w)
{
const uint8_t old = m_portb_data;
@@ -670,26 +700,53 @@ WRITE8_MEMBER(cdimono2_state::slave_portb_w)
{
m_maincpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE);
}
+ if (!(old & 0x10) && (data & 0x10))
+ {
+ m_slave->uart_rx(0x55);
+ }
+ else if ((old & 0x10) && !(data & 0x10))
+ {
+ m_mouse_timer->adjust(attotime::from_ticks(10, 9600), 0, attotime::from_ticks(10, 9600));
+ m_mouse_buffer[0] = 0x4d;
+ m_mouse_buffer[1] = 0x20;
+ m_mouse_buffer[2] = 0x41;
+ m_mouse_buffer[3] = 0x22;
+ m_mouse_buffer[4] = 0x43;
+ m_mouse_buffer[5] = 0x24;
+ }
+ m_maincpu->in2_w(1 - BIT(data, 5));
}
WRITE8_MEMBER(cdimono2_state::servo_portb_w)
{
logerror("%s: servo_portb_w: %02x\n", machine().describe_context(), data);
if (BIT(data, 7))
- m_portd_data &= ~0x20;
+ m_slave->ss_in(0);
else
- m_portd_data |= 0x20;
+ m_slave->ss_in(1);
}
WRITE8_MEMBER(cdimono2_state::slave_portc_w)
{
m_portc_data = data | 0x80;
- uint8_t disdat = BIT(data | ~mem_mask, 3);
- uint8_t disclk = BIT(data | ~mem_mask, 4);
- uint8_t disen = BIT(data | ~mem_mask, 5);
- logerror("%s: slave_portc_w: %02x / %02x DISDAT=%u DISCLK=%u DISEN=%u RTSUART=%u\n", machine().describe_context(),
- data, mem_mask, disdat, disclk, disen, BIT(data,6));
+ uint8_t old_clk = m_disclk;
+ m_disdat = BIT(data | ~mem_mask, 3);
+ m_disclk = BIT(data | ~mem_mask, 4);
+ m_disen = 1 - BIT(data | ~mem_mask, 5);
+ //logerror("%s: slave_portc_w: %02x / %02x DISDAT=%u DISCLK=%u DISEN=%u RTSUART=%u\n", machine().describe_context(),
+ //data, mem_mask, m_disdat, m_disclk, m_disen, BIT(data,6));
+ if (!old_clk && m_disclk)
+ {
+ m_disdata |= m_disdat << (7 - m_disbit);
+ m_disbit++;
+ if (m_disbit == 8)
+ {
+ logerror("display data: %02x\n", m_disdata);
+ m_disbit = 0;
+ m_disdata = 0;
+ }
+ }
}
WRITE8_MEMBER(cdimono2_state::slave_portd_w)
diff --git a/src/mame/includes/cdi.h b/src/mame/includes/cdi.h
index f8c40130cc1..2da173f3d7b 100644
--- a/src/mame/includes/cdi.h
+++ b/src/mame/includes/cdi.h
@@ -86,6 +86,7 @@ public:
protected:
virtual void machine_start() override;
virtual void machine_reset() override;
+ virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override;
private:
void cdi910_mem(address_map &map);
@@ -118,6 +119,16 @@ private:
uint8_t m_portb_data;
uint8_t m_portc_data;
uint8_t m_portd_data;
+
+ uint8_t m_disdat;
+ uint8_t m_disclk;
+ uint8_t m_disen;
+ uint8_t m_disdata;
+ uint8_t m_disbit;
+
+ uint8_t m_mouse_buffer[6];
+ uint8_t m_mouse_idx;
+ emu_timer *m_mouse_timer;
};
class quizard_state : public cdi_state