summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author Lord-Nightmare <Lord-Nightmare@users.noreply.github.com>2016-04-04 20:21:41 -0400
committer Lord-Nightmare <Lord-Nightmare@users.noreply.github.com>2016-04-04 20:21:41 -0400
commitd5b01cf514212573c6490132cabf736b8b7ae9a8 (patch)
treec3478eb414868ebef03f9f03c88656205b0a247f /src
parentb02e9f3083bf3c6d5303db47e36ffee762a413fc (diff)
TMS5220: add a 'combined rs/ws write' function for systems which require both pins to change at exactly the same time and not to reset the chip. [Lord Nightmare]
Diffstat (limited to 'src')
-rw-r--r--src/devices/sound/tms5220.cpp82
-rw-r--r--src/devices/sound/tms5220.h2
2 files changed, 80 insertions, 4 deletions
diff --git a/src/devices/sound/tms5220.cpp b/src/devices/sound/tms5220.cpp
index ca743e73d70..8bc51d5683f 100644
--- a/src/devices/sound/tms5220.cpp
+++ b/src/devices/sound/tms5220.cpp
@@ -1842,7 +1842,7 @@ WRITE_LINE_MEMBER( tms5220_device::rsq_w )
#ifdef DEBUG_RS_WS
else
/* illegal */
- fprintf(stderr,"tms5220_rs_w: illegal\n");
+ fprintf(stderr,"tms5220_rsq_w: illegal\n");
#endif
return;
}
@@ -1889,12 +1889,12 @@ WRITE_LINE_MEMBER( tms5220_device::wsq_w )
m_rs_ws = new_val;
if (new_val == 0)
{
- if (TMS5220_HAS_RATE_CONTROL) // correct for 5220c, ? for cd2501ecd
+ if (TMS5220_HAS_RATE_CONTROL) // correct for 5220c, probably also correct for cd2501ecd
reset();
#ifdef DEBUG_RS_WS
else
/* illegal */
- fprintf(stderr,"tms5220_ws_w: illegal\n");
+ fprintf(stderr,"tms5220_wsq_w: illegal\n");
#endif
return;
}
@@ -1917,7 +1917,7 @@ WRITE_LINE_MEMBER( tms5220_device::wsq_w )
/* upon /WS being activated, /READY goes inactive after 100 nsec from data sheet, through 3 asynchronous gates on patent. This is effectively within one clock, so we immediately set io_ready to 0 and activate the callback. */
m_io_ready = 0;
update_ready_state();
- /* Now comes the complicated part: long does /READY stay inactive, when /WS is pulled low? This depends ENTIRELY on the command written, or whether the chip is in speak external mode or not...
+ /* Now comes the complicated part: how long does /READY stay inactive, when /WS is pulled low? This depends ENTIRELY on the command written, or whether the chip is in speak external mode or not...
Speak external mode: ~16 cycles
Command Mode:
SPK: ? cycles
@@ -1933,6 +1933,80 @@ WRITE_LINE_MEMBER( tms5220_device::wsq_w )
}
}
+/*
+ * combined /RS and /WS line write handler;
+ * /RS is bit 1, /WS is bit 0
+ * Note this is a hack and probably can be removed later, once the 'real' line handlers above defer by at least 4 clock cycles before taking effect
+ */
+WRITE8_MEMBER( tms5220_device::combined_rsq_wsq_w )
+{
+ UINT8 new_val;
+ UINT8 falling_edges;
+ m_true_timing = 1;
+#ifdef DEBUG_RS_WS
+ fprintf(stderr,"/RS and /WS written with %d and %d respectively\n", (data&2)>>1), data&1;
+#endif
+ new_val = data&0x03;
+ if (new_val != m_rs_ws)
+ {
+ falling_edges = ((m_rs_ws^new_val)&(~new_val));
+ m_rs_ws = new_val;
+ switch(new_val)
+ {
+ case 0:
+ if (TMS5220_HAS_RATE_CONTROL) // correct for 5220c, probably also correct for cd2501ecd
+ reset();
+#ifdef DEBUG_RS_WS
+ else
+ /* illegal */
+ fprintf(stderr,"tms5220_combined_rsq_wsq_w: illegal\n");
+#endif
+ return;
+ case 3:
+ /* high impedance */
+ m_read_latch = 0xff;
+ return;
+ case 2: // /WS active, /RS not
+ /* check for falling or rising edge */
+ if (!(falling_edges&0x02)) return; /* low to high, do nothing */
+ /* high to low - schedule ready cycle */
+#ifdef DEBUG_RS_WS
+ fprintf(stderr,"Scheduling ready cycle for /WS...\n");
+#endif
+ /* upon /WS being activated, /READY goes inactive after 100 nsec from data sheet, through 3 asynchronous gates on patent. This is effectively within one clock, so we immediately set io_ready to 0 and activate the callback. */
+ m_io_ready = 0;
+ update_ready_state();
+ /* Now comes the complicated part: how long does /READY stay inactive, when /WS is pulled low? This depends ENTIRELY on the command written, or whether the chip is in speak external mode or not...
+ Speak external mode: ~16 cycles
+ Command Mode:
+ SPK: ? cycles
+ SPKEXT: ? cycles
+ RDBY: between 60 and 140 cycles
+ RB: ? cycles (80?)
+ RST: between 60 and 140 cycles
+ SET RATE (5220C and CD2501ECD only): ? cycles (probably ~16)
+ */
+ // TODO: actually HANDLE the timing differences! currently just assuming always 16 cycles
+ m_timer_io_ready->adjust(attotime::from_hz(clock()/16), 1); // this should take around 10-16 (closer to ~15) cycles to complete for fifo writes, TODO: but actually depends on what command is written if in command mode
+ return;
+ case 1: // /RS active, /WS not
+ /* check for falling or rising edge */
+ if (!(falling_edges&0x01)) return; /* low to high, do nothing */
+ /* high to low - schedule ready cycle */
+#ifdef DEBUG_RS_WS
+ fprintf(stderr,"Scheduling ready cycle for /RS...\n");
+#endif
+ /* upon /RS being activated, /READY goes inactive after 100 nsec from data sheet, through 3 asynchronous gates on patent. This is effectively within one clock, so we immediately set io_ready to 0 and activate the callback. */
+ m_io_ready = 0;
+ update_ready_state();
+ /* How long does /READY stay inactive, when /RS is pulled low? I believe its almost always ~16 clocks (25 usec at 800khz as shown on the datasheet) */
+ m_timer_io_ready->adjust(attotime::from_hz(clock()/16), 1); // this should take around 10-16 (closer to ~11?) cycles to complete
+ return;
+ }
+ }
+}
+
+
/**********************************************************************************************
tms5220_data_w -- write data to the sound chip
diff --git a/src/devices/sound/tms5220.h b/src/devices/sound/tms5220.h
index 38a0ea20dc7..706a728b28a 100644
--- a/src/devices/sound/tms5220.h
+++ b/src/devices/sound/tms5220.h
@@ -72,6 +72,8 @@ public:
WRITE_LINE_MEMBER( rsq_w );
WRITE_LINE_MEMBER( wsq_w );
+ DECLARE_WRITE8_MEMBER( combined_rsq_wsq_w ); // this hack is necessary for specific systems such as the TI 99/8 since the 5220c and cd2501ecd do specific things if both lines go active or inactive at slightly different times by separate write_line writes, which causes the chip to incorrectly reset itself on the 99/8, where the writes are supposed to happen simultaneously; /RS is bit 1, /WS is bit 0
+ // Note this is a hack and probably can be removed later, once the 'real' line handlers above defer by at least 4 clock cycles before taking effect
DECLARE_WRITE8_MEMBER( data_w );
DECLARE_READ8_MEMBER( status_r );