Previous 199869 Revisions Next

r22067 Monday 25th March, 2013 at 02:33:41 UTC by R. Belmont
Add support for Mitsubishi M50740/50741 MCUs. [R. Belmont]
[src/emu/cpu]cpu.mak
[src/emu/cpu/m6502]m5074x.c* m5074x.h*

trunk/src/emu/cpu/cpu.mak
r22066r22067
10361036         $(CPUOBJ)/m6502/r65c02.o \
10371037         $(CPUOBJ)/m6502/m740.o \
10381038         $(CPUOBJ)/m6502/m3745x.o \
1039         $(CPUOBJ)/m6502/m5074x.o \
10391040
10401041DASMOBJS +=
10411042endif
r22066r22067
11201121$(CPUOBJ)/m6502/m3745x.o:   $(CPUSRC)/m6502/m3745x.c \
11211122                     $(CPUSRC)/m6502/m3745x.h
11221123
1124$(CPUOBJ)/m6502/m5074x.o:   $(CPUSRC)/m6502/m5074x.c \
1125                     $(CPUSRC)/m6502/m5074x.h
1126
11231127# rule to generate the C files
11241128$(CPUOBJ)/m6502/deco16.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/odeco16.lst $(CPUSRC)/m6502/ddeco16.lst
11251129   @echo Generating DECO16 source file...
trunk/src/emu/cpu/m6502/m5074x.c
r0r22067
1/*
2    Mitsubishi M5074x 8-bit microcontroller family
3*/
4
5#include "emu.h"
6#include "m5074x.h"
7
8//**************************************************************************
9//  MACROS / CONSTANTS
10//**************************************************************************
11
12#define IRQ_CNTRREQ   (0x80)
13#define IRQ_CNTRENA   (0x40)
14#define IRQ_TMR1REQ   (0x20)
15#define IRQ_TMR1ENA   (0x10)
16#define IRQ_TMR2REQ   (0x08)
17#define IRQ_TMR2ENA   (0x04)
18#define IRQ_INTREQ   (0x02)
19#define IRQ_INTENA   (0x01)
20
21#define TMRC_TMRXREQ (0x80)
22#define TMRC_TMRXENA (0x40)
23#define TMRC_TMRXHLT (0x20)
24#define TMRC_TMRXMDE (0x0c)
25
26//**************************************************************************
27//  DEVICE DEFINITIONS
28//**************************************************************************
29
30const device_type M50740 = &device_creator<m50740_device>;
31const device_type M50741 = &device_creator<m50741_device>;
32
33//**************************************************************************
34//  LIVE DEVICE
35//**************************************************************************
36
37//-------------------------------------------------
38//  m5074x_device - constructor
39//-------------------------------------------------
40m5074x_device::m5074x_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, address_map_constructor internal_map) :
41   m740_device(mconfig, type, name, tag, owner, clock),
42   m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0, internal_map),
43   read_p0(*this),
44   read_p1(*this),
45   read_p2(*this),
46   read_p3(*this),
47   write_p0(*this),
48   write_p1(*this),
49   write_p2(*this),
50   write_p3(*this)
51{
52}
53
54void m5074x_device::device_config_complete()
55{
56   m_shortname = "m5074x";
57}
58
59//-------------------------------------------------
60//  device_start - device-specific startup
61//-------------------------------------------------
62
63void m5074x_device::device_start()
64{
65   read_p0.resolve_safe(0);
66   read_p1.resolve_safe(0);
67   read_p2.resolve_safe(0);
68   read_p3.resolve_safe(0);
69   write_p0.resolve_safe();
70   write_p1.resolve_safe();
71   write_p2.resolve_safe();
72    write_p3.resolve_safe();
73
74   for (int i = 0; i < NUM_TIMERS; i++)
75   {
76      m_timers[i] = timer_alloc(i, NULL);
77   }
78
79   m740_device::device_start();
80
81   save_item(NAME(m_ports));
82   save_item(NAME(m_ddrs));
83   save_item(NAME(m_intctrl));
84   save_item(NAME(m_tmrctrl));
85   save_item(NAME(m_tmr12pre));
86   save_item(NAME(m_tmr1));
87   save_item(NAME(m_tmr2));
88   save_item(NAME(m_tmrxpre));
89   save_item(NAME(m_tmrx));
90   save_item(NAME(m_tmr1latch));
91   save_item(NAME(m_tmr2latch));
92   save_item(NAME(m_tmrxlatch));
93   save_item(NAME(m_last_all_ints));
94
95   memset(m_ports, 0, sizeof(m_ports));
96   memset(m_ddrs, 0, sizeof(m_ddrs));
97   m_intctrl = m_tmrctrl = 0;
98   m_tmr12pre = m_tmrxpre = 0;
99   m_tmr1 = m_tmr2 = m_tmrx = 0;
100   m_last_all_ints = 0;
101}
102
103
104//-------------------------------------------------
105//  device_reset - device-specific reset
106//-------------------------------------------------
107
108void m5074x_device::device_reset()
109{
110   m740_device::device_reset();
111
112   // all ports reset to input on startup
113   memset(m_ports, 0, sizeof(m_ports));
114   memset(m_ddrs, 0, sizeof(m_ddrs));
115   m_intctrl = m_tmrctrl = 0;
116   m_tmr12pre = m_tmrxpre = 0;
117   m_tmr1 = m_tmr2 = m_tmrx = 0;
118}
119
120void m5074x_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
121{
122   switch (id)
123   {
124      case TIMER_1:
125         m_tmr1--;
126
127         if (m_tmr1 <= 0)
128         {
129            m_intctrl |= IRQ_TMR1REQ;
130            m_tmr1 = m_tmr1latch;
131            recalc_irqs();
132         }
133         break;
134
135      case TIMER_2:
136         m_tmr2--;
137
138         if (m_tmr2 <= 0)
139         {
140            m_intctrl |= IRQ_TMR2REQ;
141            m_tmr2 = m_tmr2latch;
142            recalc_irqs();
143         }
144         break;
145
146      case TIMER_X:
147         m_tmrx--;
148
149         if (m_tmrx <= 0)
150         {
151            m_tmrctrl |= TMRC_TMRXREQ;
152            m_tmrx = m_tmrxlatch;
153            recalc_irqs();
154         }
155         break;
156   }
157}
158
159void m5074x_device::execute_set_input(int inputnum, int state)
160{
161   switch (inputnum)
162   {
163      case M5074X_INT1_LINE:
164         if (state == ASSERT_LINE)
165         {
166            m_intctrl |= IRQ_INTREQ;
167         }
168         else
169         {
170            m_intctrl &= ~IRQ_INTREQ;
171         }
172         break;
173
174      case M5074X_SET_OVERFLOW:   // the base 740 class can handle this
175         m740_device::execute_set_input(M740_SET_OVERFLOW, state);
176         break;
177   }
178
179   recalc_irqs();
180}
181
182void m5074x_device::recalc_irqs()
183{
184   UINT8 all_ints = 0;
185
186   if ((m_intctrl & (IRQ_CNTRREQ|IRQ_CNTRENA)) == (IRQ_CNTRREQ|IRQ_CNTRENA))
187   {
188      all_ints |= 0x01;
189   }
190   if ((m_tmrctrl & (TMRC_TMRXREQ|TMRC_TMRXENA)) == (TMRC_TMRXREQ|TMRC_TMRXENA))
191   {
192      all_ints |= 0x02;
193   }
194   if ((m_intctrl & (IRQ_TMR1REQ|IRQ_TMR1ENA)) == (IRQ_TMR1REQ|IRQ_TMR1ENA))
195   {
196      all_ints |= 0x04;
197   }
198   if ((m_intctrl & (IRQ_TMR2REQ|IRQ_TMR2ENA)) == (IRQ_TMR2REQ|IRQ_TMR2ENA))
199   {
200      all_ints |= 0x08;
201   }
202   if ((m_intctrl & (IRQ_INTREQ|IRQ_INTENA)) == (IRQ_INTREQ|IRQ_INTENA))
203   {
204      all_ints |= 0x10;
205   }
206
207   // check all 6 IRQ bits for changes
208   for (int i = 0; i < 6; i++)
209   {
210      // if bit is set now
211      if (all_ints & (1 << i))
212      {
213         // and wasn't last time
214         if (!(m_last_all_ints & (1 << i)))
215         {
216            m740_device::execute_set_input(M740_INT0_LINE + i, ASSERT_LINE);
217         }
218      }
219      else    // bit is clear now
220      {
221         // ...and wasn't clear last time
222         if (m_last_all_ints & (1 << i))
223         {
224            m740_device::execute_set_input(M740_INT0_LINE + i, CLEAR_LINE);
225         }
226      }
227   }
228
229   m_last_all_ints = all_ints;
230}
231
232void m5074x_device::recalc_timer(int timer)
233{
234   int hz;
235
236   switch (timer)
237   {
238      case 0:
239         hz = clock() / 16;
240         hz /= (m_tmr12pre + 2);
241         m_timers[TIMER_1]->adjust(attotime::from_hz(hz), 0, attotime::from_hz(hz));
242         break;
243
244      case 1:
245         hz = clock() / 16;
246         hz /= (m_tmr12pre + 2);
247         m_timers[TIMER_2]->adjust(attotime::from_hz(hz), 0, attotime::from_hz(hz));
248         break;
249
250      case 2:
251         // Timer X modes: 00 = free run countdown, 01 = invert CNTR pin each time expires,
252         // 10 = count each time CNTR pin inverts, 11 = count when CNTR pin low
253         if ((m_tmrctrl & TMRC_TMRXMDE) == 0)
254         {
255            // stop bit?
256            if (m_tmrctrl & TMRC_TMRXHLT)
257            {
258               m_timers[TIMER_X]->adjust(attotime::never, 0, attotime::never);
259            }
260            else
261            {
262               hz = clock() / 16;
263               hz /= (m_tmrxpre + 2);
264               m_timers[TIMER_X]->adjust(attotime::from_hz(hz), 0, attotime::from_hz(hz));
265            }
266         }
267         else
268         {
269            fatalerror("M5074x: Unhandled timer X mode %d\n", (m_tmrctrl&TMRC_TMRXMDE)>>2);
270         }
271         break;
272   }
273}
274
275void m5074x_device::send_port(address_space &space, UINT8 offset, UINT8 data)
276{
277   switch (offset)
278   {
279      case 0:
280         write_p0(data);
281         break;
282
283      case 1:
284         write_p1(data);
285         break;
286
287      case 2:
288         write_p2(data);
289         break;
290
291      case 3:
292         write_p3(data);
293         break;
294   }
295}
296
297UINT8 m5074x_device::read_port(UINT8 offset)
298{
299   UINT8 incoming = 0;
300
301   switch (offset)
302   {
303      case 0:
304         incoming = read_p0();
305         break;
306
307      case 1:
308         incoming = read_p1();
309         break;
310
311      case 2:
312         incoming = read_p2();
313         break;
314
315      case 3:
316         incoming = read_p3();
317         break;
318   }
319
320   // apply data direction registers
321   incoming &= (m_ddrs[offset] ^ 0xff);
322   // OR in ddr-masked version of port writes
323   incoming |= (m_ports[offset] & m_ddrs[offset]);
324
325   return incoming;
326}
327
328READ8_MEMBER(m5074x_device::ports_r)
329{
330   switch (offset)
331   {
332      case 0:
333        return read_port(0);
334
335      case 1:
336        return m_ddrs[0];
337
338      case 2:
339        return read_port(1);
340
341      case 3:
342        return m_ddrs[1];
343
344      case 4:
345        return read_port(2);
346
347      case 5:
348        return m_ddrs[2];
349
350      case 8:
351        return read_port(3);
352
353      case 9:
354        return m_ddrs[3];
355   }
356
357   return 0xff;
358}
359
360WRITE8_MEMBER(m5074x_device::ports_w)
361{
362   switch (offset)
363   {
364      case 0:   // p0
365        send_port(space, 0, data & m_ddrs[0]);
366        m_ports[0] = data;
367        break;
368
369      case 1: // p0 ddr
370        send_port(space, 0, m_ports[0] & data);
371        m_ddrs[0] = data;
372        break;
373
374      case 2:   // p1
375        send_port(space, 1, data & m_ddrs[1]);
376        m_ports[1] = data;
377        break;
378
379      case 3: // p1 ddr
380        send_port(space, 1, m_ports[1] & data);
381        m_ddrs[1] = data;
382        break;
383
384      case 4:   // p2
385        send_port(space, 2, data & m_ddrs[2]);
386        m_ports[2] = data;
387        break;
388
389      case 5: // p2 ddr
390        send_port(space, 2, m_ports[2] & data);
391        m_ddrs[2] = data;
392        break;
393
394      case 8:   // p3
395        send_port(space, 3, data & m_ddrs[3]);
396        m_ports[3] = data;
397        break;
398
399      case 9: // p3 ddr
400        send_port(space, 3, m_ports[3] & data);
401        m_ddrs[3] = data;
402        break;
403   }
404}
405
406READ8_MEMBER(m5074x_device::tmrirq_r)
407{
408   switch (offset)
409   {
410      case 0:
411         return m_tmr12pre;
412
413      case 1:
414         return m_tmr1;
415
416      case 2:
417         return m_tmr2;
418
419      case 3:
420         return m_tmrxpre;
421
422      case 4:
423         return m_tmrx;
424
425      case 5:
426         return m_intctrl;
427
428      case 6:
429         return m_tmrctrl;
430   }
431
432   return 0xff;
433}
434
435WRITE8_MEMBER(m5074x_device::tmrirq_w)
436{
437//   printf("%02x to tmrirq @ %d\n", data, offset);
438
439   switch (offset)
440   {
441      case 0:
442         m_tmr12pre = data;
443         recalc_timer(0);
444         recalc_timer(1);
445         break;
446
447      case 1:
448         m_tmr1 = m_tmr1latch = data;
449         break;
450
451      case 2:
452         m_tmr2 = m_tmr2latch = data;
453         break;
454
455      case 3:
456         m_tmrxpre = m_tmrxlatch = data;
457         recalc_timer(2);
458         break;
459
460      case 4:
461         m_tmrx = data;
462         break;
463
464      case 5:
465         m_intctrl = data;
466         recalc_irqs();
467         break;
468
469      case 6:
470         m_tmrctrl = data;
471         recalc_irqs();
472         break;
473   }
474}
475
476/* M50740 - baseline for this familiy */
477static ADDRESS_MAP_START( m50740_map, AS_PROGRAM, 8, m50740_device )
478   ADDRESS_MAP_GLOBAL_MASK(0x1fff)
479   AM_RANGE(0x0000, 0x005f) AM_RAM
480   AM_RANGE(0x00e0, 0x00e9) AM_READWRITE(ports_r, ports_w)
481   AM_RANGE(0x00f9, 0x00ff) AM_READWRITE(tmrirq_r, tmrirq_w)
482   AM_RANGE(0x1400, 0x1fff) AM_ROM AM_REGION(":m50740", 0)
483ADDRESS_MAP_END
484
485m50740_device::m50740_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
486   m5074x_device(mconfig, M50740, "Mitsubishi M50740", tag, owner, clock, ADDRESS_MAP_NAME(m50740_map))
487{
488}
489
490m50740_device::m50740_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
491   m5074x_device(mconfig, type, name, tag, owner, clock, ADDRESS_MAP_NAME(m50740_map))
492{
493}
494
495/* M50741 - 50740 with a larger internal ROM */
496static ADDRESS_MAP_START( m50741_map, AS_PROGRAM, 8, m50741_device )
497   ADDRESS_MAP_GLOBAL_MASK(0x1fff)
498   AM_RANGE(0x0000, 0x005f) AM_RAM
499   AM_RANGE(0x00e0, 0x00e9) AM_READWRITE(ports_r, ports_w)
500   AM_RANGE(0x00f9, 0x00ff) AM_READWRITE(tmrirq_r, tmrirq_w)
501   AM_RANGE(0x1000, 0x1fff) AM_ROM AM_REGION(":m50741", 0)
502ADDRESS_MAP_END
503
504m50741_device::m50741_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
505   m5074x_device(mconfig, M50740, "Mitsubishi M50741", tag, owner, clock, ADDRESS_MAP_NAME(m50741_map))
506{
507}
508
509m50741_device::m50741_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
510   m5074x_device(mconfig, type, name, tag, owner, clock, ADDRESS_MAP_NAME(m50741_map))
511{
512}
513
Property changes on: trunk/src/emu/cpu/m6502/m5074x.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/cpu/m6502/m5074x.h
r0r22067
1#pragma once
2
3#ifndef __M5074X_H__
4#define __M5074X_H__
5
6#include "m740.h"
7
8//**************************************************************************
9//  INTERFACE CONFIGURATION MACROS
10//**************************************************************************
11
12#define MCFG_M5074X_PORT0_CALLBACKS(_read, _write) \
13   downcast<m5074x_device *>(device)->set_p0_callbacks(DEVCB2_##_read, DEVCB2_##_write);
14
15#define MCFG_M5074X_PORT1_CALLBACKS(_read, _write) \
16   downcast<m5074x_device *>(device)->set_p1_callbacks(DEVCB2_##_read, DEVCB2_##_write);
17
18#define MCFG_M5074X_PORT2_CALLBACKS(_read, _write) \
19   downcast<m5074x_device *>(device)->set_p2_callbacks(DEVCB2_##_read, DEVCB2_##_write);
20
21#define MCFG_M5074X_PORT3_CALLBACKS(_read, _write) \
22   downcast<m5074x_device *>(device)->set_p3_callbacks(DEVCB2_##_read, DEVCB2_##_write);
23
24//**************************************************************************
25//  TYPE DEFINITIONS
26//**************************************************************************
27
28// ======================> m5074x_device
29
30class m5074x_device :  public m740_device
31{
32   friend class m50740_device;
33   friend class m50741_device;
34
35   enum
36   {
37      M5074X_INT1_LINE = INPUT_LINE_IRQ0,
38
39      M5074X_SET_OVERFLOW = M740_SET_OVERFLOW
40   };
41
42   enum
43   {
44      TIMER_1 = 0,
45      TIMER_2,
46      TIMER_X,
47
48      NUM_TIMERS
49   };
50
51public:
52   // construction/destruction
53   m5074x_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, address_map_constructor internal_map);
54
55   const address_space_config m_program_config;
56
57   template<class _read, class _write> void set_p0_callbacks(_read rd, _write wr)
58   {
59      read_p0.set_callback(rd);
60      write_p0.set_callback(wr);
61   }
62
63   template<class _read, class _write> void set_p1_callbacks(_read rd, _write wr)
64   {
65      read_p1.set_callback(rd);
66      write_p1.set_callback(wr);
67   }
68
69   template<class _read, class _write> void set_p2_callbacks(_read rd, _write wr)
70   {
71      read_p2.set_callback(rd);
72      write_p2.set_callback(wr);
73   }
74
75   template<class _read, class _write> void set_p3_callbacks(_read rd, _write wr)
76   {
77      read_p3.set_callback(rd);
78      write_p3.set_callback(wr);
79   }
80
81   devcb2_read8  read_p0, read_p1, read_p2, read_p3;
82   devcb2_write8 write_p0, write_p1, write_p2, write_p3;
83
84    DECLARE_READ8_MEMBER(ports_r);
85    DECLARE_WRITE8_MEMBER(ports_w);
86    DECLARE_READ8_MEMBER(tmrirq_r);
87    DECLARE_WRITE8_MEMBER(tmrirq_w);
88
89   bool are_port_bits_output(UINT8 port, UINT8 mask) { return ((m_ddrs[port] & mask) == mask) ? true : false; }
90
91protected:
92   // device-level overrides
93   virtual void device_start();
94   virtual void device_reset();
95   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
96   virtual void device_config_complete();
97   virtual void execute_set_input(int inputnum, int state);
98   virtual const address_space_config *memory_space_config(address_spacenum spacenum) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; }
99
100   void send_port(address_space &space, UINT8 offset, UINT8 data);
101    UINT8 read_port(UINT8 offset);
102
103   void recalc_irqs();
104   void recalc_timer(int timer);
105
106    UINT8 m_ports[6], m_ddrs[6];
107   UINT8 m_intctrl, m_tmrctrl;
108   UINT8 m_tmr12pre, m_tmr1, m_tmr2, m_tmrxpre, m_tmrx;
109   UINT8 m_tmr1latch, m_tmr2latch, m_tmrxlatch;
110   UINT8 m_last_all_ints;
111
112private:
113   emu_timer *m_timers[NUM_TIMERS];
114};
115
116class m50740_device : public m5074x_device
117{
118public:
119   m50740_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
120   m50740_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
121
122protected:
123
124private:
125};
126
127class m50741_device : public m5074x_device
128{
129public:
130   m50741_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
131   m50741_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
132
133protected:
134
135private:
136};
137
138extern const device_type M50740;
139extern const device_type M50741;
140
141#endif
Property changes on: trunk/src/emu/cpu/m6502/m5074x.h
Added: svn:eol-style
   + native
Added: svn:mime-type
   + text/plain

Previous 199869 Revisions Next


© 1997-2024 The MAME Team