summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2021-06-02 01:53:50 -0700
committer Aaron Giles <aaron@aarongiles.com>2021-06-02 01:53:50 -0700
commit3f3e0eda38bc08c9ad67ae46543ff7a0f45a856e (patch)
treeb4a0a60be3a58874316b8c2dd9e8e4705a4b0be8
parent251389765dd5b1b41b919e6e66aa688277d64150 (diff)
ympsr60: Add filters around BBD
-rw-r--r--src/mame/drivers/ympsr60.cpp94
1 files changed, 78 insertions, 16 deletions
diff --git a/src/mame/drivers/ympsr60.cpp b/src/mame/drivers/ympsr60.cpp
index 81631ad32f0..48293bbf2e3 100644
--- a/src/mame/drivers/ympsr60.cpp
+++ b/src/mame/drivers/ympsr60.cpp
@@ -1,15 +1,22 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont
+// copyright-holders:R. Belmont,Aaron Giles
/*
Yamaha PSR-60/PSR-70 PortaSound keyboards
Preliminary driver by R. Belmont, major thanks to reverse-engineering work by JKN0
+ Note: PSR-50 is likely the same hardware.
+
+ Special thanks to
+
Documentation: https://github.com/JKN0/PSR70-reverse
More documentation: https://retroandreverse.blogspot.com/2021/01/reversing-psr-70-hardware.html
https://retroandreverse.blogspot.com/2021/01/reversing-psr-70-firmware.html
https://retroandreverse.blogspot.com/2021/01/digging-into-ymopq.html
- Service manual: https://elektrotanya.com/yamaha_psr-70_sm.pdf/download.html
+ Service manuals: https://elektrotanya.com/yamaha_psr-60.pdf/download.html
+ https://elektrotanya.com/yamaha_psr-70_sm.pdf/download.html
+
+ Thanks to Lord Nightmare for help with the BBD filter chain
CPU: Z80 @ 6 MHz
Sound: YM3533 "OPQ" FM @ 3.58 MHz + YM2154 "RYP" sample playback chip for drums
@@ -47,6 +54,8 @@
#include "machine/6850acia.h"
#include "machine/clock.h"
#include "sound/bbd.h"
+#include "sound/flt_biquad.h"
+#include "sound/flt_rc.h"
#include "sound/mixer.h"
#include "sound/ym2154.h"
#include "sound/ymopq.h"
@@ -73,8 +82,16 @@ public:
m_acia(*this, "acia"),
m_lmixer(*this, "lmixer"),
m_rmixer(*this, "rmixer"),
+ m_bbd_mixer(*this, "bbdmixer"),
m_bbd(*this, "bbd"),
m_ryp4(*this, "ryp4"),
+ m_ic206b(*this, "ic206b"),
+ m_ic206a(*this, "ic206a"),
+ m_ic205(*this, "ic205"),
+ m_postbbd_rc(*this, "postbbd_rc"),
+ m_ic204b(*this, "ic204b"),
+ m_first_rc(*this, "first_rc"),
+ m_ic204a(*this, "ic204a"),
m_rom2bank(*this, "rom2bank"),
m_keyboard(*this, "P1_%u", 0),
m_drvif(*this, "DRVIF_%u", 0),
@@ -99,8 +116,16 @@ private:
required_device<acia6850_device> m_acia;
required_device<mixer_device> m_lmixer;
required_device<mixer_device> m_rmixer;
+ required_device<mixer_device> m_bbd_mixer;
required_device<mn3204p_device> m_bbd;
required_device<ym2154_device> m_ryp4;
+ required_device<filter_biquad_device> m_ic206b;
+ required_device<filter_biquad_device> m_ic206a;
+ required_device<filter_biquad_device> m_ic205;
+ required_device<filter_rc_device> m_postbbd_rc;
+ required_device<filter_biquad_device> m_ic204b;
+ required_device<filter_rc_device> m_first_rc;
+ required_device<filter_biquad_device> m_ic204a;
required_memory_bank m_rom2bank;
required_ioport_array<10> m_keyboard;
required_ioport_array<DRVIF_MAX_TARGETS> m_drvif;
@@ -194,7 +219,7 @@ void psr60_state::ryp4_out_w(u8 data)
m_bbd_config = data;
// bit 0 (CT0) enables/disables the effect
- m_bbd->set_output_gain(0, BIT(data, 0) ? 1.0 : 0.0);
+ m_ic206a->set_output_gain(0, BIT(data, 0) ? 1.0 : 0.0);
// bits 1 + 2 go to the 'T' and 'C' pins and control the frequency
// modulation, which we simulate in a periodic timer
@@ -290,7 +315,6 @@ void psr60_state::machine_start()
m_rom2bank->configure_entries(0, 2, memregion("rom2")->base(), 0x4000);
m_rom2bank->set_entry(0);
m_acia_irq = CLEAR_LINE;
- timer_alloc()->adjust(attotime::from_hz(50), 0, attotime::from_hz(50));
}
void psr60_state::machine_reset()
@@ -433,7 +457,7 @@ static INPUT_PORTS_START(psr60)
RYP4_PORT(10, 0, "Unused10")
PORT_START("MASTERVOL")
- PORT_ADJUSTER(50, "Master Volume") PORT_CHANGED_MEMBER(DEVICE_SELF, psr60_state, mastervol_changed, 0)
+ PORT_ADJUSTER(50, "PSR Master Volume") PORT_CHANGED_MEMBER(DEVICE_SELF, psr60_state, mastervol_changed, 0)
INPUT_PORTS_END
static INPUT_PORTS_START(psr70)
@@ -573,7 +597,7 @@ static INPUT_PORTS_START(psr70)
RYP4_PORT(10, 0, "Unused10")
PORT_START("MASTERVOL")
- PORT_ADJUSTER(50, "Master Volume") PORT_CHANGED_MEMBER(DEVICE_SELF, psr60_state, mastervol_changed, 0)
+ PORT_ADJUSTER(50, "PSR Master Volume") PORT_CHANGED_MEMBER(DEVICE_SELF, psr60_state, mastervol_changed, 0)
INPUT_PORTS_END
void psr60_state::psr_common(machine_config &config)
@@ -608,17 +632,48 @@ void psr60_state::psr_common(machine_config &config)
MIXER(config, m_rmixer);
m_rmixer->add_route(0, "rspeaker", 1.0);
- YM2154(config, m_ryp4, 2250000);
- m_ryp4->irq_handler().set(FUNC(psr60_state::ryp4_irq_w));
- m_ryp4->io_read_handler().set(FUNC(psr60_state::ryp4_an_r));
- m_ryp4->io_write_handler().set(FUNC(psr60_state::ryp4_out_w));
- m_ryp4->add_route(0, m_lmixer, 0.50); // rhythm channels are mixed in separately
- m_ryp4->add_route(1, m_rmixer, 0.50);
+ // begin BBD filter chain....
+ // thanks to Lord Nightmare for figuring this out
+ FILTER_BIQUAD(config, m_ic206b);
+ m_ic206b->opamp_mfb_lowpass_setup(RES_K(100), 0, RES_K(100), 0, CAP_P(100));
+ m_ic206b->add_route(0, m_lmixer, 0.11);
+ m_ic206b->add_route(0, m_rmixer, 0.11);
+
+ // not accurate, not correctly modeling the 22k resistor in series with the cap
+ FILTER_BIQUAD(config, m_ic206a);
+ m_ic206a->opamp_mfb_lowpass_setup(RES_K(33), 0, RES_K(22), 0, CAP_P(0.0039));
+ m_ic206a->add_route(0, m_ic206b, 1.0);
+
+ FILTER_BIQUAD(config, m_ic205);
+ m_ic205->opamp_sk_lowpass_setup(RES_K(22), RES_K(22), RES_M(999.9), RES_R(0.001), CAP_U(0.0068), CAP_P(82));
+ m_ic205->add_route(0, m_ic206a, 1.0);
+
+ FILTER_RC(config, m_postbbd_rc);
+ m_postbbd_rc->set_rc(filter_rc_device::LOWPASS_2C, RES_K(22), 0, 0, CAP_U(0.0015));
+ m_postbbd_rc->add_route(0, m_ic205, 1.0);
- MN3204P(config, m_bbd, 12700); // 6.7kHz feeds the iG10090 driver, range is 10-200kHz
+ MIXER(config, m_bbd_mixer);
+ m_bbd_mixer->add_route(0, m_postbbd_rc, 1.0);
+
+ MN3204P(config, m_bbd, 50000);
m_bbd->set_cv_handler(FUNC(psr60_state::cv_handler));
- m_bbd->add_route(0, m_lmixer, 0.11); // BBD is mixed in
- m_bbd->add_route(0, m_rmixer, 0.11);
+ m_bbd->add_route(0, m_bbd_mixer, 0.5);
+ m_bbd->add_route(1, m_bbd_mixer, 0.5);
+
+ FILTER_BIQUAD(config, m_ic204b);
+ m_ic204b->opamp_sk_lowpass_setup(RES_K(22), RES_K(22), RES_M(999.9), RES_R(0.001), CAP_U(0.0068), CAP_P(82));
+ m_ic204b->add_route(0, m_bbd, 1.0);
+
+ FILTER_RC(config, m_first_rc);
+ m_first_rc->set_rc(filter_rc_device::LOWPASS_2C, RES_R(22), 0, 0, CAP_U(0.0015));
+ m_first_rc->add_route(0, m_ic204b, 1.0);
+
+ // not accurate, not correctly modeling the 22k resistor bypassing the 22k resistor in series
+ // with the cap, and just assuming two 22k resistors in parallel
+ FILTER_BIQUAD(config, m_ic204a);
+ m_ic204a->opamp_mfb_lowpass_setup(RES_K(11), 0, RES_K(47), 0, CAP_P(150));
+ m_ic204a->add_route(0, m_first_rc, 1.0);
+ // end BBD filter chain....
YM3533(config, m_ym3533, 3.579545_MHz_XTAL);
m_ym3533->irq_handler().set(FUNC(psr60_state::ym_irq_w));
@@ -626,7 +681,14 @@ void psr60_state::psr_common(machine_config &config)
m_ym3533->add_route(0, m_rmixer, 0.16);
m_ym3533->add_route(1, m_lmixer, 0.22); // channel 2 = SABC
m_ym3533->add_route(1, m_rmixer, 0.22);
- m_ym3533->add_route(1, m_bbd, 1.0);
+ m_ym3533->add_route(1, m_ic204a, 1.0); // routed to BBD via filters
+
+ YM2154(config, m_ryp4, 2250000);
+ m_ryp4->irq_handler().set(FUNC(psr60_state::ryp4_irq_w));
+ m_ryp4->io_read_handler().set(FUNC(psr60_state::ryp4_an_r));
+ m_ryp4->io_write_handler().set(FUNC(psr60_state::ryp4_out_w));
+ m_ryp4->add_route(0, m_lmixer, 0.50);
+ m_ryp4->add_route(1, m_rmixer, 0.50);
}
void psr60_state::psr60(machine_config &config)