Previous 199869 Revisions Next

r21921 Monday 18th March, 2013 at 01:12:44 UTC by R. Belmont
M3745x: Preliminary support for the Mitsubishi M37450 microcontroller [R. Belmont]
[src/emu/cpu]cpu.mak
[src/emu/cpu/m6502]m3745x.c* m3745x.h*

trunk/src/emu/cpu/m6502/m3745x.c
r0r21921
1/*
2    Mitsubishi M3745x 8-bit microcontroller family
3*/
4
5#include "emu.h"
6#include "m3745x.h"
7
8//**************************************************************************
9//  MACROS / CONSTANTS
10//**************************************************************************
11
12// Interrupt control bits (interpolated from C68 program; need 7450 Group manual badly)
13
14#define IRQ1_INT1      (0x04)
15#define IRQ1_INT2      (0x08)   // guess, not used in C68
16#define IRQ1_INT3      (0x10)  // guess, not used in C68
17
18#define IRQ2_SERIALRX   (0x08)
19#define IRQ2_SERIALTX   (0x10)
20#define IRQ2_ADC      (0x20)
21
22#define ADCTRL_CH_MASK   (0x07)   // AD ctrl reg. channel mask
23#define ADCTRL_COMPLETE   (0x08)   // AD ctrl "start"/"complete" bit
24
25//**************************************************************************
26//  DEVICE DEFINITIONS
27//**************************************************************************
28
29const device_type M37450 = &device_creator<m37450_device>;
30
31//**************************************************************************
32//  LIVE DEVICE
33//**************************************************************************
34
35//-------------------------------------------------
36//  m3745x_device - constructor
37//-------------------------------------------------
38m3745x_device::m3745x_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, address_map_constructor internal_map) :
39   m740_device(mconfig, type, name, tag, owner, clock),
40   m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0, internal_map),
41   read_p3(*this),
42   read_p4(*this),
43   read_p5(*this),
44   read_p6(*this),
45   write_p3(*this),
46   write_p4(*this),
47   write_p5(*this),
48   write_p6(*this),
49   read_ad_0(*this),
50   read_ad_1(*this),
51   read_ad_2(*this),
52   read_ad_3(*this),
53   read_ad_4(*this),
54   read_ad_5(*this),
55   read_ad_6(*this),
56   read_ad_7(*this)
57{
58}
59
60void m3745x_device::device_config_complete()
61{
62   m_shortname = "m3745x";
63}
64
65//-------------------------------------------------
66//  device_start - device-specific startup
67//-------------------------------------------------
68
69void m3745x_device::device_start()
70{
71   read_p3.resolve_safe(0);
72   read_p4.resolve_safe(0);
73   read_p5.resolve_safe(0);
74   read_p6.resolve_safe(0);
75   write_p3.resolve_safe();
76   write_p4.resolve_safe();
77   write_p5.resolve_safe();
78    write_p6.resolve_safe();
79   read_ad_0.resolve_safe(0);
80   read_ad_1.resolve_safe(0);
81   read_ad_2.resolve_safe(0);
82   read_ad_3.resolve_safe(0);
83   read_ad_4.resolve_safe(0);
84   read_ad_5.resolve_safe(0);
85   read_ad_6.resolve_safe(0);
86   read_ad_7.resolve_safe(0);
87
88   for (int i = 0; i < NUM_TIMERS; i++)
89   {
90      m_timers[i] = timer_alloc(i, NULL);
91   }
92
93   m740_device::device_start();
94
95   // all ports reset to input on startup
96   memset(m_ddrs, 0, sizeof(m_ddrs));
97   memset(m_ports, 0, sizeof(m_ports));
98   m_intreq1 = m_intreq2 = m_intctrl1 = m_intctrl2 = 0;
99   m_adctrl = 0;
100   m_last_all_ints = 0;
101}
102
103
104//-------------------------------------------------
105//  device_reset - device-specific reset
106//-------------------------------------------------
107
108void m3745x_device::device_reset()
109{
110   m740_device::device_reset();
111
112   SP = 0x01ff;   // we have the "traditional" stack in page 1, not 0 like some M740 derivatives
113
114   for (int i = 0; i < NUM_TIMERS; i++)
115   {
116      m_timers[i]->adjust(attotime::never);
117   }
118
119   // all ports reset to input on startup
120   memset(m_ddrs, 0, sizeof(m_ddrs));
121   memset(m_ports, 0, sizeof(m_ports));
122   m_intreq1 = m_intreq2 = m_intctrl1 = m_intctrl2 = 0;
123   m_adctrl = 0;
124   m_last_all_ints = 0;
125}
126
127void m3745x_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
128{
129   switch (id)
130   {
131      case TIMER_ADC:
132         m_timers[TIMER_ADC]->adjust(attotime::never);
133
134         m_adctrl |= ADCTRL_COMPLETE;
135         m_intreq2 |= IRQ2_ADC;
136         recalc_irqs();
137         break;
138
139      default:
140         printf("M3775x: unknown timer expire %d\n", id);
141         break;
142   }
143}
144
145void m3745x_device::execute_set_input(int inputnum, int state)
146{
147   switch (inputnum)
148   {
149      case M3745X_INT1_LINE:
150         if (state == ASSERT_LINE)
151         {
152            m_intreq1 |= IRQ1_INT1;
153         }
154         else
155         {
156            m_intreq1 &= ~IRQ1_INT1;
157         }
158         break;
159
160      case M3745X_INT2_LINE:
161         if (state == ASSERT_LINE)
162         {
163            m_intreq1 |= IRQ1_INT2;
164         }
165         else
166         {
167            m_intreq1 &= ~IRQ1_INT2;
168         }
169         break;
170
171      case M3745X_INT3_LINE:
172         if (state == ASSERT_LINE)
173         {
174            m_intreq1 |= IRQ1_INT3;
175         }
176         else
177         {
178            m_intreq1 &= ~IRQ1_INT3;
179         }
180         break;
181
182      case M3745X_SET_OVERFLOW:   // the base 740 class can handle this
183         m740_device::execute_set_input(M740_SET_OVERFLOW, state);
184         break;
185   }
186
187   recalc_irqs();
188}
189
190void m3745x_device::recalc_irqs()
191{
192   UINT16 all_ints = 0;
193   int static const irq_lines[16] =
194   {
195      -1, -1, -1, M740_INT11_LINE, M740_INT12_LINE, M740_INT13_LINE, -1, -1,
196      -1, -1, M740_INT2_LINE, M740_INT3_LINE, M740_INT4_LINE, -1, -1, -1
197   };
198
199   all_ints = (m_intreq1 & m_intctrl1) << 8;
200   all_ints |= (m_intreq2 & m_intctrl2);
201
202//   printf("recalc_irqs: last_all_ints = %04x last_ints = %04x (req1 %02x ctrl1 %02x req2 %02x ctrl2 %02x)\n", all_ints, m_last_all_ints, m_intreq1, m_intctrl1, m_intreq2, m_intctrl2);
203
204   // check all 16 IRQ bits for changes
205   for (int i = 0; i < 16; i++)
206   {
207      // if bit is set now
208      if (all_ints & (1 << i))
209      {
210         // and wasn't last time
211         if (!(m_last_all_ints & (1 << i)))
212         {
213//            printf("    asserting irq %d (%d)\n", i, irq_lines[i]);
214            if (irq_lines[i] != -1)
215            {
216               m740_device::execute_set_input(irq_lines[i], ASSERT_LINE);
217            }
218         }
219      }
220      else   // bit is clear now
221      {
222         // ...and wasn't clear last time
223         if (m_last_all_ints & (1 << i))
224         {
225//            printf("    clearing irq %d (%d)\n", i, irq_lines[i]);
226            if (irq_lines[i] != -1)
227            {
228               m740_device::execute_set_input(irq_lines[i], CLEAR_LINE);
229            }
230         }
231      }
232   }
233
234   m_last_all_ints = all_ints;
235}
236
237void m3745x_device::send_port(address_space &space, UINT8 offset, UINT8 data)
238{
239   switch (offset)
240   {
241      case 0:
242         write_p3(data);
243         break;
244
245      case 1:
246         write_p4(data);
247         break;
248
249      case 2:
250         write_p5(data);
251         break;
252
253      case 3:
254         write_p6(data);
255         break;
256   }
257}
258
259UINT8 m3745x_device::read_port(UINT8 offset)
260{
261   UINT8 incoming = 0;
262
263   switch (offset)
264   {
265      case 0:
266         incoming = read_p3();
267         break;
268
269      case 1:
270         incoming = read_p4();
271         break;
272
273      case 2:
274         incoming = read_p5();
275         break;
276
277      case 3:
278         incoming = read_p6();
279         break;
280   }
281
282   // apply data direction registers
283   incoming &= (m_ddrs[offset] ^ 0xff);
284   // OR in ddr-masked version of port writes
285   incoming |= (m_ports[offset] & m_ddrs[offset]);
286
287   return incoming;
288}
289
290READ8_MEMBER(m3745x_device::ports_r)
291{
292   switch (offset)
293   {
294      case 0:
295        return read_port(0);
296
297      case 1:
298        return m_ddrs[0];
299
300      case 2:
301        return read_port(1);
302
303      case 4:
304        return read_port(2);
305
306      case 5:
307        return m_ddrs[2];
308
309      case 6:
310        return read_port(3);
311
312      case 7:
313        return m_ddrs[3];
314   }
315
316   return 0xff;
317}
318
319WRITE8_MEMBER(m3745x_device::ports_w)
320{
321   switch (offset)
322   {
323      case 0:   // p3
324        send_port(space, 0, data & m_ddrs[0]);
325        m_ports[0] = data;
326        break;
327
328      case 1: // p3 ddr
329        send_port(space, 0, m_ports[0] & data);
330        m_ddrs[0] = data;
331        break;
332
333      case 2:   // p4
334        send_port(space, 1, data & m_ddrs[1]);
335        m_ports[1] = data;
336        break;
337
338      case 4:   // p5
339        send_port(space, 2, data & m_ddrs[2]);
340        m_ports[2] = data;
341        break;
342
343      case 5: // p5 ddr
344        send_port(space, 2, m_ports[2] & data);
345        m_ddrs[2] = data;
346        break;
347
348      case 6:   // p6
349        send_port(space, 3, data & m_ddrs[3]);
350        m_ports[3] = data;
351        break;
352
353      case 7: // p6 ddr
354        send_port(space, 3, m_ports[3] & data);
355        m_ddrs[3] = data;
356        break;
357   }
358}
359
360READ8_MEMBER(m3745x_device::intregs_r)
361{
362   switch (offset)
363   {
364      case 0:
365         return m_intreq1;
366
367      case 1:
368         return m_intreq2;
369
370      case 2:
371         return m_intctrl1;
372
373      case 3:
374         return m_intctrl2;
375   }
376
377   // this should never happen
378   assert(0);
379   return 0;
380}
381
382WRITE8_MEMBER(m3745x_device::intregs_w)
383{
384   switch (offset)
385   {
386      case 0:
387         m_intreq1 = data;
388         break;
389
390      case 1:
391         m_intreq2 = data;
392         break;
393
394      case 2:
395         m_intctrl1 = data;
396         break;
397
398      case 3:
399         m_intctrl2 = data;
400         break;
401   }
402
403   recalc_irqs();
404}
405
406READ8_MEMBER(m3745x_device::adc_r)
407{
408   UINT8 rv = 0;
409
410   switch (offset)
411   {
412      case 0:
413         m_intreq2 &= ~IRQ2_ADC;
414         recalc_irqs();
415
416         switch (m_adctrl & 7)
417         {
418            case 0:
419               rv = read_ad_0();
420               break;
421
422            case 1:
423               rv = read_ad_1();
424               break;
425
426            case 2:
427               rv = read_ad_2();
428               break;
429
430            case 3:
431               rv = read_ad_3();
432               break;
433
434            case 4:
435               rv = read_ad_4();
436               break;
437
438            case 5:
439               rv = read_ad_5();
440               break;
441
442            case 6:
443               rv = read_ad_6();
444               break;
445
446            case 7:
447               rv = read_ad_7();
448               break;
449         }
450         return rv;
451
452      case 1:
453         return m_adctrl;
454   }
455
456   return 0;
457}
458
459WRITE8_MEMBER(m3745x_device::adc_w)
460{
461   switch (offset)
462   {
463      case 0:
464         printf("M3745x: Write %02x to ADC output?!\n", data);
465         break;
466
467      case 1:
468         m_adctrl = data;
469
470         // starting a conversion?  this takes 50 cycles.
471         if (!(m_adctrl & ADCTRL_COMPLETE))
472         {
473            double hz = (double)clock() / 50.0f;
474            m_timers[TIMER_ADC]->adjust(attotime::from_hz(hz));
475         }
476         break;
477   }
478}
479
480/* M37450 - baseline for this familiy */
481static ADDRESS_MAP_START( m37450_map, AS_PROGRAM, 8, m37450_device )
482   AM_RANGE(0x0000, 0x00bf) AM_RAM
483   AM_RANGE(0x00d6, 0x00dd) AM_READWRITE(ports_r, ports_w)
484   AM_RANGE(0x00e2, 0x00e3) AM_READWRITE(adc_r, adc_w)
485   AM_RANGE(0x00fc, 0x00ff) AM_READWRITE(intregs_r, intregs_w)
486   AM_RANGE(0x0100, 0x01ff) AM_RAM
487ADDRESS_MAP_END
488
489m37450_device::m37450_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
490   m3745x_device(mconfig, M37450, "Mitsubishi M37450", tag, owner, clock, ADDRESS_MAP_NAME(m37450_map))
491{
492}
493
494m37450_device::m37450_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock) :
495   m3745x_device(mconfig, type, name, tag, owner, clock, ADDRESS_MAP_NAME(m37450_map))
496{
497}
498
Property changes on: trunk/src/emu/cpu/m6502/m3745x.c
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/cpu/m6502/m3745x.h
r0r21921
1#pragma once
2
3#ifndef __M3745X_H__
4#define __M3745X_H__
5
6#include "m740.h"
7
8//**************************************************************************
9//  INTERFACE CONFIGURATION MACROS
10//**************************************************************************
11
12#define MCFG_M3745X_ADC14_CALLBACKS(_ad0, _ad1, _ad2, _ad3) \
13   downcast<m3745x_device *>(device)->set_ad14_callbacks(DEVCB2_##_ad0, DEVCB2_##_ad1, DEVCB2_##_ad2, DEVCB2_##_ad3);
14
15#define MCFG_M3745X_ADC58_CALLBACKS(_ad0, _ad1, _ad2, _ad3) \
16   downcast<m3745x_device *>(device)->set_ad58_callbacks(DEVCB2_##_ad0, DEVCB2_##_ad1, DEVCB2_##_ad2, DEVCB2_##_ad3);
17
18#define MCFG_M3745X_PORT3_CALLBACKS(_read, _write) \
19   downcast<m3745x_device *>(device)->set_p3_callbacks(DEVCB2_##_read, DEVCB2_##_write);
20
21#define MCFG_M3745X_PORT4_CALLBACKS(_read, _write) \
22   downcast<m3745x_device *>(device)->set_p4_callbacks(DEVCB2_##_read, DEVCB2_##_write);
23
24#define MCFG_M3745X_PORT5_CALLBACKS(_read, _write) \
25   downcast<m3745x_device *>(device)->set_p5_callbacks(DEVCB2_##_read, DEVCB2_##_write);
26
27#define MCFG_M3745X_PORT6_CALLBACKS(_read, _write) \
28   downcast<m3745x_device *>(device)->set_p6_callbacks(DEVCB2_##_read, DEVCB2_##_write);
29
30//**************************************************************************
31//  TYPE DEFINITIONS
32//**************************************************************************
33
34// ======================> m3745x_device
35
36class m3745x_device :  public m740_device
37{
38   friend class m37450_device;
39
40   enum
41   {
42      TIMER_1 = 0,
43      TIMER_2,
44      TIMER_3,
45
46      TIMER_ADC,
47
48      NUM_TIMERS
49   };
50
51public:
52   enum
53   {
54      M3745X_INT1_LINE = INPUT_LINE_IRQ0,
55      M3745X_INT2_LINE,
56      M3745X_INT3_LINE,
57
58      M3745X_SET_OVERFLOW = M740_SET_OVERFLOW
59   };
60
61   // construction/destruction
62   m3745x_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, address_map_constructor internal_map);
63
64   const address_space_config m_program_config;
65
66   template<class _read, class _write> void set_p3_callbacks(_read rd, _write wr)
67   {
68      read_p3.set_callback(rd);
69      write_p3.set_callback(wr);
70   }
71
72   template<class _read, class _write> void set_p4_callbacks(_read rd, _write wr)
73   {
74      read_p4.set_callback(rd);
75      write_p4.set_callback(wr);
76   }
77
78   template<class _read, class _write> void set_p5_callbacks(_read rd, _write wr)
79   {
80      read_p5.set_callback(rd);
81      write_p5.set_callback(wr);
82   }
83
84   template<class _read, class _write> void set_p6_callbacks(_read rd, _write wr)
85   {
86      read_p6.set_callback(rd);
87      write_p6.set_callback(wr);
88   }
89
90   template<class _read, class _read2, class _read3, class _read4> void set_ad14_callbacks(_read rd, _read2 rd2, _read3 rd3, _read4 rd4)
91   {
92      read_ad_0.set_callback(rd);
93      read_ad_1.set_callback(rd2);
94      read_ad_2.set_callback(rd3);
95      read_ad_3.set_callback(rd4);
96   }
97
98   template<class _read, class _read2, class _read3, class _read4> void set_ad58_callbacks(_read rd, _read2 rd2, _read3 rd3, _read4 rd4)
99   {
100      read_ad_4.set_callback(rd);
101      read_ad_5.set_callback(rd2);
102      read_ad_6.set_callback(rd3);
103      read_ad_7.set_callback(rd4);
104   }
105
106   devcb2_read8  read_p3, read_p4, read_p5, read_p6;
107   devcb2_write8 write_p3, write_p4, write_p5, write_p6;
108   devcb2_read8  read_ad_0, read_ad_1, read_ad_2, read_ad_3;
109   devcb2_read8  read_ad_4, read_ad_5, read_ad_6, read_ad_7;
110
111    DECLARE_READ8_MEMBER(ports_r);
112    DECLARE_WRITE8_MEMBER(ports_w);
113    DECLARE_READ8_MEMBER(adc_r);
114    DECLARE_WRITE8_MEMBER(adc_w);
115    DECLARE_READ8_MEMBER(intregs_r);
116    DECLARE_WRITE8_MEMBER(intregs_w);
117
118   bool are_port_bits_output(UINT8 port, UINT8 mask) { return ((m_ddrs[port] & mask) == mask) ? true : false; }
119
120protected:
121   // device-level overrides
122   virtual void device_start();
123   virtual void device_reset();
124   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
125   virtual void device_config_complete();
126   virtual void execute_set_input(int inputnum, int state);
127   virtual const address_space_config *memory_space_config(address_spacenum spacenum) const { return (spacenum == AS_PROGRAM) ? &m_program_config : NULL; }
128
129   void send_port(address_space &space, UINT8 offset, UINT8 data);
130    UINT8 read_port(UINT8 offset);
131
132   void recalc_irqs();
133
134    UINT8 m_ports[6], m_ddrs[6];
135   UINT8 m_intreq1, m_intreq2, m_intctrl1, m_intctrl2;
136   UINT8 m_adctrl;
137   UINT16 m_last_all_ints;
138
139private:
140   emu_timer *m_timers[NUM_TIMERS];
141};
142
143class m37450_device : public m3745x_device
144{
145public:
146   m37450_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
147   m37450_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock);
148
149protected:
150
151private:
152};
153
154extern const device_type M37450;
155
156#endif
Property changes on: trunk/src/emu/cpu/m6502/m3745x.h
Added: svn:mime-type
   + text/plain
Added: svn:eol-style
   + native
trunk/src/emu/cpu/cpu.mak
r21920r21921
10341034         $(CPUOBJ)/m6502/m8502.o \
10351035         $(CPUOBJ)/m6502/n2a03.o \
10361036         $(CPUOBJ)/m6502/r65c02.o \
1037         $(CPUOBJ)/m6502/m740.o
1037         $(CPUOBJ)/m6502/m740.o \
1038         $(CPUOBJ)/m6502/m3745x.o \
10381039
10391040DASMOBJS +=
10401041endif
r21920r21921
11161117                     $(CPUSRC)/m6502/m740.h \
11171118                     $(CPUSRC)/m6502/m6502.h
11181119
1120$(CPUOBJ)/m6502/m3745x.o:   $(CPUSRC)/m6502/m3745x.c \
1121                     $(CPUSRC)/m6502/m3745x.h
1122
11191123# rule to generate the C files
11201124$(CPUOBJ)/m6502/deco16.inc: $(CPUSRC)/m6502/m6502make.py $(CPUSRC)/m6502/odeco16.lst $(CPUSRC)/m6502/ddeco16.lst
11211125   @echo Generating DECO16 source file...

Previous 199869 Revisions Next


© 1997-2024 The MAME Team