diff options
author | cracyc <cracyc@users.noreply.github.com> | 2016-03-19 21:13:00 -0500 |
---|---|---|
committer | cracyc <cracyc@users.noreply.github.com> | 2016-03-19 21:13:00 -0500 |
commit | 8fc8fc5ca3a402ce4ee0292c2d8695d9ffcf1013 (patch) | |
tree | 6cbba239a80c62b9d3a3b3f028c09dce19f64f34 /src/devices/sound | |
parent | 9328fa902887c15a58c95bfdf69cfa28e9a012c2 (diff) |
pcat_dyn: add sound and mark toursol working [Carl]
Diffstat (limited to 'src/devices/sound')
-rw-r--r-- | src/devices/sound/ad1848.cpp | 186 | ||||
-rw-r--r-- | src/devices/sound/ad1848.h | 67 |
2 files changed, 253 insertions, 0 deletions
diff --git a/src/devices/sound/ad1848.cpp b/src/devices/sound/ad1848.cpp new file mode 100644 index 00000000000..4c299be37be --- /dev/null +++ b/src/devices/sound/ad1848.cpp @@ -0,0 +1,186 @@ +// license:BSD-3-Clause +// copyright-holders:Carl + +// Analog Devices AD1848, main codec in Windows Sound System adapters + +#include "sound/ad1848.h" + +const device_type AD1848 = device_creator<ad1848_device>; + +ad1848_device::ad1848_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) : + device_t(mconfig, AD1848, "Analog Devices AD1848", tag, owner, clock, "ad1848", __FILE__), + m_irq_cb(*this), + m_drq_cb(*this), + m_dacl(*this, "dacl"), + m_dacr(*this, "dacr") +{ +} + +static MACHINE_CONFIG_FRAGMENT( ad1848_config ) + MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") + MCFG_SOUND_ADD("dacl", DAC, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "lspeaker", 1.00) + MCFG_SOUND_ADD("dacr", DAC, 0) + MCFG_SOUND_ROUTE(ALL_OUTPUTS, "rspeaker", 1.00) +MACHINE_CONFIG_END + +machine_config_constructor ad1848_device::device_mconfig_additions() const +{ + return MACHINE_CONFIG_NAME( ad1848_config ); +} + +void ad1848_device::device_start() +{ + m_timer = timer_alloc(0, nullptr); + m_irq_cb.resolve_safe(); + m_drq_cb.resolve_safe(); +} + +void ad1848_device::device_reset() +{ + memset(&m_regs.idx[0], '\0', sizeof(m_regs)); + m_addr = 0; + m_stat = 0; + m_sam_cnt = 0; + m_samples = 0; + m_play = false; +} + +READ8_MEMBER(ad1848_device::read) +{ + switch(offset) + { + case 0: + return m_addr | (m_mce ? 0x40 : 0) | (m_trd ? 0x20 : 0); + case 1: + return m_regs.idx[m_addr]; + case 2: + return m_stat; + case 3: + break; // capture + } + return 0; +} + +WRITE8_MEMBER(ad1848_device::write) +{ + const int div_factor[] = {3072, 1536, 896, 768, 448, 384, 512, 2560}; + switch(offset) + { + case 0: + m_addr = data & 0xf; + m_mce = data & 0x40 ? true : false; + m_trd = data & 0x20 ? true : false; + break; + case 1: + if(m_addr == 12) + return; + m_regs.idx[m_addr] = data; + switch(m_addr) + { + case 8: + if(m_mce) + return; + m_regs.dform &= 0x7f; + break; + case 9: + { + m_play = (data & 1) ? true : false; + attotime rate = m_play ? attotime::from_hz(((m_regs.dform & 1) ? XTAL_24_576MHz : XTAL_16_9344MHz) + / div_factor[(m_regs.dform >> 1) & 7]) : attotime::never; + m_timer->adjust(rate, 0 , rate); + m_drq_cb(m_play ? ASSERT_LINE : CLEAR_LINE); + break; + } + case 14: + m_count = (m_regs.ubase << 8) | m_regs.lbase; + break; + } + break; + case 2: + m_irq_cb(CLEAR_LINE); + if(m_regs.iface & 1) + m_play = true; + break; + case 3: + break; // playback + } +} + +READ8_MEMBER(ad1848_device::dack_r) +{ + m_drq_cb(CLEAR_LINE); + return 0; // not implemented +} + +WRITE8_MEMBER(ad1848_device::dack_w) +{ + if(!m_play) + return; + m_samples = (m_samples << 8) | data; + m_sam_cnt++; + switch(m_regs.dform >> 4) + { + case 0: + case 2: + case 6: + m_sam_cnt = 0; + break; + case 1: + case 3: + case 4: + case 7: + if(m_sam_cnt == 2) + m_sam_cnt = 0; + break; + case 5: + if(m_sam_cnt == 4) + m_sam_cnt = 0; + break; + } + if(!m_sam_cnt) + m_drq_cb(CLEAR_LINE); +} + +void ad1848_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + if(!m_play) + return; + switch(m_regs.dform >> 4) + { + case 0: // 8bit mono + m_dacl->write_unsigned8(m_samples & 0xff); + m_dacr->write_unsigned8(m_samples & 0xff); + break; + case 1: // 8bit stereo + m_dacl->write_unsigned8(m_samples & 0xff); + m_dacr->write_unsigned8((m_samples >> 8) & 0xff); + break; + case 2: // ulaw mono + case 3: // ulaw stereo + case 6: // alaw mono + case 7: // alaw stereo + break; + case 4: // 16bit mono + m_dacl->write(m_samples & 0xffff); + m_dacr->write(m_samples & 0xffff); + break; + case 5: // 16bit stereo + m_dacl->write(m_samples & 0xffff); + m_dacr->write(m_samples >> 16); + break; + } + if(!m_count) + { + if(m_regs.pinc & 2) + { + if(m_trd) + m_play = false; + m_irq_cb(ASSERT_LINE); + } + m_count = (m_regs.ubase << 8) | m_regs.lbase; + } + else + m_count--; + m_drq_cb(ASSERT_LINE); +} diff --git a/src/devices/sound/ad1848.h b/src/devices/sound/ad1848.h new file mode 100644 index 00000000000..d2c93c57329 --- /dev/null +++ b/src/devices/sound/ad1848.h @@ -0,0 +1,67 @@ +// license:BSD-3-Clause +// copyright-holders:Carl +#ifndef _AD1848_H_ +#define _AD1848_H_ + +#include "emu.h" +#include "sound/dac.h" + +#define MCFG_AD1848_IRQ_CALLBACK(_cb) \ + devcb = &ad1848_device::set_irq_callback(*device, DEVCB_##_cb); + +#define MCFG_AD1848_DRQ_CALLBACK(_cb) \ + devcb = &ad1848_device::set_drq_callback(*device, DEVCB_##_cb); + +class ad1848_device : public device_t +{ +public: + ad1848_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); + DECLARE_READ8_MEMBER(read); + DECLARE_WRITE8_MEMBER(write); + DECLARE_READ8_MEMBER(dack_r); + DECLARE_WRITE8_MEMBER(dack_w); + template<class _Object> static devcb_base &set_irq_callback(device_t &device, _Object object) { return downcast<ad1848_device &>(device).m_irq_cb.set_callback(object); } + template<class _Object> static devcb_base &set_drq_callback(device_t &device, _Object object) { return downcast<ad1848_device &>(device).m_drq_cb.set_callback(object); } + virtual machine_config_constructor device_mconfig_additions() const override; +protected: + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; +private: + union { + struct { + UINT8 linp; + UINT8 rinp; + UINT8 laux1; + UINT8 raux1; + UINT8 laux2; + UINT8 raux2; + UINT8 lout; + UINT8 rout; + UINT8 dform; + UINT8 iface; + UINT8 pinc; + UINT8 init; + UINT8 misc; + UINT8 mix; + UINT8 ubase; + UINT8 lbase; + }; + UINT8 idx[15]; + } m_regs; + UINT8 m_addr; + UINT8 m_stat; + UINT16 m_count; + UINT32 m_samples; + UINT8 m_sam_cnt; + bool m_play, m_mce, m_trd; + devcb_write_line m_irq_cb; + devcb_write_line m_drq_cb; + required_device<dac_device> m_dacl; + required_device<dac_device> m_dacr; + emu_timer *m_timer; +}; + +extern const device_type AD1848; + +#endif |