1 // license:BSD-3-Clause
2 // copyright-holders:Curt Coder
3 /***************************************************************************
4
5 dirtc.cpp
6
7 Device Real Time Clock interfaces.
8
9 ***************************************************************************/
10
11 #include "emu.h"
12 #include "dirtc.h"
13
14
15 //**************************************************************************
16 // MACROS / CONSTANTS
17 //**************************************************************************
18
19 static const int DAYS_PER_MONTH[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
20
21
22
23 //**************************************************************************
24 // DEVICE RTC INTERFACE
25 //**************************************************************************
26
27 //-------------------------------------------------
28 // device_rtc_interface - constructor
29 //-------------------------------------------------
30
device_rtc_interface(const machine_config & mconfig,device_t & device)31 device_rtc_interface::device_rtc_interface(const machine_config &mconfig, device_t &device)
32 : device_interface(device, "rtc")
33 {
34 }
35
36
37 //-------------------------------------------------
38 // ~device_rtc_interface - destructor
39 //-------------------------------------------------
40
~device_rtc_interface()41 device_rtc_interface::~device_rtc_interface()
42 {
43 }
44
45
46 //-------------------------------------------------
47 // set_time - called to initialize the RTC to
48 // a known date/time
49 //-------------------------------------------------
50
set_time(bool update,int year,int month,int day,int day_of_week,int hour,int minute,int second)51 void device_rtc_interface::set_time(bool update, int year, int month, int day, int day_of_week, int hour, int minute, int second)
52 {
53 if (!rtc_feature_y2k())
54 {
55 year %= 100;
56 }
57
58 set_clock_register(RTC_YEAR, year);
59 set_clock_register(RTC_MONTH, month);
60 set_clock_register(RTC_DAY, day);
61 set_clock_register(RTC_DAY_OF_WEEK, day_of_week);
62 set_clock_register(RTC_HOUR, hour);
63 set_clock_register(RTC_MINUTE, minute);
64 set_clock_register(RTC_SECOND, second);
65
66 if (update)
67 {
68 rtc_clock_updated(m_register[RTC_YEAR], m_register[RTC_MONTH], m_register[RTC_DAY], m_register[RTC_DAY_OF_WEEK],
69 m_register[RTC_HOUR], m_register[RTC_MINUTE], m_register[RTC_SECOND]);
70 }
71 }
72
73
74 //-------------------------------------------------
75 // set_current_time - called to initialize the RTC
76 // to the current system time
77 //-------------------------------------------------
78
set_current_time(const system_time & systime)79 void device_rtc_interface::set_current_time(const system_time &systime)
80 {
81 set_time(true, systime.local_time.year, systime.local_time.month + 1, systime.local_time.mday, systime.local_time.weekday + 1,
82 systime.local_time.hour, systime.local_time.minute, systime.local_time.second);
83 }
84
85
86 //-------------------------------------------------
87 // convert_to_bcd -
88 //-------------------------------------------------
89
convert_to_bcd(int val)90 u8 device_rtc_interface::convert_to_bcd(int val)
91 {
92 return ((val / 10) << 4) | (val % 10);
93 }
94
95
96 //-------------------------------------------------
97 // bcd_to_integer -
98 //-------------------------------------------------
99
bcd_to_integer(u8 val)100 int device_rtc_interface::bcd_to_integer(u8 val)
101 {
102 return (((val & 0xf0) >> 4) * 10) + (val & 0x0f);
103 }
104
105
106 //-------------------------------------------------
107 // set_clock_register -
108 //-------------------------------------------------
109
set_clock_register(int reg,int value)110 void device_rtc_interface::set_clock_register(int reg, int value)
111 {
112 m_register[reg] = value;
113 }
114
115
116 //-------------------------------------------------
117 // get_clock_register -
118 //-------------------------------------------------
119
get_clock_register(int reg)120 int device_rtc_interface::get_clock_register(int reg)
121 {
122 return m_register[reg];
123 }
124
125
126 //-------------------------------------------------
127 // clock_updated -
128 //-------------------------------------------------
129
clock_updated()130 void device_rtc_interface::clock_updated()
131 {
132 rtc_clock_updated(m_register[RTC_YEAR], m_register[RTC_MONTH], m_register[RTC_DAY], m_register[RTC_DAY_OF_WEEK],
133 m_register[RTC_HOUR], m_register[RTC_MINUTE], m_register[RTC_SECOND]);
134 }
135
136
137 //-------------------------------------------------
138 // advance_seconds -
139 //-------------------------------------------------
140
advance_seconds()141 void device_rtc_interface::advance_seconds()
142 {
143 m_register[RTC_SECOND]++;
144
145 if (m_register[RTC_SECOND] == 60)
146 {
147 m_register[RTC_SECOND] = 0;
148
149 advance_minutes();
150 }
151 else
152 {
153 clock_updated();
154 }
155 }
156
157
158 //-------------------------------------------------
159 // advance_minutes
160 //-------------------------------------------------
161
advance_minutes()162 void device_rtc_interface::advance_minutes()
163 {
164 m_register[RTC_MINUTE]++;
165
166 if (m_register[RTC_MINUTE] == 60)
167 {
168 m_register[RTC_MINUTE] = 0;
169 m_register[RTC_HOUR]++;
170 }
171
172 if (m_register[RTC_HOUR] == 24)
173 {
174 m_register[RTC_HOUR] = 0;
175 advance_days();
176 }
177 else
178 {
179 clock_updated();
180 }
181 }
182
183
184 //-------------------------------------------------
185 // advance_days
186 //-------------------------------------------------
187
advance_days()188 void device_rtc_interface::advance_days()
189 {
190 m_register[RTC_DAY]++;
191 m_register[RTC_DAY_OF_WEEK]++;
192
193 if (m_register[RTC_DAY_OF_WEEK] == 8)
194 {
195 m_register[RTC_DAY_OF_WEEK] = 1;
196 }
197
198 if (m_register[RTC_MONTH] > 0 && m_register[RTC_DAY] > DAYS_PER_MONTH[m_register[RTC_MONTH] - 1])
199 {
200 if (m_register[RTC_MONTH] != 2 || m_register[RTC_DAY] != 29 || !rtc_feature_leap_year() || !(m_register[RTC_YEAR] % 4))
201 {
202 m_register[RTC_DAY] = 1;
203 m_register[RTC_MONTH]++;
204 }
205 }
206
207 if (m_register[RTC_MONTH] == 13)
208 {
209 m_register[RTC_MONTH] = 1;
210 m_register[RTC_YEAR]++;
211
212 if (!rtc_feature_y2k() && m_register[RTC_YEAR] == 100)
213 {
214 m_register[RTC_YEAR] = 0;
215 }
216 }
217
218 clock_updated();
219 }
220
221
222 //-------------------------------------------------
223 // adjust_seconds -
224 //-------------------------------------------------
225
adjust_seconds()226 void device_rtc_interface::adjust_seconds()
227 {
228 int seconds = get_clock_register(RTC_SECOND);
229
230 set_clock_register(RTC_SECOND, 0);
231
232 if (seconds >= 30)
233 {
234 advance_minutes();
235 }
236 else
237 {
238 clock_updated();
239 }
240 }
241