AICA: Implemented DMA [Angelo Salese]

This commit is contained in:
Angelo Salese 2013-08-28 18:49:04 +00:00
parent 268de4b9d0
commit 3fdc34d03b
4 changed files with 136 additions and 25 deletions

View File

@ -194,9 +194,14 @@ struct aica_state
emu_timer *timerA, *timerB, *timerC;
// DMA stuff
UINT32 aica_dmea;
UINT16 aica_drga;
UINT16 aica_dtlg;
struct{
UINT32 dmea;
UINT16 drga;
UINT16 dlg;
UINT8 dgate;
UINT8 ddir;
}dma;
int ARTABLE[64], DRTABLE[64];
@ -204,6 +209,8 @@ struct aica_state
device_t *device;
};
static void aica_exec_dma(aica_state *aica,address_space &space); /*state DMA transfer function*/
static const float SDLT[16]={-1000000.0,-42.0,-39.0,-36.0,-33.0,-30.0,-27.0,-24.0,-21.0,-18.0,-15.0,-12.0,-9.0,-6.0,-3.0,0.0};
static stream_sample_t *bufferl;
@ -712,6 +719,32 @@ static void AICA_UpdateReg(aica_state *AICA, address_space &space, int reg)
case 0x16:
case 0x17:
break;
case 0x80:
case 0x81:
AICA->dma.dmea = ((AICA->udata.data[0x80/2] & 0xfe00) << 7) | (AICA->dma.dmea & 0xfffc);
/* TODO: $TSCD - MRWINH regs */
break;
case 0x84:
case 0x85:
AICA->dma.dmea = (AICA->udata.data[0x84/2] & 0xfffc) | (AICA->dma.dmea & 0x7f0000);
break;
case 0x88:
case 0x89:
AICA->dma.drga = (AICA->udata.data[0x88/2] & 0x7ffc);
AICA->dma.dgate = (AICA->udata.data[0x88/2] & 0x8000) >> 15;
break;
case 0x8c:
case 0x8d:
AICA->dma.dlg = (AICA->udata.data[0x8c/2] & 0x7ffc);
AICA->dma.ddir = (AICA->udata.data[0x8c/2] & 0x8000) >> 15;
if(AICA->udata.data[0x8c/2] & 1) // dexe
aica_exec_dma(AICA,space);
break;
case 0x90:
case 0x91:
if(AICA->Master)
@ -920,6 +953,7 @@ static void AICA_w16(aica_state *AICA,address_space &space,unsigned int addr,uns
// printf("%x to AICA global @ %x\n", val, addr & 0xff);
*((unsigned short *) (AICA->udata.datab+((addr&0xff)))) = val;
AICA_UpdateReg(AICA, space, addr&0xff);
}
else if (addr == 0x2d00)
{
@ -986,6 +1020,16 @@ static unsigned short AICA_r16(aica_state *AICA, address_space &space, unsigned
return AICA->IRQR;
}
}
else
{
if(addr<0x3200) //COEF
v= *((unsigned short *) (AICA->DSP.COEF+(addr-0x3000)/2));
else if(addr<0x3400)
v= *((unsigned short *) (AICA->DSP.MADRS+(addr-0x3200)/2));
else if(addr<0x3c00)
v= *((unsigned short *) (AICA->DSP.MPRO+(addr-0x3400)/2));
}
// else if (addr<0x700)
// v=AICA->RINGBUF[(addr-0x600)/2];
return v;
@ -1250,6 +1294,85 @@ static void AICA_DoMasterSamples(aica_state *AICA, int nsamples)
}
}
static void aica_exec_dma(aica_state *aica,address_space &space)
{
static UINT16 tmp_dma[4];
int i;
printf("AICA: DMA transfer START\n"
"DMEA: %08x DRGA: %08x DLG: %04x\n"
"DGATE: %d DDIR: %d\n",aica->dma.dmea,aica->dma.drga,aica->dma.dlg,aica->dma.dgate,aica->dma.ddir);
/* Copy the dma values in a temp storage for resuming later */
/* (DMA *can't* overwrite his parameters). */
if(!(aica->dma.ddir))
{
for(i=0;i<4;i++)
tmp_dma[i] = aica->udata.data[(0x80+(i*4))/2];
}
/* TODO: don't know if params auto-updates, I guess not ... */
if(aica->dma.ddir)
{
if(aica->dma.dgate)
{
for(i=0;i < aica->dma.dlg;i+=2)
{
aica->AICARAM[aica->dma.dmea] = 0;
aica->AICARAM[aica->dma.dmea+1] = 0;
aica->dma.dmea+=2;
}
}
else
{
for(i=0;i < aica->dma.dlg;i+=2)
{
UINT16 tmp;
tmp = AICA_r16(aica, space, aica->dma.drga);;
aica->AICARAM[aica->dma.dmea] = tmp & 0xff;
aica->AICARAM[aica->dma.dmea+1] = tmp>>8;
aica->dma.dmea+=4;
aica->dma.drga+=4;
}
}
}
else
{
if(aica->dma.dgate)
{
for(i=0;i < aica->dma.dlg;i+=2)
{
AICA_w16(aica, space, aica->dma.drga, 0);
aica->dma.drga+=4;
}
}
else
{
for(i=0;i < aica->dma.dlg;i+=2)
{
UINT16 tmp;
tmp = aica->AICARAM[aica->dma.dmea];
tmp|= aica->AICARAM[aica->dma.dmea+1]<<8;
AICA_w16(aica, space, aica->dma.drga, tmp);
aica->dma.dmea+=4;
aica->dma.drga+=4;
}
}
}
/*Resume the values*/
if(!(aica->dma.ddir))
{
for(i=0;i<4;i++)
aica->udata.data[(0x80+(i*4))/2] = tmp_dma[i];
}
/* Job done, clear DEXE */
aica->udata.data[0x8c/2] &= ~1;
/* request a dma end irq (TBD) */
// ...
}
#ifdef UNUSED_FUNCTION
static int AICA_IRQCB(void *param)
{

View File

@ -57,8 +57,8 @@ class dc_state : public driver_device
TIMER_CALLBACK_MEMBER(ch2_dma_irq);
TIMER_CALLBACK_MEMBER(yuv_fifo_irq);
TIMER_CALLBACK_MEMBER(dc_rtc_increment);
DECLARE_READ64_MEMBER(dc_aica_reg_r);
DECLARE_WRITE64_MEMBER(dc_aica_reg_w);
DECLARE_READ32_MEMBER(dc_aica_reg_r);
DECLARE_WRITE32_MEMBER(dc_aica_reg_w);
DECLARE_READ32_MEMBER(dc_arm_aica_r);
DECLARE_WRITE32_MEMBER(dc_arm_aica_w);
void wave_dma_execute(address_space &space);

View File

@ -762,30 +762,18 @@ void dc_state::machine_reset()
dc_sysctrl_regs[SB_SBREV] = 0x0b;
}
READ64_MEMBER(dc_state::dc_aica_reg_r)
READ32_MEMBER(dc_state::dc_aica_reg_r)
{
//int reg;
UINT64 shift;
/*reg = */decode_reg32_64(offset, mem_mask, &shift);
// mame_printf_verbose("AICA REG: [%08x] read %" I64FMT "x, mask %" I64FMT "x\n", 0x700000+reg*4, (UINT64)offset, mem_mask);
return (UINT64) aica_r(machine().device("aica"), space, offset*2, 0xffff)<<shift;
return aica_r(machine().device("aica"), space, offset*2, 0xffff);
}
WRITE64_MEMBER(dc_state::dc_aica_reg_w)
WRITE32_MEMBER(dc_state::dc_aica_reg_w)
{
int reg;
UINT64 shift;
UINT32 dat;
reg = decode_reg32_64(offset, mem_mask, &shift);
dat = (UINT32)(data >> shift);
if (reg == (0x2c00/4))
if (offset == (0x2c00/4))
{
if (dat & 1)
if (data & 1)
{
/* halt the ARM7 */
m_soundcpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
@ -797,9 +785,9 @@ WRITE64_MEMBER(dc_state::dc_aica_reg_w)
}
}
aica_w(machine().device("aica"), space, offset*2, dat, shift ? ((mem_mask>>32)&0xffff) : (mem_mask & 0xffff));
aica_w(machine().device("aica"), space, offset*2, data, 0xffff);
// mame_printf_verbose("AICA REG: [%08x=%x] write %" I64FMT "x to %x, mask %" I64FMT "x\n", 0x700000+reg*4, dat, data, offset, mem_mask);
// mame_printf_verbose("AICA REG: [%08x=%x] write %x to %x, mask %" I64FMT "x\n", 0x700000+reg*4, data, offset, mem_mask);
}
READ32_MEMBER(dc_state::dc_arm_aica_r)

View File

@ -371,7 +371,7 @@ static ADDRESS_MAP_START( dc_map, AS_PROGRAM, 64, dc_cons_state )
AM_RANGE(0x005f7c00, 0x005f7cff) AM_DEVICE32("powervr2", powervr2_device, pd_dma_map, U64(0xffffffffffffffff))
AM_RANGE(0x005f8000, 0x005f9fff) AM_DEVICE32("powervr2", powervr2_device, ta_map, U64(0xffffffffffffffff))
AM_RANGE(0x00600000, 0x006007ff) AM_READWRITE(dc_modem_r, dc_modem_w )
AM_RANGE(0x00700000, 0x00707fff) AM_READWRITE(dc_aica_reg_r, dc_aica_reg_w )
AM_RANGE(0x00700000, 0x00707fff) AM_READWRITE32(dc_aica_reg_r, dc_aica_reg_w, U64(0xffffffffffffffff))
AM_RANGE(0x00710000, 0x0071000f) AM_MIRROR(0x02000000) AM_READWRITE32(dc_rtc_r, dc_rtc_w, U64(0xffffffffffffffff) )
AM_RANGE(0x00800000, 0x009fffff) AM_READWRITE(dc_arm_r, dc_arm_w )