summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/mc146818.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/mc146818.cpp')
-rw-r--r--src/devices/machine/mc146818.cpp147
1 files changed, 101 insertions, 46 deletions
diff --git a/src/devices/machine/mc146818.cpp b/src/devices/machine/mc146818.cpp
index 1259e1502ca..06525f07893 100644
--- a/src/devices/machine/mc146818.cpp
+++ b/src/devices/machine/mc146818.cpp
@@ -54,12 +54,15 @@ mc146818_device::mc146818_device(const machine_config &mconfig, device_type type
void mc146818_device::device_start()
{
- m_data.resize(data_size());
+ m_data = make_unique_clear<uint8_t[]>(data_size());
m_last_refresh = machine().time();
m_clock_timer = timer_alloc(TIMER_CLOCK);
m_periodic_timer = timer_alloc(TIMER_PERIODIC);
m_write_irq.resolve_safe();
+
+ save_pointer(NAME(m_data), data_size());
+ save_item(NAME(m_index));
}
@@ -147,7 +150,20 @@ void mc146818_device::device_timer(emu_timer &timer, device_timer_id id, int par
{
set_month(1);
- set_year((get_year() + 1) % 100);
+ int year = get_year() + 1;
+ if (year <= 99)
+ {
+ set_year(year);
+ }
+ else
+ {
+ set_year(0);
+
+ if (century_count_enabled())
+ {
+ set_century((get_century() + 1) % 100);
+ }
+ }
}
}
}
@@ -181,15 +197,14 @@ void mc146818_device::device_timer(emu_timer &timer, device_timer_id id, int par
void mc146818_device::nvram_default()
{
// populate from a memory region if present
- memory_region *region = memregion(DEVICE_SELF);
- if (region != nullptr)
+ if (m_region.found())
{
- uint32_t bytes = region->bytes();
+ uint32_t bytes = m_region->bytes();
if (bytes > data_size())
bytes = data_size();
- memcpy(&m_data[0], region->base(), bytes);
+ memcpy(&m_data[0], m_region->base(), bytes);
}
else
{
@@ -237,7 +252,7 @@ void mc146818_device::nvram_write(emu_file &file)
// to_ram - convert value to current ram format
//-------------------------------------------------
-int mc146818_device::to_ram(int a)
+int mc146818_device::to_ram(int a) const
{
if (!(m_data[REG_B] & REG_B_DM))
return dec_2_bcd(a);
@@ -250,7 +265,7 @@ int mc146818_device::to_ram(int a)
// from_ram - convert value from current ram format
//-------------------------------------------------
-int mc146818_device::from_ram(int a)
+int mc146818_device::from_ram(int a) const
{
if (!(m_data[REG_B] & REG_B_DM))
return bcd_2_dec(a);
@@ -259,7 +274,7 @@ int mc146818_device::from_ram(int a)
}
-int mc146818_device::get_seconds()
+int mc146818_device::get_seconds() const
{
return from_ram(m_data[REG_SECONDS]);
}
@@ -269,7 +284,7 @@ void mc146818_device::set_seconds(int seconds)
m_data[REG_SECONDS] = to_ram(seconds);
}
-int mc146818_device::get_minutes()
+int mc146818_device::get_minutes() const
{
return from_ram(m_data[REG_MINUTES]);
}
@@ -279,7 +294,7 @@ void mc146818_device::set_minutes(int minutes)
m_data[REG_MINUTES] = to_ram(minutes);
}
-int mc146818_device::get_hours()
+int mc146818_device::get_hours() const
{
if (!(m_data[REG_B] & REG_B_24_12))
{
@@ -328,7 +343,7 @@ void mc146818_device::set_hours(int hours)
}
}
-int mc146818_device::get_dayofweek()
+int mc146818_device::get_dayofweek() const
{
return from_ram(m_data[REG_DAYOFWEEK]);
}
@@ -338,7 +353,7 @@ void mc146818_device::set_dayofweek(int dayofweek)
m_data[REG_DAYOFWEEK] = to_ram(dayofweek);
}
-int mc146818_device::get_dayofmonth()
+int mc146818_device::get_dayofmonth() const
{
return from_ram(m_data[REG_DAYOFMONTH]);
}
@@ -348,7 +363,7 @@ void mc146818_device::set_dayofmonth(int dayofmonth)
m_data[REG_DAYOFMONTH] = to_ram(dayofmonth);
}
-int mc146818_device::get_month()
+int mc146818_device::get_month() const
{
return from_ram(m_data[REG_MONTH]);
}
@@ -358,7 +373,7 @@ void mc146818_device::set_month(int month)
m_data[REG_MONTH] = to_ram(month);
}
-int mc146818_device::get_year()
+int mc146818_device::get_year() const
{
return from_ram(m_data[REG_YEAR]);
}
@@ -368,6 +383,18 @@ void mc146818_device::set_year(int year)
m_data[REG_YEAR] = to_ram(year);
}
+int mc146818_device::get_century() const
+{
+ assert(m_century_index != -1);
+ return from_ram(m_data[m_century_index]);
+}
+
+void mc146818_device::set_century(int century)
+{
+ assert(m_century_index != -1);
+ m_data[m_century_index] = to_ram(century);
+}
+
//-------------------------------------------------
@@ -400,7 +427,7 @@ void mc146818_device::set_base_datetime()
set_year((current_time.year - m_epoch) % 100);
if (m_century_index >= 0)
- m_data[m_century_index] = to_ram(current_time.year / 100);
+ set_century(current_time.year / 100);
}
@@ -410,9 +437,7 @@ void mc146818_device::set_base_datetime()
void mc146818_device::update_timer()
{
- int bypass;
-
- bypass = get_timer_bypass();
+ int bypass = get_timer_bypass();
attotime update_period = attotime::never;
attotime update_interval = attotime::never;
@@ -452,7 +477,7 @@ void mc146818_device::update_timer()
// get_timer_bypass - get main clock divisor based on A register
//---------------------------------------------------------------
-int mc146818_device::get_timer_bypass()
+int mc146818_device::get_timer_bypass() const
{
int bypass;
@@ -520,7 +545,8 @@ uint8_t mc146818_device::read(offs_t offset)
break;
case 1:
- data = read_direct(m_index);
+ data = internal_read(m_index);
+ LOG("mc146818_port_r(): offset=0x%02x data=0x%02x\n", m_index, data);
break;
}
@@ -529,6 +555,54 @@ uint8_t mc146818_device::read(offs_t offset)
uint8_t mc146818_device::read_direct(offs_t offset)
{
+ offset %= data_logical_size();
+ if (!machine().side_effects_disabled())
+ internal_set_address(offset);
+
+ uint8_t data = internal_read(offset);
+
+ LOG("mc146818_port_r(): offset=0x%02x data=0x%02x\n", offset, data);
+
+ return data;
+}
+
+//-------------------------------------------------
+// write - I/O handler for writing
+//-------------------------------------------------
+
+void mc146818_device::write(offs_t offset, uint8_t data)
+{
+ switch (offset)
+ {
+ case 0:
+ internal_set_address(data % data_logical_size());
+ break;
+
+ case 1:
+ LOG("mc146818_port_w(): offset=0x%02x data=0x%02x\n", m_index, data);
+ internal_write(m_index, data);
+ break;
+ }
+}
+
+void mc146818_device::write_direct(offs_t offset, uint8_t data)
+{
+ offset %= data_logical_size();
+ if (!machine().side_effects_disabled())
+ internal_set_address(offset);
+
+ LOG("mc146818_port_w(): offset=0x%02x data=0x%02x\n", offset, data);
+
+ internal_write(offset, data);
+}
+
+void mc146818_device::internal_set_address(uint8_t address)
+{
+ m_index = address;
+}
+
+uint8_t mc146818_device::internal_read(offs_t offset)
+{
uint8_t data = 0;
switch (offset)
@@ -546,8 +620,11 @@ uint8_t mc146818_device::read_direct(offs_t offset)
// the unused bits b0 ... b3 are always read as 0
data = m_data[REG_C] & (REG_C_IRQF | REG_C_PF | REG_C_AF | REG_C_UF);
// read 0x0c will clear all IRQ flags in register 0x0c
- m_data[REG_C] &= ~(REG_C_IRQF | REG_C_PF | REG_C_AF | REG_C_UF);
- update_irq();
+ if (!machine().side_effects_disabled())
+ {
+ m_data[REG_C] &= ~(REG_C_IRQF | REG_C_PF | REG_C_AF | REG_C_UF);
+ update_irq();
+ }
break;
case REG_D:
@@ -560,33 +637,11 @@ uint8_t mc146818_device::read_direct(offs_t offset)
break;
}
- LOG("mc146818_port_r(): offset=0x%02x data=0x%02x\n", offset, data);
-
return data;
}
-//-------------------------------------------------
-// write - I/O handler for writing
-//-------------------------------------------------
-
-void mc146818_device::write(offs_t offset, uint8_t data)
-{
- switch (offset)
- {
- case 0:
- m_index = data % data_size();
- break;
-
- case 1:
- write_direct(m_index, data);
- break;
- }
-}
-
-void mc146818_device::write_direct(offs_t offset, uint8_t data)
+void mc146818_device::internal_write(offs_t offset, uint8_t data)
{
- LOG("mc146818_port_w(): offset=0x%02x data=0x%02x\n", offset, data);
-
switch (offset)
{
case REG_SECONDS: