From 03d7ea2bcf0ac978c7829f920ddeb7ba9e06bfa7 Mon Sep 17 00:00:00 2001 From: meepingsnesroms Date: Fri, 26 Oct 2018 13:02:44 -0700 Subject: [PATCH] The audio still sounds lower frequency, but the correct samples are playing At this point its likely the speaker just doset squeal the same way as the Palm and never will since its not a peizo buzzer. --- bugs/unimplementedHardware.txt | 2 +- src/audio/inductor.c | 17 ++++--- src/audio/inductor.h | 4 +- src/emulator.c | 18 ++++---- src/emulator.h | 2 +- src/hardwareRegistersAccessors.c.h | 72 +++++++++++++++++------------- src/portability.h | 16 +++---- 7 files changed, 69 insertions(+), 62 deletions(-) diff --git a/bugs/unimplementedHardware.txt b/bugs/unimplementedHardware.txt index ee18015..58da93a 100644 --- a/bugs/unimplementedHardware.txt +++ b/bugs/unimplementedHardware.txt @@ -25,7 +25,6 @@ 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) 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 Debug tools: ADS7846 channels can't be read in single reference mode in hwTestSuite @@ -49,6 +48,7 @@ in the edge case that SPICLK2 is disabled while using ADS7846 and a 1 was the la Fixed: +inductor dosent properly drain when PWM1 gets disabled PWM1 FIFOAV is always set true may need to force sound generation until buffer is adequately filled when sound is on(not possible, INT_PWM1 is masked) if a timer triggers more than once per CLK32(> 32768 times a second) it will lose any triggers after the first and get out of sync(still not perfect but resolution is much higher) diff --git a/src/audio/inductor.c b/src/audio/inductor.c index e5be09a..8064593 100644 --- a/src/audio/inductor.c +++ b/src/audio/inductor.c @@ -6,24 +6,23 @@ #include "blip_buf.h" -#define INDUCTOR_RANGE 10000 -#define INDUCTOR_CLOCK_POWER 0.80 +#define INDUCTOR_CLOCK_POWER 0.000001//the amount 1 clock of true or false will increase the inductors total value -int32_t inductorCurrentCharge; -int32_t inductorLastAudioSample; +double inductorCurrentCharge; +double inductorChargeAtLastSample; void inductorReset(){ - inductorCurrentCharge = 0; - inductorLastAudioSample = 0; + inductorCurrentCharge = 0.0; + inductorChargeAtLastSample = 0.0; } void inductorAddClocks(int32_t clocks, bool charge){ - inductorCurrentCharge = sClamp(-INDUCTOR_RANGE, inductorCurrentCharge + (charge ? +clocks : -clocks) * INDUCTOR_CLOCK_POWER, INDUCTOR_RANGE); + inductorCurrentCharge = dClamp(0.0, inductorCurrentCharge + (charge ? +clocks : -clocks) * INDUCTOR_CLOCK_POWER, 1.0); } void inductorSampleAudio(int32_t now){ - blip_add_delta(palmAudioResampler, now, inductorCurrentCharge - inductorLastAudioSample); - inductorLastAudioSample = inductorCurrentCharge; + blip_add_delta(palmAudioResampler, now, (inductorCurrentCharge - inductorChargeAtLastSample) * AUDIO_VOLUME); + inductorChargeAtLastSample = inductorCurrentCharge; } diff --git a/src/audio/inductor.h b/src/audio/inductor.h index 1ea5319..a81588e 100644 --- a/src/audio/inductor.h +++ b/src/audio/inductor.h @@ -3,8 +3,8 @@ #include #include -extern int32_t inductorCurrentCharge; -extern int32_t inductorLastAudioSample; +extern double inductorCurrentCharge; +extern double inductorChargeAtLastSample; void inductorReset(); diff --git a/src/emulator.c b/src/emulator.c index 2ca66d5..5da5b9d 100644 --- a/src/emulator.c +++ b/src/emulator.c @@ -188,7 +188,7 @@ uint64_t emulatorGetStateSize(){ size += sizeof(int32_t);//pwm1ClocksToNextSample size += sizeof(uint8_t) * 6;//pwm1Fifo[6] size += sizeof(uint8_t) * 2;//pwm1(Read/Write) - size += sizeof(int32_t) * 2;//inductorCurrentCharge / inductorLastAudioSample + size += sizeof(uint64_t) * 2;//inductorCurrentCharge / inductorChargeAtLastSample size += sizeof(uint8_t) * 7;//palmMisc size += sizeof(uint32_t);//palmSdCard.command size += sizeof(uint8_t) * 2;//palmSdCard.response / palmSdCard.commandBitsRemaining @@ -313,10 +313,10 @@ bool emulatorSaveState(buffer_t buffer){ offset += sizeof(uint8_t); writeStateValueUint8(buffer.data + offset, pwm1WritePosition); offset += sizeof(uint8_t); - writeStateValueInt32(buffer.data + offset, inductorCurrentCharge); - offset += sizeof(int32_t); - writeStateValueInt32(buffer.data + offset, inductorLastAudioSample); - offset += sizeof(int32_t); + writeStateValueDouble(buffer.data + offset, inductorCurrentCharge); + offset += sizeof(uint64_t); + writeStateValueDouble(buffer.data + offset, inductorChargeAtLastSample); + offset += sizeof(uint64_t); //misc writeStateValueBool(buffer.data + offset, palmMisc.powerButtonLed); @@ -466,10 +466,10 @@ bool emulatorLoadState(buffer_t buffer){ offset += sizeof(uint8_t); pwm1WritePosition = readStateValueUint8(buffer.data + offset); offset += sizeof(uint8_t); - inductorCurrentCharge = readStateValueInt32(buffer.data + offset); - offset += sizeof(int32_t); - inductorLastAudioSample = readStateValueInt32(buffer.data + offset); - offset += sizeof(int32_t); + inductorCurrentCharge = readStateValueDouble(buffer.data + offset); + offset += sizeof(uint64_t); + inductorChargeAtLastSample = readStateValueDouble(buffer.data + offset); + offset += sizeof(uint64_t); //misc palmMisc.powerButtonLed = readStateValueBool(buffer.data + offset); diff --git a/src/emulator.h b/src/emulator.h index 13bb778..d3147f6 100644 --- a/src/emulator.h +++ b/src/emulator.h @@ -120,7 +120,7 @@ typedef struct{ //system constants #define CRYSTAL_FREQUENCY 32768 -#define AUDIO_VOLUME 10//1000000 +#define AUDIO_VOLUME 1000000 #define AUDIO_SAMPLES_PER_FRAME (AUDIO_SAMPLE_RATE / EMU_FPS) #define AUDIO_END_OF_FRAME (235929600 / EMU_FPS)//smallest amount of time a second can be split into:(2.0 * (14.0 * (255 + 1.0) + 15 + 1.0)) * 32768 == 235929600, used to convert the variable timing of SYSCLK and CLK32 to a fixed location in the current frame 0<->AUDIO_END_OF_FRAME #define AUDIO_WAIT_FOR_SAMPLE INT32_MIN diff --git a/src/hardwareRegistersAccessors.c.h b/src/hardwareRegistersAccessors.c.h index 6ae3a77..330e610 100644 --- a/src/hardwareRegistersAccessors.c.h +++ b/src/hardwareRegistersAccessors.c.h @@ -620,53 +620,61 @@ static inline uint8_t getPortMValue(){ static inline void samplePwm1(bool forClk32, double sysclks){ //clear PWM1 FIFO values if enough time has passed uint16_t pwmc1 = registerArrayRead16(PWMC1); + int32_t audioNow; int32_t audioClocks; //check if enabled and validate clock mode - if(!(pwmc1 & 0x0010) || forClk32 != (bool)(pwmc1 & 0x8000)) + if(forClk32 != (bool)(pwmc1 & 0x8000)) return; - //this calculation is fairly heavy, only do it after we know the clock mode is valid + //these calculations are fairly heavy, only do them after we know the clock mode is valid + audioNow = audioGetFramePercentage(); audioClocks = forClk32 ? audioGetFramePercentIncrementFromClk32s(1) : audioGetFramePercentIncrementFromSysclks(sysclks); - //add cycles - if(pwm1ClocksToNextSample != AUDIO_WAIT_FOR_SAMPLE) - pwm1ClocksToNextSample -= audioClocks; + if(pwmc1 & 0x0010){ + //add cycles + if(pwm1ClocksToNextSample != AUDIO_WAIT_FOR_SAMPLE) + pwm1ClocksToNextSample -= audioClocks; - //use samples - if(pwm1ClocksToNextSample <= 0){ - int32_t audioNow = audioGetFramePercentage(); - int32_t audioClocksLeft = audioClocks; + //use samples + if(pwm1ClocksToNextSample <= 0){ + int32_t audioClocksLeft = audioClocks; - while(pwm1FifoEntrys() > 0 && pwm1ClocksToNextSample <= 0){ - int32_t audioUsed; + while(pwm1FifoEntrys() > 0 && pwm1ClocksToNextSample <= 0){ + int32_t audioUsed; - //switch out samples until waiting(pwm1ClocksToNextSample is positive) - if(pwm1ClocksToNextSample == AUDIO_WAIT_FOR_SAMPLE){ - //got first sample in a while - audioUsed = pwm1FifoRunSample(audioNow, 0); - pwm1ClocksToNextSample = audioUsed; - } - else{ - //continue processing existing sample stream - audioUsed += pwm1FifoRunSample(audioNow, pwm1ClocksToNextSample); - pwm1ClocksToNextSample += audioUsed; + //switch out samples until waiting(pwm1ClocksToNextSample is positive) + if(pwm1ClocksToNextSample == AUDIO_WAIT_FOR_SAMPLE){ + //got first sample in a while + audioUsed = pwm1FifoRunSample(audioNow, 0); + pwm1ClocksToNextSample = audioUsed; + } + else{ + //continue processing existing sample stream + audioUsed += pwm1FifoRunSample(audioNow, pwm1ClocksToNextSample); + pwm1ClocksToNextSample += audioUsed; + } + + audioNow += audioUsed; + audioClocksLeft -= audioUsed;//goes negative when extra clocks are used } - audioNow += audioUsed; - audioClocksLeft -= audioUsed;//goes negative when extra clocks are used - } + //all samples used and its still negative, wait for next sample + if(pwm1ClocksToNextSample <= 0) + pwm1ClocksToNextSample = AUDIO_WAIT_FOR_SAMPLE; - //all samples used and its still negative, wait for next sample - if(pwm1ClocksToNextSample <= 0) - pwm1ClocksToNextSample = AUDIO_WAIT_FOR_SAMPLE; - - //add 0 cycles to inductor when theres no samples - if(audioClocksLeft > 0){ - inductorAddClocks(audioClocksLeft, false); - inductorSampleAudio(audioNow + audioClocksLeft); + //add 0 to inductor when theres no samples + if(audioClocksLeft > 0){ + inductorAddClocks(audioClocksLeft, false); + inductorSampleAudio(audioNow + audioClocksLeft); + } } } + else{ + //PWM1 not enabled, add 0 to inductor + inductorAddClocks(audioClocks, false); + inductorSampleAudio(audioNow + audioClocks); + } } static inline uint16_t getPwmc1(){ diff --git a/src/portability.h b/src/portability.h index 2ccc69c..41da75e 100644 --- a/src/portability.h +++ b/src/portability.h @@ -18,9 +18,9 @@ static inline uint64_t uMax(uint64_t x, uint64_t y){ return x > y ? x : y; } -static inline uint64_t uClamp(uint64_t x, uint64_t y, uint64_t z){ +static inline uint64_t uClamp(uint64_t low, uint64_t value, uint64_t high){ //x must always be less than z! - return (y < x ? x : y) > z ? z : y; + return uMax(low, uMin(value, high)); } static inline int64_t sMin(int64_t x, int64_t y){ @@ -31,9 +31,9 @@ static inline int64_t sMax(int64_t x, int64_t y){ return x > y ? x : y; } -static inline int64_t sClamp(int64_t x, int64_t y, int64_t z){ +static inline int64_t sClamp(int64_t low, int64_t value, int64_t high){ //x must always be less than z! - return (y < x ? x : y) > z ? z : y; + return sMax(low, sMin(value, high)); } static inline double dMin(double x, double y){ @@ -44,9 +44,9 @@ static inline double dMax(double x, double y){ return x > y ? x : y; } -static inline double dClamp(double x, double y, double z){ +static inline double dClamp(double low, double value, double high){ //x must always be less than z! - return (y < x ? x : y) > z ? z : y; + return dMax(low, dMin(value, high)); } @@ -61,7 +61,7 @@ static inline uint64_t getUint64FromDouble(double data){ fixedPointDouble |= (uint64_t)data << 31; data -= (uint64_t)data; - data *= 1000000000.0; + data *= (double)0x7FFFFFFF; fixedPointDouble |= (uint64_t)data; return fixedPointDouble; @@ -72,7 +72,7 @@ static inline double getDoubleFromUint64(uint64_t data){ double floatingPointDouble; floatingPointDouble = (double)(data & 0x000000007FFFFFFF); - floatingPointDouble /= 1000000000.0; + floatingPointDouble /= (double)0x7FFFFFFF; floatingPointDouble += (double)(data >> 31 & 0xFFFFFFFF); if(data & 0x8000000000000000) floatingPointDouble = -floatingPointDouble;