Skip to content

Commit 0ca5bac

Browse files
authored
Merge pull request #9 from esp-cpp/feature/haptic-configuration
Haptic Feedback Configuration (on settings page)
2 parents 63736ad + 1a84c7f commit 0ca5bac

File tree

7 files changed

+185
-24
lines changed

7 files changed

+185
-24
lines changed

components/drv2605/include/drv2605.hpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,17 @@ class Drv2605 {
1010

1111
/**
1212
* @brief Function to write a byte to a register
13-
* @param uint8_t register address to write to
14-
* @param uint8_t data to write
13+
* @param reg_addr register address to write to
14+
* @param data Data to write
1515
*/
16-
typedef std::function<void(uint8_t, uint8_t)> write_fn;
16+
typedef std::function<void(uint8_t reg_addr, uint8_t data)> write_fn;
1717

1818
/**
1919
* @brief Function to read a byte from a register
20-
* @param uint8_t register address to read from
20+
* @param reg_addr register address to read from
2121
* @return Byte read from the register
2222
*/
23-
typedef std::function<uint8_t(uint8_t)> read_fn;
23+
typedef std::function<uint8_t(uint8_t reg_addr)> read_fn;
2424

2525
enum class Mode : uint8_t {
2626
INTTRIG, ///< Internal Trigger (call star() to start playback)
@@ -42,7 +42,7 @@ class Drv2605 {
4242
DOUBLE_CLICK = 10,
4343
TRIPLE_CLICK = 12,
4444
SOFT_FUZZ = 13,
45-
STRONG_BUZZ = 13,
45+
STRONG_BUZZ = 14,
4646
ALERT_750MS = 15,
4747
ALERT_1000MS = 16, // omg there are 123 of theese i'm not typing them out right now...
4848
BUZZ1 = 47,
@@ -65,10 +65,10 @@ class Drv2605 {
6565
};
6666

6767
struct Config {
68-
write_fn write;
69-
read_fn read;
70-
MotorType motor_type{MotorType::ERM};
71-
espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN};
68+
write_fn write; /**< Function for writing a byte to a register on the Drv2605. */
69+
read_fn read; /**< Function for reading a byte from a register on the Drv2605. */
70+
MotorType motor_type{MotorType::ERM}; /**< MotorType that this driver is driving. */
71+
espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN}; /**< Log verbosity for the Drv2605. */
7272
};
7373

7474
Drv2605(const Config& config)

components/gui/generated/ui.c

Lines changed: 87 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ lv_obj_t *ui_settingsscreen_Label3;
3636
lv_obj_t *ui_fillpanel;
3737
lv_obj_t *ui_settingsscreen_Label4;
3838
lv_obj_t *ui_videosettingdropdown;
39+
lv_obj_t *ui_hapticpanel;
40+
lv_obj_t *ui_settingsscreen_Label5;
41+
lv_obj_t *ui_settingsscreen_Panel1;
42+
lv_obj_t *ui_hapticlabel;
43+
lv_obj_t *ui_hapticdownbutton;
44+
lv_obj_t *ui_settingsscreen_Label7;
45+
lv_obj_t *ui_hapticupbutton;
46+
lv_obj_t *ui_settingsscreen_Label6;
47+
lv_obj_t *ui_hapticplaybutton;
48+
lv_obj_t *ui_settingsscreen_Label8;
3949

4050
///////////////////// TEST LVGL SETTINGS ////////////////////
4151
#if LV_COLOR_DEPTH != 16
@@ -164,6 +174,11 @@ lv_obj_set_height( ui_settingspanel, 165);
164174
lv_obj_set_width( ui_settingspanel, lv_pct(100));
165175
lv_obj_set_align( ui_settingspanel, LV_ALIGN_BOTTOM_MID );
166176
lv_obj_add_flag( ui_settingspanel, LV_OBJ_FLAG_SCROLL_ON_FOCUS | LV_OBJ_FLAG_SCROLL_ONE ); /// Flags
177+
lv_obj_set_scroll_dir(ui_settingspanel, LV_DIR_VER);
178+
lv_obj_set_style_pad_left(ui_settingspanel, 0, LV_PART_MAIN| LV_STATE_DEFAULT);
179+
lv_obj_set_style_pad_right(ui_settingspanel, 0, LV_PART_MAIN| LV_STATE_DEFAULT);
180+
lv_obj_set_style_pad_top(ui_settingspanel, 0, LV_PART_MAIN| LV_STATE_DEFAULT);
181+
lv_obj_set_style_pad_bottom(ui_settingspanel, 0, LV_PART_MAIN| LV_STATE_DEFAULT);
167182

168183
ui_volumepanel = lv_obj_create(ui_settingspanel);
169184
lv_obj_set_height( ui_volumepanel, 50);
@@ -173,9 +188,9 @@ lv_obj_clear_flag( ui_volumepanel, LV_OBJ_FLAG_SCROLLABLE ); /// Flags
173188

174189
ui_volumebar = lv_bar_create(ui_volumepanel);
175190
lv_bar_set_value(ui_volumebar,25,LV_ANIM_OFF);
176-
lv_obj_set_width( ui_volumebar, 150);
191+
lv_obj_set_width( ui_volumebar, 130);
177192
lv_obj_set_height( ui_volumebar, 10);
178-
lv_obj_set_x( ui_volumebar, 20 );
193+
lv_obj_set_x( ui_volumebar, 25 );
179194
lv_obj_set_y( ui_volumebar, 0 );
180195
lv_obj_set_align( ui_volumebar, LV_ALIGN_CENTER );
181196

@@ -210,8 +225,6 @@ lv_label_set_text(ui_settingsscreen_Label2, LV_SYMBOL_VOLUME_MID);
210225
ui_volumeupbutton = lv_btn_create(ui_volumepanel);
211226
lv_obj_set_width( ui_volumeupbutton, 32);
212227
lv_obj_set_height( ui_volumeupbutton, 32);
213-
lv_obj_set_x( ui_volumeupbutton, -10 );
214-
lv_obj_set_y( ui_volumeupbutton, 0 );
215228
lv_obj_set_align( ui_volumeupbutton, LV_ALIGN_RIGHT_MID );
216229
lv_obj_add_flag( ui_volumeupbutton, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags
217230
lv_obj_clear_flag( ui_volumeupbutton, LV_OBJ_FLAG_SCROLLABLE ); /// Flags
@@ -226,7 +239,7 @@ ui_fillpanel = lv_obj_create(ui_settingspanel);
226239
lv_obj_set_height( ui_fillpanel, 50);
227240
lv_obj_set_width( ui_fillpanel, lv_pct(100));
228241
lv_obj_set_x( ui_fillpanel, 0 );
229-
lv_obj_set_y( ui_fillpanel, 50 );
242+
lv_obj_set_y( ui_fillpanel, 60 );
230243
lv_obj_set_align( ui_fillpanel, LV_ALIGN_TOP_MID );
231244
lv_obj_clear_flag( ui_fillpanel, LV_OBJ_FLAG_SCROLLABLE ); /// Flags
232245

@@ -243,6 +256,75 @@ lv_obj_set_height( ui_videosettingdropdown, LV_SIZE_CONTENT); /// 1
243256
lv_obj_set_align( ui_videosettingdropdown, LV_ALIGN_RIGHT_MID );
244257
lv_obj_add_flag( ui_videosettingdropdown, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags
245258

259+
ui_hapticpanel = lv_obj_create(ui_settingspanel);
260+
lv_obj_set_height( ui_hapticpanel, 50);
261+
lv_obj_set_width( ui_hapticpanel, lv_pct(100));
262+
lv_obj_set_x( ui_hapticpanel, 0 );
263+
lv_obj_set_y( ui_hapticpanel, 120 );
264+
lv_obj_set_align( ui_hapticpanel, LV_ALIGN_TOP_MID );
265+
lv_obj_clear_flag( ui_hapticpanel, LV_OBJ_FLAG_SCROLLABLE ); /// Flags
266+
267+
ui_settingsscreen_Label5 = lv_label_create(ui_hapticpanel);
268+
lv_obj_set_width( ui_settingsscreen_Label5, LV_SIZE_CONTENT); /// 1
269+
lv_obj_set_height( ui_settingsscreen_Label5, LV_SIZE_CONTENT); /// 1
270+
lv_obj_set_align( ui_settingsscreen_Label5, LV_ALIGN_LEFT_MID );
271+
lv_label_set_text(ui_settingsscreen_Label5,"Haptics");
272+
273+
ui_settingsscreen_Panel1 = lv_obj_create(ui_hapticpanel);
274+
lv_obj_set_width( ui_settingsscreen_Panel1, 140);
275+
lv_obj_set_height( ui_settingsscreen_Panel1, 50);
276+
lv_obj_set_x( ui_settingsscreen_Panel1, -30 );
277+
lv_obj_set_y( ui_settingsscreen_Panel1, 0 );
278+
lv_obj_set_align( ui_settingsscreen_Panel1, LV_ALIGN_RIGHT_MID );
279+
lv_obj_clear_flag( ui_settingsscreen_Panel1, LV_OBJ_FLAG_SCROLLABLE ); /// Flags
280+
lv_obj_set_style_border_color(ui_settingsscreen_Panel1, lv_color_hex(0x000000), LV_PART_MAIN | LV_STATE_DEFAULT );
281+
lv_obj_set_style_border_opa(ui_settingsscreen_Panel1, 0, LV_PART_MAIN| LV_STATE_DEFAULT);
282+
283+
ui_hapticlabel = lv_label_create(ui_settingsscreen_Panel1);
284+
lv_obj_set_width( ui_hapticlabel, LV_SIZE_CONTENT); /// 1
285+
lv_obj_set_height( ui_hapticlabel, LV_SIZE_CONTENT); /// 1
286+
lv_obj_set_align( ui_hapticlabel, LV_ALIGN_CENTER );
287+
lv_label_set_text(ui_hapticlabel,"128");
288+
289+
ui_hapticdownbutton = lv_btn_create(ui_settingsscreen_Panel1);
290+
lv_obj_set_width( ui_hapticdownbutton, 32);
291+
lv_obj_set_height( ui_hapticdownbutton, 32);
292+
lv_obj_set_align( ui_hapticdownbutton, LV_ALIGN_LEFT_MID );
293+
lv_obj_add_flag( ui_hapticdownbutton, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags
294+
lv_obj_clear_flag( ui_hapticdownbutton, LV_OBJ_FLAG_SCROLLABLE ); /// Flags
295+
296+
ui_settingsscreen_Label7 = lv_label_create(ui_hapticdownbutton);
297+
lv_obj_set_width( ui_settingsscreen_Label7, LV_SIZE_CONTENT); /// 1
298+
lv_obj_set_height( ui_settingsscreen_Label7, LV_SIZE_CONTENT); /// 1
299+
lv_obj_set_align( ui_settingsscreen_Label7, LV_ALIGN_CENTER );
300+
lv_label_set_text(ui_settingsscreen_Label7, LV_SYMBOL_MINUS);
301+
302+
ui_hapticupbutton = lv_btn_create(ui_settingsscreen_Panel1);
303+
lv_obj_set_width( ui_hapticupbutton, 32);
304+
lv_obj_set_height( ui_hapticupbutton, 32);
305+
lv_obj_set_align( ui_hapticupbutton, LV_ALIGN_RIGHT_MID );
306+
lv_obj_add_flag( ui_hapticupbutton, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags
307+
lv_obj_clear_flag( ui_hapticupbutton, LV_OBJ_FLAG_SCROLLABLE ); /// Flags
308+
309+
ui_settingsscreen_Label6 = lv_label_create(ui_hapticupbutton);
310+
lv_obj_set_width( ui_settingsscreen_Label6, LV_SIZE_CONTENT); /// 1
311+
lv_obj_set_height( ui_settingsscreen_Label6, LV_SIZE_CONTENT); /// 1
312+
lv_obj_set_align( ui_settingsscreen_Label6, LV_ALIGN_CENTER );
313+
lv_label_set_text(ui_settingsscreen_Label6, LV_SYMBOL_PLUS);
314+
315+
ui_hapticplaybutton = lv_btn_create(ui_hapticpanel);
316+
lv_obj_set_width( ui_hapticplaybutton, 32);
317+
lv_obj_set_height( ui_hapticplaybutton, 32);
318+
lv_obj_set_align( ui_hapticplaybutton, LV_ALIGN_RIGHT_MID );
319+
lv_obj_add_flag( ui_hapticplaybutton, LV_OBJ_FLAG_SCROLL_ON_FOCUS ); /// Flags
320+
lv_obj_clear_flag( ui_hapticplaybutton, LV_OBJ_FLAG_SCROLLABLE ); /// Flags
321+
322+
ui_settingsscreen_Label8 = lv_label_create(ui_hapticplaybutton);
323+
lv_obj_set_width( ui_settingsscreen_Label8, LV_SIZE_CONTENT); /// 1
324+
lv_obj_set_height( ui_settingsscreen_Label8, LV_SIZE_CONTENT); /// 1
325+
lv_obj_set_align( ui_settingsscreen_Label8, LV_ALIGN_CENTER );
326+
lv_label_set_text(ui_settingsscreen_Label8, LV_SYMBOL_PLAY);
327+
246328
lv_obj_add_event_cb(ui_closebutton, ui_event_closebutton, LV_EVENT_ALL, NULL);
247329

248330
}

components/gui/generated/ui.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ extern lv_obj_t *ui_settingsscreen_Label3;
4141
extern lv_obj_t *ui_fillpanel;
4242
extern lv_obj_t *ui_settingsscreen_Label4;
4343
extern lv_obj_t *ui_videosettingdropdown;
44+
extern lv_obj_t *ui_hapticpanel;
45+
extern lv_obj_t *ui_settingsscreen_Label5;
46+
extern lv_obj_t *ui_settingsscreen_Panel1;
47+
extern lv_obj_t *ui_hapticlabel;
48+
extern lv_obj_t *ui_hapticdownbutton;
49+
extern lv_obj_t *ui_settingsscreen_Label7;
50+
extern lv_obj_t *ui_hapticupbutton;
51+
extern lv_obj_t *ui_settingsscreen_Label6;
52+
extern lv_obj_t *ui_hapticplaybutton;
53+
extern lv_obj_t *ui_settingsscreen_Label8;
4454

4555

4656

components/gui/include/gui.hpp

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,24 @@ extern "C" {
1515

1616
class Gui {
1717
public:
18+
typedef std::function<void(void)> play_haptic_fn;
19+
typedef std::function<void(int)> set_waveform_fn;
20+
typedef std::function<void(int, int)> set_haptic_slot_fn;
21+
1822
struct Config {
23+
play_haptic_fn play_haptic;
24+
set_waveform_fn set_waveform;
1925
std::shared_ptr<espp::Display> display;
2026
espp::Logger::Verbosity log_level{espp::Logger::Verbosity::WARN};
2127
};
2228

2329
enum class VideoSetting { ORIGINAL, FIT, FILL, MAX_UNUSED };
2430

25-
Gui(const Config& config) : display_(config.display), logger_({.tag="Gui", .level=config.log_level}) {
31+
Gui(const Config& config)
32+
: play_haptic_(config.play_haptic),
33+
set_waveform_(config.set_waveform),
34+
display_(config.display),
35+
logger_({.tag="Gui", .level=config.log_level}) {
2636
init_ui();
2737
// now start the gui updater task
2838
using namespace std::placeholders;
@@ -182,6 +192,30 @@ class Gui {
182192
lv_img_set_src(ui_boxart, boxarts_[focused_rom_].c_str());
183193
}
184194

195+
void set_haptic_waveform(int new_waveform) {
196+
if (new_waveform > 123) {
197+
new_waveform = 1;
198+
} else if (new_waveform <= 0) {
199+
new_waveform = 123;
200+
}
201+
haptic_waveform_ = new_waveform;
202+
set_waveform_(haptic_waveform_);
203+
update_haptic_waveform_label();
204+
}
205+
206+
void next_haptic_waveform() {
207+
set_haptic_waveform(haptic_waveform_ + 1);
208+
}
209+
210+
void previous_haptic_waveform() {
211+
set_haptic_waveform(haptic_waveform_ - 1);
212+
}
213+
214+
void update_haptic_waveform_label() {
215+
auto haptic_label = fmt::format("{}", haptic_waveform_);
216+
lv_label_set_text(ui_hapticlabel, haptic_label.c_str());
217+
}
218+
185219
protected:
186220
void init_ui() {
187221
ui_init();
@@ -201,11 +235,21 @@ class Gui {
201235

202236
lv_bar_set_value(ui_volumebar, audio_level_, LV_ANIM_OFF);
203237

238+
// rom screen navigation
204239
lv_obj_add_event_cb(ui_settingsbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast<void*>(this));
205240
lv_obj_add_event_cb(ui_playbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast<void*>(this));
241+
242+
// volume settings
206243
lv_obj_add_event_cb(ui_volumeupbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast<void*>(this));
207244
lv_obj_add_event_cb(ui_volumedownbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast<void*>(this));
208245
lv_obj_add_event_cb(ui_mutebutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast<void*>(this));
246+
247+
// haptic settings
248+
lv_obj_add_event_cb(ui_hapticdownbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast<void*>(this));
249+
lv_obj_add_event_cb(ui_hapticupbutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast<void*>(this));
250+
lv_obj_add_event_cb(ui_hapticplaybutton, &Gui::event_callback, LV_EVENT_PRESSED, static_cast<void*>(this));
251+
// ensure the waveform is set and the ui is updated
252+
set_haptic_waveform(haptic_waveform_);
209253
}
210254

211255
void update(std::mutex& m, std::condition_variable& cv) {
@@ -251,6 +295,7 @@ class Gui {
251295
// TODO: DO SOMETHING HERE!
252296
return;
253297
}
298+
// volume controls
254299
bool is_volume_up_button = (target == ui_volumeupbutton);
255300
if (is_volume_up_button) {
256301
set_audio_level(audio_level_ + 10);
@@ -266,6 +311,22 @@ class Gui {
266311
toggle_mute();
267312
return;
268313
}
314+
// haptic controls
315+
bool is_haptic_up_button = (target == ui_hapticupbutton);
316+
if (is_haptic_up_button) {
317+
next_haptic_waveform();
318+
return;
319+
}
320+
bool is_haptic_down_button = (target == ui_hapticdownbutton);
321+
if (is_haptic_down_button) {
322+
previous_haptic_waveform();
323+
return;
324+
}
325+
bool is_hapticplay_button = (target == ui_hapticplaybutton);
326+
if (is_hapticplay_button) {
327+
play_haptic_();
328+
return;
329+
}
269330
// or is it the play button?
270331
bool is_play_button = (target == ui_playbutton);
271332
if (is_play_button) {
@@ -290,6 +351,10 @@ class Gui {
290351
lv_anim_t rom_label_animation_template_;
291352
lv_style_t rom_label_style_;
292353

354+
play_haptic_fn play_haptic_;
355+
set_waveform_fn set_waveform_;
356+
std::atomic<int> haptic_waveform_{16}; // for the DRV2605, this is a 1s alert
357+
293358
std::atomic<bool> ready_to_play_{false};
294359
std::atomic<bool> paused_{false};
295360
std::shared_ptr<espp::Display> display_;

main/main.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,22 @@ extern "C" void app_main(void) {
8181
.write = write_drv,
8282
.read = read_drv,
8383
});
84-
8584
// we're using an ERM motor, so select an ERM library.
8685
haptic_motor.select_library(1);
87-
// we want strong click (for when user selects rom)
88-
haptic_motor.set_waveform(0, Drv2605::Waveform::STRONG_CLICK);
89-
haptic_motor.set_waveform(1, Drv2605::Waveform::END);
90-
// let the user know we're booting up
91-
haptic_motor.start();
86+
87+
auto play_haptic = [&haptic_motor]() {
88+
haptic_motor.start();
89+
};
90+
auto set_waveform = [&haptic_motor](int waveform) {
91+
haptic_motor.set_waveform(0, (Drv2605::Waveform)waveform);
92+
haptic_motor.set_waveform(1, Drv2605::Waveform::END);
93+
};
9294

9395
fmt::print("initializing gui...\n");
9496
// initialize the gui
9597
Gui gui({
98+
.play_haptic = play_haptic,
99+
.set_waveform = set_waveform,
96100
.display = display,
97101
.log_level = espp::Logger::Verbosity::WARN
98102
});

0 commit comments

Comments
 (0)