diff options
Diffstat (limited to 'trunk/src/emu/machine/msm6242.c')
-rw-r--r-- | trunk/src/emu/machine/msm6242.c | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/trunk/src/emu/machine/msm6242.c b/trunk/src/emu/machine/msm6242.c new file mode 100644 index 00000000000..8ba28098905 --- /dev/null +++ b/trunk/src/emu/machine/msm6242.c @@ -0,0 +1,204 @@ +/*************************************************************************** + + MSM6242 Real Time Clock + +***************************************************************************/ + +#include "emu.h" +#include "machine/msm6242.h" + + +enum +{ + MSM6242_REG_S1 = 0, + MSM6242_REG_S10, + MSM6242_REG_MI1, + MSM6242_REG_MI10, + MSM6242_REG_H1, + MSM6242_REG_H10, + MSM6242_REG_D1, + MSM6242_REG_D10, + MSM6242_REG_MO1, + MSM6242_REG_MO10, + MSM6242_REG_Y1, + MSM6242_REG_Y10, + MSM6242_REG_W, + MSM6242_REG_CD, + MSM6242_REG_CE, + MSM6242_REG_CF +}; + + +typedef struct _msm6242_t msm6242_t; +struct _msm6242_t +{ + UINT8 reg[3]; + system_time hold_time; +}; + + +/* makes sure that the passed in device is the right type */ +INLINE msm6242_t *get_safe_token(device_t *device) +{ + assert(device != NULL); + assert(device->type() == MSM6242); + + return (msm6242_t *)downcast<legacy_device_base *>(device)->token(); +} + + +READ8_DEVICE_HANDLER( msm6242_r ) +{ + system_time curtime, *systime = &curtime; + msm6242_t *msm6242 = get_safe_token(device); + + if (msm6242->reg[0] & 1) /* if HOLD is set, use the hold time */ + { + systime = &msm6242->hold_time; + } + else /* otherwise, use the current time */ + { + device->machine().current_datetime(curtime); + } + + switch(offset) + { + case MSM6242_REG_S1: return systime->local_time.second % 10; + case MSM6242_REG_S10: return systime->local_time.second / 10; + case MSM6242_REG_MI1: return systime->local_time.minute % 10; + case MSM6242_REG_MI10: return systime->local_time.minute / 10; + case MSM6242_REG_H1: + case MSM6242_REG_H10: + { + int hour = systime->local_time.hour; + int pm = 0; + + /* check for 12/24 hour mode */ + if ((msm6242->reg[2] & 0x04) == 0) /* 12 hour mode? */ + { + if (hour >= 12) + pm = 1; + + hour %= 12; + + if ( hour == 0 ) + hour = 12; + } + + if ( offset == MSM6242_REG_H1 ) + return hour % 10; + + return (hour / 10) | (pm <<2); + } + + case MSM6242_REG_D1: return systime->local_time.mday % 10; + case MSM6242_REG_D10: return systime->local_time.mday / 10; + case MSM6242_REG_MO1: return (systime->local_time.month+1) % 10; + case MSM6242_REG_MO10: return (systime->local_time.month+1) / 10; + case MSM6242_REG_Y1: return systime->local_time.year % 10; + case MSM6242_REG_Y10: return (systime->local_time.year % 100) / 10; + case MSM6242_REG_W: return systime->local_time.weekday; + case MSM6242_REG_CD: return msm6242->reg[0]; + case MSM6242_REG_CE: return msm6242->reg[1]; + case MSM6242_REG_CF: return msm6242->reg[2]; + } + + logerror("%s: MSM6242 unmapped offset %02x read\n", device->machine().describe_context(), offset); + return 0; +} + + +WRITE8_DEVICE_HANDLER( msm6242_w ) +{ + msm6242_t *msm6242 = get_safe_token(device); + + switch(offset) + { + case MSM6242_REG_CD: + { + msm6242->reg[0] = data & 0x0f; + + if (data & 1) /* was Hold set? */ + { + device->machine().current_datetime(msm6242->hold_time); + } + + return; + } + + case MSM6242_REG_CE: msm6242->reg[1] = data & 0x0f; return; + + case MSM6242_REG_CF: + { + /* the 12/24 mode bit can only be changed while REST is 1 */ + if ((data ^ msm6242->reg[2]) & 0x04) + { + msm6242->reg[2] = (msm6242->reg[2] & 0x04) | (data & ~0x04); + + if (msm6242->reg[2] & 1) + msm6242->reg[2] = (msm6242->reg[2] & ~0x04) | (data & 0x04); + } + else + { + msm6242->reg[2] = data & 0x0f; + } + return; + } + } + + logerror("%s: MSM6242 unmapped offset %02x written with %02x\n", device->machine().describe_context(), offset, data); +} + + +static DEVICE_START( msm6242 ) +{ + msm6242_t *msm6242 = get_safe_token(device); + + msm6242->reg[0] = 0; + msm6242->reg[1] = 0; + msm6242->reg[2] = 0; + memset(&msm6242->hold_time, 0, sizeof(system_time)); +} + + +DEVICE_GET_INFO( msm6242 ) +{ + switch (state) + { + /* --- the following bits of info are returned as 64-bit signed integers --- */ + case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(msm6242_t); break; + case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break; + + /* --- the following bits of info are returned as pointers to data or functions --- */ + case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(msm6242); break; + case DEVINFO_FCT_STOP: /* Nothing */ break; + case DEVINFO_FCT_RESET: /* Nothing */ break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case DEVINFO_STR_NAME: strcpy(info->s, "OKI MSM6242"); break; + case DEVINFO_STR_FAMILY: strcpy(info->s, "MSM6242 RTC"); break; + case DEVINFO_STR_VERSION: strcpy(info->s, "1.00"); break; + case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; + case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright Nicola Salmoria and the MAME Team"); break; + } +} + + + + + +#if 0 +READ16_HANDLER( msm6242_lsb_r ) +{ + return msm6242_r(space, offset); +} + +WRITE16_HANDLER( msm6242_lsb_w ) +{ + if (ACCESSING_BITS_0_7) + msm6242_w(space, offset, data); +} +#endif + + +DEFINE_LEGACY_DEVICE(MSM6242, msm6242); |