diff options
-rw-r--r-- | src/devices/machine/z8536.cpp | 490 | ||||
-rw-r--r-- | src/devices/machine/z8536.h | 209 | ||||
-rw-r--r-- | src/mame/drivers/c900.cpp | 13 |
3 files changed, 425 insertions, 287 deletions
diff --git a/src/devices/machine/z8536.cpp b/src/devices/machine/z8536.cpp index d8581e04101..b5ce53c6bfc 100644 --- a/src/devices/machine/z8536.cpp +++ b/src/devices/machine/z8536.cpp @@ -2,7 +2,20 @@ // copyright-holders:Curt Coder /********************************************************************** - Zilog Z8536 Counter/Timer and Parallel I/O emulation + Zilog Z8036/Z8536 Counter/Timer and Parallel I/O Unit + + Much like the SCC, two alternate versions of this peripheral + were developed by Zilog. The Z8036 (Z-CIO) was compatible with + the Z8000's address-latched Z-Bus and could write to any + register directly, while the Z8536 interfaced to a generic bus + using two address bits, requiring sequential writes to its + control register in order to access any of the internal registers + besides the three for port data. + + Both versions of the CIO can be reset through hardware as well as + software, despite that neither provides a dedicated RESET pin. + Pulling AS and DS active low at the same time resets the Z8036, + and Z8536 is reset by activating RD and WR simultaneously. **********************************************************************/ @@ -28,7 +41,8 @@ #include "logmacro.h" -// device type definition +// device type definitions +DEFINE_DEVICE_TYPE(Z8036, z8036_device, "z8036", "Zilog Z8036 Z-CIO") DEFINE_DEVICE_TYPE(Z8536, z8536_device, "z8536", "Zilog Z8536 CIO") @@ -42,76 +56,6 @@ static char const *const PMS_PMS[] = { "Disabled", "AND", "OR", "OR-PEV" }; static char const *const CTMS_DCS[] = { "Pulse", "One-shot", "Square Wave", "Do not use" }; -// master interrupt control register -#define MICR_RESET 0x01 // reset -#define MICR_RJA 0x02 // right justified address -#define MICR_CT_VIS 0x04 // counter/timer vector includes status -#define MICR_PB_VIS 0x08 // port B vector includes status -#define MICR_PA_VIS 0x10 // port A vector includes status -#define MICR_NV 0x20 // no vector -#define MICR_DLC 0x40 // disable lower chain -#define MICR_MIE 0x80 // master interrupt enable - - -// master configuration control register -#define MCCR_LC_MASK 0x03 // counter/timer link controls -#define MCCR_PAE 0x04 // port A enable -#define MCCR_PLC 0x08 // port link control -#define MCCR_PCE_CT3E 0x10 // port C and counter/timer 3 enable -#define MCCR_CT2E 0x20 // counter/timer 2 enable -#define MCCR_CT1E 0x40 // counter/timer 1 enable -#define MCCR_PBE 0x80 // port B enable - - -// port mode specification registers -#define PMS_LPM 0x01 // latch on pattern match -#define PMS_DTE 0x01 // deskew timer enable -#define PMS_PMS_MASK 0x06 // pattern mode specification -#define PMS_IMO 0x08 // interrupt on match only -#define PMS_SB 0x10 // single buffer -#define PMS_ITB 0x20 // interrupt on two bytes -#define PMS_PTS_MASK 0xc0 // port type select - - -// port handshake specification registers -#define PHS_DTS_MASK 0x07 // deskew time specification -#define PHS_RWS_MASK 0x38 // request/wait specification -#define PHS_HTS_MASK 0xc0 // handshake type specification - - -// port command and status registers -#define PCS_IOE 0x01 // interrupt on error -#define PCS_PMF 0x02 // pattern match flag (read only) -#define PCS_IRF 0x04 // input register full (read only) -#define PCS_ORE 0x08 // output register empty (read only) -#define PCS_ERR 0x10 // interrupt error (read only) -#define PCS_IP 0x20 // interrupt pending -#define PCS_IE 0x40 // interrupt enable -#define PCS_IUS 0x80 // interrupt under service - - -// counter/timer mode specification registers -#define CTMS_DCS_MASK 0x03 // output duty cycle -#define CTMS_REB 0x04 // retrigger enable bit -#define CTMS_EDE 0x08 // external gate enable -#define CTMS_ETE 0x10 // external trigger enable -#define CTMS_ECE 0x20 // external count enable -#define CTMS_EOE 0x40 // external output enable -#define CTMS_CSC 0x80 // continuous/single cycle - - -// counter/timer command and status registers -#define CTCS_CIP 0x01 // count in progress (read only) -#define CTCS_TCB 0x02 // trigger command bit (write only - read returns 0) -#define CTCS_GCB 0x04 // gate command bit -#define CTCS_RCC 0x08 // read counter control (read/set only - cleared by reading CCR LSB) -#define CTCS_ERR 0x10 // interrupt error (read only) -#define CTCS_IP 0x20 // interrupt pending -#define CTCS_IE 0x40 // interrupt enable -#define CTCS_IUS 0x80 // interrupt under service - - - //************************************************************************** // INLINE HELPERS //************************************************************************** @@ -120,7 +64,7 @@ static char const *const CTMS_DCS[] = { "Pulse", "One-shot", "Square Wave", "Do // get_interrupt_vector - //------------------------------------------------- -void z8536_device::get_interrupt_vector() +void cio_base_device::get_interrupt_vector() { uint8_t vector = 0xff; @@ -213,7 +157,7 @@ void z8536_device::get_interrupt_vector() // check_interrupt - check interrupt status //------------------------------------------------- -void z8536_device::check_interrupt() +void cio_base_device::check_interrupt() { int state; @@ -239,7 +183,7 @@ void z8536_device::check_interrupt() if (m_irq != state) { - LOG("%s Z8536 Interrupt: %u\n", machine().describe_context(), state); + LOG("%s CIO Interrupt: %u\n", machine().describe_context(), state); m_irq = state; m_write_irq(state); } @@ -250,7 +194,7 @@ void z8536_device::check_interrupt() // read_register - read from register //------------------------------------------------- -uint8_t z8536_device::read_register(offs_t offset) +uint8_t cio_base_device::read_register(offs_t offset) { uint8_t data; @@ -327,7 +271,7 @@ uint8_t z8536_device::read_register(offs_t offset) // read_register - masked read from register //------------------------------------------------- -uint8_t z8536_device::read_register(offs_t offset, uint8_t mask) +uint8_t cio_base_device::read_register(offs_t offset, uint8_t mask) { return read_register(offset) & mask; } @@ -337,43 +281,38 @@ uint8_t z8536_device::read_register(offs_t offset, uint8_t mask) // write_register - write to register //------------------------------------------------- -void z8536_device::write_register(offs_t offset, uint8_t data) +void cio_base_device::write_register(offs_t offset, uint8_t data) { switch (offset) { case MASTER_INTERRUPT_CONTROL: if (data & MICR_RESET) { - LOG("%s Z8536 Reset\n", machine().describe_context()); + LOG("%s CIO Reset\n", machine().describe_context()); device_reset(); } else { - if (m_state == STATE_RESET) - { - m_state = STATE_0; - } - - LOG("%s Z8536 Master Interrupt Enable: %u\n", machine().describe_context(), (data & MICR_MIE) ? 1 : 0); - LOG("%s Z8536 Disable Lower Chain: %u\n", machine().describe_context(), (data & MICR_DLC) ? 1 : 0); - LOG("%s Z8536 No Vector: %u\n", machine().describe_context(), (data & MICR_NV) ? 1 : 0); - LOG("%s Z8536 Port A Vector Includes Status: %u\n", machine().describe_context(), (data & MICR_PA_VIS) ? 1 : 0); - LOG("%s Z8536 Port B Vector Includes Status: %u\n", machine().describe_context(), (data & MICR_PB_VIS) ? 1 : 0); - LOG("%s Z8536 Counter/Timer Vector Includes Status: %u\n", machine().describe_context(), (data & MICR_CT_VIS) ? 1 : 0); - LOG("%s Z8536 Right Justified Address: %u\n", machine().describe_context(), (data & MICR_RJA) ? 1 : 0); + LOG("%s CIO Master Interrupt Enable: %u\n", machine().describe_context(), (data & MICR_MIE) ? 1 : 0); + LOG("%s CIO Disable Lower Chain: %u\n", machine().describe_context(), (data & MICR_DLC) ? 1 : 0); + LOG("%s CIO No Vector: %u\n", machine().describe_context(), (data & MICR_NV) ? 1 : 0); + LOG("%s CIO Port A Vector Includes Status: %u\n", machine().describe_context(), (data & MICR_PA_VIS) ? 1 : 0); + LOG("%s CIO Port B Vector Includes Status: %u\n", machine().describe_context(), (data & MICR_PB_VIS) ? 1 : 0); + LOG("%s CIO Counter/Timer Vector Includes Status: %u\n", machine().describe_context(), (data & MICR_CT_VIS) ? 1 : 0); + LOG("%s CIO Right Justified Address: %u\n", machine().describe_context(), (data & MICR_RJA) ? 1 : 0); m_register[offset] = data; } break; case MASTER_CONFIGURATION_CONTROL: - LOG("%s Z8536 Port B Enable: %u\n", machine().describe_context(), (data & MCCR_PBE) ? 1 : 0); - LOG("%s Z8536 Counter/Timer 1 Enable: %u\n", machine().describe_context(), (data & MCCR_CT1E) ? 1 : 0); - LOG("%s Z8536 Counter/Timer 2 Enable: %u\n", machine().describe_context(), (data & MCCR_CT2E) ? 1 : 0); - LOG("%s Z8536 Port C and Counter/Timer 3 Enable: %u\n", machine().describe_context(), (data & MCCR_PCE_CT3E) ? 1 : 0); - LOG("%s Z8536 Port A Enable: %u\n", machine().describe_context(), (data & MCCR_PAE) ? 1 : 0); - LOG("%s Z8536 Port Link Control: %u\n", machine().describe_context(), (data & MCCR_PLC) ? 1 : 0); - LOG("%s Z8536 Counter/Timer Link Controls: %u\n", machine().describe_context(), data & MCCR_LC_MASK); + LOG("%s CIO Port B Enable: %u\n", machine().describe_context(), (data & MCCR_PBE) ? 1 : 0); + LOG("%s CIO Counter/Timer 1 Enable: %u\n", machine().describe_context(), (data & MCCR_CT1E) ? 1 : 0); + LOG("%s CIO Counter/Timer 2 Enable: %u\n", machine().describe_context(), (data & MCCR_CT2E) ? 1 : 0); + LOG("%s CIO Port C and Counter/Timer 3 Enable: %u\n", machine().describe_context(), (data & MCCR_PCE_CT3E) ? 1 : 0); + LOG("%s CIO Port A Enable: %u\n", machine().describe_context(), (data & MCCR_PAE) ? 1 : 0); + LOG("%s CIO Port Link Control: %u\n", machine().describe_context(), (data & MCCR_PLC) ? 1 : 0); + LOG("%s CIO Counter/Timer Link Controls: %u\n", machine().describe_context(), data & MCCR_LC_MASK); m_register[offset] = data; @@ -385,32 +324,32 @@ void z8536_device::write_register(offs_t offset, uint8_t data) break; case PORT_A_INTERRUPT_VECTOR: - LOG("%s Z8536 Port A Interrupt Vector: %02x\n", machine().describe_context(), data); + LOG("%s CIO Port A Interrupt Vector: %02x\n", machine().describe_context(), data); m_register[offset] = data; break; case PORT_B_INTERRUPT_VECTOR: - LOG("%s Z8536 Port B Interrupt Vector: %02x\n", machine().describe_context(), data); + LOG("%s CIO Port B Interrupt Vector: %02x\n", machine().describe_context(), data); m_register[offset] = data; break; case COUNTER_TIMER_INTERRUPT_VECTOR: - LOG("%s Z8536 Counter/Timer Interrupt Vector: %02x\n", machine().describe_context(), data); + LOG("%s CIO Counter/Timer Interrupt Vector: %02x\n", machine().describe_context(), data); m_register[offset] = data; break; case PORT_C_DATA_PATH_POLARITY: - LOG("%s Z8536 Port C Data Path Polarity: %02x\n", machine().describe_context(), data); + LOG("%s CIO Port C Data Path Polarity: %02x\n", machine().describe_context(), data); m_register[offset] = data; break; case PORT_C_DATA_DIRECTION: - LOG("%s Z8536 Port C Data Direction: %02x\n", machine().describe_context(), data); + LOG("%s CIO Port C Data Direction: %02x\n", machine().describe_context(), data); m_register[offset] = data; break; case PORT_C_SPECIAL_IO_CONTROL: - LOG("%s Z8536 Port C Special I/O Control: %02x\n", machine().describe_context(), data); + LOG("%s CIO Port C Special I/O Control: %02x\n", machine().describe_context(), data); m_register[offset] = data; break; @@ -419,17 +358,17 @@ void z8536_device::write_register(offs_t offset, uint8_t data) { char port = 'A' + offset - PORT_A_COMMAND_AND_STATUS; - LOG("%s Z8536 Port %c Interrupt on Error: %u\n", machine().describe_context(), port, (data & PCS_IOE) ? 1 : 0); + LOG("%s CIO Port %c Interrupt on Error: %u\n", machine().describe_context(), port, (data & PCS_IOE) ? 1 : 0); switch (data >> 5) { - case IC_CLEAR_IP_IUS: m_register[offset] &= ~(PCS_IP | PCS_IUS); LOG("%s Z8536 Port %c Clear IP/IUS\n", machine().describe_context(), port); break; - case IC_SET_IUS: m_register[offset] |= PCS_IUS; LOG("%s Z8536 Port %c Set IUS\n", machine().describe_context(), port); break; - case IC_CLEAR_IUS: m_register[offset] &= ~PCS_IUS; LOG("%s Z8536 Port %c Clear IUS\n", machine().describe_context(), port); break; - case IC_SET_IP: m_register[offset] |= PCS_IP; LOG("%s Z8536 Port %c Set IP\n", machine().describe_context(), port); break; - case IC_CLEAR_IP: m_register[offset] &= ~PCS_IP; LOG("%s Z8536 Port %c Clear IP\n", machine().describe_context(), port); break; - case IC_SET_IE: m_register[offset] |= PCS_IE; LOG("%s Z8536 Port %c Set IE\n", machine().describe_context(), port); break; - case IC_CLEAR_IE: m_register[offset] &= ~PCS_IE; LOG("%s Z8536 Port %c Clear IE\n", machine().describe_context(), port); break; + case IC_CLEAR_IP_IUS: m_register[offset] &= ~(PCS_IP | PCS_IUS); LOG("%s CIO Port %c Clear IP/IUS\n", machine().describe_context(), port); break; + case IC_SET_IUS: m_register[offset] |= PCS_IUS; LOG("%s CIO Port %c Set IUS\n", machine().describe_context(), port); break; + case IC_CLEAR_IUS: m_register[offset] &= ~PCS_IUS; LOG("%s CIO Port %c Clear IUS\n", machine().describe_context(), port); break; + case IC_SET_IP: m_register[offset] |= PCS_IP; LOG("%s CIO Port %c Set IP\n", machine().describe_context(), port); break; + case IC_CLEAR_IP: m_register[offset] &= ~PCS_IP; LOG("%s CIO Port %c Clear IP\n", machine().describe_context(), port); break; + case IC_SET_IE: m_register[offset] |= PCS_IE; LOG("%s CIO Port %c Set IE\n", machine().describe_context(), port); break; + case IC_CLEAR_IE: m_register[offset] &= ~PCS_IE; LOG("%s CIO Port %c Clear IE\n", machine().describe_context(), port); break; } m_register[offset] = (m_register[offset] & ~PCS_IOE) | (data & PCS_IOE); @@ -445,19 +384,19 @@ void z8536_device::write_register(offs_t offset, uint8_t data) { int counter = offset - COUNTER_TIMER_1_COMMAND_AND_STATUS; - LOG("%s Z8536 Counter/Timer %u Trigger Command Bit: %u\n", machine().describe_context(), counter + 1, (data & CTCS_TCB) ? 1 : 0); - LOG("%s Z8536 Counter/Timer %u Gate Command Bit: %u\n", machine().describe_context(), counter + 1, (data & CTCS_GCB) ? 1 : 0); - LOG("%s Z8536 Counter/Timer %u Read Counter Control: %u\n", machine().describe_context(), counter + 1, (data & CTCS_RCC) ? 1 : 0); + LOG("%s CIO Counter/Timer %u Trigger Command Bit: %u\n", machine().describe_context(), counter + 1, (data & CTCS_TCB) ? 1 : 0); + LOG("%s CIO Counter/Timer %u Gate Command Bit: %u\n", machine().describe_context(), counter + 1, (data & CTCS_GCB) ? 1 : 0); + LOG("%s CIO Counter/Timer %u Read Counter Control: %u\n", machine().describe_context(), counter + 1, (data & CTCS_RCC) ? 1 : 0); switch (data >> 5) { - case IC_CLEAR_IP_IUS: m_register[offset] &= ~(CTCS_IP | CTCS_IUS);LOG("%s Z8536 Counter/Timer %u Clear IP/IUS\n", machine().describe_context(), counter + 1); break; - case IC_SET_IUS: m_register[offset] |= CTCS_IUS; LOG("%s Z8536 Counter/Timer %u Set IUS\n", machine().describe_context(), counter + 1); break; - case IC_CLEAR_IUS: m_register[offset] &= ~CTCS_IUS; LOG("%s Z8536 Counter/Timer %u Clear IUS\n", machine().describe_context(), counter + 1); break; - case IC_SET_IP: m_register[offset] |= CTCS_IP; LOG("%s Z8536 Counter/Timer %u Set IP\n", machine().describe_context(), counter + 1); break; - case IC_CLEAR_IP: m_register[offset] &= ~CTCS_IP; LOG("%s Z8536 Counter/Timer %u Clear IP\n", machine().describe_context(), counter + 1); break; - case IC_SET_IE: m_register[offset] |= CTCS_IE; LOG("%s Z8536 Counter/Timer %u Set IE\n", machine().describe_context(), counter + 1); break; - case IC_CLEAR_IE: m_register[offset] &= ~CTCS_IE; LOG("%s Z8536 Counter/Timer %u Clear IE\n", machine().describe_context(), counter + 1); break; + case IC_CLEAR_IP_IUS: m_register[offset] &= ~(CTCS_IP | CTCS_IUS);LOG("%s CIO Counter/Timer %u Clear IP/IUS\n", machine().describe_context(), counter + 1); break; + case IC_SET_IUS: m_register[offset] |= CTCS_IUS; LOG("%s CIO Counter/Timer %u Set IUS\n", machine().describe_context(), counter + 1); break; + case IC_CLEAR_IUS: m_register[offset] &= ~CTCS_IUS; LOG("%s CIO Counter/Timer %u Clear IUS\n", machine().describe_context(), counter + 1); break; + case IC_SET_IP: m_register[offset] |= CTCS_IP; LOG("%s CIO Counter/Timer %u Set IP\n", machine().describe_context(), counter + 1); break; + case IC_CLEAR_IP: m_register[offset] &= ~CTCS_IP; LOG("%s CIO Counter/Timer %u Clear IP\n", machine().describe_context(), counter + 1); break; + case IC_SET_IE: m_register[offset] |= CTCS_IE; LOG("%s CIO Counter/Timer %u Set IE\n", machine().describe_context(), counter + 1); break; + case IC_CLEAR_IE: m_register[offset] &= ~CTCS_IE; LOG("%s CIO Counter/Timer %u Clear IE\n", machine().describe_context(), counter + 1); break; } // gate command bit @@ -503,7 +442,7 @@ void z8536_device::write_register(offs_t offset, uint8_t data) case COUNTER_TIMER_1_TIME_CONSTANT_MS_BYTE: case COUNTER_TIMER_2_TIME_CONSTANT_MS_BYTE: case COUNTER_TIMER_3_TIME_CONSTANT_MS_BYTE: - LOG("%s Z8536 Counter/Timer %u Time Constant MSB: %02x\n", machine().describe_context(), ((offset - COUNTER_TIMER_1_TIME_CONSTANT_MS_BYTE) >> 1) + 1, data); + LOG("%s CIO Counter/Timer %u Time Constant MSB: %02x\n", machine().describe_context(), ((offset - COUNTER_TIMER_1_TIME_CONSTANT_MS_BYTE) >> 1) + 1, data); m_register[offset] = data; break; @@ -511,7 +450,7 @@ void z8536_device::write_register(offs_t offset, uint8_t data) case COUNTER_TIMER_1_TIME_CONSTANT_LS_BYTE: case COUNTER_TIMER_2_TIME_CONSTANT_LS_BYTE: case COUNTER_TIMER_3_TIME_CONSTANT_LS_BYTE: - LOG("%s Z8536 Counter/Timer %u Time Constant LSB: %02x\n", machine().describe_context(), ((offset - COUNTER_TIMER_1_TIME_CONSTANT_LS_BYTE) >> 1) + 1, data); + LOG("%s CIO Counter/Timer %u Time Constant LSB: %02x\n", machine().describe_context(), ((offset - COUNTER_TIMER_1_TIME_CONSTANT_LS_BYTE) >> 1) + 1, data); m_register[offset] = data; break; @@ -524,13 +463,13 @@ void z8536_device::write_register(offs_t offset, uint8_t data) int const counter = offset - COUNTER_TIMER_1_MODE_SPECIFICATION; int const dcs = data & CTMS_DCS_MASK; - LOG("%s Z8536 Counter/Timer %u Mode: %s\n", machine().describe_context(), counter + 1, (data & CTMS_CSC) ? "Continuous" : "Single Cycle"); - LOG("%s Z8536 Counter/Timer %u External Output Enable: %u\n", machine().describe_context(), counter + 1, (data & CTMS_EOE) ? 1 : 0); - LOG("%s Z8536 Counter/Timer %u External Count Enable: %u\n", machine().describe_context(), counter + 1, (data & CTMS_ECE) ? 1 : 0); - LOG("%s Z8536 Counter/Timer %u External Trigger Enable: %u\n", machine().describe_context(), counter + 1, (data & CTMS_ETE) ? 1 : 0); - LOG("%s Z8536 Counter/Timer %u External Gate Enable: %u\n", machine().describe_context(), counter + 1, (data & CTMS_EDE) ? 1 : 0); - LOG("%s Z8536 Counter/Timer %u Retrigger Enable: %u\n", machine().describe_context(), counter + 1, (data & CTMS_REB) ? 1 : 0); - LOG("%s Z8536 Counter/Timer %u Output Duty Cycle: %s\n", machine().describe_context(), counter + 1, CTMS_DCS[dcs]); + LOG("%s CIO Counter/Timer %u Mode: %s\n", machine().describe_context(), counter + 1, (data & CTMS_CSC) ? "Continuous" : "Single Cycle"); + LOG("%s CIO Counter/Timer %u External Output Enable: %u\n", machine().describe_context(), counter + 1, (data & CTMS_EOE) ? 1 : 0); + LOG("%s CIO Counter/Timer %u External Count Enable: %u\n", machine().describe_context(), counter + 1, (data & CTMS_ECE) ? 1 : 0); + LOG("%s CIO Counter/Timer %u External Trigger Enable: %u\n", machine().describe_context(), counter + 1, (data & CTMS_ETE) ? 1 : 0); + LOG("%s CIO Counter/Timer %u External Gate Enable: %u\n", machine().describe_context(), counter + 1, (data & CTMS_EDE) ? 1 : 0); + LOG("%s CIO Counter/Timer %u Retrigger Enable: %u\n", machine().describe_context(), counter + 1, (data & CTMS_REB) ? 1 : 0); + LOG("%s CIO Counter/Timer %u Output Duty Cycle: %s\n", machine().describe_context(), counter + 1, CTMS_DCS[dcs]); } m_register[offset] = data; @@ -544,16 +483,16 @@ void z8536_device::write_register(offs_t offset, uint8_t data) int const pts = (data & PMS_PTS_MASK) >> 6; int const pms = (data & PMS_PMS_MASK) >> 1; - LOG("%s Z8536 Port %c Port Type: %s\n", machine().describe_context(), port, PMS_PTS[pts]); - LOG("%s Z8536 Port %c Interrupt on 2 Bytes: %u\n", machine().describe_context(), port, (data & PMS_ITB) ? 1 : 0); - LOG("%s Z8536 Port %c Single Buffer: %u\n", machine().describe_context(), port, (data & PMS_SB) ? 1 : 0); - LOG("%s Z8536 Port %c Interrupt on Match Only: %u\n", machine().describe_context(), port, (data & PMS_IMO) ? 1 : 0); - LOG("%s Z8536 Port %c Pattern Mode: %s\n", machine().describe_context(), port, PMS_PMS[pms]); + LOG("%s CIO Port %c Port Type: %s\n", machine().describe_context(), port, PMS_PTS[pts]); + LOG("%s CIO Port %c Interrupt on 2 Bytes: %u\n", machine().describe_context(), port, (data & PMS_ITB) ? 1 : 0); + LOG("%s CIO Port %c Single Buffer: %u\n", machine().describe_context(), port, (data & PMS_SB) ? 1 : 0); + LOG("%s CIO Port %c Interrupt on Match Only: %u\n", machine().describe_context(), port, (data & PMS_IMO) ? 1 : 0); + LOG("%s CIO Port %c Pattern Mode: %s\n", machine().describe_context(), port, PMS_PMS[pms]); if (pts == PTS_BIT) - LOG("%s Z8536 Port %c Latch on Pattern Match: %u\n", machine().describe_context(), port, (data & PMS_LPM) ? 1 : 0); + LOG("%s CIO Port %c Latch on Pattern Match: %u\n", machine().describe_context(), port, (data & PMS_LPM) ? 1 : 0); else - LOG("%s Z8536 Port %c Deskew Timer Enable: %u\n", machine().describe_context(), port, (data & PMS_DTE) ? 1 : 0); + LOG("%s CIO Port %c Deskew Timer Enable: %u\n", machine().describe_context(), port, (data & PMS_DTE) ? 1 : 0); } m_register[offset] = data; @@ -566,37 +505,37 @@ void z8536_device::write_register(offs_t offset, uint8_t data) case PORT_A_DATA_PATH_POLARITY: case PORT_B_DATA_PATH_POLARITY: - LOG("%s Z8536 Port %c Data Path Polarity: %02x\n", machine().describe_context(), BIT(offset, 3) ? 'B' : 'A', data); + LOG("%s CIO Port %c Data Path Polarity: %02x\n", machine().describe_context(), BIT(offset, 3) ? 'B' : 'A', data); m_register[offset] = data; break; case PORT_A_DATA_DIRECTION: case PORT_B_DATA_DIRECTION: - LOG("%s Z8536 Port %c Data Direction: %02x\n", machine().describe_context(), BIT(offset, 3) ? 'B' : 'A', data); + LOG("%s CIO Port %c Data Direction: %02x\n", machine().describe_context(), BIT(offset, 3) ? 'B' : 'A', data); m_register[offset] = data; break; case PORT_A_SPECIAL_IO_CONTROL: case PORT_B_SPECIAL_IO_CONTROL: - LOG("%s Z8536 Port %c Special I/O Control: %02x\n", machine().describe_context(), BIT(offset, 3) ? 'B' : 'A', data); + LOG("%s CIO Port %c Special I/O Control: %02x\n", machine().describe_context(), BIT(offset, 3) ? 'B' : 'A', data); m_register[offset] = data; break; case PORT_A_PATTERN_POLARITY: case PORT_B_PATTERN_POLARITY: - LOG("%s Z8536 Port %c Pattern Polarity: %02x\n", machine().describe_context(), BIT(offset, 3) ? 'B' : 'A', data); + LOG("%s CIO Port %c Pattern Polarity: %02x\n", machine().describe_context(), BIT(offset, 3) ? 'B' : 'A', data); m_register[offset] = data; break; case PORT_A_PATTERN_TRANSITION: case PORT_B_PATTERN_TRANSITION: - LOG("%s Z8536 Port %c Pattern Transition: %02x\n", machine().describe_context(), BIT(offset, 3) ? 'B' : 'A', data); + LOG("%s CIO Port %c Pattern Transition: %02x\n", machine().describe_context(), BIT(offset, 3) ? 'B' : 'A', data); m_register[offset] = data; break; case PORT_A_PATTERN_MASK: case PORT_B_PATTERN_MASK: - LOG("%s Z8536 Port %c Pattern Mask: %02x\n", machine().describe_context(), BIT(offset, 3) ? 'B' : 'A', data); + LOG("%s CIO Port %c Pattern Mask: %02x\n", machine().describe_context(), BIT(offset, 3) ? 'B' : 'A', data); m_register[offset] = data; match_pattern(BIT(offset, 3)); check_interrupt(); @@ -613,7 +552,7 @@ void z8536_device::write_register(offs_t offset, uint8_t data) // write_register - masked write to register //------------------------------------------------- -void z8536_device::write_register(offs_t offset, uint8_t data, uint8_t mask) +void cio_base_device::write_register(offs_t offset, uint8_t data, uint8_t mask) { uint8_t combined_data = (data & mask) | (m_register[offset] & (mask ^ 0xff)); @@ -625,7 +564,7 @@ void z8536_device::write_register(offs_t offset, uint8_t data, uint8_t mask) // counter_enabled - is counter enabled? //------------------------------------------------- -bool z8536_device::counter_enabled(device_timer_id id) +bool cio_base_device::counter_enabled(device_timer_id id) { bool enabled = false; @@ -652,7 +591,7 @@ bool z8536_device::counter_enabled(device_timer_id id) // counter_external_output - //------------------------------------------------- -bool z8536_device::counter_external_output(device_timer_id id) +bool cio_base_device::counter_external_output(device_timer_id id) { return (m_register[COUNTER_TIMER_1_MODE_SPECIFICATION + id] & CTMS_EOE) ? true : false; } @@ -662,7 +601,7 @@ bool z8536_device::counter_external_output(device_timer_id id) // counter_external_count - //------------------------------------------------- -bool z8536_device::counter_external_count(device_timer_id id) +bool cio_base_device::counter_external_count(device_timer_id id) { return (m_register[COUNTER_TIMER_1_MODE_SPECIFICATION + id] & CTMS_ECE) ? true : false; } @@ -672,7 +611,7 @@ bool z8536_device::counter_external_count(device_timer_id id) // counter_external_trigger - //------------------------------------------------- -bool z8536_device::counter_external_trigger(device_timer_id id) +bool cio_base_device::counter_external_trigger(device_timer_id id) { return (m_register[COUNTER_TIMER_1_MODE_SPECIFICATION + id] & CTMS_ETE) ? true : false; } @@ -682,7 +621,7 @@ bool z8536_device::counter_external_trigger(device_timer_id id) // counter_external_gate - //------------------------------------------------- -bool z8536_device::counter_external_gate(device_timer_id id) +bool cio_base_device::counter_external_gate(device_timer_id id) { return (m_register[COUNTER_TIMER_1_MODE_SPECIFICATION + id] & CTMS_EDE) ? true : false; } @@ -692,7 +631,7 @@ bool z8536_device::counter_external_gate(device_timer_id id) // counter_gated - //------------------------------------------------- -bool z8536_device::counter_gated(device_timer_id id) +bool cio_base_device::counter_gated(device_timer_id id) { return (m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + id] & CTCS_GCB) ? true : false; } @@ -702,7 +641,7 @@ bool z8536_device::counter_gated(device_timer_id id) // count - count down //------------------------------------------------- -void z8536_device::count(device_timer_id id) +void cio_base_device::count(device_timer_id id) { if (!counter_gated(id)) return; if (!(m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + id] & CTCS_CIP)) return; @@ -719,7 +658,7 @@ void z8536_device::count(device_timer_id id) } else { - LOG("%s Z8536 Counter/Timer %u Interrupt Pending\n", machine().describe_context(), id + 1); + LOG("%s CIO Counter/Timer %u Interrupt Pending\n", machine().describe_context(), id + 1); // set interrupt pending bit m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + id] |= CTCS_IP; @@ -732,7 +671,7 @@ void z8536_device::count(device_timer_id id) } else { - LOG("%s Z8536 Counter/Timer %u Terminal Count\n", machine().describe_context(), id + 1); + LOG("%s CIO Counter/Timer %u Terminal Count\n", machine().describe_context(), id + 1); // clear count in progress bit m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + id] &= ~CTCS_CIP; @@ -747,12 +686,12 @@ void z8536_device::count(device_timer_id id) // trigger - //------------------------------------------------- -void z8536_device::trigger(device_timer_id id) +void cio_base_device::trigger(device_timer_id id) { // ignore triggers during countdown if retrigger is disabled if (!(m_register[COUNTER_TIMER_1_MODE_SPECIFICATION + id] & CTMS_REB) && (m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + id] & CTCS_CIP)) return; - LOG("%s Z8536 Counter/Timer %u Trigger\n", machine().describe_context(), id + 1); + LOG("%s CIO Counter/Timer %u Trigger\n", machine().describe_context(), id + 1); // load counter with time constant m_counter[id] = (m_register[COUNTER_TIMER_1_TIME_CONSTANT_MS_BYTE + (id << 1)] << 8) | m_register[COUNTER_TIMER_1_TIME_CONSTANT_LS_BYTE + (id << 1)]; @@ -766,7 +705,7 @@ void z8536_device::trigger(device_timer_id id) // gate - //------------------------------------------------- -void z8536_device::gate(device_timer_id id, int state) +void cio_base_device::gate(device_timer_id id, int state) { // TODO } @@ -776,7 +715,7 @@ void z8536_device::gate(device_timer_id id, int state) // match_pattern - //------------------------------------------------- -void z8536_device::match_pattern(int port) +void cio_base_device::match_pattern(int port) { uint8_t pms = m_register[PORT_A_MODE_SPECIFICATION + (port << 3)]; uint8_t pm = m_register[PORT_A_PATTERN_MASK + (port << 3)]; @@ -789,7 +728,7 @@ void z8536_device::match_pattern(int port) if (m_match[port]) { - LOG("%s Z8536 Port %c Interrupt Pending\n", machine().describe_context(), 'A' + port); + LOG("%s CIO Port %c Interrupt Pending\n", machine().describe_context(), 'A' + port); m_register[PORT_A_COMMAND_AND_STATUS + port] |= PCS_IP; check_interrupt(); } @@ -802,7 +741,7 @@ void z8536_device::match_pattern(int port) // external_port_w - external port write //------------------------------------------------- -void z8536_device::external_port_w(int port, int bit, int state) +void cio_base_device::external_port_w(int port, int bit, int state) { switch (port) { @@ -814,7 +753,7 @@ void z8536_device::external_port_w(int port, int bit, int state) if (!BIT(ddr, bit)) return; - LOG("%s Z8536 Port %c Bit %u: %u\n", machine().describe_context(), 'A' + port, bit, state); + LOG("%s CIO Port %c Bit %u: %u\n", machine().describe_context(), 'A' + port, bit, state); m_input[port] = (m_input[port] & ~(1 << bit)) | (state << bit); @@ -834,12 +773,11 @@ void z8536_device::external_port_w(int port, int bit, int state) //************************************************************************** //------------------------------------------------- -// z8536_device - constructor +// cio_base_device - constructor //------------------------------------------------- -z8536_device::z8536_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - device_t(mconfig, Z8536, tag, owner, clock), - device_z80daisy_interface(mconfig, *this), +cio_base_device::cio_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : + device_t(mconfig, type, tag, owner, clock), m_write_irq(*this), m_read_pa(*this), m_write_pa(*this), @@ -853,10 +791,31 @@ z8536_device::z8536_device(const machine_config &mconfig, const char *tag, devic //------------------------------------------------- +// z8036_device - constructor +//------------------------------------------------- + +z8036_device::z8036_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + cio_base_device(mconfig, Z8036, tag, owner, clock) +{ +} + + +//------------------------------------------------- +// z8536_device - constructor +//------------------------------------------------- + +z8536_device::z8536_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : + cio_base_device(mconfig, Z8536, tag, owner, clock), + device_z80daisy_interface(mconfig, *this) +{ +} + + +//------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- -void z8536_device::device_start() +void cio_base_device::device_start() { for (int i = 0; i < 3; i++) { @@ -878,6 +837,22 @@ void z8536_device::device_start() m_write_pb.resolve_safe(); m_read_pc.resolve_safe(0); m_write_pc.resolve_safe(); + + save_item(NAME(m_irq)); + save_item(NAME(m_register)); + save_item(NAME(m_input)); + save_item(NAME(m_output)); + save_item(NAME(m_buffer)); + save_item(NAME(m_match)); + save_item(NAME(m_counter)); +} + +void z8536_device::device_start() +{ + cio_base_device::device_start(); + + save_item(NAME(m_state0)); + save_item(NAME(m_pointer)); } @@ -885,10 +860,8 @@ void z8536_device::device_start() // device_start - device-specific reset //------------------------------------------------- -void z8536_device::device_reset() +void cio_base_device::device_reset() { - m_state = STATE_RESET; - for (auto & elem : m_register) { elem = 0; @@ -899,9 +872,15 @@ void z8536_device::device_reset() m_register[PORT_B_COMMAND_AND_STATUS] = PCS_ORE; m_register[CURRENT_VECTOR] = 0xff; + check_interrupt(); +} + +void z8536_device::device_reset() +{ m_pointer = 0; + m_state0 = false; - check_interrupt(); + cio_base_device::device_reset(); } @@ -909,7 +888,7 @@ void z8536_device::device_reset() // device_timer - handler timer events //------------------------------------------------- -void z8536_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +void cio_base_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { if (counter_enabled(TIMER_1) && !counter_external_count(TIMER_1)) { @@ -965,25 +944,74 @@ void z8536_device::z80daisy_irq_reti() } +//------------------------------------------------- +// intack_r - interrupt acknowledge +//------------------------------------------------- + +int cio_base_device::intack_r() +{ + get_interrupt_vector(); + int data = m_register[CURRENT_VECTOR]; + + LOG("%s CIO Interrupt Acknowledge: %02x\n", machine().describe_context(), data); + + // set interrupt under service bit + if ((m_register[COUNTER_TIMER_3_COMMAND_AND_STATUS] & (CTCS_IP | CTCS_IE)) == (CTCS_IP | CTCS_IE)) + { + m_register[COUNTER_TIMER_3_COMMAND_AND_STATUS] |= CTCS_IUS; + } + else if ((m_register[PORT_A_COMMAND_AND_STATUS] & (PCS_IP | PCS_IE)) == (PCS_IP | PCS_IE)) + { + m_register[PORT_A_COMMAND_AND_STATUS] |= PCS_IUS; + } + else if ((m_register[COUNTER_TIMER_2_COMMAND_AND_STATUS] & (CTCS_IP | CTCS_IE)) == (CTCS_IP | CTCS_IE)) + { + m_register[COUNTER_TIMER_2_COMMAND_AND_STATUS] |= CTCS_IUS; + } + else if ((m_register[PORT_B_COMMAND_AND_STATUS] & (PCS_IP | PCS_IE)) == (PCS_IP | PCS_IE)) + { + m_register[PORT_B_COMMAND_AND_STATUS] |= PCS_IUS; + } + else if ((m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS] & (CTCS_IP | CTCS_IE)) == (CTCS_IP | CTCS_IE)) + { + m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS] |= CTCS_IUS; + } + + check_interrupt(); + + if (m_register[MASTER_INTERRUPT_CONTROL] & MICR_NV) + { + // no vector + data = -1; + } + + return data; +} + //************************************************************************** // INTERNAL STATE MANAGEMENT //************************************************************************** //------------------------------------------------- -// read - register read +// read - register read (Z-Bus) +//------------------------------------------------- + +READ8_MEMBER( z8036_device::read ) +{ + return is_reset() ? 0 : read_register(offset); +} + + +//------------------------------------------------- +// read - register read (universal bus) //------------------------------------------------- READ8_MEMBER( z8536_device::read ) { uint8_t data = 0; - if (m_state == STATE_RESET) - { - // read RESET bit - data = read_register(m_pointer, 0x01); - } - else + if (!is_reset()) { switch (offset & 0x03) { @@ -1000,15 +1028,13 @@ READ8_MEMBER( z8536_device::read ) break; case 3: - switch (m_state) - { - case STATE_1: - m_state = STATE_0; - // fallthru - case STATE_0: - data = read_register(m_pointer); - break; - } + // state 0 or state 1: read data + data = read_register(m_pointer); + + // return to state 0 after read + if (!machine().side_effect_disabled()) + m_state0 = true; + break; } } @@ -1018,15 +1044,38 @@ READ8_MEMBER( z8536_device::read ) //------------------------------------------------- -// write - register write +// write - register write (Z-Bus) +//------------------------------------------------- + +WRITE8_MEMBER( z8036_device::write ) +{ + if (is_reset()) + { + // writes to other registers are ignored during reset + if (offset != MASTER_INTERRUPT_CONTROL) + return; + + // RESET bit must be written before all others + data &= 0x01; + } + + write_register(offset, data); +} + + +//------------------------------------------------- +// write - register write (universal bus) //------------------------------------------------- WRITE8_MEMBER( z8536_device::write ) { - if (m_state == STATE_RESET) + if (is_reset()) { // write RESET bit write_register(m_pointer, data, 0x01); + + // proceed to state 0 if no longer reset + m_state0 = !is_reset(); } else { @@ -1045,64 +1094,23 @@ WRITE8_MEMBER( z8536_device::write ) break; case CONTROL: - switch (m_state) + if (m_state0) { - case STATE_0: + // state 0: write pointer m_pointer = data; - m_state = STATE_1; - break; - case STATE_1: + // proceed to state 1 + m_state0 = false; + } + else + { + // state 1: write data write_register(m_pointer, data); - if (m_state != STATE_RESET) - m_state = STATE_0; + + // return to state 0 unless reset + m_state0 = !is_reset(); } break; } } } - - -//------------------------------------------------- -// intack_r - interrupt acknowledge -//------------------------------------------------- - -int z8536_device::intack_r() -{ - get_interrupt_vector(); - int data = m_register[CURRENT_VECTOR]; - - LOG("%s Z8536 Interrupt Acknowledge: %02x\n", machine().describe_context(), data); - - // set interrupt under service bit - if ((m_register[COUNTER_TIMER_3_COMMAND_AND_STATUS] & (CTCS_IP | CTCS_IE)) == (CTCS_IP | CTCS_IE)) - { - m_register[COUNTER_TIMER_3_COMMAND_AND_STATUS] |= CTCS_IUS; - } - else if ((m_register[PORT_A_COMMAND_AND_STATUS] & (PCS_IP | PCS_IE)) == (PCS_IP | PCS_IE)) - { - m_register[PORT_A_COMMAND_AND_STATUS] |= PCS_IUS; - } - else if ((m_register[COUNTER_TIMER_2_COMMAND_AND_STATUS] & (CTCS_IP | CTCS_IE)) == (CTCS_IP | CTCS_IE)) - { - m_register[COUNTER_TIMER_2_COMMAND_AND_STATUS] |= CTCS_IUS; - } - else if ((m_register[PORT_B_COMMAND_AND_STATUS] & (PCS_IP | PCS_IE)) == (PCS_IP | PCS_IE)) - { - m_register[PORT_B_COMMAND_AND_STATUS] |= PCS_IUS; - } - else if ((m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS] & (CTCS_IP | CTCS_IE)) == (CTCS_IP | CTCS_IE)) - { - m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS] |= CTCS_IUS; - } - - check_interrupt(); - - if (m_register[MASTER_INTERRUPT_CONTROL] & MICR_NV) - { - // no vector - data = -1; - } - - return data; -} diff --git a/src/devices/machine/z8536.h b/src/devices/machine/z8536.h index 3a21628e53f..ccecde18849 100644 --- a/src/devices/machine/z8536.h +++ b/src/devices/machine/z8536.h @@ -2,10 +2,32 @@ // copyright-holders:Curt Coder /********************************************************************** - Zilog Z8536 Counter/Timer and Parallel I/O emulation + Zilog Z8036/Z8536 Counter/Timer and Parallel I/O Unit ********************************************************************** _____ _____ + AD4 1 |* \_/ | 40 AD3 + AD5 2 | | 39 AD2 + AD6 3 | | 38 AD1 + AD7 4 | | 37 AD0 + _DS 5 | | 36 _CS0 + R/_W 6 | | 35 CS1 + GND 7 | | 34 _AS + PB0 8 | | 33 PA0 + PB1 9 | | 32 PA1 + PB2 10 | Z8036 | 31 PA2 + PB3 11 | | 30 PA3 + PB4 12 | | 29 PA4 + PB5 13 | | 28 PA5 + PB6 14 | | 27 PA6 + PB7 15 | | 26 PA7 + PCLK 16 | | 25 _INTACK + IEI 17 | | 24 _INT + IEO 18 | | 23 +5 V + PC0 19 | | 22 PC3 + PC1 20 |_____________| 21 PC2 + + _____ _____ D4 1 |* \_/ | 40 D3 D5 2 | | 39 D2 D6 3 | | 38 D1 @@ -69,27 +91,19 @@ // TYPE DEFINITIONS //************************************************************************** -// ======================> z8536_device +// ======================> cio_base_device -class z8536_device : public device_t, - public device_z80daisy_interface +class cio_base_device : public device_t { public: - // construction/destruction - z8536_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - template <class Object> static devcb_base &set_irq_wr_callback(device_t &device, Object &&cb) { return downcast<z8536_device &>(device).m_write_irq.set_callback(std::forward<Object>(cb)); } - template <class Object> static devcb_base &set_pa_rd_callback(device_t &device, Object &&cb) { return downcast<z8536_device &>(device).m_read_pa.set_callback(std::forward<Object>(cb)); } - template <class Object> static devcb_base &set_pa_wr_callback(device_t &device, Object &&cb) { return downcast<z8536_device &>(device).m_write_pa.set_callback(std::forward<Object>(cb)); } - template <class Object> static devcb_base &set_pb_rd_callback(device_t &device, Object &&cb) { return downcast<z8536_device &>(device).m_read_pb.set_callback(std::forward<Object>(cb)); } - template <class Object> static devcb_base &set_pb_wr_callback(device_t &device, Object &&cb) { return downcast<z8536_device &>(device).m_write_pb.set_callback(std::forward<Object>(cb)); } - template <class Object> static devcb_base &set_pc_rd_callback(device_t &device, Object &&cb) { return downcast<z8536_device &>(device).m_read_pc.set_callback(std::forward<Object>(cb)); } - template <class Object> static devcb_base &set_pc_wr_callback(device_t &device, Object &&cb) { return downcast<z8536_device &>(device).m_write_pc.set_callback(std::forward<Object>(cb)); } - - DECLARE_READ8_MEMBER( read ); - DECLARE_WRITE8_MEMBER( write ); - - int intack_r(); + template <class Object> static devcb_base &set_irq_wr_callback(device_t &device, Object &&cb) { return downcast<cio_base_device &>(device).m_write_irq.set_callback(std::forward<Object>(cb)); } + template <class Object> static devcb_base &set_pa_rd_callback(device_t &device, Object &&cb) { return downcast<cio_base_device &>(device).m_read_pa.set_callback(std::forward<Object>(cb)); } + template <class Object> static devcb_base &set_pa_wr_callback(device_t &device, Object &&cb) { return downcast<cio_base_device &>(device).m_write_pa.set_callback(std::forward<Object>(cb)); } + template <class Object> static devcb_base &set_pb_rd_callback(device_t &device, Object &&cb) { return downcast<cio_base_device &>(device).m_read_pb.set_callback(std::forward<Object>(cb)); } + template <class Object> static devcb_base &set_pb_wr_callback(device_t &device, Object &&cb) { return downcast<cio_base_device &>(device).m_write_pb.set_callback(std::forward<Object>(cb)); } + template <class Object> static devcb_base &set_pc_rd_callback(device_t &device, Object &&cb) { return downcast<cio_base_device &>(device).m_read_pc.set_callback(std::forward<Object>(cb)); } + template <class Object> static devcb_base &set_pc_wr_callback(device_t &device, Object &&cb) { return downcast<cio_base_device &>(device).m_write_pc.set_callback(std::forward<Object>(cb)); } DECLARE_WRITE_LINE_MEMBER( pa0_w ) { external_port_w(PORT_A, 0, state); } DECLARE_WRITE_LINE_MEMBER( pa1_w ) { external_port_w(PORT_A, 1, state); } @@ -114,18 +128,19 @@ public: DECLARE_WRITE_LINE_MEMBER( pc2_w ) { external_port_w(PORT_C, 2, state); } DECLARE_WRITE_LINE_MEMBER( pc3_w ) { external_port_w(PORT_C, 3, state); } + int intack_r(); + protected: + // construction/destruction + cio_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t 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; - // device_z80daisy_interface overrides - virtual int z80daisy_irq_state() override; - virtual int z80daisy_irq_ack() override; - virtual void z80daisy_irq_reti() override; + bool is_reset() const { return (m_register[MASTER_INTERRUPT_CONTROL] & MICR_RESET) != 0; } -private: enum { TIMER_1 = 0, @@ -133,15 +148,6 @@ private: TIMER_3 }; - // states - enum - { - STATE_RESET = -1, - STATE_0, - STATE_1 - }; - - // ports enum { @@ -155,7 +161,7 @@ private: // registers enum { - MASTER_INTERRUPT_CONTROL = 0, + MASTER_INTERRUPT_CONTROL = 0x00, MASTER_CONFIGURATION_CONTROL, PORT_A_INTERRUPT_VECTOR, PORT_B_INTERRUPT_VECTOR, @@ -171,7 +177,7 @@ private: PORT_A_DATA, PORT_B_DATA, PORT_C_DATA, - COUNTER_TIMER_1_CURRENT_COUNT_MS_BYTE, + COUNTER_TIMER_1_CURRENT_COUNT_MS_BYTE = 0x10, COUNTER_TIMER_1_CURRENT_COUNT_LS_BYTE, COUNTER_TIMER_2_CURRENT_COUNT_MS_BYTE, COUNTER_TIMER_2_CURRENT_COUNT_LS_BYTE, @@ -187,7 +193,7 @@ private: COUNTER_TIMER_2_MODE_SPECIFICATION, COUNTER_TIMER_3_MODE_SPECIFICATION, CURRENT_VECTOR, - PORT_A_MODE_SPECIFICATION, + PORT_A_MODE_SPECIFICATION = 0x20, PORT_A_HANDSHAKE_SPECIFICATION, PORT_A_DATA_PATH_POLARITY, PORT_A_DATA_DIRECTION, @@ -206,6 +212,96 @@ private: }; + // master interrupt control register + enum + { + MICR_RESET = 0x01, // reset + MICR_RJA = 0x02, // right justified address + MICR_CT_VIS = 0x04, // counter/timer vector includes status + MICR_PB_VIS = 0x08, // port B vector includes status + MICR_PA_VIS = 0x10, // port A vector includes status + MICR_NV = 0x20, // no vector + MICR_DLC = 0x40, // disable lower chain + MICR_MIE = 0x80 // master interrupt enable + }; + + + // master configuration control register + enum + { + MCCR_LC_MASK = 0x03, // counter/timer link controls + MCCR_PAE = 0x04, // port A enable + MCCR_PLC = 0x08, // port link control + MCCR_PCE_CT3E = 0x10, // port C and counter/timer 3 enable + MCCR_CT2E = 0x20, // counter/timer 2 enable + MCCR_CT1E = 0x40, // counter/timer 1 enable + MCCR_PBE = 0x80 // port B enable + }; + + + // port mode specification registers + enum + { + PMS_LPM = 0x01, // latch on pattern match + PMS_DTE = 0x01, // deskew timer enable + PMS_PMS_MASK = 0x06, // pattern mode specification + PMS_IMO = 0x08, // interrupt on match only + PMS_SB = 0x10, // single buffer + PMS_ITB = 0x20, // interrupt on two bytes + PMS_PTS_MASK = 0xc0 // port type select + }; + + + // port handshake specification registers + enum + { + PHS_DTS_MASK = 0x07, // deskew time specification + PHS_RWS_MASK = 0x38, // request/wait specification + PHS_HTS_MASK = 0xc0 // handshake type specification + }; + + + // port command and status registers + enum + { + PCS_IOE = 0x01, // interrupt on error + PCS_PMF = 0x02, // pattern match flag (read only) + PCS_IRF = 0x04, // input register full (read only) + PCS_ORE = 0x08, // output register empty (read only) + PCS_ERR = 0x10, // interrupt error (read only) + PCS_IP = 0x20, // interrupt pending + PCS_IE = 0x40, // interrupt enable + PCS_IUS = 0x80 // interrupt under service + }; + + + // counter/timer mode specification registers + enum + { + CTMS_DCS_MASK = 0x03, // output duty cycle + CTMS_REB = 0x04, // retrigger enable bit + CTMS_EDE = 0x08, // external gate enable + CTMS_ETE = 0x10, // external trigger enable + CTMS_ECE = 0x20, // external count enable + CTMS_EOE = 0x40, // external output enable + CTMS_CSC = 0x80 // continuous/single cycle + }; + + + // counter/timer command and status registers + enum + { + CTCS_CIP = 0x01, // count in progress (read only) + CTCS_TCB = 0x02, // trigger command bit (write only - read returns 0) + CTCS_GCB = 0x04, // gate command bit + CTCS_RCC = 0x08, // read counter control (read/set only - cleared by reading CCR LSB) + CTCS_ERR = 0x10, // interrupt error (read only) + CTCS_IP = 0x20, // interrupt pending + CTCS_IE = 0x40, // interrupt enable + CTCS_IUS = 0x80 // interrupt under service + }; + + // interrupt control enum { @@ -313,6 +409,7 @@ private: void match_pattern(int port); void external_port_w(int port, int bit, int state); +private: devcb_write_line m_write_irq; devcb_read8 m_read_pa; @@ -328,9 +425,7 @@ private: int m_irq; // register state - int m_state; uint8_t m_register[48]; - uint8_t m_pointer; // input/output port state uint8_t m_input[3]; @@ -343,8 +438,48 @@ private: uint16_t m_counter[3]; }; +// ======================> z8036_device + +class z8036_device : public cio_base_device +{ +public: + // construction/destruction + z8036_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); +}; + +// ======================> z8536_device + +class z8536_device : public cio_base_device, public device_z80daisy_interface +{ +public: + // construction/destruction + z8536_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + DECLARE_READ8_MEMBER( read ); + DECLARE_WRITE8_MEMBER( write ); + +protected: + // device-level overrides + virtual void device_start() override; + virtual void device_reset() override; + + // device_z80daisy_interface overrides + virtual int z80daisy_irq_state() override; + virtual int z80daisy_irq_ack() override; + virtual void z80daisy_irq_reti() override; + +private: + // control state machine + bool m_state0; + uint8_t m_pointer; +}; + // device type definition +DECLARE_DEVICE_TYPE(Z8036, z8036_device) DECLARE_DEVICE_TYPE(Z8536, z8536_device) #endif // MAME_MACHINE_Z8536_H diff --git a/src/mame/drivers/c900.cpp b/src/mame/drivers/c900.cpp index 18b3dc19cf5..e86e6660353 100644 --- a/src/mame/drivers/c900.cpp +++ b/src/mame/drivers/c900.cpp @@ -30,6 +30,7 @@ into the weeds (jumps to 00000). //#include "machine/z80scc.h" //#include "bus/rs232/rs232.h" #include "machine/terminal.h" +#include "machine/z8536.h" class c900_state : public driver_device @@ -41,7 +42,6 @@ public: , m_terminal(*this, "terminal") { } - DECLARE_READ16_MEMBER(port1e_r); DECLARE_READ16_MEMBER(key_r); DECLARE_READ16_MEMBER(stat_r); void kbd_put(u8 data); @@ -62,10 +62,8 @@ static ADDRESS_MAP_START(data_map, AS_DATA, 16, c900_state) ADDRESS_MAP_END static ADDRESS_MAP_START(io_map, AS_IO, 16, c900_state) + AM_RANGE(0x0000, 0x007f) AM_DEVREADWRITE8("cio", z8036_device, read, write, 0x00ff) //AM_RANGE(0x0100, 0x011f) AM_DEVREADWRITE8("scc", scc8030_device, zbus_r, zbus_w, 0x00ff) // range for one channel - AM_RANGE(0x0010, 0x0011) AM_READ(stat_r) - AM_RANGE(0x001A, 0x001B) AM_READ(key_r) - AM_RANGE(0x001E, 0x001F) AM_READ(port1e_r) AM_RANGE(0x0100, 0x0101) AM_READ(stat_r) AM_RANGE(0x0110, 0x0111) AM_READ(key_r) AM_DEVWRITE8("terminal", generic_terminal_device, write, 0x00ff) ADDRESS_MAP_END @@ -73,11 +71,6 @@ ADDRESS_MAP_END static INPUT_PORTS_START( c900 ) INPUT_PORTS_END -READ16_MEMBER( c900_state::port1e_r ) -{ - return 0; -} - READ16_MEMBER( c900_state::key_r ) { uint8_t ret = m_term_data; @@ -125,6 +118,8 @@ static MACHINE_CONFIG_START( c900 ) MCFG_GFXDECODE_ADD("gfxdecode", "palette", c900) MCFG_PALETTE_ADD_MONOCHROME("palette") + MCFG_DEVICE_ADD("cio", Z8036, 6'000'000) + //MCFG_SCC8030_ADD("scc", 6'000'000, 326400, 0, 326400, 0) /* Port A */ //MCFG_Z80SCC_OUT_TXDA_CB(DEVWRITELINE("rs232a", rs232_port_device, write_txd)) |