Settings: add buzzer volume control (5 levels, like brightness)

- NodePrefs: add buzzer_volume field (0=min..4=max, default 4)
- DataStore: persist buzzer_volume at end of prefs file (backward-compat)
- buzzer: setVolume()/getVolume(); applyVolume() sets PWM duty cycle via
  analogWrite() after each rtttl::play() call to control output amplitude
- Settings UI: new BzrVol bar item in Sound section (left/right to adjust)
- UITask: apply saved volume on startup alongside brightness

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Jakub
2026-05-12 09:17:37 +02:00
parent 861a65d4b1
commit ffa568938f
7 changed files with 57 additions and 1 deletions

View File

@@ -31,8 +31,24 @@ bool genericBuzzer::isPlaying() {
return rtttl::isPlaying();
}
void genericBuzzer::applyVolume() {
// After tone() sets 50% duty, analogWrite overrides duty cycle on the same PWM channel.
// Level 4 = 50% (leave tone as-is), lower levels reduce duty = quieter output.
static const uint8_t duty[] = { 6, 20, 50, 90, 128 };
uint8_t d = duty[_volume_level < 5 ? _volume_level : 4];
if (d < 128) analogWrite(PIN_BUZZER, d);
}
void genericBuzzer::setVolume(uint8_t level) {
_volume_level = level < 5 ? level : 4;
if (isPlaying()) applyVolume();
}
void genericBuzzer::loop() {
if (!rtttl::done()) rtttl::play();
if (!rtttl::done()) {
rtttl::play();
if (_volume_level < 4) applyVolume();
}
}
void genericBuzzer::startup() {

View File

@@ -28,8 +28,12 @@ class genericBuzzer
bool isPlaying(); // returns true if a sound is still playing else false
void quiet(bool buzzer_state); // enables or disables the buzzer
bool isQuiet(); // get buzzer state on/off
void setVolume(uint8_t level); // 0=min..4=max
uint8_t getVolume() const { return _volume_level; }
private:
uint8_t _volume_level = 4;
void applyVolume();
// gemini's picks:
const char *startup_song = "Startup:d=4,o=5,b=160:16c6,16e6,8g6";
const char *shutdown_song = "Shutdown:d=4,o=5,b=100:8g5,16e5,16c5";