Record the WM8960 mixer state and the audio switch gotcha

Capture works: singing at arm's length reads -34 to -49 dBFS RMS with peaks at
-18 dBFS and no clipping. The earlier all-zero recordings were the HAT's hardware
Audio ON/OFF switch being off; the codec answers on I2C and looks fully
configured either way. Save the stored mixer state (capture +18 dB, input mixer
boost on) in pi/wm8960_asound.state.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AFN8nRRCiDiMN7ChBpHJhs
This commit is contained in:
2026-10-04 23:01:36 -07:00
co-authored by Claude Sonnet 5.5
parent 8d5033d0a2
commit e54ad8aa04
2 changed files with 715 additions and 12 deletions
+13 -12
View File
@@ -62,20 +62,21 @@ printed enclosure, speakers. Work until those arrive is limited to what the Pi,
`opencv-python-headless==4.10.0.84` with `numpy<2` (system NumPy stays 1.26.4 for ROS), and
`robot-env.sh` puts the venv first on `PYTHONPATH`; YuNet also needs input sides that are multiples
of 32. Tested on a sample image and on a live frame (one face found, upright, no flip needed).
- **Audio: card works, microphones read digital silence (open).** The stock `wm8960-soundcard`
overlay fails every stream with `wm8960: No MCLK configured` on Ubuntu 24.04: it puts the 12.288 MHz
fixed clock on the sound card's codec link, but the codec driver reads `mclk` from its own node.
- **Audio capture works (verified 2026-10-04).** The stock `wm8960-soundcard` overlay fails every
stream with `wm8960: No MCLK configured` on Ubuntu 24.04: it puts the 12.288 MHz fixed clock on the
sound card's codec link, but the codec driver reads `mclk` from its own node.
`pi/overlays/hermes-wm8960.dts` is the stock overlay plus `clocks`/`clock-names` on the codec node;
`pi/install-audio-overlay.sh` compiles it to `/boot/firmware/overlays/hermes-wm8960.dtbo`, sets
`dtparam=audio=off` and `dtoverlay=hermes-wm8960`. With it, capture opens at 8-48 kHz. Address
the card by name (`hw:CARD=wm8960soundcard,DEV=0`): its index changes (it was card 1, then 0).
But every recording is exactly zero (no noise floor), with every mixer path on and gains maxed.
Checked: DAPM shows ADCs, input mixers, boost mixers and LINPUT1/RINPUT1 on; registers
`R25=0xfc`, `R47=0x30`, `R32/33=0x108`; MCLK 12.288 MHz and BCLK 1.536 MHz running; GPIO18-21 in
`alt0` for the I2S; setting `ALRCGPIO` (R9 bit 6) over I2C made no difference. Not yet checked:
the HAT's hardware **Audio ON/OFF slide switch** position, MICBIAS, a DAC-to-ADC loopback.
`Left/Right Input Mixer Boost Switch` default to off and must be turned on for the mic path.
No speakers on hand, so playback is untested.
`dtparam=audio=off` and `dtoverlay=hermes-wm8960`. Capture then opens at 8-48 kHz. Address the
card by name (`hw:CARD=wm8960soundcard,DEV=0`): its index changes (it was card 1, then 0).
- **The HAT's hardware Audio ON/OFF slide switch (right edge, by the "Audio" label) must be ON.**
With it off, the codec still answers on I2C and every software check looks right, but all
recordings are exactly zero. That cost an hour of debugging; check it first.
- Mixer: `Left/Right Input Mixer Boost Switch` default to off and must be on. Settings in use:
Capture 47/47 (+18 dB), `Left/Right Input Boost Mixer LINPUT1/RINPUT1` volume 1, input mixer boost
on. Singing at arm's length: RMS -34 to -49 dBFS, peaks -18 dBFS, no clipping, channels within
1-2 dB. Saved with `alsactl store` and exported as `pi/wm8960_asound.state`; restoring at boot is
not yet verified. No speakers on hand, so playback is untested.
- Not done: PWM (waits for servos). Ask before rebooting the Pi.
## Package 0b (USB link): Pi side and talos side working
+702
View File
@@ -0,0 +1,702 @@
state.wm8960soundcard {
control.1 {
iface MIXER
name 'Capture Volume'
value.0 47
value.1 47
comment {
access 'read write'
type INTEGER
count 2
range '0 - 63'
dbmin -1725
dbmax 3000
dbvalue.0 1800
dbvalue.1 1800
}
}
control.2 {
iface MIXER
name 'Capture Volume ZC Switch'
value.0 false
value.1 false
comment {
access 'read write'
type BOOLEAN
count 2
}
}
control.3 {
iface MIXER
name 'Capture Switch'
value.0 true
value.1 true
comment {
access 'read write'
type BOOLEAN
count 2
}
}
control.4 {
iface MIXER
name 'Left Input Boost Mixer LINPUT3 Volume'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 7'
dbmin -9999999
dbmax 600
dbvalue.0 -9999999
}
}
control.5 {
iface MIXER
name 'Left Input Boost Mixer LINPUT2 Volume'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 7'
dbmin -9999999
dbmax 600
dbvalue.0 -9999999
}
}
control.6 {
iface MIXER
name 'Right Input Boost Mixer RINPUT3 Volume'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 7'
dbmin -9999999
dbmax 600
dbvalue.0 -9999999
}
}
control.7 {
iface MIXER
name 'Right Input Boost Mixer RINPUT2 Volume'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 7'
dbmin -9999999
dbmax 600
dbvalue.0 -9999999
}
}
control.8 {
iface MIXER
name 'Right Input Boost Mixer RINPUT1 Volume'
value 1
comment {
access 'read write'
type INTEGER
count 1
range '0 - 3'
dbmin 0
dbmax 2900
dbvalue.0 1300
}
}
control.9 {
iface MIXER
name 'Left Input Boost Mixer LINPUT1 Volume'
value 1
comment {
access 'read write'
type INTEGER
count 1
range '0 - 3'
dbmin 0
dbmax 2900
dbvalue.0 1300
}
}
control.10 {
iface MIXER
name 'Playback Volume'
value.0 215
value.1 215
comment {
access 'read write'
type INTEGER
count 2
range '0 - 255'
dbmin -9999999
dbmax 0
dbvalue.0 -2000
dbvalue.1 -2000
}
}
control.11 {
iface MIXER
name 'Headphone Playback Volume'
value.0 101
value.1 101
comment {
access 'read write'
type INTEGER
count 2
range '0 - 127'
dbmin -9999999
dbmax 600
dbvalue.0 -2000
dbvalue.1 -2000
}
}
control.12 {
iface MIXER
name 'Headphone Playback ZC Switch'
value.0 false
value.1 false
comment {
access 'read write'
type BOOLEAN
count 2
}
}
control.13 {
iface MIXER
name 'Speaker Playback Volume'
value.0 101
value.1 101
comment {
access 'read write'
type INTEGER
count 2
range '0 - 127'
dbmin -9999999
dbmax 600
dbvalue.0 -2000
dbvalue.1 -2000
}
}
control.14 {
iface MIXER
name 'Speaker Playback ZC Switch'
value.0 false
value.1 false
comment {
access 'read write'
type BOOLEAN
count 2
}
}
control.15 {
iface MIXER
name 'Speaker DC Volume'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 5'
}
}
control.16 {
iface MIXER
name 'Speaker AC Volume'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 5'
}
}
control.17 {
iface MIXER
name 'PCM Playback -6dB Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.18 {
iface MIXER
name 'ADC Polarity'
value 'No Inversion'
comment {
access 'read write'
type ENUMERATED
count 1
item.0 'No Inversion'
item.1 'Left Inverted'
item.2 'Right Inverted'
item.3 'Stereo Inversion'
}
}
control.19 {
iface MIXER
name 'ADC High Pass Filter Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.20 {
iface MIXER
name 'DAC Polarity'
value 'No Inversion'
comment {
access 'read write'
type ENUMERATED
count 1
item.0 'No Inversion'
item.1 'Left Inverted'
item.2 'Right Inverted'
item.3 'Stereo Inversion'
}
}
control.21 {
iface MIXER
name 'DAC Deemphasis Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.22 {
iface MIXER
name '3D Filter Upper Cut-Off'
value High
comment {
access 'read write'
type ENUMERATED
count 1
item.0 High
item.1 Low
}
}
control.23 {
iface MIXER
name '3D Filter Lower Cut-Off'
value Low
comment {
access 'read write'
type ENUMERATED
count 1
item.0 Low
item.1 High
}
}
control.24 {
iface MIXER
name '3D Volume'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 15'
}
}
control.25 {
iface MIXER
name '3D Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.26 {
iface MIXER
name 'ALC Function'
value Off
comment {
access 'read write'
type ENUMERATED
count 1
item.0 Off
item.1 Right
item.2 Left
item.3 Stereo
}
}
control.27 {
iface MIXER
name 'ALC Max Gain'
value 7
comment {
access 'read write'
type INTEGER
count 1
range '0 - 7'
}
}
control.28 {
iface MIXER
name 'ALC Target'
value 4
comment {
access 'read write'
type INTEGER
count 1
range '0 - 15'
}
}
control.29 {
iface MIXER
name 'ALC Min Gain'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 7'
}
}
control.30 {
iface MIXER
name 'ALC Hold Time'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 15'
}
}
control.31 {
iface MIXER
name 'ALC Mode'
value ALC
comment {
access 'read write'
type ENUMERATED
count 1
item.0 ALC
item.1 Limiter
}
}
control.32 {
iface MIXER
name 'ALC Decay'
value 3
comment {
access 'read write'
type INTEGER
count 1
range '0 - 15'
}
}
control.33 {
iface MIXER
name 'ALC Attack'
value 2
comment {
access 'read write'
type INTEGER
count 1
range '0 - 15'
}
}
control.34 {
iface MIXER
name 'Noise Gate Threshold'
value 0
comment {
access 'read write'
type INTEGER
count 1
range '0 - 31'
}
}
control.35 {
iface MIXER
name 'Noise Gate Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.36 {
iface MIXER
name 'ADC PCM Capture Volume'
value.0 195
value.1 195
comment {
access 'read write'
type INTEGER
count 2
range '0 - 255'
dbmin -9999999
dbmax 3000
dbvalue.0 0
dbvalue.1 0
}
}
control.37 {
iface MIXER
name 'Left Output Mixer Boost Bypass Volume'
value 2
comment {
access 'read write'
type INTEGER
count 1
range '0 - 7'
dbmin -2100
dbmax 0
dbvalue.0 -1500
}
}
control.38 {
iface MIXER
name 'Left Output Mixer LINPUT3 Volume'
value 2
comment {
access 'read write'
type INTEGER
count 1
range '0 - 7'
dbmin -2100
dbmax 0
dbvalue.0 -1500
}
}
control.39 {
iface MIXER
name 'Right Output Mixer Boost Bypass Volume'
value 2
comment {
access 'read write'
type INTEGER
count 1
range '0 - 7'
dbmin -2100
dbmax 0
dbvalue.0 -1500
}
}
control.40 {
iface MIXER
name 'Right Output Mixer RINPUT3 Volume'
value 2
comment {
access 'read write'
type INTEGER
count 1
range '0 - 7'
dbmin -2100
dbmax 0
dbvalue.0 -1500
}
}
control.41 {
iface MIXER
name 'ADC Data Output Select'
value 'Left Data = Left ADC; Right Data = Right ADC'
comment {
access 'read write'
type ENUMERATED
count 1
item.0 'Left Data = Left ADC; Right Data = Right ADC'
item.1 'Left Data = Left ADC; Right Data = Left ADC'
item.2 'Left Data = Right ADC; Right Data = Right ADC'
item.3 'Left Data = Right ADC; Right Data = Left ADC'
}
}
control.42 {
iface MIXER
name 'DAC Mono Mix'
value Stereo
comment {
access 'read write'
type ENUMERATED
count 1
item.0 Stereo
item.1 Mono
}
}
control.43 {
iface MIXER
name 'DAC Filter Characteristics'
value Normal
comment {
access 'read write'
type ENUMERATED
count 1
item.0 Normal
item.1 Sloping
}
}
control.44 {
iface MIXER
name 'Left Boost Mixer LINPUT2 Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.45 {
iface MIXER
name 'Left Boost Mixer LINPUT3 Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.46 {
iface MIXER
name 'Left Boost Mixer LINPUT1 Switch'
value true
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.47 {
iface MIXER
name 'Right Boost Mixer RINPUT2 Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.48 {
iface MIXER
name 'Right Boost Mixer RINPUT3 Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.49 {
iface MIXER
name 'Right Boost Mixer RINPUT1 Switch'
value true
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.50 {
iface MIXER
name 'Left Input Mixer Boost Switch'
value true
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.51 {
iface MIXER
name 'Right Input Mixer Boost Switch'
value true
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.52 {
iface MIXER
name 'Left Output Mixer PCM Playback Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.53 {
iface MIXER
name 'Left Output Mixer LINPUT3 Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.54 {
iface MIXER
name 'Left Output Mixer Boost Bypass Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.55 {
iface MIXER
name 'Right Output Mixer PCM Playback Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.56 {
iface MIXER
name 'Right Output Mixer RINPUT3 Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.57 {
iface MIXER
name 'Right Output Mixer Boost Bypass Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.58 {
iface MIXER
name 'Mono Output Mixer Left Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
control.59 {
iface MIXER
name 'Mono Output Mixer Right Switch'
value false
comment {
access 'read write'
type BOOLEAN
count 1
}
}
}