al520ex: added preliminary Magic Sound expansion (not working) [Barry Rodewald]

This commit is contained in:
mahlemiut 2015-09-10 23:53:20 +12:00
parent 78c8d33ebd
commit 91b0190a5d
7 changed files with 321 additions and 2 deletions

View File

@ -2185,6 +2185,8 @@ if (BUSES["CPC"]~=null) then
MAME_DIR .. "src/emu/bus/cpc/hd20.h",
MAME_DIR .. "src/emu/bus/cpc/ddi1.c",
MAME_DIR .. "src/emu/bus/cpc/ddi1.h",
MAME_DIR .. "src/emu/bus/cpc/magicsound.c",
MAME_DIR .. "src/emu/bus/cpc/magicsound.h",
}
end

View File

@ -31,6 +31,16 @@
* RAMDIS 45 46 CURSOR
* L.PEN 47 48 _EXP
* GND 49 50 CLOCK
*
* Aleste 520EX expansion port is 62-pin. Same as the CPC above, except that pin 40 is not connected, plus the following:
*
* MAP14 A26 B26 MAP15
* MAP16 A27 B27 MAP17
* MAP18 A28 B28 MAPBLK
* _INTA A29 B29 _DISP
* Agnd A30 B30 _CPU
* Aucc A31 B31 HIGH
*
*/
#pragma once

View File

