sfxphasor: added netlist sound

This commit is contained in:
hap 2023-01-06 17:29:35 +01:00
parent f3e219ff88
commit 2892a11538
4 changed files with 117 additions and 54 deletions

View File

@ -49,8 +49,6 @@ ROM source notes when dumped from another title, but confident it's the same:
TODO:
- tweak MCU frequency for games when video/audio recording surfaces(YouTube etc.)
- sfxphasor default music mode should have volume decay, I can't get it working
without breaking sound effects or command C (volume decay with values 15 and up)
- what's the relation between drdunk and hccbaskb? Probably made by the same
Hong Kong subcontractor? I presume Toytronic.
- uspbball and pabball internal artwork
@ -63,6 +61,7 @@ TODO:
#include "video/pwm.h"
#include "machine/clock.h"
#include "machine/input_merger.h"
#include "machine/netlist.h"
#include "machine/timer.h"
#include "sound/dac.h"
#include "sound/flt_vol.h"
@ -70,6 +69,8 @@ TODO:
#include "speaker.h"
#include "nl_sfxphasor.h"
// internal artwork
#include "drdunk.lh"
#include "flash.lh" // clickable
@ -448,7 +449,7 @@ ROM_END
Electroplay Sound FX Phasor
* PIC 1655A-522
* 3-bit sound with volume decay
* 3-bit sound with volume envelope
It's a toy synthesizer. It included keypad overlays with nursery rhymes.
@ -465,61 +466,34 @@ class sfxphasor_state : public hh_pic16_state
public:
sfxphasor_state(const machine_config &mconfig, device_type type, const char *tag) :
hh_pic16_state(mconfig, type, tag),
m_dac(*this, "dac"),
m_volume(*this, "volume")
m_sound_nl(*this, "sound_nl:p%02u", 10U)
{ }
void sfxphasor(machine_config &config);
protected:
virtual void machine_start() override;
private:
required_device<dac_3bit_r2r_device> m_dac;
required_device<filter_volume_device> m_volume;
optional_device_array<netlist_mame_logic_input_device, 8> m_sound_nl;
void write_b(u8 data);
void write_c(u8 data);
u8 read_c();
TIMER_DEVICE_CALLBACK_MEMBER(speaker_decay_sim);
double m_speaker_volume = 0.0;
};
void sfxphasor_state::machine_start()
{
hh_pic16_state::machine_start();
save_item(NAME(m_speaker_volume));
}
// handlers
TIMER_DEVICE_CALLBACK_MEMBER(sfxphasor_state::speaker_decay_sim)
{
m_speaker_volume = std::clamp(m_speaker_volume, 0.0001, 1.0);
m_volume->flt_volume_set_volume(m_speaker_volume);
// volume goes down while B3 is low
if (~m_b & 8)
m_speaker_volume /= 1.0001;
// volume goes up while B3 is high
else
m_speaker_volume *= 1.0013;
}
void sfxphasor_state::write_b(u8 data)
{
// B2: trigger power off
if (~m_b & data & 4)
set_power(false);
// B0: trigger speaker on
if (~m_b & data & 1)
m_volume->flt_volume_set_volume(m_speaker_volume = 1.0);
// B0,B3: envelope param
m_sound_nl[0]->write_line(BIT(data, 0));
m_sound_nl[3]->write_line(BIT(data, 3));
// B5-B7: speaker out via 68K, 12K, 1K resistors
m_dac->write(data >> 5 & 7);
// B5-B7: sound out
for (int i = 5; i < 8; i++)
m_sound_nl[i]->write_line(BIT(data, i));
m_b = data;
}
@ -591,10 +565,14 @@ void sfxphasor_state::sfxphasor(machine_config &config)
// sound hardware
SPEAKER(config, "mono").front_center();
DAC_3BIT_R2R(config, m_dac).add_route(ALL_OUTPUTS, "volume", 0.25);
FILTER_VOLUME(config, m_volume).add_route(ALL_OUTPUTS, "mono", 1.0);
NETLIST_SOUND(config, "sound_nl", 48000).set_source(NETLIST_NAME(sfxphasor)).add_route(ALL_OUTPUTS, "mono", 0.25);
NETLIST_STREAM_OUTPUT(config, "sound_nl:cout0", 0, "SPK1.1").set_mult_offset(1.0, 0.0);
TIMER(config, "speaker_decay").configure_periodic(FUNC(sfxphasor_state::speaker_decay_sim), attotime::from_usec(10));
NETLIST_LOGIC_INPUT(config, "sound_nl:p10", "P10.IN", 0);
NETLIST_LOGIC_INPUT(config, "sound_nl:p13", "P13.IN", 0);
NETLIST_LOGIC_INPUT(config, "sound_nl:p15", "P15.IN", 0);
NETLIST_LOGIC_INPUT(config, "sound_nl:p16", "P16.IN", 0);
NETLIST_LOGIC_INPUT(config, "sound_nl:p17", "P17.IN", 0);
}
// roms

