MC6801/6803 updates: [R. Belmont]

* Support for timer output capture to pin P21
  * Support for externally-clocked serial
  * Added devcb2 hook for serial xmit to easily differentiate xmit from other Port 2 updates.  Bits are still also sent to Port 2 of course.
This commit is contained in:
R. Belmont 2013-08-12 03:54:45 +00:00
parent cc03077c5b
commit 237e8e235f
2 changed files with 46 additions and 9 deletions

View File

@ -536,6 +536,7 @@ m6800_cpu_device::m6800_cpu_device(const machine_config &mconfig, const char *ta
, m_io_config("io", ENDIANNESS_BIG, 8, 9, 0)
, m_has_io(false)
, m_out_sc2_func(*this)
, m_out_sertx_func(*this)
, m_insn(m6800_insn)
, m_cycles(cycles_6800)
{
@ -548,6 +549,7 @@ m6800_cpu_device::m6800_cpu_device(const machine_config &mconfig, device_type ty
, m_io_config("io", ENDIANNESS_BIG, 8, 9, 0)
, m_has_io(has_io)
, m_out_sc2_func(*this)
, m_out_sertx_func(*this)
, m_insn(insn)
, m_cycles(cycles)
{
@ -730,6 +732,15 @@ void m6800_cpu_device::check_timer_event()
m_wai_state &= ~M6800_SLP;
if ( !(CC & 0x10) && (m_tcsr & TCSR_EOCI))
TAKE_OCI;
// if output on P21 is enabled, let's do it
if (m_port2_ddr & 2)
{
m_port2_data &= ~2;
m_port2_data |= (m_tcsr & TCSR_OLVL) << 1;
m_port2_written = 1;
write_port2();
}
}
/* TOI */
if( CTD >= TOD)
@ -767,7 +778,12 @@ void m6800_cpu_device::set_rmcr(UINT8 data)
switch ((m_rmcr & M6800_RMCR_CC_MASK) >> 2)
{
case 0:
case 3: // not implemented
m_sci_timer->enable(false);
m_use_ext_serclock = false;
break;
case 3: // external clock
m_use_ext_serclock = true;
m_sci_timer->enable(false);
break;
@ -778,6 +794,7 @@ void m6800_cpu_device::set_rmcr(UINT8 data)
int clock = m_clock / m_clock_divider;
m_sci_timer->adjust(attotime::from_hz(clock / divisor), 0, attotime::from_hz(clock / divisor));
m_use_ext_serclock = false;
}
break;
}
@ -844,8 +861,8 @@ void m6800_cpu_device::serial_transmit()
case M6800_SERIAL_START:
if (m_trcsr & M6800_TRCSR_TDRE)
{
// transmit buffer is empty, send consecutive '1's
m_tx = 1;
// transmit buffer is empty, send nothing
return;
}
else
{
@ -892,6 +909,7 @@ void m6800_cpu_device::serial_transmit()
break;
}
m_out_sertx_func((m_tx == 1) ? ASSERT_LINE : CLEAR_LINE);
m_port2_written = 1;
write_port2();
}
@ -1023,6 +1041,7 @@ void m6800_cpu_device::device_start()
m_io = &space(AS_IO);
m_out_sc2_func.resolve_safe();
m_out_sertx_func.resolve_safe();
m_sci_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(m6800_cpu_device::sci_tick),this));
save_item(NAME(m_ppc.w.l));
@ -1144,6 +1163,8 @@ void m6800_cpu_device::device_reset()
m_trcsr_read_tdre = 0;
m_trcsr_read_orfe = 0;
m_trcsr_read_rdrf = 0;
m_ext_serclock = 0;
m_use_ext_serclock = false;
set_rmcr(0);
}
@ -1479,9 +1500,6 @@ WRITE8_MEMBER( m6800_cpu_device::m6801_io_w )
{
m_port2_ddr = data;
write_port2();
if (m_port2_ddr & 2)
logerror("CPU '%s' PC %04x: warning - port 2 bit 1 set as output (OLVL) - not supported\n",space.device().tag(),space.device().safe_pc());
}
break;
@ -1683,6 +1701,20 @@ WRITE8_MEMBER( m6800_cpu_device::m6801_io_w )
}
}
void m6801_cpu_device::m6801_clock_serial()
{
if (m_use_ext_serclock)
{
m_ext_serclock++;
if (m_ext_serclock >= 8)
{
m_ext_serclock = 0;
serial_transmit();
serial_receive();
}
}
}
offs_t m6800_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
{
@ -1739,4 +1771,3 @@ offs_t nsc8105_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UIN
return CPU_DISASSEMBLE_NAME(nsc8105)(this, buffer, pc, oprom, opram, options);
}

View File

@ -46,7 +46,8 @@ enum
#define MCFG_M6801_SC2(_devcb) \
m6800_cpu_device::set_out_sc2_func(*device, DEVCB2_##_devcb);
#define MCFG_M6801_SER_TX(_devcb) \
m6800_cpu_device::set_out_sertx_func(*device, DEVCB2_##_devcb);
class m6800_cpu_device : public cpu_device
{
@ -59,6 +60,7 @@ public:
// static configuration helpers
template<class _Object> static devcb2_base &set_out_sc2_func(device_t &device, _Object object) { return downcast<m6800_cpu_device &>(device).m_out_sc2_func.set_callback(object); }
template<class _Object> static devcb2_base &set_out_sertx_func(device_t &device, _Object object) { return downcast<m6800_cpu_device &>(device).m_out_sertx_func.set_callback(object); }
DECLARE_READ8_MEMBER( m6801_io_r );
DECLARE_WRITE8_MEMBER( m6801_io_w );
@ -92,6 +94,7 @@ protected:
bool m_has_io;
devcb2_write_line m_out_sc2_func;
devcb2_write_line m_out_sertx_func;
PAIR m_ppc; /* Previous program counter */
PAIR m_pc; /* Program counter */
@ -135,7 +138,8 @@ protected:
int m_clock_divider;
UINT8 m_trcsr, m_rmcr, m_rdr, m_tdr, m_rsr, m_tsr;
int m_rxbits, m_txbits, m_txstate, m_trcsr_read_tdre, m_trcsr_read_orfe, m_trcsr_read_rdrf, m_tx;
int m_rxbits, m_txbits, m_txstate, m_trcsr_read_tdre, m_trcsr_read_orfe, m_trcsr_read_rdrf, m_tx, m_ext_serclock;
bool m_use_ext_serclock;
int m_port2_written;
int m_icount;
@ -425,6 +429,8 @@ public:
m6801_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
m6801_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source, const m6800_cpu_device::op_func *insn, const UINT8 *cycles, address_map_constructor internal = NULL);
void m6801_clock_serial();
protected:
virtual UINT64 execute_clocks_to_cycles(UINT64 clocks) const { return (clocks + 4 - 1) / 4; }
virtual UINT64 execute_cycles_to_clocks(UINT64 cycles) const { return (cycles * 4); }