diff --git a/src/devices/machine/68230pit.cpp b/src/devices/machine/68230pit.cpp index 9e66dcb10b5..ed14aca4910 100644 --- a/src/devices/machine/68230pit.cpp +++ b/src/devices/machine/68230pit.cpp @@ -20,7 +20,7 @@ * - Complete support for clock and timers * - Add interrupt support * - Add DMA support -* - Add double buffering for each submode +* - Add appropriate buffering for each submode **********************************************************************/ #include "68230pit.h" @@ -30,6 +30,7 @@ #define LOGPRINT(x) { do { if (VERBOSE) logerror x; } while (0); } #define LOG(x) {} LOGPRINT(x) #define LOGR(x) {} LOGPRINT(x) +#define LOGDR(x) {} LOGPRINT(x) #define LOGINT(x) {} LOGPRINT(x) #define LOGSETUP(x) {} LOGPRINT(x) #if VERBOSE > 1 @@ -137,7 +138,7 @@ void pit68230_device::device_start () m_pb_out_cb.resolve_safe(); m_pb_in_cb.resolve_safe(0); m_pc_out_cb.resolve_safe(); - m_pc_in_cb.resolve_safe(0); + m_pc_in_cb.resolve(); // A temporary way to check if handler is installed with isnull(). TODO: Need better fix. m_h1_out_cb.resolve_safe(); m_h2_out_cb.resolve_safe(); m_h3_out_cb.resolve_safe(); @@ -179,16 +180,34 @@ void pit68230_device::device_reset () m_pbddr = 0; m_pcddr = 0; m_pivr = 0x0f; - m_pacr = 0; m_h2_out_cb(m_pacr); - m_pbcr = 0; + 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); m_pbdr = 0; m_pb_out_cb((offs_t)0, m_pbdr); + m_pcdr = 0; m_pc_out_cb((offs_t)0, m_pcdr); m_psr = 0; m_tcr = 0; m_tivr = 0x0f; m_tsr = 0; } +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 */ + 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; + } + } +} + //------------------------------------------------- // device_timer - handler timer events //------------------------------------------------- @@ -197,14 +216,7 @@ void pit68230_device::device_timer (emu_timer &timer, device_timer_id id, int32_ switch(id) { case TIMER_ID_PIT: - if (m_cntr-- == 0) // Zero detect - { - /* TODO: Check mode and use preload value if required or just rollover 24 bit */ - if ((m_tcr & REG_TCR_ZD) == 0) - m_cntr = m_cpr; - else // mask off to 24 bit on rollover - m_cntr &= 0xffffff; - } + tick_clock(); break; default: LOGINT(("Unhandled Timer ID %d\n", id)); @@ -214,16 +226,29 @@ void pit68230_device::device_timer (emu_timer &timer, device_timer_id id, int32_ void pit68230_device::h1_set (uint8_t state) { - LOG(("%s %s %d @ m_psr %2x => ",tag(), FUNCNAME, state, m_psr)); if (state) m_psr |= 1; else m_psr &= ~1; - LOG(("%02x %lld\n", m_psr, machine ().firstcpu->total_cycles ())); } -void pit68230_device::portb_setbit (uint8_t bit, uint8_t state) +void pit68230_device::portb_setbit(uint8_t bit, uint8_t state) { - LOG(("%s %s %d/%d @ m_pbdr %2x => ", tag(), FUNCNAME, bit, state, m_pbdr)); if (state) m_pbdr |= (1 << bit); else m_pbdr &= ~(1 << bit); - LOG(("%02x %lld\n", m_pbdr, machine ().firstcpu->total_cycles ())); +} + +// Bit updaters will make it possible to move registers to private data +// TODO: Make sure to only update input bits and that the port is in the right alternate mode +void pit68230_device::pa_update_bit(uint8_t bit, uint8_t state){ if (state) m_padr |= (1 << bit); else m_padr &= ~(1 << bit); } +void pit68230_device::pb_update_bit(uint8_t bit, uint8_t state){ if (state) m_pbdr |= (1 << bit); else m_pbdr &= ~(1 << bit); } +void pit68230_device::pc_update_bit(uint8_t bit, uint8_t state){ if (state) m_pcdr |= (1 << bit); else m_pcdr &= ~(1 << bit); } + +void pit68230_device::update_tin(uint8_t state) +{ + // Tick clock on falling edge. TODO: check what flank is correct + if (state == CLEAR_LINE) + { + tick_clock(); + } + + pc_update_bit(REG_PCDR_TIN_BIT, state == ASSERT_LINE ? 0 : 1); } #if VERBOSE > 2 @@ -298,20 +323,79 @@ void pit68230_device::wr_pitreg_pacr(uint8_t data) * 1 X0 Output pin - negated, H2S is always cleared. * 1 X1 Output pin - asserted, H2S is always cleared. */ - m_h2_out_cb (m_pacr & 0x08 ? 1 : 0); // TODO: Check mode and submodes + if (m_pgcr & REG_PGCR_H12_ENABLE) + { + if (m_pacr & REG_PACR_H2_CTRL_IN_OUT) + { + switch(m_pacr & REG_PACR_H2_CTRL_MASK) + { + case REG_PACR_H2_CTRL_OUT_00: + LOG((" - H2 cleared\n")); + m_h2_out_cb(CLEAR_LINE); + break; + case REG_PACR_H2_CTRL_OUT_01: + LOG((" - H2 asserted\n")); + m_h2_out_cb(ASSERT_LINE); + break; + case REG_PACR_H2_CTRL_OUT_10: + LOGSETUP((" - interlocked handshake not implemented\n")); + break; + case REG_PACR_H2_CTRL_OUT_11: + LOGSETUP((" - pulsed handshake not implemented\n")); + break; + default: logerror(("Undefined H2 mode, broken driver - please report!\n")); + } + } + } + else + { + LOG((" - H2 cleared because beeing disabled in PGCR\n")); + m_h2_out_cb(CLEAR_LINE); + } } +// TODO add support for sense status void pit68230_device::wr_pitreg_pbcr(uint8_t data) { LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data)); m_pbcr = data; + if ((m_pgcr & REG_PGCR_H34_ENABLE) || ((m_pbcr & REG_PBCR_SUBMODE_MASK) == REG_PBCR_SUBMODE_1X)) + { + if (m_pbcr & REG_PBCR_H4_CTRL_IN_OUT) + { + switch(m_pbcr & REG_PBCR_H4_CTRL_MASK) + { + case REG_PBCR_H4_CTRL_OUT_00: + LOG((" - H4 cleared\n")); + m_h4_out_cb(CLEAR_LINE); + break; + case REG_PBCR_H4_CTRL_OUT_01: + LOG((" - H4 asserted\n")); + m_h4_out_cb(ASSERT_LINE); + break; + case REG_PBCR_H4_CTRL_OUT_10: + LOGSETUP((" - interlocked handshake not implemented\n")); + break; + case REG_PBCR_H4_CTRL_OUT_11: + LOGSETUP((" - pulsed handshake not implemented\n")); + break; + default: logerror(("Undefined H4 mode, broken driver - please report!\n")); + } + } + } + else + { + LOG((" - H4 cleared because beeing disabled in PGCR\n")); + m_h4_out_cb(CLEAR_LINE); + } } void pit68230_device::wr_pitreg_padr(uint8_t data) { LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data)); m_padr |= (data & m_paddr); - // callbacks + + // callback m_pa_out_cb ((offs_t)0, m_padr); } @@ -319,7 +403,8 @@ void pit68230_device::wr_pitreg_pbdr(uint8_t data) { LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data)); m_pbdr |= (data & m_pbddr); - // callbacks + + // callback m_pb_out_cb ((offs_t)0, m_pbdr & m_pbddr); } @@ -327,7 +412,8 @@ void pit68230_device::wr_pitreg_pcdr(uint8_t data) { LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data)); m_pcdr |= (data & m_pcddr); - // callbacks + + // callback m_pc_out_cb ((offs_t)0, m_pcdr); } @@ -482,7 +568,7 @@ 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())); - m_tsr = data; + if (data & 1) m_tsr = 0; // A write resets the TSR; } WRITE8_MEMBER (pit68230_device::write) @@ -592,7 +678,7 @@ uint8_t pit68230_device::rr_pitreg_padr() { m_padr &= m_paddr; m_padr |= (m_pa_in_cb() & ~m_paddr); - LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_padr)); + LOGDR(("%s %s <- %02x\n",tag(), FUNCNAME, m_padr)); return m_padr; } @@ -607,15 +693,19 @@ uint8_t pit68230_device::rr_pitreg_pbdr() { m_pbdr &= m_pbddr; m_pbdr |= (m_pb_in_cb() & ~m_pbddr); - LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pbdr)); + + LOGDR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pbdr)); return m_pbdr; } uint8_t pit68230_device::rr_pitreg_pcdr() { - m_pcdr &= m_pcddr; - m_pcdr |= (m_pc_in_cb() & ~m_pcddr); - LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pcdr)); + if (!m_pc_in_cb.isnull()) // Port C has alternate functions that may set bits apart from callback + { + m_pcdr &= m_pcddr; + m_pcdr |= (m_pc_in_cb() & ~m_pcddr); + } + if (m_pcdr != 0) { LOGDR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pcdr)); } return m_pcdr; } @@ -739,7 +829,7 @@ READ8_MEMBER (pit68230_device::read){ case PIT_68230_CNTRL: data = rr_pitreg_cntrl(); break; case PIT_68230_TSR: data = rr_pitreg_tsr(); break; default: - LOG (("Unhandled read register %02x\n", offset)); + LOG (("Unhandled read register %02x returning 0x00\n", offset)); data = 0; } diff --git a/src/devices/machine/68230pit.h b/src/devices/machine/68230pit.h index 0fe41d1a68f..10dd7c3bd08 100644 --- a/src/devices/machine/68230pit.h +++ b/src/devices/machine/68230pit.h @@ -125,6 +125,13 @@ class pit68230_device : public device_t//, public device_execute_interface 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); + void pb_update_bit(uint8_t bit, uint8_t state); + void pc_update_bit(uint8_t bit, uint8_t state); + void update_tin(uint8_t); void wr_pitreg_pgcr(uint8_t data); void wr_pitreg_psrr(uint8_t data); @@ -173,7 +180,65 @@ class pit68230_device : public device_t//, public device_execute_interface protected: + enum { // PGCR - Port Global Control register + REG_PGCR_MODE_MASK = 0xc0, + REG_PGCR_MODE_0 = 0x00, // 0 0 Unidirectional 8 bit mode + REG_PGCR_MODE_1 = 0x40, // 0 1 Unidirectional 16 bit mode + REG_PGCR_MODE_2 = 0x80, // 1 0 Bidirectional 8 bit mode + REG_PGCR_MODE_3 = 0xc0, // 1 1 Bidirectional 16 bit mode + REG_PGCR_H34_ENABLE = 0x20, + REG_PGCR_H12_ENABLE = 0x10, + REG_PGCR_H4_SENSE = 0x80, + REG_PGCR_H3_SENSE = 0x40, + REG_PGCR_H2_SENSE = 0x20, + REG_PGCR_H1_SENSE = 0x10, + }; + enum { + REG_PACR_SUBMODE_MASK = 0xc0, + REG_PACR_SUBMODE_0 = 0x00, // 0 0 + REG_PACR_SUBMODE_1 = 0x40, // 0 1 + REG_PACR_SUBMODE_2 = 0x80, // 1 0 + REG_PACR_SUBMODE_3 = 0xc0, // 1 1 + REG_PACR_H2_CTRL_MASK = 0x38, + REG_PACR_H2_CTRL_IN_OUT = 0x20, // H2 sense always cleared if set + REG_PACR_H2_CTRL_OUT_00 = 0x20, // H2 output negated + REG_PACR_H2_CTRL_OUT_01 = 0x28, // H2 output asserted + REG_PACR_H2_CTRL_OUT_10 = 0x30, // H2 output in interlocked input handshake protocol + REG_PACR_H2_CTRL_OUT_11 = 0x38, // H2 output in pulsed input handshake protocol + REG_PACR_H2_INT_ENABLE = 0x04, + REG_PACR_H1_SVCR_ENABLE = 0x02, + REG_PACR_H1_STATUS_CTRL = 0x01, + }; + + enum { + REG_PBCR_SUBMODE_MASK = 0xc0, + REG_PBCR_SUBMODE_00 = 0x00, // 0 0 + REG_PBCR_SUBMODE_01 = 0x40, // 0 1 + REG_PBCR_SUBMODE_10 = 0x80, // 1 0 + REG_PBCR_SUBMODE_11 = 0xc0, // 1 1 + REG_PBCR_SUBMODE_1X = 0x80, // submode 2 or 3 + REG_PBCR_H4_CTRL_MASK = 0x38, + REG_PBCR_H4_CTRL_IN_OUT = 0x20, // H4 sense always cleared if set + REG_PBCR_H4_CTRL_OUT_00 = 0x20, // H4 output negated + REG_PBCR_H4_CTRL_OUT_01 = 0x28, // H4 output asserted + REG_PBCR_H4_CTRL_OUT_10 = 0x30, // H4 output in interlocked input handshake protocol + REG_PBCR_H4_CTRL_OUT_11 = 0x38, // H4 output in pulsed input handshake protocol + REG_PBCR_H4_INT_ENABLE = 0x04, + REG_PBCR_H3_SVCRQ_ENABLE= 0x02, + REG_PBCR_H3_STATUS_CTRL = 0x01, + }; + + enum { + REG_PCDR_TIN_BIT = 2, // BIT number + REG_PCDR_TIN = 0x04 // bit position + }; + + enum { + REG_TCR_TIMER_ENABLE = 0x01 + }; + + enum { // TCR - Timer Control register REG_TCR_ENABLE = 0x01, REG_TCR_CC_MASK = 0x06, REG_TCR_CC_PC2_CLK_PSC = 0x00, @@ -224,11 +289,11 @@ protected: uint8_t m_pbdr; // Port B Data register uint8_t m_pcdr; // Port C Data register uint8_t m_psr; // Port Status Register - uint8_t m_tcr; // Timer Control Register - uint8_t m_tivr; // Timer Interrupt Vector register - int m_cpr; // Counter Preload Registers (3 x 8 = 24 bits) - int m_cntr; // - The 24 bit Counter - uint8_t m_tsr; // Timer Status Register + uint8_t m_tcr; // Timer Control Register + uint8_t m_tivr; // Timer Interrupt Vector register + int m_cpr; // Counter Preload Registers (3 x 8 = 24 bits) + int m_cntr; // - The 24 bit Counter + uint8_t m_tsr; // Timer Status Register // Timers emu_timer *pit_timer;