Sound is fully working

This commit is contained in:
meepingsnesroms
2018-11-01 16:23:19 -07:00
parent 73c6f1b06a
commit dda3237a70
7 changed files with 36 additions and 25 deletions

View File

@@ -1,5 +1,5 @@
Theory of speaker output issues:
SysTaskDelay is used in PrvDoFreqDurationAmp, if SysTaskDelay waits on a timer the timer will not be triggered until addSysclks, the same time at which the PWM is sampled with empty samples due to the timer not being triggered properly.
SysTaskDelay is used in PrvDoFreqDurationAmp, if SysTaskDelay waits on a timer the timer will not be triggered until addSysclks, the same time at which the PWM is sampled with empty samples due to the timer not being triggered properly.(this is wrong the actual solution is listed below)
It is not stated what PWM1 does when it runs out of samples, does it keep playing the last sample, or does it set 0% duty cycle?(the last sample plays infinitely!)

View File

@@ -25,7 +25,7 @@ ICR POL(1,2,3,6) may flip the pin value as well as the interrupt, POL5 does not
edge triggered INT* don't clear on write to ISR when masked in IMR(at least that seems to be the reason)
if a sound interrupt is triggered while the button interrupt is disabled the button interrupt will still trigger(in galax game)
Cyclone will cause SIGSEGVs, don't know why yet
audio can max out the resampler buffer, the max 1 FIFO sample can play is around 2.16 minutes(CLK32 / period(257) / clockDivider(16) / prescaler(128) / repeat(8))(257 * 16 * 128 * 8 / 32768=128.5 seconds)
PWM2 is not implemented
Debug tools:
ADS7846 channels can't be read in single reference mode in hwTestSuite
@@ -49,6 +49,7 @@ in the edge case that SPICLK2 is disabled while using ADS7846 and a 1 was the la
Fixed:
audio can max out the resampler buffer, the max 1 FIFO sample can play is around 2.16 minutes(CLK32 / period(257) / clockDivider(16) / prescaler(128) / repeat(8))(257 * 16 * 128 * 8 / 32768=128.5 seconds)(safety check added, >= 1 second duty cycle is useless and will just make annoying cracks anyway)
Cyclone CPU emulator is not working
PWM1 output value is not a direct range cast of 0<->255 to 0<->32767, its additive, see properPwmSineWave.png
inductor dosent properly drain when PWM1 gets disabled

View File

