diff options
author | MooglyGuy <therealmogminer@gmail.com> | 2019-12-26 19:03:37 +0100 |
---|---|---|
committer | MooglyGuy <therealmogminer@gmail.com> | 2019-12-26 19:03:37 +0100 |
commit | dee55a8f5a05877e65cdc59d54a9325c93a612c9 (patch) | |
tree | f4ce6b2a6856118cdb0fd3a37b6c125045337133 | |
parent | 33b51348633f0016a6afaababd3db016a7d7f73e (diff) |
-cdimono2: Improved SPI emulation in the 68hc05 core, better hookup of /SS lines, nw
-rw-r--r-- | src/devices/cpu/m6805/m68hc05.cpp | 78 | ||||
-rw-r--r-- | src/devices/cpu/m6805/m68hc05.h | 4 | ||||
-rw-r--r-- | src/devices/machine/scc68070.cpp | 2 | ||||
-rw-r--r-- | src/mame/drivers/cdi.cpp | 75 | ||||
-rw-r--r-- | src/mame/includes/cdi.h | 11 |
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 |