1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
/*
* Copyright 2023 jacqueline <me@jacqueline.id.au>
*
* SPDX-License-Identifier: GPL-3.0-only
*/
#pragma once
#include <stdint.h>
#include <memory>
#include <optional>
#include "esp_err.h"
#include "nvs.h"
#include "bluetooth_types.hpp"
#include "lru_cache.hpp"
#include "tasks.hpp"
namespace drivers {
/*
* Wrapper for a single NVS setting, with its backing value cached in memory.
* NVS values that are just plain old data should generally use these for
* simpler implementation.
*/
template <typename T>
class Setting {
public:
Setting(const char* name) : name_(name), val_(), dirty_(false) {}
auto set(const std::optional<T>&& v) -> void {
if (val_.has_value() != v.has_value() || *val_ != *v) {
val_ = v;
dirty_ = true;
}
}
auto get() -> std::optional<T>& { return val_; }
/* Reads the stored value from NVS and parses it into the correct type. */
auto load(nvs_handle_t) -> std::optional<T>;
/* Encodes the given value and writes it to NVS. */
auto store(nvs_handle_t, T v) -> void;
auto read(nvs_handle_t nvs) -> void { val_ = load(nvs); }
auto write(nvs_handle_t nvs) -> void {
if (!dirty_) {
return;
}
dirty_ = false;
if (val_) {
store(nvs, *val_);
} else {
nvs_erase_key(nvs, name_);
}
}
private:
const char* name_;
std::optional<T> val_;
bool dirty_;
};
class NvsStorage {
public:
static auto OpenSync() -> NvsStorage*;
auto Read() -> void;
auto Write() -> bool;
auto LockPolarity() -> bool;
auto LockPolarity(bool) -> void;
auto DisplaySize()
-> std::pair<std::optional<uint16_t>, std::optional<uint16_t>>;
auto DisplaySize(std::pair<std::optional<uint16_t>, std::optional<uint16_t>>)
-> void;
auto PreferredBluetoothDevice() -> std::optional<bluetooth::MacAndName>;
auto PreferredBluetoothDevice(std::optional<bluetooth::MacAndName>) -> void;
auto BluetoothVolume(const bluetooth::mac_addr_t&) -> uint8_t;
auto BluetoothVolume(const bluetooth::mac_addr_t&, uint8_t) -> void;
enum class Output : uint8_t {
kHeadphones = 0,
kBluetooth = 1,
};
auto OutputMode() -> Output;
auto OutputMode(Output) -> void;
auto ScreenBrightness() -> uint_fast8_t;
auto ScreenBrightness(uint_fast8_t) -> void;
auto ScrollSensitivity() -> uint_fast8_t;
auto ScrollSensitivity(uint_fast8_t) -> void;
auto AmpMaxVolume() -> uint16_t;
auto AmpMaxVolume(uint16_t) -> void;
auto AmpCurrentVolume() -> uint16_t;
auto AmpCurrentVolume(uint16_t) -> void;
auto AmpLeftBias() -> int_fast8_t;
auto AmpLeftBias(int_fast8_t) -> void;
enum class InputModes : uint8_t {
kButtonsOnly = 0,
kButtonsWithWheel = 1,
kDirectionalWheel = 2,
kRotatingWheel = 3,
};
auto PrimaryInput() -> InputModes;
auto PrimaryInput(InputModes) -> void;
explicit NvsStorage(nvs_handle_t);
~NvsStorage();
private:
auto DowngradeSchemaSync() -> bool;
auto SchemaVersionSync() -> uint8_t;
std::mutex mutex_;
nvs_handle_t handle_;
Setting<uint8_t> lock_polarity_;
Setting<uint16_t> display_cols_;
Setting<uint16_t> display_rows_;
Setting<uint8_t> brightness_;
Setting<uint8_t> sensitivity_;
Setting<uint16_t> amp_max_vol_;
Setting<uint16_t> amp_cur_vol_;
Setting<int8_t> amp_left_bias_;
Setting<uint8_t> input_mode_;
Setting<uint8_t> output_mode_;
Setting<bluetooth::MacAndName> bt_preferred_;
util::LruCache<10, bluetooth::mac_addr_t, uint8_t> bt_volumes_;
bool bt_volumes_dirty_;
auto readBtVolumes() -> void;
auto writeBtVolumes() -> void;
};
} // namespace drivers
|