summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/machine/z8536.c
diff options
context:
space:
mode:
author Miodrag Milanovic <mmicko@gmail.com>2015-09-13 08:41:44 +0200
committer Miodrag Milanovic <mmicko@gmail.com>2015-09-13 08:41:44 +0200
commitf88cefad27a1737c76e09d99c9fb43e173506081 (patch)
tree2d8167d03579c46e226471747eb4407bd00ed6fa /src/emu/machine/z8536.c
parente92ac9e0fa8e99869894bea00589bbb526be30aa (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.c1123
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;
-}