summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author hap <happppp@users.noreply.github.com>2024-03-24 00:57:22 +0100
committer hap <happppp@users.noreply.github.com>2024-03-24 00:57:22 +0100
commit2d381367a3a01dffa9a456e054a5ff455033c306 (patch)
tree09f40e5b5c0171f1b049b1920f392c62472ac255
parenta4cf1316fa003f73193c3010984a373015051e02 (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.cpp139
-rw-r--r--src/devices/cpu/m6800/m6801.h13
-rw-r--r--src/mame/novag/primo.cpp4
-rw-r--r--src/mame/novag/vip.cpp3
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,