mirror of
https://github.com/holub/mame
synced 2025-04-27 02:33:13 +03:00
68340: simplified code by making the timer module implementation a device and created two independent instanses, as it should be
This commit is contained in:
parent
9100c4e0d7
commit
08d77828bf
@ -9,7 +9,6 @@
|
||||
|
||||
DEFINE_DEVICE_TYPE(M68340, m68340_cpu_device, "mc68340", "MC68340")
|
||||
|
||||
|
||||
int m68340_cpu_device::calc_cs(offs_t address) const
|
||||
{
|
||||
if ( !(m68340SIM->m_ba[0] & 1) ) return 1;
|
||||
@ -88,9 +87,12 @@ WRITE32_MEMBER( m68340_cpu_device::m68340_internal_base_w )
|
||||
internal->install_readwrite_handler(base + 0x040, base + 0x05f,
|
||||
read32_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_cs_r),this),
|
||||
write32_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_cs_w),this));
|
||||
internal->install_readwrite_handler(base + 0x600, base + 0x67f,
|
||||
read16_delegate(FUNC(m68340_cpu_device::m68340_internal_timer_r),this),
|
||||
write16_delegate(FUNC(m68340_cpu_device::m68340_internal_timer_w),this),0xffffffff);
|
||||
internal->install_readwrite_handler(base + 0x600, base + 0x63f,
|
||||
READ16_DEVICE_DELEGATE(m_timer1, mc68340_timer_module_device, read),
|
||||
WRITE16_DEVICE_DELEGATE(m_timer1, mc68340_timer_module_device, write),0xffffffff);
|
||||
internal->install_readwrite_handler(base + 0x640, base + 0x67f,
|
||||
READ16_DEVICE_DELEGATE(m_timer2, mc68340_timer_module_device, read),
|
||||
WRITE16_DEVICE_DELEGATE(m_timer2, mc68340_timer_module_device, write),0xffffffff);
|
||||
internal->install_readwrite_handler(base + 0x700, base + 0x723,
|
||||
READ8_DEVICE_DELEGATE(m_serial, mc68340_serial_module_device, read),
|
||||
WRITE8_DEVICE_DELEGATE(m_serial, mc68340_serial_module_device, write),0xffffffff);
|
||||
@ -121,6 +123,8 @@ ADDRESS_MAP_END
|
||||
MACHINE_CONFIG_MEMBER( m68340_cpu_device::device_add_mconfig )
|
||||
MCFG_DEVICE_ADD("serial", MC68340_SERIAL_MODULE, 0)
|
||||
MCFG_MC68340SER_IRQ_CALLBACK(DEVWRITELINE("serial", mc68340_serial_module_device, irq_w))
|
||||
MCFG_DEVICE_ADD("timer1", MC68340_TIMER_MODULE, 0)
|
||||
MCFG_DEVICE_ADD("timer2", MC68340_TIMER_MODULE, 0)
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
|
||||
@ -131,6 +135,8 @@ MACHINE_CONFIG_END
|
||||
m68340_cpu_device::m68340_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: fscpu32_device(mconfig, tag, owner, clock, M68340, 32,32, ADDRESS_MAP_NAME(m68340_internal_map))
|
||||
, m_serial(*this, "serial")
|
||||
, m_timer1(*this, "timer1")
|
||||
, m_timer2(*this, "timer2")
|
||||
, m_clock_mode(0)
|
||||
, m_crystal(0)
|
||||
, m_extal(0)
|
||||
@ -138,24 +144,12 @@ m68340_cpu_device::m68340_cpu_device(const machine_config &mconfig, const char *
|
||||
, m_pa_in_cb(*this)
|
||||
, m_pb_out_cb(*this)
|
||||
, m_pb_in_cb(*this)
|
||||
, m_tout1_out_cb(*this)
|
||||
, m_tin1_in_cb(*this)
|
||||
, m_tgate1_in_cb(*this)
|
||||
, m_tout2_out_cb(*this)
|
||||
, m_tin2_in_cb(*this)
|
||||
, m_tgate2_in_cb(*this)
|
||||
{
|
||||
m68340SIM = nullptr;
|
||||
m68340DMA = nullptr;
|
||||
m68340TIMER = nullptr;
|
||||
m68340_base = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void m68340_cpu_device::device_reset()
|
||||
{
|
||||
fscpu32_device::device_reset();
|
||||
@ -176,14 +170,11 @@ void m68340_cpu_device::device_start()
|
||||
|
||||
m68340SIM = new m68340_sim();
|
||||
m68340DMA = new m68340_dma();
|
||||
m68340TIMER = new m68340_timer();
|
||||
|
||||
m68340SIM->reset();
|
||||
m68340DMA->reset();
|
||||
m68340TIMER->reset();
|
||||
|
||||
start_68340_sim();
|
||||
start_68340_timer();
|
||||
|
||||
m68340_base = 0x00000000;
|
||||
|
||||
|
@ -52,6 +52,7 @@
|
||||
class m68340_cpu_device : public fscpu32_device
|
||||
{
|
||||
friend class mc68340_serial_module_device;
|
||||
friend class mc68340_timer_module_device;
|
||||
|
||||
public:
|
||||
m68340_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
@ -61,12 +62,12 @@ public:
|
||||
template <class Object> static devcb_base &set_pb_in_callback (device_t &device, Object &&cb){ return downcast<m68340_cpu_device &>(device).m_pb_in_cb.set_callback (std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_pb_out_callback (device_t &device, Object &&cb){ return downcast<m68340_cpu_device &>(device).m_pb_out_cb.set_callback (std::forward<Object>(cb)); }
|
||||
|
||||
template <class Object> static devcb_base &set_tout1_out_callback (device_t &device, Object &&cb){ return downcast<m68340_cpu_device &>(device).m_tout1_out_cb.set_callback (std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_tin1_in_callback (device_t &device, Object &&cb) { return downcast<m68340_cpu_device &>(device).m_tin1_in_cb.set_callback (std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_tgate1_in_callback (device_t &device, Object &&cb){ return downcast<m68340_cpu_device &>(device).m_tgate1_in_cb.set_callback (std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_tout2_out_callback (device_t &device, Object &&cb){ return downcast<m68340_cpu_device &>(device).m_tout2_out_cb.set_callback (std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_tin2_in_callback (device_t &device, Object &&cb) { return downcast<m68340_cpu_device &>(device).m_tin2_in_cb.set_callback (std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_tgate2_in_callback (device_t &device, Object &&cb){ return downcast<m68340_cpu_device &>(device).m_tgate2_in_cb.set_callback (std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_tout1_out_callback (device_t &device, Object &&cb){ return downcast<m68340_cpu_device &>(device).m_timer1->m_tout_out_cb.set_callback (std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_tin1_in_callback (device_t &device, Object &&cb) { return downcast<m68340_cpu_device &>(device).m_timer1->m_tin_in_cb.set_callback (std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_tgate1_in_callback (device_t &device, Object &&cb){ return downcast<m68340_cpu_device &>(device).m_timer1->m_tgate_in_cb.set_callback (std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_tout2_out_callback (device_t &device, Object &&cb){ return downcast<m68340_cpu_device &>(device).m_timer2->m_tout_out_cb.set_callback (std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_tin2_in_callback (device_t &device, Object &&cb) { return downcast<m68340_cpu_device &>(device).m_timer2->m_tin_in_cb.set_callback (std::forward<Object>(cb)); }
|
||||
template <class Object> static devcb_base &set_tgate2_in_callback (device_t &device, Object &&cb){ return downcast<m68340_cpu_device &>(device).m_timer2->m_tgate_in_cb.set_callback (std::forward<Object>(cb)); }
|
||||
|
||||
uint16_t get_cs(offs_t address);
|
||||
|
||||
@ -88,18 +89,16 @@ public:
|
||||
WRITE16_MEMBER( m68340_internal_sim_w );
|
||||
WRITE8_MEMBER( m68340_internal_sim_ports_w );
|
||||
WRITE32_MEMBER( m68340_internal_sim_cs_w );
|
||||
READ16_MEMBER( m68340_internal_timer_r );
|
||||
WRITE16_MEMBER( m68340_internal_timer_w );
|
||||
|
||||
// Clock/VCO setting TODO: support external clock with PLL and Limp mode
|
||||
DECLARE_WRITE_LINE_MEMBER( set_modck );
|
||||
DECLARE_WRITE_LINE_MEMBER( extal_w );
|
||||
|
||||
// Timer input methods, can be used instead of the corresponding polling MCFG callbacks
|
||||
DECLARE_WRITE_LINE_MEMBER( tin1_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( tgate1_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( tin2_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( tgate2_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( tin1_w ) { m_timer1->tin_w(state); }
|
||||
DECLARE_WRITE_LINE_MEMBER( tgate1_w ){ m_timer1->tgate_w(state); }
|
||||
DECLARE_WRITE_LINE_MEMBER( tin2_w ) { m_timer2->tin_w(state); }
|
||||
DECLARE_WRITE_LINE_MEMBER( tgate2_w ){ m_timer2->tgate_w(state); }
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
@ -107,19 +106,17 @@ protected:
|
||||
virtual void device_add_mconfig(machine_config &config) override;
|
||||
|
||||
required_device<mc68340_serial_module_device> m_serial;
|
||||
required_device<mc68340_timer_module_device> m_timer1;
|
||||
required_device<mc68340_timer_module_device> m_timer2;
|
||||
|
||||
TIMER_CALLBACK_MEMBER(periodic_interrupt_timer_callback);
|
||||
TIMER_CALLBACK_MEMBER(timer1_callback);
|
||||
TIMER_CALLBACK_MEMBER(timer2_callback);
|
||||
|
||||
void start_68340_sim();
|
||||
void start_68340_timer();
|
||||
void do_pit_irq();
|
||||
void do_tick_pit();
|
||||
void do_timer_irq(int id);
|
||||
void do_timer_tick(int id);
|
||||
|
||||
int calc_cs(offs_t address) const;
|
||||
int get_timer_index(mc68340_timer_module_device *timer) { return (timer == m_timer1) ? 0 : 1; }
|
||||
|
||||
int m_currentcs;
|
||||
uint32_t m_clock_mode;
|
||||
@ -130,7 +127,6 @@ protected:
|
||||
/* 68340 peripheral modules */
|
||||
m68340_sim* m68340SIM;
|
||||
m68340_dma* m68340DMA;
|
||||
m68340_timer* m68340TIMER;
|
||||
|
||||
uint32_t m68340_base;
|
||||
|
||||
@ -140,12 +136,6 @@ protected:
|
||||
devcb_read8 m_pa_in_cb;
|
||||
devcb_write8 m_pb_out_cb;
|
||||
devcb_read8 m_pb_in_cb;
|
||||
devcb_write_line m_tout1_out_cb;
|
||||
devcb_write_line m_tin1_in_cb;
|
||||
devcb_write_line m_tgate1_in_cb;
|
||||
devcb_write_line m_tout2_out_cb;
|
||||
devcb_write_line m_tin2_in_cb;
|
||||
devcb_write_line m_tgate2_in_cb;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(M68340, m68340_cpu_device)
|
||||
|
@ -4,7 +4,6 @@
|
||||
|
||||
/*
|
||||
* TODO:
|
||||
* - Make the timer a device and instantiate two from 68340.cpp
|
||||
* - implement all timer modes, only "Input Capture/Output Compare" mode is verified to work
|
||||
*/
|
||||
|
||||
@ -38,60 +37,56 @@
|
||||
#define FUNCNAME __PRETTY_FUNCTION__
|
||||
#endif
|
||||
|
||||
READ16_MEMBER( m68340_cpu_device::m68340_internal_timer_r )
|
||||
READ16_MEMBER( mc68340_timer_module_device::read )
|
||||
{
|
||||
LOGSETUP("%s\n", FUNCNAME);
|
||||
|
||||
assert(m68340TIMER);
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
int val = 0;
|
||||
|
||||
int pc = space.device().safe_pc();
|
||||
LOGR("%08x m68340_internal_timer_r %08x, (%08x)\n", pc, offset * 2, mem_mask);
|
||||
|
||||
int id = (offset * 2) < 0x40 ? 0 : 1; // Timer1 or Timer2
|
||||
|
||||
/*Setting the STP bit stops all clocks within the timer module except for the clock
|
||||
from the IMB. The clock from the IMB remains active to allow the CPU32 access to the MCR.
|
||||
Accesses to timer module registers while in stop mode produce a bus error. */
|
||||
if ( (timer.m_mcr[id] & m68340_timer::REG_MCR_STP) && ((offset * 2) % 0x40) != m68340_timer::REG_MCR)
|
||||
if ( (m_mcr & REG_MCR_STP) && (offset * 2) != REG_MCR)
|
||||
{
|
||||
logerror("Attempt to access timer registers while timer clocks are stopped, STP bit in MCR is set!");
|
||||
return val; // TODO: Should cause BUSERROR
|
||||
}
|
||||
|
||||
switch ((offset * 2) % 0x40)
|
||||
switch (offset * 2)
|
||||
{
|
||||
case m68340_timer::REG_MCR:
|
||||
val = timer.m_mcr[id];
|
||||
case REG_MCR:
|
||||
val = m_mcr;
|
||||
LOGTIMER("- %08x %s %04x, %04x (%04x) (MCR - Module Configuration Register)\n", pc, FUNCNAME, offset * 2, val, mem_mask);
|
||||
break;
|
||||
case m68340_timer::REG_IR:
|
||||
val = timer.m_ir[id];
|
||||
case REG_IR:
|
||||
val = m_ir;
|
||||
LOGTIMER("- %08x %s %04x, %04x (%04x) (IR - Interrupt Register)\n", pc, FUNCNAME, offset * 2, val, mem_mask);
|
||||
break;
|
||||
case m68340_timer::REG_CR:
|
||||
val = timer.m_cr[id];
|
||||
case REG_CR:
|
||||
val = m_cr;
|
||||
LOGTIMER("- %08x %s %04x, %04x (%04x) (CR - Control Register)\n", pc, FUNCNAME, offset * 2, val, mem_mask);
|
||||
break;
|
||||
case m68340_timer::REG_SR:
|
||||
val = timer.m_sr[id];
|
||||
case REG_SR:
|
||||
val = m_sr;
|
||||
LOGTIMER("- %08x %s %04x, %04x (%04x) (SR - Status/Prescaler Register)\n", pc, FUNCNAME, offset * 2, val, mem_mask);
|
||||
break;
|
||||
case m68340_timer::REG_CNTR:
|
||||
val = timer.m_cntr_reg[id];
|
||||
case REG_CNTR:
|
||||
val = m_cntr_reg;
|
||||
LOGTIMER("- %08x %s %04x, %04x (%04x) (CNTR - Counter Register)\n", pc, FUNCNAME, offset * 2, val, mem_mask);
|
||||
break;
|
||||
case m68340_timer::REG_PREL1:
|
||||
val = timer.m_prel1[id];
|
||||
case REG_PREL1:
|
||||
val = m_prel1;
|
||||
LOGTIMER("- %08x %s %04x, %04x (%04x) (PREL1 - Preload 1 Register)\n", pc, FUNCNAME, offset * 2, val, mem_mask);
|
||||
break;
|
||||
case m68340_timer::REG_PREL2:
|
||||
val = timer.m_prel2[id];
|
||||
case REG_PREL2:
|
||||
val = m_prel2;
|
||||
LOGTIMER("- %08x %s %04x, %04x (%04x) (PREL2 - Preload 2 Register)\n", pc, FUNCNAME, offset * 2, val, mem_mask);
|
||||
break;
|
||||
case m68340_timer::REG_COM:
|
||||
val = timer.m_com[id];
|
||||
case REG_COM:
|
||||
val = m_com;
|
||||
LOGTIMER("- %08x %s %04x, %04x (%04x) (COM - Compare Register)\n", pc, FUNCNAME, offset * 2, val, mem_mask);
|
||||
break;
|
||||
default:
|
||||
@ -99,62 +94,59 @@ READ16_MEMBER( m68340_cpu_device::m68340_internal_timer_r )
|
||||
logerror("%08x m68340_internal_timer_r %08x, %08x (%08x)\n", pc, offset * 2, val, mem_mask);
|
||||
break;
|
||||
}
|
||||
LOGR(" * Timer%d Reg %02x [%02x] -> %02x - %s\n", id + 1, offset * 2 % 0x40, offset, val, ((offset * 2) % 0x40) > 0x12 ? "reserved" : std::array<char const *, 9> {{"MCR", "reserved", "IR", "CR", "SR", "CNTR", "PREL1", "PREL2", "COM"}}[offset % 0x20]);
|
||||
LOGR(" * Timer%d Reg %02x [%02x] -> %02x - %s\n", m_cpu->get_timer_index(this) + 1, offset * 2, offset, val, (offset * 2) > 0x12 ? "reserved" : std::array<char const *, 9> {{"MCR", "reserved", "IR", "CR", "SR", "CNTR", "PREL1", "PREL2", "COM"}}[offset % 0x20]);
|
||||
return val;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER( m68340_cpu_device::m68340_internal_timer_w )
|
||||
WRITE16_MEMBER( mc68340_timer_module_device::write )
|
||||
{
|
||||
int id = (offset * 2) < 0x40 ? 0 : 1; // Timer1 or Timer2
|
||||
int pc = space.device().safe_pc();
|
||||
|
||||
LOGSETUP("\n%s\n", FUNCNAME);
|
||||
LOGSETUP(" * Timer%d Reg %02x [%02x] <- %02x - %s\n", id + 1, (offset * 2) % 0x40, offset, data,
|
||||
((offset * 2) % 0x40) > 0x12 ? "reserved" : std::array<char const *, 9>
|
||||
LOGSETUP(" * Timer%d Reg %02x [%02x] <- %02x - %s\n", m_cpu->get_timer_index(this) + 1, (offset * 2), offset, data,
|
||||
(offset * 2) > 0x12 ? "reserved" : std::array<char const *, 9>
|
||||
{{"MCR", "reserved", "IR", "CR", "SR", "CNTR", "PREL1", "PREL2", "COM"}}[offset % 0x20]);
|
||||
|
||||
assert(m68340TIMER);
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
|
||||
/*Setting the STP bit stops all clocks within the timer module except for the clock
|
||||
from the IMB. The clock from the IMB remains active to allow the CPU32 access to the MCR.
|
||||
Accesses to timer module registers while in stop mode produce a bus error. */
|
||||
if ( (timer.m_mcr[id] & m68340_timer::REG_MCR_STP) && ((offset * 2) % 0x40) != m68340_timer::REG_MCR)
|
||||
if ( (m_mcr & REG_MCR_STP) && (offset * 2) != REG_MCR)
|
||||
{
|
||||
logerror("Attempt to access timer registers while timer clocks are stopped, STP bit in MCR is set!");
|
||||
return; // TODO: Should cause BUSERROR
|
||||
}
|
||||
|
||||
switch ((offset * 2) % 0x40)
|
||||
switch (offset * 2)
|
||||
{
|
||||
case m68340_timer::REG_MCR:
|
||||
COMBINE_DATA(&timer.m_mcr[id]);
|
||||
case REG_MCR:
|
||||
COMBINE_DATA(&m_mcr);
|
||||
LOGTIMER("PC: %08x %s %04x, %04x (%04x) (MCR - Module Configuration Register)\n", pc, FUNCNAME, offset * 2, data, mem_mask);
|
||||
LOGTIMER("- Clocks are %s\n", data & m68340_timer::REG_MCR_STP ? "stopped" : "running");
|
||||
LOGTIMER("- Freeze signal %s - not implemented\n", data & m68340_timer::REG_MCR_FRZ1 ? "stops execution" : "is ignored");
|
||||
LOGTIMER("- Supervisor registers %s - not implemented\n", data & m68340_timer::REG_MCR_SUPV ? "requries supervisor privileges" : "can be accessed by user privileged software");
|
||||
LOGTIMER("- Interrupt Arbitration level: %02x - not implemented\n", data & m68340_timer::REG_MCR_ARBLV);
|
||||
LOGTIMER("- Clocks are %s\n", data & REG_MCR_STP ? "stopped" : "running");
|
||||
LOGTIMER("- Freeze signal %s - not implemented\n", data & REG_MCR_FRZ1 ? "stops execution" : "is ignored");
|
||||
LOGTIMER("- Supervisor registers %s - not implemented\n", data & REG_MCR_SUPV ? "requries supervisor privileges" : "can be accessed by user privileged software");
|
||||
LOGTIMER("- Interrupt Arbitration level: %02x - not implemented\n", data & REG_MCR_ARBLV);
|
||||
break;
|
||||
case m68340_timer::REG_IR:
|
||||
COMBINE_DATA(&timer.m_ir[id]);
|
||||
case REG_IR:
|
||||
COMBINE_DATA(&m_ir);
|
||||
LOGTIMER("PC: %08x %s %04x, %04x (%04x) (IR - Interrupt Register)\n", pc, FUNCNAME, offset * 2, data, mem_mask);
|
||||
LOGTIMER("- Interrupt level : %02x\n", (data & m68340_timer::REG_IR_INTLEV) >> 8);
|
||||
LOGTIMER("- Interrupt vector: %02x\n", (data & m68340_timer::REG_IR_INTVEC));
|
||||
LOGTIMER("- Interrupt level : %02x\n", (data & REG_IR_INTLEV) >> 8);
|
||||
LOGTIMER("- Interrupt vector: %02x\n", (data & REG_IR_INTVEC));
|
||||
break;
|
||||
case m68340_timer::REG_CR:
|
||||
COMBINE_DATA(&timer.m_cr[id]);
|
||||
case REG_CR:
|
||||
COMBINE_DATA(&m_cr);
|
||||
LOGTIMER("PC %08x %s %04x, %04x (%04x) (CR - Module Control Register)\n", pc, FUNCNAME, offset * 2, data, mem_mask);
|
||||
LOGTIMER("- Software reset: %s\n", (data & m68340_timer::REG_CR_SWR) ? "inactive" : "active" );
|
||||
LOGTIMER("- Software reset: %s\n", (data & REG_CR_SWR) ? "inactive" : "active" );
|
||||
LOGTIMER("- Enabled interrupts: %02x TO:%d TG:%d TC:%d\n",
|
||||
data & m68340_timer::REG_CR_INTMSK,
|
||||
(data & m68340_timer::REG_CR_IE0) ? 1 : 0,
|
||||
(data & m68340_timer::REG_CR_IE1) ? 1 : 0,
|
||||
(data & m68340_timer::REG_CR_IE2) ? 1 : 0);
|
||||
LOGTIMER("- TGE signal, TGATE%d is %s\n", id + 1, (data & m68340_timer::REG_CR_TGE) ? "enabled" : "disabled");
|
||||
LOGTIMER("- PCLK: Counter uses %s\n", (data & m68340_timer::REG_CR_PCLK) ? "prescaler" : "clock");
|
||||
LOGTIMER("- CPE: Counter is %s\n", (data & m68340_timer::REG_CR_CPE) ? "enabled" : "disabled");
|
||||
LOGTIMER("- CLK: Clock is %s\n", (data & m68340_timer::REG_CR_CLK) ? "TIN (external)" : "system clock / 2");
|
||||
LOGTIMER("- Prescaler: Divide by %d\n", (data & m68340_timer::REG_CR_POT_MASK) ? ( 1 << ((data & m68340_timer::REG_CR_POT_MASK) >> 5)) : 256);
|
||||
LOGTIMER("- Prescaler: Divide by %d\n", (0x101 << ((data & m68340_timer::REG_CR_POT_MASK) >> 5) & 0x1fe));
|
||||
data & REG_CR_INTMSK,
|
||||
(data & REG_CR_IE0) ? 1 : 0,
|
||||
(data & REG_CR_IE1) ? 1 : 0,
|
||||
(data & REG_CR_IE2) ? 1 : 0);
|
||||
LOGTIMER("- TGE signal, TGATE%d is %s\n", m_cpu->get_timer_index(this) + 1, (data & REG_CR_TGE) ? "enabled" : "disabled");
|
||||
LOGTIMER("- PCLK: Counter uses %s\n", (data & REG_CR_PCLK) ? "prescaler" : "clock");
|
||||
LOGTIMER("- CPE: Counter is %s\n", (data & REG_CR_CPE) ? "enabled" : "disabled");
|
||||
LOGTIMER("- CLK: Clock is %s\n", (data & REG_CR_CLK) ? "TIN (external)" : "system clock / 2");
|
||||
LOGTIMER("- Prescaler: Divide by %d\n", (data & REG_CR_POT_MASK) ? ( 1 << ((data & REG_CR_POT_MASK) >> 5)) : 256);
|
||||
LOGTIMER("- Prescaler: Divide by %d\n", (0x101 << ((data & REG_CR_POT_MASK) >> 5) & 0x1fe));
|
||||
LOGTIMER("- MODE: %s\n", std::array<char const *, 8>
|
||||
{{ "Input Capture/Output Compare",
|
||||
"Square-Wave Generator - not implemented",
|
||||
@ -164,89 +156,89 @@ WRITE16_MEMBER( m68340_cpu_device::m68340_internal_timer_w )
|
||||
"Period Measurement - not implemented",
|
||||
"Event Count - not implemented",
|
||||
"Timer Bypass (Simple Test Method) - not implemented"
|
||||
}}[data & m68340_timer::REG_CR_MODE_MASK]);
|
||||
}}[data & REG_CR_MODE_MASK]);
|
||||
|
||||
LOGTIMER("- OC: %s mode\n", std::array<char const *, 4>{{"Disabled", "Toggle", "Zero", "One"}}[data & m68340_timer::REG_CR_OC_MASK]);
|
||||
LOGTIMER("- OC: %s mode\n", std::array<char const *, 4>{{"Disabled", "Toggle", "Zero", "One"}}[data & REG_CR_OC_MASK]);
|
||||
|
||||
/* The timer is enabled when the counter prescaler enable (CPE) and SWRx bits in the CR
|
||||
are set. Once enabled, the counter enable (ON) bit in the SR is set, and the next falling
|
||||
edge of the counter clock causes the counter to be loaded with the value in the preload 1
|
||||
register (PREL1). TODO: make sure of the intial load of PREL1 on first falling flank */
|
||||
if (timer.m_cr[id] & m68340_timer::REG_CR_SWR)
|
||||
if (m_cr & REG_CR_SWR)
|
||||
{
|
||||
if (timer.m_cr[id] & m68340_timer::REG_CR_CPE)
|
||||
if (m_cr & REG_CR_CPE)
|
||||
{
|
||||
timer.m_sr[id] |= m68340_timer::REG_SR_ON; // Starts the counter
|
||||
LOGTIMER("Starts counter %d\n", id);
|
||||
if ((timer.m_cr[id] & m68340_timer::REG_CR_CLK) == 0)
|
||||
m_sr |= REG_SR_ON; // Starts the counter
|
||||
LOGTIMER("Starts counter %d\n", m_cpu->get_timer_index(this));
|
||||
if ((m_cr & REG_CR_CLK) == 0)
|
||||
{
|
||||
LOGTIMER("- Using system clock/2\n");
|
||||
timer.m_timer[id]->adjust(cycles_to_attotime( (clock() / 2) / (0x101 << ((timer.m_cr[id] & m68340_timer::REG_CR_POT_MASK) >> 5) & 0x1fe) * 2));
|
||||
m_timer->adjust(m_cpu->cycles_to_attotime( (m_cpu->clock() / 2) / (0x101 << ((m_cr & REG_CR_POT_MASK) >> 5) & 0x1fe) * 2) );
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGTIMER("- Using TIN%d\n", id);
|
||||
LOGTIMER("- Using TIN%d\n", m_cpu->get_timer_index(this));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
timer.m_sr[id] &= ~m68340_timer::REG_SR_ON; // Stops the counter
|
||||
LOGTIMER("Stops counter %d\n", id);
|
||||
timer.m_timer[id]->adjust(attotime::never);
|
||||
m_sr &= ~REG_SR_ON; // Stops the counter
|
||||
LOGTIMER("Stops counter %d\n", m_cpu->get_timer_index(this));
|
||||
m_timer->adjust(attotime::never);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // TODO: Detect Disable mode setting line to three state
|
||||
if ((timer.m_cr[id] & m68340_timer::REG_CR_OC_MASK) == m68340_timer::REG_CR_OC_ONE)
|
||||
if ((m_cr & REG_CR_OC_MASK) == REG_CR_OC_ONE)
|
||||
{
|
||||
id == 0 ? m_tout1_out_cb(ASSERT_LINE) : m_tout2_out_cb(ASSERT_LINE);
|
||||
m_tout_out_cb(ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
id == 0 ? m_tout1_out_cb(CLEAR_LINE) : m_tout2_out_cb(CLEAR_LINE);
|
||||
m_tout_out_cb(CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case m68340_timer::REG_SR:
|
||||
case REG_SR:
|
||||
LOGTIMER("PC %08x %s %04x, %04x (%04x) (SR - Status/Prescaler Register)\n", pc, FUNCNAME, offset * 2, data, mem_mask);
|
||||
|
||||
/* IRQ - Interrupt Request bit
|
||||
1 = An interrupt condition has occurred. This bit is the logical OR of the enabled TO, TG, and TC interrupt bits.
|
||||
0 = The bit(s) that caused the interrupt condition has been cleared. If an IRQ signal has been asserted, it is negated when this bit is cleared. */
|
||||
data = (timer.m_sr[id] & ~(data & (m68340_timer::REG_SR_TO | m68340_timer::REG_SR_TG | m68340_timer::REG_SR_TC))); // Clear only the set interrupt bits
|
||||
if ((data & (m68340_timer::REG_SR_TO | m68340_timer::REG_SR_TG | m68340_timer::REG_SR_TC)) == 0)
|
||||
data = (m_sr & ~(data & (REG_SR_TO | REG_SR_TG | REG_SR_TC))); // Clear only the set interrupt bits
|
||||
if ((data & (REG_SR_TO | REG_SR_TG | REG_SR_TC)) == 0)
|
||||
{
|
||||
data &= ~m68340_timer::REG_SR_IRQ;
|
||||
data &= ~REG_SR_IRQ;
|
||||
// TODO: clear IRQ line
|
||||
}
|
||||
COMBINE_DATA(&timer.m_sr[id]);
|
||||
COMBINE_DATA(&m_sr);
|
||||
LOGTIMER("PC %08x %s %04x, %04x (%04x) (SR - Status/Prescaler Register)\n", pc, FUNCNAME, offset * 2, data, mem_mask);
|
||||
LOGTIMER("- IRQ: %s\n", (data & m68340_timer::REG_SR_IRQ) ? "Yes" : "None");
|
||||
LOGTIMER("- TO TimeOut int : %s\n", (data & m68340_timer::REG_SR_TO) ? "Asserted" : "Cleared");
|
||||
LOGTIMER("- TG Timer Gate int : %s\n", (data & m68340_timer::REG_SR_TG) ? "Asserted" : "Cleared");
|
||||
LOGTIMER("- TC Timer Counter int: %s\n", (data & m68340_timer::REG_SR_TC) ? "Asserted" : "Cleared");
|
||||
LOGTIMER("- TGL: %s\n", (data & m68340_timer::REG_SR_TGL) ? "Negated" : "Asserted");
|
||||
LOGTIMER("- ON Counter is: %s\n", (data & m68340_timer::REG_SR_ON) ? "Enabled" : "Disabled");
|
||||
LOGTIMER("- OUT: Tout is %s\n", (data & m68340_timer::REG_SR_OUT) ? "1" : "0 or three-stated");
|
||||
LOGTIMER("- COM: Compare is %s\n", (data & m68340_timer::REG_SR_COM) ? "Match" : "Cleared");
|
||||
LOGTIMER("- PO7-PO0: %02x\n", (data & m68340_timer::REG_SR_PSC_OUT));
|
||||
LOGTIMER("- IRQ: %s\n", (data & REG_SR_IRQ) ? "Yes" : "None");
|
||||
LOGTIMER("- TO TimeOut int : %s\n", (data & REG_SR_TO) ? "Asserted" : "Cleared");
|
||||
LOGTIMER("- TG Timer Gate int : %s\n", (data & REG_SR_TG) ? "Asserted" : "Cleared");
|
||||
LOGTIMER("- TC Timer Counter int: %s\n", (data & REG_SR_TC) ? "Asserted" : "Cleared");
|
||||
LOGTIMER("- TGL: %s\n", (data & REG_SR_TGL) ? "Negated" : "Asserted");
|
||||
LOGTIMER("- ON Counter is: %s\n", (data & REG_SR_ON) ? "Enabled" : "Disabled");
|
||||
LOGTIMER("- OUT: Tout is %s\n", (data & REG_SR_OUT) ? "1" : "0 or three-stated");
|
||||
LOGTIMER("- COM: Compare is %s\n", (data & REG_SR_COM) ? "Match" : "Cleared");
|
||||
LOGTIMER("- PO7-PO0: %02x\n", (data & REG_SR_PSC_OUT));
|
||||
break;
|
||||
case m68340_timer::REG_CNTR:
|
||||
COMBINE_DATA(&timer.m_cntr_reg[id]);
|
||||
case REG_CNTR:
|
||||
COMBINE_DATA(&m_cntr_reg);
|
||||
LOGTIMER("- %08x %s %04x, %04x (%04x) (CNTR - Counter Register)\n", pc, FUNCNAME, offset * 2, data, mem_mask);
|
||||
break;
|
||||
case m68340_timer::REG_PREL1:
|
||||
COMBINE_DATA(&timer.m_prel1[id]);
|
||||
case REG_PREL1:
|
||||
COMBINE_DATA(&m_prel1);
|
||||
LOGTIMER("PC %08x %s %04x, %04x (%04x) (PREL1 - Preload 1 Register)\n", pc, FUNCNAME, offset * 2, data, mem_mask);
|
||||
LOGTIMER("- PR1-15 to PR1-0: %04x\n", (data & 0xffff));
|
||||
break;
|
||||
case m68340_timer::REG_PREL2:
|
||||
COMBINE_DATA(&timer.m_prel2[id]);
|
||||
case REG_PREL2:
|
||||
COMBINE_DATA(&m_prel2);
|
||||
LOGTIMER("PC %08x %s %04x, %04x (%04x) (PREL2 - Preload 2 Register)\n", pc, FUNCNAME, offset * 2, data, mem_mask);
|
||||
LOGTIMER("- PR2-15 to PR2-0: %04x\n", (data & 0xffff));
|
||||
break;
|
||||
case m68340_timer::REG_COM:
|
||||
COMBINE_DATA(&timer.m_com[id]);
|
||||
case REG_COM:
|
||||
COMBINE_DATA(&m_com);
|
||||
LOGTIMER("PC %08x %s %04x, %04x (%04x) (COM - Compare Register)\n", pc, FUNCNAME, offset * 2, data, mem_mask);
|
||||
LOGTIMER("- COM15-COM0: %04x\n", (data & 0xfff));
|
||||
break;
|
||||
@ -256,150 +248,72 @@ WRITE16_MEMBER( m68340_cpu_device::m68340_internal_timer_w )
|
||||
break;
|
||||
}
|
||||
|
||||
int pc = space.device().safe_pc();
|
||||
LOG("%08x m68340_internal_timer_w %08x, %08x (%08x)\n", pc, offset * 2, data, mem_mask);
|
||||
}
|
||||
|
||||
void m68340_timer::reset()
|
||||
{
|
||||
LOGSETUP("%s\n", FUNCNAME);
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( m68340_cpu_device::tin1_w)
|
||||
WRITE_LINE_MEMBER( mc68340_timer_module_device::tin_w)
|
||||
{
|
||||
LOGTIMER("%s\n", FUNCNAME);
|
||||
|
||||
assert(m68340TIMER);
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
|
||||
timer.m_tin[0] = state;
|
||||
m_tin = state;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( m68340_cpu_device::tgate1_w)
|
||||
WRITE_LINE_MEMBER( mc68340_timer_module_device::tgate_w)
|
||||
{
|
||||
LOGTIMER("%s\n", FUNCNAME);
|
||||
|
||||
assert(m68340TIMER);
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
|
||||
timer.m_tgate[0] = state;
|
||||
m_tgate = state;
|
||||
if (state == ASSERT_LINE)
|
||||
{
|
||||
if (timer.m_cr[0] & m68340_timer::REG_CR_TGE)
|
||||
if (m_cr & REG_CR_TGE)
|
||||
{
|
||||
timer.m_sr[0] |= m68340_timer::REG_SR_TG;
|
||||
if (timer.m_cr[0] & m68340_timer::REG_CR_IE1)
|
||||
m_sr |= REG_SR_TG;
|
||||
if (m_cr & REG_CR_IE1)
|
||||
{
|
||||
LOGTIMER(" - TG interrupt");
|
||||
do_timer_irq(0);
|
||||
timer.m_sr[0] |= m68340_timer::REG_SR_IRQ;
|
||||
do_timer_irq();
|
||||
m_sr |= REG_SR_IRQ;
|
||||
|
||||
}
|
||||
}
|
||||
timer.m_sr[0] |= m68340_timer::REG_SR_TGL;
|
||||
m_sr |= REG_SR_TGL;
|
||||
}
|
||||
else
|
||||
{
|
||||
timer.m_sr[0] &= ~m68340_timer::REG_SR_TGL;
|
||||
m_sr &= ~REG_SR_TGL;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( m68340_cpu_device::tin2_w)
|
||||
TIMER_CALLBACK_MEMBER(mc68340_timer_module_device::timer_callback)
|
||||
{
|
||||
LOGTIMER("%s\n", FUNCNAME);
|
||||
|
||||
assert(m68340TIMER);
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
|
||||
timer.m_tin[1] = state;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( m68340_cpu_device::tgate2_w)
|
||||
{
|
||||
LOGTIMER("%s\n", FUNCNAME);
|
||||
|
||||
assert(m68340TIMER);
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
|
||||
timer.m_tgate[1] = state;
|
||||
if (state == ASSERT_LINE)
|
||||
do_timer_tick();
|
||||
if ((m_sr & REG_SR_ON) != 0)
|
||||
{
|
||||
if (timer.m_cr[1] & m68340_timer::REG_CR_TGE)
|
||||
{
|
||||
timer.m_sr[1] |= m68340_timer::REG_SR_TG;
|
||||
if (timer.m_cr[1] & m68340_timer::REG_CR_IE1)
|
||||
{
|
||||
LOGTIMER(" - TG interrupt");
|
||||
do_timer_irq(1);
|
||||
timer.m_sr[1] |= m68340_timer::REG_SR_IRQ;
|
||||
|
||||
}
|
||||
}
|
||||
timer.m_sr[1] |= m68340_timer::REG_SR_TGL;
|
||||
}
|
||||
else
|
||||
{
|
||||
timer.m_sr[1] &= ~m68340_timer::REG_SR_TGL;
|
||||
LOGTIMER("Re-arming timer %d using system clock/2 as base: %d Hz\n", m_cpu->get_timer_index(this) + 1, (m_cpu->clock() / 2) / (0x101 << ((m_cr & REG_CR_POT_MASK) >> 5) & 0x1fe));
|
||||
m_timer->adjust(m_cpu->cycles_to_attotime( (m_cpu->clock() / 2) / (0x101 << ((m_cr & REG_CR_POT_MASK) >> 5) & 0x1fe) * 2));
|
||||
}
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(m68340_cpu_device::timer1_callback)
|
||||
{
|
||||
assert(m68340TIMER);
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
do_timer_tick(0);
|
||||
if ((timer.m_sr[0] & m68340_timer::REG_SR_ON) != 0)
|
||||
{
|
||||
LOGTIMER("Re-arming timer 1 using system clock/2 as base %d Hz\n", (clock() / 2) / (0x101 << ((timer.m_cr[0] & m68340_timer::REG_CR_POT_MASK) >> 5) & 0x1fe));
|
||||
timer.m_timer[0]->adjust(cycles_to_attotime( (clock() / 2) / (0x101 << ((timer.m_cr[0] & m68340_timer::REG_CR_POT_MASK) >> 5) & 0x1fe) * 2));
|
||||
}
|
||||
}
|
||||
|
||||
TIMER_CALLBACK_MEMBER(m68340_cpu_device::timer2_callback)
|
||||
{
|
||||
assert(m68340TIMER);
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
do_timer_tick(1);
|
||||
if ((timer.m_sr[1] & m68340_timer::REG_SR_ON) != 0)
|
||||
{
|
||||
LOGTIMER("Re-arming timer 2 using system clock/2 as base: %d Hz\n", (clock() / 2) / (0x101 << ((timer.m_cr[1] & m68340_timer::REG_CR_POT_MASK) >> 5) & 0x1fe));
|
||||
timer.m_timer[1]->adjust(cycles_to_attotime( (clock() / 2) / (0x101 << ((timer.m_cr[1] & m68340_timer::REG_CR_POT_MASK) >> 5) & 0x1fe) * 2));
|
||||
}
|
||||
}
|
||||
|
||||
void m68340_cpu_device::start_68340_timer()
|
||||
void mc68340_timer_module_device::device_start()
|
||||
{
|
||||
LOGSETUP("%s\n", FUNCNAME);
|
||||
|
||||
assert(m68340TIMER);
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
m_cpu = downcast<m68340_cpu_device *>(owner());
|
||||
|
||||
timer.m_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(m68340_cpu_device::timer1_callback),this));
|
||||
timer.m_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(m68340_cpu_device::timer2_callback),this));
|
||||
|
||||
// resolve callbacks Port A
|
||||
m_pa_out_cb.resolve_safe();
|
||||
m_pa_in_cb.resolve();
|
||||
m_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(timer_callback),this));
|
||||
|
||||
// Resolve Timer callbacks
|
||||
m_tout1_out_cb.resolve_safe();
|
||||
m_tgate1_in_cb.resolve_safe();
|
||||
m_tin1_in_cb.resolve_safe();
|
||||
m_tout2_out_cb.resolve_safe();
|
||||
m_tgate2_in_cb.resolve_safe();
|
||||
m_tin2_in_cb.resolve_safe();
|
||||
m_tout_out_cb.resolve_safe();
|
||||
m_tgate_in_cb.resolve_safe();
|
||||
m_tin_in_cb.resolve_safe();
|
||||
}
|
||||
|
||||
void m68340_cpu_device::do_timer_irq(int id)
|
||||
void mc68340_timer_module_device::do_timer_irq()
|
||||
{
|
||||
assert(m68340TIMER);
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
|
||||
assert(m68340SIM);
|
||||
m68340_sim &sim = *m68340SIM;
|
||||
|
||||
int timer_irq_level = (timer.m_ir[id] & 0x0700) >> 8;
|
||||
int timer_irq_vector = (timer.m_ir[id] & 0x00ff) >> 0;
|
||||
m68340_sim &sim = *m_cpu->m68340SIM;
|
||||
int timer_irq_level = (m_ir & 0x0700) >> 8;
|
||||
int timer_irq_vector = (m_ir & 0x00ff) >> 0;
|
||||
|
||||
if (timer_irq_level) // 0 is irq disabled
|
||||
{
|
||||
@ -410,35 +324,32 @@ void m68340_cpu_device::do_timer_irq(int id)
|
||||
if (use_autovector)
|
||||
{
|
||||
//logerror("irq with autovector\n");
|
||||
set_input_line(timer_irq_level, HOLD_LINE);
|
||||
m_cpu->set_input_line(timer_irq_level, HOLD_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
//logerror("irq without autovector\n");
|
||||
set_input_line_and_vector(timer_irq_level, HOLD_LINE, timer_irq_vector);
|
||||
m_cpu->set_input_line_and_vector(timer_irq_level, HOLD_LINE, timer_irq_vector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* do_timer_tick works on flanks, thus half clock cycles, to capture both rising and falling clock flanks */
|
||||
void m68340_cpu_device::do_timer_tick( int id )
|
||||
void mc68340_timer_module_device::do_timer_tick()
|
||||
{
|
||||
assert(m68340TIMER);
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
|
||||
timer.m_timer_counter[id]--; // Count flanks, least significant bit is state of the clock line
|
||||
if ( (timer.m_mcr[id] & m68340_timer::REG_MCR_STP) == 0)
|
||||
m_timer_counter--; // Count flanks, least significant bit is state of the clock line
|
||||
if ( (m_mcr & REG_MCR_STP) == 0)
|
||||
{
|
||||
if (timer.m_timer_counter[id] & 1) // Raising flank, copy shadow to register
|
||||
if (m_timer_counter & 1) // Raising flank, copy shadow to register
|
||||
{
|
||||
// Shadow the counter only if we are NOT in the ICOC mode WHILE the TG bit is set
|
||||
if (!((timer.m_cr[id] & m68340_timer::REG_CR_MODE_MASK) == m68340_timer::REG_CR_MODE_ICOC &&
|
||||
(timer.m_sr[id] & m68340_timer::REG_SR_TG) != 0))
|
||||
timer.m_cntr_reg[id] = timer.m_cntr[id];
|
||||
if (!((m_cr & REG_CR_MODE_MASK) == REG_CR_MODE_ICOC &&
|
||||
(m_sr & REG_SR_TG) != 0))
|
||||
m_cntr_reg = m_cntr;
|
||||
}
|
||||
else // Falling flank
|
||||
{
|
||||
timer.m_cntr[id]--;
|
||||
m_cntr--;
|
||||
|
||||
/* TC - Timer Compare Interrupt
|
||||
1 = This bit is set when the counter transitions (off a clock/event falling edge) to the
|
||||
@ -448,22 +359,22 @@ void m68340_cpu_device::do_timer_tick( int id )
|
||||
IMB, regardless of the mode of operation. This bit may also be cleared by writing
|
||||
a one to it. Writing a zero to this bit does not alter its contents. This bit is not
|
||||
affected by disabling the timer (SWR = 0).*/
|
||||
if (timer.m_cntr[id] == timer.m_com[id]) // Check COM register
|
||||
if (m_cntr == m_com) // Check COM register
|
||||
{
|
||||
timer.m_sr[id] |= (m68340_timer::REG_SR_TC | m68340_timer::REG_SR_COM);
|
||||
m_sr |= (REG_SR_TC | REG_SR_COM);
|
||||
}
|
||||
}
|
||||
|
||||
LOGINT("%s reached\n", timer.m_cntr_reg[id] == 0 ? "Timeout" : "COM value");
|
||||
LOGINT("%s reached\n", m_cntr_reg == 0 ? "Timeout" : "COM value");
|
||||
/* OC1/OC0 - Output Control
|
||||
These bits select the conditions under which TOUTx changes These
|
||||
bits may have a different effect when in the input capture/output compare mode.*/
|
||||
switch (timer.m_cr[id] & m68340_timer::REG_CR_OC_MASK)
|
||||
switch (m_cr & REG_CR_OC_MASK)
|
||||
{
|
||||
case m68340_timer::REG_CR_OC_DISABLED:
|
||||
case REG_CR_OC_DISABLED:
|
||||
/* Disabled - TOUTx is disabled and three-stated TODO: support three-stated level */
|
||||
break;
|
||||
case m68340_timer::REG_CR_OC_TOGGLE:
|
||||
case REG_CR_OC_TOGGLE:
|
||||
/* Toggle Mode - If the timer is disabled (SWR = 0) when this encoding is programmed,
|
||||
TOUTx is immediately set to zero. If the timer is enabled (SWR = 1), timeout events
|
||||
(counter reaches $0000) toggle TOUTx.
|
||||
@ -472,36 +383,22 @@ void m68340_cpu_device::do_timer_tick( int id )
|
||||
TOUTx is immediately set to zero if the timer is disabled (SWR = 0). If the timer is
|
||||
enabled (SWR = 1), timer compare events toggle TOUTx. (Timer compare events occur
|
||||
when the counter reaches the value stored in the COM.)*/
|
||||
if ((timer.m_cr[id] & m68340_timer::REG_CR_MODE_MASK) == m68340_timer::REG_CR_MODE_ICOC) // Detect Input Capture/Output Compare mode
|
||||
if ((m_cr & REG_CR_MODE_MASK) == REG_CR_MODE_ICOC) // Detect Input Capture/Output Compare mode
|
||||
{
|
||||
if ((timer.m_sr[id] & m68340_timer::REG_SR_COM) != 0) // timer reached compare value?
|
||||
if ((m_sr & REG_SR_COM) != 0) // timer reached compare value?
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
m_tout1_out_cb((timer.m_tout[0]++ & 1) != 0 ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tout2_out_cb((timer.m_tout[1]++ & 1) != 0 ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
m_tout_out_cb((m_tout++ & 1) != 0 ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
else // Any oher mode
|
||||
{
|
||||
if (timer.m_cntr_reg[id] == 0) // Counter reached timeout?
|
||||
if (m_cntr_reg == 0) // Counter reached timeout?
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
m_tout1_out_cb((timer.m_tout[0]++ & 1) != 0 ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tout2_out_cb((timer.m_tout[1]++ & 1) != 0 ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
m_tout_out_cb((m_tout++ & 1) != 0 ? ASSERT_LINE : CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case m68340_timer::REG_CR_OC_ZERO:
|
||||
case REG_CR_OC_ZERO:
|
||||
/* Zero Mode - If the timer is disabled (SWR = 0) when this encoding is programmed,
|
||||
TOUTx is immediately set to zero. If the timer is enabled (SWR = 1), TOUTx will be set
|
||||
to zero at the next timeout.
|
||||
@ -510,47 +407,26 @@ void m68340_cpu_device::do_timer_tick( int id )
|
||||
immediately set to zero if the timer is disabled (SWR = 0). If the timer is enabled (SWR
|
||||
= 1), TOUTx will be set to zero at timeouts and set to one at timer compare events. If
|
||||
the COM is $0000, TOUTx will be set to zero at the timeout/timer compare event.*/
|
||||
if ((timer.m_cr[id] & m68340_timer::REG_CR_MODE_MASK) == m68340_timer::REG_CR_MODE_ICOC) // Detect Input Capture/Output Compare mode
|
||||
if ((m_cr & REG_CR_MODE_MASK) == REG_CR_MODE_ICOC) // Detect Input Capture/Output Compare mode
|
||||
{
|
||||
if ((timer.m_sr[id] & m68340_timer::REG_SR_COM) != 0) // timer reached compare value?
|
||||
if ((m_sr & REG_SR_COM) != 0) // timer reached compare value?
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
m_tout1_out_cb(ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tout2_out_cb(ASSERT_LINE);
|
||||
}
|
||||
m_tout_out_cb(ASSERT_LINE);
|
||||
}
|
||||
if (timer.m_cntr_reg[id] == 0) // timer reached timeout value?
|
||||
if (m_cntr_reg == 0) // timer reached timeout value?
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
m_tout1_out_cb(CLEAR_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tout2_out_cb(CLEAR_LINE);
|
||||
}
|
||||
m_tout_out_cb(CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (timer.m_cntr_reg[id] == 0) // timer reached timeout value?
|
||||
if (m_cntr_reg == 0) // timer reached timeout value?
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
m_tout1_out_cb(CLEAR_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tout2_out_cb(CLEAR_LINE);
|
||||
}
|
||||
m_tout_out_cb(CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case m68340_timer::REG_CR_OC_ONE:
|
||||
case REG_CR_OC_ONE:
|
||||
/* One Mode - If the timer is disabled (SWR = 0) when this encoding is programmed,
|
||||
TOUTx is immediately set to one. If the timer is enabled (SWR = 1), TOUTx will be set
|
||||
to one at the next timeout.
|
||||
@ -559,43 +435,22 @@ void m68340_cpu_device::do_timer_tick( int id )
|
||||
immediately set to one if the timer is disabled (SWR = 0). If the timer is enabled (SWR =
|
||||
1), TOUTx will be set to one at timeouts and set to zero at timer compare events. If the
|
||||
COM is $0000, TOUTx will be set to one at the timeout/timer compare event.*/
|
||||
if ((timer.m_cr[id] & m68340_timer::REG_CR_MODE_MASK) == m68340_timer::REG_CR_MODE_ICOC) // Detect Input Capture/Output Compare mode
|
||||
if ((m_cr & REG_CR_MODE_MASK) == REG_CR_MODE_ICOC) // Detect Input Capture/Output Compare mode
|
||||
{
|
||||
if ((timer.m_sr[id] & m68340_timer::REG_SR_COM) != 0) // timer reached compare value?
|
||||
if ((m_sr & REG_SR_COM) != 0) // timer reached compare value?
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
m_tout1_out_cb(CLEAR_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tout2_out_cb(CLEAR_LINE);
|
||||
}
|
||||
m_tout_out_cb(CLEAR_LINE);
|
||||
}
|
||||
if (timer.m_cntr_reg[id] == 0) // timer reached timeout value?
|
||||
if (m_cntr_reg == 0) // timer reached timeout value?
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
m_tout1_out_cb(ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tout2_out_cb(ASSERT_LINE);
|
||||
}
|
||||
m_tout_out_cb(ASSERT_LINE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (timer.m_cntr_reg[id] == 0) // timer reached timeout value?
|
||||
if (m_cntr_reg == 0) // timer reached timeout value?
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
m_tout1_out_cb(ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tout2_out_cb(ASSERT_LINE);
|
||||
}
|
||||
m_tout_out_cb(ASSERT_LINE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -603,25 +458,35 @@ void m68340_cpu_device::do_timer_tick( int id )
|
||||
LOGTIMER("Wrong TOUT mode, fix the code!\n");
|
||||
}
|
||||
|
||||
if (timer.m_cntr_reg[id] == 0) // timer reached timeout value?
|
||||
if (m_cntr_reg == 0) // timer reached timeout value?
|
||||
{
|
||||
timer.m_cntr[id] = timer.m_prel1[id]; // TODO: Support prel2 for certain modes
|
||||
if (timer.m_cr[id] & m68340_timer::REG_CR_IE2)
|
||||
m_cntr = m_prel1; // TODO: Support prel2 for certain modes
|
||||
if (m_cr & REG_CR_IE2)
|
||||
{
|
||||
LOGTIMER(" - TO interrupt");
|
||||
do_timer_irq(id);
|
||||
timer.m_sr[id] |= m68340_timer::REG_SR_IRQ;
|
||||
do_timer_irq();
|
||||
m_sr |= REG_SR_IRQ;
|
||||
}
|
||||
}
|
||||
if ((timer.m_sr[id] & m68340_timer::REG_SR_COM) != 0) // timer reached compare value? )
|
||||
if ((m_sr & REG_SR_COM) != 0) // timer reached compare value? )
|
||||
{
|
||||
if (timer.m_cr[id] & m68340_timer::REG_CR_IE0)
|
||||
if (m_cr & REG_CR_IE0)
|
||||
{
|
||||
LOGTIMER(" - TC interrupt");
|
||||
do_timer_irq(id);
|
||||
timer.m_sr[id] |= m68340_timer::REG_SR_IRQ;
|
||||
do_timer_irq();
|
||||
m_sr |= REG_SR_IRQ;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mc68340_timer_module_device::mc68340_timer_module_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, MC68340_TIMER_MODULE, tag, owner, clock)
|
||||
, m_tout_out_cb(*this)
|
||||
, m_tin_in_cb(*this)
|
||||
, m_tgate_in_cb(*this)
|
||||
{
|
||||
}
|
||||
|
||||
DEFINE_DEVICE_TYPE(MC68340_TIMER_MODULE, mc68340_timer_module_device, "mc68340timmod", "MC68340 Timer Module")
|
||||
|
@ -1,30 +1,52 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
// copyright-holders:David Haywood, Joakim Larsson Edstrom
|
||||
#ifndef MAME_MACHINE_68340TMU_H
|
||||
#define MAME_MACHINE_68340TMU_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class m68340_timer
|
||||
{
|
||||
public:
|
||||
// Registers for timer 1 and timer 2
|
||||
uint16_t m_mcr[2];
|
||||
uint16_t m_ir[2];
|
||||
uint16_t m_cr[2];
|
||||
uint16_t m_sr[2];
|
||||
uint16_t m_cntr[2];
|
||||
uint16_t m_cntr_reg[2];
|
||||
uint16_t m_prel1[2];
|
||||
uint16_t m_prel2[2];
|
||||
uint16_t m_com[2];
|
||||
uint16_t m_timer_counter[2];
|
||||
uint32_t m_tin[2];
|
||||
uint32_t m_tgate[2];
|
||||
uint32_t m_tout[2];
|
||||
emu_timer *m_timer[2];
|
||||
class m68340_cpu_device;
|
||||
|
||||
void reset();
|
||||
class mc68340_timer_module_device : public device_t
|
||||
{
|
||||
friend class m68340_cpu_device;
|
||||
|
||||
public:
|
||||
mc68340_timer_module_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
|
||||
|
||||
// device-level overrides
|
||||
virtual void device_start() override;
|
||||
|
||||
READ16_MEMBER( read );
|
||||
WRITE16_MEMBER( write );
|
||||
DECLARE_WRITE_LINE_MEMBER( tin_w );
|
||||
DECLARE_WRITE_LINE_MEMBER( tgate_w );
|
||||
|
||||
protected:
|
||||
m68340_cpu_device *m_cpu;
|
||||
|
||||
uint16_t m_mcr;
|
||||
uint16_t m_ir;
|
||||
uint16_t m_cr;
|
||||
uint16_t m_sr;
|
||||
uint16_t m_cntr;
|
||||
uint16_t m_cntr_reg;
|
||||
uint16_t m_prel1;
|
||||
uint16_t m_prel2;
|
||||
uint16_t m_com;
|
||||
uint16_t m_timer_counter;
|
||||
uint32_t m_tin;
|
||||
uint32_t m_tgate;
|
||||
uint32_t m_tout;
|
||||
emu_timer *m_timer;
|
||||
|
||||
devcb_write_line m_tout_out_cb;
|
||||
devcb_write_line m_tin_in_cb;
|
||||
devcb_write_line m_tgate_in_cb;
|
||||
void do_timer_irq();
|
||||
void do_timer_tick();
|
||||
|
||||
TIMER_CALLBACK_MEMBER(timer_callback);
|
||||
|
||||
enum {
|
||||
REG_MCR = 0x00,
|
||||
@ -91,4 +113,6 @@ public:
|
||||
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(MC68340_TIMER_MODULE, mc68340_timer_module_device)
|
||||
|
||||
#endif // MAME_MACHINE_68340TMU_H
|
||||
|
Loading…
Reference in New Issue
Block a user