1
/**********************************************************************
3
Ricoh RP5C15 Real Time Clock emulation
6
Visit http://mamedev.org for licensing and usage restrictions.
8
*********************************************************************/
24
//**************************************************************************
26
//**************************************************************************
34
REGISTER_1_SECOND = 0, REGISTER_CLOCK_OUTPUT = REGISTER_1_SECOND,
35
REGISTER_10_SECOND, REGISTER_ADJUST = REGISTER_10_SECOND,
40
REGISTER_DAY_OF_THE_WEEK,
44
REGISTER_10_MONTH, REGISTER_12_24_SELECT = REGISTER_10_MONTH,
45
REGISTER_1_YEAR, REGISTER_LEAP_YEAR = REGISTER_1_YEAR,
53
// clock output select
67
// register write mask
68
static const int REGISTER_WRITE_MASK[2][16] =
70
{ 0xf, 0x7, 0xf, 0x7, 0xf, 0x3, 0x7, 0xf, 0x3, 0xf, 0x1, 0xf, 0xf, 0xf, 0xf, 0xf },
71
{ 0x3, 0x1, 0xf, 0x7, 0xf, 0x3, 0x7, 0xf, 0x3, 0x0, 0x1, 0x3, 0x0, 0xf, 0xf, 0xf }
76
static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
88
#define MODE_MASK 0x01
89
#define MODE_ALARM_EN 0x04
90
#define MODE_TIMER_EN 0x08
101
#define RESET_ALARM 0x01
102
#define RESET_TIMER 0x02
103
#define RESET_16_HZ 0x04
104
#define RESET_1_HZ 0x08
108
//**************************************************************************
110
//**************************************************************************
113
const device_type RP5C15 = &device_creator<rp5c15_device>;
117
//**************************************************************************
119
//**************************************************************************
121
//-------------------------------------------------
123
//-------------------------------------------------
125
inline void rp5c15_device::set_alarm_line()
127
int alarm = ((m_mode & MODE_ALARM_EN) ? m_alarm_on : 1) &
128
((m_reset & RESET_16_HZ) ? 1 : m_16hz) &
129
((m_reset & RESET_1_HZ) ? 1 : m_1hz);
131
if (m_alarm != alarm)
133
if (LOG) logerror("RP5C15 '%s' Alarm %u\n", tag(), alarm);
135
m_out_alarm_func(alarm);
141
//-------------------------------------------------
143
//-------------------------------------------------
145
inline int rp5c15_device::read_counter(int counter)
147
return (m_reg[MODE00][counter + 1] * 10) + m_reg[MODE00][counter];
151
//-------------------------------------------------
153
//-------------------------------------------------
155
inline void rp5c15_device::write_counter(int counter, int value)
157
m_reg[MODE00][counter] = value % 10;
158
m_reg[MODE00][counter + 1] = value / 10;
162
//-------------------------------------------------
164
//-------------------------------------------------
166
inline void rp5c15_device::advance_seconds()
168
int seconds = read_counter(REGISTER_1_SECOND);
179
write_counter(REGISTER_1_SECOND, seconds);
183
//-------------------------------------------------
185
//-------------------------------------------------
187
inline void rp5c15_device::advance_minutes()
189
int minutes = read_counter(REGISTER_1_MINUTE);
190
int hours = read_counter(REGISTER_1_HOUR);
191
int days = read_counter(REGISTER_1_DAY);
192
int month = read_counter(REGISTER_1_MONTH);
193
int year = read_counter(REGISTER_1_YEAR);
194
int day_of_week = m_reg[MODE00][REGISTER_DAY_OF_THE_WEEK];
216
if (days > DAYS_PER_MONTH[month - 1])
226
m_reg[MODE01][REGISTER_LEAP_YEAR]++;
227
m_reg[MODE01][REGISTER_LEAP_YEAR] &= 0x03;
235
write_counter(REGISTER_1_MINUTE, minutes);
236
write_counter(REGISTER_1_HOUR, hours);
237
write_counter(REGISTER_1_DAY, days);
238
write_counter(REGISTER_1_MONTH, month);
239
write_counter(REGISTER_1_YEAR, year);
240
m_reg[MODE00][REGISTER_DAY_OF_THE_WEEK] = day_of_week;
247
//-------------------------------------------------
249
//-------------------------------------------------
251
inline void rp5c15_device::adjust_seconds()
253
int seconds = read_counter(REGISTER_1_SECOND);
257
write_counter(REGISTER_1_SECOND, 0);
261
write_counter(REGISTER_1_SECOND, 0);
267
//-------------------------------------------------
269
//-------------------------------------------------
271
inline void rp5c15_device::check_alarm()
273
bool all_match = true;
274
bool all_zeroes = true;
276
for (int i = REGISTER_1_MINUTE; i < REGISTER_1_MONTH; i++)
278
if (m_reg[MODE01][i] != 0) all_zeroes = false;
279
if (m_reg[MODE01][i] != m_reg[MODE00][i]) all_match = false;
282
m_alarm_on = (all_match || (!m_alarm_on && all_zeroes)) ? 0 : 1;
287
//**************************************************************************
289
//**************************************************************************
291
//-------------------------------------------------
292
// rp5c15_device - constructor
293
//-------------------------------------------------
295
rp5c15_device::rp5c15_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
296
: device_t(mconfig, RP5C15, "RP5C15", tag, owner, clock),
297
device_rtc_interface(mconfig, *this),
307
//-------------------------------------------------
308
// device_config_complete - perform any
309
// operations now that the configuration is
311
//-------------------------------------------------
313
void rp5c15_device::device_config_complete()
315
// inherit a copy of the static data
316
const rp5c15_interface *intf = reinterpret_cast<const rp5c15_interface *>(static_config());
318
*static_cast<rp5c15_interface *>(this) = *intf;
320
// or initialize to defaults if none provided
323
memset(&m_out_alarm_cb, 0, sizeof(m_out_alarm_cb));
324
memset(&m_out_clkout_cb, 0, sizeof(m_out_clkout_cb));
329
//-------------------------------------------------
330
// device_start - device-specific startup
331
//-------------------------------------------------
333
void rp5c15_device::device_start()
336
m_out_alarm_func.resolve(m_out_alarm_cb, *this);
337
m_out_clkout_func.resolve(m_out_clkout_cb, *this);
340
m_clock_timer = timer_alloc(TIMER_CLOCK);
341
m_clock_timer->adjust(attotime::from_hz(clock() / 16384), 0, attotime::from_hz(clock() / 16384));
343
m_16hz_timer = timer_alloc(TIMER_16HZ);
344
m_16hz_timer->adjust(attotime::from_hz(clock() / 1024), 0, attotime::from_hz(clock() / 1024));
346
m_clkout_timer = timer_alloc(TIMER_CLKOUT);
349
save_item(NAME(m_reg[MODE00]));
350
save_item(NAME(m_reg[MODE01]));
351
save_item(NAME(m_mode));
352
save_item(NAME(m_reset));
353
save_item(NAME(m_alarm));
354
save_item(NAME(m_alarm_on));
355
save_item(NAME(m_1hz));
356
save_item(NAME(m_16hz));
357
save_item(NAME(m_clkout));
361
//-------------------------------------------------
362
// device_timer - handler timer events
363
//-------------------------------------------------
365
void rp5c15_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
370
if (m_1hz && (m_mode & MODE_TIMER_EN))
385
m_clkout = !m_clkout;
386
m_out_clkout_func(m_clkout);
392
//-------------------------------------------------
393
// rtc_set_time - called to initialize the RTC to
395
//-------------------------------------------------
397
void rp5c15_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second)
399
write_counter(REGISTER_1_YEAR, year);
400
write_counter(REGISTER_1_MONTH, month);
401
write_counter(REGISTER_1_DAY, day);
402
m_reg[MODE00][REGISTER_DAY_OF_THE_WEEK] = day_of_week;
403
write_counter(REGISTER_1_HOUR, hour);
404
write_counter(REGISTER_1_MINUTE, minute);
405
write_counter(REGISTER_1_SECOND, second);
409
//-------------------------------------------------
411
//-------------------------------------------------
413
READ8_MEMBER( rp5c15_device::read )
417
switch (offset & 0x0f)
429
data = m_reg[m_mode & MODE_MASK][offset];
433
if (LOG) logerror("RP5C15 '%s' Register %u Read %02x\n", tag(), offset & 0x0f, data);
439
//-------------------------------------------------
441
//-------------------------------------------------
443
WRITE8_MEMBER( rp5c15_device::write )
445
int mode = m_mode & MODE_MASK;
447
switch (offset & 0x0f)
450
m_mode = data & 0x0f;
454
logerror("RP5C15 '%s' Mode %u\n", tag(), data & MODE_MASK);
455
logerror("RP5C15 '%s' Timer %s\n", tag(), (data & MODE_TIMER_EN) ? "enabled" : "disabled");
456
logerror("RP5C15 '%s' Alarm %s\n", tag(), (data & MODE_ALARM_EN) ? "enabled" : "disabled");
461
if (LOG) logerror("RP5C15 '%s' Test %u not supported!\n", tag(), data);
465
m_reset = data & 0x0f;
467
if (data & RESET_ALARM)
471
// reset alarm registers
472
for (i = REGISTER_1_MINUTE; i < REGISTER_1_MONTH; i++)
474
m_reg[MODE01][i] = 0;
480
if (data & RESET_ALARM) logerror("RP5C15 '%s' Alarm Reset\n", tag());
481
if (data & RESET_TIMER) logerror("RP5C15 '%s' Timer Reset not supported!\n", tag());
482
logerror("RP5C15 '%s' 16Hz Signal %s\n", tag(), (data & RESET_16_HZ) ? "disabled" : "enabled");
483
logerror("RP5C15 '%s' 1Hz Signal %s\n", tag(), (data & RESET_1_HZ) ? "disabled" : "enabled");
491
m_reg[mode][offset & 0x0f] = data & REGISTER_WRITE_MASK[mode][offset & 0x0f];
495
switch (offset & 0x0f)
497
case REGISTER_CLOCK_OUTPUT:
500
case CLKOUT_16384_HZ:
501
m_clkout_timer->adjust(attotime::from_hz(clock()), 0, attotime::from_hz(clock()));
505
m_clkout_timer->adjust(attotime::from_hz(clock() / 16), 0, attotime::from_hz(clock() / 16));
509
m_clkout_timer->adjust(attotime::from_hz(clock() / 128), 0, attotime::from_hz(clock() / 128));
513
m_clkout_timer->adjust(attotime::from_hz(clock() / 1024), 0, attotime::from_hz(clock() / 1024));
517
m_clkout_timer->adjust(attotime::from_hz(clock() / 16384), 0, attotime::from_hz(clock() / 16384));
520
case CLKOUT_1_DIV_60_HZ:
527
m_clkout_timer->adjust(attotime::zero, 0);
531
m_reg[mode][offset & 0x0f] = data & REGISTER_WRITE_MASK[mode][offset & 0x0f];
534
case REGISTER_ADJUST:
539
m_reg[mode][offset & 0x0f] = data & REGISTER_WRITE_MASK[mode][offset & 0x0f];
543
m_reg[mode][offset & 0x0f] = data & REGISTER_WRITE_MASK[mode][offset & 0x0f];
549
if (LOG) logerror("RP5C15 '%s' Register %u Write %02x\n", tag(), offset & 0x0f, data);