From e15b2b50addadecbf4e13304dca4e99991140118 Mon Sep 17 00:00:00 2001 From: mooglyguy Date: Wed, 29 May 2019 02:16:16 +0200 Subject: -hal2: Various changes. [Ryan Holtz] * Added handling for different frequency rates. * Moved DAC devices into HAL2 from HPC3. * Added readback of DAC parameters. * Fixed stereo DAC playback. --- src/mame/machine/hal2.cpp | 269 ++++++++++++++++++++++++++++++++++++++++++---- src/mame/machine/hal2.h | 56 +++++++++- src/mame/machine/hpc3.cpp | 37 ++----- src/mame/machine/hpc3.h | 5 - 4 files changed, 308 insertions(+), 59 deletions(-) diff --git a/src/mame/machine/hal2.cpp b/src/mame/machine/hal2.cpp index f80c7b80fec..778e26f6f23 100644 --- a/src/mame/machine/hal2.cpp +++ b/src/mame/machine/hal2.cpp @@ -21,8 +21,8 @@ DEFINE_DEVICE_TYPE(SGI_HAL2, hal2_device, "hal2", "SGI HAL2") hal2_device::hal2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SGI_HAL2, tag, owner, clock) - , m_iar(0) - , m_idr{0, 0, 0, 0} + , m_ldac(*this, "ldac") + , m_rdac(*this, "rdac") { } @@ -31,6 +31,19 @@ void hal2_device::device_start() save_item(NAME(m_isr)); save_item(NAME(m_iar)); save_item(NAME(m_idr)); + save_item(NAME(m_codeca_ctrl)); + save_item(NAME(m_codeca_channel)); + save_item(NAME(m_codeca_clock)); + save_item(NAME(m_codeca_channel_count)); + save_item(NAME(m_codecb_ctrl)); + save_item(NAME(m_codecb_channel)); + save_item(NAME(m_codecb_clock)); + save_item(NAME(m_codecb_channel_count)); + save_item(NAME(m_bres_clock_sel)); + save_item(NAME(m_bres_clock_inc)); + save_item(NAME(m_bres_clock_modctrl)); + save_item(NAME(m_bres_clock_freq)); + save_item(NAME(m_curr_dac)); } void hal2_device::device_reset() @@ -38,6 +51,23 @@ void hal2_device::device_reset() m_isr = 0; m_iar = 0; memset(m_idr, 0, sizeof(uint32_t) * 4); + memset(m_codeca_ctrl, 0, sizeof(uint32_t) * 2); + m_codeca_channel = 0; + m_codeca_clock = 0; + m_codeca_channel_count = 0; + memset(m_codecb_ctrl, 0, sizeof(uint32_t) * 2); + m_codecb_channel = 0; + m_codecb_clock = 0; + m_codecb_channel_count = 0; + memset(m_bres_clock_sel, 0, sizeof(uint32_t) * 3); + memset(m_bres_clock_inc, 0, sizeof(uint32_t) * 3); + memset(m_bres_clock_modctrl, 0, sizeof(uint32_t) * 3); + memset(m_bres_clock_freq, 0, sizeof(uint32_t) * 3); + for (int i = 0; i < 3; i++) + { + m_bres_clock_rate[i] = attotime::zero; + } + m_curr_dac = 0; } READ32_MEMBER(hal2_device::read) @@ -50,6 +80,22 @@ READ32_MEMBER(hal2_device::read) case REVISION_REG: LOGMASKED(LOG_READS, "%s: HAL2 Revision Read: 0x4011\n", machine().describe_context()); return 0x4011; + + case INDIRECT_DATA0_REG: + LOGMASKED(LOG_WRITES, "%s: HAL2 Indirect Data Register 0 Read: %08x & %08x\n", machine().describe_context(), m_idr[3], mem_mask); + return m_idr[0]; + + case INDIRECT_DATA1_REG: + LOGMASKED(LOG_WRITES, "%s: HAL2 Indirect Data Register 1 Read: %08x & %08x\n", machine().describe_context(), m_idr[3], mem_mask); + return m_idr[1]; + + case INDIRECT_DATA2_REG: + LOGMASKED(LOG_WRITES, "%s: HAL2 Indirect Data Register 2 Read: %08x & %08x\n", machine().describe_context(), m_idr[3], mem_mask); + return m_idr[2]; + + case INDIRECT_DATA3_REG: + LOGMASKED(LOG_WRITES, "%s: HAL2 Indirect Data Register 3 Read: %08x & %08x\n", machine().describe_context(), m_idr[3], mem_mask); + return m_idr[3]; } LOGMASKED(LOG_READS | LOG_UNKNOWN, "%s: Unknown HAL2 read: %08x & %08x\n", machine().describe_context(), 0x1fbd8000 + offset*4, mem_mask); return 0; @@ -85,31 +131,143 @@ WRITE32_MEMBER(hal2_device::write) LOGMASKED(LOG_WRITES, " AES Out\n"); break; case 0x0400: - LOGMASKED(LOG_WRITES, " DAC Out\n"); + { + LOGMASKED(LOG_WRITES, " Codec A (DAC) Out\n"); + const uint32_t param = (data & IAR_PARAM) >> IAR_PARAM_SHIFT; + switch (param) + { + case 1: + LOGMASKED(LOG_WRITES, " Control 1\n"); + if (data & IAR_ACCESS_SEL) + { + m_idr[0] = m_codeca_ctrl[0]; + } + else + { + m_codeca_ctrl[0] = m_idr[0]; + m_codeca_channel = m_idr[0] & 3; + m_codeca_clock = (m_idr[0] >> 3) & 3; + m_codeca_channel_count = (m_idr[0] >> 8) & 3; + } + break; + case 2: + LOGMASKED(LOG_WRITES, " Control 2\n"); + if (data & IAR_ACCESS_SEL) + { + m_idr[0] = m_codeca_ctrl[1]; + } + else + { + m_codeca_ctrl[1] = m_idr[0]; + } + break; + default: + LOGMASKED(LOG_WRITES, " Unknown Register\n"); + break; + } break; + } case 0x0500: - LOGMASKED(LOG_WRITES, " ADC Out\n"); + { + LOGMASKED(LOG_WRITES, " Codec B (ADC) Out\n"); + const uint32_t param = (data & IAR_PARAM) >> IAR_PARAM_SHIFT; + switch (param) + { + case 1: + LOGMASKED(LOG_WRITES, " Control 1\n"); + if (data & IAR_ACCESS_SEL) + { + m_idr[0] = m_codecb_ctrl[0]; + } + else + { + m_codecb_ctrl[0] = m_idr[0]; + m_codecb_channel = m_idr[0] & 3; + m_codecb_clock = (m_idr[0] >> 3) & 3; + m_codecb_channel_count = (m_idr[0] >> 8) & 3; + } + break; + case 2: + LOGMASKED(LOG_WRITES, " Control 2\n"); + if (data & IAR_ACCESS_SEL) + { + m_idr[0] = m_codecb_ctrl[1]; + } + else + { + m_codecb_ctrl[1] = m_idr[0]; + } + break; + default: + LOGMASKED(LOG_WRITES, " Unknown Register\n"); + break; + } break; + } case 0x0600: LOGMASKED(LOG_WRITES, " Synth Control\n"); break; + default: + LOGMASKED(LOG_WRITES, " Unknown\n"); + break; } break; case 0x2000: + { LOGMASKED(LOG_WRITES, " Bresenham\n"); - switch (data & IAR_NUM) + uint32_t clock_gen = (data & IAR_NUM) >> IAR_NUM_SHIFT; + if (clock_gen >= 1 && clock_gen <= 3) { - case 0x0100: - LOGMASKED(LOG_WRITES, " Bresenham Clock Gen 1\n"); - break; - case 0x0200: - LOGMASKED(LOG_WRITES, " Bresenham Clock Gen 2\n"); - break; - case 0x0300: - LOGMASKED(LOG_WRITES, " Bresenham Clock Gen 3\n"); - break; + LOGMASKED(LOG_WRITES, " Bresenham Clock Gen %d\n", clock_gen); + clock_gen--; + const uint32_t param = (data & IAR_PARAM) >> IAR_PARAM_SHIFT; + if (param == 1) + { + LOGMASKED(LOG_WRITES, " Control 1 (Clock Select)\n"); + if (data & IAR_ACCESS_SEL) + { + m_idr[0] = m_bres_clock_sel[clock_gen]; + } + else + { + m_bres_clock_sel[clock_gen] = m_idr[0]; + switch (m_idr[0]) + { + case 0: LOGMASKED(LOG_WRITES, " 48kHz\n"); break; + case 1: LOGMASKED(LOG_WRITES, " 44.1kHz\n"); break; + case 2: LOGMASKED(LOG_WRITES, " Off\n"); break; + default: LOGMASKED(LOG_WRITES, " Unknown (%d)\n", m_idr[0]); break; + } + update_clock_freq(clock_gen); + } + } + else if (param == 2) + { + LOGMASKED(LOG_WRITES, " Control 2 (Inc/Mod Ctrl)\n"); + if (data & IAR_ACCESS_SEL) + { + m_idr[0] = m_bres_clock_inc[clock_gen]; + m_idr[1] = m_bres_clock_modctrl[clock_gen]; + } + else + { + m_bres_clock_inc[clock_gen] = m_idr[0]; + m_bres_clock_modctrl[clock_gen] = m_idr[1]; + LOGMASKED(LOG_WRITES, " Inc:%04x, ModCtrl:%04x\n", (uint16_t)m_idr[0], (uint16_t)m_idr[1]); + update_clock_freq(clock_gen); + } + } + else + { + LOGMASKED(LOG_WRITES, " Unknown Param\n"); + } + } + else + { + LOGMASKED(LOG_WRITES, " Unknown\n"); } break; + } case 0x3000: LOGMASKED(LOG_WRITES, " Unix Timer\n"); @@ -118,6 +276,9 @@ WRITE32_MEMBER(hal2_device::write) case 0x0100: LOGMASKED(LOG_WRITES, " Unix Timer\n"); break; + default: + LOGMASKED(LOG_WRITES, " Unknown\n"); + break; } break; @@ -128,19 +289,18 @@ WRITE32_MEMBER(hal2_device::write) case 0x0100: LOGMASKED(LOG_WRITES, " DMA Control\n"); break; + default: + LOGMASKED(LOG_WRITES, " Unknown\n"); + break; } break; } - switch (data & IAR_ACCESS_SEL) - { - case 0x0000: - LOGMASKED(LOG_WRITES, " Write\n"); - break; - case 0x0080: + if (data & IAR_ACCESS_SEL) LOGMASKED(LOG_WRITES, " Read\n"); - break; - } + else + LOGMASKED(LOG_WRITES, " Write\n"); + LOGMASKED(LOG_WRITES, " Parameter: %01x\n", (data & IAR_PARAM) >> 2); return; @@ -169,3 +329,68 @@ WRITE32_MEMBER(hal2_device::write) break; } } + +void hal2_device::update_clock_freq(int clock_gen) +{ + switch (m_bres_clock_sel[clock_gen]) + { + case 0: // 48kHz + m_bres_clock_freq[clock_gen] = 48000; + break; + case 1: // 44.1kHz + m_bres_clock_freq[clock_gen] = 44100; + break; + default: + m_bres_clock_freq[clock_gen] = 0; + m_bres_clock_rate[clock_gen] = attotime::zero; + return; + } + + const uint32_t mod = 0x10000 - (((uint16_t)m_bres_clock_modctrl[clock_gen] + 1) - m_bres_clock_inc[clock_gen]); + if (mod == 0) + m_bres_clock_rate[clock_gen] = attotime::from_ticks(1, m_bres_clock_freq[clock_gen] * m_bres_clock_inc[clock_gen]); + else + m_bres_clock_rate[clock_gen] = attotime::from_ticks(mod, m_bres_clock_freq[clock_gen] * m_bres_clock_inc[clock_gen]); +} + +attotime hal2_device::get_rate(const uint32_t channel) +{ + if ((channel == m_codeca_channel || channel == (3 - m_codeca_channel)) && m_codeca_clock > 0 && m_codeca_channel_count > 0) + return m_bres_clock_rate[m_codeca_clock - 1] / m_codeca_channel_count; + if ((channel == m_codecb_channel || channel == (3 - m_codecb_channel)) && m_codecb_clock > 0 && m_codecb_channel_count > 0) + return m_bres_clock_rate[m_codecb_clock - 1] / m_codecb_channel_count; + return attotime::zero; +} + +void hal2_device::dma_write(uint32_t channel, int16_t data) +{ + if (channel >= 2) + return; + + if (m_curr_dac) + m_rdac->write(data); + else + m_ldac->write(data); + + m_curr_dac++; + if (m_curr_dac == m_codeca_channel_count) + m_curr_dac = 0; +} + +void hal2_device::device_add_mconfig(machine_config &config) +{ + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + + DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_ldac, 0); + m_ldac->add_route(ALL_OUTPUTS, "lspeaker", 0.25); + + DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_rdac, 0); + m_rdac->add_route(ALL_OUTPUTS, "rspeaker", 0.25); + + voltage_regulator_device &vreg = VOLTAGE_REGULATOR(config, "vref"); + vreg.add_route(0, "ldac", 1.0, DAC_VREF_POS_INPUT); + vreg.add_route(0, "rdac", 1.0, DAC_VREF_POS_INPUT); + vreg.add_route(0, "ldac", -1.0, DAC_VREF_NEG_INPUT); + vreg.add_route(0, "rdac", -1.0, DAC_VREF_NEG_INPUT); +} diff --git a/src/mame/machine/hal2.h b/src/mame/machine/hal2.h index 046429ca017..f7a866375fe 100644 --- a/src/mame/machine/hal2.h +++ b/src/mame/machine/hal2.h @@ -11,6 +11,10 @@ #pragma once +#include "sound/dac.h" +#include "sound/volt_reg.h" +#include "speaker.h" + class hal2_device : public device_t { public: @@ -24,17 +28,30 @@ public: DECLARE_WRITE32_MEMBER(write); DECLARE_READ32_MEMBER(read); + attotime get_rate(const uint32_t channel); + + void set_right_volume(uint8_t vol) { m_rdac->set_output_gain(ALL_OUTPUTS, vol / 255.0f); } + void set_left_volume(uint8_t vol) { m_ldac->set_output_gain(ALL_OUTPUTS, vol / 255.0f); } + + void dma_write(uint32_t channel, int16_t data); + protected: virtual void device_start() override; virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + void update_clock_freq(int clock_gen); enum { - IAR_TYPE = 0xf000, - IAR_NUM = 0x0f00, - IAR_ACCESS_SEL = 0x0080, - IAR_PARAM = 0x000c, - IAR_RB_INDEX = 0x0003, + IAR_TYPE = 0xf000, + IAR_TYPE_SHIFT = 12, + IAR_NUM = 0x0f00, + IAR_NUM_SHIFT = 8, + IAR_ACCESS_SEL = 0x0080, + IAR_PARAM = 0x000c, + IAR_PARAM_SHIFT = 2, + IAR_RB_INDEX = 0x0003 }; enum @@ -57,9 +74,38 @@ protected: INDIRECT_DATA3_REG = 0x0070/4, }; + enum + { + DAC_L, + DAC_R + }; + + required_device m_ldac; + required_device m_rdac; + uint32_t m_isr; uint32_t m_iar; uint32_t m_idr[4]; + + uint32_t m_codeca_ctrl[2]; + uint32_t m_codeca_channel; + uint32_t m_codeca_clock; + uint32_t m_codeca_channel_count; + + uint32_t m_codecb_ctrl[2]; + uint32_t m_codecb_channel; + uint32_t m_codecb_clock; + uint32_t m_codecb_channel_count; + + uint32_t m_bres_clock_sel[3]; + uint32_t m_bres_clock_inc[3]; + uint32_t m_bres_clock_modctrl[3]; + uint32_t m_bres_clock_freq[3]; + attotime m_bres_clock_rate[3]; + + uint32_t m_curr_dac; + + static const uint32_t s_channel_pair[4]; }; DECLARE_DEVICE_TYPE(SGI_HAL2, hal2_device) diff --git a/src/mame/machine/hpc3.cpp b/src/mame/machine/hpc3.cpp index 19bc0d71132..aa866bd29e4 100644 --- a/src/mame/machine/hpc3.cpp +++ b/src/mame/machine/hpc3.cpp @@ -45,8 +45,6 @@ hpc3_base_device::hpc3_base_device(const machine_config &mconfig, device_type ty , m_rtc(*this, "rtc") , m_ioc2(*this, "ioc2") , m_hal2(*this, "hal2") - , m_ldac(*this, "ldac") - , m_rdac(*this, "rdac") { } @@ -148,21 +146,6 @@ void hpc3_base_device::device_reset() void hpc3_base_device::device_add_mconfig(machine_config &config) { - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); - - DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_ldac, 0); - m_ldac->add_route(ALL_OUTPUTS, "lspeaker", 0.25); - - DAC_16BIT_R2R_TWOS_COMPLEMENT(config, m_rdac, 0); - m_rdac->add_route(ALL_OUTPUTS, "rspeaker", 0.25); - - voltage_regulator_device &vreg = VOLTAGE_REGULATOR(config, "vref"); - vreg.add_route(0, "ldac", 1.0, DAC_VREF_POS_INPUT); - vreg.add_route(0, "rdac", 1.0, DAC_VREF_POS_INPUT); - vreg.add_route(0, "ldac", -1.0, DAC_VREF_NEG_INPUT); - vreg.add_route(0, "rdac", -1.0, DAC_VREF_NEG_INPUT); - SGI_HAL2(config, m_hal2); DS1386_8K(config, m_rtc, 32768); @@ -237,10 +220,7 @@ void hpc3_base_device::do_pbus_dma(uint32_t channel) uint16_t temp16 = m_cpu_space->read_dword(dma.m_cur_ptr) >> 16; int16_t stemp16 = (int16_t)((temp16 >> 8) | (temp16 << 8)); - if (channel == 1) - m_ldac->write(stemp16); - else if (channel == 2) - m_rdac->write(stemp16); + m_hal2->dma_write(channel, stemp16); dma.m_cur_ptr += 4; dma.m_bytes_left -= 4; @@ -266,7 +246,7 @@ void hpc3_base_device::do_pbus_dma(uint32_t channel) return; } } - dma.m_timer->adjust(attotime::from_hz(44100)); + dma.m_timer->adjust(m_hal2->get_rate(channel)); } else { @@ -646,12 +626,12 @@ WRITE32_MEMBER(hpc3_base_device::volume_w) if (offset == 0) { m_volume_r = (uint8_t)data; - m_rdac->set_output_gain(ALL_OUTPUTS, m_volume_r / 255.0f); + m_hal2->set_right_volume((uint8_t)data); } else { m_volume_l = (uint8_t)data; - m_ldac->set_output_gain(ALL_OUTPUTS, m_volume_l / 255.0f); + m_hal2->set_left_volume((uint8_t)data); } } @@ -765,7 +745,6 @@ WRITE32_MEMBER(hpc3_base_device::pbus4_w) READ32_MEMBER(hpc3_base_device::pbusdma_r) { uint32_t channel = offset / (0x2000/4); - LOGMASKED(LOG_PBUS_DMA, "%s: PBUS DMA Channel %d Read: %08x & %08x\n", machine().describe_context(), channel, 0x1fb80000 + offset*4, mem_mask); pbus_dma_t &dma = m_pbus_dma[channel]; uint32_t ret = 0; @@ -836,8 +815,12 @@ WRITE32_MEMBER(hpc3_base_device::pbusdma_w) if (((data & PBUS_CTRL_DMASTART) && (data & PBUS_CTRL_LOAD_EN)) && channel < 4) { LOGMASKED(LOG_PBUS_DMA, " Starting DMA\n"); - dma.m_timer->adjust(attotime::from_hz(44100)); - dma.m_active = true; + attotime rate = m_hal2->get_rate(channel); + if (rate != attotime::zero) + { + dma.m_timer->adjust(rate); + dma.m_active = true; + } } break; default: diff --git a/src/mame/machine/hpc3.h b/src/mame/machine/hpc3.h index df72fbe424a..5b10a724be5 100644 --- a/src/mame/machine/hpc3.h +++ b/src/mame/machine/hpc3.h @@ -16,9 +16,6 @@ #include "machine/hal2.h" #include "machine/ioc2.h" #include "machine/wd33c9x.h" -#include "sound/dac.h" -#include "sound/volt_reg.h" -#include "speaker.h" class hpc3_base_device : public device_t { @@ -149,8 +146,6 @@ protected: required_device m_rtc; required_device m_ioc2; required_device m_hal2; - required_device m_ldac; - required_device m_rdac; uint32_t m_intstat; uint32_t m_cpu_aux_ctrl; -- cgit v1.2.3