Previous 15994 Revisions Next

r14331 Friday 3rd February, 2012 at 14:43:30 UTC by Sandro Ronco
Added emulation of HD64610 RTC and hooked up to pda600 driver. [Sandro Ronco]
[src/mess]mess.mak
[src/mess/drivers]pda600.c
[src/mess/machine]hd64610.c* hd64610.h*

src/mess/machine/hd64610.c
r0r14331
1/**********************************************************************
2
3    Hitachi HD64610 Real Time Clock
4
5*********************************************************************/
6
7/*
8
9    TODO:
10    - leap year
11    - test mode
12
13*/
14
15#include "hd64610.h"
16#include "coreutil.h"
17
18
19// device type definition
20const device_type HD64610 = &device_creator<hd64610_device>;
21
22
23//**************************************************************************
24//  MACROS / CONSTANTS
25//**************************************************************************
26
27#define LOG 1
28
29// internal registers
30enum
31{
32   REG_64HZ = 0,
33   REG_SECOND,
34   REG_MINUTE,
35   REG_HOUR,
36   REG_DAY_OF_THE_WEEK,
37   REG_DAY,
38   REG_MONTH,
39   REG_YEAR,
40   REG_64HZ_ALARM,
41   REG_SECOND_ALARM,
42   REG_MINUTE_ALARM,
43   REG_HOUR_ALARM,
44   REG_DAY_OF_THE_WEEK_ALARM,
45   REG_DAY_ALARM,
46   REG_CRA,
47   REG_CRB,
48};
49
50
51// Control Register A
52#define CRA_CF         0x80
53#define CRA_CIE         0x10
54#define CRA_AIE         0x08
55#define CRA_AF         0x01
56
57// Control Register B
58#define CRB_TEST      0x08
59#define CRB_ADJ         0x04
60#define CRB_RESET      0x02
61#define CRB_S         0x01
62
63// alarm
64#define ALARM_ENB      0x80
65
66// days per month
67static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
68
69// register write mask
70static const int REG_WRITE_MASK[0x10] =
71{
72   0x00, 0x7f, 0x7f, 0x3f, 0x07, 0x3f, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xbf, 0x83, 0xbf, 0x18, 0xff
73};
74
75//**************************************************************************
76//  INLINE HELPERS
77//**************************************************************************
78
79//-------------------------------------------------
80//  set_irq_line -
81//-------------------------------------------------
82
83inline void hd64610_device::set_irq_line()
84{
85   int irq_out = (((m_regs[REG_CRA] & CRA_CF) && (m_regs[REG_CRA] & CRA_CIE)) ||
86              ((m_regs[REG_CRA] & CRA_AF) && (m_regs[REG_CRA] & CRA_AIE))) ? 0 : 1;
87
88   if (m_irq_out != irq_out)
89   {
90      if (LOG) logerror("HD64610 '%s' IRQ %u\n", tag(), irq_out);
91
92      m_out_irq_func(irq_out);
93      m_irq_out = irq_out;
94   }
95}
96
97//-------------------------------------------------
98//  read_counter -
99//-------------------------------------------------
100
101inline UINT8 hd64610_device::read_counter(int counter)
102{
103   return bcd_2_dec(m_regs[counter]);
104}
105
106//-------------------------------------------------
107//  write_counter -
108//-------------------------------------------------
109
110inline void hd64610_device::write_counter(int counter, UINT8 value)
111{
112   m_regs[counter] = dec_2_bcd(value);
113}
114
115//-------------------------------------------------
116//  advance_seconds -
117//-------------------------------------------------
118
119inline void hd64610_device::advance_seconds()
120{
121   int seconds = read_counter(REG_SECOND);
122
123   seconds++;
124
125   if (seconds > 59)
126   {
127      seconds = 0;
128
129      advance_minutes();
130   }
131
132   write_counter(REG_SECOND, seconds);
133}
134
135
136//-------------------------------------------------
137//  advance_minutes -
138//-------------------------------------------------
139
140inline void hd64610_device::advance_minutes()
141{
142   int minutes = read_counter(REG_MINUTE);
143   int hours = read_counter(REG_HOUR);
144   int days = read_counter(REG_DAY);
145   int month = read_counter(REG_MONTH);
146   int year = read_counter(REG_YEAR);
147   int day_of_week = read_counter(REG_DAY_OF_THE_WEEK);
148
149   minutes++;
150
151   if (minutes > 59)
152   {
153      minutes = 0;
154      hours++;
155   }
156
157   if (hours > 23)
158   {
159      hours = 0;
160      days++;
161      day_of_week++;
162   }
163
164   if (day_of_week > 6)
165   {
166      day_of_week++;
167   }
168
169   if (days > DAYS_PER_MONTH[month - 1])
170   {
171      days = 1;
172      month++;
173   }
174
175   if (month > 12)
176   {
177      month = 1;
178      year++;
179   }
180
181   if (year > 99)
182   {
183      year = 0;
184   }
185
186   write_counter(REG_MINUTE, minutes);
187   write_counter(REG_HOUR, hours);
188   write_counter(REG_DAY, days);
189   write_counter(REG_MONTH, month);
190   write_counter(REG_YEAR,year);
191   m_regs[REG_DAY_OF_THE_WEEK] = day_of_week;
192
193   check_alarm();
194   set_irq_line();
195}
196
197//-------------------------------------------------
198//  adjust_seconds -
199//-------------------------------------------------
200
201inline void hd64610_device::adjust_seconds()
202{
203   int seconds = read_counter(REG_SECOND);
204
205   write_counter(REG_SECOND, 0);
206
207   if (seconds >= 30)
208      advance_minutes();
209}
210
211//-------------------------------------------------
212//  check_alarm -
213//-------------------------------------------------
214
215inline void hd64610_device::check_alarm()
216{
217   bool alarm_flag = true;
218
219   // clear alarm flag
220   m_regs[REG_CRA] &= ~CRA_AF;
221
222   if (m_regs[REG_64HZ_ALARM] & ALARM_ENB || m_regs[REG_SECOND_ALARM] & ALARM_ENB || m_regs[REG_SECOND_ALARM] & ALARM_ENB ||
223      m_regs[REG_HOUR_ALARM] & ALARM_ENB || m_regs[REG_DAY_OF_THE_WEEK_ALARM] & ALARM_ENB || m_regs[REG_DAY_ALARM] & ALARM_ENB)
224   {
225      // at least one ENB is active
226
227      for (int i = REG_64HZ; i <= REG_DAY; i++)
228      {
229         if ((m_regs[i] & REG_WRITE_MASK[i]) != (m_regs[i+8] & REG_WRITE_MASK[i]) && m_regs[i+8] & ALARM_ENB)
230             alarm_flag = false;
231      }
232
233      m_regs[REG_CRA] |= (alarm_flag ? CRA_AF : 0);
234   }
235}
236
237
238
239//**************************************************************************
240//  LIVE DEVICE
241//**************************************************************************
242
243//-------------------------------------------------
244//  hd64610_device - constructor
245//-------------------------------------------------
246
247hd64610_device::hd64610_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
248   : device_t(mconfig, HD64610, "HD64610", tag, owner, clock),
249     device_rtc_interface(mconfig, *this),
250     device_nvram_interface(mconfig, *this),
251     m_hline_state(1),
252     m_irq_out(1)
253{
254}
255
256
257//-------------------------------------------------
258//  device_config_complete - perform any
259//  operations now that the configuration is
260//  complete
261//-------------------------------------------------
262
263void hd64610_device::device_config_complete()
264{
265   // inherit a copy of the static data
266   const hd64610_interface *intf = reinterpret_cast<const hd64610_interface *>(static_config());
267   if (intf != NULL)
268   {
269      *static_cast<hd64610_interface *>(this) = *intf;
270   }
271   // or initialize to defaults if none provided
272   else
273   {
274      memset(&m_out_irq_cb, 0, sizeof(m_out_irq_cb));
275   }
276}
277
278
279//-------------------------------------------------
280//  device_start - device-specific startup
281//-------------------------------------------------
282
283void hd64610_device::device_start()
284{
285   // resolve callbacks
286   m_out_irq_func.resolve(m_out_irq_cb, *this);
287   m_out_1hz_func.resolve(m_out_1hz_cb, *this);
288
289   // allocate timers
290   m_counter_timer = timer_alloc(TIMER_UPDATE_COUNTER);
291   m_counter_timer->adjust(attotime::from_hz(clock() / 256), 0, attotime::from_hz(clock() / 256));
292
293   // state saving
294   save_item(NAME(m_regs));
295   save_item(NAME(m_irq_out));
296   save_item(NAME(m_hline_state));
297}
298
299
300//-------------------------------------------------
301//  device_timer - handler timer events
302//-------------------------------------------------
303
304void hd64610_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
305{
306   switch (id)
307   {
308   case TIMER_UPDATE_COUNTER:
309      if(m_hline_state || (m_regs[REG_CRB] & CRB_S))
310      {
311         m_regs[REG_64HZ]++;
312
313         if (m_regs[REG_64HZ] & 0x80)
314         {
315            // update seconds
316            advance_seconds();
317
318            // set carry flag
319            m_regs[REG_CRA] |= CRA_CF;
320
321            m_regs[REG_64HZ] &= 0x7f;
322         }
323
324         // update 1Hz out
325         m_out_1hz_func(BIT(m_regs[REG_64HZ], 6));
326
327         // update IRQ
328         check_alarm();
329         set_irq_line();
330      }
331      break;
332   }
333}
334
335
336//-------------------------------------------------
337//  rtc_set_time - called to initialize the RTC to
338//  a known state
339//-------------------------------------------------
340
341void hd64610_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second)
342{
343   write_counter(REG_SECOND, second);
344   write_counter(REG_MINUTE, minute);
345   write_counter(REG_HOUR, hour);
346   write_counter(REG_DAY, day);
347   write_counter(REG_MONTH, month);
348   write_counter(REG_YEAR,year);
349   m_regs[REG_DAY_OF_THE_WEEK] = day_of_week;
350}
351
352
353//-------------------------------------------------
354//  nvram_default - called to initialize NVRAM to
355//  its default state
356//-------------------------------------------------
357
358void hd64610_device::nvram_default()
359{
360   memset(m_regs, 0, 0x10);
361}
362
363
364//-------------------------------------------------
365//  nvram_read - called to read NVRAM from the
366//  .nv file
367//-------------------------------------------------
368
369void hd64610_device::nvram_read(emu_file &file)
370{
371   file.read(m_regs, 0x10);
372}
373
374
375//-------------------------------------------------
376//  nvram_write - called to write NVRAM to the
377//  .nv file
378//-------------------------------------------------
379
380void hd64610_device::nvram_write(emu_file &file)
381{
382   file.write(m_regs, 0x10);
383}
384
385
386//-------------------------------------------------
387//  hardware start/stop
388//-------------------------------------------------
389
390WRITE_LINE_MEMBER( hd64610_device::h_w )
391{
392   m_hline_state = state;
393}
394
395
396//-------------------------------------------------
397//  read -
398//-------------------------------------------------
399
400READ8_MEMBER( hd64610_device::read )
401{
402   UINT8 data =  m_regs[offset & 0x0f];
403
404   if (LOG) logerror("HD64610 '%s' Register %u Read %02x\n", tag(), offset, data);
405
406   return data;
407}
408
409
410//-------------------------------------------------
411//  write -
412//-------------------------------------------------
413
414WRITE8_MEMBER( hd64610_device::write )
415{
416   switch (offset & 0x0f)
417   {
418   case REG_64HZ:
419      // read only
420      logerror("HD64610 '%s' Writing to read-only register 64Hz Counter\n", tag());
421      break;
422
423   case REG_CRA:
424      m_regs[REG_CRA] = data & REG_WRITE_MASK[REG_CRA];
425
426      if ((data & CRA_CF) == 0)
427      {
428         if (LOG) logerror("HD64610 '%s' clear carry flag\n", tag());
429         m_regs[REG_CRA] &= 0x7f;
430      }
431      if ((data & CRA_AF) == 0)
432      {
433         if (LOG) logerror("HD64610 '%s' clear alarm flag\n", tag());
434         m_regs[REG_CRA] &= 0xfe;
435      }
436
437      if (LOG) logerror("HD64610 '%s' set alarm IRQ %d\n", tag(), BIT(data, 3));
438      if (LOG) logerror("HD64610 '%s' set carry IRQ %d\n", tag(), BIT(data, 4));
439      break;
440
441   case REG_CRB:
442      m_regs[REG_CRB] = data & REG_WRITE_MASK[REG_CRB];
443
444      if (data & CRB_ADJ)
445      {
446         if (LOG) logerror("HD64610 '%s' 30-sec adjustament\n", tag());
447         adjust_seconds();
448         m_regs[REG_64HZ] = 0;
449
450         m_regs[REG_CRB] &= ~CRB_ADJ;
451      }
452
453      if (data & CRB_RESET)
454      {
455         if (LOG) logerror("HD64610 '%s' CRB reset\n", tag());
456         m_regs[REG_64HZ] = 0;
457
458         m_regs[REG_CRB] &= ~CRB_RESET;
459      }
460
461      if (LOG) logerror("HD64610 '%s' set timer %d\n", tag(), BIT(data, 0));
462      break;
463
464   default:
465      m_regs[offset & 0x0f] = data & REG_WRITE_MASK[offset & 0x0f];
466      if (LOG) logerror("HD64610 '%s' Register %u Write %02x\n", tag(), offset & 0x0f, data);
467      break;
468   }
469}
src/mess/machine/hd64610.h
r0r14331
1/**********************************************************************
2
3    Hitachi HD64610 Real Time Clock
4
5**********************************************************************
6                            _____   _____
7                   GND   1 |*    \_/     | 24  Vcc
8          H-Start/Stop   2 |             | 23  OSC2
9                  _IRQ   3 |             | 22  OSC1
10                   1Hz   4 |   HD64610   | 21  GND
11                    A3   5 |             | 20  _WE
12                    A2   6 |             | 19  _OE
13                    A1   7 |             | 18  _CS
14                    A0   8 |             | 17  I/O8
15                  I/O1   9 |             | 16  I/O7
16                  I/O2  10 |             | 15  I/O6
17                  I/O3  11 |             | 14  I/O5
18                   GND  12 |_____________| 13  I/O4
19
20**********************************************************************/
21
22#pragma once
23
24#ifndef __HD64610__
25#define __HD64610__
26
27#include "emu.h"
28
29
30
31//**************************************************************************
32//  INTERFACE CONFIGURATION MACROS
33//**************************************************************************
34
35#define MCFG_HD64610_ADD(_tag, _clock, _config) \
36   MCFG_DEVICE_ADD((_tag), HD64610, _clock)   \
37   MCFG_DEVICE_CONFIG(_config)
38
39
40#define HD64610_INTERFACE(name) \
41   const hd64610_interface (name) =
42
43
44
45//**************************************************************************
46//  TYPE DEFINITIONS
47//**************************************************************************
48
49// ======================> hd64610_interface
50
51struct hd64610_interface
52{
53   devcb_write_line      m_out_irq_cb;
54   devcb_write_line      m_out_1hz_cb;
55};
56
57
58
59// ======================> hd64610_device
60
61class hd64610_device :   public device_t,
62                  public device_rtc_interface,
63                  public device_nvram_interface,
64                  public hd64610_interface
65{
66public:
67    // construction/destruction
68   hd64610_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
69
70   DECLARE_READ8_MEMBER( read );
71   DECLARE_WRITE8_MEMBER( write );
72
73   // hardware start/stop line
74   DECLARE_WRITE_LINE_MEMBER( h_w );
75
76protected:
77   // device-level overrides
78   virtual void device_config_complete();
79   virtual void device_start();
80   virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr);
81
82   // device_rtc_interface overrides
83   virtual void rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second);
84   virtual bool rtc_is_year_2000_compliant() { return false; }
85
86   // device_nvram_interface overrides
87   virtual void nvram_default();
88   virtual void nvram_read(emu_file &file);
89   virtual void nvram_write(emu_file &file);
90
91private:
92   inline void set_irq_line();
93   inline void adjust_seconds();
94   inline UINT8 read_counter(int counter);
95   inline void write_counter(int counter, UINT8 value);
96   inline void advance_seconds();
97   inline void advance_minutes();
98   inline void check_alarm();
99
100   static const device_timer_id TIMER_UPDATE_COUNTER = 0;
101
102   devcb_resolved_write_line   m_out_irq_func;
103   devcb_resolved_write_line   m_out_1hz_func;
104
105   UINT8   m_regs[0x10];      // Internal registers
106   int      m_hline_state;      // H-Start/Stop line
107   int      m_irq_out;         // alarm output
108
109   // timers
110   emu_timer *m_counter_timer;
111};
112
113
114// device type definition
115extern const device_type HD64610;
116
117
118#endif
src/mess/mess.mak
r14330r14331
607607   $(MESS_DRIVERS)/pcw.o      \
608608   $(MESS_VIDEO)/pcw16.o      \
609609   $(MESS_DRIVERS)/pda600.o   \
610   $(MESS_MACHINE)/hd64610.o   \
610611   $(MESS_DRIVERS)/pcw16.o      \
611612
612613$(MESSOBJ)/apf.a:            \
src/mess/drivers/pda600.c
r14330r14331
5757#include "emu.h"
5858#include "cpu/z180/z180.h"
5959#include "machine/nvram.h"
60#include "machine/hd64610.h"
6061#include "rendlay.h"
6162
6263
r14330r14331
9192   ADDRESS_MAP_GLOBAL_MASK(0xff)
9293   AM_RANGE(0x00, 0x3f) AM_NOP /* Z180 internal registers */
9394   //AM_RANGE(0x40, 0x7f) AM_NOP   /* Z180 internal registers */
94   //AM_RANGE(0x80, 0x8f) AM_NOP   /* RTC */
95   AM_RANGE(0x80, 0x8f) AM_DEVREADWRITE("rtc", hd64610_device, read, write)
9596   //AM_RANGE(0xC0, 0xC1) AM_NOP   /* LCD */
96
9797ADDRESS_MAP_END
9898
9999/* Input ports */
r14330r14331
193193   GFXDECODE_ENTRY( "maincpu", 0x61d3, pda600_charlayout_13a, 0, 1 )
194194GFXDECODE_END
195195
196static HD64610_INTERFACE( rtc_intf )
197{
198   DEVCB_NULL,
199   DEVCB_NULL
200};
201
196202static MACHINE_CONFIG_START( pda600, pda600_state )
197203   /* basic machine hardware */
198204   MCFG_CPU_ADD("maincpu",Z180, XTAL_14_31818MHz)
r14330r14331
213219
214220   // NVRAM needs to be filled with random data to fail the checksum and be initialized correctly
215221   MCFG_NVRAM_ADD_RANDOM_FILL("nvram")
222
223   MCFG_HD64610_ADD("rtc", XTAL_32_768kHz, rtc_intf)
216224MACHINE_CONFIG_END
217225
218226/* ROM definition */

Previous 15994 Revisions Next


© 1998-2018 The MESS Team