mirror of
https://github.com/MarekZegare4/MeshCore-Solo.git
synced 2026-07-26 14:58:12 +00:00
fix: improve buzzer volume control on nRF52
- Use inverted PWM polarity (0x8000) with PCT {2,5,12,25,50} giving
~6-8 dB perceptual steps (-24/-16/-9/-3/0 dB) vs the original
uneven steps where levels 4 and 5 were only 1 dB apart
- Guard against cmp=0 truncation in both _nrfStartPwm and applyVolume:
at level 1 with high notes (freq > ~2.5 kHz) integer math gives
cmp=0 which with inverted polarity means 100% HIGH → complete silence
- Change volume preview note from C5 (523 Hz) to C6 (1047 Hz) to better
match the piezo resonant frequency range and actual notification sounds
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1560,7 +1560,7 @@ void UITask::setBuzzerVolumeLevel(uint8_t level) {
|
||||
if (level > 4) level = 4;
|
||||
_node_prefs->buzzer_volume = level;
|
||||
buzzer.setVolume(level);
|
||||
if (level > 0) buzzer.playForced("Vol:d=16,o=5,b=120:c");
|
||||
if (level > 0) buzzer.playForced("Vol:d=16,o=6,b=120:c");
|
||||
_next_refresh = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -86,7 +86,9 @@ bool genericBuzzer::_parseNext(const char*& p, uint8_t def_dur, uint8_t def_oct,
|
||||
}
|
||||
|
||||
uint8_t genericBuzzer::_dutyPct() const {
|
||||
static const uint8_t PCT[5] = { 2, 8, 20, 35, 50 };
|
||||
// Inverted polarity (0x8000 bit): duty_HIGH = 100% - PCT.
|
||||
// Values chosen for ~6-8 dB perceptual steps: -24/-16/-9/-3/0 dB.
|
||||
static const uint8_t PCT[5] = { 2, 5, 12, 25, 50 };
|
||||
return PCT[_volume_level < 5 ? _volume_level : 4];
|
||||
}
|
||||
|
||||
@@ -96,6 +98,7 @@ void genericBuzzer::_nrfStartPwm(uint16_t freq) {
|
||||
uint32_t nrf_pin = g_ADigitalPinMap[PIN_BUZZER];
|
||||
uint16_t top = 125000 / freq;
|
||||
uint16_t cmp = (uint16_t)(((uint32_t)top * _dutyPct()) / 100);
|
||||
if (cmp == 0) cmp = 1; // inverted polarity: cmp=0 → 100% HIGH → no AC → silence
|
||||
|
||||
// Write duty BEFORE SEQSTART so DMA reads our value on the very first period
|
||||
_duty_buf = 0x8000U | cmp;
|
||||
@@ -168,6 +171,7 @@ void genericBuzzer::applyVolume() {
|
||||
if (!_pwm_on) return;
|
||||
uint16_t top = (uint16_t)NRF_PWM2->COUNTERTOP;
|
||||
uint16_t cmp = (uint16_t)(((uint32_t)top * _dutyPct()) / 100);
|
||||
if (cmp == 0) cmp = 1;
|
||||
_duty_buf = 0x8000U | cmp; // DMA picks this up within one period (< 2.3 ms at A4)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user