From 8517445efaabf91382b4c227a8b6790041a187ab Mon Sep 17 00:00:00 2001 From: arbee Date: Mon, 17 Jun 2024 21:49:58 -0400 Subject: [PATCH] mame/apple: Added preliminary Apple DFAC audio filter/volume implementation. [R. Belmont] - Initial DFAC with volume control and master on/off - Hooked up to LC, LC II, LC III, IIvx, IIvi, Quadra 700, Quadra 800 --- src/mame/apple/dfac.cpp | 170 ++++++++++++++++++++++++++++++++ src/mame/apple/dfac.h | 34 +++++++ src/mame/apple/iosb.cpp | 11 +++ src/mame/apple/iosb.h | 6 +- src/mame/apple/maciivx.cpp | 20 +++- src/mame/apple/maclc.cpp | 37 +++++-- src/mame/apple/maclc3.cpp | 26 ++++- src/mame/apple/macquadra700.cpp | 11 ++- src/mame/apple/macquadra800.cpp | 8 ++ src/mame/apple/sonora.cpp | 19 +++- src/mame/apple/sonora.h | 5 +- src/mame/apple/v8.cpp | 26 +++-- src/mame/apple/v8.h | 6 +- src/mame/apple/vasp.cpp | 18 +++- src/mame/apple/vasp.h | 5 +- 15 files changed, 370 insertions(+), 32 deletions(-) create mode 100644 src/mame/apple/dfac.cpp create mode 100644 src/mame/apple/dfac.h diff --git a/src/mame/apple/dfac.cpp b/src/mame/apple/dfac.cpp new file mode 100644 index 00000000000..dcb20dfb904 --- /dev/null +++ b/src/mame/apple/dfac.cpp @@ -0,0 +1,170 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +/*************************************************************************** + + dfac.cpp - Apple Digitally Filtered Audio Chip, which controls input and + output gain and filtering. + + DFAC uses a 3-wire serial interface, where it caches the last + 8 bits seen over a data/clock pair and writes that byte to the + working space when a low/high transition occurs on a third + "latch" line. + + ________________________ + / 4 3 2 1 28 27 26 | + | * | + | 5 25 | + | 6 344S1033 24 | + | 7 23 | + | 8 (C)'90 APPLE 22 | + | 9 21 | + | 10 20 | + | 11 19 | + |____12_13_14_15_16_17_18__| + + 1 - Vcom - AC ground reference output, 1/2 of Vdd + 2 - Bypass - Connect 10 uF electrolytic here for Vcom stablity + 3 - Vdd2 - Chip's Vdd supply, 8 volts DC + 4 - Vdd1 - " " " " " " + 5 - IV out - Current-to-voltage op-amp output + 6 - IV- - inverted output of current-to-voltage op-amp + 7 - NFin - Noise Filter op-amp non-inverting input + 8 - AmpOut - Output for either the record gain or playback PWM. + Typically connected to SCFin. + 9 - /REDUCEGAIN - Open-drain pulldown digital output used to decrease the gain + of an external op-amp. + 10 - SoundOut - Analog audio output + 11 - SCFin - Switched Capacitor Filter input + 12 - SCFout - output of Switched Capacitor Filter + 13 - ADin - A/D converter input. Goes through volume control attenuator and + ends up at the pin 10 output. + 14 - /RESET + 15 - SerDOut - A/D converter serial digital output + 16 - SampleClk - Sample clock + 17 - SerClk - Serial clock, used to clock individual bits of the sample + 18 - VssD - Digital ground + 19 - ConfigClk - Configuration bit clock + 20 - ConfigData - Configuration bit data. Latched on the rising edge of ConfigClk. + 21 - ConfigLE - Configuration Latch Enable. Causes the last 8 bits seen on the + rising edge of ConfigClk to become the new configuraiton byte. + 22 - PWMin - PWM-encoded input pulse. TTL compatible. + 23 - PWMout - Level shifted version of PWMin. Output swings between Vss and Vdd. + 24 - LPFin - Low Pass Filter input. Used to remove harmonics from PWMout. + 25 - LPFout - Output from LPFin. Normally connected to SCFin. + 26 - VssA - Analog ground + 27 - Vlow - A/D converter's low reference voltage (1 volt less than Vcom) + 28 - Vhigh - A/D converter's high reference voltage (1 volt more than Vcom) + + The control byte is as follows: + 7654 3210 + VVV - volume + T - playthrough enable (input is mixed with output) + GG - 0 = /REDUCE_GAIN low (enabled), 2 = /REDUCE_GAIN reacts to a comparitor + on the input. If 1 or 3, /REDUCE_GAIN is tristated. + L - LPF In to mix with Noise input and go to Amp Out (0=Off, 1=On) + N - Noise input enable: 0 = enabled, 1 = disabled + + Signal flow through the chip: + PWM In -> PWM Out (level shifts the PWM signal from TTL to the chip's voltage range) + LPF In -> LPF Out (no change) and to (switch on config bit 1) -> Amp Out + NF In -> (switch on config bit 0) -> Amp Out + SCF In -> switched capacitor filter -> SCF Out + AD In -> volume attenuator (top 3 bits of config byte) -> Sound Out + + Standard hookup verified on schematics for LC/LC II/LC III/Classic II: + PWM from system ASIC -> PWM In, PWM Out -> LPF In, Amp Out -> SCF In, SCF Out -> AD In. + + TODO: SCF and external 2-pole RC lowpass filter. + + +***************************************************************************/ + +#include "emu.h" +#include "dfac.h" + +#define VERBOSE (0) + +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(APPLE_DFAC, dfac_device, "apldfac", "Apple Digitally Filtered Audio Chip") + +static constexpr double atten_table[8] = +{ + 0.0, // -infinite + 0.125892541179417, // -18dB + 0.177827941003892, // -15dB + 0.251188643150958, // -12dB + 0.354813389233575, // -9dB + 0.501187233627272, // -6dB + 0.707945784384138, // -3dB + 1.0 // No attenuation +}; + +dfac_device::dfac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, APPLE_DFAC, tag, owner, clock), + device_sound_interface(mconfig, *this), + m_stream(nullptr), + m_data(false), + m_clock(false), + m_dfaclatch(false), + m_settings_byte(0), + m_latch_byte(0) +{ +} + +void dfac_device::device_start() +{ + m_stream = stream_alloc(8, 2, clock(), STREAM_SYNCHRONOUS); + + save_item(NAME(m_clock)); + save_item(NAME(m_data)); + save_item(NAME(m_dfaclatch)); + save_item(NAME(m_settings_byte)); +} + +void dfac_device::sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) +{ + if (BIT(m_settings_byte, 1)) // LPF In can go through to Amp Out + { + for (int i = 0; i < inputs[0].samples(); i++) + { + stream_buffer::sample_t l = inputs[0].get(i); + stream_buffer::sample_t r = inputs[1].get(i); + outputs[0].put(i, l * atten_table[m_settings_byte >> 5]); + outputs[1].put(i, r * atten_table[m_settings_byte >> 5]); + } + } + else + { + for (int i = 0; i < inputs[0].samples(); i++) + { + outputs[0].put(i, 0.0); + outputs[1].put(i, 0.0); + } + } +} + +void dfac_device::clock_write(int state) +{ + // take a bit on the rising edge of SCL + if (state && !m_clock) + { + m_latch_byte >>= 1; + m_latch_byte |= m_data ? 0x80 : 0; + } + + m_clock = state; +} + +void dfac_device::latch_write(int state) +{ + // commit settings byte on the rising edge of the latch + if (state && !m_dfaclatch) + { + m_settings_byte = m_latch_byte; + LOG("DFAC: applying new settings byte %02x (volume %d, atten %f)\n", m_settings_byte, m_settings_byte >> 5, atten_table[m_settings_byte >> 5]); + } + + m_dfaclatch = state; +} + diff --git a/src/mame/apple/dfac.h b/src/mame/apple/dfac.h new file mode 100644 index 00000000000..65ce743b581 --- /dev/null +++ b/src/mame/apple/dfac.h @@ -0,0 +1,34 @@ +// license:BSD-3-Clause +// copyright-holders:R. Belmont +#ifndef MAME_APPLE_DFAC_H +#define MAME_APPLE_DFAC_H + +#pragma once + +class dfac_device : public device_t, public device_sound_interface +{ +public: + dfac_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + // DFAC uses a serial 3-wire interface where a single control byte is shifted in, and it ignores + // writes with the gate is not at the right level. This allowed it to be used on the Egret's I2C bus + // without it being disturbed by actual I2C transactions. + void data_write(int state) { m_data = state; } + void clock_write(int state); + void latch_write(int state); + +protected: + // device_r overrides + virtual void device_start() override; + // device_sound_interface overrides + virtual void sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) override; + +private: + sound_stream *m_stream; + bool m_data, m_clock, m_dfaclatch; + u8 m_settings_byte, m_latch_byte; +}; + +DECLARE_DEVICE_TYPE(APPLE_DFAC, dfac_device) + +#endif // MAME_APPLE_DFAC_H diff --git a/src/mame/apple/iosb.cpp b/src/mame/apple/iosb.cpp index 6747f5fe149..8a8a226067c 100644 --- a/src/mame/apple/iosb.cpp +++ b/src/mame/apple/iosb.cpp @@ -81,6 +81,7 @@ void iosb_base::device_add_mconfig(machine_config &config) R65NC22(config, m_via2, C7M / 10); m_via2->readpa_handler().set(FUNC(iosb_base::via2_in_a)); + m_via2->writepb_handler().set(FUNC(iosb_base::via2_out_b)); m_via2->irq_handler().set(FUNC(iosb_base::via2_irq)); SPEAKER(config, "lspeaker").front_left(); @@ -115,6 +116,9 @@ iosb_base::iosb_base(const machine_config &mconfig, device_type type, const char m_adb_st(*this), m_cb1(*this), m_cb2(*this), + m_dfac_clock_w(*this), + m_dfac_data_w(*this), + m_dfac_latch_w(*this), m_pa1(*this, 0), m_pa2(*this, 0), m_pa4(*this, 0), @@ -268,6 +272,13 @@ void iosb_base::via1_irq(int state) field_interrupts(); } +void iosb_base::via2_out_b(uint8_t data) +{ + m_dfac_latch_w(BIT(data, 0)); + m_dfac_data_w(BIT(data, 3)); + m_dfac_clock_w(BIT(data, 4)); +} + void iosb_base::via2_irq(int state) { m_via2_interrupt = state; diff --git a/src/mame/apple/iosb.h b/src/mame/apple/iosb.h index 7742729d8da..3d279ae61e2 100644 --- a/src/mame/apple/iosb.h +++ b/src/mame/apple/iosb.h @@ -28,6 +28,9 @@ public: auto write_adb_st() { return m_adb_st.bind(); } // ADB state auto write_cb1() { return m_cb1.bind(); } // ADB clock auto write_cb2() { return m_cb2.bind(); } // ADB data + auto write_dfac_clock() { return m_dfac_clock_w.bind(); } + auto write_dfac_data() { return m_dfac_data_w.bind(); } + auto write_dfac_latch() { return m_dfac_latch_w.bind(); } auto read_pa1() { return m_pa1.bind(); } // ID bits auto read_pa2() { return m_pa2.bind(); } @@ -69,7 +72,7 @@ protected: virtual void iosb_regs_w(offs_t offset, u16 data, u16 mem_mask); devcb_write8 m_adb_st; - devcb_write_line m_cb1, m_cb2; + devcb_write_line m_cb1, m_cb2, m_dfac_clock_w, m_dfac_data_w, m_dfac_latch_w; devcb_read_line m_pa1, m_pa2, m_pa4, m_pa6; required_device m_maincpu; @@ -107,6 +110,7 @@ private: void field_interrupts(); void via_out_cb1(int state); void via_out_cb2(int state); + void via2_out_b(uint8_t data); void via1_irq(int state); void via2_irq(int state); void asc_irq(int state); diff --git a/src/mame/apple/maciivx.cpp b/src/mame/apple/maciivx.cpp index 77fac6fe6cc..f2325a8b4f3 100644 --- a/src/mame/apple/maciivx.cpp +++ b/src/mame/apple/maciivx.cpp @@ -19,6 +19,7 @@ #include "emu.h" +#include "dfac.h" #include "egret.h" #include "macadb.h" #include "macscsi.h" @@ -42,6 +43,7 @@ #include "emupal.h" #include "screen.h" #include "softlist_dev.h" +#include "speaker.h" namespace { @@ -58,6 +60,7 @@ public: m_macadb(*this, "macadb"), m_ram(*this, RAM_TAG), m_vasp(*this, "vasp"), + m_dfac(*this, "dfac"), m_fdc(*this, "fdc"), m_floppy(*this, "fdc:%d", 0U), m_scsibus1(*this, "scsi"), @@ -82,6 +85,7 @@ private: required_device m_macadb; required_device m_ram; required_device m_vasp; + required_device m_dfac; required_device m_fdc; required_device_array m_floppy; required_device m_scsibus1; @@ -298,8 +302,8 @@ void maciivx_state::maciiv_base(machine_config &config) NSCSI_CONNECTOR(config, "scsi:3").option_set("cdrom", NSCSI_CDROM_APPLE).machine_config( [](device_t *device) { - device->subdevice("cdda")->add_route(0, "^^vasp:lspeaker", 1.0); - device->subdevice("cdda")->add_route(1, "^^vasp:rspeaker", 1.0); + device->subdevice("cdda")->add_route(0, "^^lspeaker", 1.0); + device->subdevice("cdda")->add_route(1, "^^rspeaker", 1.0); }); NSCSI_CONNECTOR(config, "scsi:4", mac_scsi_devices, nullptr); NSCSI_CONNECTOR(config, "scsi:5", mac_scsi_devices, nullptr); @@ -338,10 +342,19 @@ void maciivx_state::maciiv_base(machine_config &config) rs232b.dcd_handler().set(m_scc, FUNC(z80scc_device::dcdb_w)); rs232b.cts_handler().set(m_scc, FUNC(z80scc_device::ctsb_w)); + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + + APPLE_DFAC(config, m_dfac, 22257); + m_dfac->add_route(0, "lspeaker", 1.0); + m_dfac->add_route(1, "rspeaker", 1.0); + VASP(config, m_vasp, C15M); m_vasp->set_maincpu_tag("maincpu"); m_vasp->set_rom_tag("bootrom"); m_vasp->hdsel_callback().set(FUNC(maciivx_state::hdsel_w)); + m_vasp->add_route(0, m_dfac, 1.0); + m_vasp->add_route(1, m_dfac, 1.0); MACADB(config, m_macadb, C15M); @@ -374,6 +387,9 @@ void maciivx_state::maciivx(machine_config &config) EGRET(config, m_egret, XTAL(32'768)); m_egret->set_default_bios_tag("341s0851"); m_egret->reset_callback().set(FUNC(maciivx_state::egret_reset_w)); + m_egret->dfac_scl_callback().set(m_dfac, FUNC(dfac_device::clock_write)); + m_egret->dfac_sda_callback().set(m_dfac, FUNC(dfac_device::data_write)); + m_egret->dfac_latch_callback().set(m_dfac, FUNC(dfac_device::latch_write)); m_egret->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); m_egret->via_clock_callback().set(m_vasp, FUNC(vasp_device::cb1_w)); m_egret->via_data_callback().set(m_vasp, FUNC(vasp_device::cb2_w)); diff --git a/src/mame/apple/maclc.cpp b/src/mame/apple/maclc.cpp index 05bc7205cca..2e3ef95a6f4 100644 --- a/src/mame/apple/maclc.cpp +++ b/src/mame/apple/maclc.cpp @@ -10,7 +10,7 @@ controller, which has a 10 MB hard limit on RAM (8MB in the Mac TV). Mac TV video input chips: - TEA63330T - Sound fader control unit for car stereos + TEA6330T - Sound fader control unit for car stereos I2C: address 1000000x TDA8708BT - Video analog input interface SAA7197 T - Clock signal generator circuit for desktop video systems @@ -24,6 +24,7 @@ #include "emu.h" #include "cuda.h" +#include "dfac.h" #include "egret.h" #include "macadb.h" #include "macscsi.h" @@ -48,7 +49,7 @@ #include "emupal.h" #include "screen.h" #include "softlist_dev.h" - +#include "speaker.h" namespace { #define C32M (31.3344_MHz_XTAL) @@ -64,6 +65,7 @@ public: m_macadb(*this, "macadb"), m_ram(*this, RAM_TAG), m_v8(*this, "v8"), + m_dfac(*this, "dfac"), m_fdc(*this, "fdc"), m_floppy(*this, "fdc:%d", 0U), m_scsibus1(*this, "scsi"), @@ -91,6 +93,7 @@ private: required_device m_macadb; required_device m_ram; required_device m_v8; + optional_device m_dfac; optional_device m_fdc; optional_device_array m_floppy; required_device m_scsibus1; @@ -324,8 +327,8 @@ void maclc_state::maclc_base(machine_config &config) NSCSI_CONNECTOR(config, "scsi:3").option_set("cdrom", NSCSI_CDROM_APPLE).machine_config( [](device_t *device) { - device->subdevice("cdda")->add_route(0, "^^v8:lspeaker", 1.0); - device->subdevice("cdda")->add_route(1, "^^v8:rspeaker", 1.0); + device->subdevice("cdda")->add_route(0, "^^lspeaker", 1.0); + device->subdevice("cdda")->add_route(1, "^^rspeaker", 1.0); }); NSCSI_CONNECTOR(config, "scsi:4", mac_scsi_devices, nullptr); NSCSI_CONNECTOR(config, "scsi:5", mac_scsi_devices, nullptr); @@ -364,11 +367,20 @@ void maclc_state::maclc_base(machine_config &config) rs232b.dcd_handler().set(m_scc, FUNC(z80scc_device::dcdb_w)); rs232b.cts_handler().set(m_scc, FUNC(z80scc_device::ctsb_w)); + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + + APPLE_DFAC(config, m_dfac, 22257); + m_dfac->add_route(0, "lspeaker", 1.0); + m_dfac->add_route(1, "rspeaker", 1.0); + V8(config, m_v8, C15M); m_v8->set_maincpu_tag("maincpu"); m_v8->set_rom_tag("bootrom"); m_v8->hdsel_callback().set(FUNC(maclc_state::hdsel_w)); m_v8->hmmu_enable_callback().set(FUNC(maclc_state::set_hmmu)); + m_v8->add_route(0, m_dfac, 1.0); + m_v8->add_route(1, m_dfac, 1.0); nubus_device &nubus(NUBUS(config, "pds", 0)); nubus.set_space(m_maincpu, AS_PROGRAM); @@ -382,6 +394,9 @@ void maclc_state::maclc_base(machine_config &config) EGRET(config, m_egret, XTAL(32'768)); m_egret->set_default_bios_tag("341s0850"); m_egret->reset_callback().set(FUNC(maclc_state::egret_reset_w)); + m_egret->dfac_scl_callback().set(m_dfac, FUNC(dfac_device::clock_write)); + m_egret->dfac_sda_callback().set(m_dfac, FUNC(dfac_device::data_write)); + m_egret->dfac_latch_callback().set(m_dfac, FUNC(dfac_device::latch_write)); m_egret->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); m_egret->via_clock_callback().set(m_v8, FUNC(v8_device::cb1_w)); m_egret->via_data_callback().set(m_v8, FUNC(v8_device::cb2_w)); @@ -441,7 +456,7 @@ void maclc_state::maccclas(machine_config &config) config.device_remove("fdc"); CUDA_V2XX(config, m_cuda, XTAL(32'768)); - m_cuda->set_default_bios_tag("341s0788"); + m_cuda->set_default_bios_tag("341s0417"); m_cuda->reset_callback().set(FUNC(maclc_state::egret_reset_w)); m_cuda->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); m_cuda->via_clock_callback().set(m_v8, FUNC(v8_device::cb1_w)); @@ -457,6 +472,10 @@ void maclc_state::maccclas(machine_config &config) m_v8->pb4_callback().set(m_cuda, FUNC(cuda_device::set_byteack)); m_v8->pb5_callback().set(m_cuda, FUNC(cuda_device::set_tip)); m_v8->cb2_callback().set(m_cuda, FUNC(cuda_device::set_via_data)); + m_v8->add_route(0, "lspeaker", 1.0); + m_v8->add_route(1, "rspeaker", 1.0); + + config.device_remove("dfac"); NUBUS_SLOT(config, "lcpds", "pds", mac_pdslc_cards, nullptr); @@ -479,7 +498,7 @@ void maclc_state::mactv(machine_config &config) config.device_remove("fdc"); CUDA_V2XX(config, m_cuda, XTAL(32'768)); - m_cuda->set_default_bios_tag("341s0788"); + m_cuda->set_default_bios_tag("341s0788"); // TODO: 0789 freezes during boot, possible VIA bug or 6522/6523 difference? m_cuda->reset_callback().set(FUNC(maclc_state::egret_reset_w)); m_cuda->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); m_cuda->via_clock_callback().set(m_v8, FUNC(v8_device::cb1_w)); @@ -495,6 +514,10 @@ void maclc_state::mactv(machine_config &config) m_v8->pb4_callback().set(m_cuda, FUNC(cuda_device::set_byteack)); m_v8->pb5_callback().set(m_cuda, FUNC(cuda_device::set_tip)); m_v8->cb2_callback().set(m_cuda, FUNC(cuda_device::set_via_data)); + m_v8->add_route(0, "lspeaker", 1.0); + m_v8->add_route(1, "rspeaker", 1.0); + + config.device_remove("dfac"); // Mac TV doesn't have an LC PDS config.device_remove("pds"); @@ -522,6 +545,8 @@ void maclc_state::macclas2(machine_config &config) m_v8->pb4_callback().set(m_egret, FUNC(egret_device::set_via_full)); m_v8->pb5_callback().set(m_egret, FUNC(egret_device::set_sys_session)); m_v8->cb2_callback().set(m_egret, FUNC(egret_device::set_via_data)); + m_v8->add_route(0, m_dfac, 1.0); + m_v8->add_route(1, m_dfac, 1.0); // Classic II doesn't have an LC PDS slot (and its ROM has the Slot Manager disabled) config.device_remove("pds"); diff --git a/src/mame/apple/maclc3.cpp b/src/mame/apple/maclc3.cpp index b2d538013bb..c0fe497dc18 100644 --- a/src/mame/apple/maclc3.cpp +++ b/src/mame/apple/maclc3.cpp @@ -18,6 +18,7 @@ #include "emu.h" #include "cuda.h" +#include "dfac.h" #include "egret.h" #include "macadb.h" #include "macscsi.h" @@ -38,6 +39,7 @@ #include "emupal.h" #include "screen.h" +#include "speaker.h" #include "softlist_dev.h" namespace { @@ -54,6 +56,7 @@ public: m_macadb(*this, "macadb"), m_ram(*this, RAM_TAG), m_sonora(*this, "sonora"), + m_dfac(*this, "dfac"), m_scsibus1(*this, "scsi"), m_ncr5380(*this, "scsi:7:ncr5380"), m_scsihelp(*this, "scsihelp"), @@ -79,6 +82,7 @@ private: optional_device m_macadb; required_device m_ram; required_device m_sonora; + optional_device m_dfac; required_device m_scsibus1; required_device m_ncr5380; required_device m_scsihelp; @@ -247,8 +251,8 @@ void macvail_state::maclc3_base(machine_config &config) NSCSI_CONNECTOR(config, "scsi:3").option_set("cdrom", NSCSI_CDROM_APPLE).machine_config( [](device_t *device) { - device->subdevice("cdda")->add_route(0, "^^sonora:lspeaker", 1.0); - device->subdevice("cdda")->add_route(1, "^^sonora:rspeaker", 1.0); + device->subdevice("cdda")->add_route(0, "^^lspeaker", 1.0); + device->subdevice("cdda")->add_route(1, "^^rspeaker", 1.0); }); NSCSI_CONNECTOR(config, "scsi:4", mac_scsi_devices, nullptr); NSCSI_CONNECTOR(config, "scsi:5", mac_scsi_devices, nullptr); @@ -287,9 +291,18 @@ void macvail_state::maclc3_base(machine_config &config) rs232b.dcd_handler().set(m_scc, FUNC(z80scc_device::dcdb_w)); rs232b.cts_handler().set(m_scc, FUNC(z80scc_device::ctsb_w)); + SPEAKER(config, "lspeaker").front_left(); + SPEAKER(config, "rspeaker").front_right(); + + APPLE_DFAC(config, m_dfac, 22257); + m_dfac->add_route(0, "lspeaker", 1.0); + m_dfac->add_route(1, "rspeaker", 1.0); + SONORA(config, m_sonora, C15M); m_sonora->set_maincpu_tag("maincpu"); m_sonora->set_rom_tag("bootrom"); + m_sonora->add_route(0, m_dfac, 1.0); + m_sonora->add_route(1, m_dfac, 1.0); nubus_device &nubus(NUBUS(config, "pds", 0)); nubus.set_space(m_maincpu, AS_PROGRAM); @@ -310,6 +323,9 @@ void macvail_state::maclc3(machine_config &config) EGRET(config, m_egret, XTAL(32'768)); m_egret->set_default_bios_tag("341s0851"); m_egret->reset_callback().set(FUNC(macvail_state::cuda_reset_w)); + m_egret->dfac_scl_callback().set(m_dfac, FUNC(dfac_device::clock_write)); + m_egret->dfac_sda_callback().set(m_dfac, FUNC(dfac_device::data_write)); + m_egret->dfac_latch_callback().set(m_dfac, FUNC(dfac_device::latch_write)); m_egret->linechange_callback().set(m_macadb, FUNC(macadb_device::adb_linechange_w)); m_egret->via_clock_callback().set(m_sonora, FUNC(sonora_device::cb1_w)); m_egret->via_data_callback().set(m_sonora, FUNC(sonora_device::cb2_w)); @@ -347,6 +363,12 @@ void macvail_state::maclc520(machine_config &config) m_sonora->pb4_callback().set(m_cuda, FUNC(cuda_device::set_byteack)); m_sonora->pb5_callback().set(m_cuda, FUNC(cuda_device::set_tip)); m_sonora->cb2_callback().set(m_cuda, FUNC(cuda_device::set_via_data)); + + // DFAC only is found in machines with Egret, and not the IIsi + m_sonora->reset_routes(); + m_sonora->add_route(0, "lspeaker", 1.0); + m_sonora->add_route(1, "rspeaker", 1.0); + config.device_remove("dfac"); } void macvail_state::maclc550(machine_config &config) diff --git a/src/mame/apple/macquadra700.cpp b/src/mame/apple/macquadra700.cpp index 3942fed3715..058b158f9d2 100644 --- a/src/mame/apple/macquadra700.cpp +++ b/src/mame/apple/macquadra700.cpp @@ -13,6 +13,7 @@ #include "adbmodem.h" #include "dafb.h" +#include "dfac.h" #include "macadb.h" #include "macrtc.h" #include "mactoolbox.h" @@ -44,7 +45,6 @@ #define C7M (C32M/4) namespace { - class macquadra_state : public driver_device { public: @@ -64,6 +64,7 @@ public: m_sonic(*this, "sonic"), m_dafb(*this, "dafb"), m_easc(*this, "easc"), + m_dfac(*this, "dfac"), m_scc(*this, "scc"), m_cur_floppy(nullptr), m_hdsel(0) @@ -89,6 +90,7 @@ private: required_device m_sonic; required_device m_dafb; required_device m_easc; + required_device m_dfac; required_device m_scc; virtual void machine_start() override; @@ -535,6 +537,10 @@ void macquadra_state::mac_via2_out_b(u8 data) { // chain 60.15 Hz to VIA1 m_via1->write_ca1(data>>7); + + m_dfac->data_write(BIT(data, 3)); + m_dfac->clock_write(BIT(data, 4)); + m_dfac->latch_write(BIT(data, 0)); } void macquadra_state::phases_w(u8 phases) @@ -675,6 +681,9 @@ void macquadra_state::macqd700(machine_config &config) m_easc->add_route(0, "lspeaker", 1.0); m_easc->add_route(1, "rspeaker", 1.0); + // DFAC is only for audio input on Q700/Q800 + APPLE_DFAC(config, m_dfac, 22257); + /* internal ram */ RAM(config, m_ram); m_ram->set_default_size("4M"); diff --git a/src/mame/apple/macquadra800.cpp b/src/mame/apple/macquadra800.cpp index 654cab83a1d..e94fa1e985a 100644 --- a/src/mame/apple/macquadra800.cpp +++ b/src/mame/apple/macquadra800.cpp @@ -20,6 +20,7 @@ #include "emu.h" #include "adbmodem.h" +#include "dfac.h" #include "djmemc.h" #include "iosb.h" #include "macadb.h" @@ -54,6 +55,7 @@ public: m_maincpu(*this, "maincpu"), m_djmemc(*this, "djmemc"), m_iosb(*this, "iosb"), + m_dfac(*this, "dfac"), m_macadb(*this, "macadb"), m_adbmodem(*this, "adbmodem"), m_scc(*this, "scc"), @@ -78,6 +80,7 @@ private: required_device m_maincpu; required_device m_djmemc; required_device m_iosb; + required_device m_dfac; required_device m_macadb; required_device m_adbmodem; required_device m_scc; @@ -193,6 +196,11 @@ void quadra800_state::macqd800(machine_config &config) m_iosb->read_pa4().set_constant(1); m_iosb->read_pa6().set_constant(0); + APPLE_DFAC(config, m_dfac, 22257); + m_iosb->write_dfac_clock().set(m_dfac, FUNC(dfac_device::clock_write)); + m_iosb->write_dfac_data().set(m_dfac, FUNC(dfac_device::data_write)); + m_iosb->write_dfac_latch().set(m_dfac, FUNC(dfac_device::latch_write)); + SCC85C30(config, m_scc, C7M); m_scc->configure_channels(3'686'400, 3'686'400, 3'686'400, 3'686'400); m_scc->out_int_callback().set(m_iosb, FUNC(iosb_device::scc_irq_w)); diff --git a/src/mame/apple/sonora.cpp b/src/mame/apple/sonora.cpp index 64a86042a3b..961ba4841d7 100644 --- a/src/mame/apple/sonora.cpp +++ b/src/mame/apple/sonora.cpp @@ -77,11 +77,10 @@ void sonora_device::device_add_mconfig(machine_config &config) m_via1->cb2_handler().set(FUNC(sonora_device::via_out_cb2)); m_via1->irq_handler().set(FUNC(sonora_device::via1_irq)); - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); + ASC(config, m_asc, C15M, asc_device::asc_type::SONORA); - m_asc->add_route(0, "lspeaker", 1.0); - m_asc->add_route(1, "rspeaker", 1.0); + m_asc->add_route(0, tag(), 1.0); + m_asc->add_route(1, tag(), 1.0); m_asc->irqf_callback().set(FUNC(sonora_device::asc_irq)); SWIM2(config, m_fdc, C15M); @@ -98,6 +97,7 @@ void sonora_device::device_add_mconfig(machine_config &config) sonora_device::sonora_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SONORA, tag, owner, clock), + device_sound_interface(mconfig, *this), write_pb4(*this), write_pb5(*this), write_cb2(*this), @@ -123,6 +123,8 @@ void sonora_device::device_start() { m_vram = std::make_unique(0x100000 / sizeof(u32)); + m_stream = stream_alloc(8, 2, m_asc->clock(), STREAM_SYNCHRONOUS); + m_6015_timer = timer_alloc(FUNC(sonora_device::mac_6015_tick), this); m_6015_timer->adjust(attotime::never); @@ -176,6 +178,15 @@ void sonora_device::device_reset() space.install_rom(0x00000000, memory_end & ~memory_mirror, memory_mirror, m_rom_ptr); } +void sonora_device::sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) +{ + for (int i = 0; i < inputs[0].samples(); i++) + { + outputs[0].put(i, inputs[0].get(i)); + outputs[1].put(i, inputs[1].get(i)); + } +} + u32 sonora_device::rom_switch_r(offs_t offset) { // disable the overlay diff --git a/src/mame/apple/sonora.h b/src/mame/apple/sonora.h index ab2bf8c79e8..046a84386a7 100644 --- a/src/mame/apple/sonora.h +++ b/src/mame/apple/sonora.h @@ -15,7 +15,7 @@ // ======================> sonora_device -class sonora_device : public device_t +class sonora_device : public device_t, public device_sound_interface { public: // construction/destruction @@ -49,6 +49,8 @@ protected: virtual void device_reset() override; virtual void device_add_mconfig(machine_config &config) override; + virtual void sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) override; + private: devcb_write_line write_pb4, write_pb5, write_cb2; devcb_read_line read_pb3; @@ -62,6 +64,7 @@ private: required_region_ptr m_rom; std::unique_ptr m_vram; + sound_stream *m_stream; emu_timer *m_6015_timer; int m_via_interrupt, m_via2_interrupt, m_scc_interrupt, m_last_taken_interrupt; uint8_t m_pseudovia_regs[256], m_pseudovia_ier, m_pseudovia_ifr; diff --git a/src/mame/apple/v8.cpp b/src/mame/apple/v8.cpp index 485c83762cf..1661828697b 100644 --- a/src/mame/apple/v8.cpp +++ b/src/mame/apple/v8.cpp @@ -114,12 +114,10 @@ void v8_device::device_add_mconfig(machine_config &config) m_via1->cb2_handler().set(FUNC(v8_device::via_out_cb2)); m_via1->irq_handler().set(FUNC(v8_device::via1_irq)); - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); ASC(config, m_asc, C15M, asc_device::asc_type::V8); - m_asc->add_route(0, "lspeaker", 1.0); - m_asc->add_route(1, "rspeaker", 1.0); m_asc->irqf_callback().set(FUNC(v8_device::asc_irq)); + m_asc->add_route(0, tag(), 1.0); + m_asc->add_route(1, tag(), 1.0); } //------------------------------------------------- @@ -133,6 +131,7 @@ v8_device::v8_device(const machine_config &mconfig, const char *tag, device_t *o v8_device::v8_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) : device_t(mconfig, type, tag, owner, clock), + device_sound_interface(mconfig, *this), m_maincpu(*this, finder_base::DUMMY_TAG), m_screen(*this, "screen"), m_palette(*this, "palette"), @@ -159,6 +158,8 @@ void v8_device::device_start() { m_vram = std::make_unique(0x100000 / sizeof(u32)); + m_stream = stream_alloc(8, 2, m_asc->clock(), STREAM_SYNCHRONOUS); + m_6015_timer = timer_alloc(FUNC(v8_device::mac_6015_tick), this); m_6015_timer->adjust(attotime::never); @@ -214,6 +215,15 @@ void v8_device::device_reset() space.install_rom(0x00000000, memory_end & ~memory_mirror, memory_mirror, &m_rom[0]); } +void v8_device::sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) +{ + for (int i = 0; i < inputs[0].samples(); i++) + { + outputs[0].put(i, inputs[0].get(i)); + outputs[1].put(i, inputs[1].get(i)); + } +} + u32 v8_device::rom_switch_r(offs_t offset) { // disable the overlay @@ -877,8 +887,8 @@ void eagle_device::device_add_mconfig(machine_config &config) m_screen->set_raw(15.6672_MHz_XTAL, 704, 0, 512, 370, 0, 342); ASC(config.replace(), m_asc, C15M, asc_device::asc_type::EAGLE); - m_asc->add_route(0, "lspeaker", 1.0); - m_asc->add_route(1, "rspeaker", 1.0); + m_asc->add_route(0, tag(), 1.0); + m_asc->add_route(1, tag(), 1.0); m_asc->irqf_callback().set(FUNC(eagle_device::asc_irq)); } @@ -958,8 +968,8 @@ void spice_device::device_add_mconfig(machine_config &config) m_screen->set_raw(15.6672_MHz_XTAL, 640, 0, 512, 407, 0, 384); ASC(config.replace(), m_asc, C15M, asc_device::asc_type::SONORA); - m_asc->add_route(0, "lspeaker", 1.0); - m_asc->add_route(1, "rspeaker", 1.0); + m_asc->add_route(0, tag(), 1.0); + m_asc->add_route(1, tag(), 1.0); m_asc->irqf_callback().set(FUNC(spice_device::asc_irq)); SWIM2(config, m_fdc, C15M); diff --git a/src/mame/apple/v8.h b/src/mame/apple/v8.h index 10cc8ec4cb7..f97042dfb38 100644 --- a/src/mame/apple/v8.h +++ b/src/mame/apple/v8.h @@ -11,12 +11,11 @@ #include "machine/swim2.h" #include "sound/asc.h" #include "emupal.h" -#include "speaker.h" #include "screen.h" // ======================> v8_device -class v8_device : public device_t +class v8_device : public device_t, public device_sound_interface { public: // construction/destruction @@ -63,6 +62,8 @@ protected: virtual void device_add_mconfig(machine_config &config) override; virtual ioport_constructor device_input_ports() const override; + virtual void sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) override; + virtual u8 pseudovia_r(offs_t offset); void asc_irq(int state); @@ -77,6 +78,7 @@ private: required_device m_via1; required_region_ptr m_rom; + sound_stream *m_stream; emu_timer *m_6015_timer; int m_via_interrupt, m_via2_interrupt, m_scc_interrupt, m_last_taken_interrupt; u8 m_pseudovia_ier, m_pseudovia_ifr; diff --git a/src/mame/apple/vasp.cpp b/src/mame/apple/vasp.cpp index 12ca833c65c..23ff2add9bf 100644 --- a/src/mame/apple/vasp.cpp +++ b/src/mame/apple/vasp.cpp @@ -85,11 +85,9 @@ void vasp_device::device_add_mconfig(machine_config &config) m_via1->cb2_handler().set(FUNC(vasp_device::via_out_cb2)); m_via1->irq_handler().set(FUNC(vasp_device::via1_irq)); - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); ASC(config, m_asc, C15M, asc_device::asc_type::VASP); - m_asc->add_route(0, "lspeaker", 1.0); - m_asc->add_route(1, "rspeaker", 1.0); + m_asc->add_route(0, tag(), 1.0); + m_asc->add_route(1, tag(), 1.0); m_asc->irqf_callback().set(FUNC(vasp_device::asc_irq)); } @@ -99,6 +97,7 @@ void vasp_device::device_add_mconfig(machine_config &config) vasp_device::vasp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, VASP, tag, owner, clock), + device_sound_interface(mconfig, *this), write_pb4(*this), write_pb5(*this), write_cb2(*this), @@ -123,6 +122,8 @@ void vasp_device::device_start() { m_vram = std::make_unique(0x100000 / sizeof(u32)); + m_stream = stream_alloc(8, 2, m_asc->clock(), STREAM_SYNCHRONOUS); + m_6015_timer = timer_alloc(FUNC(vasp_device::mac_6015_tick), this); m_6015_timer->adjust(attotime::never); @@ -181,6 +182,15 @@ void vasp_device::device_reset() space.install_rom(0x00000000, memory_end & ~memory_mirror, memory_mirror, m_rom_ptr); } +void vasp_device::sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) +{ + for (int i = 0; i < inputs[0].samples(); i++) + { + outputs[0].put(i, inputs[0].get(i)); + outputs[1].put(i, inputs[1].get(i)); + } +} + u32 vasp_device::rom_switch_r(offs_t offset) { // disable the overlay diff --git a/src/mame/apple/vasp.h b/src/mame/apple/vasp.h index 9c98ab7bded..09184f608e7 100644 --- a/src/mame/apple/vasp.h +++ b/src/mame/apple/vasp.h @@ -14,7 +14,7 @@ // ======================> vasp_device -class vasp_device : public device_t +class vasp_device : public device_t, public device_sound_interface { public: // construction/destruction @@ -53,6 +53,8 @@ protected: virtual void device_add_mconfig(machine_config &config) override; virtual ioport_constructor device_input_ports() const override; + virtual void sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) override; + private: devcb_write_line write_pb4, write_pb5, write_cb2, write_hdsel; devcb_read_line read_pb3; @@ -66,6 +68,7 @@ private: required_region_ptr m_rom; std::unique_ptr m_vram; + sound_stream *m_stream; emu_timer *m_6015_timer; int m_via_interrupt, m_via2_interrupt, m_scc_interrupt, m_last_taken_interrupt; u8 m_pseudovia_regs[256], m_pseudovia_ier, m_pseudovia_ifr;