diff options
author | 2015-09-13 08:41:44 +0200 | |
---|---|---|
committer | 2015-09-13 08:41:44 +0200 | |
commit | f88cefad27a1737c76e09d99c9fb43e173506081 (patch) | |
tree | 2d8167d03579c46e226471747eb4407bd00ed6fa /src/emu/machine/z8536.c | |
parent | e92ac9e0fa8e99869894bea00589bbb526be30aa (diff) |
Move all devices into separate part of src tree (nw)
Diffstat (limited to 'src/emu/machine/z8536.c')
-rw-r--r-- | src/emu/machine/z8536.c | 1123 |
1 files changed, 0 insertions, 1123 deletions
diff --git a/src/emu/machine/z8536.c b/src/emu/machine/z8536.c deleted file mode 100644 index fc5e770b15a..00000000000 --- a/src/emu/machine/z8536.c +++ /dev/null @@ -1,1123 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Curt Coder -/********************************************************************** - - Zilog Z8536 Counter/Timer and Parallel I/O emulation - -**********************************************************************/ - -/* - - TODO: - - - interrupts - - vector - - status affects vector - - IE/IP/IUS - - acknowledge - - daisy chain - - port I/O - - counters/timers - -*/ - -#include "emu.h" -#include "z8536.h" - - -// device type definition -const device_type Z8536 = &device_creator<z8536_device>; - - -//************************************************************************** -// MACROS / CONSTANTS -//************************************************************************** - -#define LOG 0 - - -static const char *PMS_PTS[] = { "Bit", "Input", "Output", "Bidirectional" }; -static const char *PMS_PMS[] = { "Disabled", "AND", "OR", "OR-PEV" }; -static const char *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 -//************************************************************************** - -//------------------------------------------------- -// get_interrupt_vector - -//------------------------------------------------- - -void z8536_device::get_interrupt_vector() -{ - UINT8 vector = 0xff; - - if (m_register[MASTER_INTERRUPT_CONTROL] & MICR_MIE) - { - if ((m_register[COUNTER_TIMER_3_COMMAND_AND_STATUS] & (CTCS_IP | CTCS_IE | CTCS_IUS)) == (CTCS_IP | CTCS_IE)) - { - vector = m_register[COUNTER_TIMER_INTERRUPT_VECTOR]; - - if (m_register[MASTER_INTERRUPT_CONTROL] & MICR_CT_VIS) - { - vector = (vector & 0xf9) | 0; - } - } - else if ((m_register[PORT_A_COMMAND_AND_STATUS] & (PCS_IP | PCS_IE | PCS_IUS)) == (PCS_IP | PCS_IE)) - { - vector = m_register[PORT_A_INTERRUPT_VECTOR]; - - if (m_register[MASTER_INTERRUPT_CONTROL] & MICR_PA_VIS) - { - vector &= 0xf1; - - if (((m_register[PORT_A_MODE_SPECIFICATION] & PMS_PMS_MASK) >> 1) == PMS_OR_PEV) - { - if (m_match[PORT_A] & 0x80) vector |= 7 << 1; - else if (m_match[PORT_A] & 0x40) vector |= 6 << 1; - else if (m_match[PORT_A] & 0x20) vector |= 5 << 1; - else if (m_match[PORT_A] & 0x10) vector |= 4 << 1; - else if (m_match[PORT_A] & 0x08) vector |= 3 << 1; - else if (m_match[PORT_A] & 0x04) vector |= 2 << 1; - else if (m_match[PORT_A] & 0x02) vector |= 1 << 1; - else if (m_match[PORT_A] & 0x01) vector |= 0 << 1; - } - else - { - vector |= (m_register[PORT_A_COMMAND_AND_STATUS] & 0x0e); - } - } - } - else if ((m_register[COUNTER_TIMER_2_COMMAND_AND_STATUS] & (CTCS_IP | CTCS_IE | CTCS_IUS)) == (CTCS_IP | CTCS_IE)) - { - vector = m_register[COUNTER_TIMER_INTERRUPT_VECTOR]; - - if (m_register[MASTER_INTERRUPT_CONTROL] & MICR_CT_VIS) - { - vector = (vector & 0xf9) | 2; - } - } - else if ((m_register[PORT_B_COMMAND_AND_STATUS] & (PCS_IP | PCS_IE | PCS_IUS)) == (PCS_IP | PCS_IE)) - { - vector = m_register[PORT_B_INTERRUPT_VECTOR]; - - if (m_register[MASTER_INTERRUPT_CONTROL] & MICR_PB_VIS) - { - vector &= 0xf1; - - if (((m_register[PORT_B_MODE_SPECIFICATION] & PMS_PMS_MASK) >> 1) == PMS_OR_PEV) - { - if (m_match[PORT_B] & 0x80) vector |= 7 << 1; - else if (m_match[PORT_B] & 0x40) vector |= 6 << 1; - else if (m_match[PORT_B] & 0x20) vector |= 5 << 1; - else if (m_match[PORT_B] & 0x10) vector |= 4 << 1; - else if (m_match[PORT_B] & 0x08) vector |= 3 << 1; - else if (m_match[PORT_B] & 0x04) vector |= 2 << 1; - else if (m_match[PORT_B] & 0x02) vector |= 1 << 1; - else if (m_match[PORT_B] & 0x01) vector |= 0 << 1; - } - else - { - vector |= (m_register[PORT_B_COMMAND_AND_STATUS] & 0x0e); - } - } - } - else if ((m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS] & (CTCS_IP | CTCS_IE | CTCS_IUS)) == (CTCS_IP | CTCS_IE)) - { - vector = m_register[COUNTER_TIMER_INTERRUPT_VECTOR]; - - if (m_register[MASTER_INTERRUPT_CONTROL] & MICR_CT_VIS) - { - vector = (vector & 0xf9) | 4; - } - } - } - - m_register[CURRENT_VECTOR] = vector; -} - - -//------------------------------------------------- -// check_interrupt - check interrupt status -//------------------------------------------------- - -void z8536_device::check_interrupt() -{ - int state = ASSERT_LINE; - - if (m_register[MASTER_INTERRUPT_CONTROL] & MICR_MIE) - { - if (((m_register[COUNTER_TIMER_3_COMMAND_AND_STATUS] & (CTCS_IP | CTCS_IE | CTCS_IUS)) == (CTCS_IP | CTCS_IE)) || - ((m_register[PORT_A_COMMAND_AND_STATUS] & (PCS_IP | PCS_IE | PCS_IUS)) == (PCS_IP | PCS_IE)) || - ((m_register[COUNTER_TIMER_2_COMMAND_AND_STATUS] & (CTCS_IP | CTCS_IE | CTCS_IUS)) == (CTCS_IP | CTCS_IE)) || - ((m_register[PORT_B_COMMAND_AND_STATUS] & (PCS_IP | PCS_IE | PCS_IUS)) == (PCS_IP | PCS_IE)) || - ((m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS] & (CTCS_IP | CTCS_IE | CTCS_IUS)) == (CTCS_IP | CTCS_IE))) - { - state = ASSERT_LINE; - } - else - { - state = CLEAR_LINE; - } - } - else - { - state = CLEAR_LINE; - } - - if (m_irq != state) - { - if (LOG) logerror("%s Z8536 '%s' Interrupt: %u\n", machine().describe_context(), tag(), state); - m_irq = state; - m_write_irq(state); - } -} - - -//------------------------------------------------- -// read_register - read from register -//------------------------------------------------- - -UINT8 z8536_device::read_register(offs_t offset) -{ - UINT8 data = 0; - - switch (offset) - { - case PORT_A_DATA: - data = m_read_pa(0); - break; - - case PORT_B_DATA: - data = m_read_pb(0); - break; - - case PORT_C_DATA: - data = 0xf0 | (m_read_pc(0) & 0x0f); - break; - - case COUNTER_TIMER_1_CURRENT_COUNT_MS_BYTE: - case COUNTER_TIMER_2_CURRENT_COUNT_MS_BYTE: - case COUNTER_TIMER_3_CURRENT_COUNT_MS_BYTE: - { - int timer = (offset - COUNTER_TIMER_1_CURRENT_COUNT_MS_BYTE) >> 1; - - if (m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + timer] & CTCS_RCC) - { - // read frozen value - data = m_register[offset]; - } - else - { - // read current count - data = m_counter[timer] >> 8; - } - } - break; - - case COUNTER_TIMER_1_CURRENT_COUNT_LS_BYTE: - case COUNTER_TIMER_2_CURRENT_COUNT_LS_BYTE: - case COUNTER_TIMER_3_CURRENT_COUNT_LS_BYTE: - { - int timer = (offset - COUNTER_TIMER_1_CURRENT_COUNT_MS_BYTE) >> 1; - - if (m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + timer] & CTCS_RCC) - { - // read frozen value - data = m_register[offset]; - } - else - { - // read current count - data = m_counter[timer] & 0xff; - } - - // clear RCC bit - m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + timer] &= ~CTCS_RCC; - } - break; - - case CURRENT_VECTOR: - get_interrupt_vector(); - data = m_register[offset]; - break; - - default: - data = m_register[offset]; - break; - } - - return data; -} - - -//------------------------------------------------- -// read_register - masked read from register -//------------------------------------------------- - -UINT8 z8536_device::read_register(offs_t offset, UINT8 mask) -{ - return read_register(offset) & mask; -} - - -//------------------------------------------------- -// write_register - write to register -//------------------------------------------------- - -void z8536_device::write_register(offs_t offset, UINT8 data) -{ - switch (offset) - { - case MASTER_INTERRUPT_CONTROL: - if (data & MICR_RESET) - { - if (LOG) logerror("%s Z8536 '%s' Reset\n", machine().describe_context(), tag()); - device_reset(); - } - else - { - if (m_state == STATE_RESET) - { - m_state = STATE_0; - } - - if (LOG) - { - if (LOG) logerror("%s Z8536 '%s' Master Interrupt Enable: %u\n", machine().describe_context(), tag(), (data & MICR_MIE) ? 1 : 0); - if (LOG) logerror("%s Z8536 '%s' Disable Lower Chain: %u\n", machine().describe_context(), tag(), (data & MICR_DLC) ? 1 : 0); - if (LOG) logerror("%s Z8536 '%s' No Vector: %u\n", machine().describe_context(), tag(), (data & MICR_NV) ? 1 : 0); - if (LOG) logerror("%s Z8536 '%s' Port A Vector Includes Status: %u\n", machine().describe_context(), tag(), (data & MICR_PA_VIS) ? 1 : 0); - if (LOG) logerror("%s Z8536 '%s' Port B Vector Includes Status: %u\n", machine().describe_context(), tag(), (data & MICR_PB_VIS) ? 1 : 0); - if (LOG) logerror("%s Z8536 '%s' Counter/Timer Vector Includes Status: %u\n", machine().describe_context(), tag(), (data & MICR_CT_VIS) ? 1 : 0); - if (LOG) logerror("%s Z8536 '%s' Right Justified Address: %u\n", machine().describe_context(), tag(), (data & MICR_RJA) ? 1 : 0); - } - - m_register[offset] = data; - } - break; - - case MASTER_CONFIGURATION_CONTROL: - if (LOG) - { - if (LOG) logerror("%s Z8536 '%s' Port B Enable: %u\n", machine().describe_context(), tag(), (data & MCCR_PBE) ? 1 : 0); - if (LOG) logerror("%s Z8536 '%s' Counter/Timer 1 Enable: %u\n", machine().describe_context(), tag(), (data & MCCR_CT1E) ? 1 : 0); - if (LOG) logerror("%s Z8536 '%s' Counter/Timer 2 Enable: %u\n", machine().describe_context(), tag(), (data & MCCR_CT2E) ? 1 : 0); - if (LOG) logerror("%s Z8536 '%s' Port C and Counter/Timer 3 Enable: %u\n", machine().describe_context(), tag(), (data & MCCR_PCE_CT3E) ? 1 : 0); - if (LOG) logerror("%s Z8536 '%s' Port A Enable: %u\n", machine().describe_context(), tag(), (data & MCCR_PAE) ? 1 : 0); - if (LOG) logerror("%s Z8536 '%s' Port Link Control: %u\n", machine().describe_context(), tag(), (data & MCCR_PLC) ? 1 : 0); - if (LOG) logerror("%s Z8536 '%s' Counter/Timer Link Controls: %u\n", machine().describe_context(), tag(), data & MCCR_LC_MASK); - } - - m_register[offset] = data; - - for (int counter = 0; counter < 3; counter++) - { - // clear RCC bit if counter disabled - if (!counter_enabled(counter)) m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + counter] &= ~CTCS_RCC; - } - break; - - case PORT_A_INTERRUPT_VECTOR: - if (LOG) logerror("%s Z8536 '%s' Port A Interrupt Vector: %02x\n", machine().describe_context(), tag(), data); - m_register[offset] = data; - break; - - case PORT_B_INTERRUPT_VECTOR: - if (LOG) logerror("%s Z8536 '%s' Port B Interrupt Vector: %02x\n", machine().describe_context(), tag(), data); - m_register[offset] = data; - break; - - case COUNTER_TIMER_INTERRUPT_VECTOR: - if (LOG) logerror("%s Z8536 '%s' Counter/Timer Interrupt Vector: %02x\n", machine().describe_context(), tag(), data); - m_register[offset] = data; - break; - - case PORT_C_DATA_PATH_POLARITY: - if (LOG) logerror("%s Z8536 '%s' Port C Data Path Polarity: %02x\n", machine().describe_context(), tag(), data); - m_register[offset] = data; - break; - - case PORT_C_DATA_DIRECTION: - if (LOG) logerror("%s Z8536 '%s' Port C Data Direction: %02x\n", machine().describe_context(), tag(), data); - m_register[offset] = data; - break; - - case PORT_C_SPECIAL_IO_CONTROL: - if (LOG) logerror("%s Z8536 '%s' Port C Special I/O Control: %02x\n", machine().describe_context(), tag(), data); - m_register[offset] = data; - break; - - case PORT_A_COMMAND_AND_STATUS: - case PORT_B_COMMAND_AND_STATUS: - { - char port = 'A' + offset - PORT_A_COMMAND_AND_STATUS; - - if (LOG) logerror("%s Z8536 '%s' Port %c Interrupt on Error: %u\n", machine().describe_context(), tag(), port, (data & PCS_IOE) ? 1 : 0); - - switch (data >> 5) - { - case IC_CLEAR_IP_IUS: m_register[offset] &= ~(PCS_IP | PCS_IUS); if (LOG) logerror("%s Z8536 '%s' Port %c Clear IP/IUS\n", machine().describe_context(), tag(), port); break; - case IC_SET_IUS: m_register[offset] |= PCS_IUS; if (LOG) logerror("%s Z8536 '%s' Port %c Set IUS\n", machine().describe_context(), tag(), port); break; - case IC_CLEAR_IUS: m_register[offset] &= ~PCS_IUS; if (LOG) logerror("%s Z8536 '%s' Port %c Clear IUS\n", machine().describe_context(), tag(), port); break; - case IC_SET_IP: m_register[offset] |= PCS_IP; if (LOG) logerror("%s Z8536 '%s' Port %c Set IP\n", machine().describe_context(), tag(), port); break; - case IC_CLEAR_IP: m_register[offset] &= ~PCS_IP; if (LOG) logerror("%s Z8536 '%s' Port %c Clear IP\n", machine().describe_context(), tag(), port); break; - case IC_SET_IE: m_register[offset] |= PCS_IE; if (LOG) logerror("%s Z8536 '%s' Port %c Set IE\n", machine().describe_context(), tag(), port); break; - case IC_CLEAR_IE: m_register[offset] &= ~PCS_IE; if (LOG) logerror("%s Z8536 '%s' Port %c Clear IE\n", machine().describe_context(), tag(), port); break; - } - - m_register[offset] = (m_register[offset] & ~PCS_IOE) | (data & PCS_IOE); - - match_pattern(offset - PORT_A_COMMAND_AND_STATUS); - check_interrupt(); - } - break; - - case COUNTER_TIMER_1_COMMAND_AND_STATUS: - case COUNTER_TIMER_2_COMMAND_AND_STATUS: - case COUNTER_TIMER_3_COMMAND_AND_STATUS: - { - int counter = offset - COUNTER_TIMER_1_COMMAND_AND_STATUS; - - if (LOG) - { - if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Trigger Command Bit: %u\n", machine().describe_context(), tag(), counter + 1, (data & CTCS_TCB) ? 1 : 0); - if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Gate Command Bit: %u\n", machine().describe_context(), tag(), counter + 1, (data & CTCS_GCB) ? 1 : 0); - if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Read Counter Control: %u\n", machine().describe_context(), tag(), counter + 1, (data & CTCS_RCC) ? 1 : 0); - } - - switch (data >> 5) - { - case IC_CLEAR_IP_IUS: m_register[offset] &= ~(CTCS_IP | CTCS_IUS);if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Clear IP/IUS\n", machine().describe_context(), tag(), counter + 1); break; - case IC_SET_IUS: m_register[offset] |= CTCS_IUS; if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Set IUS\n", machine().describe_context(), tag(), counter + 1); break; - case IC_CLEAR_IUS: m_register[offset] &= ~CTCS_IUS; if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Clear IUS\n", machine().describe_context(), tag(), counter + 1); break; - case IC_SET_IP: m_register[offset] |= CTCS_IP; if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Set IP\n", machine().describe_context(), tag(), counter + 1); break; - case IC_CLEAR_IP: m_register[offset] &= ~CTCS_IP; if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Clear IP\n", machine().describe_context(), tag(), counter + 1); break; - case IC_SET_IE: m_register[offset] |= CTCS_IE; if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Set IE\n", machine().describe_context(), tag(), counter + 1); break; - case IC_CLEAR_IE: m_register[offset] &= ~CTCS_IE; if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Clear IE\n", machine().describe_context(), tag(), counter + 1); break; - } - - // gate command bit - m_register[offset] = (m_register[offset] & ~CTCS_GCB) | (data & CTCS_GCB); - - // trigger command bit - if (data & CTCS_TCB) - { - trigger(counter); - } - - // read counter control - if (counter_enabled(counter) && (data & CTCS_RCC)) - { - // freeze current count register - m_register[offset] |= CTCS_RCC; - m_register[COUNTER_TIMER_1_CURRENT_COUNT_MS_BYTE + (counter << 1)] = m_counter[counter] >> 8; - m_register[COUNTER_TIMER_1_CURRENT_COUNT_LS_BYTE + (counter << 1)] = m_counter[counter] & 0xff; - } - - check_interrupt(); - } - break; - - case PORT_A_DATA: - m_write_pa((offs_t)0, data); - break; - - case PORT_B_DATA: - m_write_pb((offs_t)0, data); - break; - - case PORT_C_DATA: - { - UINT8 mask = (data & 0xf0) | (data >> 4); - - m_output[PORT_C] = (m_output[PORT_C] & mask) | ((data & 0x0f) & (mask ^ 0xff)); - - m_write_pc((offs_t)0, m_output[PORT_C]); - } - break; - - case COUNTER_TIMER_1_TIME_CONSTANT_MS_BYTE: - case COUNTER_TIMER_2_TIME_CONSTANT_MS_BYTE: - case COUNTER_TIMER_3_TIME_CONSTANT_MS_BYTE: - if (LOG) - { - int counter = (offset - COUNTER_TIMER_1_TIME_CONSTANT_MS_BYTE) >> 1; - if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Time Constant MSB: %02x\n", machine().describe_context(), tag(), counter + 1, data); - } - - m_register[offset] = data; - break; - - case COUNTER_TIMER_1_TIME_CONSTANT_LS_BYTE: - case COUNTER_TIMER_2_TIME_CONSTANT_LS_BYTE: - case COUNTER_TIMER_3_TIME_CONSTANT_LS_BYTE: - if (LOG) - { - int counter = (offset - COUNTER_TIMER_1_TIME_CONSTANT_LS_BYTE) >> 1; - if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Time Constant LSB: %02x\n", machine().describe_context(), tag(), counter + 1, data); - } - - m_register[offset] = data; - break; - - case COUNTER_TIMER_1_MODE_SPECIFICATION: - case COUNTER_TIMER_2_MODE_SPECIFICATION: - case COUNTER_TIMER_3_MODE_SPECIFICATION: - if (LOG) - { - int counter = offset - COUNTER_TIMER_1_MODE_SPECIFICATION; - int dcs = data & CTMS_DCS_MASK; - - logerror("%s Z8536 '%s' Counter/Timer %u Mode: %s\n", machine().describe_context(), tag(), counter + 1, (data & CTMS_CSC) ? "Continuous" : "Single Cycle"); - logerror("%s Z8536 '%s' Counter/Timer %u External Output Enable: %u\n", machine().describe_context(), tag(), counter + 1, (data & CTMS_EOE) ? 1 : 0); - logerror("%s Z8536 '%s' Counter/Timer %u External Count Enable: %u\n", machine().describe_context(), tag(), counter + 1, (data & CTMS_ECE) ? 1 : 0); - logerror("%s Z8536 '%s' Counter/Timer %u External Trigger Enable: %u\n", machine().describe_context(), tag(), counter + 1, (data & CTMS_ETE) ? 1 : 0); - logerror("%s Z8536 '%s' Counter/Timer %u External Gate Enable: %u\n", machine().describe_context(), tag(), counter + 1, (data & CTMS_EDE) ? 1 : 0); - logerror("%s Z8536 '%s' Counter/Timer %u Retrigger Enable: %u\n", machine().describe_context(), tag(), counter + 1, (data & CTMS_REB) ? 1 : 0); - logerror("%s Z8536 '%s' Counter/Timer %u Output Duty Cycle: %s\n", machine().describe_context(), tag(), counter + 1, CTMS_DCS[dcs]); - } - - m_register[offset] = data; - break; - - case PORT_A_MODE_SPECIFICATION: - case PORT_B_MODE_SPECIFICATION: - if (LOG) - { - char port = BIT(offset, 3) ? 'B' : 'A'; - int pts = (data & PMS_PTS_MASK) >> 6; - int pms = (data & PMS_PMS_MASK) >> 1; - - logerror("%s Z8536 '%s' Port %c Port Type: %s\n", machine().describe_context(), tag(), port, PMS_PTS[pts]); - logerror("%s Z8536 '%s' Port %c Interrupt on 2 Bytes: %u\n", machine().describe_context(), tag(), port, (data & PMS_ITB) ? 1 : 0); - logerror("%s Z8536 '%s' Port %c Single Buffer: %u\n", machine().describe_context(), tag(), port, (data & PMS_SB) ? 1 : 0); - logerror("%s Z8536 '%s' Port %c Interrupt on Match Only: %u\n", machine().describe_context(), tag(), port, (data & PMS_IMO) ? 1 : 0); - logerror("%s Z8536 '%s' Port %c Pattern Mode: %s\n", machine().describe_context(), tag(), port, PMS_PMS[pms]); - - if (pts == PTS_BIT) - logerror("%s Z8536 '%s' Port %c Latch on Pattern Match: %u\n", machine().describe_context(), tag(), port, (data & PMS_LPM) ? 1 : 0); - else - logerror("%s Z8536 '%s' Port %c Deskew Timer Enable: %u\n", machine().describe_context(), tag(), port, (data & PMS_DTE) ? 1 : 0); - } - - m_register[offset] = data; - break; - - case PORT_A_HANDSHAKE_SPECIFICATION: - case PORT_B_HANDSHAKE_SPECIFICATION: - // TODO - break; - - case PORT_A_DATA_PATH_POLARITY: - case PORT_B_DATA_PATH_POLARITY: - if (LOG) logerror("%s Z8536 '%s' Port %c Data Path Polarity: %02x\n", machine().describe_context(), tag(), BIT(offset, 3) ? 'B' : 'A', data); - m_register[offset] = data; - break; - - case PORT_A_DATA_DIRECTION: - case PORT_B_DATA_DIRECTION: - if (LOG) logerror("%s Z8536 '%s' Port %c Data Direction: %02x\n", machine().describe_context(), tag(), BIT(offset, 3) ? 'B' : 'A', data); - m_register[offset] = data; - break; - - case PORT_A_SPECIAL_IO_CONTROL: - case PORT_B_SPECIAL_IO_CONTROL: - if (LOG) logerror("%s Z8536 '%s' Port %c Special I/O Control: %02x\n", machine().describe_context(), tag(), BIT(offset, 3) ? 'B' : 'A', data); - m_register[offset] = data; - break; - - case PORT_A_PATTERN_POLARITY: - case PORT_B_PATTERN_POLARITY: - if (LOG) logerror("%s Z8536 '%s' Port %c Pattern Polarity: %02x\n", machine().describe_context(), tag(), BIT(offset, 3) ? 'B' : 'A', data); - m_register[offset] = data; - break; - - case PORT_A_PATTERN_TRANSITION: - case PORT_B_PATTERN_TRANSITION: - if (LOG) logerror("%s Z8536 '%s' Port %c Pattern Transition: %02x\n", machine().describe_context(), tag(), BIT(offset, 3) ? 'B' : 'A', data); - m_register[offset] = data; - break; - - case PORT_A_PATTERN_MASK: - case PORT_B_PATTERN_MASK: - if (LOG) logerror("%s Z8536 '%s' Port %c Pattern Mask: %02x\n", machine().describe_context(), tag(), BIT(offset, 3) ? 'B' : 'A', data); - m_register[offset] = data; - match_pattern(BIT(offset, 3)); - check_interrupt(); - break; - - default: - logerror("%s: Z8536 '%s' Unimplemented write %02x to register %u\n", machine().describe_context(), tag(), data, offset); - m_register[offset] = data; - } -} - - -//------------------------------------------------- -// write_register - masked write to register -//------------------------------------------------- - -void z8536_device::write_register(offs_t offset, UINT8 data, UINT8 mask) -{ - UINT8 combined_data = (data & mask) | (m_register[offset] & (mask ^ 0xff)); - - write_register(offset, combined_data); -} - - -//------------------------------------------------- -// counter_enabled - is counter enabled? -//------------------------------------------------- - -bool z8536_device::counter_enabled(device_timer_id id) -{ - bool enabled = false; - - switch (id) - { - case TIMER_1: - enabled = (m_register[MASTER_CONFIGURATION_CONTROL] & MCCR_CT1E) ? true : false; - break; - - case TIMER_2: - enabled = (m_register[MASTER_CONFIGURATION_CONTROL] & MCCR_CT2E) ? true : false; - break; - - case TIMER_3: - enabled = (m_register[MASTER_CONFIGURATION_CONTROL] & MCCR_PCE_CT3E) ? true : false; - break; - } - - return enabled; -} - - -//------------------------------------------------- -// counter_external_output - -//------------------------------------------------- - -bool z8536_device::counter_external_output(device_timer_id id) -{ - return (m_register[COUNTER_TIMER_1_MODE_SPECIFICATION + id] & CTMS_EOE) ? true : false; -} - - -//------------------------------------------------- -// counter_external_count - -//------------------------------------------------- - -bool z8536_device::counter_external_count(device_timer_id id) -{ - return (m_register[COUNTER_TIMER_1_MODE_SPECIFICATION + id] & CTMS_ECE) ? true : false; -} - - -//------------------------------------------------- -// counter_external_trigger - -//------------------------------------------------- - -bool z8536_device::counter_external_trigger(device_timer_id id) -{ - return (m_register[COUNTER_TIMER_1_MODE_SPECIFICATION + id] & CTMS_ETE) ? true : false; -} - - -//------------------------------------------------- -// counter_external_gate - -//------------------------------------------------- - -bool z8536_device::counter_external_gate(device_timer_id id) -{ - return (m_register[COUNTER_TIMER_1_MODE_SPECIFICATION + id] & CTMS_EDE) ? true : false; -} - - -//------------------------------------------------- -// counter_gated - -//------------------------------------------------- - -bool z8536_device::counter_gated(device_timer_id id) -{ - return (m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + id] & CTCS_GCB) ? true : false; -} - - -//------------------------------------------------- -// count - count down -//------------------------------------------------- - -void z8536_device::count(device_timer_id id) -{ - if (!counter_gated(id)) return; - if (!(m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + id] & CTCS_CIP)) return; - - // count down - m_counter[id]--; - - if (m_counter[id] == 0) - { - if (m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + id] & CTCS_IP) - { - // set interrupt error bit - m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + id] |= CTCS_ERR; - } - else - { - if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Interrupt Pending\n", machine().describe_context(), tag(), id + 1); - - // set interrupt pending bit - m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + id] |= CTCS_IP; - } - - if (m_register[COUNTER_TIMER_1_MODE_SPECIFICATION + id] & CTMS_CSC) - { - // reload 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)]; - } - else - { - if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Terminal Count\n", machine().describe_context(), tag(), id + 1); - - // clear count in progress bit - m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + id] &= ~CTCS_CIP; - } - - check_interrupt(); - } -} - - -//------------------------------------------------- -// trigger - -//------------------------------------------------- - -void z8536_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; - - if (LOG) logerror("%s Z8536 '%s' Counter/Timer %u Trigger\n", machine().describe_context(), tag(), 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)]; - - // set count in progress bit - m_register[COUNTER_TIMER_1_COMMAND_AND_STATUS + id] |= CTCS_CIP; -} - - -//------------------------------------------------- -// gate - -//------------------------------------------------- - -void z8536_device::gate(device_timer_id id, int state) -{ - // TODO -} - - -//------------------------------------------------- -// match_pattern - -//------------------------------------------------- - -void z8536_device::match_pattern(int port) -{ - UINT8 pms = m_register[PORT_A_MODE_SPECIFICATION + (port << 3)]; - UINT8 pm = m_register[PORT_A_PATTERN_MASK + (port << 3)]; - UINT8 ddr = m_register[PORT_A_DATA_DIRECTION + (port << 3)]; - - switch ((pms & PMS_PMS_MASK) >> 1) - { - case PMS_OR_PEV: - m_match[port] = m_input[port] & ddr & pm; - - if (m_match[port]) - { - if (LOG) logerror("%s Z8536 '%s' Port %c Interrupt Pending\n", machine().describe_context(), tag(), 'A' + port); - m_register[PORT_A_COMMAND_AND_STATUS + port] |= PCS_IP; - check_interrupt(); - } - break; - } -} - - -//------------------------------------------------- -// external_port_w - external port write -//------------------------------------------------- - -void z8536_device::external_port_w(int port, int bit, int state) -{ - switch (port) - { - case PORT_A: - case PORT_B: - { - assert((PORT_A_DATA_DIRECTION + (port << 3)) >= 0 && (PORT_A_DATA_DIRECTION + (port << 3)) < ARRAY_LENGTH(m_register)); - UINT8 ddr = m_register[PORT_A_DATA_DIRECTION + (port << 3)]; - - if (!BIT(ddr, bit)) return; - - if (LOG) logerror("%s Z8536 '%s' Port %c Bit %u: %u\n", machine().describe_context(), tag(), 'A' + port, bit, state); - - m_input[port] = (m_input[port] & ~(1 << bit)) | (state << bit); - - match_pattern(port); - } - break; - - case PORT_C: - break; - } -} - - - -//************************************************************************** -// LIVE DEVICE -//************************************************************************** - -//------------------------------------------------- -// z8536_device - constructor -//------------------------------------------------- - -z8536_device::z8536_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : - device_t(mconfig, Z8536, "Zilog Z8536", tag, owner, clock, "z8536", __FILE__), - device_z80daisy_interface(mconfig, *this), - m_write_irq(*this), - m_read_pa(*this), - m_write_pa(*this), - m_read_pb(*this), - m_write_pb(*this), - m_read_pc(*this), - m_write_pc(*this), - m_irq(CLEAR_LINE) -{ -} - - -//------------------------------------------------- -// device_start - device-specific startup -//------------------------------------------------- - -void z8536_device::device_start() -{ - for (int i = 0; i < 3; i++) - { - m_input[i] = 0; - m_output[i] = 0; - m_buffer[i] = 0; - m_match[i] = 0; - } - - // allocate timer - m_timer = timer_alloc(); - m_timer->adjust(attotime::from_hz(clock() / 2), 0, attotime::from_hz(clock() / 2)); - - // resolve callbacks - m_write_irq.resolve_safe(); - m_read_pa.resolve_safe(0); - m_write_pa.resolve_safe(); - m_read_pb.resolve_safe(0); - m_write_pb.resolve_safe(); - m_read_pc.resolve_safe(0); - m_write_pc.resolve_safe(); -} - - -//------------------------------------------------- -// device_start - device-specific reset -//------------------------------------------------- - -void z8536_device::device_reset() -{ - m_state = STATE_RESET; - - for (int i = 0; i < 48; i++) - { - m_register[i] = 0; - } - - m_register[MASTER_INTERRUPT_CONTROL] = MICR_RESET; - m_register[PORT_A_COMMAND_AND_STATUS] = PCS_ORE; - m_register[PORT_B_COMMAND_AND_STATUS] = PCS_ORE; - m_register[CURRENT_VECTOR] = 0xff; - - m_pointer = 0; - - check_interrupt(); -} - - -//------------------------------------------------- -// device_timer - handler timer events -//------------------------------------------------- - -void z8536_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) -{ - if (counter_enabled(TIMER_1) && !counter_external_count(TIMER_1)) - { - count(TIMER_1); - } - - if (counter_enabled(TIMER_2) && !counter_external_count(TIMER_2)) - { - count(TIMER_2); - } - - if (counter_enabled(TIMER_3) && !counter_external_count(TIMER_3)) - { - count(TIMER_3); - } -} - - - -//************************************************************************** -// DAISY CHAIN INTERFACE -//************************************************************************** - -//------------------------------------------------- -// z80daisy_irq_state - return the overall IRQ -// state for this device -//------------------------------------------------- - -int z8536_device::z80daisy_irq_state() -{ - return 0; -} - - -//------------------------------------------------- -// z80daisy_irq_ack - acknowledge an IRQ and -// return the appropriate vector -//------------------------------------------------- - -int z8536_device::z80daisy_irq_ack() -{ - return intack_r(); -} - - -//------------------------------------------------- -// z80daisy_irq_reti - clear the interrupt -// pending state to allow other interrupts through -//------------------------------------------------- - -void z8536_device::z80daisy_irq_reti() -{ -} - - - -//************************************************************************** -// INTERNAL STATE MANAGEMENT -//************************************************************************** - -//------------------------------------------------- -// read - register read -//------------------------------------------------- - -READ8_MEMBER( z8536_device::read ) -{ - UINT8 data = 0; - - if (m_state == STATE_RESET) - { - // read RESET bit - data = read_register(m_pointer, 0x01); - } - else - { - switch (offset & 0x03) - { - case PORT_C: - data = read_register(PORT_C_DATA); - break; - - case PORT_B: - data = read_register(PORT_B_DATA); - break; - - case PORT_A: - data = read_register(PORT_A_DATA); - break; - - case CONTROL: - switch (m_state) - { - case STATE_1: - m_state = STATE_0; - // fallthru - case STATE_0: - data = read_register(m_pointer); - break; - } - break; - } - } - - return data; -} - - -//------------------------------------------------- -// write - register write -//------------------------------------------------- - -WRITE8_MEMBER( z8536_device::write ) -{ - if (m_state == STATE_RESET) - { - // write RESET bit - write_register(m_pointer, data, 0x01); - } - else - { - switch (offset & 0x03) - { - case PORT_C: - write_register(PORT_C_DATA, data); - break; - - case PORT_B: - write_register(PORT_B_DATA, data); - break; - - case PORT_A: - write_register(PORT_A_DATA, data); - break; - - case CONTROL: - switch (m_state) - { - case STATE_0: - m_pointer = data; - m_state = STATE_1; - break; - - case STATE_1: - write_register(m_pointer, data); - m_state = STATE_0; - } - break; - } - } -} - - -//------------------------------------------------- -// intack_r - interrupt acknowledge -//------------------------------------------------- - -int z8536_device::intack_r() -{ - get_interrupt_vector(); - int data = m_register[CURRENT_VECTOR]; - - if (LOG) logerror("%s Z8536 '%s' Interrupt Acknowledge: %02x\n", machine().describe_context(), tag(), 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; -} |