src/emu/dirtc.c
| r15044 | r15045 | |
| 11 | 11 | |
| 12 | 12 | |
| 13 | 13 | //************************************************************************** |
| 14 | // MACROS / CONSTANTS |
| 15 | //************************************************************************** |
| 16 | |
| 17 | static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
| 18 | |
| 19 | |
| 20 | |
| 21 | //************************************************************************** |
| 14 | 22 | // DEVICE RTC INTERFACE |
| 15 | 23 | //************************************************************************** |
| 16 | 24 | |
| r15044 | r15045 | |
| 31 | 39 | device_rtc_interface::~device_rtc_interface() |
| 32 | 40 | { |
| 33 | 41 | } |
| 42 | |
| 43 | |
| 44 | //------------------------------------------------- |
| 45 | // set_time - called to initialize the RTC to |
| 46 | // a known date/time |
| 47 | //------------------------------------------------- |
| 48 | |
| 49 | void device_rtc_interface::set_time(bool update, int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 50 | { |
| 51 | if (!rtc_feature_y2k()) |
| 52 | { |
| 53 | year %= 100; |
| 54 | } |
| 55 | |
| 56 | set_clock_register(RTC_YEAR, year); |
| 57 | set_clock_register(RTC_MONTH, month); |
| 58 | set_clock_register(RTC_DAY, day); |
| 59 | set_clock_register(RTC_DAY_OF_WEEK, day_of_week); |
| 60 | set_clock_register(RTC_HOUR, hour); |
| 61 | set_clock_register(RTC_MINUTE, minute); |
| 62 | set_clock_register(RTC_SECOND, second); |
| 63 | |
| 64 | if (update) |
| 65 | { |
| 66 | rtc_clock_updated(m_register[RTC_YEAR], m_register[RTC_MONTH], m_register[RTC_DAY], m_register[RTC_DAY_OF_WEEK], |
| 67 | m_register[RTC_HOUR], m_register[RTC_MINUTE], m_register[RTC_SECOND]); |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | |
| 72 | //------------------------------------------------- |
| 73 | // set_current_time - called to initialize the RTC |
| 74 | // to the current system time |
| 75 | //------------------------------------------------- |
| 76 | |
| 77 | void device_rtc_interface::set_current_time(running_machine &machine) |
| 78 | { |
| 79 | system_time systime; |
| 80 | machine.base_datetime(systime); |
| 81 | |
| 82 | set_time(true, systime.local_time.year, systime.local_time.month + 1, systime.local_time.mday, systime.local_time.weekday + 1, |
| 83 | systime.local_time.hour, systime.local_time.minute, systime.local_time.second); |
| 84 | } |
| 85 | |
| 86 | |
| 87 | //------------------------------------------------- |
| 88 | // convert_to_bcd - |
| 89 | //------------------------------------------------- |
| 90 | |
| 91 | UINT8 device_rtc_interface::convert_to_bcd(int val) |
| 92 | { |
| 93 | return ((val / 10) << 4) | (val % 10); |
| 94 | } |
| 95 | |
| 96 | |
| 97 | //------------------------------------------------- |
| 98 | // bcd_to_integer - |
| 99 | //------------------------------------------------- |
| 100 | |
| 101 | int device_rtc_interface::bcd_to_integer(UINT8 val) |
| 102 | { |
| 103 | return (((val & 0xf0) >> 4) * 10) + (val & 0x0f); |
| 104 | } |
| 105 | |
| 106 | |
| 107 | //------------------------------------------------- |
| 108 | // set_clock_register - |
| 109 | //------------------------------------------------- |
| 110 | |
| 111 | void device_rtc_interface::set_clock_register(int reg, int value) |
| 112 | { |
| 113 | m_register[reg] = value; |
| 114 | } |
| 115 | |
| 116 | |
| 117 | //------------------------------------------------- |
| 118 | // get_clock_register - |
| 119 | //------------------------------------------------- |
| 120 | |
| 121 | int device_rtc_interface::get_clock_register(int reg) |
| 122 | { |
| 123 | return m_register[reg]; |
| 124 | } |
| 125 | |
| 126 | |
| 127 | //------------------------------------------------- |
| 128 | // clock_updated - |
| 129 | //------------------------------------------------- |
| 130 | |
| 131 | void device_rtc_interface::clock_updated() |
| 132 | { |
| 133 | rtc_clock_updated(m_register[RTC_YEAR], m_register[RTC_MONTH], m_register[RTC_DAY], m_register[RTC_DAY_OF_WEEK], |
| 134 | m_register[RTC_HOUR], m_register[RTC_MINUTE], m_register[RTC_SECOND]); |
| 135 | } |
| 136 | |
| 137 | |
| 138 | //------------------------------------------------- |
| 139 | // advance_seconds - |
| 140 | //------------------------------------------------- |
| 141 | |
| 142 | void device_rtc_interface::advance_seconds() |
| 143 | { |
| 144 | m_register[RTC_SECOND]++; |
| 145 | |
| 146 | if (m_register[RTC_SECOND] == 60) |
| 147 | { |
| 148 | m_register[RTC_SECOND] = 0; |
| 149 | |
| 150 | advance_minutes(); |
| 151 | } |
| 152 | else |
| 153 | { |
| 154 | clock_updated(); |
| 155 | } |
| 156 | } |
| 157 | |
| 158 | |
| 159 | //------------------------------------------------- |
| 160 | // advance_clock - |
| 161 | //------------------------------------------------- |
| 162 | |
| 163 | void device_rtc_interface::advance_minutes() |
| 164 | { |
| 165 | m_register[RTC_MINUTE]++; |
| 166 | |
| 167 | if (m_register[RTC_MINUTE] == 60) |
| 168 | { |
| 169 | m_register[RTC_MINUTE] = 0; |
| 170 | m_register[RTC_HOUR]++; |
| 171 | } |
| 172 | |
| 173 | if (m_register[RTC_HOUR] == 24) |
| 174 | { |
| 175 | m_register[RTC_HOUR] = 0; |
| 176 | m_register[RTC_DAY]++; |
| 177 | m_register[RTC_DAY_OF_WEEK]++; |
| 178 | } |
| 179 | |
| 180 | if (m_register[RTC_DAY_OF_WEEK] == 8) |
| 181 | { |
| 182 | m_register[RTC_DAY_OF_WEEK] = 1; |
| 183 | } |
| 184 | |
| 185 | if (m_register[RTC_DAY] > DAYS_PER_MONTH[m_register[RTC_MONTH] - 1]) |
| 186 | { |
| 187 | m_register[RTC_DAY] = 1; |
| 188 | m_register[RTC_MONTH]++; |
| 189 | } |
| 190 | |
| 191 | if (m_register[RTC_MONTH] == 13) |
| 192 | { |
| 193 | m_register[RTC_MONTH] = 1; |
| 194 | m_register[RTC_YEAR]++; |
| 195 | |
| 196 | if (!rtc_feature_y2k() && m_register[RTC_YEAR] == 100) |
| 197 | { |
| 198 | m_register[RTC_YEAR] = 0; |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | clock_updated(); |
| 203 | } |
| 204 | |
| 205 | |
| 206 | //------------------------------------------------- |
| 207 | // adjust_seconds - |
| 208 | //------------------------------------------------- |
| 209 | |
| 210 | void device_rtc_interface::adjust_seconds() |
| 211 | { |
| 212 | int seconds = get_clock_register(RTC_SECOND); |
| 213 | |
| 214 | set_clock_register(RTC_SECOND, 0); |
| 215 | |
| 216 | if (seconds >= 30) |
| 217 | { |
| 218 | advance_minutes(); |
| 219 | } |
| 220 | else |
| 221 | { |
| 222 | clock_updated(); |
| 223 | } |
| 224 | } |
src/emu/machine/upd1990a.c
| r15044 | r15045 | |
| 45 | 45 | |
| 46 | 46 | |
| 47 | 47 | //************************************************************************** |
| 48 | | // INLINE HELPERS |
| 49 | | //************************************************************************** |
| 50 | | |
| 51 | | //------------------------------------------------- |
| 52 | | // convert_to_bcd - |
| 53 | | //------------------------------------------------- |
| 54 | | |
| 55 | | inline UINT8 upd1990a_device::convert_to_bcd(int val) |
| 56 | | { |
| 57 | | return ((val / 10) << 4) | (val % 10); |
| 58 | | } |
| 59 | | |
| 60 | | |
| 61 | | //------------------------------------------------- |
| 62 | | // bcd_to_integer - |
| 63 | | //------------------------------------------------- |
| 64 | | |
| 65 | | inline int upd1990a_device::bcd_to_integer(UINT8 val) |
| 66 | | { |
| 67 | | return (((val & 0xf0) >> 4) * 10) + (val & 0x0f); |
| 68 | | } |
| 69 | | |
| 70 | | |
| 71 | | //------------------------------------------------- |
| 72 | | // advance_seconds - |
| 73 | | //------------------------------------------------- |
| 74 | | |
| 75 | | inline void upd1990a_device::advance_seconds() |
| 76 | | { |
| 77 | | static const int days_per_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
| 78 | | |
| 79 | | int seconds = bcd_to_integer(m_time_counter[0]); |
| 80 | | int minutes = bcd_to_integer(m_time_counter[1]); |
| 81 | | int hours = bcd_to_integer(m_time_counter[2]); |
| 82 | | int days = bcd_to_integer(m_time_counter[3]); |
| 83 | | int day_of_week = m_time_counter[4] & 0x0f; |
| 84 | | int month = (m_time_counter[4] & 0xf0) >> 4; |
| 85 | | |
| 86 | | seconds++; |
| 87 | | |
| 88 | | if (seconds > 59) |
| 89 | | { |
| 90 | | seconds = 0; |
| 91 | | minutes++; |
| 92 | | } |
| 93 | | |
| 94 | | if (minutes > 59) |
| 95 | | { |
| 96 | | minutes = 0; |
| 97 | | hours++; |
| 98 | | } |
| 99 | | |
| 100 | | if (hours > 23) |
| 101 | | { |
| 102 | | hours = 0; |
| 103 | | days++; |
| 104 | | day_of_week++; |
| 105 | | } |
| 106 | | |
| 107 | | if (day_of_week > 6) |
| 108 | | { |
| 109 | | day_of_week++; |
| 110 | | } |
| 111 | | |
| 112 | | if (days > days_per_month[month - 1]) |
| 113 | | { |
| 114 | | days = 1; |
| 115 | | month++; |
| 116 | | } |
| 117 | | |
| 118 | | if (month > 12) |
| 119 | | { |
| 120 | | month = 1; |
| 121 | | } |
| 122 | | |
| 123 | | m_time_counter[0] = convert_to_bcd(seconds); |
| 124 | | m_time_counter[1] = convert_to_bcd(minutes); |
| 125 | | m_time_counter[2] = convert_to_bcd(hours); |
| 126 | | m_time_counter[3] = convert_to_bcd(days); |
| 127 | | m_time_counter[4] = (month << 4) | day_of_week; |
| 128 | | } |
| 129 | | |
| 130 | | |
| 131 | | |
| 132 | | //************************************************************************** |
| 133 | 48 | // LIVE DEVICE |
| 134 | 49 | //************************************************************************** |
| 135 | 50 | |
| r15044 | r15045 | |
| 139 | 54 | |
| 140 | 55 | upd1990a_device::upd1990a_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 141 | 56 | : device_t(mconfig, UPD1990A, "uPD1990A", tag, owner, clock), |
| 142 | | device_rtc_interface(mconfig, *this) |
| 57 | device_rtc_interface(mconfig, *this), |
| 58 | m_data_out(0) |
| 143 | 59 | { |
| 144 | 60 | } |
| 145 | 61 | |
| r15044 | r15045 | |
| 203 | 119 | |
| 204 | 120 | void upd1990a_device::device_reset() |
| 205 | 121 | { |
| 206 | | system_time curtime, *systime = &curtime; |
| 207 | | |
| 208 | | machine().current_datetime(curtime); |
| 209 | | |
| 210 | | // HACK: load time counter from system time |
| 211 | | m_time_counter[0] = convert_to_bcd(systime->local_time.second); |
| 212 | | m_time_counter[1] = convert_to_bcd(systime->local_time.minute); |
| 213 | | m_time_counter[2] = convert_to_bcd(systime->local_time.hour); |
| 214 | | m_time_counter[3] = convert_to_bcd(systime->local_time.mday); |
| 215 | | m_time_counter[4] = systime->local_time.weekday; |
| 216 | | m_time_counter[4] |= (systime->local_time.month + 1) << 4; |
| 122 | set_current_time(machine()); |
| 217 | 123 | } |
| 218 | 124 | |
| 219 | 125 | |
| r15044 | r15045 | |
| 249 | 155 | |
| 250 | 156 | |
| 251 | 157 | //------------------------------------------------- |
| 252 | | // rtc_set_time - called to initialize the RTC to |
| 253 | | // a known state |
| 158 | // rtc_clock_updated - |
| 254 | 159 | //------------------------------------------------- |
| 255 | 160 | |
| 256 | | void upd1990a_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 161 | void upd1990a_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 257 | 162 | { |
| 258 | 163 | m_time_counter[0] = convert_to_bcd(second); |
| 259 | 164 | m_time_counter[1] = convert_to_bcd(minute); |
| r15044 | r15045 | |
| 352 | 257 | for (int i = 0; i < 5; i++) |
| 353 | 258 | { |
| 354 | 259 | m_time_counter[i] = m_shift_reg[i]; |
| 260 | |
| 261 | set_time(false, 0, m_time_counter[4] >> 4, m_time_counter[4] & 0x0f, m_time_counter[3], m_time_counter[2], m_time_counter[1], m_time_counter[0]); |
| 355 | 262 | } |
| 356 | 263 | |
| 357 | 264 | /* 32 Hz time pulse */ |
src/emu/machine/rp5c15.c
| r15044 | r15045 | |
| 72 | 72 | }; |
| 73 | 73 | |
| 74 | 74 | |
| 75 | | // days per month |
| 76 | | static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
| 77 | | |
| 78 | | |
| 79 | 75 | // modes |
| 80 | 76 | enum |
| 81 | 77 | { |
| r15044 | r15045 | |
| 160 | 156 | |
| 161 | 157 | |
| 162 | 158 | //------------------------------------------------- |
| 163 | | // advance_seconds - |
| 164 | | //------------------------------------------------- |
| 165 | | |
| 166 | | inline void rp5c15_device::advance_seconds() |
| 167 | | { |
| 168 | | int seconds = read_counter(REGISTER_1_SECOND); |
| 169 | | |
| 170 | | seconds++; |
| 171 | | |
| 172 | | if (seconds > 59) |
| 173 | | { |
| 174 | | seconds = 0; |
| 175 | | |
| 176 | | advance_minutes(); |
| 177 | | } |
| 178 | | |
| 179 | | write_counter(REGISTER_1_SECOND, seconds); |
| 180 | | } |
| 181 | | |
| 182 | | |
| 183 | | //------------------------------------------------- |
| 184 | | // advance_minutes - |
| 185 | | //------------------------------------------------- |
| 186 | | |
| 187 | | inline void rp5c15_device::advance_minutes() |
| 188 | | { |
| 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]; |
| 195 | | |
| 196 | | minutes++; |
| 197 | | |
| 198 | | if (minutes > 59) |
| 199 | | { |
| 200 | | minutes = 0; |
| 201 | | hours++; |
| 202 | | } |
| 203 | | |
| 204 | | if (hours > 23) |
| 205 | | { |
| 206 | | hours = 0; |
| 207 | | days++; |
| 208 | | day_of_week++; |
| 209 | | } |
| 210 | | |
| 211 | | if (day_of_week > 6) |
| 212 | | { |
| 213 | | day_of_week++; |
| 214 | | } |
| 215 | | |
| 216 | | if (days > DAYS_PER_MONTH[month - 1]) |
| 217 | | { |
| 218 | | days = 1; |
| 219 | | month++; |
| 220 | | } |
| 221 | | |
| 222 | | if (month > 12) |
| 223 | | { |
| 224 | | month = 1; |
| 225 | | year++; |
| 226 | | m_reg[MODE01][REGISTER_LEAP_YEAR]++; |
| 227 | | m_reg[MODE01][REGISTER_LEAP_YEAR] &= 0x03; |
| 228 | | } |
| 229 | | |
| 230 | | if (year > 99) |
| 231 | | { |
| 232 | | year = 0; |
| 233 | | } |
| 234 | | |
| 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; |
| 241 | | |
| 242 | | check_alarm(); |
| 243 | | set_alarm_line(); |
| 244 | | } |
| 245 | | |
| 246 | | |
| 247 | | //------------------------------------------------- |
| 248 | | // adjust_seconds - |
| 249 | | //------------------------------------------------- |
| 250 | | |
| 251 | | inline void rp5c15_device::adjust_seconds() |
| 252 | | { |
| 253 | | int seconds = read_counter(REGISTER_1_SECOND); |
| 254 | | |
| 255 | | if (seconds < 30) |
| 256 | | { |
| 257 | | write_counter(REGISTER_1_SECOND, 0); |
| 258 | | } |
| 259 | | else |
| 260 | | { |
| 261 | | write_counter(REGISTER_1_SECOND, 0); |
| 262 | | advance_minutes(); |
| 263 | | } |
| 264 | | } |
| 265 | | |
| 266 | | |
| 267 | | //------------------------------------------------- |
| 268 | 159 | // check_alarm - |
| 269 | 160 | //------------------------------------------------- |
| 270 | 161 | |
| r15044 | r15045 | |
| 359 | 250 | |
| 360 | 251 | |
| 361 | 252 | //------------------------------------------------- |
| 253 | // device_reset - device-specific reset |
| 254 | //------------------------------------------------- |
| 255 | |
| 256 | void rp5c15_device::device_reset() |
| 257 | { |
| 258 | set_current_time(machine()); |
| 259 | } |
| 260 | |
| 261 | |
| 262 | //------------------------------------------------- |
| 362 | 263 | // device_timer - handler timer events |
| 363 | 264 | //------------------------------------------------- |
| 364 | 265 | |
| r15044 | r15045 | |
| 390 | 291 | |
| 391 | 292 | |
| 392 | 293 | //------------------------------------------------- |
| 393 | | // rtc_set_time - called to initialize the RTC to |
| 394 | | // a known state |
| 294 | // rtc_clock_updated - |
| 395 | 295 | //------------------------------------------------- |
| 396 | 296 | |
| 397 | | void rp5c15_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 297 | void rp5c15_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 398 | 298 | { |
| 299 | m_reg[MODE01][REGISTER_LEAP_YEAR] = year % 4; |
| 399 | 300 | write_counter(REGISTER_1_YEAR, year); |
| 400 | 301 | write_counter(REGISTER_1_MONTH, month); |
| 401 | 302 | write_counter(REGISTER_1_DAY, day); |
| r15044 | r15045 | |
| 403 | 304 | write_counter(REGISTER_1_HOUR, hour); |
| 404 | 305 | write_counter(REGISTER_1_MINUTE, minute); |
| 405 | 306 | write_counter(REGISTER_1_SECOND, second); |
| 307 | |
| 308 | check_alarm(); |
| 309 | set_alarm_line(); |
| 406 | 310 | } |
| 407 | 311 | |
| 408 | 312 | |
| r15044 | r15045 | |
| 489 | 393 | { |
| 490 | 394 | case MODE00: |
| 491 | 395 | m_reg[mode][offset & 0x0f] = data & REGISTER_WRITE_MASK[mode][offset & 0x0f]; |
| 396 | |
| 397 | set_time(false, read_counter(REGISTER_1_YEAR), read_counter(REGISTER_1_MONTH), read_counter(REGISTER_1_DAY), m_reg[MODE00][REGISTER_DAY_OF_THE_WEEK], |
| 398 | read_counter(REGISTER_1_HOUR), read_counter(REGISTER_1_MINUTE), read_counter(REGISTER_1_SECOND)); |
| 492 | 399 | break; |
| 493 | 400 | |
| 494 | 401 | case MODE01: |
src/emu/machine/ds1302.c
| r15044 | r15045 | |
| 1 | | /************************************************************ |
| 1 | /********************************************************************** |
| 2 | 2 | |
| 3 | | DALLAS DS1302 |
| 3 | Dallas DS1302 Trickle-Charge Timekeeping Chip emulation |
| 4 | 4 | |
| 5 | | RTC + BACKUP RAM |
| 5 | Copyright MESS Team. |
| 6 | Visit http://mamedev.org for licensing and usage restrictions. |
| 6 | 7 | |
| 8 | **********************************************************************/ |
| 7 | 9 | |
| 10 | /* |
| 8 | 11 | |
| 9 | | Emulation by ElSemi |
| 12 | TODO: |
| 10 | 13 | |
| 14 | - 12 hour format |
| 15 | - synchronize user buffers on falling edge of CE after write |
| 11 | 16 | |
| 12 | | Missing Features: |
| 13 | | - Burst Mode |
| 14 | | - Clock programming (useless) |
| 17 | */ |
| 15 | 18 | |
| 19 | #include "ds1302.h" |
| 16 | 20 | |
| 17 | 21 | |
| 18 | | 2009-05 Converted to be a device |
| 19 | 22 | |
| 20 | | ************************************************************/ |
| 23 | //************************************************************************** |
| 24 | // MACROS / CONSTANTS |
| 25 | //************************************************************************** |
| 21 | 26 | |
| 27 | #define LOG 0 |
| 22 | 28 | |
| 23 | | #include "emu.h" |
| 24 | | #include "ds1302.h" |
| 25 | | #include "devhelpr.h" |
| 26 | 29 | |
| 30 | #define RAM_SIZE 0x1f // 31 bytes |
| 27 | 31 | |
| 28 | | /*************************************************************************** |
| 29 | | INLINE FUNCTIONS |
| 30 | | ***************************************************************************/ |
| 31 | 32 | |
| 32 | | INLINE UINT8 convert_to_bcd(int val) |
| 33 | enum |
| 33 | 34 | { |
| 34 | | return ((val / 10) << 4) | (val % 10); |
| 35 | | } |
| 35 | STATE_COMMAND, |
| 36 | STATE_INPUT, |
| 37 | STATE_OUTPUT |
| 38 | }; |
| 36 | 39 | |
| 40 | enum |
| 41 | { |
| 42 | REGISTER_SECONDS = 0, |
| 43 | REGISTER_MINUTES, |
| 44 | REGISTER_HOUR, |
| 45 | REGISTER_DATE, |
| 46 | REGISTER_MONTH, |
| 47 | REGISTER_DAY, |
| 48 | REGISTER_YEAR, |
| 49 | REGISTER_CONTROL, |
| 50 | REGISTER_TRICKLE |
| 51 | }; |
| 37 | 52 | |
| 38 | | /*************************************************************************** |
| 39 | | IMPLEMENTATION |
| 40 | | ***************************************************************************/ |
| 41 | 53 | |
| 54 | #define COMMAND_READ (m_cmd & 0x01) |
| 55 | #define COMMAND_RAM (m_cmd & 0x40) |
| 56 | #define COMMAND_VALID (m_cmd & 0x80) |
| 57 | #define COMMAND_BURST (((m_cmd >> 1) & 0x1f) == 0x1f) |
| 58 | #define CLOCK_HALT (m_reg[REGISTER_SECONDS] & 0x80) |
| 59 | #define WRITE_PROTECT (m_reg[REGISTER_CONTROL] & 0x80) |
| 60 | #define BURST_END (COMMAND_RAM ? 0x1f : 0x09) |
| 61 | |
| 62 | |
| 63 | |
| 42 | 64 | //************************************************************************** |
| 43 | 65 | // LIVE DEVICE |
| 44 | 66 | //************************************************************************** |
| r15044 | r15045 | |
| 46 | 68 | // device type definition |
| 47 | 69 | const device_type DS1302 = &device_creator<ds1302_device>; |
| 48 | 70 | |
| 71 | |
| 49 | 72 | //------------------------------------------------- |
| 50 | 73 | // ds1302_device - constructor |
| 51 | 74 | //------------------------------------------------- |
| 52 | 75 | |
| 53 | 76 | ds1302_device::ds1302_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 54 | | : device_t(mconfig, DS1302, "Dallas DS1302 RTC", tag, owner, clock) |
| 77 | : device_t(mconfig, DS1302, "Dallas DS1302", tag, owner, clock), |
| 78 | device_rtc_interface(mconfig, *this), |
| 79 | device_nvram_interface(mconfig, *this) |
| 55 | 80 | { |
| 56 | | |
| 57 | 81 | } |
| 58 | 82 | |
| 83 | |
| 59 | 84 | //------------------------------------------------- |
| 60 | 85 | // device_start - device-specific startup |
| 61 | 86 | //------------------------------------------------- |
| 62 | 87 | |
| 63 | 88 | void ds1302_device::device_start() |
| 64 | 89 | { |
| 65 | | save_item(NAME(m_shift_in)); |
| 66 | | save_item(NAME(m_shift_out)); |
| 67 | | save_item(NAME(m_icount)); |
| 68 | | save_item(NAME(m_last_clk)); |
| 69 | | save_item(NAME(m_last_cmd)); |
| 70 | | save_item(NAME(m_sram)); |
| 90 | // allocate timers |
| 91 | m_clock_timer = timer_alloc(); |
| 92 | m_clock_timer->adjust(attotime::from_hz(clock() / 32768), 0, attotime::from_hz(clock() / 32768)); |
| 93 | |
| 94 | for (int i = 0; i < 9; i++) |
| 95 | m_reg[i] = 0; |
| 96 | |
| 97 | // state saving |
| 98 | save_item(NAME(m_ce)); |
| 99 | save_item(NAME(m_clk)); |
| 100 | save_item(NAME(m_io)); |
| 101 | save_item(NAME(m_state)); |
| 102 | save_item(NAME(m_bits)); |
| 103 | save_item(NAME(m_cmd)); |
| 104 | save_item(NAME(m_data)); |
| 105 | save_item(NAME(m_addr)); |
| 106 | save_item(NAME(m_reg)); |
| 107 | save_item(NAME(m_user)); |
| 71 | 108 | } |
| 72 | 109 | |
| 73 | 110 | |
| r15044 | r15045 | |
| 77 | 114 | |
| 78 | 115 | void ds1302_device::device_reset() |
| 79 | 116 | { |
| 80 | | m_shift_in = 0; |
| 81 | | m_shift_out = 0; |
| 82 | | m_icount = 0; |
| 83 | | m_last_clk = 0; |
| 84 | | m_last_cmd = 0; |
| 117 | set_current_time(machine()); |
| 118 | |
| 119 | m_clk = 0; |
| 120 | m_ce = 0; |
| 121 | m_state = STATE_COMMAND; |
| 122 | m_bits = 0; |
| 85 | 123 | } |
| 86 | 124 | |
| 87 | 125 | |
| 88 | | /*------------------------------------------------- |
| 89 | | ds1302_dat_w |
| 90 | | -------------------------------------------------*/ |
| 126 | //------------------------------------------------- |
| 127 | // device_timer - handler timer events |
| 128 | //------------------------------------------------- |
| 91 | 129 | |
| 92 | | WRITE8_DEVICE_HANDLER_TRAMPOLINE(ds1302, ds1302_dat_w) |
| 130 | void ds1302_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) |
| 93 | 131 | { |
| 94 | | if (data) |
| 132 | if (!CLOCK_HALT) |
| 95 | 133 | { |
| 96 | | m_shift_in |= (1 << m_icount); |
| 134 | advance_seconds(); |
| 97 | 135 | } |
| 98 | | else |
| 136 | } |
| 137 | |
| 138 | |
| 139 | //------------------------------------------------- |
| 140 | // nvram_default - called to initialize NVRAM to |
| 141 | // its default state |
| 142 | //------------------------------------------------- |
| 143 | |
| 144 | void ds1302_device::nvram_default() |
| 145 | { |
| 146 | memset(m_ram, 0, RAM_SIZE); |
| 147 | } |
| 148 | |
| 149 | |
| 150 | //------------------------------------------------- |
| 151 | // nvram_read - called to read NVRAM from the |
| 152 | // .nv file |
| 153 | //------------------------------------------------- |
| 154 | |
| 155 | void ds1302_device::nvram_read(emu_file &file) |
| 156 | { |
| 157 | file.read(m_ram, RAM_SIZE); |
| 158 | } |
| 159 | |
| 160 | |
| 161 | //------------------------------------------------- |
| 162 | // nvram_write - called to write NVRAM to the |
| 163 | // .nv file |
| 164 | //------------------------------------------------- |
| 165 | |
| 166 | void ds1302_device::nvram_write(emu_file &file) |
| 167 | { |
| 168 | file.write(m_ram, RAM_SIZE); |
| 169 | } |
| 170 | |
| 171 | |
| 172 | //------------------------------------------------- |
| 173 | // rtc_clock_updated - |
| 174 | //------------------------------------------------- |
| 175 | |
| 176 | void ds1302_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 177 | { |
| 178 | m_reg[REGISTER_YEAR] = convert_to_bcd(year); |
| 179 | m_reg[REGISTER_DAY] = day_of_week; |
| 180 | m_reg[REGISTER_MONTH] = convert_to_bcd(month); |
| 181 | m_reg[REGISTER_DATE] = convert_to_bcd(day); |
| 182 | m_reg[REGISTER_HOUR] = convert_to_bcd(hour); |
| 183 | m_reg[REGISTER_MINUTES] = convert_to_bcd(minute); |
| 184 | m_reg[REGISTER_SECONDS] = (m_reg[REGISTER_SECONDS] & 0x80) | convert_to_bcd(second); |
| 185 | } |
| 186 | |
| 187 | |
| 188 | //------------------------------------------------- |
| 189 | // ce_w - chip enable write |
| 190 | //------------------------------------------------- |
| 191 | |
| 192 | WRITE_LINE_MEMBER( ds1302_device::ce_w ) |
| 193 | { |
| 194 | if (LOG) logerror("DS1302 '%s' CE: %u\n", tag(), state); |
| 195 | |
| 196 | if (!state && m_ce) |
| 99 | 197 | { |
| 100 | | m_shift_in &= ~(1 << m_icount); |
| 198 | // synchronize user buffers |
| 199 | for (int i = 0; i < 9; i++) |
| 200 | { |
| 201 | m_user[i] = m_reg[i]; |
| 202 | } |
| 101 | 203 | } |
| 204 | else if (state && !m_ce) |
| 205 | { |
| 206 | // terminate data transfer |
| 207 | m_state = STATE_COMMAND; |
| 208 | m_bits = 0; |
| 209 | } |
| 210 | |
| 211 | m_ce = state; |
| 102 | 212 | } |
| 103 | 213 | |
| 104 | 214 | |
| 105 | | /*------------------------------------------------- |
| 106 | | ds1302_clk_w |
| 107 | | -------------------------------------------------*/ |
| 215 | //------------------------------------------------- |
| 216 | // load_shift_register - |
| 217 | //------------------------------------------------- |
| 108 | 218 | |
| 109 | | WRITE8_DEVICE_HANDLER_TRAMPOLINE(ds1302, ds1302_clk_w) |
| 219 | void ds1302_device::load_shift_register() |
| 110 | 220 | { |
| 111 | | if (data != m_last_clk) |
| 221 | if (COMMAND_READ) |
| 112 | 222 | { |
| 113 | | if (data) //Rising, shift in command |
| 223 | if (COMMAND_RAM) |
| 114 | 224 | { |
| 115 | | m_icount++; |
| 116 | | if(m_icount == 8) //Command start |
| 117 | | { |
| 118 | | system_time systime; |
| 119 | | machine().base_datetime(systime); |
| 225 | m_data = m_ram[m_addr]; |
| 120 | 226 | |
| 121 | | switch(m_shift_in) |
| 122 | | { |
| 123 | | case 0x81: //Sec |
| 124 | | m_shift_out = convert_to_bcd(systime.local_time.second); |
| 125 | | break; |
| 227 | if (LOG) logerror("DS1302 '%s' Read RAM %u:%02x\n", tag(), m_addr, m_data); |
| 228 | } |
| 229 | else |
| 230 | { |
| 231 | m_data = m_user[m_addr]; |
| 126 | 232 | |
| 127 | | case 0x83: //Min |
| 128 | | m_shift_out = convert_to_bcd(systime.local_time.minute); |
| 129 | | break; |
| 233 | if (LOG) logerror("DS1302 '%s' Read Clock %u:%02x\n", tag(), m_addr, m_data); |
| 234 | } |
| 235 | } |
| 236 | else |
| 237 | { |
| 238 | if (COMMAND_RAM) |
| 239 | { |
| 240 | if (LOG) logerror("DS1302 '%s' Write RAM %u:%02x\n", tag(), m_addr, m_data); |
| 130 | 241 | |
| 131 | | case 0x85: //Hour |
| 132 | | m_shift_out = convert_to_bcd(systime.local_time.hour); |
| 133 | | break; |
| 242 | m_ram[m_addr] = m_data; |
| 243 | } |
| 244 | else if (m_addr < 9) |
| 245 | { |
| 246 | if (LOG) logerror("DS1302 '%s' Write Clock %u:%02x\n", tag(), m_addr, m_data); |
| 134 | 247 | |
| 135 | | case 0x87: //Day |
| 136 | | m_shift_out = convert_to_bcd(systime.local_time.mday); |
| 137 | | break; |
| 248 | m_reg[m_addr] = m_data; |
| 249 | } |
| 250 | } |
| 251 | } |
| 138 | 252 | |
| 139 | | case 0x89: //Month |
| 140 | | m_shift_out = convert_to_bcd(systime.local_time.month + 1); |
| 141 | | break; |
| 142 | 253 | |
| 143 | | case 0x8b: //weekday |
| 144 | | m_shift_out = convert_to_bcd(systime.local_time.weekday); |
| 145 | | break; |
| 254 | //------------------------------------------------- |
| 255 | // input_bit - |
| 256 | //------------------------------------------------- |
| 146 | 257 | |
| 147 | | case 0x8d: //Year |
| 148 | | m_shift_out = convert_to_bcd(systime.local_time.year % 100); |
| 149 | | break; |
| 258 | void ds1302_device::input_bit() |
| 259 | { |
| 260 | switch (m_state) |
| 261 | { |
| 262 | case STATE_COMMAND: |
| 263 | m_cmd >>= 1; |
| 264 | m_cmd |= (m_io << 7); |
| 265 | m_bits++; |
| 150 | 266 | |
| 151 | | default: |
| 152 | | m_shift_out = 0x0; |
| 267 | if (m_bits == 8) |
| 268 | { |
| 269 | if (LOG) logerror("DS1302 '%s' Command: %02x\n", tag(), m_cmd); |
| 270 | |
| 271 | m_bits = 0; |
| 272 | m_addr = (m_cmd >> 1) & 0x1f; |
| 273 | |
| 274 | if (COMMAND_VALID) |
| 275 | { |
| 276 | if (COMMAND_BURST) |
| 277 | { |
| 278 | m_addr = 0; |
| 153 | 279 | } |
| 154 | 280 | |
| 155 | | if(m_shift_in > 0xc0) |
| 281 | if (COMMAND_READ) |
| 156 | 282 | { |
| 157 | | m_shift_out = m_sram[(m_shift_in >> 1) & 0x1f]; |
| 283 | load_shift_register(); |
| 284 | |
| 285 | m_state = STATE_OUTPUT; |
| 158 | 286 | } |
| 159 | | m_last_cmd = m_shift_in & 0xff; |
| 160 | | m_icount++; |
| 287 | else |
| 288 | { |
| 289 | m_state = STATE_INPUT; |
| 290 | } |
| 161 | 291 | } |
| 162 | | |
| 163 | | if(m_icount == 17 && !(m_last_cmd & 1)) |
| 292 | else |
| 164 | 293 | { |
| 165 | | UINT8 val = (m_shift_in >> 9) & 0xff; |
| 294 | m_state = STATE_COMMAND; |
| 295 | } |
| 296 | } |
| 297 | break; |
| 166 | 298 | |
| 167 | | switch(m_last_cmd) |
| 168 | | { |
| 169 | | case 0x80: //Sec |
| 170 | | break; |
| 299 | case STATE_INPUT: |
| 300 | m_data >>= 1; |
| 301 | m_data |= (m_io << 7); |
| 302 | m_bits++; |
| 171 | 303 | |
| 172 | | case 0x82: //Min |
| 173 | | break; |
| 304 | if (m_bits == 8) |
| 305 | { |
| 306 | if (LOG) logerror("DS1302 '%s' Data: %02x\n", tag(), m_data); |
| 174 | 307 | |
| 175 | | case 0x84: //Hour |
| 176 | | break; |
| 308 | m_bits = 0; |
| 177 | 309 | |
| 178 | | case 0x86: //Day |
| 179 | | break; |
| 310 | if (!WRITE_PROTECT) |
| 311 | { |
| 312 | load_shift_register(); |
| 313 | } |
| 180 | 314 | |
| 181 | | case 0x88: //Month |
| 182 | | break; |
| 315 | if (COMMAND_BURST) |
| 316 | { |
| 317 | m_addr++; |
| 183 | 318 | |
| 184 | | case 0x8a: //weekday |
| 185 | | break; |
| 319 | if (m_addr == BURST_END) |
| 320 | { |
| 321 | m_state = STATE_COMMAND; |
| 322 | } |
| 323 | } |
| 324 | else |
| 325 | { |
| 326 | m_state = STATE_COMMAND; |
| 327 | } |
| 328 | } |
| 329 | break; |
| 330 | } |
| 331 | } |
| 186 | 332 | |
| 187 | | case 0x8c: //Year |
| 188 | | break; |
| 189 | 333 | |
| 190 | | default: |
| 191 | | m_shift_out = 0x0; |
| 192 | | } |
| 334 | //------------------------------------------------- |
| 335 | // output_bit - |
| 336 | //------------------------------------------------- |
| 193 | 337 | |
| 194 | | if(m_last_cmd > 0xc0) |
| 195 | | { |
| 196 | | m_sram[(m_last_cmd >> 1) & 0x1f] = val; |
| 197 | | } |
| 338 | void ds1302_device::output_bit() |
| 339 | { |
| 340 | if (m_state != STATE_OUTPUT) return; |
| 198 | 341 | |
| 342 | m_io = BIT(m_data, 0); |
| 343 | m_data >>= 1; |
| 344 | m_bits++; |
| 199 | 345 | |
| 346 | if (m_bits == 8) |
| 347 | { |
| 348 | m_bits = 0; |
| 200 | 349 | |
| 350 | if (COMMAND_BURST) |
| 351 | { |
| 352 | m_addr++; |
| 353 | |
| 354 | if (m_addr == BURST_END) |
| 355 | { |
| 356 | m_state = STATE_COMMAND; |
| 201 | 357 | } |
| 358 | else |
| 359 | { |
| 360 | load_shift_register(); |
| 361 | } |
| 202 | 362 | } |
| 363 | else |
| 364 | { |
| 365 | m_state = STATE_COMMAND; |
| 366 | } |
| 203 | 367 | } |
| 204 | | m_last_clk = data; |
| 205 | 368 | } |
| 206 | 369 | |
| 207 | 370 | |
| 208 | | /*------------------------------------------------- |
| 209 | | ds1302_read |
| 210 | | -------------------------------------------------*/ |
| 371 | //------------------------------------------------- |
| 372 | // sclk_w - serial clock write |
| 373 | //------------------------------------------------- |
| 211 | 374 | |
| 212 | | READ8_DEVICE_HANDLER_TRAMPOLINE(ds1302, ds1302_read) |
| 375 | WRITE_LINE_MEMBER( ds1302_device::sclk_w ) |
| 213 | 376 | { |
| 214 | | return (m_shift_out & (1 << (m_icount - 9))) ? 1 : 0; |
| 377 | if (LOG) logerror("DS1302 '%s' CLK: %u\n", tag(), state); |
| 378 | |
| 379 | if (!m_ce) return; |
| 380 | |
| 381 | if (!m_clk && state) // rising edge |
| 382 | { |
| 383 | input_bit(); |
| 384 | } |
| 385 | else if (m_clk && !state) // falling edge |
| 386 | { |
| 387 | output_bit(); |
| 388 | } |
| 389 | |
| 390 | m_clk = state; |
| 215 | 391 | } |
| 392 | |
| 393 | |
| 394 | //------------------------------------------------- |
| 395 | // io_w - I/O write |
| 396 | //------------------------------------------------- |
| 397 | |
| 398 | WRITE_LINE_MEMBER( ds1302_device::io_w ) |
| 399 | { |
| 400 | if (LOG) logerror("DS1302 '%s' I/O: %u\n", tag(), state); |
| 401 | |
| 402 | m_io = state; |
| 403 | } |
| 404 | |
| 405 | |
| 406 | //------------------------------------------------- |
| 407 | // io_r - I/O read |
| 408 | //------------------------------------------------- |
| 409 | |
| 410 | READ_LINE_MEMBER( ds1302_device::io_r ) |
| 411 | { |
| 412 | return m_io; |
| 413 | } |
src/emu/machine/ds1302.h
| r15044 | r15045 | |
| 1 | 1 | /********************************************************************** |
| 2 | 2 | |
| 3 | | DALLAS DS1302 |
| 3 | Dallas DS1302 Trickle-Charge Timekeeping Chip emulation |
| 4 | 4 | |
| 5 | | RTC + BACKUP RAM |
| 5 | Copyright MESS Team. |
| 6 | Visit http://mamedev.org for licensing and usage restrictions. |
| 6 | 7 | |
| 8 | ********************************************************************** |
| 9 | _____ _____ |
| 10 | Vcc2 1 |* \_/ | 8 Vcc1 |
| 11 | X1 2 | | 7 SCLK |
| 12 | X2 3 | | 6 I/O |
| 13 | GND 4 |_____________| 5 CE |
| 14 | |
| 7 | 15 | **********************************************************************/ |
| 8 | 16 | |
| 9 | 17 | #pragma once |
| r15044 | r15045 | |
| 15 | 23 | |
| 16 | 24 | |
| 17 | 25 | |
| 18 | | /*************************************************************************** |
| 19 | | DEVICE CONFIGURATION MACROS |
| 20 | | ***************************************************************************/ |
| 26 | //************************************************************************** |
| 27 | // INTERFACE CONFIGURATION MACROS |
| 28 | //************************************************************************** |
| 21 | 29 | |
| 22 | | #define MCFG_DS1302_ADD(_tag) \ |
| 23 | | MCFG_DEVICE_ADD(_tag, DS1302, 0) |
| 30 | #define MCFG_DS1302_ADD(_tag, _clock) \ |
| 31 | MCFG_DEVICE_ADD(_tag, DS1302, _clock) |
| 24 | 32 | |
| 25 | 33 | |
| 26 | | /*************************************************************************** |
| 27 | | TYPE DEFINITIONS |
| 28 | | ***************************************************************************/ |
| 29 | 34 | |
| 35 | //************************************************************************** |
| 36 | // TYPE DEFINITIONS |
| 37 | //************************************************************************** |
| 30 | 38 | |
| 31 | 39 | // ======================> ds1302_device |
| 32 | 40 | |
| 33 | | class ds1302_device : public device_t |
| 41 | class ds1302_device : public device_t, |
| 42 | public device_rtc_interface, |
| 43 | public device_nvram_interface |
| 34 | 44 | { |
| 35 | 45 | public: |
| 36 | 46 | // construction/destruction |
| 37 | 47 | ds1302_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 38 | 48 | |
| 39 | | void ds1302_dat_w(UINT32 offset, UINT8 data); |
| 40 | | void ds1302_clk_w(UINT32 offset, UINT8 data); |
| 41 | | UINT8 ds1302_read(UINT32 offset); |
| 49 | DECLARE_WRITE_LINE_MEMBER( ce_w ); |
| 50 | DECLARE_WRITE_LINE_MEMBER( sclk_w ); |
| 51 | DECLARE_WRITE_LINE_MEMBER( io_w ); |
| 52 | DECLARE_READ_LINE_MEMBER( io_r ); |
| 42 | 53 | |
| 43 | 54 | protected: |
| 44 | 55 | // device-level overrides |
| 45 | 56 | virtual void device_start(); |
| 46 | 57 | virtual void device_reset(); |
| 47 | | virtual void device_post_load() { } |
| 48 | | virtual void device_clock_changed() { } |
| 58 | virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); |
| 49 | 59 | |
| 60 | // device_nvram_interface overrides |
| 61 | virtual void nvram_default(); |
| 62 | virtual void nvram_read(emu_file &file); |
| 63 | virtual void nvram_write(emu_file &file); |
| 64 | |
| 65 | // device_rtc_interface overrides |
| 66 | virtual void rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second); |
| 67 | virtual bool rtc_feature_leap_year() { return true; } |
| 68 | |
| 50 | 69 | private: |
| 70 | void load_shift_register(); |
| 71 | void input_bit(); |
| 72 | void output_bit(); |
| 51 | 73 | |
| 52 | | UINT32 m_shift_in; |
| 53 | | UINT8 m_shift_out; |
| 54 | | UINT8 m_icount; |
| 55 | | UINT8 m_last_clk; |
| 56 | | UINT8 m_last_cmd; |
| 57 | | UINT8 m_sram[0x20]; |
| 74 | int m_ce; |
| 75 | int m_clk; |
| 76 | int m_io; |
| 77 | int m_state; |
| 78 | int m_bits; |
| 79 | UINT8 m_cmd; |
| 80 | UINT8 m_data; |
| 81 | int m_addr; |
| 82 | |
| 83 | UINT8 m_reg[9]; |
| 84 | UINT8 m_user[9]; |
| 85 | UINT8 m_ram[0x20]; |
| 86 | |
| 87 | // timers |
| 88 | emu_timer *m_clock_timer; |
| 58 | 89 | }; |
| 59 | 90 | |
| 60 | 91 | |
| r15044 | r15045 | |
| 63 | 94 | |
| 64 | 95 | |
| 65 | 96 | |
| 66 | | /*************************************************************************** |
| 67 | | PROTOTYPES |
| 68 | | ***************************************************************************/ |
| 69 | | |
| 70 | | extern WRITE8_DEVICE_HANDLER( ds1302_dat_w ); |
| 71 | | extern WRITE8_DEVICE_HANDLER( ds1302_clk_w ); |
| 72 | | extern READ8_DEVICE_HANDLER( ds1302_read ); |
| 73 | | |
| 74 | | |
| 75 | | #endif /* __DS1302_H__ */ |
| 97 | #endif |
src/emu/machine/msm5832.c
| r15044 | r15045 | |
| 53 | 53 | }; |
| 54 | 54 | |
| 55 | 55 | |
| 56 | | // days per month |
| 57 | | static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
| 58 | 56 | |
| 59 | | |
| 60 | | |
| 61 | 57 | //************************************************************************** |
| 62 | 58 | // INLINE HELPERS |
| 63 | 59 | //************************************************************************** |
| r15044 | r15045 | |
| 83 | 79 | } |
| 84 | 80 | |
| 85 | 81 | |
| 86 | | //------------------------------------------------- |
| 87 | | // advance_seconds - |
| 88 | | //------------------------------------------------- |
| 89 | 82 | |
| 90 | | inline void msm5832_device::advance_seconds() |
| 91 | | { |
| 92 | | int seconds = read_counter(REGISTER_S1); |
| 93 | | |
| 94 | | seconds++; |
| 95 | | |
| 96 | | if (seconds > 59) |
| 97 | | { |
| 98 | | seconds = 0; |
| 99 | | |
| 100 | | advance_minutes(); |
| 101 | | } |
| 102 | | |
| 103 | | write_counter(REGISTER_S1, seconds); |
| 104 | | } |
| 105 | | |
| 106 | | |
| 107 | | //------------------------------------------------- |
| 108 | | // advance_minutes - |
| 109 | | //------------------------------------------------- |
| 110 | | |
| 111 | | inline void msm5832_device::advance_minutes() |
| 112 | | { |
| 113 | | int minutes = read_counter(REGISTER_MI1); |
| 114 | | int hours = read_counter(REGISTER_H1); |
| 115 | | int days = read_counter(REGISTER_D1); |
| 116 | | int month = read_counter(REGISTER_MO1); |
| 117 | | int year = read_counter(REGISTER_Y1); |
| 118 | | int day_of_week = m_reg[REGISTER_W]; |
| 119 | | |
| 120 | | minutes++; |
| 121 | | |
| 122 | | if (minutes > 59) |
| 123 | | { |
| 124 | | minutes = 0; |
| 125 | | hours++; |
| 126 | | } |
| 127 | | |
| 128 | | if (hours > 23) |
| 129 | | { |
| 130 | | hours = 0; |
| 131 | | days++; |
| 132 | | day_of_week++; |
| 133 | | } |
| 134 | | |
| 135 | | if (day_of_week > 6) |
| 136 | | { |
| 137 | | day_of_week++; |
| 138 | | } |
| 139 | | |
| 140 | | if (days > DAYS_PER_MONTH[month - 1]) |
| 141 | | { |
| 142 | | days = 1; |
| 143 | | month++; |
| 144 | | } |
| 145 | | |
| 146 | | if (month > 12) |
| 147 | | { |
| 148 | | month = 1; |
| 149 | | year++; |
| 150 | | } |
| 151 | | |
| 152 | | if (year > 99) |
| 153 | | { |
| 154 | | year = 0; |
| 155 | | } |
| 156 | | |
| 157 | | write_counter(REGISTER_MI1, minutes); |
| 158 | | write_counter(REGISTER_H1, hours); |
| 159 | | write_counter(REGISTER_D1, days); |
| 160 | | write_counter(REGISTER_MO1, month); |
| 161 | | write_counter(REGISTER_Y1, year); |
| 162 | | m_reg[REGISTER_W] = day_of_week; |
| 163 | | } |
| 164 | | |
| 165 | | |
| 166 | | |
| 167 | 83 | //************************************************************************** |
| 168 | 84 | // LIVE DEVICE |
| 169 | 85 | //************************************************************************** |
| r15044 | r15045 | |
| 207 | 123 | |
| 208 | 124 | |
| 209 | 125 | //------------------------------------------------- |
| 126 | // device_reset - device-specific reset |
| 127 | //------------------------------------------------- |
| 128 | |
| 129 | void msm5832_device::device_reset() |
| 130 | { |
| 131 | set_current_time(machine()); |
| 132 | } |
| 133 | |
| 134 | |
| 135 | //------------------------------------------------- |
| 210 | 136 | // device_timer - handler timer events |
| 211 | 137 | //------------------------------------------------- |
| 212 | 138 | |
| r15044 | r15045 | |
| 225 | 151 | |
| 226 | 152 | |
| 227 | 153 | //------------------------------------------------- |
| 228 | | // rtc_set_time - called to initialize the RTC to |
| 229 | | // a known state |
| 154 | // rtc_clock_updated - |
| 230 | 155 | //------------------------------------------------- |
| 231 | 156 | |
| 232 | | void msm5832_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 157 | void msm5832_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 233 | 158 | { |
| 234 | 159 | write_counter(REGISTER_Y1, year); |
| 235 | 160 | write_counter(REGISTER_MO1, month); |
| r15044 | r15045 | |
| 278 | 203 | if (m_cs && m_write) |
| 279 | 204 | { |
| 280 | 205 | m_reg[m_address] = data & 0x0f; |
| 206 | |
| 207 | set_time(false, read_counter(REGISTER_Y1), read_counter(REGISTER_MO1), read_counter(REGISTER_D1), m_reg[REGISTER_W], |
| 208 | read_counter(REGISTER_H1), read_counter(REGISTER_MI1), read_counter(REGISTER_S1)); |
| 281 | 209 | } |
| 282 | 210 | } |
| 283 | 211 | |
| r15044 | r15045 | |
| 304 | 232 | |
| 305 | 233 | if (state) |
| 306 | 234 | { |
| 307 | | int seconds = read_counter(REGISTER_S1); |
| 308 | | |
| 309 | | if (seconds < 30) |
| 310 | | { |
| 311 | | write_counter(REGISTER_S1, 0); |
| 312 | | } |
| 313 | | else |
| 314 | | { |
| 315 | | write_counter(REGISTER_S1, 0); |
| 316 | | advance_minutes(); |
| 317 | | } |
| 235 | adjust_seconds(); |
| 318 | 236 | } |
| 319 | 237 | } |
| 320 | 238 | |
src/emu/machine/e0516.c
| r15044 | r15045 | |
| 1 | 1 | /********************************************************************** |
| 2 | 2 | |
| 3 | | E05-16 Real Time Clock emulation |
| 3 | Microelectronic-Marin E050-16 Real Time Clock emulation |
| 4 | 4 | |
| 5 | 5 | Copyright MESS Team. |
| 6 | 6 | Visit http://mamedev.org for licensing and usage restrictions. |
| r15044 | r15045 | |
| 27 | 27 | }; |
| 28 | 28 | |
| 29 | 29 | |
| 30 | | // registers |
| 31 | | enum |
| 32 | | { |
| 33 | | SECOND = 0, |
| 34 | | MINUTE, |
| 35 | | HOUR, |
| 36 | | DAY, |
| 37 | | MONTH, |
| 38 | | DAY_OF_WEEK, |
| 39 | | YEAR, |
| 40 | | ALL |
| 41 | | }; |
| 42 | 30 | |
| 43 | | |
| 44 | 31 | //************************************************************************** |
| 45 | | // INLINE HELPERS |
| 46 | | //************************************************************************** |
| 47 | | |
| 48 | | //------------------------------------------------- |
| 49 | | // advance_seconds - |
| 50 | | //------------------------------------------------- |
| 51 | | |
| 52 | | inline void e0516_device::advance_seconds() |
| 53 | | { |
| 54 | | m_register[SECOND]++; |
| 55 | | |
| 56 | | if (m_register[SECOND] == 60) |
| 57 | | { |
| 58 | | m_register[SECOND] = 0; |
| 59 | | m_register[MINUTE]++; |
| 60 | | } |
| 61 | | |
| 62 | | if (m_register[MINUTE] == 60) |
| 63 | | { |
| 64 | | m_register[MINUTE] = 0; |
| 65 | | m_register[HOUR]++; |
| 66 | | } |
| 67 | | |
| 68 | | if (m_register[HOUR] == 24) |
| 69 | | { |
| 70 | | m_register[HOUR] = 0; |
| 71 | | m_register[DAY]++; |
| 72 | | m_register[DAY_OF_WEEK]++; |
| 73 | | } |
| 74 | | |
| 75 | | if (m_register[DAY_OF_WEEK] == 8) |
| 76 | | { |
| 77 | | m_register[DAY_OF_WEEK] = 1; |
| 78 | | } |
| 79 | | |
| 80 | | if (m_register[DAY] == 32) |
| 81 | | { |
| 82 | | m_register[DAY] = 1; |
| 83 | | m_register[MONTH]++; |
| 84 | | } |
| 85 | | |
| 86 | | if (m_register[MONTH] == 13) |
| 87 | | { |
| 88 | | m_register[MONTH] = 1; |
| 89 | | m_register[YEAR]++; |
| 90 | | } |
| 91 | | } |
| 92 | | |
| 93 | | |
| 94 | | |
| 95 | | //************************************************************************** |
| 96 | 32 | // LIVE DEVICE |
| 97 | 33 | //************************************************************************** |
| 98 | 34 | |
| r15044 | r15045 | |
| 129 | 65 | save_item(NAME(m_state)); |
| 130 | 66 | save_item(NAME(m_bits)); |
| 131 | 67 | save_item(NAME(m_dio)); |
| 132 | | save_item(NAME(m_register)); |
| 133 | 68 | } |
| 134 | 69 | |
| 135 | 70 | |
| 136 | 71 | //------------------------------------------------- |
| 137 | | // device_start - device-specific reset |
| 72 | // device_reset - device-specific reset |
| 138 | 73 | //------------------------------------------------- |
| 139 | 74 | |
| 140 | 75 | void e0516_device::device_reset() |
| 141 | 76 | { |
| 77 | set_current_time(machine()); |
| 142 | 78 | } |
| 143 | 79 | |
| 144 | 80 | |
| r15044 | r15045 | |
| 153 | 89 | |
| 154 | 90 | |
| 155 | 91 | //------------------------------------------------- |
| 156 | | // rtc_set_time - called to initialize the RTC to |
| 157 | | // a known state |
| 158 | | //------------------------------------------------- |
| 159 | | |
| 160 | | void e0516_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 161 | | { |
| 162 | | m_register[YEAR] = year; |
| 163 | | m_register[MONTH] = month; |
| 164 | | m_register[DAY] = day; |
| 165 | | m_register[DAY_OF_WEEK] = day_of_week + 1; |
| 166 | | m_register[HOUR] = hour; |
| 167 | | m_register[MINUTE] = minute; |
| 168 | | m_register[SECOND] = second; |
| 169 | | } |
| 170 | | |
| 171 | | |
| 172 | | //------------------------------------------------- |
| 173 | 92 | // cs_w - chip select input |
| 174 | 93 | //------------------------------------------------- |
| 175 | 94 | |
| 176 | 95 | WRITE_LINE_MEMBER( e0516_device::cs_w ) |
| 177 | 96 | { |
| 97 | if (LOG) logerror("E05-16 '%s' CS %u\n", tag(), state); |
| 98 | |
| 178 | 99 | m_cs = state; |
| 179 | 100 | |
| 180 | 101 | if (m_cs) |
| r15044 | r15045 | |
| 193 | 114 | |
| 194 | 115 | WRITE_LINE_MEMBER( e0516_device::clk_w ) |
| 195 | 116 | { |
| 117 | if (LOG) logerror("E05-16 '%s' CLK %u\n", tag(), state); |
| 118 | |
| 196 | 119 | m_clk = state; |
| 197 | 120 | |
| 198 | 121 | if (m_cs || m_clk) return; |
| r15044 | r15045 | |
| 215 | 138 | if (BIT(m_reg_latch, 0)) |
| 216 | 139 | { |
| 217 | 140 | // load register value to data latch |
| 218 | | m_data_latch = m_register[m_reg_latch >> 1]; |
| 141 | m_data_latch = convert_to_bcd(get_clock_register(m_reg_latch >> 1)); |
| 219 | 142 | } |
| 220 | 143 | } |
| 221 | 144 | } |
| r15044 | r15045 | |
| 247 | 170 | if (!BIT(m_reg_latch, 0)) |
| 248 | 171 | { |
| 249 | 172 | // write latched data to register |
| 250 | | m_register[m_reg_latch >> 1] = m_data_latch; |
| 173 | set_clock_register(m_reg_latch >> 1, bcd_to_integer(m_data_latch)); |
| 251 | 174 | } |
| 252 | 175 | } |
| 253 | 176 | } |
| r15044 | r15045 | |
| 260 | 183 | |
| 261 | 184 | WRITE_LINE_MEMBER( e0516_device::dio_w ) |
| 262 | 185 | { |
| 186 | if (LOG) logerror("E05-16 '%s' DIO %u\n", tag(), state); |
| 187 | |
| 263 | 188 | m_dio = state; |
| 264 | 189 | } |
| 265 | 190 | |
src/emu/machine/rp5c01.c
| r15044 | r15045 | |
| 145 | 145 | |
| 146 | 146 | |
| 147 | 147 | //------------------------------------------------- |
| 148 | | // advance_seconds - |
| 149 | | //------------------------------------------------- |
| 150 | | |
| 151 | | inline void rp5c01_device::advance_seconds() |
| 152 | | { |
| 153 | | int seconds = read_counter(REGISTER_1_SECOND); |
| 154 | | |
| 155 | | seconds++; |
| 156 | | |
| 157 | | if (seconds > 59) |
| 158 | | { |
| 159 | | seconds = 0; |
| 160 | | |
| 161 | | advance_minutes(); |
| 162 | | } |
| 163 | | |
| 164 | | write_counter(REGISTER_1_SECOND, seconds); |
| 165 | | } |
| 166 | | |
| 167 | | |
| 168 | | //------------------------------------------------- |
| 169 | | // advance_minutes - |
| 170 | | //------------------------------------------------- |
| 171 | | |
| 172 | | inline void rp5c01_device::advance_minutes() |
| 173 | | { |
| 174 | | int minutes = read_counter(REGISTER_1_MINUTE); |
| 175 | | int hours = read_counter(REGISTER_1_HOUR); |
| 176 | | int days = read_counter(REGISTER_1_DAY); |
| 177 | | int month = read_counter(REGISTER_1_MONTH); |
| 178 | | int year = read_counter(REGISTER_1_YEAR); |
| 179 | | int day_of_week = m_reg[MODE00][REGISTER_DAY_OF_THE_WEEK]; |
| 180 | | |
| 181 | | minutes++; |
| 182 | | |
| 183 | | if (minutes > 59) |
| 184 | | { |
| 185 | | minutes = 0; |
| 186 | | hours++; |
| 187 | | } |
| 188 | | |
| 189 | | if (hours > 23) |
| 190 | | { |
| 191 | | hours = 0; |
| 192 | | days++; |
| 193 | | day_of_week++; |
| 194 | | } |
| 195 | | |
| 196 | | if (day_of_week > 6) |
| 197 | | { |
| 198 | | day_of_week++; |
| 199 | | } |
| 200 | | |
| 201 | | if (days > DAYS_PER_MONTH[month - 1]) |
| 202 | | { |
| 203 | | days = 1; |
| 204 | | month++; |
| 205 | | } |
| 206 | | |
| 207 | | if (month > 12) |
| 208 | | { |
| 209 | | month = 1; |
| 210 | | year++; |
| 211 | | m_reg[MODE01][REGISTER_LEAP_YEAR]++; |
| 212 | | m_reg[MODE01][REGISTER_LEAP_YEAR] &= 0x03; |
| 213 | | } |
| 214 | | |
| 215 | | if (year > 99) |
| 216 | | { |
| 217 | | year = 0; |
| 218 | | } |
| 219 | | |
| 220 | | write_counter(REGISTER_1_MINUTE, minutes); |
| 221 | | write_counter(REGISTER_1_HOUR, hours); |
| 222 | | write_counter(REGISTER_1_DAY, days); |
| 223 | | write_counter(REGISTER_1_MONTH, month); |
| 224 | | write_counter(REGISTER_1_YEAR, year); |
| 225 | | m_reg[MODE00][REGISTER_DAY_OF_THE_WEEK] = day_of_week; |
| 226 | | |
| 227 | | check_alarm(); |
| 228 | | set_alarm_line(); |
| 229 | | } |
| 230 | | |
| 231 | | |
| 232 | | //------------------------------------------------- |
| 233 | | // adjust_seconds - |
| 234 | | //------------------------------------------------- |
| 235 | | |
| 236 | | inline void rp5c01_device::adjust_seconds() |
| 237 | | { |
| 238 | | int seconds = read_counter(REGISTER_1_SECOND); |
| 239 | | |
| 240 | | if (seconds < 30) |
| 241 | | { |
| 242 | | write_counter(REGISTER_1_SECOND, 0); |
| 243 | | } |
| 244 | | else |
| 245 | | { |
| 246 | | write_counter(REGISTER_1_SECOND, 0); |
| 247 | | advance_minutes(); |
| 248 | | } |
| 249 | | } |
| 250 | | |
| 251 | | |
| 252 | | //------------------------------------------------- |
| 253 | 148 | // check_alarm - |
| 254 | 149 | //------------------------------------------------- |
| 255 | 150 | |
| r15044 | r15045 | |
| 339 | 234 | |
| 340 | 235 | |
| 341 | 236 | //------------------------------------------------- |
| 237 | // device_reset - device-specific reset |
| 238 | //------------------------------------------------- |
| 239 | |
| 240 | void rp5c01_device::device_reset() |
| 241 | { |
| 242 | set_current_time(machine()); |
| 243 | } |
| 244 | |
| 245 | |
| 246 | //------------------------------------------------- |
| 342 | 247 | // device_timer - handler timer events |
| 343 | 248 | //------------------------------------------------- |
| 344 | 249 | |
| r15044 | r15045 | |
| 365 | 270 | |
| 366 | 271 | |
| 367 | 272 | //------------------------------------------------- |
| 368 | | // rtc_set_time - called to initialize the RTC to |
| 369 | | // a known state |
| 273 | // rtc_clock_updated - |
| 370 | 274 | //------------------------------------------------- |
| 371 | 275 | |
| 372 | | void rp5c01_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 276 | void rp5c01_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 373 | 277 | { |
| 278 | m_reg[MODE01][REGISTER_LEAP_YEAR] = year % 4; |
| 374 | 279 | write_counter(REGISTER_1_YEAR, year); |
| 375 | 280 | write_counter(REGISTER_1_MONTH, month); |
| 376 | 281 | write_counter(REGISTER_1_DAY, day); |
| r15044 | r15045 | |
| 378 | 283 | write_counter(REGISTER_1_HOUR, hour); |
| 379 | 284 | write_counter(REGISTER_1_MINUTE, minute); |
| 380 | 285 | write_counter(REGISTER_1_SECOND, second); |
| 286 | |
| 287 | check_alarm(); |
| 288 | set_alarm_line(); |
| 381 | 289 | } |
| 382 | 290 | |
| 383 | 291 | |
| r15044 | r15045 | |
| 510 | 418 | case MODE00: |
| 511 | 419 | case MODE01: |
| 512 | 420 | m_reg[mode][offset & 0x0f] = data & REGISTER_WRITE_MASK[mode][offset & 0x0f]; |
| 421 | |
| 422 | set_time(false, read_counter(REGISTER_1_YEAR), read_counter(REGISTER_1_MONTH), read_counter(REGISTER_1_DAY), m_reg[MODE00][REGISTER_DAY_OF_THE_WEEK], |
| 423 | read_counter(REGISTER_1_HOUR), read_counter(REGISTER_1_MINUTE), read_counter(REGISTER_1_SECOND)); |
| 513 | 424 | break; |
| 514 | 425 | |
| 515 | 426 | case BLOCK10: |
src/emu/machine/msm58321.c
| r15044 | r15045 | |
| 56 | 56 | }; |
| 57 | 57 | |
| 58 | 58 | |
| 59 | | // days per month |
| 60 | | static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
| 61 | 59 | |
| 62 | | |
| 63 | | |
| 64 | 60 | //************************************************************************** |
| 65 | 61 | // INLINE HELPERS |
| 66 | 62 | //************************************************************************** |
| r15044 | r15045 | |
| 86 | 82 | } |
| 87 | 83 | |
| 88 | 84 | |
| 89 | | //------------------------------------------------- |
| 90 | | // advance_seconds - |
| 91 | | //------------------------------------------------- |
| 92 | 85 | |
| 93 | | inline void msm58321_device::advance_seconds() |
| 94 | | { |
| 95 | | int seconds = read_counter(REGISTER_S1); |
| 96 | | |
| 97 | | seconds++; |
| 98 | | |
| 99 | | if (seconds > 59) |
| 100 | | { |
| 101 | | seconds = 0; |
| 102 | | |
| 103 | | advance_minutes(); |
| 104 | | } |
| 105 | | |
| 106 | | write_counter(REGISTER_S1, seconds); |
| 107 | | } |
| 108 | | |
| 109 | | |
| 110 | | //------------------------------------------------- |
| 111 | | // advance_minutes - |
| 112 | | //------------------------------------------------- |
| 113 | | |
| 114 | | inline void msm58321_device::advance_minutes() |
| 115 | | { |
| 116 | | int minutes = read_counter(REGISTER_MI1); |
| 117 | | int hours = read_counter(REGISTER_H1); |
| 118 | | int days = read_counter(REGISTER_D1); |
| 119 | | int month = read_counter(REGISTER_MO1); |
| 120 | | int year = read_counter(REGISTER_Y1); |
| 121 | | int day_of_week = m_reg[REGISTER_W]; |
| 122 | | |
| 123 | | minutes++; |
| 124 | | |
| 125 | | if (minutes > 59) |
| 126 | | { |
| 127 | | minutes = 0; |
| 128 | | hours++; |
| 129 | | } |
| 130 | | |
| 131 | | if (hours > 23) |
| 132 | | { |
| 133 | | hours = 0; |
| 134 | | days++; |
| 135 | | day_of_week++; |
| 136 | | } |
| 137 | | |
| 138 | | if (day_of_week > 6) |
| 139 | | { |
| 140 | | day_of_week++; |
| 141 | | } |
| 142 | | |
| 143 | | if (days > DAYS_PER_MONTH[month - 1]) |
| 144 | | { |
| 145 | | days = 1; |
| 146 | | month++; |
| 147 | | } |
| 148 | | |
| 149 | | if (month > 12) |
| 150 | | { |
| 151 | | month = 1; |
| 152 | | year++; |
| 153 | | } |
| 154 | | |
| 155 | | if (year > 99) |
| 156 | | { |
| 157 | | year = 0; |
| 158 | | } |
| 159 | | |
| 160 | | write_counter(REGISTER_MI1, minutes); |
| 161 | | write_counter(REGISTER_H1, hours); |
| 162 | | write_counter(REGISTER_D1, days); |
| 163 | | write_counter(REGISTER_MO1, month); |
| 164 | | write_counter(REGISTER_Y1, year); |
| 165 | | m_reg[REGISTER_W] = day_of_week; |
| 166 | | } |
| 167 | | |
| 168 | | |
| 169 | | |
| 170 | 86 | //************************************************************************** |
| 171 | 87 | // LIVE DEVICE |
| 172 | 88 | //************************************************************************** |
| r15044 | r15045 | |
| 235 | 151 | |
| 236 | 152 | |
| 237 | 153 | //------------------------------------------------- |
| 154 | // device_reset - device-specific reset |
| 155 | //------------------------------------------------- |
| 156 | |
| 157 | void msm58321_device::device_reset() |
| 158 | { |
| 159 | set_current_time(machine()); |
| 160 | } |
| 161 | |
| 162 | |
| 163 | //------------------------------------------------- |
| 238 | 164 | // device_timer - handler timer events |
| 239 | 165 | //------------------------------------------------- |
| 240 | 166 | |
| r15044 | r15045 | |
| 255 | 181 | |
| 256 | 182 | |
| 257 | 183 | //------------------------------------------------- |
| 258 | | // rtc_set_time - called to initialize the RTC to |
| 259 | | // a known state |
| 184 | // rtc_clock_updated - |
| 260 | 185 | //------------------------------------------------- |
| 261 | 186 | |
| 262 | | void msm58321_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 187 | void msm58321_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 263 | 188 | { |
| 264 | 189 | write_counter(REGISTER_Y1, year); |
| 265 | 190 | write_counter(REGISTER_MO1, month); |
| r15044 | r15045 | |
| 348 | 273 | default: |
| 349 | 274 | if (LOG) logerror("MSM58321 '%s' Register Write %01x: %01x\n", tag(), m_address, data & 0x0f); |
| 350 | 275 | m_reg[m_address] = m_latch & 0x0f; |
| 276 | |
| 277 | set_time(false, read_counter(REGISTER_Y1), read_counter(REGISTER_MO1), read_counter(REGISTER_D1), m_reg[REGISTER_W], |
| 278 | read_counter(REGISTER_H1), read_counter(REGISTER_MI1), read_counter(REGISTER_S1)); |
| 351 | 279 | break; |
| 352 | 280 | } |
| 353 | 281 | } |
src/mess/machine/hd64610.c
| r15044 | r15045 | |
| 63 | 63 | // alarm |
| 64 | 64 | #define ALARM_ENB 0x80 |
| 65 | 65 | |
| 66 | | // days per month |
| 67 | | static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
| 68 | | |
| 69 | 66 | // register write mask |
| 70 | 67 | static const int REG_WRITE_MASK[0x10] = |
| 71 | 68 | { |
| r15044 | r15045 | |
| 94 | 91 | } |
| 95 | 92 | } |
| 96 | 93 | |
| 94 | |
| 97 | 95 | //------------------------------------------------- |
| 98 | 96 | // read_counter - |
| 99 | 97 | //------------------------------------------------- |
| r15044 | r15045 | |
| 103 | 101 | return bcd_2_dec(m_regs[counter]); |
| 104 | 102 | } |
| 105 | 103 | |
| 104 | |
| 106 | 105 | //------------------------------------------------- |
| 107 | 106 | // write_counter - |
| 108 | 107 | //------------------------------------------------- |
| r15044 | r15045 | |
| 112 | 111 | m_regs[counter] = dec_2_bcd(value); |
| 113 | 112 | } |
| 114 | 113 | |
| 115 | | //------------------------------------------------- |
| 116 | | // advance_seconds - |
| 117 | | //------------------------------------------------- |
| 118 | 114 | |
| 119 | | inline 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 | 115 | //------------------------------------------------- |
| 137 | | // advance_minutes - |
| 138 | | //------------------------------------------------- |
| 139 | | |
| 140 | | inline 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 | | |
| 201 | | inline 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 | 116 | // check_alarm - |
| 213 | 117 | //------------------------------------------------- |
| 214 | 118 | |
| r15044 | r15045 | |
| 334 | 238 | |
| 335 | 239 | |
| 336 | 240 | //------------------------------------------------- |
| 337 | | // rtc_set_time - called to initialize the RTC to |
| 338 | | // a known state |
| 241 | // rtc_clock_updated - |
| 339 | 242 | //------------------------------------------------- |
| 340 | 243 | |
| 341 | | void hd64610_device::rtc_set_time(int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 244 | void hd64610_device::rtc_clock_updated(int year, int month, int day, int day_of_week, int hour, int minute, int second) |
| 342 | 245 | { |
| 343 | 246 | write_counter(REG_SECOND, second); |
| 344 | 247 | write_counter(REG_MINUTE, minute); |
| 345 | 248 | write_counter(REG_HOUR, hour); |
| 346 | 249 | write_counter(REG_DAY, day); |
| 347 | 250 | write_counter(REG_MONTH, month); |
| 348 | | write_counter(REG_YEAR,year); |
| 251 | write_counter(REG_YEAR, year); |
| 349 | 252 | m_regs[REG_DAY_OF_THE_WEEK] = day_of_week; |
| 253 | |
| 254 | check_alarm(); |
| 255 | set_irq_line(); |
| 350 | 256 | } |
| 351 | 257 | |
| 352 | 258 | |
src/mess/drivers/pc8001.c
| r15044 | r15045 | |
| 97 | 97 | */ |
| 98 | 98 | } |
| 99 | 99 | |
| 100 | READ8_MEMBER( pc8001_state::port40_r ) |
| 101 | { |
| 102 | /* |
| 103 | |
| 104 | bit description |
| 105 | |
| 106 | 0 BUSY |
| 107 | 1 ACK |
| 108 | 2 CMT CDIN |
| 109 | 3 EXP /EXTON |
| 110 | 4 RTC DATA OUT |
| 111 | 5 VRTC |
| 112 | 6 |
| 113 | 7 |
| 114 | |
| 115 | */ |
| 116 | |
| 117 | UINT8 data = 0x08; |
| 118 | |
| 119 | data |= m_centronics->busy_r(); |
| 120 | data |= m_centronics->ack_r() << 1; |
| 121 | data |= m_rtc->data_out_r() << 4; |
| 122 | data |= m_crtc->vrtc_r() << 5; |
| 123 | |
| 124 | return data; |
| 125 | } |
| 126 | |
| 127 | WRITE8_MEMBER( pc8001_state::port40_w ) |
| 128 | { |
| 129 | /* |
| 130 | |
| 131 | bit description |
| 132 | |
| 133 | 0 STROBE |
| 134 | 1 RTC STB |
| 135 | 2 RTC CLK |
| 136 | 3 CRT /CLDS CLK |
| 137 | 4 |
| 138 | 5 SPEAKER |
| 139 | 6 |
| 140 | 7 |
| 141 | |
| 142 | */ |
| 143 | |
| 144 | m_centronics->strobe_w(BIT(data, 0)); |
| 145 | |
| 146 | m_rtc->clk_w(BIT(data, 2)); |
| 147 | m_rtc->stb_w(BIT(data, 1)); |
| 148 | |
| 149 | speaker_level_w(m_speaker, BIT(data, 5)); |
| 150 | } |
| 151 | |
| 100 | 152 | /* Memory Maps */ |
| 101 | 153 | |
| 102 | 154 | static ADDRESS_MAP_START( pc8001_mem, AS_PROGRAM, 8, pc8001_state ) |
| r15044 | r15045 | |
| 122 | 174 | AM_RANGE(0x20, 0x20) AM_MIRROR(0x0e) AM_DEVREADWRITE(I8251_TAG, i8251_device, data_r, data_w) |
| 123 | 175 | AM_RANGE(0x21, 0x21) AM_MIRROR(0x0e) AM_DEVREADWRITE(I8251_TAG, i8251_device, status_r, control_w) |
| 124 | 176 | AM_RANGE(0x30, 0x30) AM_MIRROR(0x0f) AM_WRITE(port30_w) |
| 125 | | AM_RANGE(0x40, 0x40) AM_MIRROR(0x0f) AM_READ_PORT("R40") AM_WRITE_PORT("W40") |
| 177 | AM_RANGE(0x40, 0x40) AM_MIRROR(0x0f) AM_READWRITE(port40_r, port40_w) |
| 126 | 178 | AM_RANGE(0x50, 0x51) AM_DEVREADWRITE(UPD3301_TAG, upd3301_device, read, write) |
| 127 | 179 | AM_RANGE(0x60, 0x68) AM_DEVREADWRITE_LEGACY(I8257_TAG, i8257_r, i8257_w) |
| 128 | 180 | // AM_RANGE(0x70, 0x7f) unused |
| r15044 | r15045 | |
| 284 | 336 | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_KEYBOARD ) PORT_CODE(KEYCODE_ESC) PORT_CHAR(UCHAR_MAMEKEY(ESC)) |
| 285 | 337 | |
| 286 | 338 | PORT_START("DSW1") |
| 287 | | |
| 288 | | PORT_START("R40") |
| 289 | | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER(CENTRONICS_TAG, centronics_device, busy_r) |
| 290 | | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER(CENTRONICS_TAG, centronics_device, ack_r) |
| 291 | | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_SPECIAL ) // CMT CDIN |
| 292 | | PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_SPECIAL ) // EXP /EXTON |
| 293 | | PORT_BIT( 0x10, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER(UPD1990A_TAG, upd1990a_device, data_out_r) |
| 294 | | PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER(UPD3301_TAG, upd3301_device, vrtc_r) |
| 295 | | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 296 | | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 297 | | |
| 298 | | PORT_START("W40") |
| 299 | | PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER(CENTRONICS_TAG, centronics_device, strobe_w) |
| 300 | | PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER(UPD1990A_TAG, upd1990a_device, stb_w) |
| 301 | | PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE_MEMBER(UPD1990A_TAG, upd1990a_device, clk_w) |
| 302 | | PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_OUTPUT ) // CRT /CLDS CLK |
| 303 | | PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 304 | | PORT_BIT( 0x20, IP_ACTIVE_HIGH, IPT_OUTPUT ) PORT_WRITE_LINE_DEVICE(SPEAKER_TAG, speaker_level_w) |
| 305 | | PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 306 | | PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) |
| 307 | 339 | INPUT_PORTS_END |
| 308 | 340 | |
| 309 | 341 | /* Video */ |
| r15044 | r15045 | |
| 441 | 473 | |
| 442 | 474 | /* uPD1990A Interface */ |
| 443 | 475 | |
| 444 | | static UPD1990A_INTERFACE( pc8001_upd1990a_intf ) |
| 476 | static UPD1990A_INTERFACE( rtc_intf ) |
| 445 | 477 | { |
| 446 | 478 | DEVCB_NULL, |
| 447 | 479 | DEVCB_NULL |
| r15044 | r15045 | |
| 540 | 572 | MCFG_I8251_ADD(I8251_TAG, uart_intf) |
| 541 | 573 | MCFG_I8255A_ADD(I8255A_TAG, ppi_intf) |
| 542 | 574 | MCFG_I8257_ADD(I8257_TAG, 4000000, dmac_intf) |
| 543 | | MCFG_UPD1990A_ADD(UPD1990A_TAG, XTAL_32_768kHz, pc8001_upd1990a_intf) |
| 575 | MCFG_UPD1990A_ADD(UPD1990A_TAG, XTAL_32_768kHz, rtc_intf) |
| 544 | 576 | MCFG_UPD3301_ADD(UPD3301_TAG, 14318180, pc8001_upd3301_intf) |
| 545 | 577 | |
| 546 | 578 | MCFG_CENTRONICS_PRINTER_ADD(CENTRONICS_TAG, standard_centronics) |
| r15044 | r15045 | |
| 577 | 609 | MCFG_I8251_ADD(I8251_TAG, uart_intf) |
| 578 | 610 | MCFG_I8255A_ADD(I8255A_TAG, ppi_intf) |
| 579 | 611 | MCFG_I8257_ADD(I8257_TAG, 4000000, dmac_intf) |
| 580 | | MCFG_UPD1990A_ADD(UPD1990A_TAG, XTAL_32_768kHz, pc8001_upd1990a_intf) |
| 612 | MCFG_UPD1990A_ADD(UPD1990A_TAG, XTAL_32_768kHz, rtc_intf) |
| 581 | 613 | MCFG_UPD3301_ADD(UPD3301_TAG, 14318180, pc8001_upd3301_intf) |
| 582 | 614 | |
| 583 | 615 | MCFG_CENTRONICS_PRINTER_ADD(CENTRONICS_TAG, standard_centronics) |