summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/mame/audio/namco52.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/mame/audio/namco52.c')
-rw-r--r--trunk/src/mame/audio/namco52.c241
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);