summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/machine/k054321.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/machine/k054321.cpp')
-rw-r--r--src/devices/machine/k054321.cpp138
1 files changed, 138 insertions, 0 deletions
diff --git a/src/devices/machine/k054321.cpp b/src/devices/machine/k054321.cpp
new file mode 100644
index 00000000000..54c32172b37
--- /dev/null
+++ b/src/devices/machine/k054321.cpp
@@ -0,0 +1,138 @@
+// license:BSD-3-Clause
+// copyright-holders:Olivier Galibert
+
+/***************************************************************************/
+/* */
+/* 054321 / 054544 / 054986A */
+/* */
+/* Konami sound control chip */
+/* */
+/***************************************************************************/
+
+/*
+ The 054321 is a sound communication latch/volume manager chip, that
+ is integrated into the 054544 and 05489A hybrid chips. The hybrid
+ chips also include the DACs, capacitors, etc needed for the audio
+ output.
+
+ The 054321 manages three latches (maybe four) to allow communication
+ between the main cpu and the soud cpu, and provides two independant
+ busses to ensure decoupling. It also manages one global volume and
+ a per-channel mute for two channels.
+
+ Volume setting is a little strange, with one address to reset it to
+ zero and another to increment it by one. Accepted volume range
+ seems to be 1-60, with 40 for "normal".
+
+ The chip seems to be an intermediate step between the 053260
+ (full-on sound chip with dual busses and internal latches for
+ communication) and the 056800 (MIRAC, similar to the 054321 but
+ 4-channel).
+*/
+
+#include "emu.h"
+#include "k054321.h"
+
+#include <math.h>
+
+const device_type K054321 = device_creator<k054321_device>;
+
+DEVICE_ADDRESS_MAP_START(main_map, 8, k054321_device)
+ AM_RANGE(0x0, 0x0) AM_WRITE(active_w)
+ AM_RANGE(0x2, 0x2) AM_WRITE(volume_reset_w)
+ AM_RANGE(0x3, 0x3) AM_WRITE(volume_up_w)
+ AM_RANGE(0x4, 0x4) AM_WRITE(dummy_w)
+ AM_RANGE(0x6, 0x6) AM_WRITE(main1_w)
+ AM_RANGE(0x7, 0x7) AM_WRITE(main2_w)
+ AM_RANGE(0x8, 0x8) AM_READ(busy_r)
+ AM_RANGE(0xa, 0xa) AM_READ(sound1_r)
+ADDRESS_MAP_END
+
+DEVICE_ADDRESS_MAP_START(sound_map, 8, k054321_device)
+ AM_RANGE(0x0, 0x0) AM_WRITE(sound1_w)
+ AM_RANGE(0x2, 0x2) AM_READ(main1_r)
+ AM_RANGE(0x3, 0x3) AM_READ(main2_r)
+ADDRESS_MAP_END
+
+k054321_device::k054321_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, K054321, "K053421 Maincpu-Soundcpu interface", tag, owner, clock, "k054321", __FILE__),
+ m_left(*this, finder_base::DUMMY_TAG),
+ m_right(*this, finder_base::DUMMY_TAG)
+{
+}
+
+void k054321_device::set_gain_devices(const char *_left, const char *_right)
+{
+ m_left.set_tag(_left);
+ m_right.set_tag(_right);
+}
+
+void k054321_device::device_start()
+{
+}
+
+READ8_MEMBER( k054321_device::main1_r)
+{
+ return m_main1;
+}
+
+WRITE8_MEMBER(k054321_device::main1_w)
+{
+ m_main1 = data;
+}
+
+READ8_MEMBER( k054321_device::main2_r)
+{
+ return m_main2;
+}
+
+WRITE8_MEMBER(k054321_device::main2_w)
+{
+ m_main2 = data;
+}
+
+READ8_MEMBER( k054321_device::sound1_r)
+{
+ return m_sound1;
+}
+
+WRITE8_MEMBER(k054321_device::sound1_w)
+{
+ m_sound1 = data;
+}
+
+WRITE8_MEMBER(k054321_device::volume_reset_w)
+{
+ m_volume = 0;
+ propagate_volume();
+}
+
+WRITE8_MEMBER(k054321_device::volume_up_w)
+{
+ m_volume ++;
+ propagate_volume();
+}
+
+READ8_MEMBER(k054321_device::busy_r)
+{
+ return 0; // bit0 = 1 means busy
+}
+
+WRITE8_MEMBER(k054321_device::active_w)
+{
+ m_active = data;
+ propagate_volume();
+}
+
+WRITE8_MEMBER(k054321_device::dummy_w)
+{
+ if(data != 0x4a)
+ logerror("unexpected dummy_w %02x\n", data);
+}
+
+void k054321_device::propagate_volume()
+{
+ double vol = pow(2, (m_volume - 40)/10.0);
+ m_left->set_input_gain(0, m_active & 2 ? vol : 0.0);
+ m_right->set_input_gain(0, m_active & 1 ? vol : 0.0);
+}