View File

@ -0,0 +1,78 @@
// license:CC0-1.0
// copyright-holders:hap
/*
Electroplay Sound FX Phasor (hh_pic16.cpp)
3-bit sound with volume envelope
*/
#include "netlist/devices/net_lib.h"
NETLIST_START(sfxphasor)
{
SOLVER(Solver, 48000)
PARAM(Solver.ACCURACY, 1e-7)
ANALOG_INPUT(VBATT, 5)
NET_MODEL("OPENDRAIN FAMILY(TYPE=MOS OVL=0.0 OVH=0.0 ORL=1.0 ORH=1e12)")
LOGIC_INPUT(P10, 0, "OPENDRAIN")
LOGIC_INPUT(P13, 0, "OPENDRAIN")
LOGIC_INPUT(P15, 0, "OPENDRAIN")
LOGIC_INPUT(P16, 0, "OPENDRAIN")
LOGIC_INPUT(P17, 0, "OPENDRAIN")
NET_C(VBATT, P10.VDD, P13.VDD, P15.VDD, P16.VDD, P17.VDD)
NET_C(GND, P10.VSS, P13.VSS, P15.VSS, P16.VSS, P17.VSS)
RES(R7, 270)
RES(R8, RES_K(6.8))
RES(R9, RES_K(18))
RES(R10, RES_K(5.6))
RES(R11, RES_K(180))
RES(R12, RES_K(10))
RES(R13, RES_K(68))
RES(R14, RES_K(12))
RES(R15, RES_K(1))
RES(SPK1, 60)
CAP(C2, CAP_U(4.7))
CAP(C5, CAP_N(100))
CAP(C6, CAP_N(10))
DIODE(D2, "1N4002")
DIODE(D3, "1N4002")
DIODE(D4, "1N4002")
QBJT_EB(T2, "BC237B") // BC183
QBJT_EB(T3, "BC237B") // BC183
QBJT_EB(T4, "BC237B") // BC183
// pin 10
NET_C(P10.Q, R7.1, C2.1)
NET_C(R7.2, VBATT)
NET_C(C2.2, T2.B, R11.1, D2.K, D3.K)
NET_C(GND, R11.2, D3.A)
NET_C(VBATT, T2.C)
NET_C(T2.E, D4.A, R10.1)
// pin 13
NET_C(P13.Q, R8.1, R9.1)
NET_C(R8.2, VBATT)
NET_C(R9.2, C5.1)
NET_C(C5.2, D4.K, D2.A)
// pin 15-17
NET_C(P15.Q, R13.1)
NET_C(P16.Q, R14.1)
NET_C(P17.Q, R15.1)
// output
NET_C(VBATT, T3.C, T4.C)
NET_C(T3.B, R10.2, R13.2, R14.2, R15.2, C6.1)
NET_C(C6.2, GND)
NET_C(T3.E, T4.B, R12.1)
NET_C(T4.E, R12.2, SPK1.1)
NET_C(SPK1.2, GND)
}

