summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/h8/h8_sci.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/h8/h8_sci.cpp')
-rw-r--r--src/devices/cpu/h8/h8_sci.cpp1003
1 files changed, 525 insertions, 478 deletions
diff --git a/src/devices/cpu/h8/h8_sci.cpp b/src/devices/cpu/h8/h8_sci.cpp
index 04a666e5066..9f089266111 100644
--- a/src/devices/cpu/h8/h8_sci.cpp
+++ b/src/devices/cpu/h8/h8_sci.cpp
@@ -1,725 +1,772 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
+
#include "emu.h"
#include "h8_sci.h"
-// Verbosity level
-// 0 = no messages
-// 1 = transmitted/recieved bytes, reception errors and clock setup
-// 2 = everything but status register reads
-// 3 = everything
-const int V = 1;
+#include "h8.h"
+#include "h8_intc.h"
+
+#define LOG_REGS (1 << 1U) // Register writes
+#define LOG_RREGS (1 << 2U) // Register reads
+#define LOG_RATE (1 << 3U) // Bitrate setting, beware that gk2000 changes it all the time ending up in a massive slowdown, don't leave it active
+#define LOG_DATA (1 << 4U) // Bytes transmitted
+#define LOG_CLOCK (1 << 5U) // Clock and transmission start/stop
+#define LOG_STATE (1 << 6U) // State machine states
+#define LOG_TICK (1 << 7U) // Clock ticks
+#define VERBOSE (LOG_DATA)
+
+#include "logmacro.h"
DEFINE_DEVICE_TYPE(H8_SCI, h8_sci_device, "h8_sci", "H8 Serial Communications Interface")
+
+// Clocking:
+// Async mode:
+// The circuit wants 16 events per bit.
+// * Internal clocking: the cpu clock is divided by one of (1, 4, 16, 64) from the cks field of smr
+// then by (brr+1) then by 2.
+// * External clocking: the external clock is supposed to be 16*bitrate.
+// Sync mode:
+// The circuit wants 2 events per bit, a positive and a negative edge.
+// * Internal clocking: the cpu clock is divided by one of (1, 4, 16, 64) from the cks field of smr
+// then by (brr+1) then by 2. Events are then interpreted has been alternatively positive and
+// negative (e.g. another divide-by-two, sync-wise).
+// * External clocking: the external clock is supposed to be at bitrate, both edges are used.
+//
+// Synchronization:
+// Async mode:
+// Both modes use a 4-bits counter incremented on every event (16/bit).
+//
+// * Transmit sets the counter to 0 at transmit start. Output data line changes value
+// on counter == 0. If the clock output is required, clk=1 outside of transmit,
+// clk=0 on counter==0, clk=1 on counter==8.
+//
+// * Receive sets the counter to 0 when the data line initially goes down (start bit)
+// Output line is read on counter==8. It is unknown whether the counter is reset
+// on every data line level change.
+//
+// Sync mode:
+// * Transmit changes the data line on negative edges, the clock line, following positive and
+// negative edge definition, is output as long as transmit is active and is otherwise 1.
+//
+// * Receive reads the data line on positive edges.
+//
+// Framing:
+// Async mode: 1 bit of start at 0, 7 or 8 bits of data, nothing or 1 bit of parity or 1 bit of multiprocessing, 1 or 2 bits of stop at 1.
+// Sync mode: 8 bits of data.
+//
+// Multiprocessing bit is an extra bit which value can be set on transmit in bit zero of ssr.
+// On receive when zero the byte is dropped.
+
+
const char *const h8_sci_device::state_names[] = { "idle", "start", "bit", "parity", "stop", "last-tick" };
-h8_sci_device::h8_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+h8_sci_device::h8_sci_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
device_t(mconfig, H8_SCI, tag, owner, clock),
- cpu(*this, DEVICE_SELF_OWNER),
- tx_cb(*this),
- clk_cb(*this), intc(nullptr), intc_tag(nullptr), external_to_internal_ratio(0), internal_to_external_ratio(0), sync_timer(nullptr), eri_int(0), rxi_int(0), txi_int(0), tei_int(0),
- tx_state(0), rx_state(0), tx_bit(0), rx_bit(0), clock_state(0), clock_mode(0), tx_parity(0), rx_parity(0), ext_clock_counter(0), clock_value(false), ext_clock_value(false), rx_value(false),
- rdr(0), tdr(0), smr(0), scr(0), ssr(0), brr(0), rsr(0), tsr(0), clock_base(0), divider(0)
+ m_cpu(*this, finder_base::DUMMY_TAG),
+ m_intc(*this, finder_base::DUMMY_TAG),
+ m_external_to_internal_ratio(0), m_internal_to_external_ratio(0), m_sync_timer(nullptr), m_id(0), m_eri_int(0), m_rxi_int(0), m_txi_int(0), m_tei_int(0),
+ m_tx_state(0), m_rx_state(0), m_tx_bit(0), m_rx_bit(0), m_clock_state(0), m_tx_parity(0), m_rx_parity(0), m_tx_clock_counter(0), m_rx_clock_counter(0),
+ m_clock_mode(INTERNAL_ASYNC), m_ext_clock_value(false), m_rx_value(true),
+ m_rdr(0), m_tdr(0), m_smr(0), m_scr(0), m_ssr(0), m_brr(0), m_rsr(0), m_tsr(0), m_clock_event(0), m_divider(0)
{
- external_clock_period = attotime::never;
+ m_external_clock_period = attotime::never;
}
-void h8_sci_device::set_info(const char *_intc_tag, int eri, int rxi, int txi, int tei)
+void h8_sci_device::do_set_external_clock_period(const attotime &period)
{
- intc_tag = _intc_tag;
- eri_int = eri;
- rxi_int = rxi;
- txi_int = txi;
- tei_int = tei;
+ m_external_clock_period = period;
}
-void h8_sci_device::set_external_clock_period(const attotime &period)
+void h8_sci_device::smr_w(u8 data)
{
- external_clock_period = period;
-}
+ m_smr = data;
+
+ LOGMASKED(LOG_REGS, "smr_w %02x %s %c%c%c%s /%d (%06x)\n", data,
+ data & SMR_CA ? "sync" : "async",
+ data & SMR_CHR ? '7' : '8',
+ data & SMR_PE ? data & SMR_OE ? 'o' : 'e' : 'n',
+ data & SMR_STOP ? '2' : '1',
+ data & SMR_MP ? " mp" : "",
+ 1 << 2*(data & SMR_CKS),
+ m_cpu->pc());
-void h8_sci_device::smr_w(uint8_t data)
-{
- smr = data;
- if(V>=2) logerror("smr_w %02x %s %c%c%c%s /%d (%06x)\n", data,
- data & SMR_CA ? "sync" : "async",
- data & SMR_CHR ? '7' : '8',
- data & SMR_PE ? data & SMR_OE ? 'o' : 'e' : 'n',
- data & SMR_STOP ? '2' : '1',
- data & SMR_MP ? " mp" : "",
- 1 << 2*(data & SMR_CKS),
- cpu->pc());
clock_update();
}
-uint8_t h8_sci_device::smr_r()
+u8 h8_sci_device::smr_r()
{
- if(V>=2) logerror("smr_r %02x (%06x)\n", smr, cpu->pc());
- return smr;
+ LOGMASKED(LOG_RREGS, "smr_r %02x (%06x)\n", m_smr, m_cpu->pc());
+ return m_smr;
}
-void h8_sci_device::brr_w(uint8_t data)
+void h8_sci_device::brr_w(u8 data)
{
- brr = data;
- if(V>=2) logerror("brr_w %02x (%06x)\n", data, cpu->pc());
+ m_brr = data;
+ LOGMASKED(LOG_REGS, "brr_w %02x (%06x)\n", m_brr, m_cpu->pc());
clock_update();
}
-uint8_t h8_sci_device::brr_r()
+u8 h8_sci_device::brr_r()
{
- if(V>=2) logerror("brr_r %02x (%06x)\n", brr, cpu->pc());
- return brr;
+ LOGMASKED(LOG_RREGS, "brr_r %02x (%06x)\n", m_brr, m_cpu->pc());
+ return m_brr;
}
bool h8_sci_device::is_sync_start() const
{
- return (smr & SMR_CA) && ((scr & (SCR_TE|SCR_RE)) == (SCR_TE|SCR_RE));
+ return (m_smr & SMR_CA) && ((m_scr & (SCR_TE|SCR_RE)) == (SCR_TE|SCR_RE));
}
bool h8_sci_device::has_recv_error() const
{
- return ssr & (SSR_ORER|SSR_PER|SSR_FER);
+ return m_ssr & (SSR_ORER|SSR_PER|SSR_FER);
}
-void h8_sci_device::scr_w(uint8_t data)
+void h8_sci_device::scr_w(u8 data)
{
- if(V>=2) logerror("scr_w %02x%s%s%s%s%s%s clk=%d (%06x)\n", data,
- data & SCR_TIE ? " txi" : "",
- data & SCR_RIE ? " rxi" : "",
- data & SCR_TE ? " tx" : "",
- data & SCR_RE ? " rx" : "",
- data & SCR_MPIE ? " mpi" : "",
- data & SCR_TEIE ? " tei" : "",
- data & SCR_CKE,
- cpu->pc());
+ LOGMASKED(LOG_REGS, "scr_w %02x%s%s%s%s%s%s clk=%d (%06x)\n", data,
+ data & SCR_TIE ? " txi" : "",
+ data & SCR_RIE ? " rxi" : "",
+ data & SCR_TE ? " tx" : "",
+ data & SCR_RE ? " rx" : "",
+ data & SCR_MPIE ? " mpi" : "",
+ data & SCR_TEIE ? " tei" : "",
+ data & SCR_CKE,
+ m_cpu->pc());
- uint8_t delta = scr ^ data;
- scr = data;
+ u8 delta = m_scr ^ data;
+ m_scr = data;
clock_update();
- if((delta & SCR_RE) && !(scr & SCR_RE)) {
- rx_state = ST_IDLE;
+ if((delta & SCR_RE) && !(m_scr & SCR_RE)) {
+ m_rx_state = ST_IDLE;
clock_stop(CLK_RX);
}
- if((delta & SCR_RE) && (scr & SCR_RE) && rx_state == ST_IDLE && !has_recv_error() && !is_sync_start())
+ if((delta & SCR_RE) && (m_scr & SCR_RE) && m_rx_state == ST_IDLE && !has_recv_error() && !is_sync_start())
rx_start();
- if((delta & SCR_TIE) && (scr & SCR_TIE) && (ssr & SSR_TDRE))
- intc->internal_interrupt(txi_int);
- if((delta & SCR_TEIE) && (scr & SCR_TEIE) && (ssr & SSR_TEND))
- intc->internal_interrupt(tei_int);
- if((delta & SCR_RIE) && (scr & SCR_RIE) && (ssr & SSR_RDRF))
- intc->internal_interrupt(rxi_int);
- if((delta & SCR_RIE) && (scr & SCR_RIE) && has_recv_error())
- intc->internal_interrupt(eri_int);
+ if((delta & SCR_TIE) && (m_scr & SCR_TIE) && (m_ssr & SSR_TDRE))
+ m_intc->internal_interrupt(m_txi_int);
+ if((delta & SCR_TEIE) && (m_scr & SCR_TEIE) && (m_ssr & SSR_TEND))
+ m_intc->internal_interrupt(m_tei_int);
+ if((delta & SCR_RIE) && (m_scr & SCR_RIE) && (m_ssr & SSR_RDRF))
+ m_intc->internal_interrupt(m_rxi_int);
+ if((delta & SCR_RIE) && (m_scr & SCR_RIE) && has_recv_error())
+ m_intc->internal_interrupt(m_eri_int);
}
-uint8_t h8_sci_device::scr_r()
+u8 h8_sci_device::scr_r()
{
- if(V>=2) logerror("scr_r %02x (%06x)\n", scr, cpu->pc());
- return scr;
+ LOGMASKED(LOG_RREGS, "scr_r %02x (%06x)\n", m_scr, m_cpu->pc());
+ return m_scr;
}
-void h8_sci_device::tdr_w(uint8_t data)
+void h8_sci_device::tdr_w(u8 data)
{
- if(V>=2) logerror("tdr_w %02x (%06x)\n", data, cpu->pc());
- tdr = data;
- if(cpu->access_is_dma()) {
- ssr &= ~SSR_TDRE;
- if(tx_state == ST_IDLE)
+ LOGMASKED(LOG_REGS, "tdr_w %02x (%06x)\n", data, m_cpu->pc());
+ m_tdr = data;
+ if(m_cpu->access_is_dma()) {
+ m_ssr &= ~SSR_TDRE;
+ if(m_tx_state == ST_IDLE)
tx_start();
}
}
-uint8_t h8_sci_device::tdr_r()
+u8 h8_sci_device::tdr_r()
{
- if(V>=2) logerror("tdr_r %02x (%06x)\n", tdr, cpu->pc());
- return tdr;
+ LOGMASKED(LOG_RREGS, "tdr_r %02x (%06x)\n", m_tdr, m_cpu->pc());
+ return m_tdr;
}
-void h8_sci_device::ssr_w(uint8_t data)
+void h8_sci_device::ssr_w(u8 data)
{
- if(!(scr & SCR_TE)) {
+ if(!(m_scr & SCR_TE)) {
data |= SSR_TDRE;
- ssr |= SSR_TDRE;
+ m_ssr |= SSR_TDRE;
}
- if((ssr & SSR_TDRE) && !(data & SSR_TDRE))
- ssr &= ~SSR_TEND;
- ssr = ((ssr & ~SSR_MPBT) | (data & SSR_MPBT)) & (data | (SSR_TEND|SSR_MPB|SSR_MPBT));
- if(V>=2) logerror("ssr_w %02x -> %02x (%06x)\n", data, ssr, cpu->pc());
+ if((m_ssr & SSR_TDRE) && !(data & SSR_TDRE))
+ m_ssr &= ~SSR_TEND;
+ m_ssr = ((m_ssr & ~SSR_MPBT) | (data & SSR_MPBT)) & (data | (SSR_TEND|SSR_MPB|SSR_MPBT));
+ LOGMASKED(LOG_REGS, "ssr_w %02x -> %02x (%06x)\n", data, m_ssr, m_cpu->pc());
- if(tx_state == ST_IDLE && !(ssr & SSR_TDRE))
+ if(m_tx_state == ST_IDLE && !(m_ssr & SSR_TDRE))
tx_start();
- if((scr & SCR_RE) && rx_state == ST_IDLE && !has_recv_error() && !is_sync_start())
+ if((m_scr & SCR_RE) && m_rx_state == ST_IDLE && !has_recv_error() && !is_sync_start())
rx_start();
}
-uint8_t h8_sci_device::ssr_r()
+u8 h8_sci_device::ssr_r()
{
- if(V>=3) logerror("ssr_r %02x (%06x)\n", ssr, cpu->pc());
- return ssr;
+ LOGMASKED(LOG_RREGS, "ssr_r %02x (%06x)\n", m_ssr, m_cpu->pc());
+ return m_ssr;
}
-uint8_t h8_sci_device::rdr_r()
+u8 h8_sci_device::rdr_r()
{
- if(V>=2) logerror("rdr_r %02x (%06x)\n", rdr, cpu->pc());
- if(cpu->access_is_dma())
- ssr &= ~SSR_RDRF;
- return rdr;
+ LOGMASKED(LOG_RREGS, "rdr_r %02x (%06x)\n", m_rdr, m_cpu->pc());
+
+ if(!machine().side_effects_disabled() && m_cpu->access_is_dma())
+ m_ssr &= ~SSR_RDRF;
+ return m_rdr;
}
-void h8_sci_device::scmr_w(uint8_t data)
+void h8_sci_device::scmr_w(u8 data)
{
- if(V>=2) logerror("scmr_w %02x (%06x)\n", data, cpu->pc());
+ LOGMASKED(LOG_REGS, "scmr_w %02x (%06x)\n", data, m_cpu->pc());
}
-uint8_t h8_sci_device::scmr_r()
+u8 h8_sci_device::scmr_r()
{
- if(V>=2) logerror("scmr_r (%06x)\n", cpu->pc());
+ LOGMASKED(LOG_RREGS, "scmr_r (%06x)\n", m_cpu->pc());
return 0x00;
}
void h8_sci_device::clock_update()
{
- // Sync: Divider must be the time of a half-period (both edges are used, datarate*2)
- // Async: Divider must be the time of one period (only raising edge used, datarate*16)
-
- divider = 2 << (2*(smr & SMR_CKS));
- divider *= brr+1;
+ m_divider = 2 << (2*(m_smr & SMR_CKS));
+ m_divider *= m_brr+1;
- if(smr & SMR_CA) {
- if(scr & SCR_CKE1)
- clock_mode = CLKM_EXTERNAL_SYNC;
+ if(m_smr & SMR_CA) {
+ if(m_scr & SCR_CKE1)
+ m_clock_mode = EXTERNAL_SYNC;
else
- clock_mode = CLKM_INTERNAL_SYNC_OUT;
+ m_clock_mode = INTERNAL_SYNC_OUT;
} else {
- if(scr & SCR_CKE1)
- clock_mode = CLKM_EXTERNAL_ASYNC;
- else if(scr & SCR_CKE0)
- clock_mode = CLKM_INTERNAL_ASYNC_OUT;
+ if(m_scr & SCR_CKE1)
+ m_clock_mode = EXTERNAL_ASYNC;
+ else if(m_scr & SCR_CKE0)
+ m_clock_mode = INTERNAL_ASYNC_OUT;
else
- clock_mode = CLKM_INTERNAL_ASYNC;
+ m_clock_mode = INTERNAL_ASYNC;
}
- if(clock_mode == CLKM_EXTERNAL_ASYNC && !external_clock_period.is_never())
- clock_mode = CLKM_EXTERNAL_RATE_ASYNC;
- if(clock_mode == CLKM_EXTERNAL_SYNC && !external_clock_period.is_never())
- clock_mode = CLKM_EXTERNAL_RATE_SYNC;
+ if(m_clock_mode == EXTERNAL_ASYNC && !m_external_clock_period.is_never())
+ m_clock_mode = EXTERNAL_RATE_ASYNC;
+ if(m_clock_mode == EXTERNAL_SYNC && !m_external_clock_period.is_never())
+ m_clock_mode = EXTERNAL_RATE_SYNC;
- if(V>=1) {
- char buf[4096];
- switch(clock_mode) {
- case CLKM_INTERNAL_ASYNC:
- sprintf(buf, "clock internal at %d Hz, async, bitrate %d bps\n", int(cpu->clock() / divider), int(cpu->clock() / (divider*16)));
+ if(VERBOSE & LOG_RATE) {
+ std::string new_message;
+ switch(m_clock_mode) {
+ case INTERNAL_ASYNC:
+ new_message = util::string_format("clock internal at %d Hz, async, bitrate %d bps\n", int(m_cpu->clock() / m_divider), int(m_cpu->clock() / (m_divider*16)));
break;
- case CLKM_INTERNAL_ASYNC_OUT:
- sprintf(buf, "clock internal at %d Hz, async, bitrate %d bps, output\n", int(cpu->clock() / divider), int(cpu->clock() / (divider*16)));
+ case INTERNAL_ASYNC_OUT:
+ new_message = util::string_format("clock internal at %d Hz, async, bitrate %d bps, output\n", int(m_cpu->clock() / m_divider), int(m_cpu->clock() / (m_divider*16)));
break;
-
- case CLKM_EXTERNAL_ASYNC:
- sprintf(buf, "clock external, async\n");
+ case EXTERNAL_ASYNC:
+ new_message = "clock external, async\n";
break;
- case CLKM_EXTERNAL_RATE_ASYNC:
- sprintf(buf, "clock external at %d Hz, async, bitrate %d bps\n", int(cpu->clock()*internal_to_external_ratio), int(cpu->clock()*internal_to_external_ratio/16));
+ case EXTERNAL_RATE_ASYNC:
+ new_message = util::string_format("clock external at %d Hz, async, bitrate %d bps\n", int(m_cpu->clock()*m_internal_to_external_ratio), int(m_cpu->clock()*m_internal_to_external_ratio/16));
break;
-
- case CLKM_INTERNAL_SYNC_OUT:
- sprintf(buf, "clock internal at %d Hz, sync, output\n", int(cpu->clock() / (divider*2)));
+ case INTERNAL_SYNC_OUT:
+ new_message = util::string_format("clock internal at %d Hz, sync, output\n", int(m_cpu->clock() / (m_divider*2)));
break;
-
- case CLKM_EXTERNAL_SYNC:
- sprintf(buf, "clock external, sync\n");
+ case EXTERNAL_SYNC:
+ new_message = "clock external, sync\n";
break;
- case CLKM_EXTERNAL_RATE_SYNC:
- sprintf(buf, "clock external at %d Hz, sync\n", int(cpu->clock()*internal_to_external_ratio));
+ case EXTERNAL_RATE_SYNC:
+ new_message = util::string_format("clock external at %d Hz, sync\n", int(m_cpu->clock()*m_internal_to_external_ratio));
break;
}
- if(buf != last_clock_message) {
- last_clock_message = buf;
- logerror("%s", buf);
+ if(new_message != m_last_clock_message) {
+ (LOG_OUTPUT_FUNC)(new_message);
+ m_last_clock_message = std::move(new_message);
}
}
}
void h8_sci_device::device_start()
{
- tx_cb.resolve_safe();
- clk_cb.resolve_safe();
+ m_sync_timer = timer_alloc(FUNC(h8_sci_device::sync_tick), this);
- sync_timer = timer_alloc(0);
-
- if(external_clock_period.is_never()) {
- internal_to_external_ratio = 0;
- external_to_internal_ratio = 0;
+ if(m_external_clock_period.is_never()) {
+ m_internal_to_external_ratio = 0;
+ m_external_to_internal_ratio = 0;
} else {
- external_to_internal_ratio = (external_clock_period*cpu->clock()).as_double();
- internal_to_external_ratio = 1/external_to_internal_ratio;
+ m_external_to_internal_ratio = (m_external_clock_period*m_cpu->clock()).as_double();
+ m_internal_to_external_ratio = 1/m_external_to_internal_ratio;
}
- intc = siblingdevice<h8_intc_device>(intc_tag);
- save_item(NAME(rdr));
- save_item(NAME(tdr));
- save_item(NAME(smr));
- save_item(NAME(scr));
- save_item(NAME(ssr));
- save_item(NAME(brr));
- save_item(NAME(rsr));
- save_item(NAME(tsr));
- save_item(NAME(rx_bit));
- save_item(NAME(tx_bit));
- save_item(NAME(rx_state));
- save_item(NAME(tx_state));
- save_item(NAME(tx_parity));
- save_item(NAME(clock_state));
- save_item(NAME(clock_value));
- save_item(NAME(clock_base));
- save_item(NAME(divider));
- save_item(NAME(ext_clock_value));
- save_item(NAME(ext_clock_counter));
- save_item(NAME(cur_sync_time));
+ save_item(NAME(m_tx_state));
+ save_item(NAME(m_rx_state));
+ save_item(NAME(m_tx_bit));
+ save_item(NAME(m_rx_bit));
+ save_item(NAME(m_clock_state));
+ save_item(NAME(m_tx_parity));
+ save_item(NAME(m_rx_parity));
+ save_item(NAME(m_tx_clock_counter));
+ save_item(NAME(m_rx_clock_counter));
+ save_item(NAME(m_clock_mode));
+ save_item(NAME(m_ext_clock_value));
+ save_item(NAME(m_rx_value));
+
+ save_item(NAME(m_rdr));
+ save_item(NAME(m_tdr));
+ save_item(NAME(m_smr));
+ save_item(NAME(m_scr));
+ save_item(NAME(m_ssr));
+ save_item(NAME(m_brr));
+ save_item(NAME(m_rsr));
+ save_item(NAME(m_tsr));
+ save_item(NAME(m_clock_event));
+ save_item(NAME(m_clock_step));
+ save_item(NAME(m_divider));
}
void h8_sci_device::device_reset()
{
- rdr = 0x00;
- tdr = 0xff;
- smr = 0x00;
- scr = 0x00;
- ssr = 0x84;
- brr = 0xff;
- rsr = 0x00;
- tsr = 0xff;
- rx_bit = 0;
- tx_bit = 0;
- tx_state = ST_IDLE;
- rx_state = ST_IDLE;
- clock_state = 0;
- clock_mode = CLKM_INTERNAL_ASYNC;
- clock_base = 0;
+ m_rdr = 0x00;
+ m_tdr = 0xff;
+ m_smr = 0x00;
+ m_scr = 0x00;
+ m_ssr = 0x84;
+ m_brr = 0xff;
+ m_rsr = 0x00;
+ m_tsr = 0xff;
+ m_rx_bit = 0;
+ m_tx_bit = 0;
+ m_tx_state = ST_IDLE;
+ m_rx_state = ST_IDLE;
+ m_clock_state = 0;
+ m_clock_mode = INTERNAL_ASYNC;
+ m_clock_event = 0;
clock_update();
- clock_value = true;
- ext_clock_value = true;
- ext_clock_counter = 0;
- rx_value = true;
- clk_cb(clock_value);
- tx_cb(1);
- cur_sync_time = attotime::never;
+ m_ext_clock_value = true;
+ m_tx_clock_counter = 0;
+ m_rx_clock_counter = 0;
+ m_cpu->do_sci_clk(m_id, 1);
+ m_cpu->do_sci_tx(m_id, 1);
}
-void h8_sci_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
+TIMER_CALLBACK_MEMBER(h8_sci_device::sync_tick)
{
// Used only to force system-wide syncs
}
-WRITE_LINE_MEMBER(h8_sci_device::rx_w)
+void h8_sci_device::do_rx_w(int state)
{
- rx_value = state;
- if(V>=2) logerror("rx=%d\n", state);
- if(!rx_value && !(clock_state & CLK_RX) && rx_state != ST_IDLE)
+ if(m_cpu->standby()) {
+ m_rx_value = state;
+ return;
+ }
+
+ if(state != m_rx_value && (m_clock_state & CLK_RX))
+ if(m_rx_clock_counter == 1 || m_rx_clock_counter == 15)
+ m_rx_clock_counter = 0;
+
+ m_rx_value = state;
+ if(!m_rx_value && !(m_clock_state & CLK_RX) && m_rx_state != ST_IDLE)
clock_start(CLK_RX);
}
-WRITE_LINE_MEMBER(h8_sci_device::clk_w)
+void h8_sci_device::do_clk_w(int state)
{
- if(ext_clock_value != state) {
- ext_clock_value = state;
- if(clock_state) {
- switch(clock_mode) {
- case CLKM_EXTERNAL_ASYNC:
- if(ext_clock_value) {
- ext_clock_counter = (ext_clock_counter+1) & 15;
-
- if((clock_state & CLK_TX) && ext_clock_counter == 0)
- tx_dropped_edge();
- if((clock_state & CLK_RX) && ext_clock_counter == 8)
- rx_raised_edge();
- }
- break;
+ if(m_ext_clock_value == state)
+ return;
- case CLKM_EXTERNAL_SYNC:
- if((!ext_clock_value) && (clock_state & CLK_TX))
- tx_dropped_edge();
+ m_ext_clock_value = state;
+ if(!m_clock_state || m_cpu->standby())
+ return;
- else if(ext_clock_value && (clock_state & CLK_RX))
- rx_raised_edge();
- break;
- }
- }
+ if(m_clock_mode == EXTERNAL_ASYNC) {
+ if(m_clock_state & CLK_TX)
+ tx_async_tick();
+ if(m_clock_state & CLK_RX)
+ rx_async_tick();
+ } else if(m_clock_mode == EXTERNAL_SYNC) {
+ if(m_clock_state & CLK_TX)
+ tx_sync_tick();
+ if(m_clock_state & CLK_RX)
+ rx_sync_tick();
}
}
-uint64_t h8_sci_device::internal_update(uint64_t current_time)
+u64 h8_sci_device::internal_update(u64 current_time)
{
- uint64_t event = 0;
- switch(clock_mode) {
- case CLKM_INTERNAL_SYNC_OUT:
- if(clock_state || !clock_value) {
- uint64_t fp = divider*2;
- if(current_time >= clock_base) {
- uint64_t delta = current_time - clock_base;
- if(delta >= fp) {
- delta -= fp;
- clock_base += fp;
- }
- assert(delta < fp);
-
- bool new_clock = delta >= divider;
- if(new_clock != clock_value) {
- cpu->synchronize();
- if((!new_clock) && (clock_state & CLK_TX))
- tx_dropped_edge();
+ if(!m_clock_event || current_time < m_clock_event)
+ return m_clock_event;
- else if(new_clock && (clock_state & CLK_RX))
- rx_raised_edge();
-
- clock_value = new_clock;
- if(clock_state || clock_value)
- clk_cb(clock_value);
- }
- }
- event = clock_base + (clock_value ? fp : divider);
- }
- break;
-
- case CLKM_INTERNAL_ASYNC:
- case CLKM_INTERNAL_ASYNC_OUT:
- if(clock_state || !clock_value) {
- uint64_t fp = divider*16;
- if(current_time >= clock_base) {
- uint64_t delta = current_time - clock_base;
- if(delta >= fp) {
- delta -= fp;
- clock_base += fp;
- }
- assert(delta < fp);
- bool new_clock = delta >= divider*8;
- if(new_clock != clock_value) {
- cpu->synchronize();
- if((!new_clock) && (clock_state & CLK_TX))
- tx_dropped_edge();
-
- else if(new_clock && (clock_state & CLK_RX))
- rx_raised_edge();
-
- clock_value = new_clock;
- if(clock_mode == CLKM_INTERNAL_ASYNC_OUT && (clock_state || !clock_value))
- clk_cb(clock_value);
- }
- }
-
- event = clock_base + (clock_value ? fp : divider*8);
- }
- break;
-
- case CLKM_EXTERNAL_RATE_SYNC:
- if(clock_state || !clock_value) {
- uint64_t ctime = uint64_t(current_time*internal_to_external_ratio*2);
- if(ctime >= clock_base) {
- uint64_t delta = ctime - clock_base;
- clock_base += delta & ~1;
- delta &= 1;
- bool new_clock = delta >= 1;
- if(new_clock != clock_value) {
- cpu->synchronize();
- if((!new_clock) && (clock_state & CLK_TX))
- tx_dropped_edge();
-
- else if(new_clock && (clock_state & CLK_RX))
- rx_raised_edge();
-
- clock_value = new_clock;
- }
- }
-
- event = uint64_t((clock_base + (clock_value ? 2 : 1))*external_to_internal_ratio)+1;
- }
- break;
+ if(m_clock_mode == INTERNAL_ASYNC || m_clock_mode == INTERNAL_ASYNC_OUT || m_clock_mode == EXTERNAL_RATE_ASYNC) {
+ if(m_clock_state & CLK_TX)
+ tx_async_tick();
+ if(m_clock_state & CLK_RX)
+ rx_async_tick();
+ } else if(m_clock_mode == INTERNAL_SYNC_OUT || m_clock_mode == EXTERNAL_RATE_SYNC) {
+ if(m_clock_state & CLK_TX)
+ tx_sync_tick();
+ if(m_clock_state & CLK_RX)
+ rx_sync_tick();
+ }
- case CLKM_EXTERNAL_RATE_ASYNC:
- if(clock_state || !clock_value) {
- uint64_t ctime = uint64_t(current_time*internal_to_external_ratio);
- if(ctime >= clock_base) {
- uint64_t delta = ctime - clock_base;
- clock_base += delta & ~15;
- delta &= 15;
- bool new_clock = delta >= 8;
- if(new_clock != clock_value) {
- cpu->synchronize();
- if((!new_clock) && (clock_state & CLK_TX))
- tx_dropped_edge();
-
- else if(new_clock && (clock_state & CLK_RX))
- rx_raised_edge();
-
- clock_value = new_clock;
- }
- }
+ if(m_clock_state) {
+ if(m_clock_step)
+ m_clock_event += m_clock_step;
+ else if(m_clock_mode == EXTERNAL_RATE_ASYNC || m_clock_mode == EXTERNAL_RATE_SYNC)
+ m_clock_event = u64(u64(m_clock_event * m_internal_to_external_ratio + 1) * m_external_to_internal_ratio + 1);
+ else
+ m_clock_event = 0;
- event = uint64_t((clock_base + (clock_value ? 16 : 8))*external_to_internal_ratio)+1;
+ if(m_clock_event) {
+ m_sync_timer->adjust(attotime::from_ticks(m_clock_event - m_cpu->now_as_cycles(), m_cpu->clock()));
+ m_cpu->internal_update();
}
- break;
- case CLKM_EXTERNAL_ASYNC:
- case CLKM_EXTERNAL_SYNC:
- break;
- }
- if(event) {
- attotime ctime = machine().time();
- attotime sync_time = attotime::from_ticks(event-10, cpu->clock());
- if(cur_sync_time != sync_time && sync_time > ctime) {
- sync_timer->adjust(sync_time - ctime);
- cur_sync_time = sync_time;
- }
+ } else if(!m_clock_state) {
+ m_clock_event = 0;
+ if(m_clock_mode == INTERNAL_ASYNC_OUT || m_clock_mode == INTERNAL_SYNC_OUT)
+ m_cpu->do_sci_clk(m_id, 1);
}
- return event;
+ return m_clock_event;
+}
+
+void h8_sci_device::notify_standby(int state)
+{
+ if(!state && m_clock_event)
+ m_clock_event += m_cpu->total_cycles() - m_cpu->standby_time();
}
void h8_sci_device::clock_start(int mode)
{
// Happens when back-to-back
- if(clock_state & mode)
+ if(m_clock_state & mode)
return;
- if(!clock_state) {
- cpu->synchronize();
- clock_state = mode;
- switch(clock_mode) {
- case CLKM_INTERNAL_ASYNC:
- case CLKM_INTERNAL_ASYNC_OUT:
- case CLKM_INTERNAL_SYNC_OUT:
- if(V>=2) logerror("Starting internal clock\n");
- clock_base = cpu->total_cycles();
- cpu->internal_update();
- break;
+ if(mode == CLK_TX)
+ m_tx_clock_counter = 15;
+ else
+ m_rx_clock_counter = 15;
- case CLKM_EXTERNAL_RATE_ASYNC:
- if(V>=2) logerror("Simulating external clock async\n");
- clock_base = uint64_t(cpu->total_cycles()*internal_to_external_ratio);
- cpu->internal_update();
- break;
+ m_clock_state |= mode;
+ if(m_clock_state != mode)
+ return;
- case CLKM_EXTERNAL_RATE_SYNC:
- if(V>=2) logerror("Simulating external clock sync\n");
- clock_base = uint64_t(cpu->total_cycles()*2*internal_to_external_ratio);
- cpu->internal_update();
- break;
+ m_clock_step = 0;
+
+ switch(m_clock_mode) {
+ case INTERNAL_ASYNC:
+ case INTERNAL_ASYNC_OUT:
+ case INTERNAL_SYNC_OUT: {
+ LOGMASKED(LOG_CLOCK, "Starting internal clock\n");
+ m_clock_step = m_divider;
+ u64 now = mode == CLK_TX ? m_cpu->total_cycles() : m_cpu->now_as_cycles();
+ m_clock_event = (now / m_clock_step + 1) * m_clock_step;
+ m_sync_timer->adjust(attotime::from_ticks(m_clock_event - now, m_cpu->clock()));
+ m_cpu->internal_update();
+ break;
+ }
- case CLKM_EXTERNAL_ASYNC:
- if(V>=2) logerror("Waiting for external clock async\n");
- ext_clock_counter = 15;
- break;
+ case EXTERNAL_RATE_ASYNC:
+ case EXTERNAL_RATE_SYNC: {
+ LOGMASKED(LOG_CLOCK, "Simulating external clock\n", m_clock_mode == EXTERNAL_RATE_ASYNC ? "async" : "sync");
+ u64 now = mode == CLK_TX ? m_cpu->total_cycles() : m_cpu->now_as_cycles();
+ m_clock_event = u64(u64(now * m_internal_to_external_ratio + 1) * m_external_to_internal_ratio + 1);
+ m_sync_timer->adjust(attotime::from_ticks(m_clock_event - now, m_cpu->clock()));
+ m_cpu->internal_update();
+ break;
+ }
- case CLKM_EXTERNAL_SYNC:
- if(V>=2) logerror("Waiting for external clock sync\n");
- break;
- }
- } else
- clock_state |= mode;
+ case EXTERNAL_ASYNC:
+ case EXTERNAL_SYNC:
+ LOGMASKED(LOG_CLOCK, "Waiting for external clock\n");
+ break;
+ }
}
void h8_sci_device::clock_stop(int mode)
{
- clock_state &= ~mode;
- cpu->internal_update();
+ m_clock_state &= ~mode;
+ if(!m_clock_state) {
+ m_clock_event = 0;
+ m_clock_step = 0;
+ LOGMASKED(LOG_CLOCK, "Stopping clocks\n");
+ }
+ m_cpu->internal_update();
}
void h8_sci_device::tx_start()
{
- ssr |= SSR_TDRE;
- tsr = tdr;
- tx_parity = smr & SMR_OE ? 0 : 1;
- if(V>=1) logerror("start transmit %02x '%c'\n", tsr, tsr >= 32 && tsr < 127 ? tsr : '.');
- if(scr & SCR_TIE)
- intc->internal_interrupt(txi_int);
- if(smr & SMR_CA) {
- tx_state = ST_BIT;
- tx_bit = 8;
+ m_ssr |= SSR_TDRE;
+ m_tsr = m_tdr;
+ m_tx_parity = m_smr & SMR_OE ? 0 : 1;
+ LOGMASKED(LOG_DATA, "start transmit %02x '%c'\n", m_tsr, m_tsr >= 32 && m_tsr < 127 ? m_tsr : '.');
+ if(m_scr & SCR_TIE)
+ m_intc->internal_interrupt(m_txi_int);
+ if(m_smr & SMR_CA) {
+ m_tx_state = ST_BIT;
+ m_tx_bit = 8;
} else {
- tx_state = ST_START;
- tx_bit = 1;
+ m_tx_state = ST_START;
+ m_tx_bit = 1;
}
clock_start(CLK_TX);
- if(rx_state == ST_IDLE && !has_recv_error() && is_sync_start())
+ if(m_rx_state == ST_IDLE && !has_recv_error() && is_sync_start())
rx_start();
}
-void h8_sci_device::tx_dropped_edge()
+void h8_sci_device::tx_async_tick()
{
- if(V>=2) logerror("tx_dropped_edge state=%s bit=%d\n", state_names[tx_state], tx_bit);
- switch(tx_state) {
+ m_tx_clock_counter = (m_tx_clock_counter + 1) & 15;
+ LOGMASKED(LOG_TICK, "tx_async_tick %x\n", m_tx_clock_counter);
+ if(m_tx_clock_counter == 0) {
+ tx_async_step();
+
+ if(m_clock_mode == INTERNAL_ASYNC_OUT)
+ m_cpu->do_sci_clk(m_id, 0);
+
+ } else if(m_tx_clock_counter == 8 && m_clock_mode == INTERNAL_ASYNC_OUT)
+ m_cpu->do_sci_clk(m_id, 1);
+}
+
+void h8_sci_device::tx_async_step()
+{
+ LOGMASKED(LOG_STATE, "tx_async_step state=%s bit=%d\n", state_names[m_tx_state], m_tx_bit);
+ switch(m_tx_state) {
case ST_START:
- tx_cb(false);
- assert(tx_bit == 1);
- tx_state = ST_BIT;
- tx_bit = smr & SMR_CHR ? 7 : 8;
+ m_cpu->do_sci_tx(m_id, false);
+ assert(m_tx_bit == 1);
+ m_tx_state = ST_BIT;
+ m_tx_bit = m_smr & SMR_CHR ? 7 : 8;
break;
case ST_BIT:
- tx_parity ^= (tsr & 1);
- tx_cb(tsr & 1);
- tsr >>= 1;
- tx_bit--;
- if(!tx_bit) {
- if(smr & SMR_CA) {
- if(!(ssr & SSR_TDRE))
+ m_tx_parity ^= (m_tsr & 1);
+ m_cpu->do_sci_tx(m_id, m_tsr & 1);
+ m_tsr >>= 1;
+ m_tx_bit--;
+ if(!m_tx_bit) {
+ if(m_smr & SMR_CA) {
+ if(!(m_ssr & SSR_TDRE))
tx_start();
else {
- tx_state = ST_LAST_TICK;
- tx_bit = 0;
+ m_tx_state = ST_LAST_TICK;
+ m_tx_bit = 0;
}
- } else if(smr & SMR_PE) {
- tx_state = ST_PARITY;
- tx_bit = 1;
+ } else if(m_smr & SMR_PE) {
+ m_tx_state = ST_PARITY;
+ m_tx_bit = 1;
} else {
- tx_state = ST_STOP;
- tx_bit = smr & SMR_STOP ? 2 : 1;
+ m_tx_state = ST_STOP;
+ m_tx_bit = m_smr & SMR_STOP ? 2 : 1;
}
}
break;
case ST_PARITY:
- tx_cb(tx_parity);
- assert(tx_bit == 1);
- tx_state = ST_STOP;
- tx_bit = smr & SMR_STOP ? 2 : 1;
+ m_cpu->do_sci_tx(m_id, m_tx_parity);
+ assert(m_tx_bit == 1);
+ m_tx_state = ST_STOP;
+ m_tx_bit = m_smr & SMR_STOP ? 2 : 1;
break;
case ST_STOP:
- tx_cb(true);
- tx_bit--;
- if(!tx_bit) {
- if(!(ssr & SSR_TDRE))
- tx_start();
+ m_cpu->do_sci_tx(m_id, true);
+ m_tx_bit--;
+ if(!m_tx_bit) {
+ if(!(m_ssr & SSR_TDRE))
+ tx_start();
else {
- tx_state = ST_LAST_TICK;
- tx_bit = 0;
+ m_tx_state = ST_LAST_TICK;
+ m_tx_bit = 0;
}
}
break;
case ST_LAST_TICK:
- tx_state = ST_IDLE;
- tx_bit = 0;
+ m_tx_state = ST_IDLE;
+ m_tx_bit = 0;
clock_stop(CLK_TX);
- tx_cb(1);
- ssr |= SSR_TEND;
- if(scr & SCR_TEIE)
- intc->internal_interrupt(tei_int);
+ m_cpu->do_sci_tx(m_id, 1);
+ m_ssr |= SSR_TEND;
+ if(m_scr & SCR_TEIE)
+ m_intc->internal_interrupt(m_tei_int);
// if there's more to send, start the transmitter
- if ((scr & SCR_TE) && !(ssr & SSR_TDRE))
+ if((m_scr & SCR_TE) && !(m_ssr & SSR_TDRE))
tx_start();
break;
default:
abort();
}
- if(V>=2) logerror(" -> state=%s bit=%d\n", state_names[tx_state], tx_bit);
+ LOGMASKED(LOG_STATE, " -> state=%s bit=%d\n", state_names[m_tx_state], m_tx_bit);
+}
+
+void h8_sci_device::tx_sync_tick()
+{
+ m_tx_clock_counter = (m_tx_clock_counter + 1) & 1;
+ LOGMASKED(LOG_TICK, "tx_sync_tick %x\n", m_tx_clock_counter);
+ if(m_tx_clock_counter == 0) {
+ tx_sync_step();
+
+ if(m_clock_mode == INTERNAL_SYNC_OUT && m_tx_state != ST_IDLE)
+ m_cpu->do_sci_clk(m_id, 0);
+
+ } else if(m_tx_clock_counter == 1 && m_clock_mode == INTERNAL_SYNC_OUT)
+ m_cpu->do_sci_clk(m_id, 1);
+}
+
+void h8_sci_device::tx_sync_step()
+{
+ LOGMASKED(LOG_STATE, "tx_sync_step bit=%d\n", m_tx_bit);
+ if(!m_tx_bit) {
+ m_tx_state = ST_IDLE;
+ clock_stop(CLK_TX);
+ m_cpu->do_sci_tx(m_id, 1);
+ m_ssr |= SSR_TEND;
+ if(m_scr & SCR_TEIE)
+ m_intc->internal_interrupt(m_tei_int);
+
+ // if there's more to send, start the transmitter
+ if((m_scr & SCR_TE) && !(m_ssr & SSR_TDRE))
+ tx_start();
+ } else {
+ m_cpu->do_sci_tx(m_id, m_tsr & 1);
+ m_tsr >>= 1;
+ m_tx_bit--;
+ }
}
void h8_sci_device::rx_start()
{
- ssr |= SSR_TDRE;
- rx_parity = smr & SMR_OE ? 0 : 1;
- rsr = 0x00;
- if(V>=2) logerror("start receive\n");
- if(smr & SMR_CA) {
- rx_state = ST_BIT;
- rx_bit = 8;
+ m_rx_parity = m_smr & SMR_OE ? 0 : 1;
+ m_rsr = 0x00;
+ LOGMASKED(LOG_STATE, "start receive\n");
+ if(m_smr & SMR_CA) {
+ m_rx_state = ST_BIT;
+ m_rx_bit = 8;
clock_start(CLK_RX);
} else {
- rx_state = ST_START;
- rx_bit = 1;
- if(!rx_value)
+ m_rx_state = ST_START;
+ m_rx_bit = 1;
+ if(!m_rx_value)
clock_start(CLK_RX);
}
}
void h8_sci_device::rx_done()
{
- if(!(ssr & SSR_FER)) {
- if((smr & SMR_PE) && rx_parity) {
- ssr |= SSR_PER;
- if(V>=1) logerror("Receive parity error\n");
- } else if(ssr & SSR_RDRF) {
- ssr |= SSR_ORER;
- if(V>=1) logerror("Receive overrun\n");
+ if(!(m_ssr & SSR_FER)) {
+ if((m_smr & SMR_PE) && m_rx_parity) {
+ m_ssr |= SSR_PER;
+ LOGMASKED(LOG_DATA, "Receive parity error\n");
+ } else if(m_ssr & SSR_RDRF) {
+ m_ssr |= SSR_ORER;
+ LOGMASKED(LOG_DATA, "Receive overrun\n");
} else {
- ssr |= SSR_RDRF;
- if(V>=1) logerror("Received %02x '%c'\n", rsr, rsr >= 32 && rsr < 127 ? rsr : '.');
- rdr = rsr;
+ m_ssr |= SSR_RDRF;
+ LOGMASKED(LOG_DATA, "Received %02x '%c'\n", m_rsr, m_rsr >= 32 && m_rsr < 127 ? m_rsr : '.');
+ m_rdr = m_rsr;
}
}
- if(scr & SCR_RIE) {
+ if(m_scr & SCR_RIE) {
if(has_recv_error())
- intc->internal_interrupt(eri_int);
+ m_intc->internal_interrupt(m_eri_int);
else
- intc->internal_interrupt(rxi_int);
+ m_intc->internal_interrupt(m_rxi_int);
}
- if((scr & SCR_RE) && !has_recv_error() && !is_sync_start())
+ if((m_scr & SCR_RE) && !has_recv_error() && !is_sync_start())
rx_start();
else {
clock_stop(CLK_RX);
- rx_state = ST_IDLE;
+ m_rx_state = ST_IDLE;
}
}
-void h8_sci_device::rx_raised_edge()
+void h8_sci_device::rx_async_tick()
+{
+ m_rx_clock_counter = (m_rx_clock_counter + 1) & 15;
+ LOGMASKED(LOG_TICK, "rx_async_tick %x\n", m_rx_clock_counter);
+ if(m_rx_clock_counter == 8)
+ rx_async_step();
+}
+
+void h8_sci_device::rx_async_step()
{
- if(V>=2) logerror("rx_raised_edge state=%s bit=%d\n", state_names[rx_state], rx_bit);
- switch(rx_state) {
+ LOGMASKED(LOG_STATE, "rx_async_step state=%s bit=%d\n", state_names[m_rx_state], m_rx_bit);
+ switch(m_rx_state) {
case ST_START:
- if(rx_value) {
+ if(m_rx_value) {
clock_stop(CLK_RX);
break;
}
- rx_state = ST_BIT;
- rx_bit = smr & SMR_CHR ? 7 : 8;
+ m_rx_state = ST_BIT;
+ m_rx_bit = m_smr & SMR_CHR ? 7 : 8;
break;
case ST_BIT:
- rx_parity ^= rx_value;
- rsr >>= 1;
- if(rx_value) {
- rx_parity = !rx_parity;
- rsr |= (smr & (SMR_CA|SMR_CHR)) == SMR_CHR ? 0x40 : 0x80;
+ m_rx_parity ^= m_rx_value;
+ m_rsr >>= 1;
+ if(m_rx_value) {
+ m_rx_parity = !m_rx_parity;
+ m_rsr |= (m_smr & (SMR_CA|SMR_CHR)) == SMR_CHR ? 0x40 : 0x80;
}
- rx_bit--;
- if(!rx_bit) {
- if(smr & SMR_CA)
+ m_rx_bit--;
+ if(!m_rx_bit) {
+ if(m_smr & SMR_CA)
rx_done();
- else if(smr & SMR_PE) {
- rx_state = ST_PARITY;
- rx_bit = 1;
+ else if(m_smr & SMR_PE) {
+ m_rx_state = ST_PARITY;
+ m_rx_bit = 1;
} else {
- rx_state = ST_STOP;
- rx_bit = 1; // Always 1 on rx
+ m_rx_state = ST_STOP;
+ m_rx_bit = 1; // Always 1 on rx
}
}
break;
case ST_PARITY:
- rx_parity ^= rx_value;
- assert(rx_bit == 1);
- rx_state = ST_STOP;
- rx_bit = 1;
+ m_rx_parity ^= m_rx_value;
+ assert(m_rx_bit == 1);
+ m_rx_state = ST_STOP;
+ m_rx_bit = 1;
break;
case ST_STOP:
- assert(rx_bit == 1);
- if(!rx_value)
- ssr |= SSR_FER;
- else if((smr & SMR_PE) && rx_parity)
- ssr |= SSR_PER;
+ assert(m_rx_bit == 1);
+ if(!m_rx_value)
+ m_ssr |= SSR_FER;
+ else if((m_smr & SMR_PE) && m_rx_parity)
+ m_ssr |= SSR_PER;
rx_done();
break;
default:
abort();
}
- if(V>=2) logerror(" -> state=%s, bit=%d\n", state_names[rx_state], rx_bit);
+ LOGMASKED(LOG_STATE, " -> state=%s, bit=%d\n", state_names[m_rx_state], m_rx_bit);
+}
+
+void h8_sci_device::rx_sync_tick()
+{
+ m_rx_clock_counter = (m_rx_clock_counter + 1) & 1;
+ LOGMASKED(LOG_TICK, "rx_sync_tick %x\n", m_rx_clock_counter);
+
+ if(m_rx_clock_counter == 0 && m_clock_mode == INTERNAL_SYNC_OUT)
+ m_cpu->do_sci_clk(m_id, 0);
+
+ else if(m_rx_clock_counter == 1) {
+ if(m_clock_mode == INTERNAL_SYNC_OUT)
+ m_cpu->do_sci_clk(m_id, 1);
+
+ rx_sync_step();
+ }
+}
+
+void h8_sci_device::rx_sync_step()
+{
+ LOGMASKED(LOG_STATE, "rx_sync_step bit=%d\n", m_rx_value);
+ m_rsr >>= 1;
+ if(m_rx_value)
+ m_rsr |= 0x80;
+ m_rx_bit--;
+
+ if(!m_rx_bit)
+ rx_done();
}