mc146818: add square wave output

This commit is contained in:
Patrick Mackinlay 2020-11-25 10:48:15 +07:00
parent a35cd5698f
commit 481e06f3fe
2 changed files with 29 additions and 5 deletions

View File

@ -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;

View File

@ -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;
};