@@ -8,11 +8,15 @@ using namespace std::chrono_literals;
88
99static constexpr size_t MAX_CIRCLES = 100 ;
1010static std::deque<lv_obj_t *> circles;
11+ static std::vector<uint8_t > audio_bytes;
1112
1213static std::recursive_mutex lvgl_mutex;
1314static void draw_circle (int x0, int y0, int radius);
1415static void clear_circles ();
1516
17+ static size_t load_audio ();
18+ static void play_click (espp::TDeck &tdeck);
19+
1620LV_IMG_DECLARE (mouse_cursor_icon);
1721
1822extern " C" void app_main (void ) {
@@ -28,14 +32,33 @@ extern "C" void app_main(void) {
2832 auto keypress_callback = [&](uint8_t key) {
2933 logger.info (" Key pressed: {}" , key);
3034 if (key == 8 ) {
35+ // delete key will clear the circles
36+ logger.info (" Clearing circles" );
3137 std::lock_guard<std::recursive_mutex> lock (lvgl_mutex);
3238 clear_circles ();
3339 } else if (key == ' ' ) {
40+ // space key will rotate the display
41+ logger.info (" Rotating display" );
3442 std::lock_guard<std::recursive_mutex> lock (lvgl_mutex);
3543 clear_circles ();
3644 rotation = static_cast <lv_display_rotation_t >((static_cast <int >(rotation) + 1 ) % 4 );
3745 lv_display_t *disp = lv_display_get_default ();
3846 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 ());
3962 }
4063 };
4164
@@ -51,6 +74,7 @@ extern "C" void app_main(void) {
5174 previous_touchpad_data = touchpad_data;
5275 // if there is a touch point, draw a circle
5376 if (touchpad_data.num_touch_points > 0 ) {
77+ play_click (tdeck);
5478 std::lock_guard<std::recursive_mutex> lock (lvgl_mutex);
5579 draw_circle (touchpad_data.x , touchpad_data.y , 10 );
5680 }
@@ -61,12 +85,21 @@ extern "C" void app_main(void) {
6185 logger.debug (" Trackball: {}" , trackball);
6286 };
6387
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+ }
6492 // initialize the Keyboard
6593 bool start_task = true ;
6694 if (!tdeck.initialize_keyboard (start_task, keypress_callback)) {
6795 logger.error (" Failed to initialize Keyboard!" );
6896 return ;
6997 }
98+ // initialize the sound
99+ if (!tdeck.initialize_sound ()) {
100+ logger.error (" Failed to initialize sound!" );
101+ return ;
102+ }
70103 // initialize the LCD
71104 if (!tdeck.initialize_lcd ()) {
72105 logger.error (" Failed to initialize LCD!" );
@@ -142,6 +175,14 @@ extern "C" void app_main(void) {
142175 }});
143176 lv_task.start ();
144177
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+
145186 // set the display brightness to be 75%
146187 tdeck.brightness (75 .0f );
147188
@@ -177,3 +218,40 @@ static void clear_circles() {
177218 // clear the vector
178219 circles.clear ();
179220}
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