summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/tmp68301.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/tmp68301.cpp')
-rw-r--r--src/devices/machine/tmp68301.cpp380
1 files changed, 0 insertions, 380 deletions
diff --git a/src/devices/machine/tmp68301.cpp b/src/devices/machine/tmp68301.cpp
deleted file mode 100644
index 75b1f070ad8..00000000000
--- a/src/devices/machine/tmp68301.cpp
+++ /dev/null
@@ -1,380 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Luca Elia, AJR
-/***************************************************************************
-
- TMP68301 basic emulation + Interrupt Handling
-
- The Toshiba TMP68301 is a 68HC000 + serial I/O, parallel I/O,
- 3 timers, address decoder, wait generator, interrupt controller,
- all integrated in a single chip.
-
- TODO:
- - Interrupt generation: edge detection, input expansion (INT3-INT9)
- - Parallel port: handle timing latency
- - Serial port: not done at all
- - (and many other things)
-
-***************************************************************************/
-
-#include "emu.h"
-#include "machine/tmp68301.h"
-
-DEFINE_DEVICE_TYPE(TMP68301, tmp68301_device, "tmp68301", "Toshiba TMP68301")
-
-void tmp68301_device::tmp68301_regs(address_map &map)
-{
- map(0x000, 0x3ff).rw(FUNC(tmp68301_device::regs_r), FUNC(tmp68301_device::regs_w));
-
- map(0x080, 0x093).rw(FUNC(tmp68301_device::icr_r), FUNC(tmp68301_device::icr_w)).umask16(0x00ff);
-
- map(0x094, 0x095).rw(FUNC(tmp68301_device::imr_r), FUNC(tmp68301_device::imr_w));
- map(0x096, 0x097).rw(FUNC(tmp68301_device::ipr_r), FUNC(tmp68301_device::ipr_w));
- map(0x098, 0x099).rw(FUNC(tmp68301_device::iisr_r), FUNC(tmp68301_device::iisr_w));
-
- /* Parallel Port */
- map(0x100, 0x101).rw(FUNC(tmp68301_device::pdir_r), FUNC(tmp68301_device::pdir_w));
- map(0x10a, 0x10b).rw(FUNC(tmp68301_device::pdr_r), FUNC(tmp68301_device::pdr_w));
-
- /* Serial Port */
- map(0x18e, 0x18f).rw(FUNC(tmp68301_device::scr_r), FUNC(tmp68301_device::scr_w));
-}
-
-// IRQ Mask register
-READ16_MEMBER(tmp68301_device::imr_r)
-{
- return m_imr;
-}
-
-WRITE16_MEMBER(tmp68301_device::imr_w)
-{
- COMBINE_DATA(&m_imr);
- update_ipl();
-}
-
-// IRQ Pending Register
-READ16_MEMBER(tmp68301_device::ipr_r)
-{
- return m_ipr;
-}
-
-WRITE16_MEMBER(tmp68301_device::ipr_w)
-{
- // software writes only clear bits
- m_ipr &= data | ~mem_mask;
- update_ipl();
-}
-
-// IRQ In-Service Register
-READ16_MEMBER(tmp68301_device::iisr_r)
-{
- return m_iisr;
-}
-
-WRITE16_MEMBER(tmp68301_device::iisr_w)
-{
- // software writes only clear bits
- m_iisr &= data | ~mem_mask;
-}
-
-// Serial Control Register (TODO: 8-bit wide)
-READ16_MEMBER(tmp68301_device::scr_r)
-{
- return m_scr;
-}
-
-WRITE16_MEMBER(tmp68301_device::scr_w)
-{
- /*
- *--- ---- CKSE
- --*- ---- RES
- ---- ---* INTM
- */
-
- COMBINE_DATA(&m_scr);
- m_scr &= 0xa1;
-}
-
-/* Parallel direction: 1 = output, 0 = input */
-READ16_MEMBER(tmp68301_device::pdir_r)
-{
- return m_pdir;
-}
-
-WRITE16_MEMBER(tmp68301_device::pdir_w)
-{
- COMBINE_DATA(&m_pdir);
-}
-
-READ16_MEMBER(tmp68301_device::pdr_r)
-{
- return (m_in_parallel_cb(0) & ~m_pdir) | (m_pdr & m_pdir);
-}
-
-WRITE16_MEMBER(tmp68301_device::pdr_w)
-{
- uint16_t old = m_pdr;
- COMBINE_DATA(&m_pdr);
- m_pdr = (old & ~m_pdir) | (m_pdr & m_pdir);
- m_out_parallel_cb(0, m_pdr, mem_mask);
-}
-
-READ8_MEMBER(tmp68301_device::icr_r)
-{
- return m_icr[offset];
-}
-
-WRITE8_MEMBER(tmp68301_device::icr_w)
-{
-/*
- --x- ---- Vector number is autogenerated if 1, else use external source
- ---x x--- 00 falling edge, 01 low level, 10 rising edge, 11 high level
- ^ applies only to external irqs (offset 0 to 2)
- ---- -xxx irq level
-*/
- m_icr[offset] = data;
-}
-
-tmp68301_device::tmp68301_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : m68000_device(mconfig, TMP68301, tag, owner, clock),
- m_in_parallel_cb(*this),
- m_out_parallel_cb(*this),
- m_ipl(0),
- m_imr(0),
- m_ipr(0),
- m_iisr(0),
- m_scr(0),
- m_pdir(0),
- m_pdr(0)
-{
- memset(m_regs, 0, sizeof(m_regs));
- memset(m_icr, 0, sizeof(m_icr));
- m_cpu_space_config.m_internal_map = address_map_constructor(FUNC(tmp68301_device::internal_vectors_r), this);
-}
-
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void tmp68301_device::device_start()
-{
- m68000_device::device_start();
-
- for (int i = 0; i < 3; i++)
- m_tmp68301_timer[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(tmp68301_device::timer_callback), this));
-
- m_in_parallel_cb.resolve_safe(0);
- m_out_parallel_cb.resolve_safe();
-
- m_program->install_device(0xfffc00, 0xffffff, *this, &tmp68301_device::tmp68301_regs);
-
- save_item(NAME(m_regs));
- save_item(NAME(m_icr));
- save_item(NAME(m_ipl));
- save_item(NAME(m_imr));
- save_item(NAME(m_ipr));
- save_item(NAME(m_iisr));
- save_item(NAME(m_scr));
- save_item(NAME(m_pdir));
- save_item(NAME(m_pdr));
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void tmp68301_device::device_reset()
-{
- m68000_device::device_reset();
-
- m_ipr = 0;
- m_iisr = 0;
- m_imr = 0x7f7; // mask all irqs
- std::fill(std::begin(m_icr), std::end(m_icr), 0x07);
- update_ipl();
-}
-
-//**************************************************************************
-// INLINE HELPERS
-//**************************************************************************
-
-void tmp68301_device::internal_vectors_r(address_map &map)
-{
- map(0xfffff0, 0xffffff).r(FUNC(tmp68301_device::irq_callback)).umask16(0x00ff);
-}
-
-
-uint8_t tmp68301_device::irq_callback(offs_t offset)
-{
- uint8_t IVNR = m_regs[0x9a/2] & 0xe0; // Interrupt Vector Number Register (IVNR)
-
- for (int src : { 0, 7, 3, 1, 8, 4, 5, 9, 2 })
- {
- // check if the IPL matches
- if (offset == (m_icr[src] & 0x07))
- {
- // check if interrupt is pending and not masked out
- u16 mask = (src > 2 ? 2 : 1) << src;
- if ((m_ipr & mask) != 0 && (m_imr & mask) == 0)
- {
- if (!machine().side_effects_disabled())
- {
- // add cause to interrupt in-service register
- m_iisr |= mask;
-
- // no longer pending
- m_ipr &= ~mask;
- update_ipl();
- }
-
- // vary vector number by type
- if (src > 6)
- return IVNR | (src - 3);
- else if (src > 2)
- return IVNR | (src - 1) << 2 | serial_interrupt_cause(src - 3);
- else /*if (BIT(m_icr[src], 5))*/ // TODO: use external vector otherwise
- return IVNR | src;
- }
- }
- }
-
- // default vector
- return IVNR | 0x1f;
-}
-
-TIMER_CALLBACK_MEMBER(tmp68301_device::timer_callback)
-{
- int i = param;
- uint16_t TCR = m_regs[(0x200 + i * 0x20)/2];
-
-// logerror("s: callback timer %04X, j = %d\n",machine().describe_context(),i,tcount);
-
- if (TCR & 0x0004) // INT
- {
- m_ipr |= 0x100 << i;
- update_ipl();
- }
-
- if (TCR & 0x0080) // N/1
- {
- // Repeat
- update_timer(i);
- }
- else
- {
- // One Shot
- }
-}
-
-void tmp68301_device::update_timer(int i)
-{
- uint16_t TCR = m_regs[(0x200 + i * 0x20)/2];
- uint16_t MAX1 = m_regs[(0x204 + i * 0x20)/2];
- uint16_t MAX2 = m_regs[(0x206 + i * 0x20)/2];
-
- int max = 0;
- attotime duration = attotime::zero;
-
- m_tmp68301_timer[i]->adjust(attotime::never,i);
-
- // timers 1&2 only
- switch( (TCR & 0x0030)>>4 ) // MR2..1
- {
- case 1:
- max = MAX1;
- break;
- case 2:
- max = MAX2;
- break;
- }
-
- switch ( (TCR & 0xc000)>>14 ) // CK2..1
- {
- case 0: // System clock (CLK)
- if (max)
- {
- int scale = (TCR & 0x3c00)>>10; // P4..1
- if (scale > 8) scale = 8;
- duration = attotime::from_hz(unscaled_clock()) * ((1 << scale) * max);
- }
- break;
- }
-
-// logerror("%s: TMP68301 Timer %d, duration %lf, max %04X\n",machine().describe_context(),i,duration,max);
-
- if (!(TCR & 0x0002)) // CS
- {
- if (duration != attotime::zero)
- m_tmp68301_timer[i]->adjust(duration,i);
- else
- logerror("%s: TMP68301 error, timer %d duration is 0\n",machine().describe_context(),i);
- }
-}
-
-/* Update the IRQ state based on all possible causes */
-void tmp68301_device::update_ipl()
-{
- uint8_t new_ipl = 0;
-
- for (int src = 0; src < 10; src++)
- {
- u16 mask = (src > 2 ? 2 : 1) << src;
- if ((m_ipr & mask) != 0 && (m_imr & mask) == 0 && new_ipl < (m_icr[src] & 0x07))
- new_ipl = m_icr[src] & 0x07;
- }
-
- if (new_ipl != m_ipl)
- {
- if (m_ipl != 0)
- set_input_line(m_ipl, CLEAR_LINE);
- if (new_ipl != 0)
- set_input_line(new_ipl, ASSERT_LINE);
-
- m_ipl = new_ipl;
- }
-}
-
-uint8_t tmp68301_device::serial_interrupt_cause(int channel)
-{
- /*
- * 00 error occurred
- * 01 receive completed
- * 10 transmit ready
- * 11 interrupt cause cleared while interrupt pending
- */
- (void)channel;
- return 3;
-}
-
-
-READ16_MEMBER( tmp68301_device::regs_r )
-{
- return m_regs[offset];
-}
-
-WRITE16_MEMBER( tmp68301_device::regs_w )
-{
- COMBINE_DATA(&m_regs[offset]);
-
- if (!ACCESSING_BITS_0_7) return;
-
-// logerror("CPU #0 PC %06X: TMP68301 Reg %04X<-%04X & %04X\n", >pc(),offset*2,data,mem_mask^0xffff);
-
- switch( offset * 2 )
- {
- // Timers
- case 0x200:
- case 0x220:
- case 0x240:
- {
- int i = ((offset*2) >> 5) & 3;
-
- update_timer( i );
- }
- break;
- }
-}
-
-void tmp68301_device::external_interrupt_0() { m_ipr |= EXT_IRQ0; update_ipl(); }
-void tmp68301_device::external_interrupt_1() { m_ipr |= EXT_IRQ1; update_ipl(); }
-void tmp68301_device::external_interrupt_2() { m_ipr |= EXT_IRQ2; update_ipl(); }