@ -0,0 +1,190 @@
// license:BSD-3-Clause
// copyright-holders:Barry Rodewald
/*
* magicsound.c
*
* Magic Sound Board for the Aleste 520EX
*
*/
#include "emu.h"
#include "magicsound.h"
#include "includes/amstrad.h"
//**************************************************************************
// DEVICE DEFINITIONS
//**************************************************************************
const device_type AL_MAGICSOUND = &device_creator<al_magicsound_device>;
static MACHINE_CONFIG_FRAGMENT( al_magicsound )
MCFG_DEVICE_ADD( "dmac", AM9517A, XTAL_4MHz ) // CLK from expansion port
// According to the schematics, the TC pin (EOP on western chips) is connected to NMI on the expansion port.
// NMIs seem to occur too quickly when this is active, so either EOP is not triggered at the correct time, or
// the K1810WT37 is different to the i8237/AM9517A
//MCFG_I8237_OUT_EOP_CB(DEVWRITELINE("^", cpc_expansion_slot_device, nmi_w)) // MCFG_DEVCB_INVERT
MCFG_I8237_OUT_HREQ_CB(DEVWRITELINE("dmac", am9517a_device, hack_w))
MCFG_I8237_IN_MEMR_CB(READ8(al_magicsound_device,dma_read_byte))
MCFG_I8237_OUT_IOW_0_CB(WRITE8(al_magicsound_device,dma_write_byte))
MCFG_I8237_OUT_IOW_1_CB(WRITE8(al_magicsound_device,dma_write_byte))
MCFG_I8237_OUT_IOW_2_CB(WRITE8(al_magicsound_device,dma_write_byte))
MCFG_I8237_OUT_IOW_3_CB(WRITE8(al_magicsound_device,dma_write_byte))
MCFG_I8237_OUT_DACK_0_CB(WRITELINE(al_magicsound_device, dack0_w))
MCFG_I8237_OUT_DACK_1_CB(WRITELINE(al_magicsound_device, dack1_w))
MCFG_I8237_OUT_DACK_2_CB(WRITELINE(al_magicsound_device, dack2_w))
MCFG_I8237_OUT_DACK_3_CB(WRITELINE(al_magicsound_device, dack3_w))
// Timing does not seem to be correct.
// According to the schematics, the clock is from the clock pin on the expansion port (4MHz), and
// passes through an inverter to each CLK pin on both timers. This seems to be too fast.
// Timer outputs to SAM0/1/2/3 are sample clocks for each sound channel, D/A0 is the low bit of the channel select.
MCFG_DEVICE_ADD("timer1", PIT8254, 0)
MCFG_PIT8253_CLK0(XTAL_4MHz)
MCFG_PIT8253_OUT0_HANDLER(WRITELINE(al_magicsound_device,sam0_w))
MCFG_PIT8253_CLK1(XTAL_4MHz)
MCFG_PIT8253_OUT1_HANDLER(WRITELINE(al_magicsound_device,sam1_w))
MCFG_PIT8253_CLK2(XTAL_4MHz)
MCFG_PIT8253_OUT2_HANDLER(WRITELINE(al_magicsound_device,sam2_w))
MCFG_DEVICE_ADD("timer2", PIT8254, 0)
MCFG_PIT8253_CLK0(XTAL_4MHz)
MCFG_PIT8253_OUT0_HANDLER(WRITELINE(al_magicsound_device,sam3_w))
MCFG_PIT8253_CLK1(XTAL_4MHz)
MCFG_PIT8253_OUT1_HANDLER(WRITELINE(al_magicsound_device,da0_w))
MCFG_PIT8253_CLK2(XTAL_4MHz)
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_DAC_ADD("dac1")
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
// no pass-through(?)
MACHINE_CONFIG_END
machine_config_constructor al_magicsound_device::device_mconfig_additions() const
{
return MACHINE_CONFIG_NAME( al_magicsound );
}
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
al_magicsound_device::al_magicsound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
device_t(mconfig, AL_MAGICSOUND, "Magic Sound Board", tag, owner, clock, "al_magicsound", __FILE__),
device_cpc_expansion_card_interface(mconfig, *this),
m_dac1(*this,"dac1"),
m_dmac(*this,"dmac"),
m_timer1(*this,"timer1"),
m_timer2(*this,"timer2")
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void al_magicsound_device::device_start()
{
device_t* cpu = machine().device("maincpu");
address_space& space = cpu->memory().space(AS_IO);
m_slot = dynamic_cast<cpc_expansion_slot_device *>(owner());
space.install_readwrite_handler(0xf8d0,0xf8df,0,0,read8_delegate(FUNC(al_magicsound_device::dmac_r),this),write8_delegate(FUNC(al_magicsound_device::dmac_w),this));
space.install_write_handler(0xf9d0,0xf9df,0,0,write8_delegate(FUNC(al_magicsound_device::timer_w),this));
space.install_write_handler(0xfad0,0xfadf,0,0,write8_delegate(FUNC(al_magicsound_device::volume_w),this));
space.install_write_handler(0xfbd0,0xfbdf,0,0,write8_delegate(FUNC(al_magicsound_device::mapper_w),this));
m_ramptr = machine().device<ram_device>(":" RAM_TAG);
for(int x=0;x<4;x++)
{
save_item(NAME(m_output[x]),x);
}
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void al_magicsound_device::device_reset()
{
m_current_channel = -1;
m_current_output = 0;
set_timer_gate(false);
}
READ8_MEMBER(al_magicsound_device::dmac_r)
{
return m_dmac->read(space,offset);
}
WRITE8_MEMBER(al_magicsound_device::dmac_w)
{
m_dmac->write(space,offset,data);
}
WRITE8_MEMBER(al_magicsound_device::timer_w)
{
// can both PITs be selected at the same time?
if(offset & 0x08)
m_timer1->write(space,offset & 0x03,data);
if(offset & 0x04)
m_timer2->write(space,offset & 0x03,data);
}
WRITE8_MEMBER(al_magicsound_device::volume_w)
{
m_volume[offset & 0x03] = data & 0x3f;
}
WRITE8_MEMBER(al_magicsound_device::mapper_w)
{
UINT8 channel = (offset & 0x0c) >> 2;
UINT8 page = offset & 0x03;
m_page[channel][page] = (~(data) & 0x3f) * 0x4000;
set_timer_gate(true);
}
WRITE_LINE_MEMBER(al_magicsound_device::da0_w)
{
m_dac1->write_unsigned8(m_output[m_current_output++]);
if(m_current_output > 3)
m_current_output = 0;
}
WRITE_LINE_MEMBER(al_magicsound_device::dack0_w) { m_dack[0] = state; }
WRITE_LINE_MEMBER(al_magicsound_device::dack1_w) { m_dack[1] = state; }
WRITE_LINE_MEMBER(al_magicsound_device::dack2_w) { m_dack[2] = state; }
WRITE_LINE_MEMBER(al_magicsound_device::dack3_w) { m_dack[3] = state; }
WRITE_LINE_MEMBER(al_magicsound_device::sam0_w) { m_current_channel = 0; if(m_dack[0] && state) m_dmac->dreq0_w(1); }
WRITE_LINE_MEMBER(al_magicsound_device::sam1_w) { m_current_channel = 1; if(m_dack[1] && state) m_dmac->dreq1_w(1); }
WRITE_LINE_MEMBER(al_magicsound_device::sam2_w) { m_current_channel = 2; if(m_dack[2] && state) m_dmac->dreq2_w(1); }
WRITE_LINE_MEMBER(al_magicsound_device::sam3_w) { m_current_channel = 3; if(m_dack[3] && state) m_dmac->dreq3_w(1); }
READ8_MEMBER(al_magicsound_device::dma_read_byte)
{
UINT8 ret = 0xff;
UINT8 page = (offset & 0xc000) >> 14;
if(m_current_channel != -1)
ret = m_ramptr->read(m_page[m_current_channel][page] + (offset & 0x3fff));
return ret;
}
WRITE8_MEMBER(al_magicsound_device::dma_write_byte)
{
m_output[m_current_channel] = data;
}
void al_magicsound_device::set_timer_gate(bool state)
{
m_timer1->write_gate0(state);
m_timer1->write_gate1(state);
m_timer1->write_gate2(state);
m_timer2->write_gate0(state);
m_timer2->write_gate1(state);
m_timer2->write_gate2(state);
}

View File

@ -0,0 +1,91 @@
// license:BSD-3-Clause
// copyright-holders:Barry Rodewald
/*
* magicsound.h
*
* Magic Sound Board for the Aleste 520EX
*
* DMA-based 4-channel sound board
*
* 1x K1810WT37 DMA controller (i8237/AM9517A)
* 2x K1810WT54 programmable timers (i8254)
* 1x K1118PA1 DAC (MC10318)
*
* I/O Ports:
* FxDx: selects the board
* F8Dx: DMA controller (R/w)
* F9Dx: PIT timers (A2 active for channels 0-2, A3 active for channels 3-5) (W/O)
* FADx: Volume control (A1-A0 = channel) (W/O, 6-bit)
* FBDx: Mapper (A1-A0 = mapper page number, A3-A2 = channel, D5-D0 = inverted page number) (W/O)
*
* Further info available here: http://cpcwiki.eu/index.php/Magic_Sound_Board
*
*/
#ifndef MAGICSOUND_H_
#define MAGICSOUND_H_
#include "emu.h"
#include "cpcexp.h"
#include "sound/dmadac.h"
#include "sound/dac.h"
#include "machine/am9517a.h"
#include "machine/pit8253.h"
#include "machine/ram.h"
class al_magicsound_device : public device_t,
public device_cpc_expansion_card_interface
{
public:
// construction/destruction
al_magicsound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
// optional information overrides
virtual machine_config_constructor device_mconfig_additions() const;
DECLARE_READ8_MEMBER(dmac_r);
DECLARE_WRITE8_MEMBER(dmac_w);
DECLARE_WRITE8_MEMBER(timer_w);
DECLARE_WRITE8_MEMBER(volume_w);
DECLARE_WRITE8_MEMBER(mapper_w);
DECLARE_WRITE_LINE_MEMBER(da0_w);
DECLARE_READ8_MEMBER(dma_read_byte);
DECLARE_WRITE8_MEMBER(dma_write_byte);
DECLARE_WRITE_LINE_MEMBER(dack0_w);
DECLARE_WRITE_LINE_MEMBER(dack1_w);
DECLARE_WRITE_LINE_MEMBER(dack2_w);
DECLARE_WRITE_LINE_MEMBER(dack3_w);
DECLARE_WRITE_LINE_MEMBER(sam0_w);
DECLARE_WRITE_LINE_MEMBER(sam1_w);
DECLARE_WRITE_LINE_MEMBER(sam2_w);
DECLARE_WRITE_LINE_MEMBER(sam3_w);
protected:
// device-level overrides
virtual void device_start();
virtual void device_reset();
private:
cpc_expansion_slot_device *m_slot;
required_device<dac_device> m_dac1;
required_device<am9517a_device> m_dmac;
required_device<pit8254_device> m_timer1;
required_device<pit8254_device> m_timer2;
void set_timer_gate(bool state);
UINT8 m_volume[4];
UINT32 m_page[4][4];
UINT8 m_output[4];
bool m_dack[4];
INT8 m_current_channel;
ram_device* m_ramptr;
UINT8 m_current_output;
};
// device type definition
extern const device_type AL_MAGICSOUND;
#endif /* MAGICSOUND_H_ */

View File

@ -846,6 +846,23 @@ SLOT_INTERFACE_START(cpcplus_exp_cards)
SLOT_INTERFACE("hd20", CPC_HD20)
SLOT_INTERFACE_END
SLOT_INTERFACE_START(aleste_exp_cards)
SLOT_INTERFACE("ssa1", CPC_SSA1)
SLOT_INTERFACE("dkspeech", CPC_DKSPEECH)
SLOT_INTERFACE("rom", CPC_ROM)
SLOT_INTERFACE("multiface2", CPC_MFACE2)
SLOT_INTERFACE("pds", CPC_PDS)
SLOT_INTERFACE("rs232", CPC_RS232)
SLOT_INTERFACE("amsrs232", CPC_RS232_AMS)
SLOT_INTERFACE("sf2", CPC_SYMBIFACE2)
SLOT_INTERFACE("amdrum", CPC_AMDRUM)
SLOT_INTERFACE("playcity", CPC_PLAYCITY)
SLOT_INTERFACE("smartwatch", CPC_SMARTWATCH)
SLOT_INTERFACE("brunword4", CPC_BRUNWORD_MK4)
SLOT_INTERFACE("hd20", CPC_HD20)
SLOT_INTERFACE("magicsound", AL_MAGICSOUND)
SLOT_INTERFACE_END
SLOT_INTERFACE_START(amstrad_centronics_devices)
SLOT_INTERFACE("pl80", COMX_PL80)
SLOT_INTERFACE("ex800", EPSON_EX800)
@ -1128,6 +1145,14 @@ static MACHINE_CONFIG_DERIVED( aleste, cpc6128 )
MCFG_DEVICE_REMOVE("upd765")
MCFG_I8272A_ADD("upd765", true)
MCFG_DEVICE_REMOVE("exp")
MCFG_DEVICE_ADD("exp", CPC_EXPANSION_SLOT, 0)
MCFG_DEVICE_SLOT_INTERFACE(aleste_exp_cards, NULL, false)
MCFG_CPC_EXPANSION_SLOT_OUT_IRQ_CB(INPUTLINE("maincpu", 0))
MCFG_CPC_EXPANSION_SLOT_OUT_NMI_CB(INPUTLINE("maincpu", INPUT_LINE_NMI))
MCFG_CPC_EXPANSION_SLOT_OUT_ROMDIS_CB(WRITELINE(amstrad_state, cpc_romdis)) // ROMDIS
MCFG_CPC_EXPANSION_SLOT_ROM_SELECT(WRITE8(amstrad_state,rom_select))
MCFG_FLOPPY_DRIVE_ADD("upd765:0", aleste_floppies, "35dd", amstrad_state::aleste_floppy_formats)
MCFG_FLOPPY_DRIVE_ADD("upd765:1", aleste_floppies, "35dd", amstrad_state::aleste_floppy_formats)

View File

@ -29,6 +29,7 @@
#include "bus/cpc/smartwatch.h"
#include "bus/cpc/brunword4.h"
#include "bus/cpc/hd20.h"
#include "bus/cpc/magicsound.h"
#include "machine/ram.h"
#include "imagedev/cassette.h"
#include "bus/centronics/ctronics.h"

View File

@ -1694,8 +1694,8 @@ In the 464+ and 6128+ this function is performed by the ASIC or a memory expansi
WRITE8_MEMBER(amstrad_state::aleste_msx_mapper)
{
int page = (offset & 0x0300) >> 8;
int ramptr = (data & 0x1f) * 0x4000;
int rampage = data & 0x1f;
int ramptr = (data & 0x3f) * 0x4000;
int rampage = data & 0x3f;
int function = (data & 0xc0) >> 6;
UINT8 *ram = m_ram->pointer();