summaryrefslogblamecommitdiffstatshomepage
path: root/src/mame/audio/segausb.h
blob: e1e4a5817826cb214d158ff1425f2b286ab25815 (plain) (tree)































































                                                                                                                                           
                                                                                                                                                              






























































































































                                                                                                                                               
// 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 <typename T> 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<read_stream_view> const &inputs, std::vector<write_stream_view> &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<u8> m_program_ram;          // pointer to program RAM
	required_shared_ptr<u8> 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<i8035_device> m_ourcpu;
	required_device<cpu_device> m_maincpu;

private:
#if (ENABLE_SEGAUSB_NETLIST)
	// PIT devices
	required_device_array<pit8253_device, 3> m_pit;

	// channel 0
	required_device_array<netlist_mame_analog_input_device, 3> m_nl_dac0;
	required_device<netlist_mame_logic_input_device> m_nl_sel0;
	required_device_array<netlist_mame_logic_input_device, 3> m_nl_pit0_out;

	// channel 1
	required_device_array<netlist_mame_analog_input_device, 3> m_nl_dac1;
	required_device<netlist_mame_logic_input_device> m_nl_sel1;
	required_device_array<netlist_mame_logic_input_device, 3> m_nl_pit1_out;

	// channel 2
	required_device_array<netlist_mame_analog_input_device, 3> m_nl_dac2;
	required_device<netlist_mame_logic_input_device> m_nl_sel2;
	required_device_array<netlist_mame_logic_input_device, 3> 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 <typename T> 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