View File

@ -0,0 +1,6 @@
// license:CC0-1.0
// copyright-holders:hap
#include "netlist/nl_setup.h"
NETLIST_EXTERNAL(sfxphasor)

View File

@ -119,7 +119,7 @@ public:
m_psu(*this, "psu"),
m_display(*this, "display"),
m_speaker(*this, "speaker"),
m_snd_nl_pin(*this, "snd_nl:p%02u", 8U),
m_sound_nl(*this, "sound_nl:p%02u", 8U),
m_inputs(*this, "IN.%u", 0)
{ }
@ -135,7 +135,7 @@ private:
required_device<f38t56_device> m_psu;
required_device<pwm_display_device> m_display;
optional_device<speaker_sound_device> m_speaker;
optional_device_array<netlist_mame_logic_input_device, 8> m_snd_nl_pin;
optional_device_array<netlist_mame_logic_input_device, 8> m_sound_nl;
required_ioport_array<2> m_inputs;
void main_map(address_map &map);
@ -226,7 +226,7 @@ void gm_state::discrete_w(u8 data)
// P40-P47: 555 to speaker (see nl_gamemachine.cpp)
for (int i = 0; i < 8; i++)
m_snd_nl_pin[i]->write_line(BIT(~data, i));
m_sound_nl[i]->write_line(BIT(~data, i));
}
u8 gm_state::sound_r()
@ -359,17 +359,18 @@ void gm_state::gamemach(machine_config &config)
config.set_default_layout(layout_gamemach);
// sound hardware
NETLIST_SOUND(config, "snd_nl", 48000).set_source(NETLIST_NAME(gamemachine)).add_route(ALL_OUTPUTS, "mono", 1.0);
NETLIST_STREAM_OUTPUT(config, "snd_nl:cout0", 0, "SPK1.2").set_mult_offset(-10000.0 / 32768.0, 10000.0 * 3.75 / 32768.0);
config.device_remove("speaker");
NETLIST_SOUND(config, "sound_nl", 48000).set_source(NETLIST_NAME(gamemachine)).add_route(ALL_OUTPUTS, "mono", 1.0);
NETLIST_STREAM_OUTPUT(config, "sound_nl:cout0", 0, "SPK1.2").set_mult_offset(-10000.0 / 32768.0, 10000.0 * 3.75 / 32768.0);
NETLIST_LOGIC_INPUT(config, "snd_nl:p08", "P08.IN", 0);
NETLIST_LOGIC_INPUT(config, "snd_nl:p09", "P09.IN", 0);
NETLIST_LOGIC_INPUT(config, "snd_nl:p10", "P10.IN", 0);
NETLIST_LOGIC_INPUT(config, "snd_nl:p11", "P11.IN", 0);
NETLIST_LOGIC_INPUT(config, "snd_nl:p12", "P12.IN", 0);
NETLIST_LOGIC_INPUT(config, "snd_nl:p13", "P13.IN", 0);
NETLIST_LOGIC_INPUT(config, "snd_nl:p14", "P14.IN", 0);
NETLIST_LOGIC_INPUT(config, "snd_nl:p15", "P15.IN", 0);
NETLIST_LOGIC_INPUT(config, "sound_nl:p08", "P08.IN", 0);
NETLIST_LOGIC_INPUT(config, "sound_nl:p09", "P09.IN", 0);
NETLIST_LOGIC_INPUT(config, "sound_nl:p10", "P10.IN", 0);
NETLIST_LOGIC_INPUT(config, "sound_nl:p11", "P11.IN", 0);
NETLIST_LOGIC_INPUT(config, "sound_nl:p12", "P12.IN", 0);
NETLIST_LOGIC_INPUT(config, "sound_nl:p13", "P13.IN", 0);
NETLIST_LOGIC_INPUT(config, "sound_nl:p14", "P14.IN", 0);
NETLIST_LOGIC_INPUT(config, "sound_nl:p15", "P15.IN", 0);
}