// license:BSD-3-Clause // copyright-holders:David Haywood /* 68307 TIMER module */ // 2x timers #include "emu.h" #include "68307tmu.h" #define m68307TIMER_TMR (0x0) #define m68307TIMER_TRR (0x1) #define m68307TIMER_TCR (0x2) #define m68307TIMER_TCN (0x3) #define m68307TIMER_TER (0x4) #define m68307TIMER_WRR (0x5) #define m68307TIMER_WCR (0x6) #define m68307TIMER_XXX (0x7) READ16_MEMBER( m68307_cpu_device::m68307_internal_timer_r ) { assert(m_m68307TIMER); m68307_timer &timer = *m_m68307TIMER; int which = offset & 0x8; switch (offset&0x7) { case m68307TIMER_TCN: /* 0x3 (0x126 / 0x136) */ //if (m_ppc!=0x2182e) logerror("%08x m68307_internal_timer_r %08x (%04x) (TCN - Timer Counter for timer %d)\n", m_ppc, offset*2,mem_mask, which); return timer.read_tcn(mem_mask, which); default: logerror("%08x m68307_internal_timer_r %08x, (%04x)\n", m_ppc, offset*2,mem_mask); break; } return 0x0000; } WRITE16_MEMBER( m68307_cpu_device::m68307_internal_timer_w ) { assert(m_m68307TIMER); m68307_timer &timer = *m_m68307TIMER; int which = offset & 0x8; switch (offset&0x7) { case m68307TIMER_TMR: /* 0x0 (0x120 / 0x130) */ logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (TMR - Timer Mode Register for timer %d)\n", m_ppc, offset*2,data,mem_mask, which); timer.write_tmr(data, mem_mask, which); break; case m68307TIMER_TRR: /* 0x1 (0x122 / 0x132) */ logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (TRR - Timer Reference Register for timer %d)\n", m_ppc, offset*2,data,mem_mask, which); timer.write_trr(data, mem_mask, which); break; case m68307TIMER_TCR: /* 0x2 (0x124 / 0x134) */ logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (TCR - Timer Capture Register for timer %d) (illegal, read-only)\n", m_ppc, offset*2,data,mem_mask, which); break; case m68307TIMER_TCN: /* 0x3 (0x126 / 0x136) */ logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (TCN - Timer Counter for timer %d)\n", m_ppc, offset*2,data,mem_mask, which); break; case m68307TIMER_TER: /* 0x4 (0x128 / 0x138) */ /* 8-bit only!! */ //logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (TER - Timer Event Register for timer %d)\n", m_ppc, offset*2,data,mem_mask, which); timer.write_ter(data, mem_mask, which); break; case m68307TIMER_WRR: /* 0x5 (0x12a / 0x13a) */ if (which==0) { logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (WRR - Watchdog Reference Register)\n", m_ppc, offset*2,data,mem_mask); } else { logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (illegal)\n", m_ppc, offset*2,data,mem_mask); } break; case m68307TIMER_WCR: /* 0x6 (0x12c / 0x13c) */ if (which==0) { logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (WRR - Watchdog Counter Register)\n", m_ppc, offset*2,data,mem_mask); } else { logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (illegal)\n", m_ppc, offset*2,data,mem_mask); } break; case m68307TIMER_XXX: /* 0x7 (0x12e / 0x13e) */ logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (illegal)\n", m_ppc, offset*2,data,mem_mask); break; } } TIMER_CALLBACK_MEMBER(m68307_cpu_device::m68307_timer::timer0_callback ) { m68307_cpu_device* m68k = (m68307_cpu_device *)ptr; single_timer* tptr = &m68k->m_m68307TIMER->singletimer[0]; tptr->regs[m68307TIMER_TER] |= 0x2; if (BIT(tptr->regs[m68307TIMER_TMR], 4)) m68k->timer0_interrupt(1); tptr->mametimer->adjust(m68k->cycles_to_attotime(20000)); } TIMER_CALLBACK_MEMBER(m68307_cpu_device::m68307_timer::timer1_callback ) { m68307_cpu_device* m68k = (m68307_cpu_device *)ptr; single_timer* tptr = &m68k->m_m68307TIMER->singletimer[1]; tptr->regs[m68307TIMER_TER] |= 0x2; if (BIT(tptr->regs[m68307TIMER_TMR], 4)) m68k->timer1_interrupt(1); tptr->mametimer->adjust(m68k->cycles_to_attotime(20000)); } TIMER_CALLBACK_MEMBER(m68307_cpu_device::m68307_timer::wd_timer_callback ) { printf("wd timer\n"); } void m68307_cpu_device::m68307_timer::init(m68307_cpu_device *device) { parent = device; single_timer* tptr; tptr = &singletimer[0]; tptr->mametimer = device->machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(m68307_timer::timer0_callback),this), parent); tptr = &singletimer[1]; tptr->mametimer = device->machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(m68307_timer::timer1_callback),this), parent); wd_mametimer = device->machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(m68307_timer::wd_timer_callback),this), parent); } uint16_t m68307_cpu_device::m68307_timer::read_tcn(uint16_t mem_mask, int which) { // we should return the current timer value by // calculating what it should be based on the time // since it was last set return 0x3a98; } void m68307_cpu_device::m68307_timer::write_ter(uint16_t data, uint16_t mem_mask, int which) { assert(which >= 0 && which < ARRAY_LENGTH(singletimer)); single_timer* tptr = &singletimer[which]; if (data & 0x2) { tptr->regs[m68307TIMER_TER] &= ~0x2; if (which) parent->timer1_interrupt(0); else parent->timer0_interrupt(0); } } void m68307_cpu_device::m68307_timer::write_tmr(uint16_t data, uint16_t mem_mask, int which) { m68307_cpu_device* m68k = parent; assert(which >= 0 && which < ARRAY_LENGTH(singletimer)); single_timer* tptr = &singletimer[which]; COMBINE_DATA(&tptr->regs[m68307TIMER_TMR]); data = tptr->regs[m68307TIMER_TMR]; int ps = data & (0xff00)>>8; int ce = data & (0x00c0)>>6; int om = data & (0x0020)>>5; int ori = data & (0x0010)>>4; int frr = data & (0x0008)>>3; int iclk = data & (0x0006)>>1; int rst = data & (0x0001)>>0; m68k->logerror("tmr value %04x : Details :\n", data); m68k->logerror("prescale %d\n", ps); m68k->logerror("(clock divided by %d)\n", ps+1); m68k->logerror("capture edge / enable interrupt %d\n", ce); if (ce==0x0) m68k->logerror("(disable interrupt on capture event)\n"); if (ce==0x1) m68k->logerror("(capture on rising edge only + enable capture interrupt)\n"); if (ce==0x2) m68k->logerror("(capture on falling edge only + enable capture interrupt)\n"); if (ce==0x3) m68k->logerror("(capture on any edge + enable capture interrupt)\n"); m68k->logerror("output mode %d\n", om); if (om==0x0) m68k->logerror("(active-low pulse for one cycle))\n"); if (om==0x1) m68k->logerror("(toggle output)\n"); m68k->logerror("output reference interrupt %d\n", ori); if (ori==0x0) m68k->logerror("(disable reference interrupt)\n"); if (ori==0x1) m68k->logerror("(enable interrupt on reaching reference value))\n"); m68k->logerror("free running %d\n", frr); if (frr==0x0) m68k->logerror("(free running mode, counter continues after value reached)\n"); if (frr==0x1) m68k->logerror("(restart mode, counter resets after value reached)\n"); m68k->logerror("interrupt clock source %d\n", iclk); if (iclk==0x0) m68k->logerror("(stop count)\n"); if (iclk==0x1) m68k->logerror("(master system clock)\n"); if (iclk==0x2) m68k->logerror("(master system clock divided by 16)\n"); if (iclk==0x3) m68k->logerror("(TIN Pin)\n"); m68k->logerror("reset %d\n", rst); if (rst==0x0) m68k->logerror("(timer is reset)\n"); if (rst==0x1) m68k->logerror("(timer is running)\n"); tptr->mametimer->adjust(m68k->cycles_to_attotime(100000)); m68k->logerror("\n"); } void m68307_cpu_device::m68307_timer::write_trr(uint16_t data, uint16_t mem_mask, int which) { assert(which >= 0 && which < ARRAY_LENGTH(singletimer)); single_timer* tptr = &singletimer[which]; COMBINE_DATA(&tptr->regs[m68307TIMER_TRR]); } void m68307_cpu_device::m68307_timer::reset() { for (auto & elem : singletimer) { single_timer* tptr = &elem; tptr->regs[m68307TIMER_TMR] = 0x0000; tptr->regs[m68307TIMER_TRR] = 0xffff; tptr->regs[m68307TIMER_TCR] = 0x0000; tptr->regs[m68307TIMER_TCN] = 0x0000; tptr->regs[m68307TIMER_TER] = 0x0000; tptr->regs[m68307TIMER_WRR] = 0xffff; tptr->regs[m68307TIMER_WCR] = 0xffff; tptr->regs[m68307TIMER_XXX] = 0; tptr->enabled = false; tptr->mametimer->adjust(attotime::never); } wd_mametimer->adjust(attotime::never); } bool m68307_cpu_device::m68307_timer::timer_int_pending(int which) const { assert(which >= 0 && which < ARRAY_LENGTH(singletimer)); const single_timer* tptr = &singletimer[which]; return BIT(tptr->regs[m68307TIMER_TER], 1) && BIT(tptr->regs[m68307TIMER_TMR], 4); }