diff options
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 |
commit | 51601de10dcf132cf11304ca43159aa46815a901 (patch) | |
tree | 66fc6acabd26888f292f7e781095abf359ed4466 | |
parent | 69d2f79a5481879239985dc2e7b27eeeef06ef3f (diff) |
tmp68301.cpp: interrupt cleanups (nw)
-rw-r--r-- | src/devices/machine/tmp68301.cpp | 89 | ||||
-rw-r--r-- | src/devices/machine/tmp68301.h | 24 |
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; }; |