68230: added initial support for timer interrupts and embryonic support for port interrupts

This commit is contained in:
Joakim Larsson Edstrom 2016-12-08 08:53:25 +01:00
parent 4991242234
commit 8458ac2417
3 changed files with 113 additions and 34 deletions

View File

@ -16,7 +16,7 @@
*
* Todo
* - Complete support for clock and timers
* - Add interrupt support
* - Complete interrupt support
* - Add DMA support
* - Add appropriate buffering for each submode
**********************************************************************/
@ -28,6 +28,7 @@
#define LOGPRINT(x) { do { if (VERBOSE) logerror x; } while (0); }
#define LOG(x) {} LOGPRINT(x)
#define LOGR(x) {} LOGPRINT(x)
#define LOGBIT(x) {} LOGPRINT(x)
#define LOGDR(x) {} LOGPRINT(x)
#define LOGINT(x) {} LOGPRINT(x)
#define LOGSETUP(x) {} LOGPRINT(x)
@ -64,6 +65,8 @@ pit68230_device::pit68230_device(const machine_config &mconfig, device_type type
, m_h2_out_cb (*this)
, m_h3_out_cb (*this)
, m_h4_out_cb (*this)
, m_tirq_out_cb (*this)
, m_pirq_out_cb (*this)
, m_pgcr(0)
, m_psrr(0)
, m_paddr(0)
@ -100,6 +103,8 @@ pit68230_device::pit68230_device(const machine_config &mconfig, const char *tag,
, m_h2_out_cb(*this)
, m_h3_out_cb(*this)
, m_h4_out_cb(*this)
, m_tirq_out_cb (*this)
, m_pirq_out_cb (*this)
, m_pgcr(0)
, m_psrr(0)
, m_paddr(0)
@ -141,6 +146,8 @@ void pit68230_device::device_start ()
m_h2_out_cb.resolve_safe();
m_h3_out_cb.resolve_safe();
m_h4_out_cb.resolve_safe();
m_tirq_out_cb.resolve_safe();
m_pirq_out_cb.resolve_safe();
// Timers
pit_timer = timer_alloc(TIMER_ID_PIT);
@ -177,7 +184,7 @@ void pit68230_device::device_reset ()
m_paddr = 0;
m_pbddr = 0;
m_pcddr = 0;
m_pivr = 0x0f;
m_pivr = 0x0f; m_pirq_out_cb(CLEAR_LINE);
m_pacr = 0; m_h2_out_cb(CLEAR_LINE);
m_pbcr = 0; m_h4_out_cb(CLEAR_LINE);
m_padr = 0; m_pa_out_cb((offs_t)0, m_padr);
@ -185,23 +192,65 @@ void pit68230_device::device_reset ()
m_pcdr = 0; m_pc_out_cb((offs_t)0, m_pcdr);
m_psr = 0;
m_tcr = 0;
m_tivr = 0x0f;
m_tivr = 0x0f; m_tirq_out_cb(CLEAR_LINE);
m_tsr = 0;
}
/*
* PIACK* provides the Port vector in an iack cycle modified by source H1-H4
*/
uint8_t pit68230_device::irq_piack()
{
LOGINT(("%s %s <- %02x\n",tag(), FUNCNAME, m_pivr));
return m_pivr;
}
/*
* TIACK* provides the Timer vector in an iack cycle
*/
uint8_t pit68230_device::irq_tiack()
{
LOGINT(("%s %s <- %02x\n",tag(), FUNCNAME, m_tivr));
return m_tivr;
}
/*
* trigger_interrupt - called when a potential interrupt condition occurs
* but will only generate an interrupt when the PIT is programmed to do so.
*/
void pit68230_device::trigger_interrupt(int source)
{
LOGINT(("%s %s Source: %02x\n",tag(), FUNCNAME, source));
if (source == INT_TIMER)
{
// TODO: implement priorities and support nested interrupts
if ( (m_tcr & REG_TCR_TOUT_TIACK_MASK) == REG_TCR_TOUT_TIACK_INT ||
(m_tcr & REG_TCR_TOUT_TIACK_MASK) == REG_TCR_TOUT_PC7_INT )
{
m_tirq_out_cb(ASSERT_LINE);
}
}
else
{
// TODO: implement priorities and support nested interrupts for the H1-H4 sources
m_pirq_out_cb(ASSERT_LINE);
}
}
void pit68230_device::tick_clock()
{
if (m_tcr & REG_TCR_TIMER_ENABLE)
{
if (m_cntr-- == 0) // Zero detect
{
LOG(("Timer reached zero!\n"));
/* TODO: Check mode and use preload value if required or just rollover 24 bit */
LOGINT(("Timer reached zero!\n"));
if ((m_tcr & REG_TCR_ZD) == 0)
m_cntr = m_cpr;
else // mask off to 24 bit on rollover
m_cntr &= 0xffffff;
m_tsr = 1;
trigger_interrupt(INT_TIMER);
}
}
}
@ -217,7 +266,7 @@ void pit68230_device::device_timer (emu_timer &timer, device_timer_id id, int32_
tick_clock();
break;
default:
LOGINT(("Unhandled Timer ID %d\n", id));
LOG(("Unhandled Timer ID %d\n", id));
break;
}
}
@ -235,7 +284,7 @@ void pit68230_device::portb_setbit(uint8_t bit, uint8_t state)
void pit68230_device::pa_update_bit(uint8_t bit, uint8_t state)
{
LOG(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state));
LOGBIT(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state));
// Check if requested bit is an output bit and can't be affected
if (m_paddr & (1 << bit))
{
@ -250,7 +299,7 @@ void pit68230_device::pa_update_bit(uint8_t bit, uint8_t state)
void pit68230_device::pb_update_bit(uint8_t bit, uint8_t state)
{
LOG(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state));
LOGBIT(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state));
// Check if requested bit is an output bit and can't be affected
if (m_pbddr & (1 << bit))
{
@ -266,7 +315,7 @@ void pit68230_device::pb_update_bit(uint8_t bit, uint8_t state)
// TODO: Make sure port C is in the right alternate mode
void pit68230_device::pc_update_bit(uint8_t bit, uint8_t state)
{
LOG(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state));
LOGBIT(("%s %s bit %d to %d\n",tag(), FUNCNAME, bit, state));
// Check if requested bit is an output bit and can't be affected
if (m_pcddr & (1 << bit))
{
@ -541,19 +590,19 @@ void pit68230_device::wr_pitreg_tcr(uint8_t data)
case REG_TCR_PC3_PC7:
case REG_TCR_PC3_PC7_DC: LOG(("- PC3 and PC7 used as I/O pins\n")); break;
case REG_TCR_TOUT_PC7_SQ:
case REG_TCR_TOUT_PC7_SQ_DC: LOG(("- PC3 used as SQuare wave TOUT and PC7 used as I/O pin - not supported yet\n")); sqr = 1; break;
case REG_TCR_TOUT_TIACK: LOG(("- PC3 used as TOUT and PC7 used as TIACK - not supported yet\n")); tout = 1; tiack = 1; break;
case REG_TCR_TOUT_TIACK_INT: LOG(("- PC3 used as TOUT and PC7 used as TIACK, Interrupts enabled - not supported yet\n")); tout = 1; tiack = 1; irq = 1; break;
case REG_TCR_TOUT_PC7: LOG(("- PC3 used as TOUT and PC7 used as I/O pin - not supported yet\n")); break;
case REG_TCR_TOUT_PC7_INT: LOG(("- PC3 used as TOUT and PC7 used as I/O pin, Interrupts enabled - not supported yet\n")); break;
case REG_TCR_TOUT_PC7_SQ_DC: LOG(("- PC3 used as SQuare wave TOUT and PC7 used as I/O pin - not implemented yet\n")); sqr = 1; break;
case REG_TCR_TOUT_TIACK: LOG(("- PC3 used as TOUT and PC7 used as TIACK - not implemented yet\n")); tout = 1; tiack = 1; break;
case REG_TCR_TOUT_TIACK_INT: LOG(("- PC3 used as TOUT and PC7 used as TIACK, Interrupts enabled\n")); tout = 1; tiack = 1; irq = 1; break;
case REG_TCR_TOUT_PC7: LOG(("- PC3 used as TOUT and PC7 used as I/O pin - not implemented yet\n")); break;
case REG_TCR_TOUT_PC7_INT: LOG(("- PC3 used as TOUT and PC7 used as I/O pin, Interrupts enabled\n")); tout = 1; irq = 1; break;
}
switch (m_tcr & REG_TCR_CC_MASK)
{
case REG_TCR_CC_PC2_CLK_PSC: LOG(("- PC2 used as I/O pin,CLK and x32 prescaler are used\n")); clk = 1; psc = 1; break;
case REG_TCR_CC_TEN_CLK_PSC: LOG(("- PC2 used as Timer enable/disable, CLK and presacaler are used\n")); pen = 1; clk = 1; psc = 1; break;
case REG_TCR_CC_TIN_PSC: LOG(("- PC2 used as Timer clock and the presacaler is used - not supported yet\n")); psc = 1; break;
case REG_TCR_CC_TIN_RAW: LOG(("- PC2 used as Timer clock and the presacaler is NOT used - not supported yet\n")); break;
case REG_TCR_CC_PC2_CLK_PSC: LOG(("- PC2 used as I/O pin,CLK and x32 prescaler are used\n")); clk = 1; psc = 1; break;
case REG_TCR_CC_TEN_CLK_PSC: LOG(("- PC2 used as Timer enable/disable, CLK and presacaler are used - not implemented\n")); pen = 1; clk = 1; psc = 1; break;
case REG_TCR_CC_TIN_PSC: LOG(("- PC2 used as Timer clock and the presacaler is used - not implemented\n")); psc = 1; break;
case REG_TCR_CC_TIN_RAW: LOG(("- PC2 used as Timer clock and the presacaler is NOT used\n")); break;
}
LOG(("%s", m_tcr & REG_TCR_ZR ? "- Spec violation, should always be 0!\n" : ""));
LOG(("- Timer %s when reaching 0 (zero)\n", m_tcr & REG_TCR_ZD ? "rolls over" : "reload the preload values"));
@ -562,7 +611,10 @@ void pit68230_device::wr_pitreg_tcr(uint8_t data)
if (m_tcr & REG_TCR_ENABLE)
{
m_cntr = 0;
if (pen == 1){ LOG(("PC2 enable/disable TBD\n")); }
if (pen == 1)
{
LOG(("PC2 enable/disable TBD\n"));
}
if (clk == 1)
{
int rate = clock() / (psc == 1 ? 32 : 1);
@ -607,7 +659,11 @@ void pit68230_device::wr_pitreg_cprl(uint8_t data)
void pit68230_device::wr_pitreg_tsr(uint8_t data)
{
LOG(("%s(%02x) \"%s\": \n", FUNCNAME, data, tag()));
if (data & 1) m_tsr = 0; // A write resets the TSR;
if (data & 1)
{
m_tsr = 0; // A write resets the TSR;
m_tirq_out_cb(CLEAR_LINE);
}
}
WRITE8_MEMBER (pit68230_device::write)

View File

@ -44,34 +44,40 @@
//**************************************************************************
#define MCFG_PIT68230_PA_INPUT_CB(_devcb) \
devcb = &pit68230_device::set_pa_in_callback (*device, DEVCB_##_devcb);
devcb = &pit68230_device::set_pa_in_callback (*device, DEVCB_##_devcb);
#define MCFG_PIT68230_PA_OUTPUT_CB(_devcb) \
devcb = &pit68230_device::set_pa_out_callback (*device, DEVCB_##_devcb);
devcb = &pit68230_device::set_pa_out_callback (*device, DEVCB_##_devcb);
#define MCFG_PIT68230_PB_INPUT_CB(_devcb) \
devcb = &pit68230_device::set_pb_in_callback (*device, DEVCB_##_devcb);
devcb = &pit68230_device::set_pb_in_callback (*device, DEVCB_##_devcb);
#define MCFG_PIT68230_PB_OUTPUT_CB(_devcb) \
devcb = &pit68230_device::set_pb_out_callback (*device, DEVCB_##_devcb);
devcb = &pit68230_device::set_pb_out_callback (*device, DEVCB_##_devcb);
#define MCFG_PIT68230_PC_INPUT_CB(_devcb) \
devcb = &pit68230_device::set_pc_in_callback (*device, DEVCB_##_devcb);
devcb = &pit68230_device::set_pc_in_callback (*device, DEVCB_##_devcb);
#define MCFG_PIT68230_PC_OUTPUT_CB(_devcb) \
devcb = &pit68230_device::set_pc_out_callback (*device, DEVCB_##_devcb);
devcb = &pit68230_device::set_pc_out_callback (*device, DEVCB_##_devcb);
#define MCFG_PIT68230_H1_CB(_devcb) \
devcb = &pit68230_device::set_h1_out_callback (*device, DEVCB_##_devcb);
devcb = &pit68230_device::set_h1_out_callback (*device, DEVCB_##_devcb);
#define MCFG_PIT68230_H2_CB(_devcb) \
devcb = &pit68230_device::set_h2_out_callback (*device, DEVCB_##_devcb);
devcb = &pit68230_device::set_h2_out_callback (*device, DEVCB_##_devcb);
#define MCFG_PIT68230_H3_CB(_devcb) \
devcb = &pit68230_device::set_h3_out_callback (*device, DEVCB_##_devcb);
devcb = &pit68230_device::set_h3_out_callback (*device, DEVCB_##_devcb);
#define MCFG_PIT68230_H4_CB(_devcb) \
devcb = &pit68230_device::set_h4_out_callback (*device, DEVCB_##_devcb);
devcb = &pit68230_device::set_h4_out_callback (*device, DEVCB_##_devcb);
#define MCFG_PIT68230_TIMER_IRQ_CB(_devcb) \
devcb = &pit68230_device::set_tirq_out_callback(*device, DEVCB_##_devcb);
#define MCFG_PIT68230_PORT_IRQ_CB(_devcb) \
devcb = &pit68230_device::set_pirq_out_callback(*device, DEVCB_##_devcb);
/*-----------------------------------------------------------------------
* Registers RS1-RS5 R/W Description
@ -119,13 +125,14 @@ class pit68230_device : public device_t//, public device_execute_interface
template<class _Object> static devcb_base &set_h2_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_h2_out_cb.set_callback (object); }
template<class _Object> static devcb_base &set_h3_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_h3_out_cb.set_callback (object); }
template<class _Object> static devcb_base &set_h4_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_h4_out_cb.set_callback (object); }
template<class _Object> static devcb_base &set_tirq_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_tirq_out_cb.set_callback (object); }
template<class _Object> static devcb_base &set_pirq_out_callback (device_t &device, _Object object){ return downcast<pit68230_device &>(device).m_pirq_out_cb.set_callback (object); }
DECLARE_WRITE8_MEMBER (write);
DECLARE_READ8_MEMBER (read);
void h1_set (uint8_t state);
void portb_setbit (uint8_t bit, uint8_t state);
void tick_clock();
// Bit updaters
void pa_update_bit(uint8_t bit, uint8_t state);
@ -286,11 +293,18 @@ protected:
REG_TCR_TOUT_PC7_INT = 0xe0, // 1 1 1
};
void tick_clock();
// device-level overrides
virtual void device_start () override;
virtual void device_reset () override;
virtual void device_timer (emu_timer &timer, device_timer_id id, int param, void *ptr) override;
// Interrupt methods
void trigger_interrupt(int source);
uint8_t irq_tiack();
uint8_t irq_piack();
int m_icount;
devcb_write8 m_pa_out_cb;
@ -303,8 +317,10 @@ protected:
devcb_write_line m_h2_out_cb;
devcb_write_line m_h3_out_cb;
devcb_write_line m_h4_out_cb;
devcb_write_line m_tirq_out_cb;
devcb_write_line m_pirq_out_cb;
// peripheral ports
// registers
uint8_t m_pgcr; // Port General Control register
uint8_t m_psrr; // Port Service Request register
uint8_t m_paddr; // Port A Data Direction register
@ -323,6 +339,13 @@ protected:
int m_cntr; // - The 24 bit Counter
uint8_t m_tsr; // Timer Status Register
// Interrupt sources
enum
{
INT_TIMER
};
// Timers
emu_timer *pit_timer;

View File

@ -699,7 +699,7 @@ static MACHINE_CONFIG_START (cpu30, cpu30_state)
MCFG_PIT68230_PB_OUTPUT_CB(WRITE8(cpu30_state, flop_dmac_w))
MCFG_PIT68230_PC_INPUT_CB(READ8(cpu30_state, pit1c_r))
MCFG_PIT68230_PC_OUTPUT_CB(WRITE8(cpu30_state, pit1c_w))
// MCFG_PIT68230_OUT_INT_CB(DEVWRITELINE("fga002", fga002_device, lirq2_w)) // Interrupts not yet supported by 68230
// MCFG_PIT68230_TIMER_IRQ_CB(DEVWRITELINE("fga002", fga002_device, lirq2_w)) // The timer interrupt seems to silence the terminal interrupt, needs invectigation
MCFG_DEVICE_ADD ("pit2", PIT68230, XTAL_16MHz / 2) // Th PIT clock is not verified on schema but reversed from behaviour
MCFG_PIT68230_PB_INPUT_CB(READ8(cpu30_state, board_mem_id_rd))
@ -707,7 +707,7 @@ static MACHINE_CONFIG_START (cpu30, cpu30_state)
MCFG_PIT68230_PA_OUTPUT_CB(WRITE8(cpu30_state, pit2a_w))
MCFG_PIT68230_PC_INPUT_CB(READ8(cpu30_state, pit2c_r))
MCFG_PIT68230_PC_OUTPUT_CB(WRITE8(cpu30_state, pit2c_w))
// MCFG_PIT68230_OUT_INT_CB(DEVWRITELINE("fga002", fga002_device, lirq3_w)) // Interrupts not yet supported by 68230
// MCFG_PIT68230_TIMER_IRQ_CB(DEVWRITELINE("fga002", fga002_device, lirq3_w)) // The timer interrupt seems to silence the terminal interrupt, needs invectigation
/* FGA-002, Force Gate Array */
MCFG_FGA002_ADD("fga002", 0)