StopWatch: fix the ES8311 gain structure (mic noise/clipping, speaker distortion at high volume) - #350
Merged
Merged
Conversation
The capture path took all its gain after the ADC: analog PGA at 0 dB with +32 dB of ADC digital volume, which amplified the noise floor along with the signal and clipped loud input early (white noise and flattened waveforms in recordings). Move the gain to the analog side and trim the digital stage: - 0x14: analog PGA 0 dB -> +21 dB (gain code 7, 3 dB/code; the measured SNR plateaus by this level, limited by the mic element) - 0x17: ADC digital volume +32 dB -> +6 dB - 0x1C: HPF stage-2 coefficient 10 -> 4. The dynamic HPF was already enabled by the old value; the new coefficient cuts sub-200 Hz rumble at the default 16 kHz rate (silence rms 312 -> 52) Measured result: SNR 14.6 dB -> ~19 dB against a 440 Hz reference. The reset-witness comparison follows the 0x17 bulk value (0xCB).
The speaker enable procedure set DAC volume (reg 0x32) to 0xEF (+24 dB). Since digital gain ahead of the DAC cannot raise the full-scale ceiling, this only moved the clipping point down: any sample above 1/16 of full scale clipped hard, so master volumes above ~64 turned a sine wave into a buzzer-like square wave without getting any louder. Measured with a two-device sweep (StopWatch playing a 1 kHz tone, CoreS3 microphone running a Goertzel harmonic analysis): - clipping onset by 0x32 value: 0xEF = vol 64-128, 0xDF = 128-192, 0xCF = 192-255, 0xBF = none up to 255 - 0xEF at vol 64 and 0xBF at vol 255 produce the same acoustic level, confirming +24 dB adds no loudness - 0xCB (+6 dB) reaches DAC full scale right at vol 255: fundamental rises monotonically 20/100/222/300/380 (vol 64/128/192/224/255) with no 3rd-harmonic explosion, and its maximum clean output is about double the old clean ceiling 0xCB therefore maximizes clean output while removing digital clipping from the entire master volume range. ChainCaptain shares the same 0xEF value but is left unchanged (no hardware at hand to verify).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Fixes the audio gain structure on M5StopWatch (ES8311). Both directions took their gain in the wrong domain, which caused the recording quality issues and the speaker distortion at higher volumes.
Problems
Mic (capture): the enable sequence used analog PGA 0 dB with +32 dB of ADC digital volume. Digital gain after the ADC amplifies the noise floor together with the signal and clips loud input early, so recordings were noisy (white noise) and sounded flattened/muffled.
Speaker (playback): the enable sequence set the DAC digital volume to +24 dB (reg 0x32 = 0xEF). Digital gain ahead of the DAC cannot raise the full-scale ceiling, so this adds no loudness at all — it only moves the clipping point down. Any sample above 1/16 of full scale clips hard: with
Speaker.setVolume()above ~64, a sine wave turns into a buzzer-like square wave without getting any louder.Changes
Mic enable bulk:
0x14: analog PGA 0 dB → +21 dB (gain code 7; the measured SNR plateaus by this level, limited by the mic element)0x17: ADC digital volume +32 dB → +6 dB0x1C: HPF stage-2 coefficient 10 → 4 (the dynamic HPF was already enabled by the old value; the new coefficient cuts sub-200 Hz rumble at the default 16 kHz rate)Speaker enable bulk:
0x32: DAC digital volume +24 dB → +6 dB (0xCB). This value reaches DAC full scale exactly at maximum master volume.Measurements
Mic (440 Hz acoustic reference + Goertzel analysis on-device): SNR 14.6 dB → ~19 dB, silence rms 312 → 52.
Speaker (1 kHz tone played on StopWatch, recorded and analyzed by a second device's mic):
The #348 recovery matrix (speaker/mic alternating stress, 20 cycles) still passes with these values, and the stock
Basic/Speakerandadvanced/Mic_FFTexamples were verified by ear on the device.ChainCaptain shares the same ES8311 register values but is left unchanged: I have no hardware to verify it.