diff options
Diffstat (limited to 'src/mame/audio/dcs.cpp')
-rw-r--r-- | src/mame/audio/dcs.cpp | 2754 |
1 files changed, 0 insertions, 2754 deletions
diff --git a/src/mame/audio/dcs.cpp b/src/mame/audio/dcs.cpp deleted file mode 100644 index 289f334eae2..00000000000 --- a/src/mame/audio/dcs.cpp +++ /dev/null @@ -1,2754 +0,0 @@ -// license:BSD-3-Clause -// copyright-holders:Aaron Giles -/*************************************************************************** - - Midway DCS Audio Board - -**************************************************************************** - - There are several variations of this board, which was in use by - Midway and eventually Atari for almost 10 years. - - DCS ROM-based mono: - * ADSP-2105 @ 10MHz - * single channel output - * 2k external shared program/data RAM - * ROM-based, up to 8MB total - * used in: - Mortal Kombat 2 (1993) - Cruisin' USA (1994) - Revolution X (1994) - Killer Instinct (1994) - Killer Instinct 2 (1995) - Cruisin' World (1996) - Offroad Challenge (1997) - - * 8k external shared program/data RAM - * used in: - Mortal Kombat 3 (1994) - Ultimate Mortal Kombat 3 (1994) - 2 On 2 Open Ice Challenge (1995) - WWF Wrestlemania (1995) - NBA Hangtime (1996) - NBA Maximum Hangtime (1996) - Rampage World Tour (1997) - - DCS2 RAM-based stereo (Seattle): - * ADSP-2115 @ 16MHz - * dual channel output (stereo) - * SDRC ASIC for RAM/ROM access - * RAM-based, 2MB total - * used in: - War Gods (1995) - Wayne Gretzky's 3D Hockey (1996) - Mace: The Dark Age (1996) - Biofreaks (1997) - NFL Blitz (1997) - California Speed (1998) - Vapor TRX (1998) - NFL Blitz '99 (1998) - CarnEvil (1998) - Hyperdrive (1998) - NFL Blitz 2000 Gold (1999) - - DCS2 ROM-based stereo (Zeus): - * ADSP-2104 @ 16MHz - * dual channel output (stereo) - * SDRC ASIC for RAM/ROM access - * ROM-based, up to 16MB total - * used in: - Mortal Kombat 4 (1997) - Invasion (1999) - Cruisin' Exotica (1999) - The Grid (2001) - - DCS2 RAM-based stereo (Vegas): - * ADSP-2104 @ 16MHz - * dual channel output (stereo) - * SDRC ASIC for RAM/ROM access - * RAM-based, 4MB total - * used in: - Gauntlet Legends (1998) - Tenth Degree (1998) - Gauntlet Dark Legacy (1999) - War: The Final Assault (1999) - - DCS2 RAM-based stereo (DSIO): - * ADSP-2181 @ 16.667MHz - * dual channel output (stereo) - * custom ASIC for RAM/ROM access - * RAM-based, 4MB total - * used in: - Road Burners (1999) - - DCS2 RAM-based multi-channel (Denver): - * ADSP-2181 @ 16.667MHz - * 2-6 channel output - * custom ASIC for RAM/ROM access - * RAM-based, 4MB total - * used in: - San Francisco Rush: 2049 (1998) - - Unknown other DCS boards: - * NBA Jam Extreme - * NBA Showtime - * NBA Showtime / NFL Blitz 2000 Gold - * Cart Fury - -***************************************************************************** - - SDRC (Sound DRAM Control) ASIC - * Boot ROM = 32k x 8 - * Data ROM = Up to 16MB ROM (4 chip selects) - * SRAM = 32k x 24 or 8k x 24 - * common map: - PGM 0800-0fff -> RAM 4800-4fff - PGM 1000-1fff -> RAM 5000-5fff - PGM 2000-2fff -> RAM 6000-6fff - PGM 3000-3fff -> RAM 7000-7fff - * bank = 0: - DATA 0800-0fff -> RAM 0800-0fff - DATA 1000-17ff -> RAM 0000-07ff - DATA 1800-1fff -> RAM 1800-1fff - DATA 2000-27ff -> RAM 1000-17ff - DATA 2800-2fff -> RAM 2800-2fff - DATA 3000-37ff -> RAM 2000-27ff - * bank = 1: - DATA 0800-0fff -> unmapped - DATA 1000-17ff -> unmapped - DATA 1800-1fff -> RAM 3800-3fff - DATA 2000-27ff -> RAM 3000-37ff - DATA 2800-2fff -> RAM 2800-2fff - DATA 3000-37ff -> RAM 2000-27ff - - 0480 (reset = XXX0 0X00 0X00 XX00) - 15:13 = SMODE (write only) - 12 = SM_BK (SRAM bank: 0 or 1) - 11 = SM_EN (SRAM enable: 0=disabled, 1=enabled) - 9:7 = ROM_PG (ROM page select: 0-7) - 5 = ROM_MS (ROM memory select: 0=boot memory, 1=data memory) - 4 = ROM_SZ (ROM area size: 0=4k words, 1=1k words) - 1:0 = ROM_ST (ROM memory start: 0=0000, 1=3000, 2=3400, 3=none) - - 0481 (reset = 000X 00X0 0X00 XX00) - 15 = AREF_ACT (read only, 1=DRAM auto refresh in progress) - 14 = /MUTE (mute output) - 13 = /LED (LED output) - 11:10 = /RES_TFS (Reset TFS outputs: low bit = channel 1&2, high = channel 3&4) - 8 = TFS_INV (TFS output polarity: 0=same, 1=inverted) - 7 = DM_3WS (DRAM wait states: 0=2, 1=3) - 5:4 = DM_REF (DRAM refresh: 0=disabled, 1=manual, 2=auto, 3=auto 2x) - 1:0 = DM_ST (DRAM memory start: 0=none, 1=0000, 2=3000, 3=3400) - - 0482 (reset = XXX0 0000 0000 0000) - 10:0 = DM_PG[10..0] (DRAM page) - 12:0 = EPM_PG[12..0] (EPROM page [low 10 bits used for 4k pages]) - - 0483 (reset = 1010 0000 1000 0001) - 15:8 = SDRC_ID[7..0] (revision: 5A = ASIC version, A0 = FPGA version) - 7 = SEC_D7 - 6 = SEC_D[6..1] - 0 = SEC_D0 - -****************************************************************************/ - -#include "emu.h" -#include "dcs.h" -#include "speaker.h" - - -#define LOG_DCS_TRANSFERS (0) -#define LOG_DCS_IO (0) -#define LOG_BUFFER_FILLING (0) - -#define ENABLE_HLE_TRANSFERS (1) - - - -/************************************* - * - * Constants - * - *************************************/ - -#define LCTRL_OUTPUT_EMPTY 0x400 -#define LCTRL_INPUT_EMPTY 0x800 - -#define IS_OUTPUT_EMPTY() (m_latch_control & LCTRL_OUTPUT_EMPTY) -#define IS_OUTPUT_FULL() (!(m_latch_control & LCTRL_OUTPUT_EMPTY)) -#define SET_OUTPUT_EMPTY() (m_latch_control |= LCTRL_OUTPUT_EMPTY) -#define SET_OUTPUT_FULL() (m_latch_control &= ~LCTRL_OUTPUT_EMPTY) - -#define IS_INPUT_EMPTY() (m_latch_control & LCTRL_INPUT_EMPTY) -#define IS_INPUT_FULL() (!(m_latch_control & LCTRL_INPUT_EMPTY)) -#define SET_INPUT_EMPTY() (m_latch_control |= LCTRL_INPUT_EMPTY) -#define SET_INPUT_FULL() (m_latch_control &= ~LCTRL_INPUT_EMPTY) - - -/* These are some of the control registers. We don't use them all */ -enum -{ - IDMA_CONTROL_REG = 0, /* 3fe0 */ - BDMA_INT_ADDR_REG, /* 3fe1 */ - BDMA_EXT_ADDR_REG, /* 3fe2 */ - BDMA_CONTROL_REG, /* 3fe3 */ - BDMA_WORD_COUNT_REG, /* 3fe4 */ - PROG_FLAG_DATA_REG, /* 3fe5 */ - PROG_FLAG_CONTROL_REG, /* 3fe6 */ - - S1_AUTOBUF_REG = 15, /* 3fef */ - S1_RFSDIV_REG, /* 3ff0 */ - S1_SCLKDIV_REG, /* 3ff1 */ - S1_CONTROL_REG, /* 3ff2 */ - S0_AUTOBUF_REG, /* 3ff3 */ - S0_RFSDIV_REG, /* 3ff4 */ - S0_SCLKDIV_REG, /* 3ff5 */ - S0_CONTROL_REG, /* 3ff6 */ - S0_MCTXLO_REG, /* 3ff7 */ - S0_MCTXHI_REG, /* 3ff8 */ - S0_MCRXLO_REG, /* 3ff9 */ - S0_MCRXHI_REG, /* 3ffa */ - TIMER_SCALE_REG, /* 3ffb */ - TIMER_COUNT_REG, /* 3ffc */ - TIMER_PERIOD_REG, /* 3ffd */ - WAITSTATES_REG, /* 3ffe */ - SYSCONTROL_REG /* 3fff */ -}; - - -/* these macros are used to reference the SDRC ASIC */ -#define SDRC_ROM_ST ((m_sdrc.reg[0] >> 0) & 3) /* 0=0000, 1=3000, 2=3400, 3=none */ -#define SDRC_ROM_SZ ((m_sdrc.reg[0] >> 4) & 1) /* 0=4k, 1=1k */ -#define SDRC_ROM_MS ((m_sdrc.reg[0] >> 5) & 1) /* 0=/BMS, 1=/DMS */ -#define SDRC_ROM_PG ((m_sdrc.reg[0] >> 7) & 7) -#define SDRC_SM_EN ((m_sdrc.reg[0] >> 11) & 1) -#define SDRC_SM_BK ((m_sdrc.reg[0] >> 12) & 1) -#define SDRC_SMODE ((m_sdrc.reg[0] >> 13) & 7) - -#define SDRC_DM_ST ((m_sdrc.reg[1] >> 0) & 3) /* 0=none, 1=0000, 2=3000, 3=3400 */ -#define SDRC_DM_REF ((m_sdrc.reg[1] >> 4) & 3) -#define SDRC_DM_3WS ((m_sdrc.reg[1] >> 7) & 1) -#define SDRC_TFS_INV ((m_sdrc.reg[1] >> 8) & 1) -#define SDRC_RES_TFS ((m_sdrc.reg[1] >> 10) & 3) -#define SDRC_LED ((m_sdrc.reg[1] >> 13) & 1) -#define SDRC_MUTE ((m_sdrc.reg[1] >> 14) & 1) -#define SDRC_AREF_ACT ((m_sdrc.reg[1] >> 15) & 1) - -#define SDRC_DM_PG ((m_sdrc.reg[2] >> 0) & 0x7ff) -#define SDRC_EPM_PG ((m_sdrc.reg[2] >> 0) & 0x1fff) - - -/* these macros are used to reference the DSIO ASIC */ -#define DSIO_EMPTY_FIFO ((m_dsio.reg[1] >> 0) & 1) -#define DSIO_CUR_OUTPUT ((m_dsio.reg[1] >> 4) & 1) -#define DSIO_RES_TFS ((m_dsio.reg[1] >> 10) & 1) -#define DSIO_LED ((m_dsio.reg[1] >> 13) & 1) -#define DSIO_MUTE ((m_dsio.reg[1] >> 14) & 1) - -#define DSIO_DM_PG ((m_dsio.reg[2] >> 0) & 0x1fff) - -#define DSIO_BANK_END 0x3ff - -/* these macros are used to reference the DENVER ASIC */ -#define DENV_DSP_SPEED ((m_dsio.reg[1] >> 2) & 3) /* read only: 1=33.33MHz */ -#define DENV_RES_TFS ((m_dsio.reg[1] >> 10) & 1) -#define DENV_CHANNELS ((m_dsio.reg[1] >> 11) & 3) /* 0=2ch, 1=4ch, 2=6ch */ -#define DENV_LED ((m_dsio.reg[1] >> 13) & 1) -#define DENV_MUTE ((m_dsio.reg[1] >> 14) & 1) - -#define DENV_DM_PG ((m_dsio.reg[2] >> 0) & 0x1fff) - -#define DENV_NUM_BANK 0x800 - - -/************************************* - * - * Original DCS Memory Maps - * - *************************************/ - -/* DCS 2k memory map */ -void dcs_audio_device::dcs_2k_program_map(address_map &map) -{ - map(0x0000, 0x03ff).ram().share("dcsint"); - map(0x0800, 0x0fff).ram().share("dcsext"); - map(0x1000, 0x17ff).ram().share("dcsext"); - map(0x1800, 0x1fff).ram().share("dcsext"); -} - -void dcs_audio_device::dcs_2k_data_map(address_map &map) -{ - map(0x0000, 0x07ff).mirror(0x1800).rw(FUNC(dcs_audio_device::dcs_dataram_r), FUNC(dcs_audio_device::dcs_dataram_w)); - map(0x2000, 0x2fff).bankr("databank"); - map(0x3000, 0x33ff).w(FUNC(dcs_audio_device::dcs_data_bank_select_w)); - map(0x3400, 0x37ff).rw(FUNC(dcs_audio_device::input_latch_r), FUNC(dcs_audio_device::output_latch_w)); - map(0x3800, 0x39ff).ram(); - map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_device::adsp_control_r), FUNC(dcs_audio_device::adsp_control_w)); -} - - -/* DCS 2k with UART memory map */ -void dcs_audio_device::dcs_2k_uart_data_map(address_map &map) -{ - map(0x0000, 0x07ff).mirror(0x1800).rw(FUNC(dcs_audio_device::dcs_dataram_r), FUNC(dcs_audio_device::dcs_dataram_w)); - map(0x2000, 0x2fff).bankr("databank"); - map(0x3000, 0x33ff).w(FUNC(dcs_audio_device::dcs_data_bank_select_w)); - map(0x3400, 0x3402).noprw(); /* UART (ignored) */ - map(0x3403, 0x3403).rw(FUNC(dcs_audio_device::input_latch_r), FUNC(dcs_audio_device::output_latch_w)); - map(0x3404, 0x3405).noprw(); /* UART (ignored) */ - map(0x3800, 0x39ff).ram().share("iram"); - map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_device::adsp_control_r), FUNC(dcs_audio_device::adsp_control_w)); -} - - -/* DCS 8k memory map */ -void dcs_audio_device::dcs_8k_program_map(address_map &map) -{ - map(0x0000, 0x03ff).ram().share("dcsint"); - map(0x0800, 0x1fff).ram().share("dcsext"); - map(0x3000, 0x3003).rw(FUNC(dcs_audio_device::input_latch32_r), FUNC(dcs_audio_device::output_latch32_w)); // why? -} - -void dcs_audio_device::dcs_8k_data_map(address_map &map) -{ - map(0x0000, 0x07ff).ram(); - map(0x0800, 0x1fff).rw(FUNC(dcs_audio_device::dcs_dataram_r), FUNC(dcs_audio_device::dcs_dataram_w)); - map(0x2000, 0x2fff).bankr("databank"); - map(0x3000, 0x3000).w(FUNC(dcs_audio_device::dcs_data_bank_select_w)); - map(0x3400, 0x3403).rw(FUNC(dcs_audio_device::input_latch_r), FUNC(dcs_audio_device::output_latch_w)); // mk3 etc. need this - map(0x3800, 0x39ff).ram().share("iram"); - map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_device::adsp_control_r), FUNC(dcs_audio_device::adsp_control_w)); -} - -/* Williams WPC DCS/Security Pinball */ -void dcs_audio_device::dcs_wpc_program_map(address_map &map) -{ - map(0x0000, 0x03ff).ram().share("dcsint"); - map(0x1000, 0x3fff).ram().share("dcsext"); -} - -void dcs_audio_wpc_device::dcs_wpc_data_map(address_map &map) -{ - map(0x0000, 0x07ff).bankr("databank"); - map(0x1000, 0x2fff).rw(FUNC(dcs_audio_wpc_device::dcs_dataram_r), FUNC(dcs_audio_wpc_device::dcs_dataram_w)); - map(0x3000, 0x3000).w(FUNC(dcs_audio_wpc_device::dcs_data_bank_select_w)); - map(0x3100, 0x3100).w(FUNC(dcs_audio_wpc_device::dcs_data_bank_select2_w)); - map(0x3300, 0x3303).rw(FUNC(dcs_audio_wpc_device::input_latch_r), FUNC(dcs_audio_wpc_device::output_latch_w)); - map(0x3800, 0x39ff).ram().share("iram"); - map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_wpc_device::adsp_control_r), FUNC(dcs_audio_wpc_device::adsp_control_w)); -} - -/************************************* - * - * DCS2 Memory Maps - * - *************************************/ - -void dcs_audio_device::dcs2_2115_program_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0000, 0x03ff).ram().share("dcsint"); -} - -void dcs_audio_device::dcs2_2104_program_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0000, 0x01ff).ram().share("dcsint"); -} - - -void dcs_audio_device::dcs2_2115_data_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0400, 0x0400).rw(FUNC(dcs_audio_device::input_latch_r), FUNC(dcs_audio_device::input_latch_ack_w)); - map(0x0401, 0x0401).w(FUNC(dcs_audio_device::output_latch_w)); - map(0x0402, 0x0402).rw(FUNC(dcs_audio_device::output_control_r), FUNC(dcs_audio_device::output_control_w)); - map(0x0403, 0x0403).r(FUNC(dcs_audio_device::latch_status_r)); - map(0x0404, 0x0407).r(FUNC(dcs_audio_device::fifo_input_r)); - map(0x0480, 0x0483).rw(FUNC(dcs_audio_device::sdrc_r), FUNC(dcs_audio_device::sdrc_w)); - map(0x3800, 0x39ff).ram().share("iram"); - map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_device::adsp_control_r), FUNC(dcs_audio_device::adsp_control_w)); -} - -void dcs_audio_device::dcs2_2104_data_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0400, 0x0400).rw(FUNC(dcs_audio_device::input_latch_r), FUNC(dcs_audio_device::input_latch_ack_w)); - map(0x0401, 0x0401).w(FUNC(dcs_audio_device::output_latch_w)); - map(0x0402, 0x0402).rw(FUNC(dcs_audio_device::output_control_r), FUNC(dcs_audio_device::output_control_w)); - map(0x0403, 0x0403).r(FUNC(dcs_audio_device::latch_status_r)); - map(0x0404, 0x0407).r(FUNC(dcs_audio_device::fifo_input_r)); - map(0x0480, 0x0483).rw(FUNC(dcs_audio_device::sdrc_r), FUNC(dcs_audio_device::sdrc_w)); - map(0x3800, 0x39ff).ram().share("iram"); - map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_device::adsp_control_r), FUNC(dcs_audio_device::adsp_control_w)); -} - - - -/************************************* - * - * DSIO Memory Maps - * - *************************************/ - -void dcs_audio_device::dsio_program_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0000, 0x3fff).ram().share("dcsint"); -} - - -void dcs_audio_device::dsio_data_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0000, 0x1fff).m("data_map_bank", FUNC(address_map_bank_device::amap16)); - map(0x2000, 0x3fdf).ram().share("dcsint_data"); - map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_device::adsp_control_r), FUNC(dcs_audio_device::adsp_control_w)); -} - -void dcs_audio_device::dsio_rambank_map(address_map &map) -{ - map(0x0000, 0x1fff).ram(); - map(0x2000, 0x3fff).bankrw("databank"); -} - -void dcs_audio_device::dsio_io_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0400, 0x0400).rw(FUNC(dcs_audio_device::input_latch_r), FUNC(dcs_audio_device::input_latch_ack_w)); - map(0x0401, 0x0401).w(FUNC(dcs_audio_device::output_latch_w)); - map(0x0402, 0x0402).rw(FUNC(dcs_audio_device::output_control_r), FUNC(dcs_audio_device::output_control_w)); - map(0x0403, 0x0403).r(FUNC(dcs_audio_device::latch_status_r)); - map(0x0404, 0x0407).r(FUNC(dcs_audio_device::fifo_input_r)); - map(0x0480, 0x0483).rw(FUNC(dcs_audio_device::dsio_r), FUNC(dcs_audio_device::dsio_w)); -} - - - -/************************************* - * - * Denver Memory Maps - * - *************************************/ - -void dcs_audio_device::denver_program_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0000, 0x3fff).ram().share("dcsint"); -} - - -void dcs_audio_device::denver_data_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0000, 0x1fff).m("data_map_bank", FUNC(address_map_bank_device::amap16)); - map(0x2000, 0x3fdf).ram().share("dcsint_data"); - map(0x3fe0, 0x3fff).rw(FUNC(dcs_audio_device::adsp_control_r), FUNC(dcs_audio_device::adsp_control_w)); -} - -void dcs_audio_device::denver_rambank_map(address_map &map) -{ - map(0x0000, 0x3fff).ram(); - map(0x4000, 0x7fff).bankrw("databank"); -} - - -void dcs_audio_device::denver_io_map(address_map &map) -{ - map.unmap_value_high(); - map(0x0400, 0x0400).rw(FUNC(dcs_audio_device::input_latch_r), FUNC(dcs_audio_device::input_latch_ack_w)); - map(0x0401, 0x0401).w(FUNC(dcs_audio_device::output_latch_w)); - map(0x0402, 0x0402).rw(FUNC(dcs_audio_device::output_control_r), FUNC(dcs_audio_device::output_control_w)); - map(0x0403, 0x0403).r(FUNC(dcs_audio_device::latch_status_r)); - map(0x0404, 0x0407).r(FUNC(dcs_audio_device::fifo_input_r)); - map(0x0480, 0x0483).rw(FUNC(dcs_audio_device::denver_r), FUNC(dcs_audio_device::denver_w)); -} - - -/************************************* - * - * ADSP booting - * - *************************************/ - -void dcs_audio_device::dcs_boot() -{ - switch (m_rev) - { - /* rev 1/1.5: use the last set data bank to boot from */ - case REV_DCS1: - case REV_DCS1P5: - { - /* determine the base */ - // max_banks = m_bootrom_words / 0x1000; - uint16_t* base = m_bootrom + ((m_sounddata_bank * 0x1000) % m_bootrom_words); - - /* convert from 16-bit data to 8-bit data and boot */ - uint8_t buffer[0x1000]; - for (int i = 0; i < 0x1000; i++) - { - buffer[i] = base[i]; - } - assert(m_internal_program_ram != nullptr); - m_cpu->load_boot_data(buffer, m_internal_program_ram); - break; - } - - /* rev 2: use the ROM page in the SDRC to boot from */ - case REV_DCS2: - { - /* determine the base */ - uint16_t* base; - if (m_bootrom == m_sounddata) - { - /* EPROM case: page is selected from the page register */ - base = m_bootrom + ((SDRC_EPM_PG * 0x1000) % m_bootrom_words); - } - else - { - /* DRAM case: page is selected from the ROM page register */ - base = m_bootrom + ((SDRC_ROM_PG * 0x1000) % m_bootrom_words); - } - - /* convert from 16-bit data to 8-bit data and boot */ - uint8_t buffer[0x1000]; - for (int i = 0; i < 0x1000; i++) - { - buffer[i] = base[i]; - } - assert(m_internal_program_ram != nullptr); - m_cpu->load_boot_data(buffer, m_internal_program_ram); - break; - } - - /* rev 3/4: HALT the ADSP-2181 until program is downloaded via IDMA */ - case REV_DSIO: - case REV_DENV: - m_cpu->set_input_line(INPUT_LINE_HALT, ASSERT_LINE); - m_dsio.start_on_next_write = 0; - break; - } -} - - - -/************************************* - * - * System reset - * - *************************************/ - -TIMER_CALLBACK_MEMBER( dcs_audio_device::dcs_reset ) -{ - if (LOG_DCS_IO) - logerror("dcs_reset\n"); - - /* reset the memory banking */ - switch (m_rev) - { - /* rev 1/1.5: just reset the bank to 0 */ - case REV_DCS1: - case REV_DCS1P5: - m_sounddata_bank = 0; - m_data_bank->set_entry(0); - break; - - /* rev 2: reset the SDRC ASIC */ - case REV_DCS2: - sdrc_reset(); - break; - - /* rev 3: reset the DSIO ASIC */ - case REV_DSIO: - dsio_reset(); - break; - - /* rev 4: reset the Denver ASIC */ - case REV_DENV: - denver_reset(); - break; - } - /* initialize our state structure and install the transmit callback */ - m_size = 0; - m_incs = 0; - m_ireg = 0; - - /* initialize the ADSP control regs */ - memset(m_control_regs, 0, sizeof(m_control_regs)); - /* clear all interrupts */ - m_cpu->set_input_line(ADSP2105_IRQ0, CLEAR_LINE); - m_cpu->set_input_line(ADSP2105_IRQ1, CLEAR_LINE); - m_cpu->set_input_line(ADSP2105_IRQ2, CLEAR_LINE); - - /* initialize the comm bits */ - SET_INPUT_EMPTY(); - SET_OUTPUT_EMPTY(); - if (!m_last_input_empty && !m_input_empty_cb.isnull()) - m_input_empty_cb(m_last_input_empty = 1); - if (m_last_output_full && !m_output_full_cb.isnull()) - m_output_full_cb(m_last_output_full = 0); - - /* boot */ - dcs_boot(); - - /* reset timers */ - m_timer_ignore = false; - m_timer_enable = 0; - m_timer_scale = 1; - m_internal_timer->reset(); - - /* reset the HLE transfer states */ - m_transfer.dcs_state = m_transfer.state = 0; - -} - - - -/************************************* - * - * System setup - * - *************************************/ - -void dcs_audio_device::dcs_register_state() -{ - save_item(NAME(m_sdrc.reg)); - save_item(NAME(m_sdrc.seed)); - - save_item(NAME(m_dsio.reg)); - save_item(NAME(m_dsio.start_on_next_write)); - save_item(NAME(m_dsio.channelbits)); - - save_item(NAME(m_channels)); - save_item(NAME(m_size)); - save_item(NAME(m_incs)); - save_item(NAME(m_ireg)); - save_item(NAME(m_ireg_base)); - save_item(NAME(m_control_regs)); - - save_item(NAME(m_sounddata_bank)); - save_item(NAME(m_dmovlay_val)); - - save_item(NAME(m_auto_ack)); - save_item(NAME(m_latch_control)); - save_item(NAME(m_input_data)); - save_item(NAME(m_output_data)); - save_item(NAME(m_output_control)); - save_item(NAME(m_output_control_cycles)); - save_item(NAME(m_last_output_full)); - save_item(NAME(m_last_input_empty)); - save_item(NAME(m_progflags)); - - save_item(NAME(m_timer_enable)); - save_item(NAME(m_timer_ignore)); - save_item(NAME(m_timer_start_cycles)); - save_item(NAME(m_timer_start_count)); - save_item(NAME(m_timer_scale)); - save_item(NAME(m_timer_period)); - save_item(NAME(m_timers_fired)); - - save_item(NAME(m_transfer.dcs_state)); - save_item(NAME(m_transfer.state)); - save_item(NAME(m_transfer.start)); - save_item(NAME(m_transfer.stop)); - save_item(NAME(m_transfer.type)); - save_item(NAME(m_transfer.temp)); - save_item(NAME(m_transfer.writes_left)); - save_item(NAME(m_transfer.sum)); - save_item(NAME(m_transfer.fifo_entries)); - - save_item(NAME(m_polling_value)); - save_item(NAME(m_polling32_value)); - - if (m_sram != nullptr) - save_pointer(NAME(m_sram), 0x8000*4 / sizeof(m_sram[0])); - - if (m_rev == REV_DCS2) - machine().save().register_postload(save_prepost_delegate(FUNC(dcs_audio_device::sdrc_remap_memory), this)); - - if (m_rev == REV_DENV) - machine().save().register_postload(save_prepost_delegate(FUNC(dcs_audio_device::denver_postload), this)); -} - -void dcs_audio_device::denver_postload() -{ - m_data_bank->set_entry(DENV_DM_PG % m_sounddata_banks); - dmovlay_remap_memory(); - denver_alloc_dmadac(); - install_speedup(); -} - -//------------------------------------------------- -// dcs_audio_device - constructor -//------------------------------------------------- - -dcs_audio_device::dcs_audio_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int rev) : - device_t(mconfig, type, tag, owner, clock), - m_cpu(nullptr), - m_program(nullptr), - m_data(nullptr), - m_rev(rev), - m_polling_offset(0), - m_polling_count(0), - m_channels(0), - m_size(0), - m_incs(0), - m_reg_timer(nullptr), - m_sport0_timer(nullptr), - m_internal_timer(nullptr), - m_ireg(0), - m_ireg_base(0), - m_bootrom(nullptr), - m_bootrom_words(0), - m_sounddata(nullptr), - m_sounddata_words(0), - m_sounddata_banks(0), - m_sounddata_bank(0), - m_ram_map(*this, "data_map_bank"), - m_data_bank(*this, "databank"), - m_rom_page(nullptr), - m_dram_page(nullptr), - m_auto_ack(0), - m_latch_control(0), - m_input_data(0), - m_output_data(0), - m_output_control(0), - m_output_control_cycles(0), - m_last_output_full(0), - m_last_input_empty(0), - m_progflags(0), - m_timer_enable(0), - m_timer_ignore(false), - m_timer_start_cycles(0), - m_timer_start_count(0), - m_timer_scale(0), - m_timer_period(0), - m_timers_fired(0), - m_sram(nullptr), - m_internal_program_ram(nullptr), - m_external_program_ram(nullptr), - m_internal_data_ram(nullptr), - m_dram_in_mb(0), - m_iram(*this, "iram"), - m_maincpu(*this, ":maincpu") -{ - m_dmadac[0] = m_dmadac[1] = m_dmadac[2] = m_dmadac[3] = m_dmadac[4] = m_dmadac[5] = nullptr; - memset(m_control_regs, 0, sizeof(m_control_regs)); - memset(&m_sdrc, 0, sizeof(m_sdrc)); - memset(&m_dsio, 0, sizeof(m_dsio)); - memset(&m_transfer, 0, sizeof(m_transfer)); -} - -void dcs_audio_device::device_reset() -{ - dcs_reset(nullptr, 0); -} - -void dcs_audio_device::device_start() -{ - m_sram = nullptr; - - memory_share *internal_ram = memshare("dcsint"); - if (internal_ram != nullptr) - { - m_internal_program_ram = (uint32_t *)internal_ram->ptr(); - } - memory_share *external_ram = memshare("dcsext"); - if (external_ram != nullptr) - { - m_external_program_ram = (uint32_t *)external_ram->ptr(); - } - - /* find the DCS CPU and the sound ROMs */ - m_cpu = subdevice<adsp21xx_device>("dcs"); - if (m_cpu != nullptr && !m_cpu->started()) - throw device_missing_dependencies(); - - m_program = &m_cpu->space(AS_PROGRAM); - m_data = &m_cpu->space(AS_DATA); - m_channels = 1; - m_dmadac[0] = subdevice<dmadac_sound_device>("dac"); - - /* configure boot and sound ROMs */ - m_bootrom = (uint16_t *)machine().root_device().memregion("dcs")->base(); - m_bootrom_words = machine().root_device().memregion("dcs")->bytes() / 2; - m_sounddata = m_bootrom; - m_sounddata_words = m_bootrom_words; - if (m_rev == REV_DCS1) - { - m_sounddata_banks = m_sounddata_words / 0x1000; - m_data_bank->configure_entries(0, m_sounddata_banks, m_sounddata, 0x1000*2); - } - else - { - m_sounddata_banks = m_sounddata_words / 0x800; - m_data_bank->configure_entries(0, m_sounddata_banks, m_sounddata, 0x800*2); - } - - /* create the timers */ - m_internal_timer = subdevice<timer_device>("dcs_int_timer"); - m_reg_timer = subdevice<timer_device>("dcs_reg_timer"); - - /* non-RAM based automatically acks */ - m_auto_ack = true; - /* register for save states */ - dcs_register_state(); - /* reset the system */ - dcs_reset(nullptr, 0); -} - - -void dcs2_audio_device::device_start() -{ - int soundbank_words; - - memory_share *internal_ram = memshare("dcsint"); - if (internal_ram != nullptr) - { - m_internal_program_ram = (uint32_t *)internal_ram->ptr(); - } - memory_share *external_ram = memshare("dcsext"); - if (external_ram != nullptr) - { - m_external_program_ram = (uint32_t *)external_ram->ptr(); - } - memory_share *internal_data_ram = memshare("dcsint_data"); - if (internal_data_ram != nullptr) - { - m_internal_data_ram = (uint32_t *)internal_ram->ptr(); - } - - /* find the DCS CPU and the sound ROMs */ - m_cpu = subdevice<adsp21xx_device>("dcs2"); - m_rev = REV_DCS2; - soundbank_words = 0x1000; - if (m_cpu == nullptr) - { - m_cpu = subdevice<adsp21xx_device>("dsio"); - m_rev = REV_DSIO; - soundbank_words = DSIO_BANK_END + 1; - } - if (m_cpu == nullptr) - { - m_cpu = subdevice<adsp21xx_device>("denver"); - m_rev = REV_DENV; - soundbank_words = ((m_dram_in_mb << 20) / 2) / DENV_NUM_BANK; - } - if (m_cpu != nullptr && !m_cpu->started()) - throw device_missing_dependencies(); - - m_program = &m_cpu->space(AS_PROGRAM); - m_data = &m_cpu->space(AS_DATA); - m_channels = 2; - m_dmadac[0] = subdevice<dmadac_sound_device>("dac1"); - m_dmadac[1] = subdevice<dmadac_sound_device>("dac2"); - - /* always boot from the base of "dcs" */ - memory_region *bootrom_region = machine().root_device().memregion("dcs"); - if (bootrom_region != nullptr) - { - m_bootrom = (uint16_t *)bootrom_region->base(); - m_bootrom_words = bootrom_region->bytes() / 2; - } - - /* supports both RAM and ROM variants */ - if (m_dram_in_mb != 0) - { - m_sounddata_words = (m_dram_in_mb << 20) / 2; - m_sounddata = auto_alloc_array(machine(), uint16_t, m_sounddata_words); - save_pointer(NAME(m_sounddata), m_sounddata_words); - } - else - { - m_sounddata = m_bootrom; - m_sounddata_words = m_bootrom_words; - } - m_sounddata_banks = m_sounddata_words / soundbank_words; - if (m_rev != REV_DCS2) - { - if (m_ram_map) - m_ram_map->set_bank(0); - m_data_bank->configure_entries(0, m_sounddata_banks, m_sounddata, soundbank_words * 2); - logerror("device_start: audio ram banks: %x size: %x\n", m_sounddata_banks, soundbank_words); - } - - - /* allocate memory for the SRAM */ - m_sram = auto_alloc_array(machine(), uint16_t, 0x8000*4/2); - - /* create the timers */ - m_internal_timer = subdevice<timer_device>("dcs_int_timer"); - m_reg_timer = subdevice<timer_device>("dcs_reg_timer"); - m_sport0_timer = subdevice<timer_device>("dcs_sport0_timer"); - - /* we don't do auto-ack by default */ - m_auto_ack = false; - - /* install the speedup handler */ - install_speedup(); - - /* allocate a watchdog timer for HLE transfers */ - m_transfer.hle_enabled = (ENABLE_HLE_TRANSFERS && m_dram_in_mb != 0 && m_rev < REV_DSIO); - if (m_transfer.hle_enabled) - m_transfer.watchdog = subdevice<timer_device>("dcs_hle_timer"); - - /* register for save states */ - dcs_register_state(); - - /* reset the system */ - dcs_reset(nullptr, 0); -} - - -void dcs_audio_device::install_speedup(void) -{ - if (m_polling_offset) { - if (m_rev < REV_DSIO) { - m_cpu->space(AS_DATA).install_readwrite_handler(m_polling_offset, m_polling_offset, read16_delegate(FUNC(dcs_audio_device::dcs_polling_r), this), write16_delegate(FUNC(dcs_audio_device::dcs_polling_w), this)); - } - else { - // ADSP 2181 (DSIO and DENVER) use program memory - m_cpu->space(AS_PROGRAM).install_readwrite_handler(m_polling_offset, m_polling_offset, read32_delegate(FUNC(dcs_audio_device::dcs_polling32_r), this), write32_delegate(FUNC(dcs_audio_device::dcs_polling32_w), this)); - // DSIO and DENVER poll in two spots. This offset covers all three machines (mwskins, sf2049, roadburn). - m_cpu->space(AS_PROGRAM).install_readwrite_handler(m_polling_offset + 9, m_polling_offset + 9, read32_delegate(FUNC(dcs_audio_device::dcs_polling32_r), this), write32_delegate(FUNC(dcs_audio_device::dcs_polling32_w), this)); - } - } -} - -void dcs_audio_device::set_auto_ack(int state) -{ - m_auto_ack = state; -} - - - -/************************************* - * - * Original DCS read/write handlers - * - *************************************/ - -READ16_MEMBER( dcs_audio_device::dcs_dataram_r ) -{ - assert(m_external_program_ram != nullptr); - return m_external_program_ram[offset] >> 8; -} - - -WRITE16_MEMBER( dcs_audio_device::dcs_dataram_w ) -{ - assert(m_external_program_ram != nullptr); - uint16_t val = m_external_program_ram[offset] >> 8; - COMBINE_DATA(&val); - m_external_program_ram[offset] = (val << 8) | (m_external_program_ram[offset] & 0x0000ff); -} - - -WRITE16_MEMBER( dcs_audio_device::dcs_data_bank_select_w ) -{ - if (m_rev != REV_DCS1P5) - m_sounddata_bank = data & 0x7ff; - else - m_sounddata_bank = (m_sounddata_bank & 0xff00) | (data & 0xff); - - m_data_bank->set_entry(m_sounddata_bank % m_sounddata_banks); - - /* bit 11 = sound board led */ -#if 0 - if (m_rev != REV_DCS1P5) - output().set_led_value(2, data & 0x800); -#endif -} - -WRITE16_MEMBER( dcs_audio_device::dcs_data_bank_select2_w ) -{ - m_sounddata_bank = (m_sounddata_bank & 0x00ff) | ((data & 0x01) << 8) | ((data & 0xfc) << 7); - - m_data_bank->set_entry(m_sounddata_bank % m_sounddata_banks); -} - -/************************************* - * - * SDRC ASIC Memory handling - * - *************************************/ - -void dcs_audio_device::sdrc_update_bank_pointers() -{ - if (SDRC_SM_EN != 0) - { - int pagesize = (SDRC_ROM_SZ == 0 && SDRC_ROM_ST != 0) ? 4096 : 1024; - - /* update the bank pointer based on whether we are ROM-based or RAM-based */ - if (m_bootrom == m_sounddata) - { - /* ROM-based; use the memory page to select from ROM */ - if (SDRC_ROM_MS == 1 && SDRC_ROM_ST != 3) - { - m_rom_page->set_base(&m_sounddata[(SDRC_EPM_PG * pagesize) % m_sounddata_words]); - } - } - else - { - /* RAM-based; use the ROM page to select from ROM, and the memory page to select from RAM */ - if (SDRC_ROM_MS == 1 && SDRC_ROM_ST != 3) - { - m_rom_page->set_base(&m_bootrom[(SDRC_ROM_PG * 4096 /*pagesize*/) % m_bootrom_words]); - } - if (SDRC_DM_ST != 0) - { - m_dram_page->set_base(&m_sounddata[(SDRC_DM_PG * 1024) % m_sounddata_words]); - } - } - } -} - - -void dcs_audio_device::sdrc_remap_memory() -{ - /* if SRAM disabled, clean it out */ - if (SDRC_SM_EN == 0) - { - m_program->unmap_readwrite(0x0800, 0x3fff); - m_data->unmap_readwrite(0x0800, 0x37ff); - } - - /* otherwise, map the SRAM */ - else - { - /* first start with a clean program map */ - m_program->install_ram(0x0800, 0x3fff, m_sram + 0x4800); - - /* set up the data map based on the SRAM banking */ - /* map 0: ram from 0800-37ff */ - if (SDRC_SM_BK == 0) - { - m_data->install_ram(0x0800, 0x17ff, m_sram + 0x0000); - m_data->install_ram(0x1800, 0x27ff, m_sram + 0x1000); - m_data->install_ram(0x2800, 0x37ff, m_sram + 0x2000); - } - - /* map 1: nothing from 0800-17ff, alternate RAM at 1800-27ff, same RAM at 2800-37ff */ - else - { - m_data->unmap_readwrite(0x0800, 0x17ff); - m_data->install_ram(0x1800, 0x27ff, m_sram + 0x3000); - m_data->install_ram(0x2800, 0x37ff, m_sram + 0x2000); - } - } - - /* map the ROM page as bank 25 */ - if (SDRC_ROM_MS == 1 && SDRC_ROM_ST != 3) - { - int baseaddr = (SDRC_ROM_ST == 0) ? 0x0000 : (SDRC_ROM_ST == 1) ? 0x3000 : 0x3400; - int pagesize = (SDRC_ROM_SZ == 0 && SDRC_ROM_ST != 0) ? 4096 : 1024; - m_data->install_read_bank(baseaddr, baseaddr + pagesize - 1, "rompage"); - m_rom_page = membank("rompage"); - } - - /* map the DRAM page as bank 26 */ - if (SDRC_DM_ST != 0) - { - int baseaddr = (SDRC_DM_ST == 1) ? 0x0000 : (SDRC_DM_ST == 2) ? 0x3000 : 0x3400; - m_data->install_readwrite_bank(baseaddr, baseaddr + 0x3ff, "drampage"); - m_dram_page = membank("drampage"); - } - - /* update the bank pointers */ - sdrc_update_bank_pointers(); - - /* reinstall the polling hotspot */ - install_speedup(); -} - - -void dcs_audio_device::sdrc_reset() -{ - memset(m_sdrc.reg, 0, sizeof(m_sdrc.reg)); - sdrc_remap_memory(); -} - - - -/************************************* - * - * SDRC ASIC read/write - * - *************************************/ - -READ16_MEMBER( dcs_audio_device::sdrc_r ) -{ - sdrc_state &sdrc = m_sdrc; - uint16_t result = sdrc.reg[offset]; - - /* offset 3 is for security */ - if (offset == 3) - { - switch (SDRC_SMODE) - { - default: - case 0: /* no-op */ - result = 0x5a81; - break; - - case 1: /* write seed */ - result = 0x5aa4; - break; - - case 2: /* read data */ - result = 0x5a00 | ((sdrc.seed & 0x3f) << 1); - break; - - case 3: /* shift left */ - result = 0x5ab9; - break; - - case 4: /* add */ - result = 0x5a03; - break; - - case 5: /* xor */ - result = 0x5a69; - break; - - case 6: /* prg */ - result = 0x5a20; - break; - - case 7: /* invert */ - result = 0x5aff; - break; - } - } - - return result; -} - - -WRITE16_MEMBER( dcs_audio_device::sdrc_w ) -{ - sdrc_state &sdrc = m_sdrc; - uint16_t diff = sdrc.reg[offset] ^ data; - - switch (offset) - { - /* offset 0 controls ROM mapping */ - case 0: - sdrc.reg[0] = data; - if (diff & 0x1833) - sdrc_remap_memory(); - if (diff & 0x0380) - sdrc_update_bank_pointers(); - break; - - /* offset 1 controls RAM mapping */ - case 1: - sdrc.reg[1] = data; - //dmadac_enable(&m_dmadac[0], m_channels, SDRC_MUTE); - if (diff & 0x0003) - sdrc_remap_memory(); - break; - - /* offset 2 controls paging */ - case 2: - sdrc.reg[2] = data; - if (diff & 0x1fff) - sdrc_update_bank_pointers(); - break; - - /* offset 3 controls security */ - case 3: - switch (SDRC_SMODE) - { - case 0: /* no-op */ - case 2: /* read data */ - break; - - case 1: /* write seed */ - sdrc.seed = data & 0xff; - break; - - case 3: /* shift left */ - sdrc.seed = (sdrc.seed << 1) | 1; - break; - - case 4: /* add */ - sdrc.seed += sdrc.seed >> 1; - break; - - case 5: /* xor */ - sdrc.seed ^= (sdrc.seed << 1) | 1; - break; - - case 6: /* prg */ - sdrc.seed = (((sdrc.seed << 7) ^ (sdrc.seed << 5) ^ (sdrc.seed << 4) ^ (sdrc.seed << 3)) & 0x80) | (sdrc.seed >> 1); - break; - - case 7: /* invert */ - sdrc.seed = ~sdrc.seed; - break; - } - break; - } -} - - - -/************************************* - * - * DSIO ASIC read/write - * - *************************************/ - -void dcs_audio_device::dsio_reset() -{ - memset(&m_dsio, 0, sizeof(m_dsio)); - m_dmovlay_val = 0; - dmovlay_remap_memory(); -} - - -READ16_MEMBER( dcs_audio_device::dsio_r ) -{ - dsio_state &dsio = m_dsio; - uint16_t result = dsio.reg[offset]; - - if (offset == 1) - { - /* bit 4 specifies which channel is being output */ - dsio.channelbits ^= 0x0010; - result = (result & ~0x0010) | dsio.channelbits; - } - if (LOG_DCS_IO && offset != 2) logerror("%s dsio_r 0x%x = %04x\n", machine().describe_context(), offset, result); - return result; -} - - -WRITE16_MEMBER( dcs_audio_device::dsio_w ) -{ - dsio_state &dsio = m_dsio; - - switch (offset) - { - /* offset 1 controls I/O */ - case 1: - dsio.reg[1] = data; - - /* determine /MUTE and number of channels */ - dmadac_enable(&m_dmadac[0], m_channels, DSIO_MUTE); - - /* bit 0 resets the FIFO */ - if (!m_fifo_reset_w.isnull()) - m_fifo_reset_w(DSIO_EMPTY_FIFO ^ 1); - break; - - /* offset 2 controls RAM pages */ - case 2: - dsio.reg[2] = data; - m_data_bank->set_entry(DSIO_DM_PG % m_sounddata_banks); - break; - } - if (LOG_DCS_IO) logerror("%s dsio_w 0x%x = %04x\n", machine().describe_context(), offset, data); -} - - - -/************************************* - * - * Denver ASIC read/write - * - *************************************/ - -void dcs_audio_device::denver_reset() -{ - memset(&m_dsio, 0, sizeof(m_dsio)); - m_dmovlay_val = 0; - dmovlay_remap_memory(); - dmadac_enable(&m_dmadac[0], m_channels, 0); - m_reg_timer->reset(); - m_sport0_timer->reset(); -} - -void dcs_audio_device::denver_alloc_dmadac() -{ - int enable = DENV_MUTE; - for (int chan = 0; chan < m_channels; chan++) - { - char buffer[10]; - sprintf(buffer, "dac%d", chan + 1); - m_dmadac[chan] = subdevice<dmadac_sound_device>(buffer); - } - dmadac_enable(&m_dmadac[0], m_channels, enable); - if (m_channels < 6) - dmadac_enable(&m_dmadac[m_channels], 6 - m_channels, false); - //if (enable) - // recompute_sample_rate(); -} - -READ16_MEMBER( dcs_audio_device::denver_r ) -{ - uint16_t result = m_dsio.reg[offset]; - - if (offset == 3) - { - /* returns 1 for DRAM, 2 for EPROM-based */ - // SDRC Revision - result = 0x0003; - } - if (LOG_DCS_IO && offset != 0x2) logerror("%s denver_r %s 0x%x = %04x\n", machine().describe_context(), denver_regname[offset], offset, result); - - return result; -} - - -WRITE16_MEMBER( dcs_audio_device::denver_w ) -{ - dsio_state &dsio = m_dsio; - int channels; - - uint16_t data_change = dsio.reg[offset] ^ data; - - switch (offset) - { - /* offset 1 controls I/O */ - case 1: - dsio.reg[1] = data; - // Ignore LED - data_change &= ~(1 << 13); - /* determine /MUTE and number of channels */ - channels = 2 + 2 * DENV_CHANNELS; - - /* if the number of channels has changed adjust */ - if (channels != m_channels) - { - m_channels = channels; - denver_alloc_dmadac(); - } - // Set MUTE - if (data_change & (1 << 14)) { - dmadac_enable(&m_dmadac[0], m_channels, DENV_MUTE); - if (m_channels < 6) - dmadac_enable(&m_dmadac[m_channels], 6 - m_channels, false); - } - // Disable timer after DENV_RES_TFS - if (!m_timer_ignore && DENV_RES_TFS && DENV_MUTE) { - logerror("%s denver_w: Disabling timer\n", machine().describe_context()); - m_timer_ignore = true; - } - break; - - /* offset 2 controls RAM pages */ - case 2: - dsio.reg[2] = data; - m_data_bank->set_entry(DENV_DM_PG % m_sounddata_banks); - break; - /* offset 3 controls FIFO reset */ - case 3: - if (!m_fifo_reset_w.isnull()) - m_fifo_reset_w(1); - break; - } - if (LOG_DCS_IO && offset != 0x2) logerror("%s denver_w %s 0x%x = %04x\n", machine().describe_context(), denver_regname[offset], offset, data); -} - - - -/************************************* - * - * DSIO/Denver IDMA access - * - *************************************/ - -WRITE32_MEMBER( dcs_audio_device::dsio_idma_addr_w ) -{ - if (LOG_DCS_TRANSFERS) - logerror("%s IDMA_addr = %04X\n", machine().describe_context(), data); - downcast<adsp2181_device *>(m_cpu)->idma_addr_w(data); - if (data == 0) - m_dsio.start_on_next_write = 2; -} - - -WRITE32_MEMBER( dcs_audio_device::dsio_idma_data_w ) -{ - dsio_state &dsio = m_dsio; - // IDMA is to internal memory only - if (m_dmovlay_val) - m_ram_map->set_bank(0); - if (ACCESSING_BITS_0_15) - { - if (LOG_DCS_TRANSFERS && !(downcast<adsp2181_device *>(m_cpu)->idma_addr_r() & 0x00ff)) - logerror("%s IDMA_data_w(%04X) = %04X\n", machine().describe_context(), downcast<adsp2181_device *>(m_cpu)->idma_addr_r(), data & 0xffff); - downcast<adsp2181_device *>(m_cpu)->idma_data_w(data & 0xffff); - } - if (ACCESSING_BITS_16_31) - { - if (LOG_DCS_TRANSFERS && !(downcast<adsp2181_device *>(m_cpu)->idma_addr_r() & 0x00ff)) - logerror("%s IDMA_data_w(%04X) = %04X\n", machine().describe_context(), downcast<adsp2181_device *>(m_cpu)->idma_addr_r(), data >> 16); - downcast<adsp2181_device *>(m_cpu)->idma_data_w(data >> 16); - } - if (dsio.start_on_next_write && --dsio.start_on_next_write == 0) - { - logerror("%s: Starting DSIO CPU\n", machine().describe_context()); - m_cpu->set_input_line(INPUT_LINE_HALT, CLEAR_LINE); - } - // Restore internal/external mapping - if (m_dmovlay_val) - m_ram_map->set_bank(m_dmovlay_val); - -} - - -READ32_MEMBER( dcs_audio_device::dsio_idma_data_r ) -{ - uint32_t result; - // IDMA is to internal memory only - m_ram_map->set_bank(0); - result = downcast<adsp2181_device *>(m_cpu)->idma_data_r(); - // Restore internal/external mapping - m_ram_map->set_bank(m_dmovlay_val); - if (LOG_DCS_TRANSFERS) - logerror("%s IDMA_data_r(%04X) = %04X\n", machine().describe_context(), downcast<adsp2181_device *>(m_cpu)->idma_addr_r(), result); - return result; -} - -void dcs_audio_device::dmovlay_remap_memory() -{ - // Switch banks - // Internal ram is bank 0 - if (m_dmovlay_val == 0) { - m_ram_map->set_bank(0); - } else { - m_ram_map->set_bank(1); - } - if (LOG_DCS_IO) { - if (m_dmovlay_val==0) - logerror("%s dmovlay_remap_memory: Switching to internal data ram location dmovlay=%i\n", machine().describe_context(), m_dmovlay_val); - else - logerror("%s dmovlay_remap_memory: Switching to external data ram location dmovlay=%i\n", machine().describe_context(), m_dmovlay_val); - } -} - -WRITE32_MEMBER(dcs_audio_device::dmovlay_callback) -{ - // Do some checking first - if (data < 0 || data > 1) { - logerror("dmovlay_callback: Error! dmovlay called with value = %X\n", data); - } else { - m_dmovlay_val = data; - dmovlay_remap_memory(); - } -} - - -/*************************************************************************** - DCS COMMUNICATIONS -****************************************************************************/ - -void dcs_audio_device::set_io_callbacks(write_line_delegate output_full_cb, write_line_delegate input_empty_cb) -{ - m_input_empty_cb = input_empty_cb; - m_output_full_cb = output_full_cb; -} - - -void dcs_audio_device::set_fifo_callbacks(read16_delegate fifo_data_r, read16_delegate fifo_status_r, write_line_delegate fifo_reset_w) -{ - m_fifo_data_r = fifo_data_r; - m_fifo_status_r = fifo_status_r; - m_fifo_reset_w = fifo_reset_w; -} - - -int dcs_audio_device::control_r() -{ - /* only boost for DCS2 boards */ - if (!m_auto_ack && !m_transfer.hle_enabled) - machine().scheduler().boost_interleave(attotime::from_nsec(500), attotime::from_usec(5)); - if ( /* m_rev == REV_DSC1 || */ m_rev == REV_DCS1P5) // == 1 check breaks mk3 - return IS_OUTPUT_FULL() ? 0x80 : 0x00; - return m_latch_control; -} - - -void dcs_audio_device::reset_w(int state) -{ - /* going high halts the CPU */ - if (state) - { - // logerror("%s: DCS reset = %d\n", machine().describe_context(), state); - - /* just run through the init code again */ - machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::dcs_reset),this)); - m_cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE); - } - - /* going low resets and reactivates the CPU */ - else - m_cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE); -} - - -READ16_MEMBER( dcs_audio_device::latch_status_r ) -{ - int result = 0; - if (IS_INPUT_FULL()) - result |= 0x80; - if (IS_OUTPUT_EMPTY()) - result |= 0x40; - if (!m_fifo_status_r.isnull() && (!m_transfer.hle_enabled || m_transfer.state == 0)) - result |= m_fifo_status_r(space, 0, 0xffff) & 0x38; - if (m_transfer.hle_enabled && m_transfer.state != 0) - result |= 0x08; - return result; -} - - -READ16_MEMBER( dcs_audio_device::fifo_input_r ) -{ - if (!m_fifo_data_r.isnull()) - return m_fifo_data_r(space,0, 0xffff); - else - return 0xffff; -} - - - -/*************************************************************************** - INPUT LATCH (data from host to DCS) -****************************************************************************/ - -void dcs_audio_device::dcs_delayed_data_w(uint16_t data) -{ - if (LOG_DCS_IO) - logerror("%s:dcs_data_w(%04X)\n", machine().describe_context(), data); - - /* boost the interleave temporarily */ - machine().scheduler().boost_interleave(attotime::from_nsec(500), attotime::from_usec(5)); - - /* set the IRQ line on the ADSP */ - m_cpu->set_input_line(ADSP2105_IRQ2, ASSERT_LINE); - - /* indicate we are no longer empty */ - if (m_last_input_empty && !m_input_empty_cb.isnull()) - m_input_empty_cb(m_last_input_empty = 0); - SET_INPUT_FULL(); - - /* set the data */ - m_input_data = data; -} - - -TIMER_CALLBACK_MEMBER( dcs_audio_device::dcs_delayed_data_w_callback ) -{ - dcs_delayed_data_w(param); -} - - -void dcs_audio_device::data_w(uint16_t data) -{ - /* preprocess the write */ - // ADSP2181 variants use IDMA to transfer data - if (m_rev <= REV_DCS2 && preprocess_write(data)) - return; - - /* if we are DCS1, set a timer to latch the data */ - if (m_sport0_timer == nullptr) - machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::dcs_delayed_data_w_callback),this), data); - else - dcs_delayed_data_w(data); -} - - -WRITE16_MEMBER( dcs_audio_device::input_latch_ack_w ) -{ - if (!m_last_input_empty && !m_input_empty_cb.isnull()) - m_input_empty_cb(m_last_input_empty = 1); - SET_INPUT_EMPTY(); - m_cpu->set_input_line(ADSP2105_IRQ2, CLEAR_LINE); - - if (LOG_DCS_IO) - logerror("%s input_latch_ack_w\n", machine().describe_context()); -} - - -READ16_MEMBER( dcs_audio_device::input_latch_r ) -{ - if (m_auto_ack) - input_latch_ack_w(space,0,0,0xffff); - - if (LOG_DCS_IO) - logerror("%s input_latch_r(%04X)\n", machine().describe_context(), m_input_data); - return m_input_data; -} - -READ32_MEMBER( dcs_audio_device::input_latch32_r ) -{ - if (m_auto_ack) - input_latch_ack_w(space,0,0,0xffff); - if (LOG_DCS_IO) - logerror("%s input_latch32_r(%04X)\n", machine().describe_context(), m_input_data); - return m_input_data << 8; -} - -/*************************************************************************** - OUTPUT LATCH (data from DCS to host) -****************************************************************************/ - -TIMER_CALLBACK_MEMBER( dcs_audio_device::latch_delayed_w ) -{ - if (!m_last_output_full && !m_output_full_cb.isnull()) - m_output_full_cb(m_last_output_full = 1); - SET_OUTPUT_FULL(); - m_output_data = m_pre_output_data; -} - - -WRITE16_MEMBER( dcs_audio_device::output_latch_w ) -{ - m_pre_output_data = data; - if (LOG_DCS_IO) - logerror("%s output_latch_w(%04X) (empty=%d)\n", machine().describe_context(), data, IS_OUTPUT_EMPTY()); - - machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::latch_delayed_w),this), data>>8); -} - -WRITE32_MEMBER( dcs_audio_device::output_latch32_w ) -{ - m_pre_output_data = data >> 8; - if (LOG_DCS_IO) - logerror("%s output_latch32_w(%04X) (empty=%d)\n", machine().describe_context(), data>>8, IS_OUTPUT_EMPTY()); - - machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::latch_delayed_w),this), data>>8); -} - - -void dcs_audio_device::delayed_ack_w() -{ - SET_OUTPUT_EMPTY(); -} - - -TIMER_CALLBACK_MEMBER( dcs_audio_device::delayed_ack_w_callback ) -{ - delayed_ack_w(); -} - - -void dcs_audio_device::ack_w() -{ - if (LOG_DCS_IO) - logerror("%s:ack_w\n", machine().describe_context()); - machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::delayed_ack_w_callback),this)); -} - - -uint16_t dcs_audio_device::data_r() -{ - // If the cpu is reading empty data it is probably polling so eat some cyles - if IS_OUTPUT_EMPTY() - m_maincpu->eat_cycles(4444); - - /* data is actually only 8 bit (read from d8-d15, which is d0-d7 from the data access instructions POV) on early dcs, but goes 16 on later (seattle) */ - if (m_last_output_full && !m_output_full_cb.isnull()) - m_output_full_cb(m_last_output_full = 0); - if (m_auto_ack) - delayed_ack_w(); - - if (LOG_DCS_IO) - logerror("%s:dcs_data_r(%04X)\n", machine().describe_context(), m_output_data); - return m_output_data; -} - - - -/*************************************************************************** - OUTPUT CONTROL BITS (has 3 additional lines to the host) -****************************************************************************/ - -TIMER_CALLBACK_MEMBER( dcs_audio_device::output_control_delayed_w ) -{ - //if (LOG_DCS_IO) - // logerror("output_control = %04X\n", param); - m_output_control = param; - m_output_control_cycles = 0; -} - - -WRITE16_MEMBER( dcs_audio_device::output_control_w ) -{ - if (LOG_DCS_IO) - logerror("%s output_control_w = %04X\n", machine().describe_context(), data); - machine().scheduler().synchronize(timer_expired_delegate(FUNC(dcs_audio_device::output_control_delayed_w),this), data); -} - - -READ16_MEMBER( dcs_audio_device::output_control_r ) -{ - if (LOG_DCS_IO) - logerror("%s output_control_r = %04X\n", machine().describe_context(), m_output_control); - m_output_control_cycles = m_cpu->total_cycles(); - return m_output_control; -} - - -int dcs_audio_device::data2_r() -{ - if (LOG_DCS_IO) - logerror("%s: dcs:data2_r = %04X\n", machine().describe_context(), m_output_control); - - return m_output_control; -} - - - -/************************************* - * - * Timer management - * - *************************************/ - -void dcs_audio_device::update_timer_count() -{ - uint64_t periods_since_start; - uint64_t elapsed_cycles; - uint64_t elapsed_clocks; - - /* if not enabled, skip */ - if (!m_timer_enable) - return; - - /* count cycles */ - elapsed_cycles = m_cpu->total_cycles() - m_timer_start_cycles; - elapsed_clocks = elapsed_cycles / m_timer_scale; - - /* if we haven't counted past the initial count yet, just do that */ - if (elapsed_clocks < m_timer_start_count + 1) { - m_timer_start_count -= elapsed_clocks; - m_control_regs[TIMER_COUNT_REG] = m_timer_start_count; - - /* otherwise, count how many periods */ - } - else - { - elapsed_clocks -= m_timer_start_count + 1; - periods_since_start = elapsed_clocks / (m_timer_period + 1); - elapsed_clocks -= periods_since_start * (m_timer_period + 1); - m_timer_start_count = m_timer_period - elapsed_clocks; - m_control_regs[TIMER_COUNT_REG] = m_timer_start_count; - } -} - - -TIMER_DEVICE_CALLBACK_MEMBER( dcs_audio_device::internal_timer_callback ) -{ - int64_t target_cycles; - - /* compute the absolute cycle when the next one should fire */ - /* we do this to avoid drifting */ - m_timers_fired++; - target_cycles = m_timer_start_cycles + m_timer_scale * (m_timer_start_count + 1 + m_timers_fired * (uint64_t)(m_timer_period + 1)); - target_cycles -= m_cpu->total_cycles(); - - /* set the next timer, but only if it's for a reasonable number */ - if (!m_timer_ignore && (m_timer_period > 10 || m_timer_scale > 1)) - timer.adjust(m_cpu->cycles_to_attotime(target_cycles)); - - /* the IRQ line is edge triggered */ - m_cpu->set_input_line(ADSP2105_TIMER, ASSERT_LINE); - m_cpu->set_input_line(ADSP2105_TIMER, CLEAR_LINE); -} - - -void dcs_audio_device::reset_timer() -{ - /* if not enabled, skip */ - if (!m_timer_enable) - return; - - /* compute the time until the first firing */ - m_timer_start_cycles = m_cpu->total_cycles(); - m_timers_fired = 0; - - /* if this is the first timer, check the IRQ routine for the DRAM refresh stub */ - /* if that's all the timer does, we don't really need to fire */ - if (!m_timer_ignore) - { - // Denver variants (mwskins and sf2049) use the timer as a scaler for another count so we can't disable here - // Denver gets disabled when reset TFS in the adsp control written - // Road Burners: Code gets moved after initial diagnostic checks - /* Road Burners: @ 28: JMP $0032 18032F, same code at $32 */ - /* Road Burners: @ 28: JMP $0030 18030F, same code at $30 */ - if (m_rev < REV_DSIO && - m_program->read_dword(0x18) == 0x0c0030 && /* ENA SEC_REG */ - m_program->read_dword(0x19) == 0x804828 && /* SI = DM($0482) */ - m_program->read_dword(0x1a) == 0x904828 && /* DM($0482) = SI */ - m_program->read_dword(0x1b) == 0x0C0020 && /* DIS SEC_REG */ - m_program->read_dword(0x1c) == 0x0A001F) /* RTI */ - { - if (LOG_DCS_IO) - logerror("reset_timer: Disabled timer %llu\n", m_timer_start_cycles); - m_timer_ignore = true; - } else if (m_rev == REV_DSIO && - m_program->read_dword(0x30) == 0x0c0030 && /* ENA SEC_REG */ - m_program->read_dword(0x31) == 0x014828 && /* SI = IO($0482) */ - m_program->read_dword(0x32) == 0x01c828 && /* IO($0482) = SI */ - m_program->read_dword(0x33) == 0x0C0020 && /* DIS SEC_REG */ - m_program->read_dword(0x34) == 0x0A001F) /* RTI */ - { - if (LOG_DCS_IO) - logerror("reset_timer: Disabled timer %llu\n", m_timer_start_cycles); - m_timer_ignore = true; - } - } - - /* adjust the timer if not optimized */ - if (!m_timer_ignore) - m_internal_timer->adjust(m_cpu->cycles_to_attotime(m_timer_scale * (m_timer_start_count + 1))); -} - - -WRITE_LINE_MEMBER(dcs_audio_device::timer_enable_callback) -{ - if (state) - { - //logerror("Timer enabled @ %d cycles/int, or %f Hz\n", m_timer_scale * (m_timer_period + 1), 1.0 / m_cpu->cycles_to_attotime(m_timer_scale * (m_timer_period + 1)).as_double()); - m_timer_enable = state; - reset_timer(); - } - else - { - //logerror("Timer disabled\n"); - // Update the timer so the start count is correct the next time the timer is enabled - update_timer_count(); - m_timer_enable = state; - m_internal_timer->reset(); - } -} - - - -/*************************************************************************** - ADSP CONTROL & TRANSMIT CALLBACK -****************************************************************************/ - -/* - The ADSP2105 memory map when in boot rom mode is as follows: - - Program Memory: - 0x0000-0x03ff = Internal Program Ram (contents of boot rom gets copied here) - 0x0400-0x07ff = Reserved - 0x0800-0x3fff = External Program Ram - - Data Memory: - 0x0000-0x03ff = External Data - 0 Waitstates - 0x0400-0x07ff = External Data - 1 Waitstates - 0x0800-0x2fff = External Data - 2 Waitstates - 0x3000-0x33ff = External Data - 3 Waitstates - 0x3400-0x37ff = External Data - 4 Waitstates - 0x3800-0x39ff = Internal Data Ram - 0x3a00-0x3bff = Reserved (extra internal ram space on ADSP2101, etc) - 0x3c00-0x3fff = Memory Mapped control registers & reserved. -*/ - -READ16_MEMBER( dcs_audio_device::adsp_control_r ) -{ - uint16_t result = 0xffff; - - switch (offset) - { - case PROG_FLAG_DATA_REG: - // Probably some sort of frame start for DAC with external clock - // Denver Atlantis mwskins wants 0x2 to toggle - // Denver Durnago sf2049te wants 0x6 to toogle - result = (m_control_regs[PROG_FLAG_CONTROL_REG] & m_control_regs[PROG_FLAG_DATA_REG]) | (m_progflags & ~m_control_regs[PROG_FLAG_CONTROL_REG]); - m_progflags ^= 0x6; - break; - - case IDMA_CONTROL_REG: - if (m_rev == REV_DSIO || m_rev == REV_DENV) - result = downcast<adsp2181_device *>(m_cpu)->idma_addr_r(); - break; - - case TIMER_COUNT_REG: - update_timer_count(); - result = m_control_regs[offset]; - break; - - default: - result = m_control_regs[offset]; - break; - } - if (LOG_DCS_IO) - logerror("%s adsp_control_r(%06x) = %04X\n", machine().describe_context(), offset + 0x3fe0, result); - return result; -} - - -WRITE16_MEMBER(dcs_audio_device:: adsp_control_w ) -{ - m_control_regs[offset] = data; - - switch (offset) - { - case SYSCONTROL_REG: - /* bit 9 forces a reset (not on 2181) */ - if ((data & 0x0200) && !(m_rev == REV_DSIO || m_rev == REV_DENV)) - { - logerror("%s Rebooting DCS due to SYSCONTROL write = %04X\n", machine().describe_context(), data); - m_cpu->pulse_input_line(INPUT_LINE_RESET, attotime::zero); - dcs_boot(); - m_control_regs[SYSCONTROL_REG] = 0; - } - - /* see if SPORT1 got disabled */ - if ((data & 0x0800) == 0) - { - dmadac_enable(&m_dmadac[0], m_channels, 0); - m_reg_timer->reset(); - } - - // Check SPORT0 enabled - if (m_sport0_timer != nullptr) { - if (data & 0x1000) { - // Start the SPORT0 timer - // SPORT0 is used as a 1kHz timer - m_sport0_timer->adjust(attotime::from_usec(10), 0, attotime::from_hz(1000)); - if (LOG_DCS_IO) - logerror("adsp_control_w: Setting SPORT0 freqency to 1kHz\n"); - } - else { - // Stop the SPORT0 timer - m_sport0_timer->reset(); - } - } - break; - - case S1_AUTOBUF_REG: - /* autobuffer off: nuke the timer, and disable the DAC */ - if ((data & 0x0002) == 0) - { - dmadac_enable(&m_dmadac[0], m_channels, 0); - m_reg_timer->reset(); - } - break; - - case S1_CONTROL_REG: - if (((data >> 4) & 3) == 2) - logerror("DCS: Oh no!, the data is compressed with u-law encoding\n"); - if (((data >> 4) & 3) == 3) - logerror("DCS: Oh no!, the data is compressed with A-law encoding\n"); - break; - - case TIMER_SCALE_REG: - data = (data & 0xff) + 1; - if (data != m_timer_scale) - { - update_timer_count(); - m_timer_scale = data; - reset_timer(); - } - break; - - case TIMER_COUNT_REG: - m_timer_start_count = data; - reset_timer(); - break; - - case TIMER_PERIOD_REG: - if (data != m_timer_period) - { - update_timer_count(); - m_timer_period = data; - reset_timer(); - } - break; - - case IDMA_CONTROL_REG: - if (m_rev == REV_DSIO || m_rev == REV_DENV) - dsio_idma_addr_w(space, offset, data); - break; - } - if (LOG_DCS_IO) - logerror("%s adsp_control_w(%06x) = %04X\n", machine().describe_context(), offset + 0x3fe0, data); -} - - -/*************************************************************************** - DCS IRQ GENERATION CALLBACKS -****************************************************************************/ - -TIMER_DEVICE_CALLBACK_MEMBER( dcs_audio_device::dcs_irq ) -{ - /* get the index register */ - int reg = m_cpu->state_int(ADSP2100_I0 + m_ireg); - if (LOG_DCS_IO) - logerror("dcs_irq: m_ireg: %x m_size: %x m_incs: %x m_channels: %d m_ireg_base: %x reg: %06x\n", m_ireg, m_size, m_incs, m_channels, m_ireg_base, reg); - - /* copy the current data into the buffer */ - { - int count = m_size / (2*(m_incs ? m_incs : 1)); - // sf2049se was having overflow issues with fixed size of 0x400 buffer (m_size==0xb40, count=0x5a0). - int16_t buffer[0x800]; - int i; - - for (i = 0; i < count; i++) - { - buffer[i] = m_data->read_word(reg); - reg += m_incs; - } - - if (m_channels) - dmadac_transfer(&m_dmadac[0], m_channels, 1, m_channels, count / m_channels, buffer); - } - - /* check for wrapping */ - m_ireg_base = m_cpu->get_ibase(m_ireg); - if (reg >= m_ireg_base + m_size) - { - /* reset the base pointer */ - reg = m_ireg_base; - - /* generate the (internal, thats why the pulse) irq */ - if (LOG_DCS_IO) - logerror("dcs_irq: Genrating interrupt\n"); - m_cpu->pulse_input_line(ADSP2105_IRQ1, m_cpu->minimum_quantum_time()); - } - - /* store it */ - m_cpu->set_state_int(ADSP2100_I0 + m_ireg, reg); - if (LOG_DCS_IO) - logerror("dcs_irq end: m_size: %x m_incs: %x m_channels: %d m_ireg_base: %x reg: %06x\n", m_size, m_incs, m_channels, m_ireg_base, reg); -} - -TIMER_DEVICE_CALLBACK_MEMBER( dcs_audio_device::sport0_irq ) -{ - - /* this latches internally, so we just pulse */ - /* note that there is non-interrupt code that reads/modifies/writes the output_control */ - /* register; if we don't interlock it, we will eventually lose sound (see CarnEvil) */ - /* so we skip the SPORT interrupt if we read with output_control within the last 5 cycles */ - uint64_t diff = m_cpu->total_cycles() - m_output_control_cycles; - if (diff > 5) - { - m_cpu->set_input_line(ADSP2115_SPORT0_RX, ASSERT_LINE); - m_cpu->set_input_line(ADSP2115_SPORT0_RX, CLEAR_LINE); - } -} - - -void dcs_audio_device::recompute_sample_rate() -{ - /* calculate how long until we generate an interrupt */ - - /* frequency the time per each bit sent */ - attotime sample_period; - if (m_control_regs[S1_CONTROL_REG] & 0x4000) { - // Use internal clock for SPORT1 Tx timing - sample_period = attotime::from_hz(m_cpu->unscaled_clock()) * (2 * (m_control_regs[S1_SCLKDIV_REG] + 1)); - /* now put it down to samples, so we know what the channel frequency has to be */ - sample_period *= (16 * m_channels); - } - else { - // Use external clock for SPORT1 Tx timing 31.25 KHz sample clock - sample_period = attotime::from_hz(31250); - } - - dmadac_set_frequency(&m_dmadac[0], m_channels, sample_period.as_hz()); - dmadac_enable(&m_dmadac[0], m_channels, 1); - if (LOG_DCS_IO) - logerror("recompute_sample_rate: Channels: %d Freq: %e Size: 0x%x m_incs: 0x%x\n", m_channels, sample_period.as_hz(), m_size, m_incs); - - /* fire off a timer which will hit every half-buffer */ - if (m_incs) - { - attotime period = (sample_period * m_size) / (2 * m_channels * m_incs); - m_reg_timer->adjust(period, 0, period); - } -} - -WRITE32_MEMBER(dcs_audio_device::sound_tx_callback) -{ - /* check if it's for SPORT1 */ - if (offset != 1) { - logerror("sound_tx_callback: No code for offset %x\n", offset); - return; - } - - /* check if SPORT1 is enabled */ - if (m_control_regs[SYSCONTROL_REG] & 0x0800) /* bit 11 */ - { - /* we only support autobuffer here (wich is what this thing uses), bail if not enabled */ - if (m_control_regs[S1_AUTOBUF_REG] & 0x0002) /* bit 1 */ - { - /* get the autobuffer registers */ - int mreg, lreg; - uint16_t source; - - m_ireg = (m_control_regs[S1_AUTOBUF_REG] >> 9) & 7; - mreg = (m_control_regs[S1_AUTOBUF_REG] >> 7) & 3; - mreg |= m_ireg & 0x04; /* msb comes from ireg */ - lreg = m_ireg; - - /* now get the register contents in a more legible format */ - /* we depend on register indexes to be continuous (which is the case in our core) */ - source = m_cpu->state_int(ADSP2100_I0 + m_ireg); - m_incs = m_cpu->state_int(ADSP2100_M0 + mreg); - m_size = m_cpu->state_int(ADSP2100_L0 + lreg); - - /* get the base value, since we need to keep it around for wrapping */ - //source -= m_incs; - // Just clear lower 4 bits of source since some DCS versions haven't incremented yet - source &= ~0xf; - - /* make it go back one so we dont lose the first sample */ - m_cpu->set_state_int(ADSP2100_I0 + m_ireg, source); - - /* save it as it is now */ - m_ireg_base = source; - - if (LOG_DCS_IO) - logerror("sound_tx_callback: m_ireg_base: %x m_size: %x m_incs: %x \n", m_ireg_base, m_size, m_incs); - /* recompute the sample rate and timer */ - recompute_sample_rate(); - return; - } - else - logerror( "ADSP SPORT1: trying to transmit and autobuffer not enabled!\n" ); - } - - /* if we get there, something went wrong. Disable playing */ - dmadac_enable(&m_dmadac[0], m_channels, 0); - - /* remove timer */ - m_reg_timer->reset(); -} - - - -/*************************************************************************** - VERY BASIC & SAFE OPTIMIZATIONS -****************************************************************************/ - -READ16_MEMBER( dcs_audio_device::dcs_polling_r ) -{ - if (m_polling_count++ > 5) - space.device().execute().eat_cycles(2000); - return m_polling_value; -} - - -WRITE16_MEMBER( dcs_audio_device::dcs_polling_w ) -{ - m_polling_count = 0; - COMBINE_DATA(&m_polling_value); -} - -READ32_MEMBER(dcs_audio_device::dcs_polling32_r) -{ - space.device().execute().eat_cycles(1000); - return m_polling32_value; -} - -WRITE32_MEMBER(dcs_audio_device::dcs_polling32_w) -{ - m_polling_count = 0; - COMBINE_DATA(&m_polling32_value); -} - - - -/*************************************************************************** - DATA TRANSFER HLE MECHANISM -****************************************************************************/ - -void dcs_audio_device::fifo_notify(int count, int max) -{ - hle_transfer_state &transfer = m_transfer; - - /* skip if not in mid-transfer */ - if (!transfer.hle_enabled || transfer.state == 0 || m_fifo_data_r.isnull()) - { - transfer.fifo_entries = 0; - return; - } - - /* preprocess a word */ - transfer.fifo_entries = count; - if (transfer.state != 5 || transfer.fifo_entries == transfer.writes_left || transfer.fifo_entries >= 256) - { - for ( ; transfer.fifo_entries; transfer.fifo_entries--) - preprocess_write(m_fifo_data_r(machine().dummy_space(), 0, 0xffff)); - } -} - - -TIMER_DEVICE_CALLBACK_MEMBER( dcs_audio_device::transfer_watchdog_callback ) -{ - hle_transfer_state &transfer = m_transfer; - int starting_writes_left = param; - - if (transfer.fifo_entries && starting_writes_left == transfer.writes_left) - { - for ( ; transfer.fifo_entries; transfer.fifo_entries--) - preprocess_write(m_fifo_data_r(machine().dummy_space(), 0, 0xffff)); - } - if (transfer.watchdog != nullptr) - transfer.watchdog->adjust(attotime::from_msec(1), transfer.writes_left); -} - - -TIMER_CALLBACK_MEMBER( dcs_audio_device::s1_ack_callback2 ) -{ - /* if the output is full, stall for a usec */ - if (IS_OUTPUT_FULL()) - { - machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(dcs_audio_device::s1_ack_callback2),this), param); - return; - } - output_latch_w(m_cpu->space(AS_PROGRAM), 0, 0x000a, 0xffff); -} - - -TIMER_CALLBACK_MEMBER( dcs_audio_device::s1_ack_callback1 ) -{ - /* if the output is full, stall for a usec */ - if (IS_OUTPUT_FULL()) - { - machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(dcs_audio_device::s1_ack_callback1),this), param); - return; - } - output_latch_w(m_cpu->space(AS_PROGRAM), 0, param, 0xffff); - - /* chain to the next word we need to write back */ - machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(dcs_audio_device::s1_ack_callback2),this)); -} - - -int dcs_audio_device::preprocess_stage_1(uint16_t data) -{ - hle_transfer_state &transfer = m_transfer; - - switch (transfer.state) - { - case 0: - /* look for command 0x001a to transfer chunks of data */ - if (data == 0x001a) - { - if (LOG_DCS_TRANSFERS) - logerror("%s:DCS Transfer command %04X\n", machine().describe_context(), data); - transfer.state++; - if (transfer.hle_enabled) - return 1; - } - - /* look for command 0x002a to start booting the uploaded program */ - else if (data == 0x002a) - { - if (LOG_DCS_TRANSFERS) - logerror("%s:DCS State change %04X\n", machine().describe_context(), data); - transfer.dcs_state = 1; - } - - /* anything else is ignored */ - else - { - if (LOG_DCS_TRANSFERS) - logerror("Command: %04X\n", data); - } - break; - - case 1: - /* first word is the start address */ - transfer.start = data; - transfer.state++; - if (LOG_DCS_TRANSFERS) - logerror("Start address = %04X\n", transfer.start); - if (transfer.hle_enabled) - return 1; - break; - - case 2: - /* second word is the stop address */ - transfer.stop = data; - transfer.state++; - if (LOG_DCS_TRANSFERS) - logerror("Stop address = %04X\n", transfer.stop); - if (transfer.hle_enabled) - return 1; - break; - - case 3: - /* third word is the transfer type */ - /* transfer type 0 = program memory */ - /* transfer type 1 = SRAM bank 0 */ - /* transfer type 2 = SRAM bank 1 */ - transfer.type = data; - transfer.state++; - if (LOG_DCS_TRANSFERS) logerror("Transfer type = %04X\n", transfer.type); - - /* at this point, we can compute how many words to expect for the transfer */ - transfer.writes_left = transfer.stop - transfer.start + 1; - if (transfer.type == 0) - transfer.writes_left *= 2; - - /* reset the checksum */ - transfer.sum = 0; - - /* handle the HLE case */ - if (transfer.hle_enabled) - { - if (transfer.type == 1 && SDRC_SM_BK == 1) - { - m_sdrc.reg[0] &= ~0x1000; - sdrc_remap_memory(); - } - if (transfer.type == 2 && SDRC_SM_BK == 0) - { - m_sdrc.reg[0] |= 0x1000; - sdrc_remap_memory(); - } - return 1; - } - break; - - case 4: - /* accumulate the sum over all data */ - transfer.sum += data; - - /* if we're out, stop the transfer */ - if (--transfer.writes_left == 0) - { - if (LOG_DCS_TRANSFERS) logerror("Transfer done, sum = %04X\n", transfer.sum); - transfer.state = 0; - } - - /* handle the HLE case */ - if (transfer.hle_enabled) - { - /* write the new data to memory */ - if (transfer.type == 0) - { - if (transfer.writes_left & 1) - transfer.temp = data; - else - m_program->write_dword(transfer.start++, (transfer.temp << 8) | (data & 0xff)); - } - else - m_data->write_word(transfer.start++, data); - - /* if we're done, start a timer to send the response words */ - if (transfer.state == 0) - machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(dcs_audio_device::s1_ack_callback1),this), transfer.sum); - return 1; - } - break; - } - return 0; -} - - -TIMER_CALLBACK_MEMBER( dcs_audio_device::s2_ack_callback ) -{ - address_space &space = m_cpu->space(AS_PROGRAM); - - /* if the output is full, stall for a usec */ - if (IS_OUTPUT_FULL()) - { - machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(dcs_audio_device::s2_ack_callback),this), param); - return; - } - output_latch_w(space, 0, param, 0xffff); - output_control_w(space, 0, (m_output_control & ~0xff00) | 0x0300, 0xffff); -} - - -int dcs_audio_device::preprocess_stage_2(uint16_t data) -{ - hle_transfer_state &transfer = m_transfer; - - switch (transfer.state) - { - case 0: - /* look for command 0x55d0 or 0x55d1 to transfer chunks of data */ - if (data == 0x55d0 || data == 0x55d1) - { - if (LOG_DCS_TRANSFERS) - logerror("%s:DCS Transfer command %04X\n", machine().describe_context(), data); - transfer.state++; - if (transfer.hle_enabled) - return 1; - } - - /* anything else is ignored */ - else - { - if (LOG_DCS_TRANSFERS) - logerror("%s:Command: %04X\n", machine().describe_context(), data); - } - break; - - case 1: - /* first word is the upper bits of the start address */ - transfer.start = data << 16; - transfer.state++; - if (transfer.hle_enabled) - return 1; - break; - - case 2: - /* second word is the lower bits of the start address */ - transfer.start |= data; - transfer.state++; - if (LOG_DCS_TRANSFERS) - logerror("Start address = %08X\n", transfer.start); - if (transfer.hle_enabled) - return 1; - break; - - case 3: - /* third word is the upper bits of the stop address */ - transfer.stop = data << 16; - transfer.state++; - if (transfer.hle_enabled) - return 1; - break; - - case 4: - /* fourth word is the lower bits of the stop address */ - transfer.stop |= data; - transfer.state++; - if (LOG_DCS_TRANSFERS) - logerror("Stop address = %08X\n", transfer.stop); - - /* at this point, we can compute how many words to expect for the transfer */ - transfer.writes_left = transfer.stop - transfer.start + 1; - - /* reset the checksum */ - transfer.sum = 0; - if (transfer.hle_enabled) - { - transfer.watchdog->adjust(attotime::from_msec(1), transfer.writes_left); - return 1; - } - break; - - case 5: - /* accumulate the sum over all data */ - transfer.sum += data; - - /* if we're out, stop the transfer */ - if (--transfer.writes_left == 0) - { - if (LOG_DCS_TRANSFERS) - logerror("Transfer done, sum = %04X\n", transfer.sum); - transfer.state = 0; - } - - /* handle the HLE case */ - if (transfer.hle_enabled) - { - /* write the new data to memory */ - m_sounddata[transfer.start++] = data; - - /* if we're done, start a timer to send the response words */ - if (transfer.state == 0) - { - machine().scheduler().timer_set(attotime::from_usec(1), timer_expired_delegate(FUNC(dcs_audio_device::s2_ack_callback),this), transfer.sum); - transfer.watchdog->reset(); - } - return 1; - } - break; - } - return 0; -} - - -int dcs_audio_device::preprocess_write(uint16_t data) -{ - hle_transfer_state &transfer = m_transfer; - int result; - - /* if we're not DCS2, skip */ - if (m_sport0_timer == nullptr) - return 0; - - /* state 0 - initialization phase */ - if (transfer.dcs_state == 0) - result = preprocess_stage_1(data); - else - result = preprocess_stage_2(data); - - /* if we did the write, toggle the full/not full state so interrupts are generated */ - if (result && !m_input_empty_cb.isnull()) - { - if (m_last_input_empty) - m_input_empty_cb(m_last_input_empty = 0); - if (!m_last_input_empty) - m_input_empty_cb(m_last_input_empty = 1); - } - return result; -} - -/* Basic DCS system with ADSP-2105 and 2k of SRAM (T-unit, V-unit, Killer Instinct) */ - -void dcs_audio_device::add_mconfig_dcs(machine_config &config) -{ - adsp2105_device &dcs(ADSP2105(config, "dcs", XTAL(10'000'000))); - dcs.sport_tx().set(FUNC(dcs_audio_device::sound_tx_callback)); /* callback for serial transmit */ - dcs.timer_fired().set(FUNC(dcs_audio_device::timer_enable_callback)); /* callback for timer fired */ - dcs.set_addrmap(AS_PROGRAM, &dcs_audio_device::dcs_2k_program_map); - dcs.set_addrmap(AS_DATA, &dcs_audio_device::dcs_2k_data_map); - - TIMER(config, "dcs_reg_timer").configure_generic(FUNC(dcs_audio_device::dcs_irq)); - TIMER(config, "dcs_int_timer").configure_generic(FUNC(dcs_audio_device::internal_timer_callback)); - - SPEAKER(config, "mono").front_center(); - - DMADAC(config, "dac").add_route(ALL_OUTPUTS, "mono", 1.0); // AD-1851 16bit mono -} - -DEFINE_DEVICE_TYPE(DCS_AUDIO_2K, dcs_audio_2k_device, "dcs_audio_2k", "DCS Audio 2K") - -//------------------------------------------------- -// dcs_audio_2k_device - constructor -//------------------------------------------------- - -dcs_audio_2k_device::dcs_audio_2k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - dcs_audio_device(mconfig, DCS_AUDIO_2K, tag, owner, clock, REV_DCS1) -{ -} - -void dcs_audio_2k_device::device_add_mconfig(machine_config &config) -{ - dcs_audio_device::add_mconfig_dcs(config); -} - -DEFINE_DEVICE_TYPE(DCS_AUDIO_2K_UART, dcs_audio_2k_uart_device, "dcs_audio_2k_uart", "DCS Audio 2K UART") - -//------------------------------------------------- -// dcs_audio_2k_uart_device - constructor -//------------------------------------------------- - -dcs_audio_2k_uart_device::dcs_audio_2k_uart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - dcs_audio_device(mconfig, DCS_AUDIO_2K_UART, tag, owner, clock, REV_DCS1) -{ -} - -/* Basic DCS system with ADSP-2105 and 2k of SRAM, using a UART for communications (X-unit) */ -void dcs_audio_2k_uart_device::device_add_mconfig(machine_config &config) -{ - dcs_audio_device::add_mconfig_dcs(config); - subdevice<adsp21xx_device>("dcs")->set_addrmap(AS_DATA, &dcs_audio_2k_uart_device::dcs_2k_uart_data_map); -} - -DEFINE_DEVICE_TYPE(DCS_AUDIO_8K, dcs_audio_8k_device, "dcs_audio_8k", "DCS Audio 8K") - -//------------------------------------------------- -// dcs_audio_8k_device - constructor -//------------------------------------------------- - -dcs_audio_8k_device::dcs_audio_8k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - dcs_audio_device(mconfig, DCS_AUDIO_8K, tag, owner, clock, REV_DCS1) -{ -} - -/* Basic DCS system with ADSP-2105 and 8k of SRAM (Wolf-unit) */ -void dcs_audio_8k_device::device_add_mconfig(machine_config &config) -{ - dcs_audio_device::add_mconfig_dcs(config); - subdevice<adsp21xx_device>("dcs")->set_addrmap(AS_PROGRAM, &dcs_audio_8k_device::dcs_8k_program_map); - subdevice<adsp21xx_device>("dcs")->set_addrmap(AS_DATA, &dcs_audio_8k_device::dcs_8k_data_map); -} - -DEFINE_DEVICE_TYPE(DCS_AUDIO_WPC, dcs_audio_wpc_device, "dcs_audio_wpc", "DCS Audio WPC") - -//------------------------------------------------- -// dcs_audio_wpc_device - constructor -//------------------------------------------------- - -dcs_audio_wpc_device::dcs_audio_wpc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - dcs_audio_device(mconfig, DCS_AUDIO_WPC, tag, owner, clock, REV_DCS1P5) -{ -} - -void dcs_audio_wpc_device::device_add_mconfig(machine_config &config) -{ - dcs_audio_device::add_mconfig_dcs(config); - subdevice<adsp21xx_device>("dcs")->set_addrmap(AS_PROGRAM, &dcs_audio_wpc_device::dcs_wpc_program_map); - subdevice<adsp21xx_device>("dcs")->set_addrmap(AS_DATA, &dcs_audio_wpc_device::dcs_wpc_data_map); -} - - -//------------------------------------------------- -// dcs2_audio_device - constructor -//------------------------------------------------- - -dcs2_audio_device::dcs2_audio_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - dcs_audio_device(mconfig, type, tag, owner, clock, REV_DCS1) -{ -} - -void dcs2_audio_device::add_mconfig_dcs2(machine_config &config) -{ - adsp2115_device &dcs2(ADSP2115(config, "dcs2", XTAL(16'000'000))); - dcs2.sport_tx().set(FUNC(dcs_audio_device::sound_tx_callback)); /* callback for serial transmit */ - dcs2.timer_fired().set(FUNC(dcs_audio_device::timer_enable_callback)); /* callback for timer fired */ - dcs2.set_addrmap(AS_PROGRAM, &dcs2_audio_device::dcs2_2115_program_map); - dcs2.set_addrmap(AS_DATA, &dcs2_audio_device::dcs2_2115_data_map); - - TIMER(config, "dcs_reg_timer").configure_generic(FUNC(dcs_audio_device::dcs_irq)); - TIMER(config, "dcs_sport0_timer").configure_generic(FUNC(dcs_audio_device::sport0_irq)); - TIMER(config, "dcs_int_timer").configure_generic(FUNC(dcs_audio_device::internal_timer_callback)); - TIMER(config, "dcs_hle_timer").configure_generic(FUNC(dcs_audio_device::transfer_watchdog_callback)); - - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); - - DMADAC(config, "dac1").add_route(ALL_OUTPUTS, "rspeaker", 1.0); - DMADAC(config, "dac2").add_route(ALL_OUTPUTS, "lspeaker", 1.0); -} - -DEFINE_DEVICE_TYPE(DCS2_AUDIO_2115, dcs2_audio_2115_device, "dcs2_audio_2115", "DCS2 Audio 2115") - -//------------------------------------------------- -// dcs2_audio_2115_device - constructor -//------------------------------------------------- - -dcs2_audio_2115_device::dcs2_audio_2115_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - dcs2_audio_device(mconfig, DCS2_AUDIO_2115, tag, owner, clock) -{ -} - -void dcs2_audio_2115_device::device_add_mconfig(machine_config &config) -{ - dcs2_audio_device::add_mconfig_dcs2(config); -} - -DEFINE_DEVICE_TYPE(DCS2_AUDIO_2104, dcs2_audio_2104_device, "dcs2_audio_2104", "DCS2 Audio 2104") - -//------------------------------------------------- -// dcs2_audio_2104_device - constructor -//------------------------------------------------- - - -dcs2_audio_2104_device::dcs2_audio_2104_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - dcs2_audio_device(mconfig, DCS2_AUDIO_2104, tag, owner, clock) -{ -} - -void dcs2_audio_2104_device::device_add_mconfig(machine_config &config) -{ - dcs2_audio_device::add_mconfig_dcs2(config); - - adsp2104_device &dcs2(ADSP2104(config.replace(), "dcs2", XTAL(16'000'000))); - dcs2.sport_tx().set(FUNC(dcs_audio_device::sound_tx_callback)); /* callback for serial transmit */ - dcs2.timer_fired().set(FUNC(dcs_audio_device::timer_enable_callback)); /* callback for timer fired */ - dcs2.set_addrmap(AS_PROGRAM, &dcs2_audio_2104_device::dcs2_2104_program_map); - dcs2.set_addrmap(AS_DATA, &dcs2_audio_2104_device::dcs2_2104_data_map); -} - -DEFINE_DEVICE_TYPE(DCS2_AUDIO_DSIO, dcs2_audio_dsio_device, "dcs2_audio_dsio", "DCS2 Audio DSIO") - -//------------------------------------------------- -// dcs2_audio_dsio_device - constructor -//------------------------------------------------- - -dcs2_audio_dsio_device::dcs2_audio_dsio_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - dcs2_audio_device(mconfig, DCS2_AUDIO_DSIO, tag, owner, clock) -{ -} - -void dcs2_audio_dsio_device::device_add_mconfig(machine_config &config) -{ - adsp2181_device &dsio(ADSP2181(config, "dsio", XTAL(32'000'000))); - dsio.sport_tx().set(FUNC(dcs_audio_device::sound_tx_callback)); /* callback for serial transmit */ - dsio.timer_fired().set(FUNC(dcs_audio_device::timer_enable_callback)); /* callback for timer fired */ - dsio.dmovlay().set(FUNC(dcs_audio_device::dmovlay_callback)); /* callback for adsp 2181 dmovlay instruction */ - dsio.set_addrmap(AS_PROGRAM, &dcs2_audio_dsio_device::dsio_program_map); - dsio.set_addrmap(AS_DATA, &dcs2_audio_dsio_device::dsio_data_map); - dsio.set_addrmap(AS_IO, &dcs2_audio_dsio_device::dsio_io_map); - - ADDRESS_MAP_BANK(config, "data_map_bank").set_map(&dcs2_audio_dsio_device::dsio_rambank_map).set_options(ENDIANNESS_LITTLE, 16, 14, 0x2000); - - TIMER(config, "dcs_reg_timer").configure_generic(FUNC(dcs_audio_device::dcs_irq)); - TIMER(config, "dcs_int_timer").configure_generic(FUNC(dcs_audio_device::internal_timer_callback)); - TIMER(config, "dcs_sport0_timer").configure_generic(FUNC(dcs_audio_device::sport0_irq)); // roadburn needs this to pass hardware test - - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); - - DMADAC(config, "dac1").add_route(ALL_OUTPUTS, "rspeaker", 1.0); - DMADAC(config, "dac2").add_route(ALL_OUTPUTS, "lspeaker", 1.0); -} - - -//------------------------------------------------- -// dcs2_audio_denver_device - constructor -//------------------------------------------------- -dcs2_audio_denver_device::dcs2_audio_denver_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : - dcs2_audio_device(mconfig, type, tag, owner, clock) -{ -} - -void dcs2_audio_denver_device::device_add_mconfig(machine_config &config) -{ - adsp2181_device &denver(ADSP2181(config, "denver", XTAL(33'333'000))); - denver.sport_tx().set(FUNC(dcs_audio_device::sound_tx_callback)); /* callback for serial transmit */ - denver.timer_fired().set(FUNC(dcs_audio_device::timer_enable_callback)); /* callback for timer fired */ - denver.dmovlay().set(FUNC(dcs_audio_device::dmovlay_callback)); /* callback for adsp 2181 dmovlay instruction */ - denver.set_addrmap(AS_PROGRAM, &dcs2_audio_denver_device::denver_program_map); - denver.set_addrmap(AS_DATA, &dcs2_audio_denver_device::denver_data_map); - denver.set_addrmap(AS_IO, &dcs2_audio_denver_device::denver_io_map); - - ADDRESS_MAP_BANK(config, "data_map_bank").set_map(&dcs2_audio_denver_device::denver_rambank_map).set_options(ENDIANNESS_LITTLE, 16, 15, 0x2000*2); - - TIMER(config, "dcs_reg_timer").configure_generic(FUNC(dcs_audio_device::dcs_irq)); - TIMER(config, "dcs_int_timer").configure_generic(FUNC(dcs_audio_device::internal_timer_callback)); - TIMER(config, "dcs_sport0_timer").configure_generic(FUNC(dcs_audio_device::sport0_irq)); // Atlantis driver waits for sport0 rx interrupts -} - -dcs2_audio_denver_5ch_device::dcs2_audio_denver_5ch_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - dcs2_audio_denver_device(mconfig, DCS2_AUDIO_DENVER_5CH, tag, owner, clock) -{ -} - -void dcs2_audio_denver_5ch_device::device_add_mconfig(machine_config &config) -{ - dcs2_audio_denver_device::device_add_mconfig(config); - - SPEAKER(config, "flspeaker").front_left(); - SPEAKER(config, "frspeaker").front_right(); - SPEAKER(config, "rlspeaker").rear_left(); - SPEAKER(config, "rrspeaker").rear_right(); - SPEAKER(config, "subwoofer").subwoofer(); - - DMADAC(config, "dac1").add_route(ALL_OUTPUTS, "flspeaker", 1.0); - DMADAC(config, "dac2").add_route(ALL_OUTPUTS, "frspeaker", 1.0); - DMADAC(config, "dac3").add_route(ALL_OUTPUTS, "rlspeaker", 1.0); - DMADAC(config, "dac4").add_route(ALL_OUTPUTS, "rrspeaker", 1.0); - DMADAC(config, "dac5").add_route(ALL_OUTPUTS, "subwoofer", 1.0); - DMADAC(config, "dac6"); - // Does not produce sound -} - -DEFINE_DEVICE_TYPE(DCS2_AUDIO_DENVER_5CH, dcs2_audio_denver_5ch_device, "dcs2_audio_denver_5ch", "DCS2 Audio Denver 5 Channel") - -dcs2_audio_denver_2ch_device::dcs2_audio_denver_2ch_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - dcs2_audio_denver_device(mconfig, DCS2_AUDIO_DENVER_2CH, tag, owner, clock) -{ -} - -void dcs2_audio_denver_2ch_device::device_add_mconfig(machine_config &config) -{ - dcs2_audio_denver_device::device_add_mconfig(config); - - SPEAKER(config, "lspeaker").front_left(); - SPEAKER(config, "rspeaker").front_right(); - - DMADAC(config, "dac1").add_route(ALL_OUTPUTS, "rspeaker", 1.0); - DMADAC(config, "dac2").add_route(ALL_OUTPUTS, "lspeaker", 1.0); -} - -DEFINE_DEVICE_TYPE(DCS2_AUDIO_DENVER_2CH, dcs2_audio_denver_2ch_device, "dcs2_audio_denver_2ch", "DCS2 Audio Denver 2 Channel") |