diff --git a/src/devices/machine/68230pit.cpp b/src/devices/machine/68230pit.cpp index ff1fae80be0..6b19873be6a 100644 --- a/src/devices/machine/68230pit.cpp +++ b/src/devices/machine/68230pit.cpp @@ -16,7 +16,7 @@ * * Todo * - Complete support for clock and timers -* - Add interrupt support +* - Complete interrupt support * - Add DMA support * - Add appropriate buffering for each submode **********************************************************************/ @@ -28,6 +28,7 @@ #define LOGPRINT(x) { do { if (VERBOSE) logerror x; } while (0); } #define LOG(x) {} LOGPRINT(x) #define LOGR(x) {} LOGPRINT(x) +#define LOGBIT(x) {} LOGPRINT(x) #define LOGDR(x) {} LOGPRINT(x) #define LOGINT(x) {} LOGPRINT(x) #define LOGSETUP(x) {} LOGPRINT(x) @@ -64,6 +65,8 @@ pit68230_device::pit68230_device(const machine_config &mconfig, device_type type , m_h2_out_cb (*this) , m_h3_out_cb (*this) , m_h4_out_cb (*this) + , m_tirq_out_cb (*this) + , m_pirq_out_cb (*this) , m_pgcr(0) , m_psrr(0) , m_paddr(0) @@ -100,6 +103,8 @@ pit68230_device::pit68230_device(const machine_config &mconfig, const char *tag, , m_h2_out_cb(*this) , m_h3_out_cb(*this) , m_h4_out_cb(*this) + , m_tirq_out_cb (*this) + , m_pirq_out_cb (*this) , m_pgcr(0) , m_psrr(0) , m_paddr(0) @@ -141,6 +146,8 @@ void pit68230_device::device_start () m_h2_out_cb.resolve_safe(); m_h3_out_cb.resolve_safe(); m_h4_out_cb.resolve_safe(); + m_tirq_out_cb.resolve_safe(); + m_pirq_out_cb.resolve_safe(); // Timers pit_timer = timer_alloc(TIMER_ID_PIT); @@ -177,7 +184,7 @@ void pit68230_device::device_reset () m_paddr = 0; m_pbddr = 0; m_pcddr = 0; - m_pivr = 0x0f; + m_pivr = 0x0f; m_pirq_out_cb(CLEAR_LINE); m_pacr = 0; m_h2_out_cb(CLEAR_LINE); m_pbcr = 0; m_h4_out_cb(CLEAR_LINE); m_padr = 0; m_pa_out_cb((offs_t)0, m_padr); @@ -185,23 +192,65 @@ void pit68230_device::device_reset () m_pcdr = 0; m_pc_out_cb((offs_t)0, m_pcdr); m_psr = 0; m_tcr = 0; - m_tivr = 0x0f; + m_tivr = 0x0f; m_tirq_out_cb(CLEAR_LINE); m_tsr = 0; } +/* + * PIACK* provides the Port vector in an iack cycle modified by source H1-H4 + */ +uint8_t pit68230_device::irq_piack() +{ + LOGINT(("%s %s <- %02x\n",tag(), FUNCNAME, m_pivr)); + return m_pivr; +} + +/* + * TIACK* provides the Timer vector in an iack cycle + */ +uint8_t pit68230_device::irq_tiack() +{ + LOGINT(("%s %s <- %02x\n",tag(), FUNCNAME, m_tivr)); + return m_tivr; +} + +/* + * trigger_interrupt - called when a potential interrupt condition occurs + * but will only generate an interrupt when the PIT is programmed to do so. + */ +void pit68230_device::trigger_interrupt(int source) +{ + LOGINT(("%s %s Source: %02x\n",tag(), FUNCNAME, source)); + + if (source == INT_TIMER) + { + // TODO: implement priorities and support nested interrupts + if ( (m_tcr & REG_TCR_TOUT_TIACK_MASK) == REG_TCR_TOUT_TIACK_INT || + (m_tcr & REG_TCR_TOUT_TIACK_MASK) == REG_TCR_TOUT_PC7_INT ) + { + m_tirq_out_cb(ASSERT_LINE); + } + } + else + { + // TODO: implement priorities and support nested interrupts for the H1-H4 sources + m_pirq_out_cb(ASSERT_LINE); + } +} + void pit68230_device::tick_clock() { if (m_tcr & REG_TCR_TIMER_ENABLE) { if (m_cntr-- == 0) // Zero detect { - LOG(("Timer reached zero!\n")); - /* TODO: Check mode and use preload value if required or just rollover 24 bit */ + LOGINT(("Timer reached zero!\n")); if ((m_tcr & REG_TCR_ZD) == 0) m_cntr = m_cpr; else // mask off to 24 bit on rollover m_cntr &= 0xffffff; m_tsr = 1; + trigger_interrupt(INT_TIMER); } } } @@ -217,7 +266,7 @@ void pit68230_device::device_timer (emu_timer &timer, device_timer_id id, int32_ tick_clock(); break; default: - LOGINT(("Unhandled Timer ID %d\n", id)); + LOG(("Unhandled Timer ID %d\n", id)); break; } } @@ -235,7 +284,7 @@ void pit68230_device::portb_setbit(uint8_t bit, uint8_t state) void pit68230_device::pa_update_bit(uint8_t bit, uint8_t state) { - LOG(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state)); + LOGBIT(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state)); // Check if requested bit is an output bit and can't be affected if (m_paddr & (1 << bit)) { @@ -250,7 +299,7 @@ void pit68230_device::pa_update_bit(uint8_t bit, uint8_t state) void pit68230_device::pb_update_bit(uint8_t bit, uint8_t state) { - LOG(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state)); + LOGBIT(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state)); // Check if requested bit is an output bit and can't be affected if (m_pbddr & (1 << bit)) { @@ -266,7 +315,7 @@ void pit68230_device::pb_update_bit(uint8_t bit, uint8_t state) // TODO: Make sure port C is in the right alternate mode void pit68230_device::pc_update_bit(uint8_t bit, uint8_t state) { - LOG(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state)); + LOGBIT(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state)); // Check if requested bit is an output bit and can't be affected if (m_pcddr & (1 << bit)) { @@ -541,19 +590,19 @@ void pit68230_device::wr_pitreg_tcr(uint8_t data) case REG_TCR_PC3_PC7: case REG_TCR_PC3_PC7_DC: LOG(("- PC3 and PC7 used as I/O pins\n")); break; case REG_TCR_TOUT_PC7_SQ: - case REG_TCR_TOUT_PC7_SQ_DC: LOG(("- PC3 used as SQuare wave TOUT and PC7 used as I/O pin - not supported yet\n")); sqr = 1; break; - case REG_TCR_TOUT_TIACK: LOG(("- PC3 used as TOUT and PC7 used as TIACK - not supported yet\n")); tout = 1; tiack = 1; break; - case REG_TCR_TOUT_TIACK_INT: LOG(("- PC3 used as TOUT and PC7 used as TIACK, Interrupts enabled - not supported yet\n")); tout = 1; tiack = 1; irq = 1; break; - case REG_TCR_TOUT_PC7: LOG(("- PC3 used as TOUT and PC7 used as I/O pin - not supported yet\n")); break; - case REG_TCR_TOUT_PC7_INT: LOG(("- PC3 used as TOUT and PC7 used as I/O pin, Interrupts enabled - not supported yet\n")); break; + case REG_TCR_TOUT_PC7_SQ_DC: LOG(("- PC3 used as SQuare wave TOUT and PC7 used as I/O pin - not implemented yet\n")); sqr = 1; break; + case REG_TCR_TOUT_TIACK: LOG(("- PC3 used as TOUT and PC7 used as TIACK - not implemented yet\n")); tout = 1; tiack = 1; break; + case REG_TCR_TOUT_TIACK_INT: LOG(("- PC3 used as TOUT and PC7 used as TIACK, Interrupts enabled\n")); tout = 1; tiack = 1; irq = 1; break; + case REG_TCR_TOUT_PC7: LOG(("- PC3 used as TOUT and PC7 used as I/O pin - not implemented yet\n")); break; + case REG_TCR_TOUT_PC7_INT: LOG(("- PC3 used as TOUT and PC7 used as I/O pin, Interrupts enabled\n")); tout = 1; irq = 1; break; } switch (m_tcr & REG_TCR_CC_MASK) { - case REG_TCR_CC_PC2_CLK_PSC: LOG(("- PC2 used as I/O pin,CLK and x32 prescaler are used\n")); clk = 1; psc = 1; break; - case REG_TCR_CC_TEN_CLK_PSC: LOG(("- PC2 used as Timer enable/disable, CLK and presacaler are used\n")); pen = 1; clk = 1; psc = 1; break; - case REG_TCR_CC_TIN_PSC: LOG(("- PC2 used as Timer clock and the presacaler is used - not supported yet\n")); psc = 1; break; - case REG_TCR_CC_TIN_RAW: LOG(("- PC2 used as Timer clock and the presacaler is NOT used - not supported yet\n")); break; + case REG_TCR_CC_PC2_CLK_PSC: LOG(("- PC2 used as I/O pin,CLK and x32 prescaler are used\n")); clk = 1; psc = 1; break; + case REG_TCR_CC_TEN_CLK_PSC: LOG(("- PC2 used as Timer enable/disable, CLK and presacaler are used - not implemented\n")); pen = 1; clk = 1; psc = 1; break; + case REG_TCR_CC_TIN_PSC: LOG(("- PC2 used as Timer clock and the presacaler is used - not implemented\n")); psc = 1; break; + case REG_TCR_CC_TIN_RAW: LOG(("- PC2 used as Timer clock and the presacaler is NOT used\n")); break; } LOG(("%s", m_tcr & REG_TCR_ZR ? "- Spec violation, should always be 0!\n" : "")); LOG(("- Timer %s when reaching 0 (zero)\n", m_tcr & REG_TCR_ZD ? "rolls over" : "reload the preload values")); @@ -562,7 +611,10 @@ void pit68230_device::wr_pitreg_tcr(uint8_t data) if (m_tcr & REG_TCR_ENABLE) { m_cntr = 0; - if (pen == 1){ LOG(("PC2 enable/disable TBD\n")); } + if (pen == 1) + { + LOG(("PC2 enable/disable TBD\n")); + } if (clk == 1) { int rate = clock() / (psc == 1 ? 32 : 1); @@ -607,7 +659,11 @@ void pit68230_device::wr_pitreg_cprl(uint8_t data) void pit68230_device::wr_pitreg_tsr(uint8_t data) { LOG(("%s(%02x) \"%s\": \n", FUNCNAME, data, tag())); - if (data & 1) m_tsr = 0; // A write resets the TSR; + if (data & 1) + { + m_tsr = 0; // A write resets the TSR; + m_tirq_out_cb(CLEAR_LINE); + } } WRITE8_MEMBER (pit68230_device::write) diff --git a/src/devices/machine/68230pit.h b/src/devices/machine/68230pit.h index 13ad1a63f39..92bfe062b43 100644 --- a/src/devices/machine/68230pit.h +++ b/src/devices/machine/68230pit.h @@ -44,34 +44,40 @@ //************************************************************************** #define MCFG_PIT68230_PA_INPUT_CB(_devcb) \ - devcb = &pit68230_device::set_pa_in_callback (*device, DEVCB_##_devcb); + devcb = &pit68230_device::set_pa_in_callback (*device, DEVCB_##_devcb); #define MCFG_PIT68230_PA_OUTPUT_CB(_devcb) \ - devcb = &pit68230_device::set_pa_out_callback (*device, DEVCB_##_devcb); + devcb = &pit68230_device::set_pa_out_callback (*device, DEVCB_##_devcb); #define MCFG_PIT68230_PB_INPUT_CB(_devcb) \ - devcb = &pit68230_device::set_pb_in_callback (*device, DEVCB_##_devcb); + devcb = &pit68230_device::set_pb_in_callback (*device, DEVCB_##_devcb); #define MCFG_PIT68230_PB_OUTPUT_CB(_devcb) \ - devcb = &pit68230_device::set_pb_out_callback (*device, DEVCB_##_devcb); + devcb = &pit68230_device::set_pb_out_callback (*device, DEVCB_##_devcb); #define MCFG_PIT68230_PC_INPUT_CB(_devcb) \ - devcb = &pit68230_device::set_pc_in_callback (*device, DEVCB_##_devcb); + devcb = &pit68230_device::set_pc_in_callback (*device, DEVCB_##_devcb); #define MCFG_PIT68230_PC_OUTPUT_CB(_devcb) \ - devcb = &pit68230_device::set_pc_out_callback (*device, DEVCB_##_devcb); + devcb = &pit68230_device::set_pc_out_callback (*device, DEVCB_##_devcb); #define MCFG_PIT68230_H1_CB(_devcb) \ - devcb = &pit68230_device::set_h1_out_callback (*device, DEVCB_##_devcb); + devcb = &pit68230_device::set_h1_out_callback (*device, DEVCB_##_devcb); #define MCFG_PIT68230_H2_CB(_devcb) \ - devcb = &pit68230_device::set_h2_out_callback (*device, DEVCB_##_devcb); + devcb = &pit68230_device::set_h2_out_callback (*device, DEVCB_##_devcb); #define MCFG_PIT68230_H3_CB(_devcb) \ - devcb = &pit68230_device::set_h3_out_callback (*device, DEVCB_##_devcb); + devcb = &pit68230_device::set_h3_out_callback (*device, DEVCB_##_devcb); #define MCFG_PIT68230_H4_CB(_devcb) \ - devcb = &pit68230_device::set_h4_out_callback (*device, DEVCB_##_devcb); + devcb = &pit68230_device::set_h4_out_callback (*device, DEVCB_##_devcb); + +#define MCFG_PIT68230_TIMER_IRQ_CB(_devcb) \ + devcb = &pit68230_device::set_tirq_out_callback(*device, DEVCB_##_devcb); + +#define MCFG_PIT68230_PORT_IRQ_CB(_devcb) \ + devcb = &pit68230_device::set_pirq_out_callback(*device, DEVCB_##_devcb); /*----------------------------------------------------------------------- * Registers RS1-RS5 R/W Description @@ -119,13 +125,14 @@ class pit68230_device : public device_t//, public device_execute_interface template static devcb_base &set_h2_out_callback (device_t &device, _Object object){ return downcast(device).m_h2_out_cb.set_callback (object); } template static devcb_base &set_h3_out_callback (device_t &device, _Object object){ return downcast(device).m_h3_out_cb.set_callback (object); } template static devcb_base &set_h4_out_callback (device_t &device, _Object object){ return downcast(device).m_h4_out_cb.set_callback (object); } + template static devcb_base &set_tirq_out_callback (device_t &device, _Object object){ return downcast(device).m_tirq_out_cb.set_callback (object); } + template static devcb_base &set_pirq_out_callback (device_t &device, _Object object){ return downcast(device).m_pirq_out_cb.set_callback (object); } DECLARE_WRITE8_MEMBER (write); DECLARE_READ8_MEMBER (read); void h1_set (uint8_t state); void portb_setbit (uint8_t bit, uint8_t state); - void tick_clock(); // Bit updaters void pa_update_bit(uint8_t bit, uint8_t state); @@ -286,11 +293,18 @@ protected: REG_TCR_TOUT_PC7_INT = 0xe0, // 1 1 1 }; + void tick_clock(); + // device-level overrides virtual void device_start () override; virtual void device_reset () override; virtual void device_timer (emu_timer &timer, device_timer_id id, int param, void *ptr) override; + // Interrupt methods + void trigger_interrupt(int source); + uint8_t irq_tiack(); + uint8_t irq_piack(); + int m_icount; devcb_write8 m_pa_out_cb; @@ -303,8 +317,10 @@ protected: devcb_write_line m_h2_out_cb; devcb_write_line m_h3_out_cb; devcb_write_line m_h4_out_cb; + devcb_write_line m_tirq_out_cb; + devcb_write_line m_pirq_out_cb; - // peripheral ports + // registers uint8_t m_pgcr; // Port General Control register uint8_t m_psrr; // Port Service Request register uint8_t m_paddr; // Port A Data Direction register @@ -323,6 +339,13 @@ protected: int m_cntr; // - The 24 bit Counter uint8_t m_tsr; // Timer Status Register + + // Interrupt sources + enum + { + INT_TIMER + }; + // Timers emu_timer *pit_timer; diff --git a/src/mame/drivers/fccpu30.cpp b/src/mame/drivers/fccpu30.cpp index ffdab965674..1812a500fdb 100644 --- a/src/mame/drivers/fccpu30.cpp +++ b/src/mame/drivers/fccpu30.cpp @@ -699,7 +699,7 @@ static MACHINE_CONFIG_START (cpu30, cpu30_state) MCFG_PIT68230_PB_OUTPUT_CB(WRITE8(cpu30_state, flop_dmac_w)) MCFG_PIT68230_PC_INPUT_CB(READ8(cpu30_state, pit1c_r)) MCFG_PIT68230_PC_OUTPUT_CB(WRITE8(cpu30_state, pit1c_w)) -// MCFG_PIT68230_OUT_INT_CB(DEVWRITELINE("fga002", fga002_device, lirq2_w)) // Interrupts not yet supported by 68230 +// MCFG_PIT68230_TIMER_IRQ_CB(DEVWRITELINE("fga002", fga002_device, lirq2_w)) // The timer interrupt seems to silence the terminal interrupt, needs invectigation MCFG_DEVICE_ADD ("pit2", PIT68230, XTAL_16MHz / 2) // Th PIT clock is not verified on schema but reversed from behaviour MCFG_PIT68230_PB_INPUT_CB(READ8(cpu30_state, board_mem_id_rd)) @@ -707,7 +707,7 @@ static MACHINE_CONFIG_START (cpu30, cpu30_state) MCFG_PIT68230_PA_OUTPUT_CB(WRITE8(cpu30_state, pit2a_w)) MCFG_PIT68230_PC_INPUT_CB(READ8(cpu30_state, pit2c_r)) MCFG_PIT68230_PC_OUTPUT_CB(WRITE8(cpu30_state, pit2c_w)) -// MCFG_PIT68230_OUT_INT_CB(DEVWRITELINE("fga002", fga002_device, lirq3_w)) // Interrupts not yet supported by 68230 +// MCFG_PIT68230_TIMER_IRQ_CB(DEVWRITELINE("fga002", fga002_device, lirq3_w)) // The timer interrupt seems to silence the terminal interrupt, needs invectigation /* FGA-002, Force Gate Array */ MCFG_FGA002_ADD("fga002", 0)