AD1848 clean-ups and fixed DMA over a 16-bit channel.

This commit is contained in:
OBattler
2024-04-23 03:14:12 +02:00
parent 10fd8fb004
commit 3dbb0daa17

View File

@@ -63,46 +63,85 @@ ad1848_updatevolmask(ad1848_t *ad1848)
ad1848->wave_vol_mask = 0x7f;
}
static double
ad1848_get_default_freq(ad1848_t *ad1848)
{
double freq = (ad1848->regs[8] & 1) ? 16934400.0 : 24576000.0;
switch ((ad1848->regs[8] >> 1) & 7) {
default:
break;
case 0:
freq /= 3072.0;
break;
case 1:
freq /= 1536.0;
break;
case 2:
freq /= 896.0;
break;
case 3:
freq /= 768.0;
break;
case 4:
freq /= 448.0;
break;
case 5:
freq /= 384.0;
break;
case 6:
freq /= 512.0;
break;
case 7:
freq /= 2560.0;
break;
}
return freq;
}
static void
ad1848_updatefreq(ad1848_t *ad1848)
{
double freq = 0.0;
uint8_t set = 0;
double freq;
if (ad1848->type >= AD1848_TYPE_CS4235) {
if (ad1848->xregs[11] & 0x20) {
freq = 16934400LL;
freq = 16934400.0;
switch (ad1848->xregs[13]) {
default:
freq /= 16.0 * MAX(ad1848->xregs[13], 21);
break;
case 1:
freq /= 353;
freq /= 353.0;
break;
case 2:
freq /= 529;
freq /= 529.0;
break;
case 3:
freq /= 617;
freq /= 617.0;
break;
case 4:
freq /= 1058;
freq /= 1058.0;
break;
case 5:
freq /= 1764;
freq /= 1764.0;
break;
case 6:
freq /= 2117;
freq /= 2117.0;
break;
case 7:
freq /= 2558;
break;
default:
freq /= 16 * MAX(ad1848->xregs[13], 21);
freq /= 2558.0;
break;
}
set = 1;
} else if (ad1848->regs[22] & 0x80) {
freq = (ad1848->regs[22] & 1) ? 33868800LL : 49152000LL;
set = (ad1848->regs[22] >> 1) & 0x3f;
const uint8_t set = (ad1848->regs[22] >> 1) & 0x3f;
freq = (ad1848->regs[22] & 1) ? 33868800.0 : 49152000.0;
switch (ad1848->regs[10] & 0x30) {
default:
break;
case 0x00:
freq /= 128 * set;
break;
@@ -112,48 +151,13 @@ ad1848_updatefreq(ad1848_t *ad1848)
case 0x20:
freq /= 256 * set;
break;
}
} else
freq = ad1848_get_default_freq(ad1848);
} else
freq = ad1848_get_default_freq(ad1848);
default:
break;
}
set = 1;
}
}
if (!set) {
freq = (ad1848->regs[8] & 1) ? 16934400LL : 24576000LL;
switch ((ad1848->regs[8] >> 1) & 7) {
case 0:
freq /= 3072;
break;
case 1:
freq /= 1536;
break;
case 2:
freq /= 896;
break;
case 3:
freq /= 768;
break;
case 4:
freq /= 448;
break;
case 5:
freq /= 384;
break;
case 6:
freq /= 512;
break;
case 7:
freq /= 2560;
break;
default:
break;
}
}
ad1848->freq = freq;
ad1848->freq = (int) trunc(freq);
ad1848->timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) ad1848->freq));
}
@@ -251,6 +255,7 @@ ad1848_write(uint16_t addr, uint8_t val, void *priv)
case 9:
if (!ad1848->enable && (val & 0x41) == 0x01) {
ad1848->adpcm_pos = 0;
ad1848->dma_ff = 0;
if (ad1848->timer_latch)
timer_set_delay_u64(&ad1848->timer_count, ad1848->timer_latch);
else
@@ -450,18 +455,32 @@ static int16_t
ad1848_process_mulaw(uint8_t byte)
{
byte = ~byte;
int16_t dec = ((byte & 0x0f) << 3) + 0x84;
dec <<= (byte & 0x70) >> 4;
return (byte & 0x80) ? (0x84 - dec) : (dec - 0x84);
int temp = (((byte & 0x0f) << 3) + 0x84);
int16_t dec;
temp <<= ((byte & 0x70) >> 4);
temp = (byte & 0x80) ? (0x84 - temp) : (temp - 0x84);
if (temp > 32767)
dec = 32767;
else if (temp < -32768)
dec = -32768;
else
dec = (int16_t) temp;
return dec;
}
static int16_t
ad1848_process_alaw(uint8_t byte)
{
byte ^= 0x55;
int16_t dec = (byte & 0x0f) << 4;
int seg = (byte & 0x70) >> 4;
int dec = ((byte & 0x0f) << 4);;
const int seg = (int) ((byte & 0x70) >> 4);
switch (seg) {
default:
dec |= 0x108;
dec <<= seg - 1;
break;
case 0:
dec |= 0x8;
break;
@@ -469,13 +488,34 @@ ad1848_process_alaw(uint8_t byte)
case 1:
dec |= 0x108;
break;
default:
dec |= 0x108;
dec <<= seg - 1;
break;
}
return (byte & 0x80) ? dec : -dec;
dec = (byte & 0x80) ? dec : -dec;
return (int16_t) dec;
}
static uint32_t
ad1848_dma_channel_read(ad1848_t *ad1848, int channel)
{
uint32_t ret;
if (channel >= 4) {
if (ad1848->dma_ff) {
ret = (ad1848->dma_data & 0xff00) >> 8;
ret |= (ad1848->dma_data & 0xffff0000);
} else {
ad1848->dma_data = dma_channel_read(channel);
if (ad1848->dma_data == DMA_NODATA)
return DMA_NODATA;
ret = ad1848->dma_data & 0xff;
}
ad1848->dma_ff = !ad1848->dma_ff;
} else
ret = dma_channel_read(channel);
return ret;
}
static int16_t
@@ -485,7 +525,7 @@ ad1848_process_adpcm(ad1848_t *ad1848)
if (ad1848->adpcm_pos++ & 1) {
temp = (ad1848->adpcm_data & 0x0f) + ad1848->adpcm_step;
} else {
ad1848->adpcm_data = dma_channel_read(ad1848->dma);
ad1848->adpcm_data = (int) (ad1848_dma_channel_read(ad1848, ad1848->dma) & 0xffff);
temp = (ad1848->adpcm_data >> 4) + ad1848->adpcm_step;
}
if (temp < 0)
@@ -499,9 +539,9 @@ ad1848_process_adpcm(ad1848_t *ad1848)
else if (ad1848->adpcm_ref < 0x00)
ad1848->adpcm_ref = 0x00;
ad1848->adpcm_step = (ad1848->adpcm_step + adjustMap4[temp]) & 0xff;
ad1848->adpcm_step = (int8_t) ((ad1848->adpcm_step + adjustMap4[temp]) & 0xff);
return (ad1848->adpcm_ref ^ 0x80) << 8;
return (int16_t) ((ad1848->adpcm_ref ^ 0x80) << 8);
}
static void
@@ -521,42 +561,42 @@ ad1848_poll(void *priv)
switch (ad1848->regs[8] & ad1848->fmt_mask) {
case 0x00: /* Mono, 8-bit PCM */
ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) << 8;
ad1848->out_l = ad1848->out_r = (int16_t) ((ad1848_dma_channel_read(ad1848, ad1848->dma) ^ 0x80) << 8);
break;
case 0x10: /* Stereo, 8-bit PCM */
ad1848->out_l = (dma_channel_read(ad1848->dma) ^ 0x80) << 8;
ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) << 8;
ad1848->out_l = (int16_t) ((ad1848_dma_channel_read(ad1848, ad1848->dma) ^ 0x80) << 8);
ad1848->out_r = (int16_t) ((ad1848_dma_channel_read(ad1848, ad1848->dma) ^ 0x80) << 8);
break;
case 0x20: /* Mono, 8-bit Mu-Law */
ad1848->out_l = ad1848->out_r = ad1848_process_mulaw(dma_channel_read(ad1848->dma));
ad1848->out_l = ad1848->out_r = ad1848_process_mulaw(ad1848_dma_channel_read(ad1848, ad1848->dma));
break;
case 0x30: /* Stereo, 8-bit Mu-Law */
ad1848->out_l = ad1848_process_mulaw(dma_channel_read(ad1848->dma));
ad1848->out_r = ad1848_process_mulaw(dma_channel_read(ad1848->dma));
ad1848->out_l = ad1848_process_mulaw(ad1848_dma_channel_read(ad1848, ad1848->dma));
ad1848->out_r = ad1848_process_mulaw(ad1848_dma_channel_read(ad1848, ad1848->dma));
break;
case 0x40: /* Mono, 16-bit PCM little endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp;
temp = (int32_t) ad1848_dma_channel_read(ad1848, ad1848->dma);
ad1848->out_l = ad1848->out_r = (int16_t) ((ad1848_dma_channel_read(ad1848, ad1848->dma) << 8) | temp);
break;
case 0x50: /* Stereo, 16-bit PCM little endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = (dma_channel_read(ad1848->dma) << 8) | temp;
temp = dma_channel_read(ad1848->dma);
ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp;
temp = (int32_t) ad1848_dma_channel_read(ad1848, ad1848->dma);
ad1848->out_l = (int16_t) ((ad1848_dma_channel_read(ad1848, ad1848->dma) << 8) | temp);
temp = (int32_t) ad1848_dma_channel_read(ad1848, ad1848->dma);
ad1848->out_r = (int16_t) ((ad1848_dma_channel_read(ad1848, ad1848->dma) << 8) | temp);
break;
case 0x60: /* Mono, 8-bit A-Law */
ad1848->out_l = ad1848->out_r = ad1848_process_alaw(dma_channel_read(ad1848->dma));
ad1848->out_l = ad1848->out_r = ad1848_process_alaw(ad1848_dma_channel_read(ad1848, ad1848->dma));
break;
case 0x70: /* Stereo, 8-bit A-Law */
ad1848->out_l = ad1848_process_alaw(dma_channel_read(ad1848->dma));
ad1848->out_r = ad1848_process_alaw(dma_channel_read(ad1848->dma));
ad1848->out_l = ad1848_process_alaw(ad1848_dma_channel_read(ad1848, ad1848->dma));
ad1848->out_r = ad1848_process_alaw(ad1848_dma_channel_read(ad1848, ad1848->dma));
break;
/* 0x80 and 0x90 reserved */
@@ -571,15 +611,15 @@ ad1848_poll(void *priv)
break;
case 0xc0: /* Mono, 16-bit PCM big endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8);
temp = (int32_t) ad1848_dma_channel_read(ad1848, ad1848->dma);
ad1848->out_l = ad1848->out_r = (int16_t) (ad1848_dma_channel_read(ad1848, ad1848->dma) | (temp << 8));
break;
case 0xd0: /* Stereo, 16-bit PCM big endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = dma_channel_read(ad1848->dma) | (temp << 8);
temp = dma_channel_read(ad1848->dma);
ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8);
temp = (int32_t) ad1848_dma_channel_read(ad1848, ad1848->dma);
ad1848->out_l = (int16_t) (ad1848_dma_channel_read(ad1848, ad1848->dma) | (temp << 8));
temp = (int32_t) ad1848_dma_channel_read(ad1848, ad1848->dma);
ad1848->out_r = (int16_t) (ad1848_dma_channel_read(ad1848, ad1848->dma) | (temp << 8));
break;
/* 0xe0 and 0xf0 reserved */
@@ -591,12 +631,12 @@ ad1848_poll(void *priv)
if (ad1848->regs[6] & 0x80)
ad1848->out_l = 0;
else
ad1848->out_l = (ad1848->out_l * ad1848_vols_7bits[ad1848->regs[6] & ad1848->wave_vol_mask]) >> 16;
ad1848->out_l = (int16_t) ((ad1848->out_l * ad1848_vols_7bits[ad1848->regs[6] & ad1848->wave_vol_mask]) >> 16);
if (ad1848->regs[7] & 0x80)
ad1848->out_r = 0;
else
ad1848->out_r = (ad1848->out_r * ad1848_vols_7bits[ad1848->regs[7] & ad1848->wave_vol_mask]) >> 16;
ad1848->out_r = (int16_t) ((ad1848->out_r * ad1848_vols_7bits[ad1848->regs[7] & ad1848->wave_vol_mask]) >> 16);
if (ad1848->count < 0) {
ad1848->count = ad1848->regs[15] | (ad1848->regs[14] << 8);