diff options
author | AJR <ajrhacker@users.noreply.github.com> | 2017-01-04 15:10:23 -0500 |
---|---|---|
committer | AJR <ajrhacker@users.noreply.github.com> | 2017-01-04 17:43:31 -0500 |
commit | 6f8c39e442abbad88cb124266f503036facb00e2 (patch) | |
tree | 40ff85dd46aad66937a016b6645f98bd6a4264df /src/mame/audio/efo_zsu.cpp | |
parent | 47c4f47bd40def91566dda49cc378d4ae0d63e37 (diff) |
Cedar Magnet/EFO ZSU
- Conversion of the Cedar Magnet board from a base device class to a mix-in interface
- Emulate EFO ZSU as main variant of the Cedar Magnet sound board
- Hook up ZSU1 to Skill Flight and Phantom Ship
- Modernize ZSU soundlatch/IRQ mechanism
- More hardware notes (nw)
- Various associated code cleanups (nw)
Diffstat (limited to 'src/mame/audio/efo_zsu.cpp')
-rw-r--r-- | src/mame/audio/efo_zsu.cpp | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/src/mame/audio/efo_zsu.cpp b/src/mame/audio/efo_zsu.cpp new file mode 100644 index 00000000000..7fe7744e69b --- /dev/null +++ b/src/mame/audio/efo_zsu.cpp @@ -0,0 +1,275 @@ +// license:BSD-3-Clause +// copyright-holders:David Haywood,AJR + +/*************************************************************************** + + ZSU Sound Control Unit (Proyectado 21/4/86 J. Gamell) + ZSU1 Sound Control Unit (Proyectado 12/6/86 J. Gamell) + Cedar Magnet Sound Board + + The ZSU board is a component of the Z-Pinball hardware developed by + E.F.O. (Electrónica Funcional Operativa) S.A. of Barcelona, Spain. Its + sound generators are 2 AY-3-8910As and 1 OKI MSM5205, and 2 MF10s and + 1 HC4066 are used to mix their outputs. The timing circuits are rather + intricate, using Z80-CTCs, HC74s and HC393s and various other gates to + drive both the 5205 and the SGS HCF40105BE through which its samples + are funneled. + + There are no available schematics for the Cedar Magnet video game + system (also designed by E.F.O.), but its sound board is believed to be + a close analogue of ZSU, since it includes all of the aforementioned + devices. The main known difference is that the Cedar Magnet sound + code and data are externally loaded into 64K of RAM (2xTMM41464P-15), + whereas ZSU's memory map consists primarily of a bank of up to 5 27256 + EPROMs switched from two output lines of the first 8910, overlaid with + a mere 2K of RAM. + + irq vectors + + 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 (vector = F0) + 0xff - read sound latch (triggered by write from master board; default vector set by 5K/+5 pullups on D0-D7) + +***************************************************************************/ + +#include "emu.h" +#include "audio/efo_zsu.h" + +#include "machine/clock.h" +#include "machine/input_merger.h" + + +extern const device_type EFO_ZSU = &device_creator<efo_zsu_device>; +extern const device_type EFO_ZSU1 = &device_creator<efo_zsu1_device>; +extern const device_type CEDAR_MAGNET_SOUND = &device_creator<cedar_magnet_sound_device>; + + +efo_zsu_device::efo_zsu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, u32 clock, const char *shortname, const char *source) + : device_t(mconfig, type, name, tag, owner, clock, shortname, source), + m_ctc0(*this, "ctc0"), + m_ctc1(*this, "ctc1"), + m_soundlatch(*this, "soundlatch"), + m_fifo(*this, "fifo"), + m_adpcm(*this, "adpcm") +{ +} + + +efo_zsu_device::efo_zsu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : efo_zsu_device(mconfig, EFO_ZSU, "ZSU Sound Control Unit", tag, owner, clock, "efo_zsu", __FILE__) +{ +} + + +efo_zsu1_device::efo_zsu1_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : efo_zsu_device(mconfig, EFO_ZSU1, "ZSU1 Sound Control Unit", tag, owner, clock, "efo_zsu1", __FILE__) +{ +} + + +cedar_magnet_sound_device::cedar_magnet_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : efo_zsu_device(mconfig, CEDAR_MAGNET_SOUND, "Cedar Sound", tag, owner, clock, "cedmag_sound", __FILE__), + cedar_magnet_board_interface(mconfig, *this, "soundcpu", "ram") +{ +} + + +WRITE8_MEMBER(efo_zsu_device::sound_command_w) +{ + m_soundlatch->write(space, 0, data); +} + + + +static ADDRESS_MAP_START( zsu_map, AS_PROGRAM, 8, efo_zsu_device ) + AM_RANGE(0x0000, 0x6fff) AM_ROM + AM_RANGE(0x7000, 0x77ff) AM_MIRROR(0x0800) AM_RAM + AM_RANGE(0x8000, 0xffff) AM_ROMBANK("rombank") +ADDRESS_MAP_END + +static ADDRESS_MAP_START( cedar_magnet_sound_map, AS_PROGRAM, 8, cedar_magnet_sound_device ) + AM_RANGE(0x0000, 0xffff) AM_RAM AM_SHARE("ram") +ADDRESS_MAP_END + +static ADDRESS_MAP_START( zsu_io, AS_IO, 8, efo_zsu_device ) + ADDRESS_MAP_GLOBAL_MASK(0xff) + ADDRESS_MAP_UNMAP_HIGH + + 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_fifo_w) + + AM_RANGE(0x0c, 0x0c) AM_DEVWRITE("aysnd0", ay8910_device, address_w) + AM_RANGE(0x0d, 0x0d) AM_DEVWRITE("aysnd0", ay8910_device, data_w) + + AM_RANGE(0x10, 0x10) AM_DEVWRITE("aysnd1", ay8910_device, address_w) + AM_RANGE(0x11, 0x11) AM_DEVWRITE("aysnd1", ay8910_device, data_w) + + AM_RANGE(0x14, 0x14) AM_DEVREAD("soundlatch", generic_latch_8_device, read) + +ADDRESS_MAP_END + +WRITE8_MEMBER(efo_zsu_device::adpcm_fifo_w) +{ + // 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 (not in ZSU schematic); 0x80 written on reset +} + +WRITE8_MEMBER(efo_zsu_device::ay1_porta_w) +{ + 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(efo_zsu_device::ctc0_z0_w) +{ +// printf("USED ctc0_z0_w %d\n", state); +} + +WRITE_LINE_MEMBER(efo_zsu_device::ctc0_z1_w) +{ +// printf("USED ctc0_z1_w %d\n", state); +} + +WRITE_LINE_MEMBER(efo_zsu_device::ctc1_z0_w) +{ + printf("ctc1_z0_w %d\n", state); +} + +WRITE_LINE_MEMBER(efo_zsu_device::ctc1_z1_w) +{ + printf("ctc1_z1_w %d\n", state); +} + +WRITE_LINE_MEMBER(efo_zsu_device::ctc1_z2_w) +{ + printf("ctc1_z2_w %d\n", state); +} + +WRITE_LINE_MEMBER(efo_zsu_device::ctc0_z2_w) +{ + printf("ctc0_z2_w %d\n", state); +} + +WRITE_LINE_MEMBER(efo_zsu_device::fifo_dor_w) +{ + // combined with a clock signal and used to drive ctc0 channel 3 +} + +static const z80_daisy_config daisy_chain[] = +{ + { "ctc1" }, + { "ctc0" }, + { nullptr } +}; + +TIMER_CALLBACK_MEMBER(cedar_magnet_sound_device::reset_assert_callback) +{ + cedar_magnet_board_interface::reset_assert_callback(ptr,param); + // reset lines go to the ctc as well? + m_ctc0->reset(); + m_ctc1->reset(); +} + + + +static MACHINE_CONFIG_FRAGMENT( efo_zsu ) + MCFG_CPU_ADD("soundcpu", Z80, 4000000) + MCFG_CPU_PROGRAM_MAP(zsu_map) + MCFG_CPU_IO_MAP(zsu_io) + MCFG_Z80_DAISY_CHAIN(daisy_chain) + + MCFG_DEVICE_ADD("ctc0", Z80CTC, 4000000) + MCFG_Z80CTC_INTR_CB(DEVWRITELINE("soundirq", input_merger_device, in0_w)) + MCFG_Z80CTC_ZC0_CB(WRITELINE(efo_zsu_device, ctc0_z0_w)) + MCFG_Z80CTC_ZC1_CB(WRITELINE(efo_zsu_device, ctc0_z1_w)) + MCFG_Z80CTC_ZC2_CB(WRITELINE(efo_zsu_device, ctc0_z2_w)) + + MCFG_DEVICE_ADD("ctc1", Z80CTC, 4000000) + MCFG_Z80CTC_INTR_CB(DEVWRITELINE("soundirq", input_merger_device, in0_w)) + MCFG_Z80CTC_ZC0_CB(WRITELINE(efo_zsu_device, ctc1_z0_w)) + MCFG_Z80CTC_ZC1_CB(WRITELINE(efo_zsu_device, ctc1_z1_w)) + MCFG_Z80CTC_ZC2_CB(WRITELINE(efo_zsu_device, ctc1_z2_w)) + +#if 0 // does nothing useful now + MCFG_DEVICE_ADD("ck1mhz", CLOCK, 4000000/4) + MCFG_CLOCK_SIGNAL_HANDLER(DEVWRITELINE("ctc1", z80ctc_device, trg0)) + MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("ctc1", z80ctc_device, trg1)) + MCFG_DEVCB_CHAIN_OUTPUT(DEVWRITELINE("ctc1", z80ctc_device, trg2)) +#endif + + MCFG_GENERIC_LATCH_8_ADD("soundlatch") + MCFG_GENERIC_LATCH_DATA_PENDING_CB(DEVWRITELINE("soundirq", input_merger_device, in1_w)) + + MCFG_INPUT_MERGER_ACTIVE_HIGH("soundirq") // 74HC03 NAND gate + MCFG_INPUT_MERGER_OUTPUT_HANDLER(INPUTLINE("soundcpu", INPUT_LINE_IRQ0)) + + MCFG_SPEAKER_STANDARD_MONO("mono") + + MCFG_SOUND_ADD("aysnd0", AY8910, 4000000/2) + MCFG_AY8910_PORT_A_WRITE_CB(MEMBANK("rombank")) MCFG_DEVCB_MASK(0x03) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5) + + MCFG_SOUND_ADD("aysnd1", AY8910, 4000000/2) + MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(efo_zsu_device, ay1_porta_w)) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.5) + + MCFG_DEVICE_ADD("fifo", HC40105, 0) + MCFG_40105_DATA_OUT_READY_CB(WRITELINE(efo_zsu_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 + +static MACHINE_CONFIG_FRAGMENT( cedar_magnet_sound ) + MCFG_FRAGMENT_ADD(efo_zsu) + + MCFG_CPU_MODIFY("soundcpu") + MCFG_CPU_PROGRAM_MAP(cedar_magnet_sound_map) + + MCFG_SOUND_MODIFY("aysnd0") + MCFG_AY8910_PORT_A_WRITE_CB(WRITE8(cedar_magnet_sound_device, ay0_porta_w)) +MACHINE_CONFIG_END + +machine_config_constructor efo_zsu_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( efo_zsu ); +} + +machine_config_constructor cedar_magnet_sound_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( cedar_magnet_sound ); +} + +void efo_zsu_device::device_start() +{ + memory_bank *rombank = membank("rombank"); + rombank->configure_entries(0, 4, &static_cast<u8 *>(memregion("soundcpu")->base())[0x8000], 0x8000); + rombank->set_entry(0); // 10K/GND pulldowns on banking lines +} + +void efo_zsu1_device::device_start() +{ + memory_bank *rombank = membank("rombank"); + rombank->configure_entries(0, 4, &static_cast<u8 *>(memregion("soundcpu")->base())[0x8000], 0x8000); + rombank->set_entry(3); // 10K/+5 pullups on banking lines +} + +void cedar_magnet_sound_device::device_start() +{ +} |