|
|
| version 1.2, 2003/10/20 06:36:33 | version 1.8, 2004/03/29 14:19:25 |
|---|---|
| Line 1 | Line 1 |
| #include "compiler.h" | #include "compiler.h" |
| #include "memory.h" | #include "cpucore.h" |
| #include "pccore.h" | #include "pccore.h" |
| #include "iocore.h" | #include "iocore.h" |
| #include "sound.h" | #include "sound.h" |
| Line 8 | Line 8 |
| CS4231CFG cs4231cfg; | CS4231CFG cs4231cfg; |
| enum { | |
| CS4231REG_LINPUT = 0x00, | |
| CS4231REG_RINPUT = 0x01, | |
| CS4231REG_AUX1L = 0x02, | |
| CS4231REG_AUX1R = 0x03, | |
| CS4231REG_AUX2L = 0x04, | |
| CS4231REG_AUX2R = 0x05, | |
| CS4231REG_LOUTPUT = 0x06, | |
| CS4231REG_ROUTPUT = 0x07, | |
| CS4231REG_PLAYFMT = 0x08, | |
| CS4231REG_INTERFACE = 0x09, | |
| CS4231REG_PINCTRL = 0x0a, | |
| CS4231REG_TESTINIT = 0x0b, | |
| CS4231REG_MISCINFO = 0x0c, | |
| CS4231REG_LOOPBACK = 0x0d, | |
| CS4231REG_PLAYCNTM = 0x0e, | |
| CS4231REG_PLAYCNTL = 0x0f, | |
| CS4231REG_FEATURE1 = 0x10, | |
| CS4231REG_FEATURE2 = 0x11, | |
| CS4231REG_LLINEIN = 0x12, | |
| CS4231REG_RLINEIN = 0x13, | |
| CS4231REG_TIMERL = 0x14, | |
| CS4231REG_TIMERH = 0x15, | |
| CS4231REG_IRQSTAT = 0x18, | |
| CS4231REG_VERSION = 0x19, | |
| CS4231REG_MONOCTRL = 0x1a, | |
| CS4231REG_RECFMT = 0x1c, | |
| CS4231REG_PLAYFREQ = 0x1d, | |
| CS4231REG_RECCNTM = 0x1e, | |
| CS4231REG_RECCNTL = 0x1f | |
| }; | |
| static const UINT32 cs4231xtal64[2] = {24576000/64, 16934400/64}; | |
| static const UINT8 cs4231cnt64[8] = { | |
| 3072/64, // 8000/ 5510 | |
| 1536/64, // 16000/11025 | |
| 896/64, // 27420/18900 | |
| 768/64, // 32000/22050 | |
| 448/64, // 54840/37800 | |
| 384/64, // 64000/44100 | |
| 512/64, // 48000/33075 | |
| 2560/64}; // 9600/ 6620 | |
| static const UINT16 cs4231samprate[] = { | // 640:441 |
| 8000, 5510, 16000, 11025, | |
| 27420, 18900, 32000, 22050, | |
| 54840, 37800, 64000, 44100, | |
| 48000, 33075, 9600, 6620}; | |
| static const BYTE dmach[] = {0xff, 0x00, 0x01, 0x03, 0xff, 0xff, 0xff, 0xff}; | |
| static const BYTE dmairq[] = {0xff, 0x03, 0x06, 0x0a, 0x0c, 0xff, 0xff, 0xff}; | |
| void cs4231_initialize(UINT rate) { | void cs4231_initialize(UINT rate) { |
| Line 29 void cs4231_setvol(UINT vol) { | Line 67 void cs4231_setvol(UINT vol) { |
| (void)vol; | (void)vol; |
| } | } |
| void cs4231_dma(NEVENTITEM item) { | void cs4231_dma(NEVENTITEM item) { |
| BYTE ret; | DMACH dmach; |
| UINT rem; | |
| UINT pos; | |
| UINT size; | |
| UINT r; | |
| SINT32 cnt; | SINT32 cnt; |
| if (item->flag & NEVENT_SETEVENT) { | if (item->flag & NEVENT_SETEVENT) { |
| if (dmac.dmach[0].leng.w) { | if (cs4231.dmach != 0xff) { |
| sound_sync(); | sound_sync(); |
| ret = cs4231.proc(); | dmach = dmac.dmach + cs4231.dmach; |
| if ((ret) && (cs4231.reg.pinctrl & 2)) { | if (cs4231.bufsize > cs4231.bufdatas) { |
| dmac.dmach[0].leng.w = 0; | rem = cs4231.bufsize - cs4231.bufdatas; |
| cs4231.intflag = 1; | pos = (cs4231.bufpos + cs4231.bufdatas) & CS4231_BUFMASK; |
| pic_setirq(0x0c); | size = min(rem, CS4231_BUFFERS - pos); |
| r = dmac_getdatas(dmach, cs4231.buffer + pos, size); | |
| rem -= r; | |
| cs4231.bufdatas += r; | |
| if (r != size) { | |
| r = dmac_getdatas(dmach, cs4231.buffer, rem); | |
| cs4231.bufdatas += r; | |
| } | |
| } | |
| if ((dmach->leng.w) && (cs4231cfg.rate)) { | |
| cnt = pccore.realclock * 16 / cs4231cfg.rate; | |
| nevent_set(NEVENT_CS4231, cnt, cs4231_dma, NEVENT_RELATIVE); | |
| } | } |
| } | |
| if (cs4231cfg.rate) { | |
| cnt = pc.realclock * 16 / cs4231cfg.rate; | |
| nevent_set(NEVENT_CS4231, cnt, cs4231_dma, NEVENT_RELATIVE); | |
| } | } |
| } | } |
| (void)item; | (void)item; |
| } | } |
| BYTE DMACCALL cs4231dmafunc(BYTE func) { | void cs4231_datasend(REG8 dat) { |
| UINT pos; | |
| if (cs4231.reg.iface & 0x40) { // PIO play enable | |
| if (cs4231.bufsize <= cs4231.bufdatas) { | |
| sound_sync(); | |
| } | |
| if (cs4231.bufsize > cs4231.bufdatas) { | |
| pos = (cs4231.bufpos + cs4231.bufdatas) & CS4231_BUFMASK; | |
| cs4231.buffer[pos] = dat; | |
| cs4231.bufdatas++; | |
| } | |
| } | |
| } | |
| REG8 DMACCALL cs4231dmafunc(REG8 func) { | |
| SINT32 cnt; | SINT32 cnt; |
| switch(func) { | switch(func) { |
| case DMAEXT_START: | case DMAEXT_START: |
| if (cs4231cfg.rate) { | if (cs4231cfg.rate) { |
| cnt = pc.realclock * 16 / cs4231cfg.rate; | cnt = pccore.realclock * 16 / cs4231cfg.rate; |
| nevent_set(NEVENT_CS4231, cnt, cs4231_dma, NEVENT_ABSOLUTE); | nevent_set(NEVENT_CS4231, cnt, cs4231_dma, NEVENT_ABSOLUTE); |
| } | } |
| break; | break; |
| case DMAEXT_END: | |
| if ((cs4231.reg.pinctrl & 2) && (cs4231.dmairq != 0xff)) { | |
| cs4231.intflag = 1; | |
| pic_setirq(cs4231.dmairq); | |
| } | |
| break; | |
| case DMAEXT_BREAK: | case DMAEXT_BREAK: |
| nevent_reset(NEVENT_CS4231); | nevent_reset(NEVENT_CS4231); |
| break; | break; |
| Line 75 BYTE DMACCALL cs4231dmafunc(BYTE func) { | Line 146 BYTE DMACCALL cs4231dmafunc(BYTE func) { |
| void cs4231_reset(void) { | void cs4231_reset(void) { |
| ZeroMemory(&cs4231, sizeof(cs4231)); | ZeroMemory(&cs4231, sizeof(cs4231)); |
| cs4231.proc = cs4231_nodecode; | cs4231.bufsize = CS4231_BUFFERS; |
| // cs4231.proc = cs4231_nodecode; | |
| cs4231.port = 0xffff; | cs4231.port = 0xffff; |
| cs4231.dmach = 0xff; | cs4231.dmach = 0xff; |
| cs4231.dmairq = 0xff; | cs4231.dmairq = 0xff; |
| Line 85 void cs4231_update(void) { | Line 157 void cs4231_update(void) { |
| } | } |
| void cs4231_control(UINT index, BYTE value) { | static void setdataalign(void) { |
| *(((BYTE *)(&cs4231.reg)) + index) = value; | UINT step; |
| step = (0 - cs4231.bufpos) & 3; | |
| if (step) { | |
| cs4231.bufpos += step; | |
| cs4231.bufdatas -= min(step, cs4231.bufdatas); | |
| } | |
| cs4231.bufdatas &= ~3; | |
| } | |
| void cs4231_control(UINT index, REG8 dat) { | |
| UINT8 modify; | |
| DMACH dmach; | |
| modify = ((BYTE *)&cs4231.reg)[index] ^ dat; | |
| ((BYTE *)&cs4231.reg)[index] = dat; | |
| switch(index) { | switch(index) { |
| case 8: // playback data format | case CS4231REG_PLAYFMT: |
| cs4231.proc = cs4231dec[value >> 4]; | if (modify & 0xf0) { |
| cs4231.step = cs4231samprate[value & 0x0f]; | setdataalign(); |
| } | |
| if (modify & 0x0f) { | |
| if (cs4231cfg.rate) { | |
| UINT32 r; | |
| r = cs4231xtal64[dat & 1] / cs4231cnt64[(dat >> 1) & 7]; | |
| TRACEOUT(("samprate = %d", r)); | |
| r <<= 12; | |
| r /= cs4231cfg.rate; | |
| cs4231.step12 = r; | |
| TRACEOUT(("step12 = %d", r)); | |
| } | |
| else { | |
| cs4231.step12 = 0; | |
| } | |
| } | |
| break; | break; |
| case 9: | case CS4231REG_INTERFACE: |
| if ((value & 0x5) == 0x5) { | if (modify & 5) { |
| dmac.dmach[0].ready = 1; | if (cs4231.dmach != 0xff) { |
| } | dmach = dmac.dmach + cs4231.dmach; |
| else { | if ((dat & 0x5) == 0x5) { |
| dmac.dmach[0].ready = 0; | dmach->ready = 1; |
| } | |
| else { | |
| dmach->ready = 0; | |
| } | |
| dmac_check(); | |
| } | |
| if (!(dat & 1)) { // stop! | |
| cs4231.pos12 = 0; | |
| } | |
| } | } |
| dmac_check(); | |
| break; | break; |
| } | } |
| } | } |