1 // license:BSD-3-Clause
2 // copyright-holders:David Haywood
3 /* 68307 TIMER module */
4 // 2x timers
5 
6 #include "emu.h"
7 #include "68307tmu.h"
8 
9 #define m68307TIMER_TMR (0x0)
10 #define m68307TIMER_TRR (0x1)
11 #define m68307TIMER_TCR (0x2)
12 #define m68307TIMER_TCN (0x3)
13 #define m68307TIMER_TER (0x4)
14 #define m68307TIMER_WRR (0x5)
15 #define m68307TIMER_WCR (0x6)
16 #define m68307TIMER_XXX (0x7)
17 
m68307_internal_timer_r(offs_t offset,uint16_t mem_mask)18 uint16_t m68307_cpu_device::m68307_internal_timer_r(offs_t offset, uint16_t mem_mask)
19 {
20 	assert(m_m68307TIMER);
21 	m68307_timer &timer = *m_m68307TIMER;
22 
23 	int which = offset & 0x8;
24 
25 	switch (offset&0x7)
26 	{
27 		case m68307TIMER_TCN: /* 0x3 (0x126 / 0x136) */
28 			//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);
29 			return timer.read_tcn(mem_mask, which);
30 
31 		default:
32 			logerror("%08x m68307_internal_timer_r %08x, (%04x)\n", m_ppc, offset*2,mem_mask);
33 			break;
34 	}
35 
36 	return 0x0000;
37 }
38 
m68307_internal_timer_w(offs_t offset,uint16_t data,uint16_t mem_mask)39 void m68307_cpu_device::m68307_internal_timer_w(offs_t offset, uint16_t data, uint16_t mem_mask)
40 {
41 	assert(m_m68307TIMER);
42 	m68307_timer &timer = *m_m68307TIMER;
43 
44 	int which = offset & 0x8;
45 
46 	switch (offset&0x7)
47 	{
48 		case m68307TIMER_TMR: /* 0x0 (0x120 / 0x130) */
49 			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);
50 			timer.write_tmr(data, mem_mask, which);
51 			break;
52 
53 		case m68307TIMER_TRR: /* 0x1 (0x122 / 0x132) */
54 			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);
55 			timer.write_trr(data, mem_mask, which);
56 			break;
57 
58 		case m68307TIMER_TCR: /* 0x2 (0x124 / 0x134) */
59 			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);
60 			break;
61 
62 		case m68307TIMER_TCN: /* 0x3 (0x126 / 0x136) */
63 			logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (TCN - Timer Counter for timer %d)\n", m_ppc, offset*2,data,mem_mask, which);
64 			break;
65 
66 		case m68307TIMER_TER: /* 0x4 (0x128 / 0x138) */
67 			/* 8-bit only!! */
68 			//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);
69 			timer.write_ter(data, mem_mask, which);
70 			break;
71 
72 		case m68307TIMER_WRR: /* 0x5 (0x12a / 0x13a) */
73 			if (which==0)
74 			{
75 				logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (WRR - Watchdog Reference Register)\n", m_ppc, offset*2,data,mem_mask);
76 			}
77 			else
78 			{
79 				logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (illegal)\n", m_ppc, offset*2,data,mem_mask);
80 			}
81 			break;
82 
83 		case m68307TIMER_WCR: /* 0x6 (0x12c / 0x13c) */
84 			if (which==0)
85 			{
86 				logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (WRR - Watchdog Counter Register)\n", m_ppc, offset*2,data,mem_mask);
87 			}
88 			else
89 			{
90 				logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (illegal)\n", m_ppc, offset*2,data,mem_mask);
91 			}
92 			break;
93 
94 		case m68307TIMER_XXX: /* 0x7 (0x12e / 0x13e) */
95 			logerror("%08x m68307_internal_timer_w %08x, %04x (%04x) (illegal)\n", m_ppc, offset*2,data,mem_mask);
96 			break;
97 	}
98 }
99 
TIMER_CALLBACK_MEMBER(m68307_cpu_device::m68307_timer::timer0_callback)100 TIMER_CALLBACK_MEMBER(m68307_cpu_device::m68307_timer::timer0_callback )
101 {
102 	m68307_cpu_device* m68k = (m68307_cpu_device *)ptr;
103 	single_timer* tptr = &m68k->m_m68307TIMER->singletimer[0];
104 	tptr->regs[m68307TIMER_TER] |= 0x2;
105 
106 	if (BIT(tptr->regs[m68307TIMER_TMR], 4))
107 		m68k->timer0_interrupt(1);
108 
109 	tptr->mametimer->adjust(m68k->cycles_to_attotime(20000));
110 }
111 
TIMER_CALLBACK_MEMBER(m68307_cpu_device::m68307_timer::timer1_callback)112 TIMER_CALLBACK_MEMBER(m68307_cpu_device::m68307_timer::timer1_callback )
113 {
114 	m68307_cpu_device* m68k = (m68307_cpu_device *)ptr;
115 	single_timer* tptr = &m68k->m_m68307TIMER->singletimer[1];
116 	tptr->regs[m68307TIMER_TER] |= 0x2;
117 
118 	if (BIT(tptr->regs[m68307TIMER_TMR], 4))
119 		m68k->timer1_interrupt(1);
120 
121 	tptr->mametimer->adjust(m68k->cycles_to_attotime(20000));
122 
123 }
124 
TIMER_CALLBACK_MEMBER(m68307_cpu_device::m68307_timer::wd_timer_callback)125 TIMER_CALLBACK_MEMBER(m68307_cpu_device::m68307_timer::wd_timer_callback )
126 {
127 	printf("wd timer\n");
128 }
129 
init(m68307_cpu_device * device)130 void m68307_cpu_device::m68307_timer::init(m68307_cpu_device *device)
131 {
132 	parent = device;
133 
134 	single_timer* tptr;
135 
136 	tptr = &singletimer[0];
137 	tptr->mametimer = device->machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(m68307_timer::timer0_callback),this), parent);
138 
139 	tptr = &singletimer[1];
140 	tptr->mametimer = device->machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(m68307_timer::timer1_callback),this), parent);
141 
142 	wd_mametimer = device->machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(m68307_timer::wd_timer_callback),this), parent);
143 }
144 
read_tcn(uint16_t mem_mask,int which)145 uint16_t m68307_cpu_device::m68307_timer::read_tcn(uint16_t mem_mask, int which)
146 {
147 	// we should return the current timer value by
148 	// calculating what it should be based on the time
149 	// since it was last set
150 	return 0x3a98;
151 }
152 
write_ter(uint16_t data,uint16_t mem_mask,int which)153 void m68307_cpu_device::m68307_timer::write_ter(uint16_t data, uint16_t mem_mask, int which)
154 {
155 	assert(which >= 0 && which < ARRAY_LENGTH(singletimer));
156 	single_timer* tptr = &singletimer[which];
157 	if (data & 0x2)
158 	{
159 		tptr->regs[m68307TIMER_TER] &= ~0x2;
160 		if (which)
161 			parent->timer1_interrupt(0);
162 		else
163 			parent->timer0_interrupt(0);
164 	}
165 }
166 
write_tmr(uint16_t data,uint16_t mem_mask,int which)167 void m68307_cpu_device::m68307_timer::write_tmr(uint16_t data, uint16_t mem_mask, int which)
168 {
169 	m68307_cpu_device* m68k = parent;
170 	assert(which >= 0 && which < ARRAY_LENGTH(singletimer));
171 	single_timer* tptr = &singletimer[which];
172 
173 	COMBINE_DATA(&tptr->regs[m68307TIMER_TMR]);
174 
175 	data = tptr->regs[m68307TIMER_TMR];
176 
177 	int ps   = data & (0xff00)>>8;
178 	int ce   = data & (0x00c0)>>6;
179 	int om   = data & (0x0020)>>5;
180 	int ori  = data & (0x0010)>>4;
181 	int frr  = data & (0x0008)>>3;
182 	int iclk = data & (0x0006)>>1;
183 	int rst  = data & (0x0001)>>0;
184 
185 
186 	m68k->logerror("tmr value %04x : Details :\n", data);
187 	m68k->logerror("prescale %d\n", ps);
188 	m68k->logerror("(clock divided by %d)\n", ps+1);
189 	m68k->logerror("capture edge / enable interrupt %d\n", ce);
190 	if (ce==0x0) m68k->logerror("(disable interrupt on capture event)\n");
191 	if (ce==0x1) m68k->logerror("(capture on rising edge only + enable capture interrupt)\n");
192 	if (ce==0x2) m68k->logerror("(capture on falling edge only + enable capture interrupt)\n");
193 	if (ce==0x3) m68k->logerror("(capture on any edge + enable capture interrupt)\n");
194 	m68k->logerror("output mode %d\n", om);
195 	if (om==0x0) m68k->logerror("(active-low pulse for one cycle))\n");
196 	if (om==0x1) m68k->logerror("(toggle output)\n");
197 	m68k->logerror("output reference interrupt %d\n", ori);
198 	if (ori==0x0) m68k->logerror("(disable reference interrupt)\n");
199 	if (ori==0x1) m68k->logerror("(enable interrupt on reaching reference value))\n");
200 	m68k->logerror("free running %d\n", frr);
201 	if (frr==0x0) m68k->logerror("(free running mode, counter continues after value reached)\n");
202 	if (frr==0x1) m68k->logerror("(restart mode, counter resets after value reached)\n");
203 	m68k->logerror("interrupt clock source %d\n", iclk);
204 	if (iclk==0x0) m68k->logerror("(stop count)\n");
205 	if (iclk==0x1) m68k->logerror("(master system clock)\n");
206 	if (iclk==0x2) m68k->logerror("(master system clock divided by 16)\n");
207 	if (iclk==0x3) m68k->logerror("(TIN Pin)\n");
208 	m68k->logerror("reset %d\n", rst);
209 	if (rst==0x0) m68k->logerror("(timer is reset)\n");
210 	if (rst==0x1) m68k->logerror("(timer is running)\n");
211 
212 	tptr->mametimer->adjust(m68k->cycles_to_attotime(100000));
213 
214 	m68k->logerror("\n");
215 }
216 
write_trr(uint16_t data,uint16_t mem_mask,int which)217 void m68307_cpu_device::m68307_timer::write_trr(uint16_t data, uint16_t mem_mask, int which)
218 {
219 	assert(which >= 0 && which < ARRAY_LENGTH(singletimer));
220 	single_timer* tptr = &singletimer[which];
221 
222 	COMBINE_DATA(&tptr->regs[m68307TIMER_TRR]);
223 }
224 
225 
226 
reset()227 void m68307_cpu_device::m68307_timer::reset()
228 {
229 	for (auto & elem : singletimer)
230 	{
231 		single_timer* tptr = &elem;
232 
233 		tptr->regs[m68307TIMER_TMR] = 0x0000;
234 		tptr->regs[m68307TIMER_TRR] = 0xffff;
235 		tptr->regs[m68307TIMER_TCR] = 0x0000;
236 		tptr->regs[m68307TIMER_TCN] = 0x0000;
237 		tptr->regs[m68307TIMER_TER] = 0x0000;
238 		tptr->regs[m68307TIMER_WRR] = 0xffff;
239 		tptr->regs[m68307TIMER_WCR] = 0xffff;
240 		tptr->regs[m68307TIMER_XXX] = 0;
241 		tptr->enabled = false;
242 		tptr->mametimer->adjust(attotime::never);
243 	}
244 
245 	wd_mametimer->adjust(attotime::never);
246 }
247 
248 
timer_int_pending(int which) const249 bool m68307_cpu_device::m68307_timer::timer_int_pending(int which) const
250 {
251 	assert(which >= 0 && which < ARRAY_LENGTH(singletimer));
252 	const single_timer* tptr = &singletimer[which];
253 
254 	return BIT(tptr->regs[m68307TIMER_TER], 1) && BIT(tptr->regs[m68307TIMER_TMR], 4);
255 }
256