refactor handling of volume steps; improve controls

custom
jacqueline 1 year ago
parent 42a98a3799
commit 938ba62f57
  1. 6
      src/audio/audio_fsm.cpp
  2. 14
      src/audio/bt_audio_output.cpp
  3. 44
      src/audio/i2s_audio_output.cpp
  4. 10
      src/audio/include/audio_sink.hpp
  5. 10
      src/audio/include/bt_audio_output.hpp
  6. 13
      src/audio/include/i2s_audio_output.hpp
  7. 4
      src/drivers/i2s_dac.cpp
  8. 2
      src/drivers/include/wm8523.hpp
  9. 2
      src/drivers/wm8523.cpp
  10. 8
      src/ui/encoder_input.cpp

@ -129,7 +129,7 @@ void Uninitialised::react(const system_fsm::BootComplete& ev) {
auto& nvs = sServices->nvs(); auto& nvs = sServices->nvs();
sI2SOutput->SetMaxVolume(nvs.AmpMaxVolume()); sI2SOutput->SetMaxVolume(nvs.AmpMaxVolume());
sI2SOutput->SetVolumeDb(nvs.AmpCurrentVolume()); sI2SOutput->SetVolume(nvs.AmpCurrentVolume());
if (sServices->nvs().OutputMode() == if (sServices->nvs().OutputMode() ==
drivers::NvsStorage::Output::kHeadphones) { drivers::NvsStorage::Output::kHeadphones) {
@ -188,6 +188,10 @@ void Playback::exit() {
vTaskDelay(pdMS_TO_TICKS(10)); vTaskDelay(pdMS_TO_TICKS(10));
sOutput->SetMode(IAudioOutput::Modes::kOnPaused); sOutput->SetMode(IAudioOutput::Modes::kOnPaused);
// Stash the current volume now, in case it changed during playback, since we
// might be powering off soon.
sServices->nvs().AmpCurrentVolume(sOutput->GetVolume());
events::System().Dispatch(PlaybackFinished{}); events::System().Dispatch(PlaybackFinished{});
events::Ui().Dispatch(PlaybackFinished{}); events::Ui().Dispatch(PlaybackFinished{});
} }

@ -43,10 +43,18 @@ auto BluetoothAudioOutput::SetMode(Modes mode) -> void {
auto BluetoothAudioOutput::SetVolumeImbalance(int_fast8_t balance) -> void {} auto BluetoothAudioOutput::SetVolumeImbalance(int_fast8_t balance) -> void {}
auto BluetoothAudioOutput::SetVolume(uint_fast8_t percent) -> void {} auto BluetoothAudioOutput::SetVolume(uint16_t) -> void {}
auto BluetoothAudioOutput::GetVolume() -> uint_fast8_t { auto BluetoothAudioOutput::GetVolume() -> uint16_t {
return 50; return 0;
}
auto BluetoothAudioOutput::GetVolumePct() -> uint_fast8_t {
return 0;
}
auto BluetoothAudioOutput::GetVolumeDb() -> int_fast16_t {
return 0;
} }
auto BluetoothAudioOutput::AdjustVolumeUp() -> bool { auto BluetoothAudioOutput::AdjustVolumeUp() -> bool {

@ -91,17 +91,9 @@ auto I2SAudioOutput::SetMaxVolume(uint16_t max) -> void {
SetVolume(GetVolume()); SetVolume(GetVolume());
} }
auto I2SAudioOutput::SetVolumeDb(uint16_t vol) -> void { auto I2SAudioOutput::SetVolume(uint16_t vol) -> void {
current_volume_ = current_volume_ = std::clamp(vol, kMinVolume, max_volume_);
std::clamp(vol, drivers::wm8523::kAbsoluteMinVolume, max_volume_); ESP_LOGI(kTag, "set volume to %u%% = %idB", GetVolumePct(), GetVolumeDb());
SetVolume(GetVolume());
}
auto I2SAudioOutput::SetVolume(uint_fast8_t percent) -> void {
percent = std::min<uint_fast8_t>(percent, 100);
float new_value = static_cast<float>(max_volume_) / 100 * percent;
current_volume_ = std::max<float>(new_value, kMinVolume);
ESP_LOGI(kTag, "set volume to %u%% = %u", percent, current_volume_);
int32_t left_unclamped = current_volume_ + left_difference_; int32_t left_unclamped = current_volume_ + left_difference_;
uint16_t left = std::clamp<int32_t>(left_unclamped, kMinVolume, max_volume_); uint16_t left = std::clamp<int32_t>(left_unclamped, kMinVolume, max_volume_);
@ -112,31 +104,37 @@ auto I2SAudioOutput::SetVolume(uint_fast8_t percent) -> void {
current_volume_ | 0x200); current_volume_ | 0x200);
} }
auto I2SAudioOutput::GetVolume() -> uint_fast8_t { auto I2SAudioOutput::GetVolume() -> uint16_t {
return static_cast<uint_fast8_t>(static_cast<float>(current_volume_) / return current_volume_;
max_volume_ * 100.0f); }
auto I2SAudioOutput::GetVolumePct() -> uint_fast8_t {
return (current_volume_ - kMinVolume) * 100 / (max_volume_ - kMinVolume);
}
auto I2SAudioOutput::GetVolumeDb() -> int_fast16_t {
// Add two before dividing in order to round correctly.
return (static_cast<int>(current_volume_) -
static_cast<int>(drivers::wm8523::kLineLevelReferenceVolume) + 2) /
4;
} }
auto I2SAudioOutput::AdjustVolumeUp() -> bool { auto I2SAudioOutput::AdjustVolumeUp() -> bool {
if (GetVolume() >= 100) { if (GetVolume() >= max_volume_) {
return false; return false;
} }
if (GetVolume() >= 95) { SetVolume(GetVolume() + 1);
SetVolume(100);
} else {
SetVolume(GetVolume() + 5);
}
return true; return true;
} }
auto I2SAudioOutput::AdjustVolumeDown() -> bool { auto I2SAudioOutput::AdjustVolumeDown() -> bool {
if (GetVolume() == 0) { if (GetVolume() == kMinVolume) {
return false; return false;
} }
if (GetVolume() <= 5) { if (GetVolume() <= kMinVolume + 1) {
SetVolume(0); SetVolume(0);
} else { } else {
SetVolume(GetVolume() - 5); SetVolume(GetVolume() - 1);
} }
return true; return true;
} }

@ -44,8 +44,14 @@ class IAudioOutput {
virtual auto SetMode(Modes) -> void = 0; virtual auto SetMode(Modes) -> void = 0;
virtual auto SetVolumeImbalance(int_fast8_t balance) -> void = 0; virtual auto SetVolumeImbalance(int_fast8_t balance) -> void = 0;
virtual auto SetVolume(uint_fast8_t percent) -> void = 0;
virtual auto GetVolume() -> uint_fast8_t = 0; virtual auto SetVolume(uint16_t) -> void = 0;
virtual auto GetVolume() -> uint16_t = 0;
virtual auto GetVolumePct() -> uint_fast8_t = 0;
virtual auto GetVolumeDb() -> int_fast16_t = 0;
virtual auto AdjustVolumeUp() -> bool = 0; virtual auto AdjustVolumeUp() -> bool = 0;
virtual auto AdjustVolumeDown() -> bool = 0; virtual auto AdjustVolumeDown() -> bool = 0;

@ -27,8 +27,14 @@ class BluetoothAudioOutput : public IAudioOutput {
auto SetMode(Modes) -> void override; auto SetMode(Modes) -> void override;
auto SetVolumeImbalance(int_fast8_t balance) -> void override; auto SetVolumeImbalance(int_fast8_t balance) -> void override;
auto SetVolume(uint_fast8_t percent) -> void override;
auto GetVolume() -> uint_fast8_t override; auto SetVolume(uint16_t) -> void override;
auto GetVolume() -> uint16_t override;
auto GetVolumePct() -> uint_fast8_t override;
auto GetVolumeDb() -> int_fast16_t override;
auto AdjustVolumeUp() -> bool override; auto AdjustVolumeUp() -> bool override;
auto AdjustVolumeDown() -> bool override; auto AdjustVolumeDown() -> bool override;

@ -20,8 +20,7 @@ namespace audio {
class I2SAudioOutput : public IAudioOutput { class I2SAudioOutput : public IAudioOutput {
public: public:
I2SAudioOutput(StreamBufferHandle_t, I2SAudioOutput(StreamBufferHandle_t, drivers::IGpios& expander);
drivers::IGpios& expander);
~I2SAudioOutput(); ~I2SAudioOutput();
auto SetMode(Modes) -> void override; auto SetMode(Modes) -> void override;
@ -30,8 +29,14 @@ class I2SAudioOutput : public IAudioOutput {
auto SetVolumeDb(uint16_t) -> void; auto SetVolumeDb(uint16_t) -> void;
auto SetVolumeImbalance(int_fast8_t balance) -> void override; auto SetVolumeImbalance(int_fast8_t balance) -> void override;
auto SetVolume(uint_fast8_t percent) -> void override;
auto GetVolume() -> uint_fast8_t override; auto SetVolume(uint16_t) -> void override;
auto GetVolume() -> uint16_t override;
auto GetVolumePct() -> uint_fast8_t override;
auto GetVolumeDb() -> int_fast16_t override;
auto AdjustVolumeUp() -> bool override; auto AdjustVolumeUp() -> bool override;
auto AdjustVolumeDown() -> bool override; auto AdjustVolumeDown() -> bool override;

@ -95,8 +95,8 @@ I2SDac::I2SDac(IGpios& gpio, i2s_chan_handle_t i2s_handle)
vTaskDelay(pdMS_TO_TICKS(10)); vTaskDelay(pdMS_TO_TICKS(10));
wm8523::WriteRegister(wm8523::Register::kPsCtrl, 0b0); wm8523::WriteRegister(wm8523::Register::kPsCtrl, 0b0);
// Ramp volume changes // Use zero-cross detection for volume changes.
wm8523::WriteRegister(wm8523::Register::kDacCtrl, 0b11); wm8523::WriteRegister(wm8523::Register::kDacCtrl, 0b10000);
} }
I2SDac::~I2SDac() { I2SDac::~I2SDac() {

@ -23,6 +23,8 @@ extern const uint16_t kLineLevelReferenceVolume;
extern const uint16_t kDefaultVolume; extern const uint16_t kDefaultVolume;
extern const uint16_t kDefaultMaxVolume; extern const uint16_t kDefaultMaxVolume;
extern const uint16_t kZeroDbVolume;
constexpr auto VolumeToDb(uint16_t vol) -> int_fast8_t { constexpr auto VolumeToDb(uint16_t vol) -> int_fast8_t {
return (vol - kLineLevelReferenceVolume) / 4; return (vol - kLineLevelReferenceVolume) / 4;
} }

@ -32,6 +32,8 @@ const uint16_t kDefaultVolume = kLineLevelReferenceVolume - 96;
// Default to +6dB == 2Vrms == 'CD Player' // Default to +6dB == 2Vrms == 'CD Player'
const uint16_t kDefaultMaxVolume = kLineLevelReferenceVolume + 12; const uint16_t kDefaultMaxVolume = kLineLevelReferenceVolume + 12;
const uint16_t kZeroDbVolume = 0x190;
static const uint8_t kAddress = 0b0011010; static const uint8_t kAddress = 0b0011010;
auto ReadRegister(Register reg) -> std::optional<uint16_t> { auto ReadRegister(Register reg) -> std::optional<uint16_t> {

@ -194,7 +194,7 @@ auto EncoderInput::Read(lv_indev_data_t* data) -> void {
data->enc_diff = scroller_->AddInput(now_ms, 0); data->enc_diff = scroller_->AddInput(now_ms, 0);
} }
trigger = TriggerKey(Keys::kVolumeUp, KeyStyle::kLongPress, now_ms); trigger = TriggerKey(Keys::kVolumeUp, KeyStyle::kRepeat, now_ms);
switch (trigger) { switch (trigger) {
case Trigger::kNone: case Trigger::kNone:
break; break;
@ -205,7 +205,7 @@ auto EncoderInput::Read(lv_indev_data_t* data) -> void {
break; break;
} }
trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kLongPress, now_ms); trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kRepeat, now_ms);
switch (trigger) { switch (trigger) {
case Trigger::kNone: case Trigger::kNone:
break; break;
@ -242,7 +242,7 @@ auto EncoderInput::Read(lv_indev_data_t* data) -> void {
break; break;
} }
trigger = TriggerKey(Keys::kVolumeUp, KeyStyle::kLongPress, now_ms); trigger = TriggerKey(Keys::kVolumeUp, KeyStyle::kRepeat, now_ms);
switch (trigger) { switch (trigger) {
case Trigger::kNone: case Trigger::kNone:
break; break;
@ -253,7 +253,7 @@ auto EncoderInput::Read(lv_indev_data_t* data) -> void {
break; break;
} }
trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kLongPress, now_ms); trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kRepeat, now_ms);
switch (trigger) { switch (trigger) {
case Trigger::kNone: case Trigger::kNone:
break; break;

Loading…
Cancel
Save