summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author angelosa <salese_corp_ltd@email.it>2017-07-16 23:59:08 +0200
committer angelosa <salese_corp_ltd@email.it>2017-07-16 23:59:34 +0200
commit51601de10dcf132cf11304ca43159aa46815a901 (patch)
tree66fc6acabd26888f292f7e781095abf359ed4466
parent69d2f79a5481879239985dc2e7b27eeeef06ef3f (diff)
tmp68301.cpp: interrupt cleanups (nw)
-rw-r--r--src/devices/machine/tmp68301.cpp89
-rw-r--r--src/devices/machine/tmp68301.h24
2 files changed, 89 insertions, 24 deletions
diff --git a/src/devices/machine/tmp68301.cpp b/src/devices/machine/tmp68301.cpp
index 8cbc9eaf5f9..39f25c3182c 100644
--- a/src/devices/machine/tmp68301.cpp
+++ b/src/devices/machine/tmp68301.cpp
@@ -23,6 +23,8 @@ DEFINE_DEVICE_TYPE(TMP68301, tmp68301_device, "tmp68301", "Toshiba TMP68301")
static ADDRESS_MAP_START( tmp68301_regs, 0, 16, tmp68301_device )
// AM_RANGE(0x000,0x3ff) AM_RAM
+ AM_RANGE(0x080,0x093) AM_READWRITE8(icr_r, icr_w,0x00ff)
+
AM_RANGE(0x094,0x095) AM_READWRITE(imr_r,imr_w)
AM_RANGE(0x098,0x099) AM_READWRITE(iisr_r,iisr_w)
@@ -98,6 +100,21 @@ WRITE16_MEMBER(tmp68301_device::pdr_w)
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)
: device_t(mconfig, TMP68301, tag, owner, clock),
@@ -112,7 +129,7 @@ tmp68301_device::tmp68301_device(const machine_config &mconfig, const char *tag,
m_space_config("regs", ENDIANNESS_LITTLE, 16, 10, 0, nullptr, *ADDRESS_MAP_NAME(tmp68301_regs))
{
memset(m_regs, 0, sizeof(m_regs));
- memset(m_IE, 0, sizeof(m_IE));
+ memset(m_icr, 0, sizeof(m_icr));
memset(m_irq_vector, 0, sizeof(m_irq_vector));
}
@@ -131,7 +148,7 @@ void tmp68301_device::device_start()
m_out_parallel_cb.resolve_safe();
save_item(NAME(m_regs));
- save_item(NAME(m_IE));
+ save_item(NAME(m_icr));
save_item(NAME(m_irq_vector));
save_item(NAME(m_imr));
save_item(NAME(m_iisr));
@@ -146,11 +163,7 @@ void tmp68301_device::device_start()
void tmp68301_device::device_reset()
{
- int i;
-
- for (i = 0; i < 3; i++)
- m_IE[i] = 0;
-
+ m_iisr = 0;
m_imr = 0x7f7; // mask all irqs
}
@@ -274,36 +287,74 @@ void tmp68301_device::update_timer( int i )
}
/* Update the IRQ state based on all possible causes */
-void tmp68301_device::update_irq_state()
+void tmp68301_device::update_irq_state(uint16_t cause)
{
int i;
/* Take care of external interrupts */
uint16_t IVNR = m_regs[0x9a/2]; // Interrupt Vector Number Register (IVNR)
-
+ // add cause to interrupt in-service register
+ m_iisr |= cause;
+
for (i = 0; i < 3; i++)
{
- if ( (m_IE[i]) &&
- !(m_imr & (1<<i))
- )
+ if ((m_iisr & 1 << i) && !(m_imr & (1<<i)))
{
- uint16_t ICR = m_regs[0x80/2+i]; // Interrupt Controller Register (ICR0..2)
+ uint8_t current_ICR = m_icr[i]; // Interrupt Controller Register (ICR0..2)
// Interrupt Controller Register (ICR0..2)
- int level = ICR & 0x0007;
+ int level = current_ICR & 0x0007;
// Interrupt Vector Number Register (IVNR)
m_irq_vector[level] = IVNR & 0x00e0;
m_irq_vector[level] += i;
- m_IE[i] = 0; // Interrupts are edge triggerred
-
machine().firstcpu->set_input_line(level,HOLD_LINE);
}
}
}
+void tmp68301_device::update_irq_serial(uint16_t cause, uint8_t type)
+{
+ int i;
+ const uint8_t serial_irq_vector[3] = { 8, 0xc, 0x10 };
+
+ /* Take care of external interrupts */
+
+ uint16_t IVNR = m_regs[0x9a/2]; // Interrupt Vector Number Register (IVNR)
+ // add cause to interrupt in-service register
+ m_iisr |= cause;
+
+ for (i = 4; i < 7; i++)
+ {
+ if ((m_iisr & 1 << i) && !(m_imr & (1<<i)))
+ {
+ uint8_t current_ICR = m_icr[i-1]; // Interrupt Controller Register (ICR0..2)
+
+ // Interrupt Controller Register (ICR0..2)
+ int level = current_ICR & 0x0007;
+
+ // Interrupt Vector Number Register (IVNR)
+ m_irq_vector[level] = IVNR & 0x00e0;
+ /*
+ * channel number
+ */
+ m_irq_vector[level] += serial_irq_vector[i-4];
+ /*
+ * 00 error occurred
+ * 01 receive completed
+ * 10 transmit ready
+ * 11 interrupt cause cleared while interrupt pending
+ */
+ m_irq_vector[level] += type;
+
+ machine().firstcpu->set_input_line(level,HOLD_LINE);
+ }
+ }
+}
+
+
READ16_MEMBER( tmp68301_device::regs_r )
{
return read_word(offset);
@@ -334,6 +385,6 @@ WRITE16_MEMBER( tmp68301_device::regs_w )
}
}
-void tmp68301_device::external_interrupt_0() { m_IE[0] = 1; update_irq_state(); }
-void tmp68301_device::external_interrupt_1() { m_IE[1] = 1; update_irq_state(); }
-void tmp68301_device::external_interrupt_2() { m_IE[2] = 1; update_irq_state(); }
+void tmp68301_device::external_interrupt_0() { update_irq_state(EXT_IRQ0); }
+void tmp68301_device::external_interrupt_1() { update_irq_state(EXT_IRQ1); }
+void tmp68301_device::external_interrupt_2() { update_irq_state(EXT_IRQ2); }
diff --git a/src/devices/machine/tmp68301.h b/src/devices/machine/tmp68301.h
index f5c69181bca..9e6c19ce9e3 100644
--- a/src/devices/machine/tmp68301.h
+++ b/src/devices/machine/tmp68301.h
@@ -40,7 +40,7 @@ public:
void external_interrupt_0();
void external_interrupt_1();
void external_interrupt_2();
-
+
DECLARE_READ16_MEMBER(imr_r);
DECLARE_WRITE16_MEMBER(imr_w);
DECLARE_READ16_MEMBER(iisr_r);
@@ -51,6 +51,8 @@ public:
DECLARE_WRITE16_MEMBER(pdr_w);
DECLARE_READ16_MEMBER(pdir_r);
DECLARE_WRITE16_MEMBER(pdir_w);
+ DECLARE_READ8_MEMBER(icr_r);
+ DECLARE_WRITE8_MEMBER(icr_w);
IRQ_CALLBACK_MEMBER(irq_callback);
@@ -63,8 +65,20 @@ protected:
private:
TIMER_CALLBACK_MEMBER( timer_callback );
void update_timer( int i );
- void update_irq_state();
-
+ void update_irq_state(uint16_t cause);
+ void update_irq_serial(uint16_t cause, uint8_t type);
+
+ static constexpr uint16_t EXT_IRQ0 = 1 << 0;
+ static constexpr uint16_t EXT_IRQ1 = 1 << 1;
+ static constexpr uint16_t EXT_IRQ2 = 1 << 2;
+ static constexpr uint16_t SERIAL_IRQ_CH0 = 1 << 4;
+ static constexpr uint16_t SERIAL_IRQ_CH1 = 1 << 5;
+ static constexpr uint16_t SERIAL_IRQ_CH2 = 1 << 6;
+ static constexpr uint16_t PARALLEL_IRQ = 1 << 7;
+ static constexpr uint16_t TIMER0_IRQ = 1 << 8;
+ static constexpr uint16_t TIMER1_IRQ = 1 << 9;
+ static constexpr uint16_t TIMER2_IRQ = 1 << 10;
+
inline uint16_t read_word(offs_t address);
inline void write_word(offs_t address, uint16_t data);
@@ -74,7 +88,6 @@ private:
// internal state
uint16_t m_regs[0x400];
- uint8_t m_IE[3]; // 3 External Interrupt Lines
emu_timer *m_tmp68301_timer[3]; // 3 Timers
uint16_t m_irq_vector[8];
@@ -84,7 +97,8 @@ private:
uint16_t m_scr;
uint16_t m_pdir;
uint16_t m_pdr;
-
+ uint8_t m_icr[10];
+
const address_space_config m_space_config;
};