diff options
author | 2024-03-24 00:57:22 +0100 | |
---|---|---|
committer | 2024-03-24 00:57:22 +0100 | |
commit | 2d381367a3a01dffa9a456e054a5ff455033c306 (patch) | |
tree | 09f40e5b5c0171f1b049b1920f392c62472ac255 | |
parent | a4cf1316fa003f73193c3010984a373015051e02 (diff) |
m6801: revert changes to serial emulation from a4cf1316fa003f73193c3010984a373015051e02 - not the correct solution, introduces time travel issue unfortunately
-rw-r--r-- | src/devices/cpu/m6800/m6801.cpp | 139 | ||||
-rw-r--r-- | src/devices/cpu/m6800/m6801.h | 13 | ||||
-rw-r--r-- | src/mame/novag/primo.cpp | 4 | ||||
-rw-r--r-- | src/mame/novag/vip.cpp | 3 |
4 files changed, 33 insertions, 126 deletions
diff --git a/src/devices/cpu/m6800/m6801.cpp b/src/devices/cpu/m6800/m6801.cpp index ae14307b246..8e44e9c40a5 100644 --- a/src/devices/cpu/m6800/m6801.cpp +++ b/src/devices/cpu/m6800/m6801.cpp @@ -5,6 +5,8 @@ 6801 and derivatives TODO: +- improve serial emulation: receiver listens to start bit at 8*data rate, + and will start reading 1.5 'bits' after the start bit - improve RAM control register - improve STBY pin? RES pin (reset) should be ineffective while STBY is low - IS3 interrupt for 6801 port 3 handshake (already implemented for 6301Y) @@ -852,50 +854,12 @@ void hd6301x_cpu_device::check_timer_event() set_timer_event(); } -void m6801_cpu_device::schedule_tx_event() -{ - if (m_trcsr & M6801_TRCSR_TE) - machine().scheduler().synchronize(timer_expired_delegate(FUNC(m6801_cpu_device::tx_tick), this)); -} - -void m6801_cpu_device::schedule_rx_event() -{ - // don't schedule more than 1 rx event - if (m_rx_event_remain) - m_rx_event_remain++; - else if (clock_internal_rx()) - { - machine().scheduler().synchronize(timer_expired_delegate(FUNC(m6801_cpu_device::rx_tick), this)); - m_rx_event_remain = 1; - } -} - -void m6801_cpu_device::check_serial_event(int amount) -{ - // serial tx/rx event (when CC is 1 or 2) - m_tx_event -= amount; - if (m_tx_event <= 0) - { - m_tx_event += m_tx_period; - schedule_tx_event(); - } - - m_rx_event -= amount; - while (m_rx_event <= 0) // rx can have more than 1 clock per timeslice - { - m_rx_event += m_rx_period; - schedule_rx_event(); - } -} - void m6801_cpu_device::increment_counter(int amount) { m6800_cpu_device::increment_counter(amount); CTD += amount; if (CTD >= m_timer_next) check_timer_event(); - if (m_tx_period) - check_serial_event(amount); } void hd6301x_cpu_device::increment_counter(int amount) @@ -930,8 +894,6 @@ void hd6301x_cpu_device::increment_counter(int amount) CTD += amount; if (CTD >= m_timer_next || (m_tcsr3 & 0xc0) == 0xc0) check_timer_event(); - if (m_tx_period) - check_serial_event(amount); } void m6801_cpu_device::eat_cycles() @@ -980,18 +942,17 @@ void m6801_cpu_device::set_rmcr(u8 data) case 3: // external clock LOGSER("SCI: Using external serial clock: true\n"); - m_use_ext_serclock = true; reset_sci_timer(); + m_use_ext_serclock = true; break; case 1: case 2: { int divisor = M6801_RMCR_SS[m_rmcr & M6801_RMCR_SS_MASK]; - LOGSER("SCI: Setting serial rate, Divisor: %d Hz: %d\n", divisor, cycles_to_attotime(divisor).as_hz()); - reset_sci_timer(); - m_rx_event = m_rx_period = divisor / 8; - m_tx_event = m_tx_period = divisor; + attotime period = cycles_to_attotime(divisor); + LOGSER("SCI: Setting serial rate, Divisor: %d Hz: %d\n", divisor, period.as_hz()); + m_sci_timer->adjust(period, 0, period); m_use_ext_serclock = false; } break; @@ -1010,8 +971,8 @@ void hd6301x_cpu_device::set_rmcr(u8 data) case 3: case 7: // external clock LOGSER("SCI: Using external serial clock: true\n"); - m_use_ext_serclock = true; reset_sci_timer(); + m_use_ext_serclock = true; break; case 1: @@ -1027,10 +988,9 @@ void hd6301x_cpu_device::set_rmcr(u8 data) else { int divisor = M6801_RMCR_SS[m_rmcr & M6801_RMCR_SS_MASK]; - LOGSER("SCI: Setting serial rate, Divisor: %d Hz: %d\n", divisor, cycles_to_attotime(divisor).as_hz()); - reset_sci_timer(); - m_rx_event = m_rx_period = divisor / 8; - m_tx_event = m_tx_period = divisor; + attotime period = cycles_to_attotime(divisor); + LOGSER("SCI: Setting serial rate, Divisor: %d Hz: %d\n", divisor, period.as_hz()); + m_sci_timer->adjust(period, 0, period); } m_use_ext_serclock = false; break; @@ -1170,12 +1130,8 @@ void m6801_cpu_device::serial_receive() // start bit found m_rxbits++; - // it synchronizes to the middle of the next bit - m_rx_clocks = 11; - LOGRX("SCI Received START bit\n"); } - break; case M6801_SERIAL_STOP: @@ -1244,57 +1200,33 @@ void m6801_cpu_device::serial_receive() } } -bool m6801_cpu_device::clock_internal_rx() +TIMER_CALLBACK_MEMBER(m6801_cpu_device::sci_tick) { - // internally, rx runs at 8 times the data rate while it waits for the start bit - if (!(m_trcsr & M6801_TRCSR_WU) && m_rxbits == M6801_SERIAL_START) - m_rx_clocks = 1; - else if (m_rx_clocks == 0) - m_rx_clocks = 8; - - return (--m_rx_clocks == 0 && m_trcsr & M6801_TRCSR_RE); + serial_transmit(); + serial_receive(); } -TIMER_CALLBACK_MEMBER(m6801_cpu_device::rx_tick) +void m6801_cpu_device::sci_clock_internal(u8 divider) { - serial_receive(); + m_sci_clocks++; - // handle leftover rx clocks now - if (m_rx_event_remain) + if (m_sci_clocks >= divider) { - while (--m_rx_event_remain) - if (clock_internal_rx()) - serial_receive(); + m_sci_clocks = 0; + sci_tick(0); } } -TIMER_CALLBACK_MEMBER(m6801_cpu_device::tx_tick) +void m6801_cpu_device::clock_serial() { - serial_transmit(); + if (m_use_ext_serclock) + sci_clock_internal(m_sclk_divider); } void m6801_cpu_device::reset_sci_timer() { - m_rx_clocks = 0; m_sci_clocks = 0; - m_tx_period = 0; - m_rx_period = 0; -} - -void m6801_cpu_device::clock_serial() -{ - if (m_use_ext_serclock) - { - m_sci_clocks++; - - if (!(m_sci_clocks & (m_sclk_divider - 1) >> 3) && clock_internal_rx()) - serial_receive(); - if (m_sci_clocks >= m_sclk_divider) - { - m_sci_clocks = 0; - serial_transmit(); - } - } + m_sci_timer->adjust(attotime::never); } @@ -1382,6 +1314,8 @@ void m6801_cpu_device::device_start() { m6800_cpu_device::device_start(); + m_sci_timer = timer_alloc(FUNC(m6801_cpu_device::sci_tick), this); + std::fill(std::begin(m_port_ddr), std::end(m_port_ddr), 0); std::fill(std::begin(m_port_data), std::end(m_port_data), 0); m_p3csr = 0; @@ -1408,12 +1342,6 @@ void m6801_cpu_device::device_start() m_trcsr_read_orfe = 0; m_trcsr_read_rdrf = 0; m_tx = 0; - m_rx_event = 0; - m_tx_event = 0; - m_rx_period = 0; - m_tx_period = 0; - m_rx_event_remain = 0; - m_rx_clocks = 0; m_sci_clocks = 0; m_use_ext_serclock = false; @@ -1451,12 +1379,6 @@ void m6801_cpu_device::device_start() save_item(NAME(m_trcsr_read_orfe)); save_item(NAME(m_trcsr_read_rdrf)); save_item(NAME(m_tx)); - save_item(NAME(m_rx_event)); - save_item(NAME(m_tx_event)); - save_item(NAME(m_rx_period)); - save_item(NAME(m_tx_period)); - save_item(NAME(m_rx_event_remain)); - save_item(NAME(m_rx_clocks)); save_item(NAME(m_sci_clocks)); save_item(NAME(m_use_ext_serclock)); @@ -1553,7 +1475,6 @@ void m6801_cpu_device::device_reset() m_trcsr_read_orfe = 0; m_trcsr_read_rdrf = 0; m_use_ext_serclock = false; - reset_sci_timer(); set_rmcr(0); } @@ -2454,17 +2375,7 @@ void hd6301x_cpu_device::increment_t2cnt(int amount) } if (BIT(m_rmcr, 5) && !m_use_ext_serclock) - { - m_sci_clocks++; - - if (!(m_sci_clocks & 3)) - schedule_rx_event(); - if (m_sci_clocks >= 32) - { - m_sci_clocks = 0; - schedule_tx_event(); - } - } + sci_clock_internal(32); m_tcsr3 |= 0x80; m_timer_next = 0; // HACK diff --git a/src/devices/cpu/m6800/m6801.h b/src/devices/cpu/m6800/m6801.h index 77a17ce62e9..aa1518487ff 100644 --- a/src/devices/cpu/m6800/m6801.h +++ b/src/devices/cpu/m6800/m6801.h @@ -163,15 +163,14 @@ protected: bool m_port2_written; u8 m_trcsr, m_rmcr, m_rdr, m_tdr, m_rsr, m_tshr; - int m_rxbits, m_txbits, m_txstate, m_trcsr_read_tdre, m_trcsr_read_orfe, m_trcsr_read_rdrf, m_tx; - s32 m_rx_event, m_tx_event, m_rx_period, m_tx_period; - u8 m_rx_event_remain, m_rx_clocks, m_sci_clocks; + int m_rxbits, m_txbits, m_txstate, m_trcsr_read_tdre, m_trcsr_read_orfe, m_trcsr_read_rdrf, m_tx, m_sci_clocks; bool m_use_ext_serclock; u8 m_latch09; int m_is3_state; PAIR m_timer_over; + emu_timer *m_sci_timer; u32 m_timer_next; // point of next timer event static const u8 cycles_6803[256]; @@ -198,12 +197,8 @@ protected: int m6801_rx(); void serial_transmit(); void serial_receive(); - TIMER_CALLBACK_MEMBER(tx_tick); - TIMER_CALLBACK_MEMBER(rx_tick); - bool clock_internal_rx(); - void schedule_tx_event(); - void schedule_rx_event(); - void check_serial_event(int amount); + TIMER_CALLBACK_MEMBER(sci_tick); + void sci_clock_internal(u8 divider); void reset_sci_timer(); void set_os3(int state); }; diff --git a/src/mame/novag/primo.cpp b/src/mame/novag/primo.cpp index ffa38ee4485..ea5e6d051e3 100644 --- a/src/mame/novag/primo.cpp +++ b/src/mame/novag/primo.cpp @@ -10,8 +10,8 @@ properly. TODO: - if/when MAME supports an exit callback, hook up power-off switch to that -- nsnova sometimes fails to detect Super System TV Interface when pressing New Game? - It should flash the screen on successful detection. +- super system peripherals don't work on nsnova due to serial clock drift, baud + rate differs a bit between host and client, m6801 serial emulation issue - unmapped reads from 0x3c/0x3d (primo/supremo) or 0x33/0x34 (nsnova) - supremo unmapped writes to 0x2000/0x6000, always 0? - is the 1st version of supremo(black plastic) the same ROM? diff --git a/src/mame/novag/vip.cpp b/src/mame/novag/vip.cpp index 2862183784d..92bb57e0149 100644 --- a/src/mame/novag/vip.cpp +++ b/src/mame/novag/vip.cpp @@ -55,7 +55,8 @@ Hardware notes: Super VIP is Novag's first chess computer with a proper serial interface. It connects to the Novag Super System Distributor, which can then connect to an -external chessboard, TV interface, computer, etc. +external chessboard, TV interface, computer, etc. They are basically RS-232 +devices, just with a different plug. Serial transmission format for Novag Super System is 1 start bit, 8 data bits, 1 stop bit, no parity. On Super VIP, the baud rate is selectable 1200 or 9600, |