Improved reset, timer and port C behaviour

This commit is contained in:
Joakim Larsson Edstrom 2016-11-29 18:36:25 +01:00
parent 7d401c1ad9
commit 6845eabdf1
2 changed files with 186 additions and 28 deletions

View File

@ -20,7 +20,7 @@
* - Complete support for clock and timers
* - Add interrupt support
* - Add DMA support
* - Add double buffering for each submode
* - Add apropriate buffering for each submode
**********************************************************************/
#include "68230pit.h"
@ -30,6 +30,7 @@
#define LOGPRINT(x) { do { if (VERBOSE) logerror x; } while (0); }
#define LOG(x) {} LOGPRINT(x)
#define LOGR(x) {} LOGPRINT(x)
#define LOGDR(x) {} LOGPRINT(x)
#define LOGINT(x) {} LOGPRINT(x)
#define LOGSETUP(x) {} LOGPRINT(x)
#if VERBOSE > 1
@ -137,7 +138,7 @@ void pit68230_device::device_start ()
m_pb_out_cb.resolve_safe();
m_pb_in_cb.resolve_safe(0);
m_pc_out_cb.resolve_safe();
m_pc_in_cb.resolve_safe(0);
m_pc_in_cb.resolve(); // A temporary way to check if handler is installed with isnull(). TODO: Need better fix.
m_h1_out_cb.resolve_safe();
m_h2_out_cb.resolve_safe();
m_h3_out_cb.resolve_safe();
@ -179,16 +180,34 @@ void pit68230_device::device_reset ()
m_pbddr = 0;
m_pcddr = 0;
m_pivr = 0x0f;
m_pacr = 0; m_h2_out_cb(m_pacr);
m_pbcr = 0;
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);
m_pbdr = 0; m_pb_out_cb((offs_t)0, m_pbdr);
m_pcdr = 0; m_pc_out_cb((offs_t)0, m_pcdr);
m_psr = 0;
m_tcr = 0;
m_tivr = 0x0f;
m_tsr = 0;
}
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 */
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;
}
}
}
//-------------------------------------------------
// device_timer - handler timer events
//-------------------------------------------------
@ -197,14 +216,7 @@ void pit68230_device::device_timer (emu_timer &timer, device_timer_id id, int32_
switch(id)
{
case TIMER_ID_PIT:
if (m_cntr-- == 0) // Zero detect
{
/* TODO: Check mode and use preload value if required or just rollover 24 bit */
if ((m_tcr & REG_TCR_ZD) == 0)
m_cntr = m_cpr;
else // mask off to 24 bit on rollover
m_cntr &= 0xffffff;
}
tick_clock();
break;
default:
LOGINT(("Unhandled Timer ID %d\n", id));
@ -214,16 +226,32 @@ void pit68230_device::device_timer (emu_timer &timer, device_timer_id id, int32_
void pit68230_device::h1_set (uint8_t state)
{
LOG(("%s %s %d @ m_psr %2x => ",tag(), FUNCNAME, state, m_psr));
if (state) m_psr |= 1; else m_psr &= ~1;
LOG(("%02x %lld\n", m_psr, machine ().firstcpu->total_cycles ()));
}
void pit68230_device::portb_setbit (uint8_t bit, uint8_t state)
void pit68230_device::portb_setbit(uint8_t bit, uint8_t state)
{
LOG(("%s %s %d/%d @ m_pbdr %2x => ", tag(), FUNCNAME, bit, state, m_pbdr));
if (state) m_pbdr |= (1 << bit); else m_pbdr &= ~(1 << bit);
LOG(("%02x %lld\n", m_pbdr, machine ().firstcpu->total_cycles ()));
}
// Bit updaters will make it possible to move registers to private data
// TODO: Make sure to only update input bits and that the port is in the right alternate mode
void pit68230_device::pa_update_bit(uint8_t bit, uint8_t state){ if (state) m_padr |= (1 << bit); else m_padr &= ~(1 << bit); }
void pit68230_device::pb_update_bit(uint8_t bit, uint8_t state){ if (state) m_pbdr |= (1 << bit); else m_pbdr &= ~(1 << bit); }
void pit68230_device::pc_update_bit(uint8_t bit, uint8_t state){ if (state) m_pcdr |= (1 << bit); else m_pcdr &= ~(1 << bit); }
void pit68230_device::update_tin()
{
static uint32_t counter = 0;
// Tick clock on falling edge. TODO: check what flank is correct
if (((counter & 1) != 0))
{
tick_clock();
}
pc_update_bit(REG_PCDR_TIN_BIT, counter & 1);
counter++;
}
#if VERBOSE > 2
@ -298,20 +326,79 @@ void pit68230_device::wr_pitreg_pacr(uint8_t data)
* 1 X0 Output pin - negated, H2S is always cleared.
* 1 X1 Output pin - asserted, H2S is always cleared.
*/
m_h2_out_cb (m_pacr & 0x08 ? 1 : 0); // TODO: Check mode and submodes
if (m_pgcr & REG_PGCR_H12_ENABLE)
{
if (m_pacr & REG_PACR_H2_CTRL_IN_OUT)
{
switch(m_pacr & REG_PACR_H2_CTRL_MASK)
{
case REG_PACR_H2_CTRL_OUT_00:
LOG((" - H2 cleared\n"));
m_h2_out_cb(CLEAR_LINE);
break;
case REG_PACR_H2_CTRL_OUT_01:
LOG((" - H2 asserted\n"));
m_h2_out_cb(ASSERT_LINE);
break;
case REG_PACR_H2_CTRL_OUT_10:
LOGSETUP((" - interlocked handshake not implemented\n"));
break;
case REG_PACR_H2_CTRL_OUT_11:
LOGSETUP((" - pulsed handshake not implemented\n"));
break;
default: logerror(("Undefined H2 mode, broken driver - please report!\n"));
}
}
}
else
{
LOG((" - H2 cleared because beeing disabled in PGCR\n"));
m_h2_out_cb(CLEAR_LINE);
}
}
// TODO add support for sense status
void pit68230_device::wr_pitreg_pbcr(uint8_t data)
{
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
m_pbcr = data;
if ((m_pgcr & REG_PGCR_H34_ENABLE) || ((m_pbcr & REG_PBCR_SUBMODE_MASK) == REG_PBCR_SUBMODE_1X))
{
if (m_pbcr & REG_PBCR_H4_CTRL_IN_OUT)
{
switch(m_pbcr & REG_PBCR_H4_CTRL_MASK)
{
case REG_PBCR_H4_CTRL_OUT_00:
LOG((" - H4 cleared\n"));
m_h4_out_cb(CLEAR_LINE);
break;
case REG_PBCR_H4_CTRL_OUT_01:
LOG((" - H4 asserted\n"));
m_h4_out_cb(ASSERT_LINE);
break;
case REG_PBCR_H4_CTRL_OUT_10:
LOGSETUP((" - interlocked handshake not implemented\n"));
break;
case REG_PBCR_H4_CTRL_OUT_11:
LOGSETUP((" - pulsed handshake not implemented\n"));
break;
default: logerror(("Undefined H4 mode, broken driver - please report!\n"));
}
}
}
else
{
LOG((" - H4 cleared because beeing disabled in PGCR\n"));
m_h4_out_cb(CLEAR_LINE);
}
}
void pit68230_device::wr_pitreg_padr(uint8_t data)
{
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
m_padr |= (data & m_paddr);
// callbacks
// callback
m_pa_out_cb ((offs_t)0, m_padr);
}
@ -319,7 +406,8 @@ void pit68230_device::wr_pitreg_pbdr(uint8_t data)
{
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
m_pbdr |= (data & m_pbddr);
// callbacks
// callback
m_pb_out_cb ((offs_t)0, m_pbdr & m_pbddr);
}
@ -327,7 +415,8 @@ void pit68230_device::wr_pitreg_pcdr(uint8_t data)
{
LOG(("%s(%02x) \"%s\": %s - %02x\n", FUNCNAME, data, tag(), FUNCNAME, data));
m_pcdr |= (data & m_pcddr);
// callbacks
// callback
m_pc_out_cb ((offs_t)0, m_pcdr);
}
@ -482,7 +571,7 @@ 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()));
m_tsr = data;
if (data & 1) m_tsr = 0; // A write resets the TSR;
}
WRITE8_MEMBER (pit68230_device::write)
@ -592,7 +681,7 @@ uint8_t pit68230_device::rr_pitreg_padr()
{
m_padr &= m_paddr;
m_padr |= (m_pa_in_cb() & ~m_paddr);
LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_padr));
LOGDR(("%s %s <- %02x\n",tag(), FUNCNAME, m_padr));
return m_padr;
}
@ -607,15 +696,19 @@ uint8_t pit68230_device::rr_pitreg_pbdr()
{
m_pbdr &= m_pbddr;
m_pbdr |= (m_pb_in_cb() & ~m_pbddr);
LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pbdr));
LOGDR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pbdr));
return m_pbdr;
}
uint8_t pit68230_device::rr_pitreg_pcdr()
{
m_pcdr &= m_pcddr;
m_pcdr |= (m_pc_in_cb() & ~m_pcddr);
LOGR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pcdr));
if (!m_pc_in_cb.isnull()) // Port C has alternate functions that may set bits apart from callback
{
m_pcdr &= m_pcddr;
m_pcdr |= (m_pc_in_cb() & ~m_pcddr);
}
if (m_pcdr != 0) { LOGDR(("%s %s <- %02x\n",tag(), FUNCNAME, m_pcdr)); }
return m_pcdr;
}
@ -739,7 +832,7 @@ READ8_MEMBER (pit68230_device::read){
case PIT_68230_CNTRL: data = rr_pitreg_cntrl(); break;
case PIT_68230_TSR: data = rr_pitreg_tsr(); break;
default:
LOG (("Unhandled read register %02x\n", offset));
LOG (("Unhandled read register %02x returning 0x00\n", offset));
data = 0;
}

