mirror of
https://github.com/holub/mame
synced 2025-06-06 12:53:46 +03:00
- Added the ability to the HC55516 emulator to take an external osciallator
- Updated Mouse Trap to use the new interface
This commit is contained in:
parent
cb6dbf5369
commit
34a413510d
@ -3,9 +3,11 @@
|
||||
#include "hc55516.h"
|
||||
#include <math.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user