diff options
| author | jacqueline <me@jacqueline.id.au> | 2024-07-11 15:11:28 +1000 |
|---|---|---|
| committer | jacqueline <me@jacqueline.id.au> | 2024-07-11 15:11:28 +1000 |
| commit | a3eb2dd9dc2399ce9c22cd3b07f482f080976440 (patch) | |
| tree | 4a7883755d07b7d9a391d5b6e7858c0ab26e3bdd /src/drivers/include | |
| parent | a9d2335e1d86b3012789a440e7f0e71033393056 (diff) | |
| download | tangara-fw-a3eb2dd9dc2399ce9c22cd3b07f482f080976440.tar.gz | |
WIP improve bluetooth api and settings screen
Diffstat (limited to 'src/drivers/include')
| -rw-r--r-- | src/drivers/include/drivers/bluetooth.hpp | 116 | ||||
| -rw-r--r-- | src/drivers/include/drivers/bluetooth_types.hpp | 7 | ||||
| -rw-r--r-- | src/drivers/include/drivers/nvs.hpp | 7 |
3 files changed, 89 insertions, 41 deletions
diff --git a/src/drivers/include/drivers/bluetooth.hpp b/src/drivers/include/drivers/bluetooth.hpp index 94a85263..449812d6 100644 --- a/src/drivers/include/drivers/bluetooth.hpp +++ b/src/drivers/include/drivers/bluetooth.hpp @@ -3,6 +3,7 @@ #include <array> #include <atomic> +#include <functional> #include <map> #include <mutex> #include <optional> @@ -25,28 +26,68 @@ namespace drivers { /* - * A handle used to interact with the bluetooth state machine. + * A handle used to interact with the bluetooth state machine. This is the main + * API that the rest of the system should use to interact with Bluetooth. */ class Bluetooth { public: - Bluetooth(NvsStorage& storage, tasks::WorkerPool&); + /* + * Callback invoked when an event is generated by the Bluetooth stack. This + * callback is invoked synchronously from a Bluetooth task context, so + * implementations should immediately hop to a different task to process the + * event. + */ + using EventHandler = std::function<void(bluetooth::Event)>; + + Bluetooth(NvsStorage&, tasks::WorkerPool&, EventHandler); + + /* Enables or disables the entire Bluetooth stack. */ + auto enable(bool en) -> void; + auto enabled() -> bool; + + auto source(PcmBuffer*) -> void; + auto softVolume(float) -> void; + + enum class ConnectionState { + kConnected, + kConnecting, + kDisconnected, + }; + + auto connectionState() -> ConnectionState; + + /* + * The 'paired' device is a device that will be preferred for connections. + * When Bluetooth is first enabled, we immediately try to connect to the + * paired device. If the paired device is seen during a scan, then we will + * also automatically connect to it. + */ + auto pairedDevice() -> std::optional<bluetooth::MacAndName>; + + /* + * Sets the preferred device. If a device is provided, a connection will be + * attempted immediately, even if the device has not been detected in a + * previous scan. + */ + auto pairedDevice(std::optional<bluetooth::MacAndName> dev) -> void; + + /* A list of devices that have previously been the paired device. */ + auto knownDevices() -> std::vector<bluetooth::MacAndName>; + auto forgetKnownDevice(const bluetooth::mac_addr_t&) -> void; + + /* Enables or disables scanning for nearby Bluetooth devices. */ + auto discoveryEnabled(bool) -> void; + auto discoveryEnabled() -> bool; + + /* + * A list of nearby devices that have been discovered since discovery was + * last enabled. This list may include the paired device, as well as devices + * that are also present in the known devices list. + */ + auto discoveredDevices() -> std::vector<bluetooth::MacAndName>; - auto Enable() -> bool; - auto Disable() -> void; - auto IsEnabled() -> bool; - - auto IsConnected() -> bool; - auto ConnectedDevice() -> std::optional<bluetooth::MacAndName>; - - auto KnownDevices() -> std::vector<bluetooth::Device>; - - auto SetPreferredDevice(std::optional<bluetooth::MacAndName> dev) -> void; - auto PreferredDevice() -> std::optional<bluetooth::MacAndName>; - - auto SetSource(PcmBuffer*) -> void; - auto SetVolumeFactor(float) -> void; - - auto SetEventHandler(std::function<void(bluetooth::Event)> cb) -> void; + private: + NvsStorage& nvs_; }; namespace bluetooth { @@ -56,7 +97,7 @@ struct Enable : public tinyfsm::Event {}; struct Disable : public tinyfsm::Event {}; struct ConnectTimedOut : public tinyfsm::Event {}; -struct PreferredDeviceChanged : public tinyfsm::Event {}; +struct PairedDeviceChanged : public tinyfsm::Event {}; struct SourceChanged : public tinyfsm::Event {}; struct DeviceDiscovered : public tinyfsm::Event { const Device& device; @@ -94,6 +135,8 @@ class Scanner { auto StopScanning() -> void; auto StopScanningNow() -> void; + auto enabled() -> bool; + auto HandleGapEvent(const events::internal::Gap&) -> void; private: @@ -103,25 +146,22 @@ class Scanner { auto HandleDeviceDiscovery(const esp_bt_gap_cb_param_t& param) -> void; }; +/* + * The main state machine for managing the state of the Bluetooth stack, and + * the current (if any) Bluetooth connection. + */ class BluetoothState : public tinyfsm::Fsm<BluetoothState> { public: - static auto Init(NvsStorage& storage) -> void; + static auto Init(NvsStorage& storage, Bluetooth::EventHandler) -> void; static auto lock() -> std::lock_guard<std::mutex>; - static auto devices() -> std::vector<Device>; - - static auto preferred_device() -> std::optional<bluetooth::MacAndName>; - static auto preferred_device(std::optional<bluetooth::MacAndName>) -> void; + static auto pairedDevice() -> std::optional<bluetooth::MacAndName>; + static auto pairedDevice(std::optional<bluetooth::MacAndName>) -> void; - static auto scanning() -> bool; static auto discovery() -> bool; static auto discovery(bool) -> void; - - static auto source() -> PcmBuffer*; - static auto source(PcmBuffer*) -> void; - - static auto event_handler(std::function<void(Event)>) -> void; + static auto discoveredDevices() -> std::vector<Device>; virtual ~BluetoothState(){}; @@ -131,7 +171,7 @@ class BluetoothState : public tinyfsm::Fsm<BluetoothState> { virtual void react(const events::Enable& ev){}; virtual void react(const events::Disable& ev) = 0; virtual void react(const events::ConnectTimedOut& ev){}; - virtual void react(const events::PreferredDeviceChanged& ev){}; + virtual void react(const events::PairedDeviceChanged& ev){}; virtual void react(const events::SourceChanged& ev){}; virtual void react(const events::DeviceDiscovered&); @@ -146,13 +186,11 @@ class BluetoothState : public tinyfsm::Fsm<BluetoothState> { static Scanner* sScanner_; static std::mutex sFsmMutex; - static std::map<mac_addr_t, Device> sDevices_; - static std::optional<bluetooth::MacAndName> sPreferredDevice_; - - static std::optional<bluetooth::MacAndName> sConnectingDevice_; + static std::map<mac_addr_t, Device> sDiscoveredDevices_; + static std::optional<bluetooth::MacAndName> sPairedWith_; + static std::optional<bluetooth::MacAndName> sConnectingTo_; static int sConnectAttemptsRemaining_; - static std::atomic<PcmBuffer*> sSource_; static std::function<void(Event)> sEventHandler_; auto connect(const bluetooth::MacAndName&) -> bool; @@ -177,7 +215,7 @@ class Idle : public BluetoothState { void exit() override; void react(const events::Disable& ev) override; - void react(const events::PreferredDeviceChanged& ev) override; + void react(const events::PairedDeviceChanged& ev) override; void react(events::internal::Gap ev) override; @@ -189,7 +227,7 @@ class Connecting : public BluetoothState { void entry() override; void exit() override; - void react(const events::PreferredDeviceChanged& ev) override; + void react(const events::PairedDeviceChanged& ev) override; void react(const events::ConnectTimedOut& ev) override; void react(const events::Disable& ev) override; @@ -204,7 +242,7 @@ class Connected : public BluetoothState { void entry() override; void exit() override; - void react(const events::PreferredDeviceChanged& ev) override; + void react(const events::PairedDeviceChanged& ev) override; void react(const events::SourceChanged& ev) override; void react(const events::Disable& ev) override; diff --git a/src/drivers/include/drivers/bluetooth_types.hpp b/src/drivers/include/drivers/bluetooth_types.hpp index d2e55ee5..05caee47 100644 --- a/src/drivers/include/drivers/bluetooth_types.hpp +++ b/src/drivers/include/drivers/bluetooth_types.hpp @@ -27,9 +27,12 @@ struct Device { }; enum class SimpleEvent { - kKnownDevicesChanged, kConnectionStateChanged, - kPreferredDeviceChanged, + kPairedDeviceChanged, + kKnownDevicesChanged, + kDiscoveryChanged, + kDeviceDiscovered, + // Passthrough events kPlayPause, kStop, diff --git a/src/drivers/include/drivers/nvs.hpp b/src/drivers/include/drivers/nvs.hpp index 88dd5ae0..2bc77a31 100644 --- a/src/drivers/include/drivers/nvs.hpp +++ b/src/drivers/include/drivers/nvs.hpp @@ -96,6 +96,10 @@ class NvsStorage { auto BluetoothVolume(const bluetooth::mac_addr_t&) -> uint8_t; auto BluetoothVolume(const bluetooth::mac_addr_t&, uint8_t) -> void; + auto BluetoothNames() -> std::vector<bluetooth::MacAndName>; + auto BluetoothName(const bluetooth::mac_addr_t&, std::optional<std::string>) + -> void; + enum class Output : uint8_t { kHeadphones = 0, kBluetooth = 1, @@ -154,7 +158,10 @@ class NvsStorage { Setting<int8_t> amp_left_bias_; Setting<uint8_t> input_mode_; Setting<uint8_t> output_mode_; + Setting<bluetooth::MacAndName> bt_preferred_; + Setting<std::vector<bluetooth::MacAndName>> bt_names_; + Setting<uint8_t> db_auto_index_; util::LruCache<10, bluetooth::mac_addr_t, uint8_t> bt_volumes_; |
