@@ -8,11 +8,15 @@ using namespace std::chrono_literals;
8
8
9
9
static constexpr size_t MAX_CIRCLES = 100 ;
10
10
static std::deque<lv_obj_t *> circles;
11
+ static std::vector<uint8_t > audio_bytes;
11
12
12
13
static std::recursive_mutex lvgl_mutex;
13
14
static void draw_circle (int x0, int y0, int radius);
14
15
static void clear_circles ();
15
16
17
+ static size_t load_audio ();
18
+ static void play_click (espp::TDeck &tdeck);
19
+
16
20
LV_IMG_DECLARE (mouse_cursor_icon);
17
21
18
22
extern " C" void app_main (void ) {
@@ -28,14 +32,33 @@ extern "C" void app_main(void) {
28
32
auto keypress_callback = [&](uint8_t key) {
29
33
logger.info (" Key pressed: {}" , key);
30
34
if (key == 8 ) {
35
+ // delete key will clear the circles
36
+ logger.info (" Clearing circles" );
31
37
std::lock_guard<std::recursive_mutex> lock (lvgl_mutex);
32
38
clear_circles ();
33
39
} else if (key == ' ' ) {
40
+ // space key will rotate the display
41
+ logger.info (" Rotating display" );
34
42
std::lock_guard<std::recursive_mutex> lock (lvgl_mutex);
35
43
clear_circles ();
36
44
rotation = static_cast <lv_display_rotation_t >((static_cast <int >(rotation) + 1 ) % 4 );
37
45
lv_display_t *disp = lv_display_get_default ();
38
46
lv_disp_set_rotation (disp, rotation);
47
+ } else if (key == ' m' ) {
48
+ // 'm' key will toggle audio mute
49
+ logger.info (" Toggling mute" );
50
+ tdeck.mute (!tdeck.is_muted ());
51
+ logger.info (" Muted: {}" , tdeck.is_muted ());
52
+ } else if (key == ' n' ) {
53
+ // 'n' key will decrease audio volume (left of 'm' key)
54
+ logger.info (" Decreasing volume" );
55
+ tdeck.volume (tdeck.volume () - 10 .0f );
56
+ logger.info (" Volume: {}" , tdeck.volume ());
57
+ } else if (key == ' $' ) {
58
+ // '$' key will increase audio volume (right of 'm' key)
59
+ logger.info (" Increasing volume" );
60
+ tdeck.volume (tdeck.volume () + 10 .0f );
61
+ logger.info (" Volume: {}" , tdeck.volume ());
39
62
}
40
63
};
41
64
@@ -51,6 +74,7 @@ extern "C" void app_main(void) {
51
74
previous_touchpad_data = touchpad_data;
52
75
// if there is a touch point, draw a circle
53
76
if (touchpad_data.num_touch_points > 0 ) {
77
+ play_click (tdeck);
54
78
std::lock_guard<std::recursive_mutex> lock (lvgl_mutex);
55
79
draw_circle (touchpad_data.x , touchpad_data.y , 10 );
56
80
}
@@ -61,12 +85,21 @@ extern "C" void app_main(void) {
61
85
logger.debug (" Trackball: {}" , trackball);
62
86
};
63
87
88
+ // initialize the uSD card
89
+ if (!tdeck.initialize_sdcard ()) {
90
+ logger.warn (" Failed to initialize uSD card, there may not be a uSD card inserted!" );
91
+ }
64
92
// initialize the Keyboard
65
93
bool start_task = true ;
66
94
if (!tdeck.initialize_keyboard (start_task, keypress_callback)) {
67
95
logger.error (" Failed to initialize Keyboard!" );
68
96
return ;
69
97
}
98
+ // initialize the sound
99
+ if (!tdeck.initialize_sound ()) {
100
+ logger.error (" Failed to initialize sound!" );
101
+ return ;
102
+ }
70
103
// initialize the LCD
71
104
if (!tdeck.initialize_lcd ()) {
72
105
logger.error (" Failed to initialize LCD!" );
@@ -142,6 +175,14 @@ extern "C" void app_main(void) {
142
175
}});
143
176
lv_task.start ();
144
177
178
+ // load the audio file (wav file bundled in memory)
179
+ size_t wav_size = load_audio ();
180
+ logger.info (" Loaded {} bytes of audio" , wav_size);
181
+
182
+ // unmute the audio and set the volume to 20%
183
+ tdeck.mute (false );
184
+ tdeck.volume (20 .0f );
185
+
145
186
// set the display brightness to be 75%
146
187
tdeck.brightness (75 .0f );
147
188
@@ -177,3 +218,40 @@ static void clear_circles() {
177
218
// clear the vector
178
219
circles.clear ();
179
220
}
221
+
222
+ static size_t load_audio () {
223
+ // if the audio_bytes vector is already populated, return the size
224
+ if (audio_bytes.size () > 0 ) {
225
+ return audio_bytes.size ();
226
+ }
227
+
228
+ // these are configured in the CMakeLists.txt file
229
+ extern const char wav_start[] asm (" _binary_click_wav_start" ); // cppcheck-suppress syntaxError
230
+ extern const char wav_end[] asm (" _binary_click_wav_end" ); // cppcheck-suppress syntaxError
231
+
232
+ // -1 due to the size being 1 byte too large, I think because end is the byte
233
+ // immediately after the last byte in the memory but I'm not sure - cmm 2022-08-20
234
+ //
235
+ // Suppression as these are linker symbols and cppcheck doesn't know how to ensure
236
+ // they are the same object
237
+ // cppcheck-suppress comparePointers
238
+ size_t wav_size = (wav_end - wav_start) - 1 ;
239
+ FILE *fp = fmemopen ((void *)wav_start, wav_size, " rb" );
240
+ // read the file into the audio_bytes vector
241
+ audio_bytes.resize (wav_size);
242
+ fread (audio_bytes.data (), 1 , wav_size, fp);
243
+ fclose (fp);
244
+ return wav_size;
245
+ }
246
+
247
+ static void play_click (espp::TDeck &tdeck) {
248
+ // use the box.play_audio() function to play a sound, breaking it into
249
+ // audio_buffer_size chunks
250
+ auto audio_buffer_size = tdeck.audio_buffer_size ();
251
+ size_t offset = 0 ;
252
+ while (offset < audio_bytes.size ()) {
253
+ size_t bytes_to_play = std::min (audio_buffer_size, audio_bytes.size () - offset);
254
+ tdeck.play_audio (audio_bytes.data () + offset, bytes_to_play);
255
+ offset += bytes_to_play;
256
+ }
257
+ }
0 commit comments