summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/lc78836m.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/lc78836m.cpp')
-rw-r--r--src/devices/sound/lc78836m.cpp206
1 files changed, 206 insertions, 0 deletions
diff --git a/src/devices/sound/lc78836m.cpp b/src/devices/sound/lc78836m.cpp
new file mode 100644
index 00000000000..ecb007ad081
--- /dev/null
+++ b/src/devices/sound/lc78836m.cpp
@@ -0,0 +1,206 @@
+// license:BSD-3-Clause
+// copyright-holders:windyfairy
+/***************************************************************************
+
+ Sanyo LC78836M Digital Audio 16-bit D/A Converter
+ with On-Chip Digital Filters
+ ____ ____
+ REFH 1 | \_/ | 24 AVDD
+ VrefH 2 | | 23 CH1OUT
+ MUTE 3 | | 22 AGND
+ D/N 4 | | 21 CH2OUT
+ BCLK 5 | | 20 REFL
+ DATA 6 | LC78836M | 19 VrefL
+ LRCK 7 | | 18 CKSL2
+ DVDD 8 | | 17 CKSL1
+ CKOUT 9 | | 16 FS2
+ XOUT 10 | | 15 FS1
+ XIN 11 | | 14 EMP
+ DGND 12 |___________| 13 INITB
+
+
+ TOOD:
+ - INITB, DN aren't implemented
+ - Filters aren't implemented
+
+***************************************************************************/
+
+#include "emu.h"
+#include "lc78836m.h"
+
+// #define VERBOSE (LOG_GENERAL)
+
+#include "logmacro.h"
+
+
+DEFINE_DEVICE_TYPE(LC78836M, lc78836m_device, "lc78836m", "Sanyo LC78836M Digital Audio 16-bit D/A Converter")
+
+
+lc78836m_device::lc78836m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, LC78836M, tag, owner, clock)
+ , device_sound_interface(mconfig, *this)
+ , m_stream(nullptr)
+ , m_cksl1(0), m_cksl2(0)
+ , m_fs1(0), m_fs2(0)
+ , m_emp(0)
+{
+}
+
+void lc78836m_device::device_start()
+{
+ save_item(NAME(m_cksl1));
+ save_item(NAME(m_cksl2));
+ save_item(NAME(m_fs1));
+ save_item(NAME(m_fs2));
+ save_item(NAME(m_emp));
+
+ save_item(NAME(m_mute));
+ save_item(NAME(m_lrck));
+ save_item(NAME(m_data));
+ save_item(NAME(m_bclk));
+ save_item(NAME(m_sample));
+ save_item(NAME(m_sample_bit));
+ save_item(NAME(m_clock_fs));
+
+ save_item(NAME(m_sample_ch1));
+ save_item(NAME(m_sample_ch2));
+ save_item(NAME(m_att));
+
+ m_stream = stream_alloc(2, 2, m_clock);
+}
+
+void lc78836m_device::device_reset()
+{
+ m_mute = 0;
+ m_lrck = 0;
+ m_data = 0;
+ m_bclk = 0;
+ m_sample = 0;
+ m_sample_bit = 0;
+ m_att = 1024;
+ m_sample_ch1 = m_sample_ch2 = 0;
+
+ update_clock();
+}
+
+void lc78836m_device::device_clock_changed()
+{
+ update_clock();
+}
+
+void lc78836m_device::sound_stream_update(sound_stream &stream)
+{
+ stream.put(0, 0, m_sample_ch1 * m_att / 1024.0);
+ m_sample_ch1 = 0;
+
+ stream.put(1, 0, m_sample_ch2 * m_att / 1024.0);
+ m_sample_ch2 = 0;
+
+ if (m_mute && m_att > 0)
+ m_att--;
+ else if (!m_mute && m_att < 1024)
+ m_att++;
+
+}
+
+void lc78836m_device::mute_w(int state)
+{
+ // Soft mute
+ m_mute = state;
+}
+
+void lc78836m_device::lrck_w(int state)
+{
+ // CH1 when high, CH2 when low
+ m_lrck = state;
+}
+
+void lc78836m_device::data_w(int state)
+{
+ m_data = state;
+}
+
+void lc78836m_device::bclk_w(int state)
+{
+ if (!m_bclk && state) {
+ m_sample |= m_data << m_sample_bit;
+ m_sample_bit++;
+
+ if (m_sample_bit >= 16) {
+ sound_stream::sample_t sample = m_sample / double(std::numeric_limits<int16_t>::max());
+
+ if (m_lrck)
+ m_sample_ch1 = sample;
+ else
+ m_sample_ch2 = sample;
+
+ m_sample = 0;
+ m_sample_bit = 0;
+
+ m_stream->update();
+ }
+ }
+
+ m_bclk = state;
+}
+
+void lc78836m_device::initb_w(int state)
+{
+ // Initialization signal input
+ // LSI is initialized when set low
+ m_initb = state;
+}
+
+void lc78836m_device::cksl1_w(int state)
+{
+ // System clock selection bit 1
+ if (state != m_cksl1) {
+ m_cksl1 = state;
+ update_clock();
+ }
+}
+
+void lc78836m_device::cksl2_w(int state)
+{
+ // System clock selection bit 2
+ if (state != m_cksl2) {
+ m_cksl2 = state;
+ update_clock();
+ }
+}
+
+void lc78836m_device::fs1_w(int state)
+{
+ // De-emphasis filter mode selection bit 1
+ m_fs1 = state;
+}
+
+void lc78836m_device::fs2_w(int state)
+{
+ // De-emphasis filter mode selection bit 2
+ m_fs2 = state;
+}
+
+void lc78836m_device::emp_w(int state)
+{
+ // De-emphasis filter on/off
+ m_emp = state;
+}
+
+void lc78836m_device::update_clock()
+{
+ if (m_cksl1 == 0 && m_cksl2 == 0)
+ m_clock_fs = 384;
+ else if (m_cksl1 == 0 && m_cksl2 == 1)
+ m_clock_fs = 392;
+ else if (m_cksl1 == 1 && m_cksl2 == 0)
+ m_clock_fs = 448;
+ else if (m_cksl1 == 1 && m_cksl2 == 1)
+ m_clock_fs = 512;
+
+ const uint32_t new_sample_rate = m_clock / m_clock_fs;
+ if (m_stream != nullptr && new_sample_rate != m_stream->sample_rate()) {
+ LOG("sample rate changed to %d\n", new_sample_rate);
+ m_stream->set_sample_rate(new_sample_rate);
+ }
+}