View File

@ -125,6 +125,13 @@ class pit68230_device : public device_t//, public device_execute_interface
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);
void pb_update_bit(uint8_t bit, uint8_t state);
void pc_update_bit(uint8_t bit, uint8_t state);
void update_tin();
void wr_pitreg_pgcr(uint8_t data);
void wr_pitreg_psrr(uint8_t data);
@ -173,7 +180,65 @@ class pit68230_device : public device_t//, public device_execute_interface
protected:
enum { // PGCR - Port Global Control register
REG_PGCR_MODE_MASK = 0xc0,
REG_PGCR_MODE_0 = 0x00, // 0 0 Unidirectional 8 bit mode
REG_PGCR_MODE_1 = 0x40, // 0 1 Unidirectional 16 bit mode
REG_PGCR_MODE_2 = 0x80, // 1 0 Bidirectional 8 bit mode
REG_PGCR_MODE_3 = 0xc0, // 1 1 Bidirectional 16 bit mode
REG_PGCR_H34_ENABLE = 0x20,
REG_PGCR_H12_ENABLE = 0x10,
REG_PGCR_H4_SENSE = 0x80,
REG_PGCR_H3_SENSE = 0x40,
REG_PGCR_H2_SENSE = 0x20,
REG_PGCR_H1_SENSE = 0x10,
};
enum {
REG_PACR_SUBMODE_MASK = 0xc0,
REG_PACR_SUBMODE_0 = 0x00, // 0 0
REG_PACR_SUBMODE_1 = 0x40, // 0 1
REG_PACR_SUBMODE_2 = 0x80, // 1 0
REG_PACR_SUBMODE_3 = 0xc0, // 1 1
REG_PACR_H2_CTRL_MASK = 0x38,
REG_PACR_H2_CTRL_IN_OUT = 0x20, // H2 sense always cleared if set
REG_PACR_H2_CTRL_OUT_00 = 0x20, // H2 output negated
REG_PACR_H2_CTRL_OUT_01 = 0x28, // H2 output asserted
REG_PACR_H2_CTRL_OUT_10 = 0x30, // H2 output in interlocked input handshake protocol
REG_PACR_H2_CTRL_OUT_11 = 0x38, // H2 output in pulsed input handshake protocol
REG_PACR_H2_INT_ENABLE = 0x04,
REG_PACR_H1_SVCR_ENABLE = 0x02,
REG_PACR_H1_STATUS_CTRL = 0x01,
};
enum {
REG_PBCR_SUBMODE_MASK = 0xc0,
REG_PBCR_SUBMODE_00 = 0x00, // 0 0
REG_PBCR_SUBMODE_01 = 0x40, // 0 1
REG_PBCR_SUBMODE_10 = 0x80, // 1 0
REG_PBCR_SUBMODE_11 = 0xc0, // 1 1
REG_PBCR_SUBMODE_1X = 0x80, // submode 2 or 3
REG_PBCR_H4_CTRL_MASK = 0x38,
REG_PBCR_H4_CTRL_IN_OUT = 0x20, // H4 sense always cleared if set
REG_PBCR_H4_CTRL_OUT_00 = 0x20, // H4 output negated
REG_PBCR_H4_CTRL_OUT_01 = 0x28, // H4 output asserted
REG_PBCR_H4_CTRL_OUT_10 = 0x30, // H4 output in interlocked input handshake protocol
REG_PBCR_H4_CTRL_OUT_11 = 0x38, // H4 output in pulsed input handshake protocol
REG_PBCR_H4_INT_ENABLE = 0x04,
REG_PBCR_H3_SVCRQ_ENABLE= 0x02,
REG_PBCR_H3_STATUS_CTRL = 0x01,
};
enum {
REG_PCDR_TIN_BIT = 2, // BIT number
REG_PCDR_TIN = 0x04 // bit position
};
enum {
REG_TCR_TIMER_ENABLE = 0x01
};
enum { // TCR - Timer Control register
REG_TCR_ENABLE = 0x01,
REG_TCR_CC_MASK = 0x06,
REG_TCR_CC_PC2_CLK_PSC = 0x00,