summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Jonathan Gevaryahu <Lord-Nightmare@users.noreply.github.com>2016-12-23 15:08:50 -0500
committer GitHub <noreply@github.com>2016-12-23 15:08:50 -0500
commit0768d0b4fd5bdc3f85b2b40402f612d1a063e8c8 (patch)
tree41b3dfa6647e7887432bf8fd298b7cb21776db89
parenta9534da1d5552e678142a3b7b08c827d2a2749ba (diff)
parent29a9165acb671f6c4c79ee889dcb52d51cbb9c24 (diff)
Merge pull request #1864 from ajrhacker/cedar_magnet_40105
Preliminary work towards improving emulation of Cedar Magnet sound bo…
-rw-r--r--scripts/target/mame/arcade.lua2
-rw-r--r--src/devices/bus/c64/magic_voice.cpp8
-rw-r--r--src/devices/machine/40105.cpp143
-rw-r--r--src/devices/machine/40105.h55
-rw-r--r--src/mame/machine/cedar_magnet_sound.cpp65
-rw-r--r--src/mame/machine/cedar_magnet_sound.h11
6 files changed, 193 insertions, 91 deletions
diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua
index 787c70cbf02..6a4276981b3 100644
--- a/scripts/target/mame/arcade.lua
+++ b/scripts/target/mame/arcade.lua
@@ -389,7 +389,7 @@ MACHINES["AY31015"] = true
MACHINES["BANKDEV"] = true
MACHINES["CDP1852"] = true
MACHINES["CDP1871"] = true
---MACHINES["CMOS40105"] = true
+MACHINES["CMOS40105"] = true
MACHINES["CDU76S"] = true
MACHINES["COM8116"] = true
MACHINES["CR589"] = true
diff --git a/src/devices/bus/c64/magic_voice.cpp b/src/devices/bus/c64/magic_voice.cpp
index 078ca95e804..a3a8353494e 100644
--- a/src/devices/bus/c64/magic_voice.cpp
+++ b/src/devices/bus/c64/magic_voice.cpp
@@ -49,7 +49,7 @@ http://www.stefan-uhlmann.de/cbm/MVM/index.html
#define T6721A_TAG "u5"
#define MOS6525_TAG "u2"
-#define CMOS40105_TAG "u1"
+#define CD40105_TAG "u1"
#define A12 BIT(offset, 12)
#define A13 BIT(offset, 13)
@@ -226,7 +226,9 @@ static MACHINE_CONFIG_FRAGMENT( c64_magic_voice )
MCFG_TPI6525_OUT_PB_CB(WRITE8(c64_magic_voice_cartridge_device, tpi_pb_w))
MCFG_TPI6525_OUT_CA_CB(WRITELINE(c64_magic_voice_cartridge_device, tpi_ca_w))
MCFG_TPI6525_OUT_CA_CB(WRITELINE(c64_magic_voice_cartridge_device, tpi_cb_w))
- MCFG_40105_ADD(CMOS40105_TAG, DEVWRITELINE(MOS6525_TAG, tpi6525_device, i3_w), NOOP)
+
+ MCFG_DEVICE_ADD(CD40105_TAG, CD40105, 0)
+ MCFG_40105_DATA_IN_READY_CB(DEVWRITELINE(MOS6525_TAG, tpi6525_device, i3_w))
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD(T6721A_TAG, T6721A, XTAL_640kHz)
@@ -265,7 +267,7 @@ c64_magic_voice_cartridge_device::c64_magic_voice_cartridge_device(const machine
device_c64_expansion_card_interface(mconfig, *this),
m_vslsi(*this, T6721A_TAG),
m_tpi(*this, MOS6525_TAG),
- m_fifo(*this, CMOS40105_TAG),
+ m_fifo(*this, CD40105_TAG),
m_exp(*this, C64_EXPANSION_SLOT_TAG), m_ca(0),
m_tpi_pb(0x60),
m_tpi_pc6(1),
diff --git a/src/devices/machine/40105.cpp b/src/devices/machine/40105.cpp
index 8dec8b78cec..63db529d3bd 100644
--- a/src/devices/machine/40105.cpp
+++ b/src/devices/machine/40105.cpp
@@ -2,7 +2,16 @@
// copyright-holders:Curt Coder
/**********************************************************************
- CMOS 40105 FIFO Register emulation
+ CD40105/HC40105 4-bit x 16-word FIFO Register
+
+ Part of the 4000B series of CMOS TTL devices, the 40105 includes
+ an asynchronous master reset pin intended to be connected to the
+ system bus.
+
+ Word size can be expanded from 4 bits to 8 bits by connecting two
+ 40105s in parallel, with external AND gates to combine the DIR and
+ DOR outputs. They can also be connected in series to extend the
+ FIFO capacity, with DOR -> SI and /SO <- DIR.
**********************************************************************/
@@ -22,8 +31,8 @@
// DEVICE DEFINITIONS
//**************************************************************************
-const device_type CMOS_40105 = &device_creator<cmos_40105_device>;
-
+const device_type CD40105 = &device_creator<cmos_40105_device>;
+const device_type HC40105 = &device_creator<cmos_40105_device>;
//**************************************************************************
@@ -34,10 +43,17 @@ const device_type CMOS_40105 = &device_creator<cmos_40105_device>;
// cmos_40105_device - constructor
//-------------------------------------------------
-cmos_40105_device::cmos_40105_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, CMOS_40105, "40105", tag, owner, clock, "40105", __FILE__),
+cmos_40105_device::cmos_40105_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : device_t(mconfig, CD40105, "40105 FIFO", tag, owner, clock, "cd40105", __FILE__),
m_write_dir(*this),
- m_write_dor(*this), m_d(0), m_q(0), m_dir(0), m_dor(0), m_si(0), m_so(0)
+ m_write_dor(*this),
+ m_write_q(*this),
+ m_d(0),
+ m_q(0),
+ m_dir(false),
+ m_dor(false),
+ m_si(false),
+ m_so(false)
{
}
@@ -51,6 +67,7 @@ void cmos_40105_device::device_start()
// resolve callbacks
m_write_dir.resolve_safe();
m_write_dor.resolve_safe();
+ m_write_q.resolve_safe();
// state saving
save_item(NAME(m_d));
@@ -68,36 +85,84 @@ void cmos_40105_device::device_start()
void cmos_40105_device::device_reset()
{
- m_fifo = std::queue<uint8_t>();
-
- m_dir = 1;
- m_dor = 0;
- m_si = 0;
-
- m_write_dir(m_dir);
- m_write_dor(m_dor);
+ // invalidate data in queue
+ m_fifo = std::queue<u8>();
+
+ // reset control flip-flops
+ m_dir = true;
+ m_dor = false;
+ m_write_dir(1);
+ m_write_dor(0);
}
//-------------------------------------------------
-// read - read Q
+// read - read output buffer (Q0 to Q3)
//-------------------------------------------------
-uint8_t cmos_40105_device::read()
+u8 cmos_40105_device::read()
{
return m_q;
}
//-------------------------------------------------
-// write - write D
+// write - write input buffer (D0 to D3)
//-------------------------------------------------
-void cmos_40105_device::write(uint8_t data)
+void cmos_40105_device::write(u8 data)
{
m_d = data & 0x0f;
}
+WRITE8_MEMBER(cmos_40105_device::write)
+{
+ write(data);
+}
+
+
+//-------------------------------------------------
+// load_input - load new data into FIFO
+//-------------------------------------------------
+
+void cmos_40105_device::load_input()
+{
+ if (m_fifo.size() == 16)
+ {
+ logerror("Attempt to load data into full FIFO\n");
+ return;
+ }
+
+ m_fifo.push(m_d);
+
+ // DIR remains low if FIFO is full, or else briefly pulses low
+ m_write_dir(0);
+ if (m_fifo.size() == 16)
+ m_dir = false;
+ else
+ m_write_dir(1);
+}
+
+
+//-------------------------------------------------
+// output_ready - place new data at output
+//-------------------------------------------------
+
+void cmos_40105_device::output_ready()
+{
+ if (m_fifo.size() == 0)
+ {
+ logerror("Attempt to output data from empty FIFO\n");
+ return;
+ }
+
+ m_q = m_fifo.front();
+ m_write_q(m_q);
+
+ m_dor = true;
+ m_write_dor(1);
+}
+
//-------------------------------------------------
// si_w - shift in write
@@ -105,22 +170,16 @@ void cmos_40105_device::write(uint8_t data)
WRITE_LINE_MEMBER( cmos_40105_device::si_w )
{
+ // load input on rising edge when ready
if (m_dir && !m_si && state)
{
- m_fifo.push(m_d);
-
- if (m_fifo.size() == 16)
- {
- m_dir = 0;
- m_write_dir(m_dir);
- }
-
+ load_input();
+ }
+ else if (m_si && !state && m_fifo.size() > 0)
+ {
+ // data propagates through FIFO when SI goes low
if (!m_dor)
- {
- m_dor = 1;
- m_write_dor(m_dor);
- }
-
+ output_ready();
}
m_si = state;
@@ -133,18 +192,26 @@ WRITE_LINE_MEMBER( cmos_40105_device::si_w )
WRITE_LINE_MEMBER( cmos_40105_device::so_w )
{
- if (m_dor && m_so && !m_so)
+ // shift out on falling edge when ready
+ if (m_dor && m_so && !state)
{
- m_dor = 0;
- m_write_dor(m_dor);
-
- m_q = m_fifo.front();
m_fifo.pop();
+ m_dor = false;
+ m_write_dor(0);
+ // DOR remains low if FIFO is now empty, or else briefly pulses low
if (m_fifo.size() > 0)
+ output_ready();
+
+ if (!m_dir)
{
- m_dor = 1;
- m_write_dor(m_dor);
+ // raise DIR since FIFO is no longer full
+ m_dir = true;
+ m_write_dir(1);
+
+ // load new input immediately if SI is held high
+ if (m_si)
+ load_input();
}
}
diff --git a/src/devices/machine/40105.h b/src/devices/machine/40105.h
index 67d3a58274e..47a8ce0b1ab 100644
--- a/src/devices/machine/40105.h
+++ b/src/devices/machine/40105.h
@@ -2,7 +2,18 @@
// copyright-holders:Curt Coder
/**********************************************************************
- CMOS 40105 FIFO Register emulation
+ CD40105/HC40105 4-bit x 16-word FIFO Register
+
+***********************************************************************
+ ____ ____
+ /OE 1 |* \_/ | 16 Vcc
+ DIR 2 | | 15 /SO
+ SI 3 | | 14 DOR
+ D0 4 | | 13 Q0
+ D1 5 | 40105 | 12 Q1
+ D2 6 | | 11 Q2
+ D3 7 | | 10 Q3
+ GND 8 |___________| 9 MR
**********************************************************************/
@@ -20,11 +31,15 @@
// INTERFACE CONFIGURATION MACROS
///*************************************************************************
-#define MCFG_40105_ADD(_tag, _dir, _dor) \
- MCFG_DEVICE_ADD(_tag, CMOS_40105, 0) \
- downcast<cmos_40105_device *>(device)->set_dir_callback(DEVCB_##_dir); \
+#define MCFG_40105_DATA_IN_READY_CB(_dir) \
+ downcast<cmos_40105_device *>(device)->set_dir_callback(DEVCB_##_dir);
+
+#define MCFG_40105_DATA_OUT_READY_CB(_dor) \
downcast<cmos_40105_device *>(device)->set_dor_callback(DEVCB_##_dor);
+#define MCFG_40105_DATA_OUT_CB(_out) \
+ downcast<cmos_40105_device *>(device)->set_data_out_callback(DEVCB_##_out);
+
///*************************************************************************
@@ -37,13 +52,15 @@ class cmos_40105_device : public device_t
{
public:
// construction/destruction
- cmos_40105_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ cmos_40105_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
template<class _dir> void set_dir_callback(_dir dir) { m_write_dir.set_callback(dir); }
template<class _dor> void set_dor_callback(_dor dor) { m_write_dor.set_callback(dor); }
+ template<class _out> void set_data_out_callback(_out out) { m_write_q.set_callback(out); }
- uint8_t read();
- void write(uint8_t data);
+ u8 read();
+ void write(u8 data);
+ DECLARE_WRITE8_MEMBER(write);
DECLARE_WRITE_LINE_MEMBER( si_w );
DECLARE_WRITE_LINE_MEMBER( so_w );
@@ -57,24 +74,30 @@ protected:
virtual void device_reset() override;
private:
+ // private helpers
+ void load_input();
+ void output_ready();
+
+ // callbacks
devcb_write_line m_write_dir;
devcb_write_line m_write_dor;
+ devcb_write8 m_write_q;
- std::queue<uint8_t> m_fifo;
+ std::queue<u8> m_fifo;
- uint8_t m_d;
- uint8_t m_q;
+ u8 m_d;
+ u8 m_q;
- int m_dir;
- int m_dor;
- int m_si;
- int m_so;
+ bool m_dir;
+ bool m_dor;
+ bool m_si;
+ bool m_so;
};
// device type definition
-extern const device_type CMOS_40105;
-
+extern const device_type CD40105;
+extern const device_type HC40105;
#endif
diff --git a/src/mame/machine/cedar_magnet_sound.cpp b/src/mame/machine/cedar_magnet_sound.cpp
index 37132fb77f3..d289c1ad200 100644
--- a/src/mame/machine/cedar_magnet_sound.cpp
+++ b/src/mame/machine/cedar_magnet_sound.cpp
@@ -2,12 +2,14 @@
// copyright-holders:David Haywood
/*
- how should the ctcs hook up properly?
+ This is very similar to the ZSU1 Sound Control Unit, also manufactured by
+ EFO SA and used in the Playmatic pinballs Skill Flight and Phantom Ship;
+ the emulation here is influenced by available schematics for that board.
irq vectors
- 0xe6 - from ctc0? (would need vector of e0?) probably used to drive MSM5205
- 0xee - from ctc0? (would need vector of e8?) ^^
+ 0xe6 - from ctc0 channel 3 (vector = E0) used to drive MSM5205 through FIFO
+ 0xee - from ctc0 channel 3 (vector = E8) ^^
0xf6 - drive AY (once per frame?) triggered by ctc1 channel 3? (sets vector to f0, f6 = channel3?)
0xff - read sound latch (triggered by write from master board)
@@ -29,7 +31,9 @@ extern const device_type CEDAR_MAGNET_SOUND = &device_creator<cedar_magnet_sound
cedar_magnet_sound_device::cedar_magnet_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cedar_magnet_board_device(mconfig, CEDAR_MAGNET_SOUND, "Cedar Sound", tag, owner, clock, "cedmag_sound", __FILE__),
m_ctc0(*this, "ctc0"),
- m_ctc1(*this, "ctc1")
+ m_ctc1(*this, "ctc1"),
+ m_fifo(*this, "fifo"),
+ m_adpcm(*this, "adpcm")
{
}
@@ -58,7 +62,7 @@ static ADDRESS_MAP_START( cedar_magnet_sound_io, AS_IO, 8, cedar_magnet_sound_de
AM_RANGE(0x00, 0x03) AM_DEVREADWRITE("ctc0", z80ctc_device, read, write)
AM_RANGE(0x04, 0x07) AM_DEVREADWRITE("ctc1", z80ctc_device, read, write)
- AM_RANGE(0x08, 0x08) AM_WRITE(adpcm_latch_w)
+ AM_RANGE(0x08, 0x08) AM_WRITE(adpcm_fifo_w)
AM_RANGE(0x0c, 0x0c) AM_DEVWRITE("aysnd0", ay8910_device, address_w)
AM_RANGE(0x0d, 0x0d) AM_DEVWRITE("aysnd0", ay8910_device, data_w)
@@ -70,16 +74,28 @@ static ADDRESS_MAP_START( cedar_magnet_sound_io, AS_IO, 8, cedar_magnet_sound_de
ADDRESS_MAP_END
-WRITE8_MEMBER(cedar_magnet_sound_device::adpcm_latch_w)
+WRITE8_MEMBER(cedar_magnet_sound_device::adpcm_fifo_w)
{
- // it writes 8-bits of sample data here, to be fed to the msm 4-bits at a time
- // probably via other triggers
- m_adpcm_data = data;
+ // Z80 code first unpacks 8 bytes of ADPCM sample data into nibbles
+ // and, upon receiving interrupt vector E6, fills FIFO at once using OTIR
+ // 4-bit data is shifted out of the FIFO to the MSM5205 by another timer
+ m_fifo->write(data & 0x0f); // only low nibble is used here
+ m_fifo->si_w(1);
+ m_fifo->si_w(0);
+}
+
+WRITE8_MEMBER(cedar_magnet_sound_device::ay0_porta_w)
+{
+ // unknown; 0x80 written on reset
}
WRITE8_MEMBER(cedar_magnet_sound_device::ay1_porta_w)
{
- // unknown but used
+ m_adpcm->reset_w(data & 1);
+ if (data & 1)
+ m_fifo->reset();
+ // D4-D6 likely used to select clock for ctc0 channel 2
+ // other bits probably used to modulate analog sound output
}
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_z0_w)
@@ -92,9 +108,6 @@ WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_z1_w)
// printf("USED ctc0_z1_w %d\n", state);
}
-
-// I don't think any of the below are used
-
WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc1_z0_w)
{
printf("ctc1_z0_w %d\n", state);
@@ -115,14 +128,9 @@ WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_z2_w)
printf("ctc0_z2_w %d\n", state);
}
-WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc0_int_w)
+WRITE_LINE_MEMBER(cedar_magnet_sound_device::fifo_dor_w)
{
- //printf("ctc0_int_w %d\n", state);
-}
-
-WRITE_LINE_MEMBER(cedar_magnet_sound_device::ctc1_int_w)
-{
-
+ // combined with a clock signal and used to drive ctc0 channel 3
}
#if 0
@@ -158,23 +166,20 @@ INTERRUPT_GEN_MEMBER(cedar_magnet_sound_device::fake_irq)
}
static MACHINE_CONFIG_FRAGMENT( cedar_magnet_sound )
- MCFG_CPU_ADD("topcpu", Z80,4000000)
+ MCFG_CPU_ADD("topcpu", Z80, 4000000)
MCFG_CPU_PROGRAM_MAP(cedar_magnet_sound_map)
MCFG_CPU_IO_MAP(cedar_magnet_sound_io)
// MCFG_Z80_DAISY_CHAIN(daisy_chain)
MCFG_CPU_PERIODIC_INT_DRIVER(cedar_magnet_sound_device, fake_irq, 4*60)
- MCFG_DEVICE_ADD("ctc0", Z80CTC, 4000000/8 )
+ MCFG_DEVICE_ADD("ctc0", Z80CTC, 4000000)
// MCFG_Z80CTC_INTR_CB(INPUTLINE("topcpu", INPUT_LINE_IRQ0))
- MCFG_Z80CTC_INTR_CB(WRITELINE(cedar_magnet_sound_device, ctc0_int_w))
MCFG_Z80CTC_ZC0_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z0_w))
MCFG_Z80CTC_ZC1_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z1_w))
MCFG_Z80CTC_ZC2_CB(WRITELINE(cedar_magnet_sound_device, ctc0_z2_w))
- MCFG_DEVICE_ADD("ctc1", Z80CTC, 4000000/8 )
+ MCFG_DEVICE_ADD("ctc1", Z80CTC, 4000000)
// MCFG_Z80CTC_INTR_CB(INPUTLINE("topcpu", INPUT_LINE_IRQ0))
-// MCFG_Z80CTC_INTR_CB(DEVWRITELINE("ctc0", z80ctc_device, trg0))
- MCFG_Z80CTC_INTR_CB(WRITELINE(cedar_magnet_sound_device, ctc1_int_w))
MCFG_Z80CTC_ZC0_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z0_w))
MCFG_Z80CTC_ZC1_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z1_w))
MCFG_Z80CTC_ZC2_CB(WRITELINE(cedar_magnet_sound_device, ctc1_z2_w))
@@ -182,15 +187,19 @@ static MACHINE_CONFIG_FRAGMENT( cedar_magnet_sound )
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("aysnd0", AY8910, 4000000/2)
+ MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(cedar_magnet_sound_device, ay0_porta_w))
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
MCFG_SOUND_ADD("aysnd1", AY8910, 4000000/2)
MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(cedar_magnet_sound_device, ay1_porta_w))
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5)
- MCFG_SOUND_ADD("adpcm", MSM5205, 4000000/16)
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
+ MCFG_DEVICE_ADD("fifo", HC40105, 0) // HCF40105BE at IC13
+ MCFG_40105_DATA_OUT_READY_CB(WRITELINE(cedar_magnet_sound_device, fifo_dor_w))
+ MCFG_40105_DATA_OUT_CB(DEVWRITELINE("adpcm", msm5205_device, data_w))
+ MCFG_SOUND_ADD("adpcm", MSM5205, 4000000/8)
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
MACHINE_CONFIG_END
machine_config_constructor cedar_magnet_sound_device::device_mconfig_additions() const
diff --git a/src/mame/machine/cedar_magnet_sound.h b/src/mame/machine/cedar_magnet_sound.h
index fcd498c1aa8..ddc2f65f65a 100644
--- a/src/mame/machine/cedar_magnet_sound.h
+++ b/src/mame/machine/cedar_magnet_sound.h
@@ -9,6 +9,7 @@
#include "cpu/z80/z80.h"
#include "cpu/z80/z80daisy.h"
#include "machine/z80ctc.h"
+#include "machine/40105.h"
#include "sound/ay8910.h"
#include "sound/msm5205.h"
#include "machine/cedar_magnet_board.h"
@@ -27,13 +28,14 @@ public:
required_device<z80ctc_device> m_ctc0;
required_device<z80ctc_device> m_ctc1;
+ required_device<cmos_40105_device> m_fifo;
+ required_device<msm5205_device> m_adpcm;
DECLARE_READ8_MEMBER(soundlatch_r);
- DECLARE_WRITE8_MEMBER(adpcm_latch_w);
+ DECLARE_WRITE8_MEMBER(adpcm_fifo_w);
+ DECLARE_WRITE8_MEMBER(ay0_porta_w);
DECLARE_WRITE8_MEMBER(ay1_porta_w);
- uint8_t m_adpcm_data;
-
void write_command(uint8_t data);
uint8_t m_command;
@@ -43,8 +45,7 @@ public:
DECLARE_WRITE_LINE_MEMBER(ctc0_z0_w);
DECLARE_WRITE_LINE_MEMBER(ctc0_z1_w);
DECLARE_WRITE_LINE_MEMBER(ctc0_z2_w);
- DECLARE_WRITE_LINE_MEMBER(ctc0_int_w);
- DECLARE_WRITE_LINE_MEMBER(ctc1_int_w);
+ DECLARE_WRITE_LINE_MEMBER(fifo_dor_w);
TIMER_CALLBACK_MEMBER(reset_assert_callback) override;