summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjacqueline <me@jacqueline.id.au>2024-01-04 15:57:58 +1100
committerjacqueline <me@jacqueline.id.au>2024-01-04 15:57:58 +1100
commit938ba62f57ed2c002bae4aec236eeaeb200e4cba (patch)
treed70948199d1f7a2572df5f2940ee13eb79537937 /src
parent42a98a3799bdfb328c5b5683bbf3d77046f1f5f8 (diff)
downloadtangara-fw-938ba62f57ed2c002bae4aec236eeaeb200e4cba.tar.gz
refactor handling of volume steps; improve controls
Diffstat (limited to 'src')
-rw-r--r--src/audio/audio_fsm.cpp6
-rw-r--r--src/audio/bt_audio_output.cpp14
-rw-r--r--src/audio/i2s_audio_output.cpp44
-rw-r--r--src/audio/include/audio_sink.hpp10
-rw-r--r--src/audio/include/bt_audio_output.hpp10
-rw-r--r--src/audio/include/i2s_audio_output.hpp13
-rw-r--r--src/drivers/i2s_dac.cpp4
-rw-r--r--src/drivers/include/wm8523.hpp2
-rw-r--r--src/drivers/wm8523.cpp2
-rw-r--r--src/ui/encoder_input.cpp8
10 files changed, 72 insertions, 41 deletions
diff --git a/src/audio/audio_fsm.cpp b/src/audio/audio_fsm.cpp
index 90bfd60b..a5179156 100644
--- a/src/audio/audio_fsm.cpp
+++ b/src/audio/audio_fsm.cpp
@@ -129,7 +129,7 @@ void Uninitialised::react(const system_fsm::BootComplete& ev) {
auto& nvs = sServices->nvs();
sI2SOutput->SetMaxVolume(nvs.AmpMaxVolume());
- sI2SOutput->SetVolumeDb(nvs.AmpCurrentVolume());
+ sI2SOutput->SetVolume(nvs.AmpCurrentVolume());
if (sServices->nvs().OutputMode() ==
drivers::NvsStorage::Output::kHeadphones) {
@@ -188,6 +188,10 @@ void Playback::exit() {
vTaskDelay(pdMS_TO_TICKS(10));
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::Ui().Dispatch(PlaybackFinished{});
}
diff --git a/src/audio/bt_audio_output.cpp b/src/audio/bt_audio_output.cpp
index a189fefe..0c11481b 100644
--- a/src/audio/bt_audio_output.cpp
+++ b/src/audio/bt_audio_output.cpp
@@ -43,10 +43,18 @@ auto BluetoothAudioOutput::SetMode(Modes mode) -> 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 {
- return 50;
+auto BluetoothAudioOutput::GetVolume() -> uint16_t {
+ return 0;
+}
+
+auto BluetoothAudioOutput::GetVolumePct() -> uint_fast8_t {
+ return 0;
+}
+
+auto BluetoothAudioOutput::GetVolumeDb() -> int_fast16_t {
+ return 0;
}
auto BluetoothAudioOutput::AdjustVolumeUp() -> bool {
diff --git a/src/audio/i2s_audio_output.cpp b/src/audio/i2s_audio_output.cpp
index 8cfd5b90..29d70fb5 100644
--- a/src/audio/i2s_audio_output.cpp
+++ b/src/audio/i2s_audio_output.cpp
@@ -91,17 +91,9 @@ auto I2SAudioOutput::SetMaxVolume(uint16_t max) -> void {
SetVolume(GetVolume());
}
-auto I2SAudioOutput::SetVolumeDb(uint16_t vol) -> void {
- current_volume_ =
- std::clamp(vol, drivers::wm8523::kAbsoluteMinVolume, max_volume_);
- 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_);
+auto I2SAudioOutput::SetVolume(uint16_t vol) -> void {
+ current_volume_ = std::clamp(vol, kMinVolume, max_volume_);
+ ESP_LOGI(kTag, "set volume to %u%% = %idB", GetVolumePct(), GetVolumeDb());
int32_t left_unclamped = current_volume_ + left_difference_;
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);
}
-auto I2SAudioOutput::GetVolume() -> uint_fast8_t {
- return static_cast<uint_fast8_t>(static_cast<float>(current_volume_) /
- max_volume_ * 100.0f);
+auto I2SAudioOutput::GetVolume() -> uint16_t {
+ return current_volume_;
+}
+
+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 {
- if (GetVolume() >= 100) {
+ if (GetVolume() >= max_volume_) {
return false;
}
- if (GetVolume() >= 95) {
- SetVolume(100);
- } else {
- SetVolume(GetVolume() + 5);
- }
+ SetVolume(GetVolume() + 1);
return true;
}
auto I2SAudioOutput::AdjustVolumeDown() -> bool {
- if (GetVolume() == 0) {
+ if (GetVolume() == kMinVolume) {
return false;
}
- if (GetVolume() <= 5) {
+ if (GetVolume() <= kMinVolume + 1) {
SetVolume(0);
} else {
- SetVolume(GetVolume() - 5);
+ SetVolume(GetVolume() - 1);
}
return true;
}
diff --git a/src/audio/include/audio_sink.hpp b/src/audio/include/audio_sink.hpp
index c37e51fb..eba55eb5 100644
--- a/src/audio/include/audio_sink.hpp
+++ b/src/audio/include/audio_sink.hpp
@@ -44,8 +44,14 @@ class IAudioOutput {
virtual auto SetMode(Modes) -> 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 AdjustVolumeDown() -> bool = 0;
diff --git a/src/audio/include/bt_audio_output.hpp b/src/audio/include/bt_audio_output.hpp
index 6e5d0720..f23ccd6a 100644
--- a/src/audio/include/bt_audio_output.hpp
+++ b/src/audio/include/bt_audio_output.hpp
@@ -27,8 +27,14 @@ class BluetoothAudioOutput : public IAudioOutput {
auto SetMode(Modes) -> 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 AdjustVolumeDown() -> bool override;
diff --git a/src/audio/include/i2s_audio_output.hpp b/src/audio/include/i2s_audio_output.hpp
index e5395ade..7c297106 100644
--- a/src/audio/include/i2s_audio_output.hpp
+++ b/src/audio/include/i2s_audio_output.hpp
@@ -20,8 +20,7 @@ namespace audio {
class I2SAudioOutput : public IAudioOutput {
public:
- I2SAudioOutput(StreamBufferHandle_t,
- drivers::IGpios& expander);
+ I2SAudioOutput(StreamBufferHandle_t, drivers::IGpios& expander);
~I2SAudioOutput();
auto SetMode(Modes) -> void override;
@@ -30,8 +29,14 @@ class I2SAudioOutput : public IAudioOutput {
auto SetVolumeDb(uint16_t) -> void;
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 AdjustVolumeDown() -> bool override;
diff --git a/src/drivers/i2s_dac.cpp b/src/drivers/i2s_dac.cpp
index 0ef1005a..4d29f917 100644
--- a/src/drivers/i2s_dac.cpp
+++ b/src/drivers/i2s_dac.cpp
@@ -95,8 +95,8 @@ I2SDac::I2SDac(IGpios& gpio, i2s_chan_handle_t i2s_handle)
vTaskDelay(pdMS_TO_TICKS(10));
wm8523::WriteRegister(wm8523::Register::kPsCtrl, 0b0);
- // Ramp volume changes
- wm8523::WriteRegister(wm8523::Register::kDacCtrl, 0b11);
+ // Use zero-cross detection for volume changes.
+ wm8523::WriteRegister(wm8523::Register::kDacCtrl, 0b10000);
}
I2SDac::~I2SDac() {
diff --git a/src/drivers/include/wm8523.hpp b/src/drivers/include/wm8523.hpp
index b13cf34b..a64f6bac 100644
--- a/src/drivers/include/wm8523.hpp
+++ b/src/drivers/include/wm8523.hpp
@@ -23,6 +23,8 @@ extern const uint16_t kLineLevelReferenceVolume;
extern const uint16_t kDefaultVolume;
extern const uint16_t kDefaultMaxVolume;
+extern const uint16_t kZeroDbVolume;
+
constexpr auto VolumeToDb(uint16_t vol) -> int_fast8_t {
return (vol - kLineLevelReferenceVolume) / 4;
}
diff --git a/src/drivers/wm8523.cpp b/src/drivers/wm8523.cpp
index 5f6c8053..9fe3e001 100644
--- a/src/drivers/wm8523.cpp
+++ b/src/drivers/wm8523.cpp
@@ -32,6 +32,8 @@ const uint16_t kDefaultVolume = kLineLevelReferenceVolume - 96;
// Default to +6dB == 2Vrms == 'CD Player'
const uint16_t kDefaultMaxVolume = kLineLevelReferenceVolume + 12;
+const uint16_t kZeroDbVolume = 0x190;
+
static const uint8_t kAddress = 0b0011010;
auto ReadRegister(Register reg) -> std::optional<uint16_t> {
diff --git a/src/ui/encoder_input.cpp b/src/ui/encoder_input.cpp
index 39aacc0c..f8b6a88b 100644
--- a/src/ui/encoder_input.cpp
+++ b/src/ui/encoder_input.cpp
@@ -194,7 +194,7 @@ auto EncoderInput::Read(lv_indev_data_t* data) -> void {
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) {
case Trigger::kNone:
break;
@@ -205,7 +205,7 @@ auto EncoderInput::Read(lv_indev_data_t* data) -> void {
break;
}
- trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kLongPress, now_ms);
+ trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kRepeat, now_ms);
switch (trigger) {
case Trigger::kNone:
break;
@@ -242,7 +242,7 @@ auto EncoderInput::Read(lv_indev_data_t* data) -> void {
break;
}
- trigger = TriggerKey(Keys::kVolumeUp, KeyStyle::kLongPress, now_ms);
+ trigger = TriggerKey(Keys::kVolumeUp, KeyStyle::kRepeat, now_ms);
switch (trigger) {
case Trigger::kNone:
break;
@@ -253,7 +253,7 @@ auto EncoderInput::Read(lv_indev_data_t* data) -> void {
break;
}
- trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kLongPress, now_ms);
+ trigger = TriggerKey(Keys::kVolumeDown, KeyStyle::kRepeat, now_ms);
switch (trigger) {
case Trigger::kNone:
break;