Skip to content

Commit a3dd796

Browse files
committed
refactor: remove static variables in members
1 parent af69f87 commit a3dd796

9 files changed

Lines changed: 286 additions & 239 deletions

File tree

include/peripherals/Display.h

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "hardware/i2c.h"
1111

1212
#include <cstdint>
13+
#include <list>
1314
#include <memory>
1415

1516
namespace Divacon::Peripherals {
@@ -30,16 +31,52 @@ class Display {
3031
Menu,
3132
};
3233

34+
class BpmCounter {
35+
private:
36+
class Buffer {
37+
private:
38+
std::list<uint16_t> m_buffer;
39+
size_t m_size_limit;
40+
41+
public:
42+
Buffer(size_t size_limit) : m_size_limit(size_limit) {};
43+
44+
void insert(uint16_t value);
45+
void clear() { m_buffer.clear(); };
46+
47+
[[nodiscard]] uint16_t getAvarage() const;
48+
};
49+
50+
static constexpr size_t WINDOW_SIZE = 20;
51+
static constexpr uint32_t DOUBLE_HIT_TIMEOUT_MS = 50;
52+
53+
uint32_t m_timeout_ms;
54+
Buffer m_buffer{WINDOW_SIZE};
55+
56+
Utils::InputState::Buttons m_prev_buttons{};
57+
uint32_t m_prev_press_time{0};
58+
59+
uint16_t m_current_bpm{0};
60+
61+
public:
62+
BpmCounter(uint32_t timeout_ms) : m_timeout_ms(timeout_ms) {};
63+
void update(const Utils::InputState::Buttons &buttons);
64+
65+
[[nodiscard]] uint16_t getBpm() const { return m_current_bpm; };
66+
};
67+
3368
Config m_config;
3469
State m_state{State::Idle};
3570

3671
uint32_t m_touched{0};
37-
Utils::InputState::Buttons m_buttons{};
3872
usb_mode_t m_usb_mode{USB_MODE_DEBUG};
3973
uint8_t m_player_id{0};
4074
Utils::Menu::State m_menu_state{};
4175

4276
ssd1306_t m_display{};
77+
uint32_t m_next_frame_time{0};
78+
79+
BpmCounter m_bpm_counter{2000};
4380

4481
void drawIdleScreen();
4582
void drawMenuScreen();

include/peripherals/TouchSlider.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,29 @@ class TouchSlider {
105105
uint32_t read() final;
106106
};
107107

108+
struct StickStates {
109+
struct State {
110+
uint8_t left_limit{0};
111+
uint8_t right_limit{UINT8_MAX};
112+
uint8_t value{Utils::InputState::AnalogStick::CENTER};
113+
};
114+
115+
State left;
116+
State right;
117+
};
118+
108119
Config m_config;
109120
usb_mode_t m_mode;
110121
uint32_t m_touched{0};
122+
StickStates m_stick_states;
111123

112124
std::unique_ptr<TouchControllerInterface> m_touch_controller;
125+
uint32_t m_last_read_time{0};
113126

114127
void read();
115128

116129
void updateInputStateArcade(Utils::InputState &input_state) const;
117-
void updateInputStateStick(Utils::InputState &input_state) const;
130+
void updateInputStateStick(Utils::InputState &input_state);
118131

119132
public:
120133
TouchSlider(const Config &config, usb_mode_t mode);

include/peripherals/TouchSliderLeds.h

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,15 @@ namespace Divacon::Peripherals {
1111

1212
class TouchSliderLeds {
1313
private:
14-
const static size_t SEGMENT_COUNT = 32;
14+
static constexpr size_t SEGMENT_COUNT = 32;
15+
16+
static constexpr uint32_t PULSE_STEPS = 4096;
17+
static constexpr uint32_t RAINBOW_STEPS = 4096;
18+
static constexpr uint32_t FADE_STEPS = 2048;
19+
static constexpr uint32_t BLEND_STEPS = 128;
20+
21+
static constexpr uint8_t PULSE_DIM_PCT_MIN = 40;
22+
static constexpr uint8_t PULSE_DIM_PCT_MAX = 100;
1523

1624
public:
1725
struct Config {
@@ -59,10 +67,42 @@ class TouchSliderLeds {
5967
using RawFrameMessage = std::array<Config::Color, SEGMENT_COUNT>;
6068

6169
private:
70+
class AnimationStepper {
71+
private:
72+
uint32_t m_steps_until_advance;
73+
uint32_t m_current_steps{0};
74+
75+
public:
76+
AnimationStepper(uint32_t steps_until_advance) : m_steps_until_advance(steps_until_advance) {};
77+
uint32_t getFrameCount(uint32_t steps);
78+
};
79+
6280
Config m_config;
6381
uint32_t m_touched{0};
6482

83+
struct {
84+
AnimationStepper stepper{PULSE_STEPS};
85+
uint8_t dim_percent{PULSE_DIM_PCT_MAX};
86+
int8_t advance_factor{-1};
87+
} m_pulse_state;
88+
89+
struct {
90+
AnimationStepper stepper{RAINBOW_STEPS};
91+
size_t position{0};
92+
} m_rainbow_state;
93+
94+
struct {
95+
AnimationStepper stepper{FADE_STEPS};
96+
std::array<uint8_t, SEGMENT_COUNT> percent{};
97+
} m_fade_state;
98+
99+
struct {
100+
AnimationStepper stepper{BLEND_STEPS};
101+
uint8_t percent{100};
102+
} m_blend_state;
103+
65104
std::vector<uint32_t> m_rendered_frame;
105+
uint32_t m_previous_frame_time{0};
66106

67107
std::array<Config::Color, SEGMENT_COUNT> m_idle_buffer{};
68108
std::array<Config::Color, SEGMENT_COUNT> m_touched_buffer{};

include/utils/InputState.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ struct InputState {
1919
};
2020

2121
struct AnalogStick {
22-
const static uint8_t CENTER = 0x80;
22+
static constexpr uint8_t CENTER = 0x80;
2323

2424
uint8_t x{CENTER}, y{CENTER};
2525
};

include/utils/Menu.h

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,38 @@ class Menu {
115115
const static std::map<Page, const Descriptor> descriptors;
116116

117117
private:
118+
class Buttons {
119+
public:
120+
enum class Id : uint8_t { Left, Right, Confirm, Back };
121+
122+
private:
123+
struct State {
124+
enum class Repeat : uint8_t {
125+
Idle,
126+
RepeatDelay,
127+
Repeat,
128+
FastRepeat,
129+
};
130+
Repeat repeat;
131+
uint32_t pressed_since;
132+
uint32_t last_repeat;
133+
bool pressed;
134+
};
135+
136+
std::map<Id, State> m_states;
137+
138+
public:
139+
Buttons();
140+
141+
void update(const InputState &state);
142+
[[nodiscard]] bool getPressed(Id id) const;
143+
};
144+
118145
std::shared_ptr<SettingsStore> m_store;
146+
Buttons m_buttons;
119147
bool m_active{false};
120-
std::stack<State> m_state_stack;
148+
149+
std::stack<State> m_state_stack{{{.page = Page::Main, .selected_value = 0, .original_value = 0}}};
121150

122151
uint8_t getCurrentValue(Page page);
123152
void gotoPage(Page page);

src/peripherals/Display.cpp

Lines changed: 38 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
#include "pico/time.h"
55

66
#include <array>
7-
#include <list>
87
#include <numeric>
98
#include <string>
109

@@ -166,79 +165,56 @@ std::string modeToString(usb_mode_t mode) {
166165
return "?";
167166
}
168167

169-
uint16_t calculateBpm(const Utils::InputState::Buttons &buttons) {
168+
} // namespace
169+
170+
void Display::BpmCounter::Buffer::insert(uint16_t value) {
171+
if (m_buffer.size() >= m_size_limit) {
172+
m_buffer.pop_back();
173+
}
174+
m_buffer.push_front(value);
175+
}
176+
177+
uint16_t Display::BpmCounter::Buffer::getAvarage() const {
178+
if (!m_buffer.empty()) {
179+
return std::accumulate(m_buffer.begin(), m_buffer.end(), 0) / m_buffer.size();
180+
}
181+
return 0;
182+
}
183+
184+
void Display::BpmCounter::update(const Utils::InputState::Buttons &buttons) {
170185
// Somewhat ugly gimmick to calculate the how often the face buttons
171186
// are pressed per minute.
172187
//
173-
// It records the average time between the last 'window_size' button
188+
// It records the average time between the last 'WINDOW_SIZE' button
174189
// presses for calculation. To avoid spikes caused by simultaneous
175-
// button presses, all presses within 'double_hit_window' are counted
190+
// button presses, all presses within 'DOUBLE_HIT_TIMEOUT_MS' are counted
176191
// as a single press.
177192
//
178-
// Counter resets after 'reset_after'.
179-
180-
static const size_t window_size = 20;
181-
static const uint32_t double_hit_window = 50;
182-
static const uint32_t reset_after = 2000;
183-
184-
static Utils::InputState::Buttons prev_buttons = {};
185-
static uint32_t prev_press = 0;
186-
static uint16_t current_bpm = 0;
187-
188-
struct StatBuffer {
189-
private:
190-
std::list<uint16_t> m_buf;
191-
size_t m_max_size;
192-
193-
public:
194-
StatBuffer(size_t max_size) : m_max_size(max_size) {}
195-
196-
void clear() { m_buf.clear(); };
197-
198-
void insert(uint16_t val) {
199-
if (m_buf.size() >= m_max_size) {
200-
m_buf.pop_back();
201-
}
202-
m_buf.push_front(val);
203-
};
204-
205-
uint16_t avg() {
206-
if (!m_buf.empty()) {
207-
return std::accumulate(m_buf.begin(), m_buf.end(), 0) / m_buf.size();
208-
}
209-
return 0;
210-
}
211-
};
212-
static StatBuffer stat_buffer(window_size);
213-
193+
// Counter resets after 'm_timeout_ms'.
214194
const uint32_t now = to_ms_since_boot(get_absolute_time());
215-
const uint32_t interval = now - prev_press;
195+
const uint32_t interval = now - m_prev_press_time;
216196

217-
if (interval > reset_after) {
218-
stat_buffer.clear();
219-
current_bpm = 0;
220-
prev_press = 0;
197+
if (interval > m_timeout_ms) {
198+
m_buffer.clear();
199+
m_current_bpm = 0;
200+
m_prev_press_time = 0;
221201
}
222202

223-
if ((interval > double_hit_window) &&
224-
((buttons.north && !prev_buttons.north) || (buttons.east && !prev_buttons.east) ||
225-
(buttons.south && !prev_buttons.south) || (buttons.west && !prev_buttons.west))) {
203+
if ((interval > DOUBLE_HIT_TIMEOUT_MS) &&
204+
((buttons.north && !m_prev_buttons.north) || (buttons.east && !m_prev_buttons.east) ||
205+
(buttons.south && !m_prev_buttons.south) || (buttons.west && !m_prev_buttons.west))) {
226206

227-
if (prev_press != 0) {
228-
stat_buffer.insert(interval);
229-
current_bpm = 60000 / stat_buffer.avg();
207+
if (m_prev_press_time != 0) {
208+
m_buffer.insert(interval);
209+
m_current_bpm = 60000 / m_buffer.getAvarage();
230210
}
231211

232-
prev_press = now;
212+
m_prev_press_time = now;
233213
}
234214

235-
prev_buttons = buttons;
236-
237-
return current_bpm;
215+
m_prev_buttons = buttons;
238216
}
239217

240-
} // namespace
241-
242218
Display::Display(const Config &config) : m_config(config) {
243219
i2c_init(m_config.i2c_block, m_config.i2c_speed_hz);
244220
gpio_set_function(m_config.sda_pin, GPIO_FUNC_I2C);
@@ -252,7 +228,7 @@ Display::Display(const Config &config) : m_config(config) {
252228
}
253229

254230
void Display::setTouched(uint32_t touched) { m_touched = touched; }
255-
void Display::setButtons(const Utils::InputState::Buttons &buttons) { m_buttons = buttons; }
231+
void Display::setButtons(const Utils::InputState::Buttons &buttons) { m_bpm_counter.update(buttons); }
256232
void Display::setUsbMode(usb_mode_t mode) { m_usb_mode = mode; };
257233
void Display::setPlayerId(uint8_t player_id) { m_player_id = player_id; };
258234

@@ -268,7 +244,7 @@ void Display::drawIdleScreen() {
268244
ssd1306_draw_line(&m_display, 0, 10, 128, 10);
269245

270246
// BPM
271-
auto bpm_str = std::to_string(calculateBpm(m_buttons)) + " bpm";
247+
auto bpm_str = std::to_string(m_bpm_counter.getBpm()) + " bpm";
272248
ssd1306_draw_string(&m_display, (127 - (bpm_str.length() * 12)) / 2, 20, 2, bpm_str.c_str());
273249

274250
// Player "LEDs"
@@ -360,13 +336,12 @@ void Display::drawMenuScreen() {
360336
}
361337

362338
void Display::update() {
363-
static const uint32_t interval_ms = 20; // Limit to ~50fps
364-
static uint32_t start_ms = 0;
339+
static const uint32_t interval_ms = 17; // Limit to ~60fps
365340

366-
if (to_ms_since_boot(get_absolute_time()) - start_ms < interval_ms) {
341+
if (to_ms_since_boot(get_absolute_time()) - m_next_frame_time < interval_ms) {
367342
return;
368343
}
369-
start_ms += interval_ms;
344+
m_next_frame_time += interval_ms;
370345

371346
ssd1306_clear(&m_display);
372347

0 commit comments

Comments
 (0)