@@ -7,7 +7,7 @@
#define INDUCTOR_CLOCK_POWER 0.0001//the amount 1 clock of true or false will change the inductors total value
#define INDUCTOR_SPEAKER_RANGE 0x6666//prevent hitting the top or bottom of the speaker when switching direction rapidly
double inductorCurrentCharge;
double inductorChargeAtLastSample;
@@ -18,19 +18,32 @@ void inductorReset(){
inductorChargeAtLastSample = 0.0;
}
void inductorPwmOff(int32_t clocks){
void inductorPwmDutyCycle(int32_t now, int32_t clocks, double dutyCycle){
int32_t onClocks = clocks * dutyCycle;
int32_t offClocks = clocks * (1.00 - dutyCycle);
double cutoffPoint = dutyCycle - 0.50;//cant go past the actual duty cycle percentage
#if !defined(EMU_NO_SAFETY)
if(now + clocks > AUDIO_CLOCK_RATE)
return;
#endif
inductorCurrentCharge = dMin(inductorCurrentCharge + onClocks * INDUCTOR_CLOCK_POWER, cutoffPoint);
blip_add_delta(palmAudioResampler, now, (inductorCurrentCharge - inductorChargeAtLastSample) * INDUCTOR_SPEAKER_RANGE);
inductorChargeAtLastSample = inductorCurrentCharge;
inductorCurrentCharge = dMax(-1.0, inductorCurrentCharge - offClocks * INDUCTOR_CLOCK_POWER);
blip_add_delta(palmAudioResampler, now + onClocks, (inductorCurrentCharge - inductorChargeAtLastSample) * INDUCTOR_SPEAKER_RANGE);
inductorChargeAtLastSample = inductorCurrentCharge;
}
void inductorPwmOff(int32_t now, int32_t clocks){
//drift towards 0
if(inductorCurrentCharge > 0.0)
inductorCurrentCharge = dMax(0.0, inductorCurrentCharge - clocks * INDUCTOR_CLOCK_POWER);
else
inductorCurrentCharge = dMin(inductorCurrentCharge + clocks * INDUCTOR_CLOCK_POWER, 0.0);
}
void inductorAddClocks(int32_t clocks, bool charge){
inductorCurrentCharge = dClamp(-1.0, inductorCurrentCharge + (charge ? +clocks : -clocks) * INDUCTOR_CLOCK_POWER, 1.0);
}
void inductorSampleAudio(int32_t now){
blip_add_delta(palmAudioResampler, now, (inductorCurrentCharge - inductorChargeAtLastSample) * 0x6666/*INT16_MAX*/);
blip_add_delta(palmAudioResampler, now, (inductorCurrentCharge - inductorChargeAtLastSample) * INDUCTOR_SPEAKER_RANGE);
inductorChargeAtLastSample = inductorCurrentCharge;
}

View File

@@ -8,6 +8,5 @@ extern double inductorChargeAtLastSample;
void inductorReset();
void inductorPwmOff(int32_t clocks);
void inductorAddClocks(int32_t clocks, bool charge);
void inductorSampleAudio(int32_t now);
void inductorPwmDutyCycle(int32_t now, int32_t clocks, double dutyCycle);
void inductorPwmOff(int32_t now, int32_t clocks);

View File

@@ -39,7 +39,7 @@ uint8_t* palmReg;
input_t palmInput;
sd_card_t palmSdCard;
misc_hw_t palmMisc;
uint16_t palmFramebuffer[160 * (160 + 60)];//really 160*160, the extra pixels are the silkscreened digitizer area
uint16_t* palmFramebuffer;
uint16_t* palmExtendedFramebuffer;
int16_t* palmAudio;
blip_t* palmAudioResampler;
@@ -62,16 +62,18 @@ uint32_t emulatorInit(buffer_t palmRomDump, buffer_t palmBootDump, uint32_t spec
palmRam = malloc(((specialFeatures & FEATURE_RAM_HUGE) ? SUPERMASSIVE_RAM_SIZE : RAM_SIZE) + 4);
palmRom = malloc(ROM_SIZE + 4);
palmReg = malloc(REG_SIZE + 4);
palmFramebuffer = malloc(160 * (160 + 60) * sizeof(uint16_t));//really 160*160, the extra pixels are the silkscreened digitizer area
palmAudio = malloc(AUDIO_SAMPLES_PER_FRAME * 2 * sizeof(int16_t));
palmAudioResampler = blip_new(AUDIO_SAMPLE_RATE);//have 1 second of samples
if(specialFeatures & FEATURE_320x320)
palmExtendedFramebuffer = malloc(320 * (320 + 120) * sizeof(uint16_t));//really 320*320, the extra pixels are the silkscreened digitizer area
else
palmExtendedFramebuffer = NULL;
if(!palmRam || !palmRom || !palmReg || !palmAudio || !palmAudioResampler || (!palmExtendedFramebuffer && (specialFeatures & FEATURE_320x320))){
if(!palmRam || !palmRom || !palmReg || !palmFramebuffer || !palmAudio || !palmAudioResampler || (!palmExtendedFramebuffer && (specialFeatures & FEATURE_320x320))){
free(palmRam);
free(palmRom);
free(palmReg);
free(palmFramebuffer);
free(palmAudio);
blip_delete(palmAudioResampler);
free(palmExtendedFramebuffer);
@@ -136,6 +138,7 @@ void emulatorExit(){
free(palmRam);
free(palmRom);
free(palmReg);
free(palmFramebuffer);
free(palmAudio);
blip_delete(palmAudioResampler);
free(palmExtendedFramebuffer);

View File

@@ -124,7 +124,7 @@ extern uint8_t* palmReg;//dont touch
extern input_t palmInput;//write allowed
extern sd_card_t palmSdCard;//dont touch
extern misc_hw_t palmMisc;//read/write allowed
extern uint16_t palmFramebuffer[];//read allowed if FEATURE_320x320 is off, or else invalid data will be displayed
extern uint16_t* palmFramebuffer;//read allowed if FEATURE_320x320 is off, or else invalid data will be displayed
extern uint16_t* palmExtendedFramebuffer;//read allowed if FEATURE_320x320 is on, or else SIGSEGV
extern int16_t* palmAudio;//read allowed, 2 channel signed 16 bit audio
extern blip_t* palmAudioResampler;//dont touch

View File

@@ -87,14 +87,10 @@ int32_t pwm1FifoRunSample(int32_t now, int32_t clockOffset){
uint8_t repeat = 1 << (pwmc1 >> 2 & 0x03);
int32_t audioNow = now + clockOffset;
int32_t audioSampleDuration = usingClk32 ? audioGetFramePercentIncrementFromClk32s(period * prescaler * clockDivider) : audioGetFramePercentIncrementFromSysclks(period * prescaler * clockDivider);
int32_t audioDutyCycle = dMin((double)sample / period, 1.0)/*dutyCycle*/ * audioSampleDuration;
double dutyCycle = dMin((double)sample / period, 1.00);
//relay all the samples to the inductor
for(uint8_t index = 0; index < repeat; index++){
inductorAddClocks(audioDutyCycle, true);
inductorSampleAudio(audioNow + audioDutyCycle);
inductorAddClocks(audioSampleDuration - audioDutyCycle, false);
inductorSampleAudio(audioNow + audioSampleDuration);
inductorPwmDutyCycle(audioNow, audioSampleDuration, dutyCycle);
audioNow += audioSampleDuration;
}
@@ -647,8 +643,7 @@ static void samplePwm1(bool forClk32, double sysclks){
}
else{
//PWM1 not enabled
inductorPwmOff(audioClocks);
inductorSampleAudio(audioNow + audioClocks);
inductorPwmOff(audioNow, audioClocks);
}
}