diff options
Diffstat (limited to 'trunk/src/mame/audio/namco52.c')
-rw-r--r-- | trunk/src/mame/audio/namco52.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/trunk/src/mame/audio/namco52.c b/trunk/src/mame/audio/namco52.c new file mode 100644 index 00000000000..8a247832b4e --- /dev/null +++ b/trunk/src/mame/audio/namco52.c @@ -0,0 +1,241 @@ +/*************************************************************************** + + Namco 52XX + + This instance of the Fujitsu MB8843 MCU is programmed to act as a + sample player. It is used by just two games: Bosconian and Pole + Position. + + A0-A15 = address to read from sample ROMs + D0-D7 = data from sample ROMs + CMD0-CMD3 = command from CPU (sample to play, 0 = none) + OUT0-OUT3 = sound output + + +------+ + EX|1 42|Vcc + X|2 41|K3 (CMD3) + /RESET|3 40|K2 (CMD2) + /IRQ|4 39|K1 (CMD1) + (n.c.) SO|5 38|K0 (CMD0) + [1] SI|6 37|R15 (A7) + (n.c.) /SC/TO|7 36|R14 (A6) + [2] /TC|8 35|R13 (A5) + (OUT0) P0|9 34|R12 (A4) + (OUT1) P1|10 33|R11 (A3) + (OUT2) P2|11 32|R10 (A2) + (OUT3) P3|12 31|R9 (A1) + (A8) O0|13 30|R8 (A0) + (A9) O1|14 29|R7 (D7) + (A10) O2|15 28|R6 (D6) + (A11) O3|16 27|R5 (D5) + (A12) O4|17 26|R4 (D4) + (A13) O5|18 25|R3 (D3) + (A14) O6|19 24|R2 (D2) + (A15) O7|20 23|R1 (D1) + GND|21 22|R0 (D0) + +------+ + + [1] in polepos, +5V; in bosco, GND + this value controls the ROM addressing mode: + if 0 (GND), A12-A15 are direct active-low chip enables + if 1 (Vcc), A12-A15 are address lines + + [2] in polepos, GND; in bosco, output from a 555 timer + this value is an external timer, which is used for some samples + +***************************************************************************/ + +#include "emu.h" +#include "namco52.h" +#include "cpu/mb88xx/mb88xx.h" + +typedef struct _namco_52xx_state namco_52xx_state; +struct _namco_52xx_state +{ + device_t *m_cpu; + device_t *m_discrete; + int m_basenode; + devcb_resolved_read8 m_romread; + devcb_resolved_read8 m_si; + UINT8 m_latched_cmd; + UINT32 m_address; +}; + +INLINE namco_52xx_state *get_safe_token(device_t *device) +{ + assert(device != NULL); + assert(device->type() == NAMCO_52XX); + + return (namco_52xx_state *)downcast<legacy_device_base *>(device)->token(); +} + + + +static TIMER_CALLBACK( namco_52xx_latch_callback ) +{ + namco_52xx_state *state = get_safe_token((device_t *)ptr); + state->m_latched_cmd = param; +} + +static READ8_HANDLER( namco_52xx_K_r ) +{ + namco_52xx_state *state = get_safe_token(space->device().owner()); + return state->m_latched_cmd & 0x0f; +} + +static READ8_HANDLER( namco_52xx_SI_r ) +{ + namco_52xx_state *state = get_safe_token(space->device().owner()); + return state->m_si(0) ? 1 : 0; +} + +static READ8_HANDLER( namco_52xx_R0_r ) +{ + namco_52xx_state *state = get_safe_token(space->device().owner()); + return state->m_romread(state->m_address) & 0x0f; +} + +static READ8_HANDLER( namco_52xx_R1_r ) +{ + namco_52xx_state *state = get_safe_token(space->device().owner()); + return state->m_romread(state->m_address) >> 4; +} + + +static WRITE8_HANDLER( namco_52xx_P_w ) +{ + namco_52xx_state *state = get_safe_token(space->device().owner()); + discrete_sound_w(state->m_discrete, NAMCO_52XX_P_DATA(state->m_basenode), data & 0x0f); +} + +static WRITE8_HANDLER( namco_52xx_R2_w ) +{ + namco_52xx_state *state = get_safe_token(space->device().owner()); + state->m_address = (state->m_address & 0xfff0) | ((data & 0xf) << 0); +} + +static WRITE8_HANDLER( namco_52xx_R3_w ) +{ + namco_52xx_state *state = get_safe_token(space->device().owner()); + state->m_address = (state->m_address & 0xff0f) | ((data & 0xf) << 4); +} + +static WRITE8_HANDLER( namco_52xx_O_w ) +{ + namco_52xx_state *state = get_safe_token(space->device().owner()); + if (data & 0x10) + state->m_address = (state->m_address & 0x0fff) | ((data & 0xf) << 12); + else + state->m_address = (state->m_address & 0xf0ff) | ((data & 0xf) << 8); +} + + + + +static TIMER_CALLBACK( namco_52xx_irq_clear ) +{ + namco_52xx_state *state = get_safe_token((device_t *)ptr); + device_set_input_line(state->m_cpu, 0, CLEAR_LINE); +} + +WRITE8_DEVICE_HANDLER( namco_52xx_write ) +{ + namco_52xx_state *state = get_safe_token(device); + + device->machine().scheduler().synchronize(FUNC(namco_52xx_latch_callback), data, (void *)device); + + device_set_input_line(state->m_cpu, 0, ASSERT_LINE); + + // The execution time of one instruction is ~4us, so we must make sure to + // give the cpu time to poll the /IRQ input before we clear it. + // The input clock to the 06XX interface chip is 64H, that is + // 18432000/6/64 = 48kHz, so it makes sense for the irq line to be + // asserted for one clock cycle ~= 21us. + + /* the 52xx uses TSTI to check for an interrupt; it also may be handling + a timer interrupt, so we need to ensure the IRQ line is held long enough */ + device->machine().scheduler().timer_set(attotime::from_usec(5*21), FUNC(namco_52xx_irq_clear), 0, (void *)device); +} + + +static TIMER_CALLBACK( external_clock_pulse ) +{ + namco_52xx_state *state = get_safe_token((device_t *)ptr); + mb88_external_clock_w(state->m_cpu, 1); + mb88_external_clock_w(state->m_cpu, 0); +} + + +/*************************************************************************** + DEVICE INTERFACE +***************************************************************************/ + +static ADDRESS_MAP_START( namco_52xx_map_io, AS_IO, 8 ) + AM_RANGE(MB88_PORTK, MB88_PORTK) AM_READ(namco_52xx_K_r) + AM_RANGE(MB88_PORTO, MB88_PORTO) AM_WRITE(namco_52xx_O_w) + AM_RANGE(MB88_PORTP, MB88_PORTP) AM_WRITE(namco_52xx_P_w) + AM_RANGE(MB88_PORTSI, MB88_PORTSI) AM_READ(namco_52xx_SI_r) + AM_RANGE(MB88_PORTR0, MB88_PORTR0) AM_READ(namco_52xx_R0_r) + AM_RANGE(MB88_PORTR1, MB88_PORTR1) AM_READ(namco_52xx_R1_r) + AM_RANGE(MB88_PORTR2, MB88_PORTR2) AM_WRITE(namco_52xx_R2_w) + AM_RANGE(MB88_PORTR3, MB88_PORTR3) AM_WRITE(namco_52xx_R3_w) +ADDRESS_MAP_END + + +static MACHINE_CONFIG_FRAGMENT( namco_52xx ) + MCFG_CPU_ADD("mcu", MB8843, DERIVED_CLOCK(1,1)) /* parent clock, internally divided by 6 */ + MCFG_CPU_IO_MAP(namco_52xx_map_io) +MACHINE_CONFIG_END + + +ROM_START( namco_52xx ) + ROM_REGION( 0x400, "mcu", 0 ) + ROM_LOAD( "52xx.bin", 0x0000, 0x0400, CRC(3257d11e) SHA1(4883b2fdbc99eb7b9906357fcc53915842c2c186) ) +ROM_END + + +/*------------------------------------------------- + device start callback +-------------------------------------------------*/ + +static DEVICE_START( namco_52xx ) +{ + namco_52xx_interface *intf = (namco_52xx_interface *)device->static_config(); + namco_52xx_state *state = get_safe_token(device); + astring tempstring; + + /* find our CPU */ + state->m_cpu = device->subdevice("mcu"); + assert(state->m_cpu != NULL); + + /* find the attached discrete sound device */ + assert(intf->discrete != NULL); + state->m_discrete = device->machine().device(intf->discrete); + assert(state->m_discrete != NULL); + state->m_basenode = intf->firstnode; + + /* resolve our read/write callbacks */ + state->m_romread.resolve(intf->romread, *device); + state->m_si.resolve(intf->si, *device); + + /* start the external clock */ + if (intf->extclock != 0) + device->machine().scheduler().timer_pulse(attotime(0, intf->extclock), FUNC(external_clock_pulse), 0, device); +} + + +/*------------------------------------------------- + device definition +-------------------------------------------------*/ + +static const char DEVTEMPLATE_SOURCE[] = __FILE__; + +#define DEVTEMPLATE_ID(p,s) p##namco_52xx##s +#define DEVTEMPLATE_FEATURES DT_HAS_START | DT_HAS_ROM_REGION | DT_HAS_MACHINE_CONFIG +#define DEVTEMPLATE_NAME "Namco 52xx" +#define DEVTEMPLATE_SHORTNAME "namco52" +#define DEVTEMPLATE_FAMILY "Namco I/O" +#include "devtempl.h" + + +DEFINE_LEGACY_DEVICE(NAMCO_52XX, namco_52xx); |