Implement basic volume control for bt outputs

custom
jacqueline 1 year ago
parent 99c56641e9
commit 0bb12912bc
  1. 3
      src/audio/audio_fsm.cpp
  2. 24
      src/audio/bt_audio_output.cpp
  3. 8
      src/audio/include/bt_audio_output.hpp
  4. 21
      src/drivers/bluetooth.cpp
  5. 9
      src/drivers/include/bluetooth.hpp

@ -171,7 +171,8 @@ void Uninitialised::react(const system_fsm::BootComplete& ev) {
sFileSource.reset(
new FatfsAudioInput(sServices->tag_parser(), sServices->bg_worker()));
sI2SOutput.reset(new I2SAudioOutput(stream, sServices->gpios()));
sBtOutput.reset(new BluetoothAudioOutput(stream, sServices->bluetooth()));
sBtOutput.reset(new BluetoothAudioOutput(stream, sServices->bluetooth(),
sServices->bg_worker()));
auto& nvs = sServices->nvs();
sI2SOutput->SetMaxVolume(nvs.AmpMaxVolume());

@ -21,6 +21,7 @@
#include "i2c.hpp"
#include "i2s_dac.hpp"
#include "result.hpp"
#include "tasks.hpp"
#include "wm8523.hpp"
[[maybe_unused]] static const char* kTag = "BTOUT";
@ -28,8 +29,9 @@
namespace audio {
BluetoothAudioOutput::BluetoothAudioOutput(StreamBufferHandle_t s,
drivers::Bluetooth& bt)
: IAudioOutput(s), bluetooth_(bt) {}
drivers::Bluetooth& bt,
tasks::WorkerPool& p)
: IAudioOutput(s), bluetooth_(bt), bg_worker_(p), volume_(10) {}
BluetoothAudioOutput::~BluetoothAudioOutput() {}
@ -43,14 +45,16 @@ auto BluetoothAudioOutput::SetMode(Modes mode) -> void {
auto BluetoothAudioOutput::SetVolumeImbalance(int_fast8_t balance) -> void {}
auto BluetoothAudioOutput::SetVolume(uint16_t) -> void {}
auto BluetoothAudioOutput::SetVolume(uint16_t v) -> void {
volume_ = std::clamp<uint16_t>(v, 0, 0x7f);
}
auto BluetoothAudioOutput::GetVolume() -> uint16_t {
return 0;
return volume_;
}
auto BluetoothAudioOutput::GetVolumePct() -> uint_fast8_t {
return 0;
return static_cast<uint_fast8_t>(static_cast<int>(volume_) * 100 / 0x7f);
}
auto BluetoothAudioOutput::GetVolumeDb() -> int_fast16_t {
@ -58,11 +62,21 @@ auto BluetoothAudioOutput::GetVolumeDb() -> int_fast16_t {
}
auto BluetoothAudioOutput::AdjustVolumeUp() -> bool {
if (volume_ == 0x7f) {
return false;
}
volume_++;
bg_worker_.Dispatch<void>([&]() { bluetooth_.SetVolume(volume_); });
return true;
}
auto BluetoothAudioOutput::AdjustVolumeDown() -> bool {
if (volume_ == 0) {
return false;
}
volume_--;
bg_worker_.Dispatch<void>([&]() { bluetooth_.SetVolume(volume_); });
return true;
}
auto BluetoothAudioOutput::PrepareFormat(const Format& orig) -> Format {

@ -6,6 +6,7 @@
#pragma once
#include <stdint.h>
#include <cstdint>
#include <memory>
#include <vector>
@ -16,12 +17,15 @@
#include "bluetooth.hpp"
#include "gpios.hpp"
#include "i2s_dac.hpp"
#include "tasks.hpp"
namespace audio {
class BluetoothAudioOutput : public IAudioOutput {
public:
BluetoothAudioOutput(StreamBufferHandle_t, drivers::Bluetooth& bt);
BluetoothAudioOutput(StreamBufferHandle_t,
drivers::Bluetooth& bt,
tasks::WorkerPool&);
~BluetoothAudioOutput();
auto SetMode(Modes) -> void override;
@ -46,6 +50,8 @@ class BluetoothAudioOutput : public IAudioOutput {
private:
drivers::Bluetooth& bluetooth_;
tasks::WorkerPool& bg_worker_;
uint8_t volume_;
};
} // namespace audio

@ -17,6 +17,7 @@
#include "esp_bt_defs.h"
#include "esp_bt_device.h"
#include "esp_bt_main.h"
#include "esp_err.h"
#include "esp_gap_bt_api.h"
#include "esp_log.h"
#include "esp_mac.h"
@ -149,6 +150,11 @@ auto Bluetooth::SetSource(StreamBufferHandle_t src) -> void {
bluetooth::events::SourceChanged{});
}
auto Bluetooth::SetVolume(uint8_t vol) -> void {
tinyfsm::FsmList<bluetooth::BluetoothState>::dispatch(
bluetooth::events::ChangeVolume{.volume = vol});
}
auto Bluetooth::SetEventHandler(std::function<void(bluetooth::Event)> cb)
-> void {
bluetooth::BluetoothState::event_handler(cb);
@ -401,6 +407,8 @@ void Disabled::entry() {
sScanner_->StopScanningNow();
esp_a2d_source_deinit();
esp_avrc_ct_deinit();
esp_bluedroid_disable();
esp_bluedroid_deinit();
esp_bt_controller_disable();
@ -603,6 +611,7 @@ void Connecting::react(const events::internal::A2dp& ev) {
void Connected::entry() {
ESP_LOGI(kTag, "entering connected state");
transaction_num_ = 0;
connected_to_ = sConnectingDevice_->mac;
sPreferredDevice_ = sConnectingDevice_;
sConnectingDevice_ = {};
@ -639,6 +648,18 @@ void Connected::react(const events::SourceChanged& ev) {
}
}
void Connected::react(const events::ChangeVolume& ev) {
ESP_LOGI(kTag, "send vol %u", ev.volume);
esp_err_t err = esp_avrc_ct_send_set_absolute_volume_cmd(
transaction_num_++, std::clamp<uint8_t>(ev.volume, 0, 0x7f));
if (err != ESP_OK) {
ESP_LOGW(kTag, "send vol failed %u", err);
}
if (transaction_num_ > ESP_AVRC_TRANS_LABEL_MAX) {
transaction_num_ = 0;
}
}
void Connected::react(const events::internal::Gap& ev) {
sScanner_->HandleGapEvent(ev);
switch (ev.type) {

@ -11,6 +11,7 @@
#include <freertos/FreeRTOS.h>
#include <freertos/stream_buffer.h>
#include <stdint.h>
#include "bluetooth_types.hpp"
#include "esp_a2dp_api.h"
#include "esp_avrc_api.h"
@ -48,6 +49,8 @@ class Bluetooth {
auto PreferredDevice() -> std::optional<bluetooth::MacAndName>;
auto SetSource(StreamBufferHandle_t) -> void;
auto SetVolume(uint8_t) -> void;
auto SetEventHandler(std::function<void(bluetooth::Event)> cb) -> void;
};
@ -63,6 +66,9 @@ struct DiscoveryChanged : public tinyfsm::Event {};
struct DeviceDiscovered : public tinyfsm::Event {
const Device& device;
};
struct ChangeVolume : public tinyfsm::Event {
const uint8_t volume;
};
namespace internal {
struct Gap : public tinyfsm::Event {
@ -129,6 +135,7 @@ class BluetoothState : public tinyfsm::Fsm<BluetoothState> {
virtual void react(const events::PreferredDeviceChanged& ev){};
virtual void react(const events::SourceChanged& ev){};
virtual void react(const events::DiscoveryChanged&);
virtual void react(const events::ChangeVolume&) {}
virtual void react(const events::DeviceDiscovered&);
@ -198,6 +205,7 @@ class Connected : public BluetoothState {
void react(const events::PreferredDeviceChanged& ev) override;
void react(const events::SourceChanged& ev) override;
void react(const events::ChangeVolume&) override;
void react(const events::Disable& ev) override;
void react(const events::internal::Gap& ev) override;
@ -207,6 +215,7 @@ class Connected : public BluetoothState {
using BluetoothState::react;
private:
uint8_t transaction_num_;
mac_addr_t connected_to_;
};

Loading…
Cancel
Save