From b20ba46fc75fba844edc442f2af2334faba18bb8 Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Sun, 2 Feb 2020 11:39:25 +0100 Subject: -6840ptm: Added specific logging channels. Added direct output state getter. Set output state to 0 when clearing the output callback. [Ryan Holtz, Phil Bennett] -i8214: Updated logging. Adjusted interrupt level check. Added combined B/SGS setter and bulk R setter. [Ryan Holtz, Phil Bennett] -cmi: Numerous IRQ-related fixes. Nearly all CMIINT tests pass. [Ryan Holtz] --- src/devices/machine/6840ptm.cpp | 63 ++++++---- src/devices/machine/6840ptm.h | 1 + src/devices/machine/i8214.cpp | 65 ++++++++-- src/devices/machine/i8214.h | 2 + src/mame/audio/cmi01a.cpp | 19 +-- src/mame/audio/cmi01a.h | 11 +- src/mame/drivers/cmi.cpp | 262 ++++++++++++++++++++++++++++++---------- 7 files changed, 320 insertions(+), 103 deletions(-) diff --git a/src/devices/machine/6840ptm.cpp b/src/devices/machine/6840ptm.cpp index 02ed1f31912..b271fd7cede 100644 --- a/src/devices/machine/6840ptm.cpp +++ b/src/devices/machine/6840ptm.cpp @@ -38,8 +38,15 @@ #include "emu.h" #include "6840ptm.h" -//#define VERBOSE 1 -//#define LOG_OUTPUT_STREAM std::cout +#define LOG_COUNTERS (1 << 1) +#define LOG_STATUS (1 << 2) +#define LOG_CONTROL (1 << 3) +#define LOG_RESETS (1 << 4) +#define LOG_TIMEOUTS (1 << 5) +#define LOG_IRQS (1 << 6) +#define LOG_ALL (LOG_COUNTERS | LOG_STATUS | LOG_CONTROL | LOG_RESETS | LOG_TIMEOUTS | LOG_IRQS) + +#define VERBOSE (0) #include "logmacro.h" @@ -276,6 +283,11 @@ void ptm6840_device::update_interrupts() ((m_status_reg & TIMER2_IRQ) && (m_control_reg[1] & INTERRUPT_EN)) || ((m_status_reg & TIMER3_IRQ) && (m_control_reg[2] & INTERRUPT_EN)); + LOGMASKED(LOG_IRQS, "%s: IRQ state update: %d, T1:%d, T1E:%d, T2:%d, T2E:%d, T3:%d, T3E:%d\n", machine().describe_context(), new_state, + (m_status_reg & TIMER1_IRQ) ? 1 : 0, (m_control_reg[0] & INTERRUPT_EN) ? 1 : 0, + (m_status_reg & TIMER2_IRQ) ? 1 : 0, (m_control_reg[1] & INTERRUPT_EN) ? 1 : 0, + (m_status_reg & TIMER3_IRQ) ? 1 : 0, (m_control_reg[2] & INTERRUPT_EN) ? 1 : 0); + if (new_state != m_irq) { m_irq = new_state; @@ -306,7 +318,7 @@ uint16_t ptm6840_device::compute_counter( int counter ) const // If there's no timer, return the count if (!m_enabled[counter]) { - LOG("Timer #%d read counter: %d\n", counter + 1, m_counter[counter]); + LOGMASKED(LOG_COUNTERS, "Timer #%d read counter: %d\n", counter + 1, m_counter[counter]); return m_counter[counter]; } @@ -314,7 +326,7 @@ uint16_t ptm6840_device::compute_counter( int counter ) const if (m_control_reg[counter] & INTERNAL_CLK_EN) { clk = static_cast(clock()); - LOG("Timer #%d internal clock freq %f \n", counter + 1, clk); + LOGMASKED(LOG_COUNTERS, "Timer #%d internal clock freq %f \n", counter + 1, clk); } else { @@ -323,7 +335,7 @@ uint16_t ptm6840_device::compute_counter( int counter ) const { clk /= m_t3_divisor; } - LOG("Timer #%d external clock freq %f \n", counter + 1, clk); + LOGMASKED(LOG_COUNTERS, "Timer #%d external clock freq %f \n", counter + 1, clk); } // See how many are left int remaining = (m_timer[counter]->remaining() * clk).as_double(); @@ -336,7 +348,7 @@ uint16_t ptm6840_device::compute_counter( int counter ) const int lsb = remaining % divisor; remaining = (msb << 8) | lsb; } - LOG("Timer #%d read counter: %d\n", counter + 1, remaining); + LOGMASKED(LOG_COUNTERS, "Timer #%d read counter: %d\n", counter + 1, remaining); return remaining; } @@ -361,12 +373,12 @@ void ptm6840_device::reload_count(int idx) if (m_control_reg[idx] & INTERNAL_CLK_EN) { clk = static_cast (clock()); - LOG("Timer #%d internal clock freq %f \n", idx + 1, clk); + LOGMASKED(LOG_COUNTERS, "Timer #%d internal clock freq %f \n", idx + 1, clk); } else { clk = m_external_clock[idx]; - LOG("Timer #%d external clock freq %f \n", idx + 1, clk); + LOGMASKED(LOG_COUNTERS, "Timer #%d external clock freq %f \n", idx + 1, clk); } // Determine the number of clock periods before we expire @@ -393,7 +405,7 @@ void ptm6840_device::reload_count(int idx) } // Set the timer - LOG("Timer #%d reload_count: clock = %f count = %d\n", idx + 1, clk, count); + LOGMASKED(LOG_COUNTERS, "Timer #%d reload_count: clock = %f count = %d\n", idx + 1, clk, count); if (clk == 0.0) { @@ -409,7 +421,7 @@ void ptm6840_device::reload_count(int idx) duration *= m_t3_divisor; } - LOG("Timer #%d reload_count: output = %f\n", idx + 1, duration.as_double()); + LOGMASKED(LOG_COUNTERS, "Timer #%d reload_count: output = %f\n", idx + 1, duration.as_double()); m_enabled[idx] = 1; m_timer[idx]->adjust(duration); @@ -437,7 +449,7 @@ uint8_t ptm6840_device::read(offs_t offset) case PTM_6840_STATUS: { - LOG("%s: Status read = %04X\n", machine().describe_context(), m_status_reg); + LOGMASKED(LOG_STATUS, "%s: Status read = %04X\n", machine().describe_context(), m_status_reg); m_status_read_since_int |= m_status_reg & 0x07; val = m_status_reg; break; @@ -459,7 +471,7 @@ uint8_t ptm6840_device::read(offs_t offset) m_lsb_buffer = result & 0xff; - LOG("%s: Counter %d read = %04X\n", machine().describe_context(), idx + 1, result >> 8); + LOGMASKED(LOG_COUNTERS, "%s: Counter %d read = %04X\n", machine().describe_context(), idx + 1, result >> 8); val = result >> 8; break; } @@ -500,10 +512,10 @@ void ptm6840_device::write(offs_t offset, uint8_t data) m_mode[idx] = (data >> 3) & 0x07; m_control_reg[idx] = data; - LOG("Control register #%d selected\n", idx + 1); - LOG("operation mode = %s\n", opmode[m_mode[idx]]); - LOG("value = %04X\n", m_control_reg[idx]); - LOG("t3divisor = %d\n", m_t3_divisor); + LOGMASKED(LOG_CONTROL, "Control register #%d selected\n", idx + 1); + LOGMASKED(LOG_CONTROL, "operation mode = %s\n", opmode[m_mode[idx]]); + LOGMASKED(LOG_CONTROL, "value = %04X\n", m_control_reg[idx]); + LOGMASKED(LOG_CONTROL, "t3divisor = %d\n", m_t3_divisor); if (diffs & INTERRUPT_EN) update_interrupts(); @@ -512,6 +524,7 @@ void ptm6840_device::write(offs_t offset, uint8_t data) { // Output cleared m_out_cb[idx](0); + m_output[idx] = 0; } // Reset? @@ -520,7 +533,7 @@ void ptm6840_device::write(offs_t offset, uint8_t data) // Holding reset down if (data & RESET_TIMERS) { - LOG("Timer reset\n"); + LOGMASKED(LOG_RESETS, "Timer reset\n"); for (int i = 0; i < 3; i++) { m_timer[i]->enable(false); @@ -555,7 +568,7 @@ void ptm6840_device::write(offs_t offset, uint8_t data) case PTM_6840_MSBBUF2: case PTM_6840_MSBBUF3: { - LOG("msbbuf%d = %02X\n", offset / 2, data); + LOGMASKED(LOG_COUNTERS, "msbbuf%d = %02X\n", offset / 2, data); m_msb_buffer = data; break; } @@ -578,7 +591,7 @@ void ptm6840_device::write(offs_t offset, uint8_t data) reload_count(idx); } - LOG("%s: Counter #%d latch = %04X\n", machine().describe_context(), idx + 1, m_latch[idx]); + LOGMASKED(LOG_COUNTERS, "%s: Counter #%d latch = %04X\n", machine().describe_context(), idx + 1, m_latch[idx]); break; } } @@ -591,7 +604,7 @@ void ptm6840_device::write(offs_t offset, uint8_t data) void ptm6840_device::timeout(int idx) { - LOG("**ptm6840 t%d timeout**\n", idx + 1); + LOGMASKED(LOG_TIMEOUTS, "**ptm6840 t%d timeout**\n", idx + 1); // Set the interrupt flag m_status_reg |= (1 << idx); @@ -616,7 +629,7 @@ void ptm6840_device::timeout(int idx) m_output[idx] = m_output[idx] ^ 1; m_out_cb[idx](m_output[idx]); } - LOG("%6.6f: **ptm6840 t%d output %d **\n", machine().time().as_double(), idx + 1, m_output[idx]); + LOGMASKED(LOG_TIMEOUTS, "%6.6f: **ptm6840 t%d output %d **\n", machine().time().as_double(), idx + 1, m_output[idx]); break; case 4: @@ -624,7 +637,7 @@ void ptm6840_device::timeout(int idx) if (!m_fired[idx]) { m_output[idx] = 1; - LOG("**ptm6840 t%d output %d **\n", idx + 1, m_output[idx]); + LOGMASKED(LOG_TIMEOUTS, "**ptm6840 t%d output %d **\n", idx + 1, m_output[idx]); m_out_cb[idx](m_output[idx]); @@ -679,6 +692,12 @@ void ptm6840_device::set_clock(int idx, int state) } +int ptm6840_device::get_output_state(int counter) +{ + assert(counter < 3); + return m_output[counter]; +} + //------------------------------------------------- // set_ext_clock - set external clock frequency //------------------------------------------------- diff --git a/src/devices/machine/6840ptm.h b/src/devices/machine/6840ptm.h index c1adcbfde13..f1e209f9d4c 100644 --- a/src/devices/machine/6840ptm.h +++ b/src/devices/machine/6840ptm.h @@ -33,6 +33,7 @@ public: auto o3_callback() { return m_out_cb[2].bind(); } auto irq_callback() { return m_irq_cb.bind(); } + int get_output_state(int counter); int status(int clock) const { return m_enabled[clock]; } // get whether timer is enabled int irq_state() const { return m_irq; } // get IRQ state uint16_t count(int counter) const { return compute_counter(counter); } // get counter value diff --git a/src/devices/machine/i8214.cpp b/src/devices/machine/i8214.cpp index f496c758453..eccf8d496bc 100644 --- a/src/devices/machine/i8214.cpp +++ b/src/devices/machine/i8214.cpp @@ -50,22 +50,42 @@ void i8214_device::trigger_interrupt(int level) void i8214_device::check_interrupt() { - if (m_int_dis || !m_etlg || !m_inte) return; + if (m_int_dis) + { + LOG("not checking interrupts because m_int_dis\n"); + return; + } + if (!m_etlg) + { + LOG("not checking interrupts because !m_etlg\n"); + return; + } + if (!m_inte) + { + LOG("not checking interrupts because !m_inte\n"); + return; + } + + LOG("checking interrupts: R:%02x, sgs:%d, current:%d\n", m_r, m_sgs, m_current_status); for (int level = 7; level >= 0; level--) { - if (!BIT(m_r, 7 - level)) + if (!BIT(m_r, level)) { if (m_sgs) { if (level > m_current_status) { + LOG("bit %d unset, level %d > current %d, triggering interrupt\n", 7 - level, level, m_current_status); trigger_interrupt(level); + return; } } else { + LOG("bit %d unset, level %d, triggering interrupt\n", 7 - level, level); trigger_interrupt(level); + return; } } } @@ -128,7 +148,7 @@ uint8_t i8214_device::a_r() { uint8_t a = m_a & 0x07; - LOG("I8214 A: %01x\n", a); + LOG("%s: a_r: %01x\n", machine().describe_context(), a); return a; } @@ -145,6 +165,26 @@ READ8_MEMBER(i8214_device::vector_r) } +//------------------------------------------------- +// b_sgs_w - +//------------------------------------------------- + +void i8214_device::b_sgs_w(uint8_t data) +{ + m_current_status = data & 0x07; + m_sgs = BIT(data, 3); + + LOG("%s: b_sgs_w: b:%d, sgs:%d\n", machine().describe_context(), m_current_status, m_sgs); + + // enable interrupts + m_int_dis = 0; + + // enable next level group + m_write_enlg(1); + + check_interrupt(); +} + //------------------------------------------------- // b_w - //------------------------------------------------- @@ -153,7 +193,7 @@ void i8214_device::b_w(uint8_t data) { m_current_status = data & 0x07; - LOG("I8214 B: %01x\n", m_current_status); + LOG("%s: b_w: %d\n", machine().describe_context(), m_current_status); // enable interrupts m_int_dis = 0; @@ -172,7 +212,7 @@ void i8214_device::b_w(uint8_t data) void i8214_device::r_w(int line, int state) { - LOG("I8214 R%d: %d\n", line, state); + LOG("%s: r_w: line %d, state %d\n", machine().describe_context(), line, state); m_r &= ~(1 << line); m_r |= (state << line); @@ -181,13 +221,22 @@ void i8214_device::r_w(int line, int state) } +void i8214_device::r_all_w(uint8_t state) +{ + LOG("%s: r_all_w: state %02x\n", machine().describe_context(), state); + + m_r = state; + + check_interrupt(); +} + //------------------------------------------------- // sgs_w - //------------------------------------------------- WRITE_LINE_MEMBER( i8214_device::sgs_w ) { - LOG("I8214 SGS: %u\n", state); + LOG("%s: sgs_w: %d\n", machine().describe_context(), state); m_sgs = state; @@ -201,7 +250,7 @@ WRITE_LINE_MEMBER( i8214_device::sgs_w ) WRITE_LINE_MEMBER( i8214_device::etlg_w ) { - LOG("I8214 ETLG: %u\n", state); + LOG("%s: etlg_w: %d\n", machine().describe_context(), state); m_etlg = state; @@ -215,7 +264,7 @@ WRITE_LINE_MEMBER( i8214_device::etlg_w ) WRITE_LINE_MEMBER( i8214_device::inte_w ) { - LOG("I8214 INTE: %u\n", state); + LOG("%s: inte_w: %d\n", machine().describe_context(), state); m_inte = state; diff --git a/src/devices/machine/i8214.h b/src/devices/machine/i8214.h index 6181fe05d81..b1246d0bec9 100644 --- a/src/devices/machine/i8214.h +++ b/src/devices/machine/i8214.h @@ -42,7 +42,9 @@ public: uint8_t a_r(); DECLARE_READ8_MEMBER(vector_r); void b_w(uint8_t data); + void b_sgs_w(uint8_t data); void r_w(int line, int state); + void r_all_w(uint8_t data); protected: // device-level overrides diff --git a/src/mame/audio/cmi01a.cpp b/src/mame/audio/cmi01a.cpp index 0ec40b75a69..2f733ed72f7 100644 --- a/src/mame/audio/cmi01a.cpp +++ b/src/mame/audio/cmi01a.cpp @@ -10,6 +10,9 @@ #include "audio/cmi01a.h" #include "machine/input_merger.h" +#define VERBOSE (0) +#include "logmacro.h" + #define MASTER_OSCILLATOR XTAL(34'291'712) @@ -179,7 +182,7 @@ void cmi01a_device::zx_timer_cb() if (m_zx_flag == 0) { /* Low to high transition - clock flip flop */ - int op = m_ptm_o1; + int op = m_ptm->get_output_state(0); /* Set /ZCINT */ if (op != m_zx_ff) @@ -255,8 +258,6 @@ WRITE_LINE_MEMBER( cmi01a_device::pia_0_cb2_w ) m_ptm->set_g2(1); m_ptm->set_g3(1); - //printf("Stop %d\n", m_channel); - m_zx_timer->adjust(attotime::never); m_active = false; m_zx_flag = 0; // TEST @@ -306,7 +307,7 @@ READ_LINE_MEMBER( cmi01a_device::zx_r ) void cmi01a_device::write(offs_t offset, uint8_t data) { - //printf("C%d W: %02x = %02x\n", m_channel, offset, data); + LOG("%s: channel card %d write: %02x = %02x\n", machine().describe_context(), m_channel, offset, data); switch (offset) { @@ -346,7 +347,7 @@ void cmi01a_device::write(offs_t offset, uint8_t data) { /* PTM addressing is a little funky */ int a0 = offset & 1; - int a1 = (m_ptm_o1 && BIT(offset, 3)) || (!BIT(offset, 3) && BIT(offset, 2)); + int a1 = (m_ptm->get_output_state(0) && BIT(offset, 3)) || (!BIT(offset, 3) && BIT(offset, 2)); int a2 = BIT(offset, 1); //printf("CH%d PTM W: [%x] = %02x\n", m_channel, (a2 << 2) | (a1 << 1) | a0, data); @@ -355,7 +356,7 @@ void cmi01a_device::write(offs_t offset, uint8_t data) } default: - logerror("Unknown channel card write to E0%02X = %02X\n", offset, data); + LOG("%s: Unknown channel card write to E0%02X = %02X\n", machine().describe_context(), offset, data); break; } } @@ -402,7 +403,7 @@ uint8_t cmi01a_device::read(offs_t offset) case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: { int a0 = offset & 1; - int a1 = (m_ptm_o1 && BIT(offset, 3)) || (!BIT(offset, 3) && BIT(offset, 2)); + int a1 = ((m_ptm_o1 && BIT(offset, 3)) || (!BIT(offset, 3) && BIT(offset, 2))) ? 1 : 0; int a2 = BIT(offset, 1); data = m_ptm->read((a2 << 2) | (a1 << 1) | a0); @@ -412,11 +413,11 @@ uint8_t cmi01a_device::read(offs_t offset) } default: - logerror("Unknown channel card read from E0%02X\n", offset); + LOG("%s: Unknown channel card %d read from E0%02X\n", machine().describe_context(), m_channel, offset); break; } - //printf("C%d R: %02x = %02x\n", m_channel, offset, data); + LOG("%s: channel card %d read: %02x = %02x\n", machine().describe_context(), m_channel, offset, data); return data; } diff --git a/src/mame/audio/cmi01a.h b/src/mame/audio/cmi01a.h index a0bfb603418..8989d12728b 100644 --- a/src/mame/audio/cmi01a.h +++ b/src/mame/audio/cmi01a.h @@ -18,6 +18,12 @@ class cmi01a_device : public device_t, public device_sound_interface { public: + cmi01a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock, uint32_t channel) + : cmi01a_device(mconfig, tag, owner, clock) + { + m_channel = channel; + } + cmi01a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); auto irq_callback() { return m_irq_cb.bind(); } @@ -50,9 +56,10 @@ private: void run_voice(); void update_wave_addr(int inc); + uint32_t m_channel; emu_timer * m_zx_timer; - uint8_t m_zx_flag; - uint8_t m_zx_ff; + uint8_t m_zx_flag; + uint8_t m_zx_ff; std::unique_ptr m_wave_ram; uint16_t m_segment_cnt; diff --git a/src/mame/drivers/cmi.cpp b/src/mame/drivers/cmi.cpp index db105420969..5cd780804c0 100644 --- a/src/mame/drivers/cmi.cpp +++ b/src/mame/drivers/cmi.cpp @@ -102,6 +102,8 @@ #include "screen.h" #include "speaker.h" +#define VERBOSE (0) +#include "logmacro.h" #define Q209_CPU_CLOCK 40.21_MHz_XTAL / 40 // divider not verified (very complex circuit) @@ -165,7 +167,7 @@ static const int ch_int_levels[8] = { - 12, 8, 13, 9, 14, 10, 15, 11 //IRQ_CHINT8_LEVEL, IRQ_CHINT7_LEVEL, IRQ_CHINT6_LEVEL, IRQ_CHINT5_LEVEL, IRQ_CHINT4_LEVEL, IRQ_CHINT3_LEVEL, IRQ_CHINT2_LEVEL, IRQ_CHINT1_LEVEL + 12 ^ 7, 8 ^ 7, 13 ^ 7, 9 ^ 7, 14 ^ 7, 10 ^ 7, 15 ^ 7, 11 ^ 7 //IRQ_CHINT8_LEVEL, IRQ_CHINT7_LEVEL, IRQ_CHINT6_LEVEL, IRQ_CHINT5_LEVEL, IRQ_CHINT4_LEVEL, IRQ_CHINT3_LEVEL, IRQ_CHINT2_LEVEL, IRQ_CHINT1_LEVEL }; #define IRQ_PERRINT_LEVEL (0 ^ 7) @@ -196,6 +198,8 @@ public: , m_maincpu2(*this, "maincpu2") , m_midicpu(*this, "smptemidi") , m_cmi07cpu(*this, "cmi07cpu") + , m_maincpu1_irq_merger(*this, "maincpu1_irq_merger") + , m_maincpu2_irq0_merger(*this, "maincpu2_irq0_merger") , m_msm5832(*this, "msm5832") , m_i8214(*this, "i8214_%u", 1U) , m_q133_pia(*this, "q133_pia_%u", 1U) @@ -235,14 +239,19 @@ public: // CPU card DECLARE_WRITE_LINE_MEMBER( q133_acia_irq ); + DECLARE_WRITE_LINE_MEMBER( q133_ptm_irq_w ); DECLARE_WRITE8_MEMBER( i8214_cpu1_w ); DECLARE_WRITE8_MEMBER( i8214_cpu2_w ); + DECLARE_WRITE_LINE_MEMBER( maincpu1_irq_w ); + DECLARE_WRITE_LINE_MEMBER( maincpu2_irq0_w ); DECLARE_WRITE_LINE_MEMBER( i8214_1_int_w ); DECLARE_WRITE_LINE_MEMBER( i8214_2_int_w ); DECLARE_WRITE_LINE_MEMBER( i8214_3_int_w ); DECLARE_WRITE_LINE_MEMBER( i8214_3_enlg ); DECLARE_READ8_MEMBER( shared_ram_r ); DECLARE_WRITE8_MEMBER( shared_ram_w ); + template DECLARE_READ8_MEMBER( perr_r ); + template DECLARE_WRITE8_MEMBER( perr_w ); DECLARE_READ8_MEMBER( q133_1_porta_r ); DECLARE_WRITE8_MEMBER( q133_1_porta_w ); @@ -295,12 +304,15 @@ public: DECLARE_WRITE8_MEMBER( master_tune_w ); DECLARE_WRITE_LINE_MEMBER( cmi02_ptm_irq ); DECLARE_WRITE_LINE_MEMBER( cmi02_ptm_o2 ); + DECLARE_WRITE_LINE_MEMBER( cmi02_pia2_irqa_w ); + DECLARE_READ_LINE_MEMBER( cmi02_pia2_ca1_r ); + DECLARE_WRITE_LINE_MEMBER( cmi02_pia2_cb2_w ); // ??? DECLARE_READ8_MEMBER( cmi07_r ); DECLARE_WRITE8_MEMBER( cmi07_w ); - DECLARE_WRITE_LINE_MEMBER( msm5832_irq ); + DECLARE_WRITE_LINE_MEMBER( msm5832_irq_w ); DECLARE_WRITE_LINE_MEMBER( cmi07_irq ); DECLARE_WRITE_LINE_MEMBER( q133_acia_clock ); @@ -318,6 +330,8 @@ protected: required_device m_midicpu; required_device m_cmi07cpu; + required_device m_maincpu1_irq_merger; + required_device m_maincpu2_irq0_merger; required_device m_msm5832; required_device_array m_i8214; required_device_array m_q133_pia; @@ -378,6 +392,7 @@ private: // Q133 CPU Card uint8_t *m_q133_rom; + uint16_t m_int_state[2]; uint8_t m_hp_int; std::unique_ptr m_shared_ram; std::unique_ptr m_scratch_ram[2]; @@ -386,12 +401,13 @@ private: uint8_t m_map_sel[16]; std::unique_ptr m_map_ram[2]; std::unique_ptr m_q256_ram[2]; + uint8_t m_ram_indices[2][PAGE_COUNT]; uint8_t m_map_ram_latch; + bool m_cpu_irq_state[2]; int m_cpu_active_space[2]; // TODO: Make one register int m_cpu_map_switch[2]; - uint8_t m_irq_address[2][2]; - int m_m6809_bs_hack_cnt; - int m_m6809_bs_hack_cpu; + uint8_t m_irq_address[2][2]; + int m_m6809_bs_hack_cnt[2]; /* Q219 lightpen/graphics card */ std::unique_ptr m_video_ram; @@ -658,9 +674,10 @@ template READ8_MEMBER( cmi_state::irq_ram_r ) if (machine().side_effects_disabled()) return m_scratch_ram[cpunum][0xf8 + offset]; - if (m_m6809_bs_hack_cnt > 0 && m_m6809_bs_hack_cpu == cpunum) + if (m_m6809_bs_hack_cnt[cpunum] > 0) { - m_m6809_bs_hack_cnt--; + m_m6809_bs_hack_cnt[cpunum]--; + LOG("CPU%d IRQ vector byte %d (offset %d): %02x\n", cpunum, 1 - m_m6809_bs_hack_cnt[cpunum], offset, m_irq_address[cpunum][offset]); return m_irq_address[cpunum][offset]; } return m_scratch_ram[cpunum][0xf8 + offset]; @@ -729,13 +746,15 @@ WRITE8_MEMBER( cmi_state::cpufunc_w ) READ8_MEMBER( cmi_state::parity_r ) { - //printf("parity_r %04x\n", offset); - // TODO - return 0xff; + m_maincpu2_irq0_merger->in_w<1>(0); + LOG("%s: parity_r %04x\n", machine().describe_context(), offset); + return 0x00; } WRITE8_MEMBER( cmi_state::mapsel_w ) { + LOG("%s: mapsel_w: %02x = %02x\n", machine().describe_context(), offset, data); + data ^= 0x1f; m_map_sel[offset] = data; @@ -818,23 +837,24 @@ bool cmi_state::map_is_active(int cpunum, int map, uint8_t *map_info) *map_info = m_map_sel[cpunum ? MAPSEL_P2_A : MAPSEL_P1_A]; if ((*map_info & 0x1f) == map) - return 1; + return true; } else { *map_info = m_map_sel[cpunum ? MAPSEL_P2_B : MAPSEL_P1_B]; if ((*map_info & 0x1f) == map) - return 1; + return true; } - return 0; + return false; } void cmi_state::update_address_space(int cpunum, uint8_t mapinfo) { int map = mapinfo & 0x1f; bool vram_en = !BIT(mapinfo, 5); + bool perr_en = BIT(mapinfo, 6); bool periph_en = !BIT(mapinfo, 7); int i; @@ -842,6 +862,18 @@ void cmi_state::update_address_space(int cpunum, uint8_t mapinfo) space->unmap_readwrite(0x0000, 0xffff); + if (perr_en) + { + if (cpunum == CPU_1) + { + space->install_readwrite_handler(0x0000, 0xffff, read8_delegate(*this, FUNC(cmi_state::perr_r)), write8_delegate(*this, FUNC(cmi_state::perr_w))); + } + else + { + space->install_readwrite_handler(0x0000, 0xffff, read8_delegate(*this, FUNC(cmi_state::perr_r)), write8_delegate(*this, FUNC(cmi_state::perr_w))); + } + } + /* Step through the map RAM assignments */ for (int page = 0; page < PAGE_COUNT; ++page) { @@ -862,8 +894,7 @@ void cmi_state::update_address_space(int cpunum, uint8_t mapinfo) { if ((cpunum == 0) || !BIT(m_cmi07_ctrl, 7)) { - if (m_cmi07_ctrl & 0x30) - if ((address & 0xc000) == ((m_cmi07_ctrl & 0x30) << 10)) + if ((m_cmi07_ctrl & 0x30) && (address & 0xc000) == ((m_cmi07_ctrl & 0x30) << 10)) { space->install_ram(address, address + PAGE_SIZE - 1, &m_cmi07_ram[(page * PAGE_SIZE) & 0x3fff]); continue; @@ -880,11 +911,19 @@ void cmi_state::update_address_space(int cpunum, uint8_t mapinfo) continue; /* If peripherals are enabled, don't install RAM here */ - if (periph_en && address >= 0xf000 && address <= 0xffff) // TODO + if (periph_en && address >= 0xf000 && address <= 0xffff) continue; /* Now map the RAM page */ - space->install_ram(address, address + PAGE_SIZE - 1, &m_q256_ram[i][(page_info & 0x7f) * PAGE_SIZE]); + if (perr_en) + { + m_ram_indices[cpunum][page] = (i << 7) | (page_info & 0x7f); + LOG("update_address_space: m_ram_indices[%d][%02x] = %02x\n", cpunum, page, m_ram_indices[cpunum][page]); + } + else + { + space->install_ram(address, address + PAGE_SIZE - 1, &m_q256_ram[i][(page_info & 0x7f) * PAGE_SIZE]); + } } if (vram_en) @@ -917,6 +956,11 @@ READ8_MEMBER( cmi_state::cmi07_r ) return 0xff; } +WRITE_LINE_MEMBER( cmi_state::q133_ptm_irq_w ) +{ + m_maincpu2_irq0_merger->in_w<0>(state); +} + WRITE_LINE_MEMBER( cmi_state::q133_acia_irq ) { set_interrupt(CPU_1, IRQ_ACINT_LEVEL, state ? ASSERT_LINE : CLEAR_LINE); @@ -1146,7 +1190,7 @@ WRITE8_MEMBER( cmi_state::master_tune_w ) WRITE_LINE_MEMBER( cmi_state::cmi02_ptm_irq ) { - //printf("cmi02_ptm_irq: %d\n", state); + LOG("%s: cmi02_ptm_irq: %d\n", machine().describe_context(), state); m_cmi02_ptm_irq = state; set_interrupt(CPU_1, IRQ_TIMINT_LEVEL, m_cmi02_ptm_irq ? ASSERT_LINE : CLEAR_LINE); } @@ -1157,6 +1201,25 @@ WRITE_LINE_MEMBER( cmi_state::cmi02_ptm_o2 ) m_cmi02_ptm->set_c3(state); } +WRITE_LINE_MEMBER( cmi_state::cmi02_pia2_irqa_w ) +{ + LOG("%s: cmi02_pia2_irqa_w: %d\n", machine().describe_context(), state); + set_interrupt(CPU_2, IRQ_ADINT_LEVEL, state ? ASSERT_LINE : CLEAR_LINE); +} + +READ_LINE_MEMBER( cmi_state::cmi02_pia2_ca1_r ) +{ + LOG("%s: cmi02_pia2_ca1_r: %d\n", machine().describe_context(), 0); + return 0; +} + +WRITE_LINE_MEMBER( cmi_state::cmi02_pia2_cb2_w ) +{ + LOG("%s: cmi02_pia2_cb2_w: %d\n", machine().describe_context(), state); + m_cmi02_pia[1]->ca1_w(1); + m_cmi02_pia[1]->ca1_w(0); +} + READ8_MEMBER( cmi_state::cmi02_r ) { if (machine().side_effects_disabled()) @@ -1178,6 +1241,8 @@ READ8_MEMBER( cmi_state::cmi02_r ) } else { + LOG("%s: CMI02 R: %x\n", machine().describe_context(), offset); + switch (offset) { case 0x20: case 0x21: case 0x22: case 0x23: @@ -1200,7 +1265,6 @@ READ8_MEMBER( cmi_state::cmi02_r ) return m_cmi02_ptm->read(offset & 7); default: - logerror("CMI02 R: %x\n", offset); return 0; } } @@ -1220,6 +1284,15 @@ WRITE8_MEMBER( cmi_state::cmi02_w ) } else { + if (offset == 0x30) + { + LOG("%s: CMI02 W: %x %x, clearing IRQ merger bit 1\n", machine().describe_context(), offset, data); + } + else + { + LOG("%s: CMI02 W: %x %x\n", machine().describe_context(), offset, data); + } + switch (offset) { case 0x20: case 0x21: case 0x22: case 0x23: @@ -1231,10 +1304,9 @@ WRITE8_MEMBER( cmi_state::cmi02_w ) break; case 0x30: - m_maincpu1->set_input_line(M6809_IRQ_LINE, CLEAR_LINE); - data ^= 0xff; - m_i8214[2]->sgs_w((data >> 3) & 1); - m_i8214[2]->b_w(data & 0x7); + m_maincpu1_irq_merger->in_w<1>(0); + m_hp_int = 0; + m_i8214[2]->b_sgs_w(~(data & 0xf)); break; case 0x31: case 0x32: @@ -1250,7 +1322,7 @@ WRITE8_MEMBER( cmi_state::cmi02_w ) break; default: - logerror("CMI02 W: %x %x\n", offset, data); + break; } } } @@ -1270,21 +1342,32 @@ void cmi_state::install_video_ram(int cpunum) WRITE8_MEMBER( cmi_state::i8214_cpu1_w ) { - //printf("i8214_cpu1_w: %02x\n", data); - m_maincpu1->set_input_line(M6809_IRQ_LINE, CLEAR_LINE); - data ^= 0xff; - m_i8214[0]->sgs_w((data >> 3) & 1); - m_i8214[0]->b_w(data & 0x7); + LOG("%s: i8214_cpu1_w, clearing IRQ merger bit 0: %02x\n", machine().describe_context(), data); + m_maincpu1_irq_merger->in_w<0>(0); + m_i8214[0]->b_sgs_w(~(data & 0xf)); } WRITE8_MEMBER( cmi_state::i8214_cpu2_w ) { - //printf("i8214_cpu2_w: %02x\n", data); + LOG("%s: i8214_cpu2_w, clearing CPU2 IRQ line: %02x\n", machine().describe_context(), data); m_maincpu2->set_input_line(M6809_IRQ_LINE, CLEAR_LINE); - data ^= 0xff; - m_i8214[1]->sgs_w((data >> 3) & 1); - m_i8214[1]->b_w(data & 0x7); + m_i8214[1]->b_sgs_w(~(data & 0xf)); +} + +template READ8_MEMBER( cmi_state::perr_r ) +{ + m_maincpu2_irq0_merger->in_w<1>(1); + const uint8_t ram_index = m_ram_indices[cpunum][offset / PAGE_SIZE]; + const uint8_t data = m_q256_ram[BIT(ram_index, 7)][(ram_index & 0x7f) * PAGE_SIZE + offset % PAGE_SIZE]; + LOG("%s: perr_r: offset %04x, RAM index %02x, value %02x\n", machine().describe_context(), offset, ram_index, data); + return data; +} + +template WRITE8_MEMBER( cmi_state::perr_w ) +{ + const uint8_t ram_index = m_ram_indices[cpunum][offset / PAGE_SIZE]; + m_q256_ram[BIT(ram_index, 7)][(ram_index & 0x7f) * PAGE_SIZE + offset % PAGE_SIZE] = data; } // TODO: replace with share() @@ -1376,15 +1459,17 @@ IRQ_CALLBACK_MEMBER( cmi_state::cpu1_interrupt_callback ) if (irqline == INPUT_LINE_IRQ0) { + //if (!m_cpu_irq_state[CPU_1]) + //m_maincpu1->set_input_line(M6809_IRQ_LINE, CLEAR_LINE); + int vector = (m_hp_int ? 0xffe0 : 0xffd0); int level = (m_hp_int ? m_i8214[2]->a_r() : m_i8214[0]->a_r()) ^ 7; m_irq_address[CPU_1][0] = m_cpu1space->read_byte(vector + level*2); m_irq_address[CPU_1][1] = m_cpu1space->read_byte(vector + level*2 + 1); - m_m6809_bs_hack_cnt = 2; - m_m6809_bs_hack_cpu = CPU_1; + m_m6809_bs_hack_cnt[CPU_1] = 2; - //printf("cpu1 interrupt, will be pushing address %02x%02x\n", m_irq_address[CPU_1][0], m_irq_address[CPU_1][1]); + LOG("%s: CPU1 interrupt, will be pushing address %02x%02x\n", machine().describe_context(), m_irq_address[CPU_1][0], m_irq_address[CPU_1][1]); } return 0; @@ -1398,12 +1483,14 @@ IRQ_CALLBACK_MEMBER( cmi_state::cpu2_interrupt_callback ) if (irqline == INPUT_LINE_IRQ0) { - int level = m_i8214[1]->a_r() ^ 0x7; + //if (!m_cpu_irq_state[CPU_2]) + //m_maincpu2->set_input_line(M6809_IRQ_LINE, CLEAR_LINE); + + int level = m_i8214[1]->a_r() ^ 7; m_irq_address[CPU_2][0] = m_cpu2space->read_byte(0xffe0 + level*2); m_irq_address[CPU_2][1] = m_cpu2space->read_byte(0xffe0 + level*2 + 1); - m_m6809_bs_hack_cnt = 2; - m_m6809_bs_hack_cpu = CPU_2; + m_m6809_bs_hack_cnt[CPU_2] = 2; //printf("cpu1 interrupt, will be pushing address %02x%02x\n", m_irq_address[CPU_2][0], m_irq_address[CPU_2][1]); } @@ -1412,32 +1499,69 @@ IRQ_CALLBACK_MEMBER( cmi_state::cpu2_interrupt_callback ) void cmi_state::set_interrupt(int cpunum, int level, int state) { - //printf("CPU%d Int: %x State: %x\n", cpunum + 1, level, state); + LOG("%s: CPU%d Int: %x State: %x\n", machine().describe_context(), cpunum + 1, level, state); + + if (state == ASSERT_LINE) + m_int_state[cpunum] |= (1 << level); + else + m_int_state[cpunum] &= ~(1 << level); - i8214_device *i8214 = ((cpunum == CPU_2) ? m_i8214[1] : (level < 8 ? m_i8214[2] : m_i8214[0])); - i8214->r_w(level & 7, state ? 0 : 1); + if (cpunum == 0) + { + if (level < 8) + m_i8214[2]->r_all_w(~(m_int_state[cpunum])); + else + m_i8214[0]->r_all_w(~(m_int_state[cpunum] >> 8)); + } + else + { + m_i8214[1]->r_all_w(~m_int_state[cpunum]); + } + + //i8214_device *i8214 = ((cpunum == CPU_2) ? m_i8214[1] : (level < 8 ? m_i8214[2] : m_i8214[0])); + //i8214->r_w(level & 7, state ? 0 : 1); +} + +WRITE_LINE_MEMBER( cmi_state::maincpu1_irq_w ) +{ + LOG("%s: maincpu1_irq_w: %d\n", machine().describe_context(), state); + //if (state) + m_maincpu1->set_input_line(M6809_IRQ_LINE, state ? ASSERT_LINE : CLEAR_LINE); + //m_cpu_irq_state[CPU_1] = state; +} + +WRITE_LINE_MEMBER( cmi_state::maincpu2_irq0_w ) +{ + LOG("%s: maincpu2_irq0_w: %d\n", machine().describe_context(), state); + set_interrupt(CPU_2, 0 ^ 7, state ? ASSERT_LINE : CLEAR_LINE); } WRITE_LINE_MEMBER( cmi_state::i8214_1_int_w ) { - //printf("i8214_1_int_w: %d\n", state); + LOG("%s: i8214_1_int_w %d%s\n", machine().describe_context(), state, state ? ", setting IRQ merger bit 0" : ""); if (state) - m_maincpu1->set_input_line(M6809_IRQ_LINE, ASSERT_LINE); + { + m_hp_int = 0; + m_maincpu1_irq_merger->in_w<0>(state); + } } WRITE_LINE_MEMBER( cmi_state::i8214_2_int_w ) { - //printf("i8214_2_int_w: %d\n", state); + LOG("%s: i8214_2_int_w: %d\n", machine().describe_context(), state); if (state) m_maincpu2->set_input_line(M6809_IRQ_LINE, ASSERT_LINE); + m_cpu_irq_state[CPU_2] = state; } WRITE_LINE_MEMBER( cmi_state::i8214_3_int_w ) { - //printf("i8214_3_int_w: %d\n", state); - m_hp_int = state; + LOG("%s: i8214_3_int_w %d%s\n", machine().describe_context(), state, state ? ", setting IRQ merger bit 1" : ""); if (state) - m_maincpu1->set_input_line(M6809_IRQ_LINE, ASSERT_LINE); + { + m_hp_int = 1; + m_maincpu1_irq_merger->in_w<1>(state); + } } @@ -1512,11 +1636,9 @@ WRITE_LINE_MEMBER( cmi_state::q133_acia_clock ) acia->write_rxc(state); } -WRITE_LINE_MEMBER( cmi_state::msm5832_irq ) +WRITE_LINE_MEMBER( cmi_state::msm5832_irq_w ) { -#if 0 set_interrupt(CPU_2, IRQ_RTCINT_LEVEL, state ? ASSERT_LINE : CLEAR_LINE); -#endif } WRITE_LINE_MEMBER( cmi_state::cmi07_irq ) @@ -1531,6 +1653,9 @@ void cmi_state::machine_reset() m_qfc9_region_ptr = (uint8_t *)m_qfc9_region->base(); + m_int_state[0] = 0; + m_int_state[1] = 0; + /* Set 8214 interrupt lines */ m_i8214[0]->etlg_w(1); m_i8214[0]->inte_w(1); @@ -1564,8 +1689,10 @@ void cmi_state::machine_reset() m_cmi07cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); m_cmi02_ptm_irq = 0; - m_m6809_bs_hack_cnt = 0; - m_m6809_bs_hack_cpu = 0; + m_m6809_bs_hack_cnt[0] = 0; + m_m6809_bs_hack_cnt[1] = 0; + + memset(m_map_sel, 0, 16); } void cmi_state::machine_start() @@ -1656,15 +1783,23 @@ void cmi_state::cmi2x(machine_config &config) m_i8214[2]->int_wr_callback().set(FUNC(cmi_state::i8214_3_int_w)); m_i8214[2]->enlg_wr_callback().set(FUNC(cmi_state::i8214_3_enlg)); + INPUT_MERGER_ANY_HIGH(config, m_maincpu1_irq_merger).output_handler().set(FUNC(cmi_state::maincpu1_irq_w)); + INPUT_MERGER_ANY_HIGH(config, m_maincpu2_irq0_merger).output_handler().set(FUNC(cmi_state::maincpu2_irq0_w)); + PIA6821(config, m_q133_pia[0]); // pia_q133_1_config m_q133_pia[0]->readpa_handler().set(FUNC(cmi_state::q133_1_porta_r)); m_q133_pia[0]->writepa_handler().set(FUNC(cmi_state::q133_1_porta_w)); m_q133_pia[0]->writepb_handler().set(FUNC(cmi_state::q133_1_portb_w)); + m_q133_pia[0]->irqa_handler().set("rtc_irq_merger", FUNC(input_merger_device::in_w<0>)); + m_q133_pia[0]->irqb_handler().set("rtc_irq_merger", FUNC(input_merger_device::in_w<1>)); + + INPUT_MERGER_ANY_HIGH(config, "rtc_irq_merger").output_handler().set(FUNC(cmi_state::msm5832_irq_w)); PIA6821(config, m_q133_pia[1]); // pia_q133_2_config PTM6840(config, m_q133_ptm, 2000000); // ptm_q133_config m_q133_ptm->set_external_clocks(1024, 1, 111); // Third is todo + m_q133_ptm->irq_callback().set(FUNC(cmi_state::q133_ptm_irq_w)); PIA6821(config, m_q219_pia); // pia_q219_config m_q219_pia->readpb_handler().set(FUNC(cmi_state::pia_q219_b_r)); @@ -1681,8 +1816,11 @@ void cmi_state::cmi2x(machine_config &config) m_cmi02_pia[0]->writepb_handler().set(FUNC(cmi_state::master_tune_w)); PIA6821(config, m_cmi02_pia[1]); // pia_cmi02_2_config + m_cmi02_pia[1]->irqa_handler().set(FUNC(cmi_state::cmi02_pia2_irqa_w)); + m_cmi02_pia[1]->readca1_handler().set(FUNC(cmi_state::cmi02_pia2_ca1_r)); + m_cmi02_pia[1]->cb2_handler().set(FUNC(cmi_state::cmi02_pia2_cb2_w)); - PTM6840(config, m_cmi02_ptm, 2000000); // ptm_cmi02_config TODO + PTM6840(config, m_cmi02_ptm, 2000000); // ptm_cmi02_config m_cmi02_ptm->o2_callback().set(FUNC(cmi_state::cmi02_ptm_o2)); m_cmi02_ptm->irq_callback().set(FUNC(cmi_state::cmi02_ptm_irq)); @@ -1725,28 +1863,28 @@ void cmi_state::cmi2x(machine_config &config) SPEAKER(config, "mono").front_center(); // Channel cards - cmi01a_device &cmi01a_0(CMI01A_CHANNEL_CARD(config, "cmi01a_0", 0)); + cmi01a_device &cmi01a_0(CMI01A_CHANNEL_CARD(config, "cmi01a_0", 0, 0)); cmi01a_0.add_route(ALL_OUTPUTS, "mono", 0.25); cmi01a_0.irq_callback().set(FUNC(cmi_state::channel_irq<0>)); - cmi01a_device &cmi01a_1(CMI01A_CHANNEL_CARD(config, "cmi01a_1", 0)); + cmi01a_device &cmi01a_1(CMI01A_CHANNEL_CARD(config, "cmi01a_1", 0, 1)); cmi01a_1.add_route(ALL_OUTPUTS, "mono", 0.25); cmi01a_1.irq_callback().set(FUNC(cmi_state::channel_irq<1>)); - cmi01a_device &cmi01a_2(CMI01A_CHANNEL_CARD(config, "cmi01a_2", 0)); + cmi01a_device &cmi01a_2(CMI01A_CHANNEL_CARD(config, "cmi01a_2", 0, 2)); cmi01a_2.add_route(ALL_OUTPUTS, "mono", 0.25); cmi01a_2.irq_callback().set(FUNC(cmi_state::channel_irq<2>)); - cmi01a_device &cmi01a_3(CMI01A_CHANNEL_CARD(config, "cmi01a_3", 0)); + cmi01a_device &cmi01a_3(CMI01A_CHANNEL_CARD(config, "cmi01a_3", 0, 3)); cmi01a_3.add_route(ALL_OUTPUTS, "mono", 0.25); cmi01a_3.irq_callback().set(FUNC(cmi_state::channel_irq<3>)); - cmi01a_device &cmi01a_4(CMI01A_CHANNEL_CARD(config, "cmi01a_4", 0)); + cmi01a_device &cmi01a_4(CMI01A_CHANNEL_CARD(config, "cmi01a_4", 0, 4)); cmi01a_4.add_route(ALL_OUTPUTS, "mono", 0.25); cmi01a_4.irq_callback().set(FUNC(cmi_state::channel_irq<4>)); - cmi01a_device &cmi01a_5(CMI01A_CHANNEL_CARD(config, "cmi01a_5", 0)); + cmi01a_device &cmi01a_5(CMI01A_CHANNEL_CARD(config, "cmi01a_5", 0, 5)); cmi01a_5.add_route(ALL_OUTPUTS, "mono", 0.25); cmi01a_5.irq_callback().set(FUNC(cmi_state::channel_irq<5>)); - cmi01a_device &cmi01a_6(CMI01A_CHANNEL_CARD(config, "cmi01a_6", 0)); + cmi01a_device &cmi01a_6(CMI01A_CHANNEL_CARD(config, "cmi01a_6", 0, 6)); cmi01a_6.add_route(ALL_OUTPUTS, "mono", 0.25); cmi01a_6.irq_callback().set(FUNC(cmi_state::channel_irq<6>)); - cmi01a_device &cmi01a_7(CMI01A_CHANNEL_CARD(config, "cmi01a_7", 0)); + cmi01a_device &cmi01a_7(CMI01A_CHANNEL_CARD(config, "cmi01a_7", 0, 7)); cmi01a_7.add_route(ALL_OUTPUTS, "mono", 0.25); cmi01a_7.irq_callback().set(FUNC(cmi_state::channel_irq<7>)); } -- cgit v1.2.3