From 481e06f3fed2018cbd3a0349370114fd214475a5 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Wed, 25 Nov 2020 10:48:15 +0700 Subject: [PATCH] mc146818: add square wave output --- src/devices/machine/mc146818.cpp | 31 ++++++++++++++++++++++++++----- src/devices/machine/mc146818.h | 3 +++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/src/devices/machine/mc146818.cpp b/src/devices/machine/mc146818.cpp index 06525f07893..cbce9ced926 100644 --- a/src/devices/machine/mc146818.cpp +++ b/src/devices/machine/mc146818.cpp @@ -39,12 +39,14 @@ mc146818_device::mc146818_device(const machine_config &mconfig, device_type type m_index(0), m_last_refresh(attotime::zero), m_clock_timer(nullptr), m_periodic_timer(nullptr), m_write_irq(*this), + m_write_sqw(*this), m_century_index(-1), m_epoch(0), m_use_utc(false), m_binary(false), m_hour(false), - m_binyear(false) + m_binyear(false), + m_sqw_state(false) { } @@ -60,9 +62,11 @@ void mc146818_device::device_start() m_periodic_timer = timer_alloc(TIMER_PERIODIC); m_write_irq.resolve_safe(); + m_write_sqw.resolve_safe(); save_pointer(NAME(m_data), data_size()); save_item(NAME(m_index)); + save_item(NAME(m_sqw_state)); } @@ -75,6 +79,10 @@ void mc146818_device::device_reset() m_data[REG_B] &= ~(REG_B_UIE | REG_B_AIE | REG_B_PIE | REG_B_SQWE); m_data[REG_C] = 0; + // square wave output is disabled + if (m_sqw_state) + m_write_sqw(CLEAR_LINE); + update_irq(); } @@ -87,8 +95,17 @@ void mc146818_device::device_timer(emu_timer &timer, device_timer_id id, int par switch (id) { case TIMER_PERIODIC: - m_data[REG_C] |= REG_C_PF; - update_irq(); + m_sqw_state = !m_sqw_state; + + if (m_data[REG_B] & REG_B_SQWE) + m_write_sqw(m_sqw_state); + + // periodic flag/interrupt on rising edge of periodic timer + if (m_sqw_state) + { + m_data[REG_C] |= REG_C_PF; + update_irq(); + } break; case TIMER_CLOCK: @@ -464,8 +481,9 @@ void mc146818_device::update_timer() double periodic_hz = (double) clock() / (1 << shift); // TODO: take the time since last timer into account - periodic_period = attotime::from_hz(periodic_hz * 2); - periodic_interval = attotime::from_hz(periodic_hz); + // periodic frequency is doubled to produce square wave output + periodic_period = attotime::from_hz(periodic_hz * 4); + periodic_interval = attotime::from_hz(periodic_hz * 2); } } @@ -662,6 +680,9 @@ void mc146818_device::internal_write(offs_t offset, uint8_t data) if ((data & REG_B_SET) && !(m_data[REG_B] & REG_B_SET)) data &= ~REG_B_UIE; + if (!(data & REG_B_SQWE) && (m_data[REG_B] & REG_B_SQWE) && m_sqw_state) + m_write_sqw(CLEAR_LINE); + m_data[REG_B] = data; update_irq(); break; diff --git a/src/devices/machine/mc146818.h b/src/devices/machine/mc146818.h index 18588b71827..83d45292dbc 100644 --- a/src/devices/machine/mc146818.h +++ b/src/devices/machine/mc146818.h @@ -26,6 +26,7 @@ public: // callbacks auto irq() { return m_write_irq.bind(); } + auto sqw() { return m_write_sqw.bind(); } // The MC146818 doesn't have century support (some variants do), but when syncing the date & time at startup we can optionally store the century. void set_century_index(int century_index) { assert(!century_count_enabled()); m_century_index = century_index; } @@ -165,8 +166,10 @@ protected: emu_timer *m_periodic_timer; devcb_write_line m_write_irq; + devcb_write_line m_write_sqw; int m_century_index, m_epoch; bool m_use_utc, m_binary, m_hour, m_binyear; + bool m_sqw_state; };