// license:BSD-3-Clause // copyright-holders:Aaron Giles /************************************************************************* Sega g80 common sound hardware *************************************************************************/ #ifndef MAME_AUDIO_SEGAUSB_H #define MAME_AUDIO_SEGAUSB_H #pragma once #define ENABLE_SEGAUSB_NETLIST (0) #include "cpu/mcs48/mcs48.h" #include "machine/netlist.h" #include "machine/timer.h" #include "netlist/nl_setup.h" #include "nl_segausb.h" #if (ENABLE_SEGAUSB_NETLIST) #include "machine/pit8253.h" #endif class usb_sound_device : public device_t, public device_mixer_interface { public: template usb_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, T &&maincpu_tag) : usb_sound_device(mconfig, tag, owner, clock) { m_maincpu.set_tag(maincpu_tag); } usb_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); uint8_t status_r(); void data_w(uint8_t data); uint8_t ram_r(offs_t offset); void ram_w(offs_t offset, uint8_t data); uint8_t workram_r(offs_t offset); void workram_w(offs_t offset, uint8_t data); TIMER_DEVICE_CALLBACK_MEMBER( increment_t1_clock_timer_cb ); void usb_map(address_map &map); void usb_map_rom(address_map &map); void usb_portmap(address_map &map); #if (ENABLE_SEGAUSB_NETLIST) TIMER_DEVICE_CALLBACK_MEMBER( gos_timer ); #endif protected: usb_sound_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); // device-level overrides virtual void device_add_mconfig(machine_config &config) override; virtual void device_start() override; virtual void device_reset() override; #if (!ENABLE_SEGAUSB_NETLIST) // sound stream update overrides virtual void sound_stream_update(sound_stream &stream, std::vector const &inputs, std::vector &outputs) override; #endif private: // internal state u8 m_in_latch; // input latch u8 m_out_latch; // output latch u8 m_last_p2_value; // current P2 output value optional_shared_ptr m_program_ram; // pointer to program RAM required_shared_ptr m_work_ram; // pointer to work RAM u8 m_work_ram_bank; // currently selected work RAM bank u8 m_t1_clock; // T1 clock value u8 m_t1_clock_mask; // T1 clock mask (configured via jumpers) protected: // devices required_device m_ourcpu; required_device m_maincpu; private: #if (ENABLE_SEGAUSB_NETLIST) // PIT devices required_device_array m_pit; // channel 0 required_device_array m_nl_dac0; required_device m_nl_sel0; required_device_array m_nl_pit0_out; // channel 1 required_device_array m_nl_dac1; required_device m_nl_sel1; required_device_array m_nl_pit1_out; // channel 2 required_device_array m_nl_dac2; required_device m_nl_sel2; required_device_array m_nl_pit2_out; u8 m_gos_clock; // state of the GOD clock #else struct g80_filter_state { g80_filter_state() { } void configure(double r, double c); double step_rc(double input) { return capval += (input - capval) * exponent; } double step_cr(double input) { double const result = input - capval; capval += result * exponent; return result; } double capval = 0.0; // current capacitor value double exponent = 0.0; // constant exponent }; struct timer8253 { struct channel { channel() { } void clock(); u8 holding = 0; // holding until counts written? u8 latchmode = 0; // latching mode u8 latchtoggle = 0; // latching state u8 clockmode = 0; // clocking mode u8 bcdmode = 0; // BCD mode? u8 output = 0; // current output value u8 lastgate = 0; // previous gate value u8 gate = 0; // current gate value u16 count = 0; // initial count u16 remain = 0; // current down counter value s32 subcount = 0; // subcount (2MHz clocks per input clock) }; timer8253() : env{ 0.0, 0.0, 0.0 } { } channel chan[3]; // three channels' worth of information double env[3]; // envelope value for each channel g80_filter_state chan_filter[2]; // filter states for the first two channels g80_filter_state gate1; // first RC filter state g80_filter_state gate2; // second RC filter state u8 config = 0; // configuration for this timer }; sound_stream *m_stream; // output stream timer8253 m_timer_group[3]; // 3 groups of timers u8 m_timer_mode[3]; // mode control for each group u32 m_noise_shift; u8 m_noise_state; s32 m_noise_subcount; double m_gate_rc1_exp[2]; double m_gate_rc2_exp[2]; g80_filter_state m_final_filter; g80_filter_state m_noise_filters[5]; #endif TIMER_CALLBACK_MEMBER( delayed_usb_data_w ); void timer_w(int which, u8 offset, u8 data); void env_w(int which, u8 offset, u8 data); uint8_t p1_r(); void p1_w(uint8_t data); void p2_w(uint8_t data); DECLARE_READ_LINE_MEMBER( t1_r ); }; DECLARE_DEVICE_TYPE(SEGAUSB, usb_sound_device) class usb_rom_sound_device : public usb_sound_device { public: template usb_rom_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, T &&maincpu_tag) : usb_rom_sound_device(mconfig, tag, owner, clock) { m_maincpu.set_tag(maincpu_tag); } usb_rom_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); protected: // device-level overrides virtual void device_add_mconfig(machine_config &config) override; }; DECLARE_DEVICE_TYPE(SEGAUSBROM, usb_rom_sound_device) #endif // MAME_AUDIO_SEGAUSB_H