diff options
| author | 2025-07-25 23:06:22 -0400 | |
|---|---|---|
| committer | 2025-07-25 23:06:22 -0400 | |
| commit | f663de7076d33ff3ad28fc4ebf963974f2cc80d8 (patch) | |
| tree | 261dcb0b406daf9a014cf51a9fea83ecc6b74588 | |
| parent | fda3d4f99eb4c868c77bf21650372bc72b8e6ca6 (diff) | |
pokey: Synchronize on SOD output transitions during serial transmission
| -rw-r--r-- | src/devices/sound/pokey.cpp | 31 | ||||
| -rw-r--r-- | src/devices/sound/pokey.h | 2 |
2 files changed, 22 insertions, 11 deletions
diff --git a/src/devices/sound/pokey.cpp b/src/devices/sound/pokey.cpp index 77c75c1bd44..0aea0ded433 100644 --- a/src/devices/sound/pokey.cpp +++ b/src/devices/sound/pokey.cpp @@ -107,7 +107,7 @@ #define VERBOSE_IRQ (1U << 5) #define VERBOSE_SERIN (1U << 6) #define VERBOSE_SEROUT (1U << 7) -#define VERBOSE (0) +#define VERBOSE (VERBOSE_SERIN | VERBOSE_SEROUT) #include "logmacro.h" @@ -216,6 +216,7 @@ pokey_device::pokey_device(const machine_config &mconfig, const char *tag, devic m_output_type(LEGACY_LINEAR), m_serout_ready_timer(nullptr), m_serout_complete_timer(nullptr), + m_serout_bit_timer(nullptr), m_serin_ready_timer(nullptr) { } @@ -303,6 +304,7 @@ void pokey_device::device_start() m_serout_ready_timer = timer_alloc(FUNC(pokey_device::serout_ready_irq), this); m_serout_complete_timer = timer_alloc(FUNC(pokey_device::serout_complete_irq), this); + m_serout_bit_timer = timer_alloc(FUNC(pokey_device::serout_transmit_bit), this); m_serin_ready_timer = timer_alloc(FUNC(pokey_device::serin_ready_irq), this); save_item(STRUCT_MEMBER(m_channel, m_borrow_cnt)); @@ -412,6 +414,10 @@ void pokey_device::device_clock_changed() TIMER_CALLBACK_MEMBER(pokey_device::serout_ready_irq) { + if (!(m_SKCTL & SK_TWOTONE)) + m_sod_w_cb(0); + m_oclk_w_cb(1); + m_IRQST &= ~IRQ_SEROC; if (m_IRQEN & IRQ_SEROR) { @@ -423,6 +429,9 @@ TIMER_CALLBACK_MEMBER(pokey_device::serout_ready_irq) TIMER_CALLBACK_MEMBER(pokey_device::serout_complete_irq) { + if (!(m_SKCTL & SK_TWOTONE) && (m_SKCTL & SK_BREAK)) + m_sod_w_cb(0); + // Completion flag is set regardless of IRQEN m_IRQST |= IRQ_SEROC; if (m_IRQEN & IRQ_SEROC) @@ -432,6 +441,13 @@ TIMER_CALLBACK_MEMBER(pokey_device::serout_complete_irq) } } +TIMER_CALLBACK_MEMBER(pokey_device::serout_transmit_bit) +{ + if (!(m_SKCTL & SK_TWOTONE)) + m_sod_w_cb(m_serout_shift & 1); + m_oclk_w_cb(1); +} + TIMER_CALLBACK_MEMBER(pokey_device::serin_ready_irq) { // Check stop bit for framing error @@ -1242,27 +1258,20 @@ void pokey_device::process_serout() { // Output start bit and reload the shift register LOG_SEROUT("SEROUT transmitting start bit of %02x @ %s\n", m_SEROUT, machine().time().to_string()); - if (!(m_SKCTL & SK_TWOTONE)) - m_sod_w_cb(0); - m_oclk_w_cb(1); m_serout_shift = (m_SEROUT << 1) | (1 << 9); m_serout_full = false; m_serout_ready_timer->adjust(attotime::zero); } else - { - if (!(m_SKCTL & SK_TWOTONE) && (m_SKCTL & SK_BREAK)) - m_sod_w_cb(0); m_serout_complete_timer->adjust(attotime::zero); - } } else { + bool last_sod = m_serout_shift & 1; m_serout_shift >>= 1; LOG_SEROUT("SEROUT transmitting %d bit @ %s\n", m_serout_shift & 1, machine().time().to_string()); - if (!(m_SKCTL & SK_TWOTONE)) - m_sod_w_cb(m_serout_shift & 1); - m_oclk_w_cb(1); + if (last_sod != (m_serout_shift & 1)) + m_serout_bit_timer->adjust(attotime::zero); } } diff --git a/src/devices/sound/pokey.h b/src/devices/sound/pokey.h index bc6b2596d38..5d3ed4e8225 100644 --- a/src/devices/sound/pokey.h +++ b/src/devices/sound/pokey.h @@ -192,6 +192,7 @@ protected: TIMER_CALLBACK_MEMBER(serout_ready_irq); TIMER_CALLBACK_MEMBER(serout_complete_irq); + TIMER_CALLBACK_MEMBER(serout_transmit_bit); TIMER_CALLBACK_MEMBER(serin_ready_irq); TIMER_CALLBACK_MEMBER(sync_write); TIMER_CALLBACK_MEMBER(sync_pot); @@ -320,6 +321,7 @@ private: emu_timer *m_serout_ready_timer; emu_timer *m_serout_complete_timer; + emu_timer *m_serout_bit_timer; emu_timer *m_serin_ready_timer; }; |
