diff --git a/src/emu/sound/hc55516.c b/src/emu/sound/hc55516.c index 47201a254a5..ff0b6492212 100644 --- a/src/emu/sound/hc55516.c +++ b/src/emu/sound/hc55516.c @@ -3,9 +3,11 @@ #include "hc55516.h" #include +#include "cpuintrf.h" + /* default to 4x oversampling */ -#define DEFAULT_SAMPLE_RATE (48000 * 4) +#define SAMPLE_RATE (48000 * 4) #define INTEGRATOR_LEAK_TC 0.001 @@ -19,10 +21,11 @@ struct hc55516_data { sound_stream *channel; - int sample_rate; + int clock; /* 0 = software driven, non-0 = oscillator */ UINT8 last_clock; UINT8 databit; + UINT8 new_databit; UINT8 shiftreg; INT16 curr_value; @@ -56,11 +59,12 @@ static void *hc55516_start(int sndindex, int clock, const void *config) leak = pow(exp(-1), 1.0 / (INTEGRATOR_LEAK_TC * 16000.0)); /* create the stream */ - chip->sample_rate = clock ? clock : DEFAULT_SAMPLE_RATE; - chip->channel = stream_create(0, 1, chip->sample_rate, chip, hc55516_update); + chip->clock = clock; + chip->channel = stream_create(0, 1, SAMPLE_RATE, chip, hc55516_update); state_save_register_item("hc55516", sndindex, chip->last_clock); state_save_register_item("hc55516", sndindex, chip->databit); + state_save_register_item("hc55516", sndindex, chip->new_databit); state_save_register_item("hc55516", sndindex, chip->shiftreg); state_save_register_item("hc55516", sndindex, chip->curr_value); state_save_register_item("hc55516", sndindex, chip->next_value); @@ -73,23 +77,79 @@ static void *hc55516_start(int sndindex, int clock, const void *config) } +INLINE int current_clock_edge(struct hc55516_data *chip) +{ + return ((UINT64)chip->update_count * chip->clock * 2 / SAMPLE_RATE) & 0x01; +} + + +static void process_bit(struct hc55516_data *chip) +{ + double integrator = chip->integrator, temp; + + /* move the estimator up or down a step based on the bit */ + if (chip->databit) + { + chip->shiftreg = ((chip->shiftreg << 1) | 1) & 7; + integrator += chip->filter; + } + else + { + chip->shiftreg = (chip->shiftreg << 1) & 7; + integrator -= chip->filter; + } + + /* simulate leakage */ + integrator *= leak; + + /* if we got all 0's or all 1's in the last n bits, bump the step up */ + if (chip->shiftreg == 0 || chip->shiftreg == 7) + { + chip->filter = FILTER_MAX - ((FILTER_MAX - chip->filter) * charge); + if (chip->filter > FILTER_MAX) + chip->filter = FILTER_MAX; + } + + /* simulate decay */ + else + { + chip->filter *= decay; + if (chip->filter < FILTER_MIN) + chip->filter = FILTER_MIN; + } + + /* compute the sample as a 32-bit word */ + temp = integrator * SAMPLE_GAIN; + chip->integrator = integrator; + + /* compress the sample range to fit better in a 16-bit word */ + if (temp < 0) + chip->next_value = (int)(temp / (-temp * (1.0 / 32768.0) + 1.0)); + else + chip->next_value = (int)(temp / (temp * (1.0 / 32768.0) + 1.0)); +} + + static void hc55516_update(void *param, stream_sample_t **inputs, stream_sample_t **_buffer, int length) { struct hc55516_data *chip = param; stream_sample_t *buffer = _buffer[0]; - INT32 data, slope; int i; + INT32 data, slope; /* zero-length? bail */ if (length == 0) return; - /* track how many samples we've updated without a clock */ - chip->update_count += length; - if (chip->update_count > chip->sample_rate / 32) + if (chip->clock == 0) { - chip->update_count = chip->sample_rate; - chip->next_value = 0; + /* track how many samples we've updated without a clock */ + chip->update_count += length; + if (chip->update_count > SAMPLE_RATE / 32) + { + chip->update_count = SAMPLE_RATE; + chip->next_value = 0; + } } /* compute the interpolation slope */ @@ -97,9 +157,37 @@ static void hc55516_update(void *param, stream_sample_t **inputs, stream_sample_ slope = ((INT32)chip->next_value - data) / length; chip->curr_value = chip->next_value; - /* reset the sample count */ - for (i = 0; i < length; i++, data += slope) - *buffer++ = data; + if (chip->clock != 0) + { + int edge = current_clock_edge(chip); + + /* external oscillator */ + for (i = 0; i < length; i++, data += slope) + { + int new_edge; + + *buffer++ = data; + + chip->update_count++; + + new_edge = current_clock_edge(chip); + + /* pull in next data bit on falling edge of the clock */ + if (edge && !new_edge) + { + chip->databit = chip->new_databit; + + process_bit(chip); + } + + edge = new_edge; + } + } + + /* software driven clock */ + else + for (i = 0; i < length; i++, data += slope) + *buffer++ = data; } @@ -108,6 +196,8 @@ void hc55516_clock_w(int num, int state) struct hc55516_data *chip = sndti_token(SOUND_HC55516, num); int clock = state & 1, diffclock; + assert(chip->clock == 0); + /* update the clock */ diffclock = clock ^ chip->last_clock; chip->last_clock = clock; @@ -115,54 +205,13 @@ void hc55516_clock_w(int num, int state) /* speech clock changing (active on rising edge) */ if (diffclock && clock) { - double integrator = chip->integrator, temp; + /* update the output buffer before changing the registers */ + stream_update(chip->channel); /* clear the update count */ chip->update_count = 0; - /* move the estimator up or down a step based on the bit */ - if (chip->databit) - { - chip->shiftreg = ((chip->shiftreg << 1) | 1) & 7; - integrator += chip->filter; - } - else - { - chip->shiftreg = (chip->shiftreg << 1) & 7; - integrator -= chip->filter; - } - - /* simulate leakage */ - integrator *= leak; - - /* if we got all 0's or all 1's in the last n bits, bump the step up */ - if (chip->shiftreg == 0 || chip->shiftreg == 7) - { - chip->filter = FILTER_MAX - ((FILTER_MAX - chip->filter) * charge); - if (chip->filter > FILTER_MAX) - chip->filter = FILTER_MAX; - } - - /* simulate decay */ - else - { - chip->filter *= decay; - if (chip->filter < FILTER_MIN) - chip->filter = FILTER_MIN; - } - - /* compute the sample as a 32-bit word */ - temp = integrator * SAMPLE_GAIN; - chip->integrator = integrator; - - /* compress the sample range to fit better in a 16-bit word */ - if (temp < 0) - chip->next_value = (int)(temp / (-temp * (1.0 / 32768.0) + 1.0)); - else - chip->next_value = (int)(temp / (temp * (1.0 / 32768.0) + 1.0)); - - /* update the output buffer before changing the registers */ - stream_update(chip->channel); + process_bit(chip); } } @@ -170,7 +219,14 @@ void hc55516_clock_w(int num, int state) void hc55516_digit_w(int num, int data) { struct hc55516_data *chip = sndti_token(SOUND_HC55516, num); - chip->databit = data & 1; + + if (chip->clock != 0) + { + stream_update(chip->channel); + chip->new_databit = data & 1; + } + else + chip->databit = data & 1; } @@ -194,17 +250,32 @@ void hc55516_digit_clock_clear_w(int num, int data) } +int hc55516_clock_edge_r(int num) +{ + struct hc55516_data *chip = sndti_token(SOUND_HC55516, num); + + assert(chip->clock != 0); + + stream_update(chip->channel); + + return current_clock_edge(chip); +} + + + WRITE8_HANDLER( hc55516_0_digit_w ) { hc55516_digit_w(0,data); } WRITE8_HANDLER( hc55516_0_clock_w ) { hc55516_clock_w(0,data); } WRITE8_HANDLER( hc55516_0_clock_clear_w ) { hc55516_clock_clear_w(0,data); } WRITE8_HANDLER( hc55516_0_clock_set_w ) { hc55516_clock_set_w(0,data); } WRITE8_HANDLER( hc55516_0_digit_clock_clear_w ) { hc55516_digit_clock_clear_w(0,data); } +READ8_HANDLER ( hc55516_0_clock_edge_r ) { return hc55516_clock_edge_r(0); } WRITE8_HANDLER( hc55516_1_digit_w ) { hc55516_digit_w(1,data); } WRITE8_HANDLER( hc55516_1_clock_w ) { hc55516_clock_w(1,data); } WRITE8_HANDLER( hc55516_1_clock_clear_w ) { hc55516_clock_clear_w(1,data); } WRITE8_HANDLER( hc55516_1_clock_set_w ) { hc55516_clock_set_w(1,data); } WRITE8_HANDLER( hc55516_1_digit_clock_clear_w ) { hc55516_digit_clock_clear_w(1,data); } +READ8_HANDLER ( hc55516_1_clock_edge_r ) { return hc55516_clock_edge_r(1); } @@ -237,8 +308,8 @@ void hc55516_get_info(void *token, UINT32 state, sndinfo *info) /* --- the following bits of info are returned as NULL-terminated strings --- */ case SNDINFO_STR_NAME: info->s = "HC55516"; break; - case SNDINFO_STR_CORE_FAMILY: info->s = "Gaelco custom"; break; - case SNDINFO_STR_CORE_VERSION: info->s = "1.0"; break; + case SNDINFO_STR_CORE_FAMILY: info->s = "CVSD"; break; + case SNDINFO_STR_CORE_VERSION: info->s = "2.0"; break; case SNDINFO_STR_CORE_FILE: info->s = __FILE__; break; case SNDINFO_STR_CORE_CREDITS: info->s = "Copyright Nicola Salmoria and the MAME Team"; break; } diff --git a/src/emu/sound/hc55516.h b/src/emu/sound/hc55516.h index e9a719e6b20..318f7296aad 100644 --- a/src/emu/sound/hc55516.h +++ b/src/emu/sound/hc55516.h @@ -15,17 +15,21 @@ void hc55516_clock_set_w(int num, int data); /* clears the clock state and sets the databit */ void hc55516_digit_clock_clear_w(int num, int data); +int hc55516_clock_edge_r(int num); + WRITE8_HANDLER( hc55516_0_digit_w ); WRITE8_HANDLER( hc55516_0_clock_w ); WRITE8_HANDLER( hc55516_0_clock_clear_w ); WRITE8_HANDLER( hc55516_0_clock_set_w ); WRITE8_HANDLER( hc55516_0_digit_clock_clear_w ); +READ8_HANDLER ( hc55516_0_clock_edge_r ); WRITE8_HANDLER( hc55516_1_digit_w ); WRITE8_HANDLER( hc55516_1_clock_w ); WRITE8_HANDLER( hc55516_1_clock_clear_w ); WRITE8_HANDLER( hc55516_1_clock_set_w ); WRITE8_HANDLER( hc55516_1_digit_clock_clear_w ); +READ8_HANDLER ( hc55516_1_clock_edge_r ); #endif diff --git a/src/mame/audio/exidy.c b/src/mame/audio/exidy.c index 6219311c569..4c72c0266a3 100644 --- a/src/mame/audio/exidy.c +++ b/src/mame/audio/exidy.c @@ -27,7 +27,8 @@ #define SH8253_CLOCK (CRYSTAL_OSC/2) #define SH6840_CLOCK (CRYSTAL_OSC/4) #define SH6532_CLOCK (CRYSTAL_OSC/4) -#define CVSD_CLOCK_FREQ (1.0 / (0.693 * (RES_K(2.4) + 2.0 * RES_K(20)) * CAP_P(2200))) +#define CVSD_CLOCK (1.0 / (0.693 * (RES_K(2.4) + 2.0 * RES_K(20)) * CAP_P(2200))) +#define CVSD_Z80_CLOCK (CRYSTAL_OSC/2) #define BASE_VOLUME (32767 / 6) enum @@ -834,10 +835,7 @@ MACHINE_DRIVER_END static WRITE8_HANDLER( mtrap_voiceio_w ) { if (!(offset & 0x10)) - { - hc55516_digit_clock_clear_w(0,data); - hc55516_clock_set_w(0,data); - } + hc55516_digit_w(0, data & 1); if (!(offset & 0x20)) riot_portb_data = data & 1; @@ -856,12 +854,8 @@ static READ8_HANDLER( mtrap_voiceio_r ) } if (!(offset & 0x40)) - { - attotime curtime = timer_get_time(); - int clock_pulse = curtime.attoseconds / HZ_TO_ATTOSECONDS(2 * CVSD_CLOCK_FREQ); + return hc55516_clock_edge_r(0) << 7; - return (clock_pulse & 1) << 7; - } return 0; } @@ -880,12 +874,12 @@ ADDRESS_MAP_END MACHINE_DRIVER_START( mtrap_cvsd_audio ) - MDRV_CPU_ADD(Z80, 3579545/2) + MDRV_CPU_ADD(Z80, CVSD_Z80_CLOCK) MDRV_CPU_PROGRAM_MAP(cvsd_map,0) MDRV_CPU_IO_MAP(cvsd_iomap,0) /* audio hardware */ - MDRV_SOUND_ADD(HC55516, 0) + MDRV_SOUND_ADD(HC55516, CVSD_CLOCK) MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.80) MACHINE_DRIVER_END