mirror of
https://github.com/holub/mame
synced 2025-04-24 09:20:02 +03:00
Merge pull request #2576 from JoakimLarsson/m68340_1
m68340: Added implementations for VCO clock synthesizer and Timer mod…
This commit is contained in:
commit
2d0121d7d2
@ -77,12 +77,24 @@ WRITE32_MEMBER( m68340_cpu_device::m68340_internal_base_w )
|
||||
{
|
||||
int base = m68340_base & 0xfffff000;
|
||||
|
||||
internal->install_readwrite_handler(base + 0x000, base + 0x03f, read16_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_r),this), write16_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_w),this),0xffffffff);
|
||||
internal->install_readwrite_handler(base + 0x010, base + 0x01f, read8_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_ports_r),this),write8_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_ports_w),this),0xffffffff);
|
||||
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, read32_delegate(FUNC(m68340_cpu_device::m68340_internal_timer_r),this), write32_delegate(FUNC(m68340_cpu_device::m68340_internal_timer_w),this));
|
||||
internal->install_readwrite_handler(base + 0x700, base + 0x723, read32_delegate(FUNC(m68340_cpu_device::m68340_internal_serial_r),this), write32_delegate(FUNC(m68340_cpu_device::m68340_internal_serial_w),this));
|
||||
internal->install_readwrite_handler(base + 0x780, base + 0x7bf, read32_delegate(FUNC(m68340_cpu_device::m68340_internal_dma_r),this), write32_delegate(FUNC(m68340_cpu_device::m68340_internal_dma_w),this));
|
||||
internal->install_readwrite_handler(base + 0x000, base + 0x03f,
|
||||
read16_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_r),this),
|
||||
write16_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_w),this),0xffffffff);
|
||||
internal->install_readwrite_handler(base + 0x010, base + 0x01f, // Intentionally punches a hole in previous address mapping
|
||||
read8_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_ports_r),this),
|
||||
write8_delegate(FUNC(m68340_cpu_device::m68340_internal_sim_ports_w),this),0xffffffff);
|
||||
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 + 0x700, base + 0x723,
|
||||
read32_delegate(FUNC(m68340_cpu_device::m68340_internal_serial_r),this),
|
||||
write32_delegate(FUNC(m68340_cpu_device::m68340_internal_serial_w),this));
|
||||
internal->install_readwrite_handler(base + 0x780, base + 0x7bf,
|
||||
read32_delegate(FUNC(m68340_cpu_device::m68340_internal_dma_r),this),
|
||||
write32_delegate(FUNC(m68340_cpu_device::m68340_internal_dma_w),this));
|
||||
|
||||
}
|
||||
|
||||
@ -107,10 +119,19 @@ ADDRESS_MAP_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_pa_out_cb(*this)
|
||||
,m_pa_in_cb(*this)
|
||||
,m_pb_out_cb(*this)
|
||||
,m_pb_in_cb(*this)
|
||||
, m_clock_mode(0)
|
||||
, m_crystal(0)
|
||||
, m_extal(0)
|
||||
, m_pa_out_cb(*this)
|
||||
, 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;
|
||||
@ -129,6 +150,14 @@ void m68340_cpu_device::device_reset()
|
||||
fscpu32_device::device_reset();
|
||||
}
|
||||
|
||||
// Some hardwares pulls this low when resetting peripherals, most just ties this line to GND or VCC
|
||||
// TODO: Support Limp mode and external clock with no PLL
|
||||
WRITE_LINE_MEMBER( m68340_cpu_device::set_modck )
|
||||
{
|
||||
m_modck = state;
|
||||
m_clock_mode &= ~(m68340_sim::CLOCK_MODCK | m68340_sim::CLOCK_PLL);
|
||||
m_clock_mode |= ((m_modck == ASSERT_LINE) ? (m68340_sim::CLOCK_MODCK | m68340_sim::CLOCK_PLL) : 0);
|
||||
}
|
||||
|
||||
void m68340_cpu_device::device_start()
|
||||
{
|
||||
@ -145,6 +174,7 @@ void m68340_cpu_device::device_start()
|
||||
m68340TIMER->reset();
|
||||
|
||||
start_68340_sim();
|
||||
start_68340_timer();
|
||||
|
||||
m68340_base = 0x00000000;
|
||||
|
||||
|
@ -28,6 +28,27 @@
|
||||
#define MCFG_MC68340_PB_OUTPUT_CB(_devcb) \
|
||||
devcb = &m68340_cpu_device::set_pb_out_callback (*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_MC68340_ADD_CRYSTAL(_crystal) \
|
||||
m68340_cpu_device::set_crystal(*device, _crystal);
|
||||
|
||||
#define MCFG_MC68340_TOUT1_OUTPUT_CB(_devcb) \
|
||||
devcb = &m68340_cpu_device::set_tout1_out_callback (*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_MC68340_TIN1_INPUT_CB(_devcb) \
|
||||
devcb = &m68340_cpu_device::set_tin1_out_callback (*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_MC68340_TGATE1_INPUT_CB(_devcb) \
|
||||
devcb = &m68340_cpu_device::set_tgate1_out_callback (*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_MC68340_TOUT2_OUTPUT_CB(_devcb) \
|
||||
devcb = &m68340_cpu_device::set_tout2_out_callback (*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_MC68340_TIN2_INPUT_CB(_devcb) \
|
||||
devcb = &m68340_cpu_device::set_tin2_out_callback (*device, DEVCB_##_devcb);
|
||||
|
||||
#define MCFG_MC68340_TGATE2_INPUT_CB(_devcb) \
|
||||
devcb = &m68340_cpu_device::set_tgate2_out_callback (*device, DEVCB_##_devcb);
|
||||
|
||||
class m68340_cpu_device : public fscpu32_device
|
||||
{
|
||||
public:
|
||||
@ -37,9 +58,24 @@ public:
|
||||
template <class Object> static devcb_base &set_pa_out_callback (device_t &device, Object &&cb){ return downcast<m68340_cpu_device &>(device).m_pa_out_cb.set_callback (std::forward<Object>(cb)); }
|
||||
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)); }
|
||||
|
||||
uint16_t get_cs(offs_t address);
|
||||
|
||||
// TODO: Support Limp mode and external clock with no PLL
|
||||
static void set_crystal(device_t &device, int crystal)
|
||||
{
|
||||
m68340_cpu_device &dev = downcast<m68340_cpu_device &>(device);
|
||||
dev.m_crystal = crystal;
|
||||
dev.m_clock_mode |= (m68340_sim::CLOCK_MODCK | m68340_sim::CLOCK_PLL);
|
||||
}
|
||||
|
||||
READ32_MEMBER( m68340_internal_base_r );
|
||||
WRITE32_MEMBER( m68340_internal_base_w );
|
||||
READ32_MEMBER( m68340_internal_dma_r );
|
||||
@ -52,20 +88,41 @@ public:
|
||||
WRITE16_MEMBER( m68340_internal_sim_w );
|
||||
WRITE8_MEMBER( m68340_internal_sim_ports_w );
|
||||
WRITE32_MEMBER( m68340_internal_sim_cs_w );
|
||||
READ32_MEMBER( m68340_internal_timer_r );
|
||||
WRITE32_MEMBER( m68340_internal_timer_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 );
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
|
||||
TIMER_CALLBACK_MEMBER(periodic_interrupt_timer_callback);
|
||||
TIMER_CALLBACK_MEMBER(timer1_callback);
|
||||
TIMER_CALLBACK_MEMBER(timer2_callback);
|
||||
|
||||
void start_68340_sim();
|
||||
void do_timer_irq();
|
||||
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 m_currentcs;
|
||||
uint32_t m_clock_mode;
|
||||
uint32_t m_modck;
|
||||
uint32_t m_crystal;
|
||||
uint32_t m_extal;
|
||||
|
||||
/* 68340 peripheral modules */
|
||||
m68340_sim* m68340SIM;
|
||||
@ -75,16 +132,18 @@ protected:
|
||||
|
||||
uint32_t m68340_base;
|
||||
|
||||
uint16_t m_avr;
|
||||
uint16_t m_picr;
|
||||
uint16_t m_pitr;
|
||||
|
||||
emu_timer *m_irq_timer;
|
||||
|
||||
devcb_write8 m_pa_out_cb;
|
||||
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)
|
||||
|
@ -13,8 +13,13 @@
|
||||
#define LOG_SETUP (1U << 1)
|
||||
#define LOG_READ (1U << 2)
|
||||
#define LOG_PORTS (1U << 3)
|
||||
#define LOG_SIM (1U << 4)
|
||||
#define LOG_CLOCK (1U << 5)
|
||||
#define LOG_DATA (1U << 6)
|
||||
#define LOG_INT (1U << 7)
|
||||
#define LOG_PIT (1U << 8)
|
||||
|
||||
//#define VERBOSE (LOG_PORTS|LOG_SETUP|LOG_READ)
|
||||
//#define VERBOSE (LOG_SETUP)
|
||||
#define LOG_OUTPUT_FUNC printf // Needs always to be enabled as the default value 'logerror' is not available here
|
||||
|
||||
#include "logmacro.h"
|
||||
@ -23,6 +28,11 @@
|
||||
#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
|
||||
#define LOGR(...) LOGMASKED(LOG_READ, __VA_ARGS__)
|
||||
#define LOGPORTS(...) LOGMASKED(LOG_PORTS, __VA_ARGS__)
|
||||
#define LOGSIM(...) LOGMASKED(LOG_SIM, __VA_ARGS__)
|
||||
#define LOGCLOCK(...) LOGMASKED(LOG_CLOCK, __VA_ARGS__)
|
||||
#define LOGDATA(...) LOGMASKED(LOG_DATA, __VA_ARGS__)
|
||||
#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
|
||||
#define LOGPIT(...) LOGMASKED(LOG_PIT, __VA_ARGS__)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define FUNCNAME __func__
|
||||
@ -30,92 +40,157 @@
|
||||
#define FUNCNAME __PRETTY_FUNCTION__
|
||||
#endif
|
||||
|
||||
#define m68340SIM_MCR (0x00)
|
||||
// (0x02)
|
||||
#define m68340SIM_SYNCR (0x04)
|
||||
#define m68340SIM_AVR_RSR (0x06)
|
||||
// (0x08)
|
||||
// (0x0a)
|
||||
// (0x0c)
|
||||
// (0x0e)
|
||||
#define m68340SIM_PORTA (0x11)
|
||||
#define m68340SIM_DDRA (0x13)
|
||||
#define m68340SIM_PPARA1 (0x15)
|
||||
#define m68340SIM_PPARA2 (0x17)
|
||||
#define m68340SIM_PORTB (0x19)
|
||||
#define m68340SIM_PORTB1 (0x1b)
|
||||
#define m68340SIM_DDRB (0x1d)
|
||||
#define m68340SIM_PPARB (0x1f)
|
||||
#define m68340SIM_SWIV_SYPCR (0x20)
|
||||
#define m68340SIM_PICR (0x22)
|
||||
#define m68340SIM_PITR (0x24)
|
||||
#define m68340SIM_SWSR (0x26)
|
||||
// (0x28)
|
||||
// (0x2a)
|
||||
// (0x2c)
|
||||
// (0x2e)
|
||||
// (0x30)
|
||||
// (0x32)
|
||||
// (0x34)
|
||||
// (0x36)
|
||||
// (0x38)
|
||||
// (0x3a)
|
||||
// (0x3c)
|
||||
// (0x3e)
|
||||
#define m68340SIM_AM_CS0 (0x40)
|
||||
#define m68340SIM_BA_CS0 (0x44)
|
||||
#define m68340SIM_AM_CS1 (0x48)
|
||||
#define m68340SIM_BA_CS1 (0x4c)
|
||||
#define m68340SIM_AM_CS2 (0x50)
|
||||
#define m68340SIM_BA_CS2 (0x54)
|
||||
#define m68340SIM_AM_CS3 (0x58)
|
||||
#define m68340SIM_BA_CS3 (0x5c)
|
||||
|
||||
|
||||
|
||||
READ16_MEMBER( m68340_cpu_device::m68340_internal_sim_r )
|
||||
{
|
||||
LOGR("%s\n", FUNCNAME);
|
||||
assert(m68340SIM);
|
||||
//m68340_sim &sim = *m68340SIM;
|
||||
m68340_sim &sim = *m68340SIM;
|
||||
int val = space.machine().rand();
|
||||
int pc = space.device().safe_pc();
|
||||
|
||||
switch (offset * 2)
|
||||
{
|
||||
case m68340_sim::REG_MCR:
|
||||
LOGSIM("- %08x %s %04x, (%04x) (MCR - Module Configuration Register) - not implemented\n", pc, FUNCNAME, offset * 2, mem_mask);
|
||||
val = sim.m_mcr;
|
||||
break;
|
||||
|
||||
case m68340_sim::REG_SYNCR:
|
||||
LOGSIM("- %08x %s %04x, (%04x) (SYNCR - Clock Synthesizer Register) - not implemented\n", pc, FUNCNAME, offset*2,mem_mask);
|
||||
val = sim.m_syncr;
|
||||
break;
|
||||
|
||||
case m68340_sim::REG_AVR_RSR:
|
||||
LOGSIM("- %08x %s %04x, (%04x) (AVR, RSR - Auto Vector Register, Reset Status Register) - not implemented\n", pc, FUNCNAME, offset*2,mem_mask);
|
||||
val = sim.m_avr_rsr;
|
||||
break;
|
||||
|
||||
case m68340_sim::REG_SWIV_SYPCR:
|
||||
LOGSIM("- %08x %s %04x, (%04x) (SWIV_SYPCR - Software Interrupt Vector, System Protection Control Register) - not implemented\n", pc, FUNCNAME, offset*2,mem_mask);
|
||||
val = sim.m_swiv_sypcr;
|
||||
break;
|
||||
|
||||
case m68340_sim::REG_PICR:
|
||||
LOGPIT("- %08x %s %04x, (%04x) (PICR - Periodic Interrupt Control Register) - not implemented\n", pc, FUNCNAME, offset*2,mem_mask);
|
||||
val = sim.m_picr;
|
||||
break;
|
||||
|
||||
case m68340_sim::REG_PITR:
|
||||
LOGPIT("- %08x %s %04x, (%04x) (PITR - Periodic Interrupt Timer Register) - not implemented\n", pc, FUNCNAME, offset*2,mem_mask);
|
||||
val = sim.m_pitr;
|
||||
break;
|
||||
|
||||
case m68340_sim::REG_SWSR:
|
||||
LOGSIM("- %08x %s %04x, (%04x) (SWSR - Software Service) - not implemented\n", pc, FUNCNAME, offset*2,mem_mask);
|
||||
val = sim.m_swsr;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOGSIM("- %08x %s %04x, (%04x)\n", pc, FUNCNAME, offset * 2, mem_mask);
|
||||
}
|
||||
|
||||
LOGR(" * Reg %02x -> %02x - %s\n", offset * 2, val,
|
||||
((offset * 2) >= 0x10 && (offset * 2) < 0x20) || (offset * 2) >= 0x60 ? "Error - should not happen" :
|
||||
std::array<char const *, 8> {{"MCR", "reserved", "SYNCR", "AVR/RSR", "SWIV/SYPCR", "PICR", "PITR", "SWSR"}}[(offset * 2) <= m68340_sim::REG_AVR_RSR ? offset : offset - 0x10 + 0x04]);
|
||||
|
||||
return 0x0000;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER( m68340_cpu_device::m68340_internal_sim_w )
|
||||
{
|
||||
LOG("\n%s\n", FUNCNAME);
|
||||
LOGSETUP(" * Reg %02x <- %02x - %s\n", offset * 2, data,
|
||||
((offset * 2) >= 0x10 && (offset * 2) < 0x20) || (offset * 2) >= 0x60 ? "Error - should not happen" :
|
||||
std::array<char const *, 8> {{"MCR", "reserved", "SYNCR", "AVR/RSR", "SWIV/SYPCR", "PICR", "PITR", "SWSR"}}[(offset * 2) <= m68340_sim::REG_AVR_RSR ? offset : offset - 0x10 + 0x04]);
|
||||
|
||||
assert(m68340SIM);
|
||||
m68340_sim &sim = *m68340SIM;
|
||||
|
||||
int pc = space.device().safe_pc();
|
||||
|
||||
switch (offset<<1)
|
||||
{
|
||||
case m68340SIM_MCR:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x, (%04x) (MCR - Module Configuration Register) - not implemented\n", pc, offset*2,mem_mask);
|
||||
return space.machine().rand();
|
||||
case m68340_sim::REG_MCR:
|
||||
COMBINE_DATA(&sim.m_mcr);
|
||||
LOGSIM("PC: %08x %s %04x, %04x (%04x) (MCR - Module Configuration Register)\n", pc, FUNCNAME, offset * 2, data, mem_mask);
|
||||
LOGPIT("- FRZ1: Watchdog and PIT timer are %s\n", (data & m68340_sim::REG_MCR_FRZ1) == 0 ? "enabled" : "disabled");
|
||||
LOGSIM("- FRZ0: The BUS monitor is %s\n", (data & m68340_sim::REG_MCR_FRZ0) == 0 ? "enabled" : "disabled");
|
||||
LOGSIM("- FIRQ: Full Interrupt Request Mode %s\n", data & m68340_sim::REG_MCR_FIRQ ? "used on port B" : "supressed, adding 4 chip select lines on Port B");
|
||||
LOGSIM("- SHEN0-SHEN1: Show Cycle Enable %02x - not implemented\n", ((data & m68340_sim::REG_MCR_SHEN) >> 8));
|
||||
LOGSIM("- Supervisor registers %s - not implemented\n", data & m68340_sim::REG_MCR_SVREG ? "requries supervisor privileges" : "can be accessed by user privileged software");
|
||||
LOGSIM("- Interrupt Arbitration level: %02x\n", data & m68340_sim::REG_MCR_ARBLV);
|
||||
break;
|
||||
|
||||
case m68340SIM_SYNCR:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x, (%04x) (SYNCR - Clock Synthesizer Register) - not implemented\n", pc, offset*2,mem_mask);
|
||||
return space.machine().rand();
|
||||
case m68340_sim::REG_SYNCR:
|
||||
LOGSIM("PC: %08x %s %04x, %04x (%04x) (SYNCR - Clock Synthesizer Register) - not implemented\n", pc, FUNCNAME, offset * 2, data, mem_mask);
|
||||
COMBINE_DATA(&sim.m_syncr);
|
||||
LOGSIM("- W : VCO x %d\n", data & m68340_sim::REG_SYNCR_W ? 4 : 1);
|
||||
LOGSIM("- X : System clock / %d\n", data & m68340_sim::REG_SYNCR_X ? 1 : 2);
|
||||
LOGSIM("- Y5-Y0: Divider: %d\n", (data & m68340_sim::REG_SYNCR_Y_MSK) >> 8);
|
||||
LOGSIM("- SLIMP: Loss of VCO input reference: %s\n", data & m68340_sim::REG_SYNCR_SLIMP ? "yes" : "no");
|
||||
LOGSIM("- SLOCK: Synthesizer lock: %s\n", data & m68340_sim::REG_SYNCR_SLOCK ? "yes" : "no");
|
||||
LOGSIM("- RSTEN: Loss of signal causes %s\n", data & m68340_sim::REG_SYNCR_RSTEN ? "system reset" : "limp mode (no external reference)");
|
||||
LOGSIM("- STSIM: LPSTOP makes SIM40 to use %s\n", data & m68340_sim::REG_SYNCR_STSIM ? "VCO" : "external clock/oscillator");
|
||||
LOGSIM("- STEXT: LPSTOP makes CLKOUT %s\n", data & m68340_sim::REG_SYNCR_STEXT ? "driven by SIM40 clock" : "low");
|
||||
|
||||
case m68340SIM_AVR_RSR:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x, (%04x) (AVR, RSR - Auto Vector Register, Reset Status Register) - not implemented\n", pc, offset*2,mem_mask);
|
||||
return space.machine().rand();
|
||||
// Adjust VCO
|
||||
if (m_clock_mode == m68340_sim::CLOCK_MODE_CRYSTAL)
|
||||
{
|
||||
set_unscaled_clock(m_crystal *
|
||||
(4 << (((sim.m_syncr & m68340_sim::REG_SYNCR_W) != 0 ? 2 : 0) + ((sim.m_syncr & m68340_sim::REG_SYNCR_X) != 0 ? 1 : 0))) *
|
||||
(((sim.m_syncr & m68340_sim::REG_SYNCR_Y_MSK) >> 8) & 0x3f));
|
||||
LOGCLOCK( " - Clock: %d [0x%08x]\n", clock(), clock());
|
||||
}
|
||||
break;
|
||||
|
||||
case m68340SIM_SWIV_SYPCR:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x, (%04x) (SWIV_SYPCR - Software Interrupt Vector, System Protection Control Register) - not implemented\n", pc, offset*2,mem_mask);
|
||||
return space.machine().rand();
|
||||
case m68340_sim::REG_AVR_RSR:
|
||||
LOGSIM("PC: %08x %s %04x, %04x (%04x) (AVR, RSR - Auto Vector Register, Reset Status Register)\n", pc, FUNCNAME, offset * 2, data, mem_mask);
|
||||
COMBINE_DATA(&sim.m_avr_rsr);
|
||||
LOGSIM("- AVR: AV7-AV1 autovector bits: %02x\n", ((data & m68340_sim::REG_AVR_VEC) >> 8) & 0xff);
|
||||
LOGSIM("- RSR: Last reset type: %02x - not implemented\n", (data & m68340_sim::REG_RSR_RESBITS) & 0xff);
|
||||
break;
|
||||
|
||||
case m68340SIM_PICR:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x, (%04x) (PICR - Periodic Interrupt Control Register) - not implemented\n", pc, offset*2,mem_mask);
|
||||
return space.machine().rand();
|
||||
case m68340_sim::REG_SWIV_SYPCR:
|
||||
LOGSIM("PC: %08x %s %04x, %04x (%04x) (SWIV_SYPCR - Software Interrupt Vector, System Protection Control Register) - not implemented\n", pc, FUNCNAME, offset * 2, data, mem_mask);
|
||||
COMBINE_DATA(&sim.m_swiv_sypcr);
|
||||
LOGSIM("- SWIV: Software watchdog Interrupt Vector: %02x\n", ((data & m68340_sim::REG_SWIV_VEC) >> 8) & 0xff);
|
||||
LOGSIM("- SWE : Software watchdog %s\n", (data & m68340_sim::REG_SYPCR_SWE) ? "enabled" : "disabled");
|
||||
LOGSIM("- SWRI: Software watchdog causes %s\n", (data & m68340_sim::REG_SYPCR_SWRI) ? "system reset" : "level 7 IRQ (NMI)");
|
||||
LOGSIM("- SWT : Software watchdog timing 2^%s/EXTAL Input Frequency\n",
|
||||
std::array<char const *, 8> {{"9", "11", "13", "15", "18", "20", "22", "24"}}[((data & m68340_sim::REG_SYPCR_SWT) >> 4) | ((sim.m_pitr & m68340_sim::REG_PITR_SWP) >> 7)]);
|
||||
break;
|
||||
|
||||
case m68340SIM_PITR:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x, (%04x) (PITR - Periodic Interrupt Timer Register) - not implemented\n", pc, offset*2,mem_mask);
|
||||
return space.machine().rand();
|
||||
case m68340_sim::REG_PICR:
|
||||
LOGPIT("PC: %08x %s %04x, %04x (%04x) (PICR - Periodic Interrupt Control Register)\n", pc, FUNCNAME, offset*2,data,mem_mask);
|
||||
COMBINE_DATA(&sim.m_picr);
|
||||
LOGPIT("- PIRQL: Periodic Interrupt Level %d%s\n", (data & m68340_sim::REG_PICR_PIRQL) >> 8, (data & m68340_sim::REG_PICR_PIRQL) == 0 ? " (disabled)" : "");
|
||||
LOGPIT("- PIV : Periodic Interrupt Vector %02x\n", (data & m68340_sim::REG_PICR_PIVEC));
|
||||
break;
|
||||
|
||||
case m68340SIM_SWSR:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x, (%04x) (SWSR - Software Service) - not implemented\n", pc, offset*2,mem_mask);
|
||||
return space.machine().rand();
|
||||
case m68340_sim::REG_PITR:
|
||||
LOGPIT("PC: %08x %s %04x, %04x (%04x) (PITR - Periodic Interrupt Timer Register)\n", pc, FUNCNAME, offset*2,data,mem_mask);
|
||||
COMBINE_DATA(&sim.m_pitr);
|
||||
LOGSIM("- SWP : Software watchdog prescale factor is %d\n", (data & m68340_sim::REG_PITR_SWP) ? 512 : 1);
|
||||
LOGPIT("- PTP : Periodic timer prescale factor is %d\n", (data & m68340_sim::REG_PITR_PTP) ? 512 : 1);
|
||||
LOGPIT("- COUNT: is %d%s\n", (data & m68340_sim::REG_PITR_COUNT), (data & m68340_sim::REG_PITR_COUNT) == 0 ? " (off)" : "d");
|
||||
if ( (sim.m_mcr & m68340_sim::REG_MCR_FRZ1) == 0 && (sim.m_pitr & m68340_sim::REG_PITR_COUNT) != 0)
|
||||
{
|
||||
LOGPIT("Starting PIT timer\n");
|
||||
sim.m_pit_counter = sim.m_pitr & m68340_sim::REG_PITR_COUNT;
|
||||
m_irq_timer->adjust(cycles_to_attotime((m_crystal / 4) / ((sim.m_pitr & m68340_sim::REG_PITR_PTP) != 0 ? 512 : 1)));
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case m68340_sim::REG_SWSR:
|
||||
// basically watchdog, you must write an alternating pattern of 0x55 / 0xaa to keep the watchdog from resetting the system
|
||||
//LOGSIM("- %08x %s %04x, %04x (%04x) (SWSR - Software Service)\n", pc, FUNCNAME, offset*2,data,mem_mask);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x, (%04x)\n", pc, offset*2,mem_mask);
|
||||
}
|
||||
LOGSIM("- %08x %s %04x, %04x (%04x) - not implemented\n", pc, FUNCNAME, offset*2,data,mem_mask);
|
||||
|
||||
return 0x0000;
|
||||
}
|
||||
}
|
||||
|
||||
READ8_MEMBER( m68340_cpu_device::m68340_internal_sim_ports_r )
|
||||
@ -130,8 +205,8 @@ READ8_MEMBER( m68340_cpu_device::m68340_internal_sim_ports_r )
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case m68340SIM_PORTA:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x (PORTA - Port A Data)\n", pc, offset);
|
||||
case m68340_sim::REG_PORTA:
|
||||
LOGR("- %08x %s %04x (PORTA - Port A Data)\n", pc, FUNCNAME, offset);
|
||||
sim.m_porta &= sim.m_ddra;
|
||||
// TODO: call callback
|
||||
|
||||
@ -148,26 +223,26 @@ READ8_MEMBER( m68340_cpu_device::m68340_internal_sim_ports_r )
|
||||
val = sim.m_porta;
|
||||
break;
|
||||
|
||||
case m68340SIM_DDRA:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x (DDRA - Port A Data Direction)\n", pc, offset);
|
||||
case m68340_sim::REG_DDRA:
|
||||
LOGR("- %08x %s %04x (DDRA - Port A Data Direction)\n", pc, FUNCNAME, offset);
|
||||
val = sim.m_ddra;
|
||||
break;
|
||||
|
||||
case m68340SIM_PPARA1:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x (PPRA1 - Port A Pin Assignment 1)\n", pc, offset);
|
||||
case m68340_sim::REG_PPARA1:
|
||||
LOGR("- %08x %s %04x (PPRA1 - Port A Pin Assignment 1)\n", pc, FUNCNAME, offset);
|
||||
val = sim.m_ppara1;
|
||||
break;
|
||||
|
||||
case m68340SIM_PPARA2:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x (PPRA2 - Port A Pin Assignment 2) - not implemented\n", pc, offset);
|
||||
case m68340_sim::REG_PPARA2:
|
||||
LOGR("- %08x %s %04x (PPRA2 - Port A Pin Assignment 2) - not implemented\n", pc, FUNCNAME, offset);
|
||||
val = sim.m_ppara2;
|
||||
break;
|
||||
|
||||
case m68340SIM_PORTB1:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x (PORTB1 - Port B Data 1)\n", pc, offset);
|
||||
case m68340_sim::REG_PORTB1:
|
||||
LOGR("- %08x %s %04x (PORTB1 - Port B Data 1)\n", pc, FUNCNAME, offset);
|
||||
// Fallthrough to mirror register
|
||||
case m68340SIM_PORTB:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x (PORTB - Port B Data 0)\n", pc, offset);
|
||||
case m68340_sim::REG_PORTB:
|
||||
LOGR("- %08x %s %04x (PORTB - Port B Data 0)\n", pc, FUNCNAME, offset);
|
||||
sim.m_portb &= sim.m_ddrb;
|
||||
// TODO: call callback
|
||||
|
||||
@ -184,19 +259,19 @@ READ8_MEMBER( m68340_cpu_device::m68340_internal_sim_ports_r )
|
||||
val = sim.m_portb;
|
||||
break;
|
||||
|
||||
case m68340SIM_DDRB:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x (DDR - Port B Data Direction)\n", pc, offset);
|
||||
case m68340_sim::REG_DDRB:
|
||||
LOGR("- %08x %s %04x (DDR - Port B Data Direction)\n", pc, FUNCNAME, offset);
|
||||
val = sim.m_ddrb;
|
||||
break;
|
||||
|
||||
case m68340SIM_PPARB:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x (PPARB - Port B Pin Assignment)\n", pc, offset);
|
||||
case m68340_sim::REG_PPARB:
|
||||
LOGR("- %08x %s %04x (PPARB - Port B Pin Assignment)\n", pc, FUNCNAME, offset);
|
||||
val = sim.m_pparb;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOGR("- %08x m68340_internal_sim_r %04x (ILLEGAL?)\n", pc, offset);
|
||||
logerror("%08x m68340_internal_sim_r %04x (ILLEGAL?)\n", pc, offset);
|
||||
LOGR("- %08x %s %04x (ILLEGAL?)\n", pc, FUNCNAME, offset);
|
||||
logerror("%08x m68340_internal_sim_r %04x (ILLEGAL?)\n", pc, FUNCNAME, offset);
|
||||
break;
|
||||
}
|
||||
LOGR(" * Reg %02x -> %02x - %s\n", offset, val, std::array<char const *, 16>
|
||||
@ -205,89 +280,6 @@ READ8_MEMBER( m68340_cpu_device::m68340_internal_sim_ports_r )
|
||||
return val;
|
||||
}
|
||||
|
||||
READ32_MEMBER( m68340_cpu_device::m68340_internal_sim_cs_r )
|
||||
{
|
||||
LOGR("%s\n", FUNCNAME);
|
||||
offset += m68340SIM_AM_CS0>>2;
|
||||
|
||||
assert(m68340SIM);
|
||||
m68340_sim &sim = *m68340SIM;
|
||||
|
||||
int pc = space.device().safe_pc();
|
||||
|
||||
switch (offset<<2)
|
||||
{
|
||||
case m68340SIM_AM_CS0: return sim.m_am[0];
|
||||
case m68340SIM_BA_CS0: return sim.m_ba[0];
|
||||
case m68340SIM_AM_CS1: return sim.m_am[1];
|
||||
case m68340SIM_BA_CS1: return sim.m_ba[1];
|
||||
case m68340SIM_AM_CS2: return sim.m_am[2];
|
||||
case m68340SIM_BA_CS2: return sim.m_ba[2];
|
||||
case m68340SIM_AM_CS3: return sim.m_am[3];
|
||||
case m68340SIM_BA_CS3: return sim.m_ba[3];
|
||||
|
||||
default:
|
||||
logerror("%08x m68340_internal_sim_r %08x, (%08x)\n", pc, offset*4,mem_mask);
|
||||
}
|
||||
|
||||
return 0x00000000;
|
||||
}
|
||||
|
||||
WRITE16_MEMBER( m68340_cpu_device::m68340_internal_sim_w )
|
||||
{
|
||||
LOGSETUP("%s\n", FUNCNAME);
|
||||
assert(m68340SIM);
|
||||
//m68340_sim &sim = *m68340SIM;
|
||||
|
||||
int pc = space.device().safe_pc();
|
||||
|
||||
switch (offset<<1)
|
||||
{
|
||||
case m68340SIM_MCR:
|
||||
LOGSETUP("- %08x m68340_internal_sim_w %04x, %04x (%04x) (MCR - Module Configuration Register) - not implemented\n", pc, offset*2,data,mem_mask);
|
||||
break;
|
||||
|
||||
case m68340SIM_SYNCR:
|
||||
LOGSETUP("- %08x m68340_internal_sim_w %04x, %04x (%04x) (SYNCR - Clock Synthesizer Register) - not implemented\n", pc, offset*2,data,mem_mask);
|
||||
break;
|
||||
|
||||
|
||||
case m68340SIM_AVR_RSR:
|
||||
LOGSETUP("- %08x m68340_internal_sim_w %04x, %04x (%04x) (AVR, RSR - Auto Vector Register, Reset Status Register)\n", pc, offset*2,data,mem_mask);
|
||||
COMBINE_DATA(&m_avr);
|
||||
break;
|
||||
|
||||
case m68340SIM_SWIV_SYPCR:
|
||||
LOGSETUP("- %08x m68340_internal_sim_w %04x, %04x (%04x) (SWIV_SYPCR - Software Interrupt Vector, System Protection Control Register) - not implemented\n", pc, offset*2,data,mem_mask);
|
||||
break;
|
||||
|
||||
case m68340SIM_PICR:
|
||||
LOGSETUP("- %08x m68340_internal_sim_w %04x, %04x (%04x) (PICR - Periodic Interrupt Control Register)\n", pc, offset*2,data,mem_mask);
|
||||
COMBINE_DATA(&m_picr);
|
||||
break;
|
||||
|
||||
case m68340SIM_PITR:
|
||||
LOGSETUP("- %08x m68340_internal_sim_w %04x, %04x (%04x) (PITR - Periodic Interrupt Timer Register)\n", pc, offset*2,data,mem_mask);
|
||||
COMBINE_DATA(&m_pitr);
|
||||
if (m_pitr !=0 ) // hack
|
||||
{
|
||||
//LOGSETUP("- timer set\n");
|
||||
m_irq_timer->adjust(cycles_to_attotime(20000)); // hack
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case m68340SIM_SWSR:
|
||||
// basically watchdog, you must write an alternating pattern of 0x55 / 0xaa to keep the watchdog from resetting the system
|
||||
//LOGSETUP("- %08x m68340_internal_sim_w %04x, %04x (%04x) (SWSR - Software Service)\n", pc, offset*2,data,mem_mask);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOGSETUP("- %08x m68340_internal_sim_w %04x, %04x (%04x) - not implemented\n", pc, offset*2,data,mem_mask);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
WRITE8_MEMBER( m68340_cpu_device::m68340_internal_sim_ports_w )
|
||||
{
|
||||
LOG("%s", FUNCNAME);
|
||||
@ -297,66 +289,66 @@ WRITE8_MEMBER( m68340_cpu_device::m68340_internal_sim_ports_w )
|
||||
|
||||
int pc = space.device().safe_pc();
|
||||
|
||||
LOGSETUP(" * Reg %02x <- %02x - %s\n", offset, data, std::array<char const *, 16>
|
||||
{{"", "PORTA", "", "DDRA", "", "PPRA1", "", "PPRA2", "", "PORTB","", "PORTB1", "", "DDRB", "", "PPARB"}}[offset - 0x10]);
|
||||
|
||||
LOGSETUP(" * Reg %02x <- %02x - %s\n", offset, data, std::array<char const *, 8>
|
||||
{{"PORTA", "DDRA", "PPRA1", "PPRA2", "PORTB", "PORTB1", "DDRB", "PPARB"}}[(offset - 0x10) / 2]);
|
||||
switch (offset)
|
||||
{
|
||||
case m68340SIM_PORTA:
|
||||
LOGPORTS("- %08x %04x, %02x (PORTA - Port A Data)\n", pc, offset,data);
|
||||
case m68340_sim::REG_PORTA:
|
||||
LOGDATA("- %08x %04x, %02x (PORTA - Port A Data)\n", pc, offset,data);
|
||||
sim.m_porta = (data & sim.m_ddra & sim.m_ppara1);
|
||||
|
||||
// callback
|
||||
m_pa_out_cb ((offs_t)0, sim.m_porta);
|
||||
break;
|
||||
|
||||
case m68340SIM_DDRA:
|
||||
case m68340_sim::REG_DDRA:
|
||||
LOGPORTS("- %08x %04x, %02x (DDRA - Port A Data Direction)\n", pc, offset,data);
|
||||
sim.m_ddra = data;
|
||||
break;
|
||||
|
||||
case m68340SIM_PPARA1:
|
||||
case m68340_sim::REG_PPARA1:
|
||||
LOGPORTS("- %08x %04x, %02x (PPARA1 - Port A Pin Assignment 1)\n", pc, offset,data);
|
||||
sim.m_ppara1 = data;
|
||||
break;
|
||||
|
||||
case m68340SIM_PPARA2:
|
||||
case m68340_sim::REG_PPARA2:
|
||||
LOGPORTS("- %08x %04x, %02x (PPARA2 - Port A Pin Assignment 2)\n", pc, offset,data);
|
||||
sim.m_ppara2 = data;
|
||||
break;
|
||||
|
||||
case m68340SIM_PORTB1:
|
||||
LOGPORTS("- %08x %04x, %02x (PORTB1 - Port B Data - mirror)\n", pc, offset,data);
|
||||
case m68340_sim::REG_PORTB1:
|
||||
LOGDATA("- %08x %04x, %02x (PORTB1 - Port B Data - mirror)\n", pc, offset,data);
|
||||
// Falling through to mirrored register portb
|
||||
case m68340SIM_PORTB:
|
||||
LOGPORTS("- %08x %04x, %02x (PORTB - Port B Data)\n", pc, offset,data);
|
||||
case m68340_sim::REG_PORTB:
|
||||
LOGDATA("- %08x %04x, %02x (PORTB - Port B Data)\n", pc, offset,data);
|
||||
sim.m_portb = (data & sim.m_ddrb & sim.m_pparb);
|
||||
|
||||
// callback
|
||||
m_pb_out_cb ((offs_t)0, sim.m_portb);
|
||||
break;
|
||||
|
||||
case m68340SIM_DDRB:
|
||||
case m68340_sim::REG_DDRB:
|
||||
LOGPORTS("- %08x %04x, %02x (DDR - Port B Data Direction)\n", pc, offset,data);
|
||||
sim.m_ddrb = data;
|
||||
break;
|
||||
|
||||
case m68340SIM_PPARB:
|
||||
case m68340_sim::REG_PPARB:
|
||||
LOGPORTS("- %08x %04x, %02x (PPARB - Port B Pin Assignment)\n", pc, offset,data);
|
||||
sim.m_pparb = data;
|
||||
break;
|
||||
|
||||
default:
|
||||
LOGPORTS("- %08x %04x, %02x (ILLEGAL?) - not implemented\n", pc, offset,data);
|
||||
logerror("%08x m68340_internal_sim_w %04x, %02x (ILLEGAL?)\n", pc, offset,data);
|
||||
LOGPORTS("- %08x %s %04x, %02x (ILLEGAL?) - not implemented\n", pc, FUNCNAME, offset,data);
|
||||
logerror("%08x m68340_internal_sim_ports_w %04x, %02x (ILLEGAL?)\n", pc, offset,data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( m68340_cpu_device::m68340_internal_sim_cs_w )
|
||||
READ32_MEMBER( m68340_cpu_device::m68340_internal_sim_cs_r )
|
||||
{
|
||||
LOGSETUP("%s\n", FUNCNAME);
|
||||
offset += m68340SIM_AM_CS0>>2;
|
||||
LOGR("%s\n", FUNCNAME);
|
||||
offset += m68340_sim::REG_AM_CS0>>2;
|
||||
|
||||
assert(m68340SIM);
|
||||
m68340_sim &sim = *m68340SIM;
|
||||
|
||||
@ -364,54 +356,87 @@ WRITE32_MEMBER( m68340_cpu_device::m68340_internal_sim_cs_w )
|
||||
|
||||
switch (offset<<2)
|
||||
{
|
||||
case m68340SIM_AM_CS0:
|
||||
case m68340_sim::REG_AM_CS0: return sim.m_am[0];
|
||||
case m68340_sim::REG_BA_CS0: return sim.m_ba[0];
|
||||
case m68340_sim::REG_AM_CS1: return sim.m_am[1];
|
||||
case m68340_sim::REG_BA_CS1: return sim.m_ba[1];
|
||||
case m68340_sim::REG_AM_CS2: return sim.m_am[2];
|
||||
case m68340_sim::REG_BA_CS2: return sim.m_ba[2];
|
||||
case m68340_sim::REG_AM_CS3: return sim.m_am[3];
|
||||
case m68340_sim::REG_BA_CS3: return sim.m_ba[3];
|
||||
|
||||
default:
|
||||
logerror("%08x m68340_internal_sim_r %08x, (%08x)\n", pc, offset*4,mem_mask);
|
||||
}
|
||||
|
||||
return 0x00000000;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( m68340_cpu_device::m68340_internal_sim_cs_w )
|
||||
{
|
||||
LOG("%s\n", FUNCNAME);
|
||||
offset += m68340_sim::REG_AM_CS0>>2;
|
||||
LOGSETUP("- %08x %s %08x, %08x (%08x) - not implemented\n", pc, FUNCNAME, offset*4,data,mem_mask);
|
||||
|
||||
assert(m68340SIM);
|
||||
m68340_sim &sim = *m68340SIM;
|
||||
|
||||
int pc = space.device().safe_pc();
|
||||
|
||||
switch (offset<<2)
|
||||
{
|
||||
case m68340_sim::REG_AM_CS0:
|
||||
COMBINE_DATA(&sim.m_am[0]);
|
||||
break;
|
||||
|
||||
case m68340SIM_BA_CS0:
|
||||
case m68340_sim::REG_BA_CS0:
|
||||
COMBINE_DATA(&sim.m_ba[0]);
|
||||
break;
|
||||
|
||||
case m68340SIM_AM_CS1:
|
||||
case m68340_sim::REG_AM_CS1:
|
||||
COMBINE_DATA(&sim.m_am[1]);
|
||||
break;
|
||||
|
||||
case m68340SIM_BA_CS1:
|
||||
case m68340_sim::REG_BA_CS1:
|
||||
COMBINE_DATA(&sim.m_ba[1]);
|
||||
break;
|
||||
|
||||
case m68340SIM_AM_CS2:
|
||||
case m68340_sim::REG_AM_CS2:
|
||||
COMBINE_DATA(&sim.m_am[2]);
|
||||
break;
|
||||
|
||||
case m68340SIM_BA_CS2:
|
||||
case m68340_sim::REG_BA_CS2:
|
||||
COMBINE_DATA(&sim.m_ba[2]);
|
||||
break;
|
||||
|
||||
case m68340SIM_AM_CS3:
|
||||
case m68340_sim::REG_AM_CS3:
|
||||
COMBINE_DATA(&sim.m_am[3]);
|
||||
break;
|
||||
|
||||
case m68340SIM_BA_CS3:
|
||||
case m68340_sim::REG_BA_CS3:
|
||||
COMBINE_DATA(&sim.m_ba[3]);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOGSETUP("- %08x m68340_internal_sim_w %08x, %08x (%08x) - not implemented\n", pc, offset*4,data,mem_mask);
|
||||
logerror("%08x m68340_internal_sim_w %08x, %08x (%08x)\n", pc, offset*4,data,mem_mask);
|
||||
logerror("%08x m68340_internal_sim_cs_w %08x, %08x (%08x)\n", pc, offset*4,data,mem_mask);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void m68340_cpu_device::do_timer_irq()
|
||||
void m68340_cpu_device::do_pit_irq()
|
||||
{
|
||||
//logerror("do_timer_irq\n");
|
||||
int timer_irq_level = (m_picr & 0x0700)>>8;
|
||||
int timer_irq_vector = (m_picr & 0x00ff)>>0;
|
||||
assert(m68340SIM);
|
||||
m68340_sim &sim = *m68340SIM;
|
||||
|
||||
//logerror("do_pit_irq\n");
|
||||
int timer_irq_level = (sim.m_picr & 0x0700) >> 8;
|
||||
int timer_irq_vector = (sim.m_picr & 0x00ff) >> 0;
|
||||
|
||||
if (timer_irq_level) // 0 is irq disabled
|
||||
{
|
||||
int use_autovector = (m_avr >> timer_irq_level)&1;
|
||||
int use_autovector = (sim.m_avr_rsr >> (8 + timer_irq_level)) & 1;
|
||||
|
||||
LOGPIT("PIT IRQ triggered, Lvl: %d using Vector: %d (0 = auto vector)\n", timer_irq_level, use_autovector ? 0 : timer_irq_vector);
|
||||
|
||||
if (use_autovector)
|
||||
{
|
||||
@ -429,12 +454,13 @@ void m68340_cpu_device::do_timer_irq()
|
||||
|
||||
TIMER_CALLBACK_MEMBER(m68340_cpu_device::periodic_interrupt_timer_callback)
|
||||
{
|
||||
do_timer_irq();
|
||||
m_irq_timer->adjust(cycles_to_attotime(20000)); // hack
|
||||
do_tick_pit();
|
||||
}
|
||||
|
||||
void m68340_cpu_device::start_68340_sim()
|
||||
{
|
||||
LOG("%s\n", FUNCNAME);
|
||||
LOGCLOCK( " - Clock: %d [0x%08x]\n", clock(), clock());
|
||||
m_irq_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(m68340_cpu_device::periodic_interrupt_timer_callback),this));
|
||||
|
||||
// resolve callbacks Port A
|
||||
@ -444,11 +470,35 @@ void m68340_cpu_device::start_68340_sim()
|
||||
// resolve callbacks Port B
|
||||
m_pb_out_cb.resolve_safe();
|
||||
m_pb_in_cb.resolve();
|
||||
|
||||
// Setup correct VCO/clock speed based on reset values and crystal
|
||||
assert(m68340SIM);
|
||||
m68340_sim &sim = *m68340SIM;
|
||||
switch (m_clock_mode)
|
||||
{
|
||||
case m68340_sim::CLOCK_MODE_EXT:
|
||||
LOGCLOCK("External Clock Mode\n");
|
||||
break;
|
||||
case m68340_sim::CLOCK_MODE_EXT_PLL:
|
||||
LOGCLOCK("External Clock Mode with PLL - not implemented\n");
|
||||
logerror("External Clock Mode with PLL - not implemented\n");
|
||||
break;
|
||||
case m68340_sim::CLOCK_MODE_CRYSTAL:
|
||||
LOGCLOCK("Crystal Mode with VCO and PLL\n");
|
||||
set_unscaled_clock(m_crystal *
|
||||
(4 << (((sim.m_syncr & m68340_sim::REG_SYNCR_W) != 0 ? 2 : 0) + ((sim.m_syncr & m68340_sim::REG_SYNCR_X) != 0 ? 1 : 0))) *
|
||||
(((sim.m_syncr & m68340_sim::REG_SYNCR_Y_MSK) >> 8) & 0x3f));
|
||||
LOGCLOCK("SYNCR: %04x\n", sim.m_syncr);
|
||||
break;
|
||||
default:
|
||||
logerror("Unknown Clock mode, check schematics and/or the source code\n");
|
||||
}
|
||||
LOGCLOCK( " - Clock: %d [0x%08x]\n", clock(), clock());
|
||||
}
|
||||
|
||||
void m68340_sim::reset()
|
||||
{
|
||||
LOGSETUP("%s\n", FUNCNAME);
|
||||
LOG("%s\n", FUNCNAME);
|
||||
|
||||
// Ports - only setup those that are affected by reset
|
||||
m_ddra = 0x00;
|
||||
@ -456,4 +506,51 @@ void m68340_sim::reset()
|
||||
m_ppara2 = 0x00;
|
||||
m_ddrb = 0x00;
|
||||
m_pparb = 0xff;
|
||||
|
||||
// SIM
|
||||
m_mcr = 0x608f;
|
||||
m_syncr = 0x3f00;
|
||||
m_avr_rsr = 0x0000;
|
||||
m_swiv_sypcr = 0x0f00;
|
||||
m_picr= 0x000f;
|
||||
m_pitr= 0x0000; // TODO: read MODCK pin to set the clock modes for watch dog and periodic timer
|
||||
m_swsr= 0x0000;
|
||||
|
||||
}
|
||||
|
||||
/* do_tick_pit works on whole clock cycles, no flank support */
|
||||
void m68340_cpu_device::do_tick_pit()
|
||||
{
|
||||
assert(m68340SIM);
|
||||
m68340_sim &sim = *m68340SIM;
|
||||
|
||||
sim.m_pit_counter--;
|
||||
if ( ( (sim.m_mcr & m68340_sim::REG_MCR_FRZ1) == 0) &&
|
||||
( (sim.m_pit_counter != 0 || (sim.m_pitr & m68340_sim::REG_PITR_COUNT) != 0)))
|
||||
{
|
||||
LOGPIT("Re-arming PIT timer\n");
|
||||
sim.m_pit_counter = sim.m_pitr & m68340_sim::REG_PITR_COUNT;
|
||||
m_irq_timer->adjust(cycles_to_attotime((m_crystal / 4) / ((sim.m_pitr & m68340_sim::REG_PITR_PTP) != 0 ? 512 : 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGPIT("Stopping PIT timer dues to %s\n", (sim.m_mcr & m68340_sim::REG_MCR_FRZ1) != 0 ? "Freeze" : "Counter disabled");
|
||||
m_irq_timer->adjust(attotime::never);
|
||||
}
|
||||
|
||||
if (sim.m_pit_counter == 0) // Zero detect
|
||||
{
|
||||
LOGPIT("PIT timer reached zero!\n");
|
||||
do_pit_irq();
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( m68340_cpu_device::extal_w )
|
||||
{
|
||||
LOGPIT("%s H1 set to %d\n", FUNCNAME, state);
|
||||
m_extal = state;
|
||||
if (m_extal == ASSERT_LINE)
|
||||
{
|
||||
do_tick_pit();
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ public:
|
||||
uint32_t m_am[4]; // chip select address mask + control, unaffected by reset
|
||||
uint32_t m_ba[4]; // chip select base address + control, unaffected by reset
|
||||
|
||||
// Ports Reset values
|
||||
// Port registers Reset values
|
||||
uint8_t m_porta; // unaffected by reset
|
||||
uint8_t m_ddra; // 0x00
|
||||
uint8_t m_ppara1; // 0xff
|
||||
@ -21,7 +21,102 @@ public:
|
||||
uint8_t m_ddrb; // 0x00
|
||||
uint8_t m_pparb; // 0xff
|
||||
|
||||
// SIM
|
||||
uint16_t m_mcr; // 0x608f
|
||||
uint16_t m_syncr; // 0x3f00
|
||||
uint16_t m_avr_rsr; // 0x0000
|
||||
uint16_t m_swiv_sypcr;//0x0f00
|
||||
uint16_t m_picr; // 0x000f
|
||||
uint16_t m_pitr; // 0x0000 | ~MODCK pin
|
||||
uint16_t m_swsr; // 0x0000
|
||||
|
||||
// Timers and counters
|
||||
uint8_t m_pit_counter;
|
||||
|
||||
void reset();
|
||||
|
||||
enum {
|
||||
REG_MCR = 0x00,
|
||||
REG_SYNCR = 0x04,
|
||||
REG_AVR_RSR = 0x06,
|
||||
REG_PORTA = 0x11,
|
||||
REG_DDRA = 0x13,
|
||||
REG_PPARA1 = 0x15,
|
||||
REG_PPARA2 = 0x17,
|
||||
REG_PORTB = 0x19,
|
||||
REG_PORTB1 = 0x1b,
|
||||
REG_DDRB = 0x1d,
|
||||
REG_PPARB = 0x1f,
|
||||
REG_SWIV_SYPCR = 0x20,
|
||||
REG_PICR = 0x22,
|
||||
REG_PITR = 0x24,
|
||||
REG_SWSR = 0x26,
|
||||
REG_AM_CS0 = 0x40,
|
||||
REG_BA_CS0 = 0x44,
|
||||
REG_AM_CS1 = 0x48,
|
||||
REG_BA_CS1 = 0x4c,
|
||||
REG_AM_CS2 = 0x50,
|
||||
REG_BA_CS2 = 0x54,
|
||||
REG_AM_CS3 = 0x58,
|
||||
REG_BA_CS3 = 0x5c,
|
||||
};
|
||||
|
||||
enum {
|
||||
REG_MCR_FRZ1 = 0x4000,
|
||||
REG_MCR_FRZ0 = 0x2000,
|
||||
REG_MCR_FIRQ = 0x1000,
|
||||
REG_MCR_SHEN = 0x0300,
|
||||
REG_MCR_SVREG = 0x0800,
|
||||
REG_MCR_ARBLV = 0x000f,
|
||||
};
|
||||
|
||||
enum {
|
||||
REG_AVR_VEC = 0xff00,
|
||||
REG_RSR_RESBITS = 0x00ff,
|
||||
};
|
||||
|
||||
enum {
|
||||
REG_SWIV_VEC = 0xff00,
|
||||
REG_SYPCR_SWE = 0x0080,
|
||||
REG_SYPCR_SWRI = 0x0040,
|
||||
REG_SYPCR_SWT = 0x0030,
|
||||
REG_SYPCR_DBFE = 0x0008,
|
||||
REG_SYPCR_BME = 0x0004,
|
||||
REG_SYPCR_BMT = 0x0003,
|
||||
};
|
||||
|
||||
enum {
|
||||
REG_PICR_PIRQL = 0x0700,
|
||||
REG_PICR_PIVEC = 0x00ff,
|
||||
};
|
||||
|
||||
enum {
|
||||
REG_PITR_SWP = 0x0200,
|
||||
REG_PITR_PTP = 0x0100,
|
||||
REG_PITR_COUNT = 0x00ff,
|
||||
};
|
||||
|
||||
enum {
|
||||
REG_SYNCR_W = 0x8000,
|
||||
REG_SYNCR_X = 0x4000,
|
||||
REG_SYNCR_Y_MSK = 0x3f00,
|
||||
REG_SYNCR_SLIMP = 0x0010,
|
||||
REG_SYNCR_SLOCK = 0x0008,
|
||||
REG_SYNCR_RSTEN = 0x0004,
|
||||
REG_SYNCR_STSIM = 0x0002,
|
||||
REG_SYNCR_STEXT = 0x0001,
|
||||
};
|
||||
|
||||
enum {
|
||||
CLOCK_PLL = 0x01,
|
||||
CLOCK_MODCK = 0x02,
|
||||
};
|
||||
|
||||
enum {
|
||||
CLOCK_MODE_EXT = 0x00,
|
||||
CLOCK_MODE_EXT_PLL = 0x01,
|
||||
CLOCK_MODE_CRYSTAL = 0x03,
|
||||
};
|
||||
};
|
||||
|
||||
#endif // MAME_MACHINE_68340SIM_H
|
||||
|
@ -1,31 +1,627 @@
|
||||
// license:BSD-3-Clause
|
||||
// copyright-holders:David Haywood
|
||||
// copyright-holders:David Haywood, Joakim Larsson Edstrom
|
||||
/* 68340 TIMER module */
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "68340.h"
|
||||
|
||||
//**************************************************************************
|
||||
// MACROS / CONSTANTS
|
||||
//**************************************************************************
|
||||
|
||||
READ32_MEMBER( m68340_cpu_device::m68340_internal_timer_r )
|
||||
//#define LOG_GENERAL (1U << 0) // Already defined in logmacro.h
|
||||
#define LOG_SETUP (1U << 1)
|
||||
#define LOG_READ (1U << 2)
|
||||
#define LOG_TIMER (1U << 3)
|
||||
#define LOG_INT (1U << 4)
|
||||
|
||||
//#define VERBOSE (LOG_SETUP|LOG_INT|LOG_TIMER)
|
||||
#define LOG_OUTPUT_FUNC printf // Needs always to be enabled as the default value 'logerror' is not available here
|
||||
|
||||
#include "logmacro.h"
|
||||
|
||||
//#define LOG(...) LOGMASKED(LOG_GENERAL, __VA_ARGS__) // Already defined in logmacro.h
|
||||
#define LOGSETUP(...) LOGMASKED(LOG_SETUP, __VA_ARGS__)
|
||||
#define LOGR(...) LOGMASKED(LOG_READ, __VA_ARGS__)
|
||||
#define LOGTIMER(...) LOGMASKED(LOG_TIMER, __VA_ARGS__)
|
||||
#define LOGINT(...) LOGMASKED(LOG_INT, __VA_ARGS__)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define FUNCNAME __func__
|
||||
#else
|
||||
#define FUNCNAME __PRETTY_FUNCTION__
|
||||
#endif
|
||||
|
||||
READ16_MEMBER( m68340_cpu_device::m68340_internal_timer_r )
|
||||
{
|
||||
LOGSETUP("%s\n", FUNCNAME);
|
||||
|
||||
assert(m68340TIMER);
|
||||
//m68340_timer &timer = *m68340TIMER;
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
int val = 0;
|
||||
|
||||
int pc = space.device().safe_pc();
|
||||
logerror("%08x m68340_internal_timer_r %08x, (%08x)\n", pc, offset*4,mem_mask);
|
||||
logerror("%08x m68340_internal_timer_r %08x, (%08x)\n", pc, offset * 2, mem_mask);
|
||||
|
||||
return 0x00000000;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
case m68340_timer::REG_MCR:
|
||||
val = timer.m_mcr[id];
|
||||
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];
|
||||
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];
|
||||
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];
|
||||
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];
|
||||
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];
|
||||
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];
|
||||
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];
|
||||
LOGTIMER("- %08x %s %04x, %04x (%04x) (COM - Compare Register)\n", pc, FUNCNAME, offset * 2, val, mem_mask);
|
||||
break;
|
||||
default:
|
||||
LOGTIMER("- %08x FUNCNAME %08x, %08x (%08x) - not implemented\n", pc, offset * 2, val, mem_mask);
|
||||
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]);
|
||||
return val;
|
||||
}
|
||||
|
||||
WRITE32_MEMBER( m68340_cpu_device::m68340_internal_timer_w )
|
||||
WRITE16_MEMBER( m68340_cpu_device::m68340_internal_timer_w )
|
||||
{
|
||||
int id = (offset * 2) < 0x40 ? 0 : 1; // Timer1 or Timer2
|
||||
|
||||
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>
|
||||
{{"MCR", "reserved", "IR", "CR", "SR", "CNTR", "PREL1", "PREL2", "COM"}}[offset % 0x20]);
|
||||
|
||||
assert(m68340TIMER);
|
||||
//m68340_timer &timer = *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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
case m68340_timer::REG_MCR:
|
||||
COMBINE_DATA(&timer.m_mcr[id]);
|
||||
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);
|
||||
break;
|
||||
case m68340_timer::REG_IR:
|
||||
COMBINE_DATA(&timer.m_ir[id]);
|
||||
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));
|
||||
break;
|
||||
case m68340_timer::REG_CR:
|
||||
COMBINE_DATA(&timer.m_cr[id]);
|
||||
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("- 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));
|
||||
LOGTIMER("- MODE: %s\n", std::array<char const *, 8>
|
||||
{{ "Input Capture/Output Compare",
|
||||
"Square-Wave Generator - not implemented",
|
||||
"Variable Duty-Cycle Square-Wave Generator - not implemented",
|
||||
"Variable-Width Single-Shot Pulse Generator - not implemented",
|
||||
"Pulse Width Measurement - not implemented",
|
||||
"Period Measurement - not implemented",
|
||||
"Event Count - not implemented",
|
||||
"Timer Bypass (Simple Test Method) - not implemented"
|
||||
}}[data & m68340_timer::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]);
|
||||
|
||||
/* 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 (timer.m_cr[id] & m68340_timer::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)
|
||||
{
|
||||
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));
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGTIMER("- Using TIN%d\n", id);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
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)
|
||||
{
|
||||
id == 0 ? m_tout1_out_cb(ASSERT_LINE) : m_tout2_out_cb(ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
id == 0 ? m_tout1_out_cb(CLEAR_LINE) : m_tout2_out_cb(CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case m68340_timer::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 &= ~m68340_timer::REG_SR_IRQ;
|
||||
// TODO: clear IRQ line
|
||||
}
|
||||
COMBINE_DATA(&timer.m_sr[id]);
|
||||
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));
|
||||
break;
|
||||
case m68340_timer::REG_CNTR:
|
||||
COMBINE_DATA(&timer.m_cntr_reg[id]);
|
||||
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]);
|
||||
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]);
|
||||
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]);
|
||||
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;
|
||||
default:
|
||||
LOGTIMER("- %08x FUNCNAME %08x, %08x (%08x) - not implemented\n", pc, offset * 2, data, mem_mask);
|
||||
logerror("%08x m68340_internal_sim_w %08x, %08x (%08x)\n", pc, offset * 2, data, mem_mask);
|
||||
break;
|
||||
}
|
||||
|
||||
int pc = space.device().safe_pc();
|
||||
logerror("%08x m68340_internal_timer_w %08x, %08x (%08x)\n", pc, offset*4,data,mem_mask);
|
||||
logerror("%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)
|
||||
{
|
||||
LOGTIMER("%s\n", FUNCNAME);
|
||||
|
||||
assert(m68340TIMER);
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
|
||||
timer.m_tin[0] = state;
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( m68340_cpu_device::tgate1_w)
|
||||
{
|
||||
LOGTIMER("%s\n", FUNCNAME);
|
||||
|
||||
assert(m68340TIMER);
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
|
||||
timer.m_tgate[0] = state;
|
||||
if (state == ASSERT_LINE)
|
||||
{
|
||||
if (timer.m_cr[0] & m68340_timer::REG_CR_TGE)
|
||||
{
|
||||
timer.m_sr[0] |= m68340_timer::REG_SR_TG;
|
||||
if (timer.m_cr[0] & m68340_timer::REG_CR_IE1)
|
||||
{
|
||||
LOGTIMER(" - TG interrupt");
|
||||
do_timer_irq(0);
|
||||
timer.m_sr[0] |= m68340_timer::REG_SR_IRQ;
|
||||
|
||||
}
|
||||
}
|
||||
timer.m_sr[0] |= m68340_timer::REG_SR_TGL;
|
||||
}
|
||||
else
|
||||
{
|
||||
timer.m_sr[0] &= ~m68340_timer::REG_SR_TGL;
|
||||
}
|
||||
}
|
||||
|
||||
WRITE_LINE_MEMBER( m68340_cpu_device::tin2_w)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
{
|
||||
LOGSETUP("%s\n", FUNCNAME);
|
||||
|
||||
assert(m68340TIMER);
|
||||
m68340_timer &timer = *m68340TIMER;
|
||||
|
||||
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();
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
void m68340_cpu_device::do_timer_irq(int id)
|
||||
{
|
||||
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;
|
||||
|
||||
if (timer_irq_level) // 0 is irq disabled
|
||||
{
|
||||
int use_autovector = (sim.m_avr_rsr >> (8 + timer_irq_level)) & 1;
|
||||
|
||||
LOGINT("TIMER IRQ triggered, Lvl: %d using Vector: %d (0 = auto vector)\n", timer_irq_level, use_autovector ? 0 : timer_irq_vector);
|
||||
|
||||
if (use_autovector)
|
||||
{
|
||||
//logerror("irq with autovector\n");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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 )
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (timer.m_timer_counter[id] & 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];
|
||||
}
|
||||
else // Falling flank
|
||||
{
|
||||
timer.m_cntr[id]--;
|
||||
|
||||
/* TC - Timer Compare Interrupt
|
||||
1 = This bit is set when the counter transitions (off a clock/event falling edge) to the
|
||||
value in the COM. This bit does not affect the programmed IRQ signal if the IE0
|
||||
bit in the CR is cleared.
|
||||
0 = This bit is cleared by the timer whenever the RESET signal is asserted on the
|
||||
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
|
||||
{
|
||||
timer.m_sr[id] |= (m68340_timer::REG_SR_TC | m68340_timer::REG_SR_COM);
|
||||
}
|
||||
}
|
||||
|
||||
LOGINT("%s reached\n", timer.m_cntr_reg[id] == 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)
|
||||
{
|
||||
case m68340_timer::REG_CR_OC_DISABLED:
|
||||
/* Disabled - TOUTx is disabled and three-stated TODO: support three-stated level */
|
||||
break;
|
||||
case m68340_timer::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.
|
||||
|
||||
In the input capture/output compare mode,
|
||||
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 ((timer.m_sr[id] & m68340_timer::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);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Any oher mode
|
||||
{
|
||||
if (timer.m_cntr_reg[id] == 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case m68340_timer::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.
|
||||
|
||||
In the input capture/output compare mode, TOUTx is
|
||||
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 ((timer.m_sr[id] & m68340_timer::REG_SR_COM) != 0) // timer reached compare value?
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
m_tout1_out_cb(ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tout2_out_cb(ASSERT_LINE);
|
||||
}
|
||||
}
|
||||
if (timer.m_cntr_reg[id] == 0) // timer reached timeout value?
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
m_tout1_out_cb(CLEAR_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tout2_out_cb(CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (timer.m_cntr_reg[id] == 0) // timer reached timeout value?
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
m_tout1_out_cb(CLEAR_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tout2_out_cb(CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case m68340_timer::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.
|
||||
|
||||
In the input capture/output compare mode, TOUTx is
|
||||
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 ((timer.m_sr[id] & m68340_timer::REG_SR_COM) != 0) // timer reached compare value?
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
m_tout1_out_cb(CLEAR_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tout2_out_cb(CLEAR_LINE);
|
||||
}
|
||||
}
|
||||
if (timer.m_cntr_reg[id] == 0) // timer reached timeout value?
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
m_tout1_out_cb(ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tout2_out_cb(ASSERT_LINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (timer.m_cntr_reg[id] == 0) // timer reached timeout value?
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
m_tout1_out_cb(ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tout2_out_cb(ASSERT_LINE);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOGTIMER("Wrong TOUT mode, fix the code!\n");
|
||||
}
|
||||
|
||||
if (timer.m_cntr_reg[id] == 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)
|
||||
{
|
||||
LOGTIMER(" - TO interrupt");
|
||||
do_timer_irq(id);
|
||||
timer.m_sr[id] |= m68340_timer::REG_SR_IRQ;
|
||||
}
|
||||
}
|
||||
if ((timer.m_sr[id] & m68340_timer::REG_SR_COM) != 0) // timer reached compare value? )
|
||||
{
|
||||
if (timer.m_cr[id] & m68340_timer::REG_CR_IE0)
|
||||
{
|
||||
LOGTIMER(" - TC interrupt");
|
||||
do_timer_irq(id);
|
||||
timer.m_sr[id] |= m68340_timer::REG_SR_IRQ;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,11 +5,90 @@
|
||||
|
||||
#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];
|
||||
|
||||
void reset();
|
||||
|
||||
enum {
|
||||
REG_MCR = 0x00,
|
||||
REG_IR = 0x04,
|
||||
REG_CR = 0x06,
|
||||
REG_SR = 0x08,
|
||||
REG_CNTR = 0x0a,
|
||||
REG_PREL1 = 0x0c,
|
||||
REG_PREL2 = 0x0e,
|
||||
REG_COM = 0x10,
|
||||
};
|
||||
|
||||
enum {
|
||||
REG_MCR_STP = 0x8000,
|
||||
REG_MCR_FRZ1 = 0x4000,
|
||||
REG_MCR_FRZ2 = 0x2000,
|
||||
REG_MCR_SUPV = 0x0800,
|
||||
REG_MCR_ARBLV = 0x000f,
|
||||
};
|
||||
|
||||
enum {
|
||||
REG_IR_INTLEV = 0x0700,
|
||||
REG_IR_INTVEC = 0x00ff,
|
||||
};
|
||||
|
||||
enum {
|
||||
REG_CR_SWR = 0x8000,
|
||||
REG_CR_INTMSK = 0x7000,
|
||||
REG_CR_IE0 = 0x4000,
|
||||
REG_CR_IE1 = 0x2000,
|
||||
REG_CR_IE2 = 0x1000,
|
||||
REG_CR_TGE = 0x0800,
|
||||
REG_CR_PCLK = 0x0400,
|
||||
REG_CR_CPE = 0x0200,
|
||||
REG_CR_CLK = 0x0100,
|
||||
REG_CR_POT_MASK = 0x00e0,
|
||||
REG_CR_MODE_MASK = 0x001c, // Mode mask
|
||||
REG_CR_MODE_ICOC = 0x0000, // Input Capture Output Compare
|
||||
REG_CR_MODE_SQWG = 0x0004, // Square Wave Generator
|
||||
REG_CR_MODE_VDCSW = 0x0008, // Variable Duty Cycle Square Wave generator
|
||||
REG_CR_MODE_VWSSPG = 0x000c, // Variable Width Single Shot Pulse Generator
|
||||
REG_CR_MODE_PWM = 0x0010, // Pulse Width Measurement
|
||||
REG_CR_MODE_PM = 0x0014, // Period Measurement
|
||||
REG_CR_MODE_EC = 0x0018, // Event Count
|
||||
REG_CR_MODE_TB = 0x001c, // Timer Bypass
|
||||
REG_CR_OC_MASK = 0x0003,
|
||||
REG_CR_OC_DISABLED = 0x0000,
|
||||
REG_CR_OC_TOGGLE = 0x0001,
|
||||
REG_CR_OC_ZERO = 0x0002,
|
||||
REG_CR_OC_ONE = 0x0003,
|
||||
};
|
||||
|
||||
enum {
|
||||
REG_SR_IRQ = 0x8000,
|
||||
REG_SR_TO = 0x4000,
|
||||
REG_SR_TG = 0x2000,
|
||||
REG_SR_TC = 0x1000,
|
||||
REG_SR_TGL = 0x0800,
|
||||
REG_SR_ON = 0x0400,
|
||||
REG_SR_OUT = 0x0200,
|
||||
REG_SR_COM = 0x0100,
|
||||
REG_SR_PSC_OUT = 0x00ff,
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif // MAME_MACHINE_68340TMU_H
|
||||
|
@ -111,18 +111,33 @@
|
||||
* SIM40 + 0x0040: 0x003FFFF5 CS0 mask 1 - block size = 4194304 (4MB)
|
||||
* SIM40 + 0x0044: 0x00000003 CS0 base 1 - base addr = 0x000000
|
||||
* SIM40 + 0x0048: 0x003FFFF5 CS1 mask 1 - block size = 4194304 (4MB)
|
||||
* SIM40 + 0x004C: 0x00800003 CS1 base 1 - base addr = 0x
|
||||
* SIM40 + 0x004C: 0x00800003 CS1 base 1 - base addr = 0x800000
|
||||
* SIM40 + 0x0050: 0x00007FFF CS2 mask 1 - block size = 65536 (64KB)
|
||||
* SIM40 + 0x0054: 0x00700003 CS2 base 1
|
||||
* SIM40 + 0x0058: 0x000007F2 CS3 mask 1 - block size = 2048 (2KB)
|
||||
* SIM40 + 0x005C: 0x00780003 CS3 base 1
|
||||
* SIM40 + 0x001F: 0x40 PBARB Port B Pin Assignment
|
||||
*
|
||||
- 0000007a void m68340_cpu_device::m68340_internal_sim_cs_w(address_space&, offs_t, osd::u32, osd::u32) 00000040, 003ffff5 (ffffffff) - not implemented
|
||||
- 00000082 void m68340_cpu_device::m68340_internal_sim_cs_w(address_space&, offs_t, osd::u32, osd::u32) 00000044, 00000003 (ffffffff) - not implemented
|
||||
- 0000008a void m68340_cpu_device::m68340_internal_sim_cs_w(address_space&, offs_t, osd::u32, osd::u32) 00000048, 003ffff5 (ffffffff) - not implemented
|
||||
- 00000092 void m68340_cpu_device::m68340_internal_sim_cs_w(address_space&, offs_t, osd::u32, osd::u32) 0000004c, 00800003 (ffffffff) - not implemented
|
||||
- 0000009a void m68340_cpu_device::m68340_internal_sim_cs_w(address_space&, offs_t, osd::u32, osd::u32) 00000050, 00007fff (ffffffff) - not implemented
|
||||
- 000000a2 void m68340_cpu_device::m68340_internal_sim_cs_w(address_space&, offs_t, osd::u32, osd::u32) 00000054, 00700003 (ffffffff) - not implemented
|
||||
- 000000aa void m68340_cpu_device::m68340_internal_sim_cs_w(address_space&, offs_t, osd::u32, osd::u32) 00000058, 000007f2 (ffffffff) - not implemented
|
||||
- 000000b2 void m68340_cpu_device::m68340_internal_sim_cs_w(address_space&, offs_t, osd::u32, osd::u32) 0000005c, 00780003 (ffffffff) - not implemented
|
||||
...
|
||||
- 008004d8 void m68340_cpu_device::m68340_internal_sim_cs_w(address_space&, offs_t, osd::u32, osd::u32) 00000044, 00000053 (ffffffff) - not implemented
|
||||
- 008004e2 void m68340_cpu_device::m68340_internal_sim_cs_w(address_space&, offs_t, osd::u32, osd::u32) 00000040, 003fff05 (ffffffff) - not implemented
|
||||
- 008004ee void m68340_cpu_device::m68340_internal_sim_cs_w(address_space&, offs_t, osd::u32, osd::u32) 00000040, 003ffff5 (ffffffff) - not implemented
|
||||
- 008004f8 void m68340_cpu_device::m68340_internal_sim_cs_w(address_space&, offs_t, osd::u32, osd::u32) 00000044, 0000005b (ffffffff) - not implemented
|
||||
|
||||
|
||||
* -------------------------------------------------------------
|
||||
* The bootstrap copies the firmware to RAM and jumps to it
|
||||
* -------------------------------------------------------------
|
||||
*
|
||||
* --- PC > 0x700000 so probably init of the RTXC tick timer setup?!
|
||||
* --- PC > 0x700000
|
||||
* SIM40 + 0x0022: 0x0140 PICR Periodic Interrupt Control Register
|
||||
* SIM40 + 0x0024: 0x0029 PICR Periodic Interrupt Timer Register
|
||||
*
|
||||
@ -274,6 +289,13 @@
|
||||
* SIM40 + 0x0640: 0x03 MCR Timer 2
|
||||
* tbc...
|
||||
*
|
||||
* // Tricks with the CS0 and the GAL:s
|
||||
* 008004d8 SIM40 + 0x0044: 0x00000053 CS0 base 1 - base addr = 0x000000, Supervisor Data Space, No CPU Space, Valid CS
|
||||
* 008004e2 SIM40 + 0x0040: 0x003FFF05 CS0 mask 1 - block size = 4194304 (4MB),
|
||||
* ... strange series of operations between 800834 and 8008D4, suspecting GAL:s to be involved in some magic here
|
||||
* 008004ee SIM40 + 0x0040: 0x003FFFF5 CS0 mask 1 - block size = 4194304 (4MB), Mask all accesses
|
||||
* 008004f8 SIM40 + 0x0044: 0x0000005b CS0 base 1 - base addr = 0x000000, Supervisor Data Space, Write Protect, No CPU Space, Valid CS
|
||||
*
|
||||
* LED Dot Matrix Display hookup
|
||||
* -------------------------------------
|
||||
* "DISPLAY CONN ALT" connected to the SDA5708
|
||||
@ -306,6 +328,31 @@
|
||||
* 14 Enable* Q1 74138 pin 14 IP12
|
||||
* 15 Clear* System reset
|
||||
*
|
||||
* Address map decoding
|
||||
* --------------------
|
||||
* IP06 GAL16V8 - DRAM
|
||||
* pin signal connected to
|
||||
* 1 Q V-FIFO-CLK inverted SCSI_CLK, origin to be found
|
||||
* 2 I1 SCSI_CLK
|
||||
* 3 I2 A0 68340 pin 113 IP01
|
||||
* 4 I3 CS1 68340 pin 2 IP01
|
||||
* 5 I4 A19 68340 pin 62 IP01
|
||||
* 6 I5 A21 68340 pin 64 IP01
|
||||
* 7 I6 BG 68340 pin 101 IP01
|
||||
* 8 I7 SIZ0 68340 pin 105 IP01
|
||||
* 9 I8 R/W 68340 pin 107 IP01
|
||||
* 11 I9/OE* GND 68340 pin 107 IP01 via an 100R resistor
|
||||
* 19 O0 FC2 68340 pin 71 IP01
|
||||
* 18 O1 I8 GAL168V pin 9 IP07 SCSI GAL
|
||||
* 17 O2 nc
|
||||
* 16 O3 RAS1 514260 pin 14 IP10-11 512KB DRAM each (IP11 is empty socket)
|
||||
* 15 O4 LCAS 514260 pin 29 IP09-11 512KB DRAM each (IP11 is empty socket)
|
||||
* 14 O5 UCAS 514260 pin 28 IP09-11 512KB DRAM each (IP11 is empty socket)
|
||||
* 13 O6 RAS0 514260 pin 14 IP09 512KB DRAM
|
||||
* 12 O7 I2 GAL16V8 pin 3 IP07 SCSI GAL (ANDed with !CS1) DMA_REQ
|
||||
* I1 GAL16V8 pin 2 IP08 LOGC GAL (ANDed with !CS1) DMA_REQ
|
||||
* G1 74257 pin 1 IP04-05 MUXes
|
||||
*
|
||||
* Identified low level drivers in firmware
|
||||
* ----------------------------------------
|
||||
* 800420..80046C : Some PORT A serialisation routine for the
|
||||
@ -316,9 +363,11 @@
|
||||
* Description Device Lvl IRQ
|
||||
* /Board Vector
|
||||
* ----------------------------------------------------------
|
||||
* On board Sources
|
||||
* IRQ7 CTRL20 IP19 circuit
|
||||
* IRQ6 SCSI/DEMUX INT
|
||||
* IRQ5 CAM module INT
|
||||
* IRQ3 Audio/Video INT
|
||||
*
|
||||
* Off board Sources (other boards)
|
||||
* ----------------------------------------------------------
|
||||
*
|
||||
* DMAC Channel Assignments
|
||||
@ -328,6 +377,7 @@
|
||||
* ----------------------------------------------------------
|
||||
*
|
||||
* TODO:
|
||||
* - Dump/understand the address decoder GAL:s IP06-IP08 (3 x 16V8)
|
||||
* - Setup a working address map
|
||||
* - Fix debug terminal
|
||||
* - TBC
|
||||
@ -388,6 +438,7 @@ class dbox_state : public driver_device
|
||||
void dbox_state::machine_reset()
|
||||
{
|
||||
LOG("%s\n", FUNCNAME);
|
||||
m_maincpu->tgate2_w(ASSERT_LINE); // Pulled high by resistor when not used as Rx from descrambler device
|
||||
}
|
||||
|
||||
// TODO: Hookup the reset latch correctly
|
||||
@ -421,17 +472,21 @@ static INPUT_PORTS_START( dbox )
|
||||
INPUT_PORTS_END
|
||||
|
||||
static MACHINE_CONFIG_START( dbox )
|
||||
MCFG_CPU_ADD("maincpu", M68340, XTAL_16MHz)
|
||||
MCFG_CPU_ADD("maincpu", M68340, 0) // The 68340 has an internal VCO as clock source, hence need no CPU clock
|
||||
MCFG_MC68340_ADD_CRYSTAL(XTAL_32_768kHz) // The dbox uses the VCO and has a crystal as VCO reference and to synthesize internal clocks from
|
||||
MCFG_CPU_PROGRAM_MAP(dbox_map)
|
||||
MCFG_MC68340_PA_OUTPUT_CB(WRITE8(dbox_state, write_pa))
|
||||
|
||||
/* Timer 2 is used to communicate with the descrambler module TODO: Write the descrambler module */
|
||||
//MCFG_MC68340_TOUT2_OUTPUT_CB(DEVWRITELINE("dcs", descrambler_device, txd_receiver))
|
||||
//MCFG_MC68340_TGATE2_INPUT_CB(DEVREADLINE("dsc", descrambler_device, rxd_receiver))
|
||||
|
||||
/* LED Matrix Display */
|
||||
MCFG_SDA5708_ADD("display")
|
||||
MCFG_DEFAULT_LAYOUT(layout_sda5708)
|
||||
/* IP16 74256 8 bit latch */
|
||||
MCFG_LATCH8_ADD("hct259.ip16")
|
||||
MCFG_LATCH8_WRITE_4(DEVWRITELINE("display", sda5708_device, reset_w))
|
||||
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
DRIVER_INIT_MEMBER(dbox_state, dbox)
|
||||
|
Loading…
Reference in New Issue
Block a user