diff --git a/src/devices/bus/epson_sio/pf10.cpp b/src/devices/bus/epson_sio/pf10.cpp index d41b247ba53..418971e47d1 100644 --- a/src/devices/bus/epson_sio/pf10.cpp +++ b/src/devices/bus/epson_sio/pf10.cpp @@ -118,7 +118,7 @@ void epson_pf10_device::device_start() void epson_pf10_device::device_reset() { - m_timer->adjust(attotime::zero, 0, attotime::from_hz(38400 * 8)); + m_timer->adjust(attotime::zero, 0, attotime::from_hz(38400 * 16)); } //------------------------------------------------- diff --git a/src/devices/cpu/m6800/m6801.cpp b/src/devices/cpu/m6800/m6801.cpp index de9cae8e9fd..fecf48c0cd3 100644 --- a/src/devices/cpu/m6800/m6801.cpp +++ b/src/devices/cpu/m6800/m6801.cpp @@ -82,6 +82,7 @@ enum #define TAKE_OCI enter_interrupt("take OCI\n",0xfff4) #define TAKE_TOI enter_interrupt("take TOI\n",0xfff2) #define TAKE_SCI enter_interrupt("take SCI\n",0xfff0) +#define TAKE_CMI enter_interrupt("take CMI\n",0xffec) /* mnemonics for the Timer Control and Status Register bits */ #define TCSR_OLVL 0x01 @@ -276,9 +277,9 @@ void hd6301x_cpu_device::hd6301x_io(address_map &map) map(0x0018, 0x0018).rw(FUNC(hd6301x_cpu_device::p7_data_r), FUNC(hd6301x_cpu_device::p7_data_w)); // TODO: external except in single-chip mode map(0x0019, 0x0019).rw(FUNC(hd6301x_cpu_device::ocr2h_r), FUNC(hd6301x_cpu_device::ocr2h_w)); map(0x001a, 0x001a).rw(FUNC(hd6301x_cpu_device::ocr2l_r), FUNC(hd6301x_cpu_device::ocr2l_w)); - //map(0x001b, 0x001b).rw(FUNC(hd6301x_cpu_device::tcsr3_r), FUNC(hd6301x_cpu_device::tcsr3_w)); - //map(0x001c, 0x001c).rw(FUNC(hd6301x_cpu_device::ff_r), FUNC(hd6301x_cpu_device::tconr_w)); - //map(0x001d, 0x001d).rw(FUNC(hd6301x_cpu_device::t2cnt_r), FUNC(hd6301x_cpu_device::t2cnt_w)); + map(0x001b, 0x001b).rw(FUNC(hd6301x_cpu_device::tcsr3_r), FUNC(hd6301x_cpu_device::tcsr3_w)); + map(0x001c, 0x001c).rw(FUNC(hd6301x_cpu_device::ff_r), FUNC(hd6301x_cpu_device::tconr_w)); + map(0x001d, 0x001d).rw(FUNC(hd6301x_cpu_device::t2cnt_r), FUNC(hd6301x_cpu_device::t2cnt_w)); //map(0x001f, 0x001f).rw(FUNC(hd6301x_cpu_device::tstreg_r), FUNC(hd6301x_cpu_device::tstreg_w)); } @@ -318,6 +319,7 @@ m6801_cpu_device::m6801_cpu_device(const machine_config &mconfig, device_type ty , m_out_port_func(*this) , m_out_sc2_func(*this) , m_out_sertx_func(*this) + , m_sclk_divider(8) { } @@ -356,6 +358,7 @@ hd6301x_cpu_device::hd6301x_cpu_device(const machine_config &mconfig, device_typ , m_in_portx_func(*this) , m_out_portx_func(*this) { + m_sclk_divider = 16; } hd6301x0_cpu_device::hd6301x0_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) @@ -433,6 +436,10 @@ void hd6301x_cpu_device::m6800_check_irq2() { TAKE_TOI; } + else if ((m_tcsr3 & 0xc0) == 0xc0) + { + TAKE_CMI; + } else if (((m_trcsr & (M6801_TRCSR_RIE|M6801_TRCSR_RDRF)) == (M6801_TRCSR_RIE|M6801_TRCSR_RDRF)) || ((m_trcsr & (M6801_TRCSR_RIE|M6801_TRCSR_ORFE)) == (M6801_TRCSR_RIE|M6801_TRCSR_ORFE)) || ((m_trcsr & (M6801_TRCSR_TIE|M6801_TRCSR_TDRE)) == (M6801_TRCSR_TIE|M6801_TRCSR_TDRE))) @@ -572,7 +579,7 @@ void hd6301x_cpu_device::check_timer_event() modified_tcsr(); } - if (m_irq2 & (TCSR_OCF | TCSR_TOF)) + if ((m_irq2 & (TCSR_OCF | TCSR_TOF)) || (m_tcsr3 & 0xc0) == 0xc0) { if (m_wai_state & M6800_SLP) m_wai_state &= ~M6800_SLP; @@ -591,6 +598,40 @@ void m6801_cpu_device::increment_counter(int amount) check_timer_event(); } +void hd6301x_cpu_device::increment_counter(int amount) +{ + m6800_cpu_device::increment_counter(amount); + if (m_t2cnt_written) + m_t2cnt_written = false; + else if (BIT(m_tcsr3, 4)) + { + switch (m_tcsr3 & 0x03) + { + case 0x00: + // Timer 2 input = E clock + increment_t2cnt(amount); + break; + + case 0x01: + // Timer 2 input = E clock/8 + increment_t2cnt((amount + (CTD & 0x0007)) >> 3); + break; + + case 0x02: + // Timer 2 input = E clock/128 + increment_t2cnt((amount + (CTD & 0x007f)) >> 7); + break; + + case 0x03: + // Timer 2 input = external Tclk + break; + } + } + CTD += amount; + if (CTD >= m_timer_next || (m_tcsr3 & 0xc0) == 0xc0) + check_timer_event(); +} + void m6801_cpu_device::EAT_CYCLES() { int cycles_to_eat = std::min(int(m_timer_next - CTD), m_icount); @@ -648,6 +689,44 @@ void m6801_cpu_device::set_rmcr(uint8_t data) } } +void hd6301x_cpu_device::set_rmcr(uint8_t data) +{ + if (m_rmcr == data) return; + + m_rmcr = data; + + switch ((m_rmcr & 0x1c) >> 2) + { + case 0: // TODO: clock sync + case 3: + case 7: // external clock + LOGSER("SCI: Using external serial clock: true\n"); + m_use_ext_serclock = true; + m_sci_timer->enable(false); + break; + + case 1: + case 2: + case 4: // TODO: clock sync + case 5: + case 6: + if (BIT(m_rmcr, 5)) + { + LOGSER("SCI: Using Timer 2 clock\n"); + m_sci_timer->enable(false); + } + else + { + int divisor = M6801_RMCR_SS[m_rmcr & M6801_RMCR_SS_MASK]; + attotime period = cycles_to_attotime(divisor); + LOGSER("SCI: Setting serial rate, Divisor: %d Hz: %d\n", divisor, period.as_hz()); + m_sci_timer->adjust(period, 0, period); + } + m_use_ext_serclock = false; + break; + } +} + int m6801_cpu_device::m6800_rx() { return (m_in_port_func[1]() & M6801_PORT2_IO3) >> 3; @@ -991,6 +1070,12 @@ void hd6301x_cpu_device::device_start() save_item(NAME(m_tcsr2)); save_item(NAME(m_pending_tcsr2)); save_item(NAME(m_output_compare2.d)); + + save_item(NAME(m_t2cnt)); + save_item(NAME(m_tconr)); + save_item(NAME(m_tcsr3)); + save_item(NAME(m_tout3)); + save_item(NAME(m_t2cnt_written)); } void m6801_cpu_device::device_reset() @@ -1043,6 +1128,12 @@ void hd6301x_cpu_device::device_reset() m_tcsr2 = 0x00; m_pending_tcsr2 = 0x00; OC2D = 0xffff; + + m_t2cnt = 0x00; + m_tconr = 0xff; + m_tcsr3 = 0x00; + m_tout3 = false; + m_t2cnt_written = false; } @@ -1086,6 +1177,11 @@ void hd6301x_cpu_device::write_port2() data = (data & 0xef) | (m_tx << 4); ddr |= 0x10; } + if ((m_tcsr3 & 0x0c) != 0) + { + data = (data & 0xbf) | (m_tout3 << 6); + ddr |= 0x40; + } m_out_port_func[1](0, data, ddr); } @@ -1540,6 +1636,93 @@ void hd6301x_cpu_device::ocr2l_w(uint8_t data) } +void hd6301x_cpu_device::increment_t2cnt(int amount) +{ + if (amount > uint8_t(m_tconr - m_t2cnt)) + { + if (m_t2cnt > m_tconr) + { + amount -= 256 - m_t2cnt; + m_t2cnt = 0; + } + m_t2cnt = (m_t2cnt + amount) % (m_tconr + 1); + + if (BIT(m_tcsr3, 3)) + { + if (m_tout3 != BIT(m_tcsr3, 2)) + { + m_tout3 = BIT(m_tcsr3, 2); + m_port2_written = true; + write_port2(); + } + } + else if (BIT(m_tcsr3, 2)) + { + m_tout3 = !m_tout3; + m_port2_written = true; + write_port2(); + } + + if (BIT(m_rmcr, 5) && !m_use_ext_serclock) + { + if (m_ext_serclock + amount >= 32) + { + m_ext_serclock = (m_ext_serclock + amount) % 32; + serial_transmit(); + serial_receive(); + } + else + m_ext_serclock += amount; + } + + m_tcsr3 |= 0x80; + m_timer_next = 0; // HACK + } + else + m_t2cnt += amount; +} + +uint8_t hd6301x_cpu_device::t2cnt_r() +{ + return m_t2cnt; +} + +void hd6301x_cpu_device::t2cnt_w(uint8_t data) +{ + m_t2cnt = data; + m_t2cnt_written = true; +} + +void hd6301x_cpu_device::tconr_w(uint8_t data) +{ + m_tconr = data; +} + +uint8_t hd6301x_cpu_device::tcsr3_r() +{ + return m_tcsr3; +} + +void hd6301x_cpu_device::tcsr3_w(uint8_t data) +{ + uint8_t tout3_last_enable = (m_tcsr3 & 0x0c) != 0; + + // Bit 5 does not exist and Bit 7 can only be written with 0 + m_tcsr3 = data & (0x5f | (m_tcsr3 & 0x80)); + + if (m_tout3 && !BIT(data, 4)) + { + m_tout3 = false; + write_port2(); + } + else if (tout3_last_enable ? (data & 0x0c) == 0 : (data & 0x0c) != 0) + { + m_port2_written = true; + write_port2(); + } +} + + uint8_t m6801_cpu_device::sci_rmcr_r() { return m_rmcr; @@ -1655,7 +1838,7 @@ void m6801_cpu_device::m6801_clock_serial() { m_ext_serclock++; - if (m_ext_serclock >= 8) + if (m_ext_serclock >= m_sclk_divider) { m_ext_serclock = 0; serial_transmit(); diff --git a/src/devices/cpu/m6800/m6801.h b/src/devices/cpu/m6800/m6801.h index 27e88dcb2c8..c88d0f3ba1c 100644 --- a/src/devices/cpu/m6800/m6801.h +++ b/src/devices/cpu/m6800/m6801.h @@ -124,6 +124,8 @@ protected: devcb_write_line m_out_sc2_func; devcb_write_line m_out_sertx_func; + int m_sclk_divider; + /* internal registers */ uint8_t m_port_ddr[4]; uint8_t m_port_data[4]; @@ -167,7 +169,7 @@ protected: virtual void set_timer_event(); virtual void modified_counters(); virtual void check_timer_event(); - void set_rmcr(uint8_t data); + virtual void set_rmcr(uint8_t data); virtual void write_port2(); int m6800_rx(); void serial_transmit(); @@ -281,12 +283,21 @@ protected: uint8_t ocr2l_r(); void ocr2l_w(uint8_t data); + void increment_t2cnt(int amount); + uint8_t t2cnt_r(); + void t2cnt_w(uint8_t data); + void tconr_w(uint8_t data); + uint8_t tcsr3_r(); + void tcsr3_w(uint8_t data); + virtual void m6800_check_irq2() override; virtual void modified_tcsr() override; virtual void set_timer_event() override; virtual void modified_counters() override; + virtual void increment_counter(int amount) override; virtual void check_timer_event() override; virtual void CLEANUP_COUNTERS() override; + virtual void set_rmcr(uint8_t data) override; devcb_read8::array<2> m_in_portx_func; devcb_write8::array<3> m_out_portx_func; @@ -297,6 +308,12 @@ protected: uint8_t m_tcsr2; uint8_t m_pending_tcsr2; PAIR m_output_compare2; + + uint8_t m_t2cnt; + uint8_t m_tconr; + uint8_t m_tcsr3; + bool m_tout3; + bool m_t2cnt_written; }; diff --git a/src/mame/drivers/novag_snova.cpp b/src/mame/drivers/novag_snova.cpp index 43402b9ff1e..d8f248ae5ff 100644 --- a/src/mame/drivers/novag_snova.cpp +++ b/src/mame/drivers/novag_snova.cpp @@ -7,7 +7,6 @@ Novag Super Nova & related chess computers. I believe the series started with Primo. The chess engine is by David Kittinger. TODO: -- remove timer hack for supremo (missing extra timer emulation in MCU core) - NMI on power-off switch, it sets 0x14 bit 7 for standby power (see below) - add nvram, MCU is missing standby power emulation - beeps are glitchy, as if interrupted for too long @@ -324,10 +323,6 @@ void snova_state::supremo(machine_config &config) m_maincpu->set_clock(8_MHz_XTAL); m_maincpu->set_addrmap(AS_PROGRAM, &snova_state::supremo_map); - // THIS IS A HACK, vector @ 0xffec, use ROM_COPY - const attotime irq_period = attotime::from_ticks(4 * 128 * 11, 8_MHz_XTAL); - m_maincpu->set_periodic_int(FUNC(snova_state::irq0_line_hold), irq_period); - config.set_default_layout(layout_novag_supremo); config.device_remove("rs232"); @@ -351,8 +346,6 @@ ROM_START( supremo ) ROM_REGION( 0x10000, "maincpu", 0 ) ROM_LOAD("sp_a10.u5", 0x8000, 0x8000, CRC(1db63786) SHA1(4f24452ed8955b31ba88f68cc95c357660930aa4) ) - ROM_COPY("maincpu", 0xffec, 0xfff8, 2) // HACK - ROM_REGION( 50926, "screen", 0 ) ROM_LOAD("nsnova.svg", 0, 50926, CRC(5ffa1b53) SHA1(8b1f862bfdf0be837a4e8dc94fea592d6ffff629) ) ROM_END diff --git a/src/mame/drivers/ymtx81z.cpp b/src/mame/drivers/ymtx81z.cpp index fbc4f6b94e1..68c367f23cc 100644 --- a/src/mame/drivers/ymtx81z.cpp +++ b/src/mame/drivers/ymtx81z.cpp @@ -41,7 +41,7 @@ private: u8 p2_r(); WRITE_LINE_MEMBER(midi_rx_r) { m_rx_data = state; } - WRITE_LINE_MEMBER(midiclock_w) { if (state == ASSERT_LINE) m_maincpu->m6801_clock_serial();} + WRITE_LINE_MEMBER(midiclock_w) { if (state) m_maincpu->m6801_clock_serial(); } required_device m_maincpu; required_ioport m_port2; @@ -130,7 +130,7 @@ void ymtx81z_state::tx81z(machine_config &config) NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0); // TC5564PL-15/-20 + CR2032 battery - auto &midiclock(CLOCK(config, "midiclock", 500_kHz_XTAL / 2)); // divider not verified + auto &midiclock(CLOCK(config, "midiclock", 500_kHz_XTAL)); midiclock.signal_handler().set(FUNC(ymtx81z_state::midiclock_w)); MIDI_PORT(config, "mdin", midiin_slot, "midiin").rxd_handler().set(FUNC(ymtx81z_state::midi_rx_r));