ohmic-net / puca_dsp

Open source ESP32 development board for audio and dsp applications.
MIT License
56 stars 4 forks source link

WM8978 and disabling onboard microphones #8

Closed troyhacks closed 3 months ago

troyhacks commented 8 months ago

I've been having issues trying to completely disable the microphone path on the Puca DSP board.

Generally, I will say that line-in is a much stronger signal and the mic contamination isn't high - but during line-in silence the code we use in WLED will eventually auto-gain and find a mic signal in the background.

My WM8978 init code and comments are here:

https://github.com/troyhacks/WLED/blob/5fa8cd0a293847d3b5e8d6b37623d471accebd01/usermods/audioreactive/audio_source.h#L648

I feel like I've been back and forth on the WM8978 spec sheet and set everything on or off I can think of - but if you have any hints, I'd love to hear them.

(It also doesn't help that I use this board in very loud rave-type environments, so the sound pressure is pretty high in the room. 🤣)

Thanks!

andy-wi commented 8 months ago

I've used this function in the library from this repository to disable or enable the mic inputs - wm8978.inputCfg(1,0,0); which does give a definite "off", but I've only tested in normal room and not loud gig type environments.

Is your function _wm8978I2cWrite(44,0b000000000); // Disconnect microphones definitely writing to the same register (looks to be), but is it actually writing the correct values... I found I had to read the default value of the registers first, then write back using bitwise operations, and then (optionally) read again to check the value matches what the desired datasheet value should be.

Might be relevant - https://electronics.stackexchange.com/questions/640531/why-is-a-register-initialised-through-bitwise-operations-instead-of-a-binary-str

troyhacks commented 7 months ago

but is it actually writing the correct values... I found I had to read the default value of the registers first, then write back using bitwise operations, and then (optionally) read again to check the value matches what the desired datasheet value should be.

Well, good question...!

As far as I know, the WM8978 has no way to query the registry over I2C. The common flow in the libraries seems to be:

  1. Read default/current registry value from WM8978_REGVAL_TBL
  2. Do something to manipulate the value in a function
  3. Call writeReg() which:
  4. Writes the value to the I2C bus
  5. ...and...
  6. Updates the value in WM8978_REGVAL_TBL as we can't read it from the chip

So I guess the question is more "am I doing manually what the (hopefully known-working) library is doing?"

wm8978.init(); wm8978.inputCfg(0,1,0);

2 = 0b110110000 44 = 0b000000000 # yup, correct 47 = 0b101010000 48 = 0b101010000 47 = 0b101010000 48 = 0b101010000

...so I think more verification work is needed on my end.

I'll take the library and see if I can make it config in a way that works, and then test my code against a dump of the registry array and see if just sending all the final values is enough, or if I need to initialize it in a particular sequence.

Will report back. Thanks!

troyhacks commented 5 months ago

I've done some additional testing and I have it working much more reliably, but not entirely fixed.

The leakage from the microphones seems with be within the WM8978 chip itself - if I mute L2 and R2 then the issue goes away - so it's clearly something within that signal path, which should NOT be the microphone path, but they're kinda adjacent.

The biggest help seems to be in registry 1. The bit for microphone bias enable - "MICBEN" - seems to like being turned on. Secondly, there's a bit for BUFIOEN which is a tie-off for unused IO pins - this should also be enabled. Finally, setting the VMIDSEL to 300kΩ seems to help as well.

_wm8978I2cWrite( 1,0b000111110);

Overall , the issue does not go away entirely - but the microphones don't seem to leak nearly as badly. WLED has its own AGC for I2S samples, so this can still auto-range and hear "something" - but that is lessened greatly, and the WLED AGC seems to squelch it out eventually.

I'm curious if the AUXR/AUXL paths have the same issues, but I picked this board for the 1/8" inputs and outputs so I'm not likely to bother now that it's not reacting to loud noises in the room (or not as much). 😄

Thanks again for an amazing piece of hardware - it's been a great companion for WLED!

andy-wi commented 5 months ago

Great, good to hear! The datasheet for WM8968 doesn't contain any values for ADC input path crosstalk between the channels, however, the datasheet for WM8962B which is a similar codec has a section on this, where;

The ADC path is enabled from one input pin; -6dBV test signal applied to the other input; crosstalk measured at ADC output. The test is repeated with the two input pins swapped; the crosstalk figure is the worst case of the two measurements.

Test values are given in a table for 1kHz and 10kHz for different input paths, such as;

IN2 / IN4 ADC input path crosstalk 1kHz -90 dB, 10kHz -69dB

There looks to be an difference of around -20dB between the 1kHz and 10kHz values. The WM8978 may have similar values to these, with increased ADC input path crosstalk at higher frequencies?

Do you have the input PGAs enabled or disabled? (register 2) You could try disabling these also. The AUXL/AUXR input paths are post the input PGA before the ADC, if there is a difference with either the PGA disabled or using the AUX inputs then possibly some of the crosstalk could be in the PGA.

troyhacks commented 5 months ago

As far as I know, the PGA is disabled and also muted - medium confidence here, but I have spent a fair amount of time testing.

When I mute L1 and R1 then the microphone effect disappears - so that would seem to indicate.... something crosstalky?

My experiments at least confirmed it seems I'm hearing the microphones in the wrong place, and adjusting the regular microphone path has no effect on this issue.

At this point I don't have a significant issue and I have found at least somewhat of a workaround, so I'm content and educated. 👍🏻

Thank you!