11#include " Metronome.h"
2-
3- #include " Screen.h"
42#include " Symbols.h"
5- #include " lvgl/lvgl.h"
6- #include " FreeRTOSConfig.h"
7- #include " task.h"
8-
9- #include < string>
10- #include < tuple>
113
124using namespace Pinetime ::Applications::Screens;
135
146namespace {
15- float calculateDelta (const TickType_t startTime, const TickType_t currentTime) {
16- TickType_t delta = 0 ;
17- // Take care of overflow
18- if (startTime > currentTime) {
19- delta = 0xffffffff - startTime;
20- delta += (currentTime + 1 );
21- } else {
22- delta = currentTime - startTime;
23- }
24- return static_cast <float >(delta) / static_cast <float >(configTICK_RATE_HZ);
25- }
26-
27- static void eventHandler (lv_obj_t * obj, lv_event_t event) {
28- Metronome* screen = static_cast <Metronome*>(obj->user_data );
7+ void eventHandler (lv_obj_t * obj, lv_event_t event) {
8+ auto * screen = static_cast <Metronome*>(obj->user_data );
299 screen->OnEvent (obj, event);
3010 }
3111
32- lv_obj_t * createLabel (const char * name, lv_obj_t * reference, lv_align_t align, lv_font_t * font, uint8_t x = 0 , uint8_t y = 0 ) {
12+ lv_obj_t * createLabel (const char * name, lv_obj_t * reference, lv_align_t align, lv_font_t * font, uint8_t x, uint8_t y) {
3313 lv_obj_t * label = lv_label_create (lv_scr_act (), nullptr );
3414 lv_obj_set_style_local_text_font (label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font);
3515 lv_obj_set_style_local_text_color (label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
@@ -41,7 +21,7 @@ namespace {
4121}
4222
4323Metronome::Metronome (DisplayApp* app, Controllers::MotorController& motorController, System::SystemTask& systemTask)
44- : Screen(app), running { true }, currentState {States::Stopped}, startTime {}, motorController {motorController}, systemTask {systemTask} {
24+ : Screen(app), motorController {motorController}, systemTask {systemTask} {
4525
4626 bpmArc = lv_arc_create (lv_scr_act (), nullptr );
4727 bpmArc->user_data = this ;
@@ -52,10 +32,10 @@ Metronome::Metronome(DisplayApp* app, Controllers::MotorController& motorControl
5232 lv_arc_set_value (bpmArc, bpm);
5333 lv_obj_set_size (bpmArc, 210 , 210 );
5434 lv_arc_set_adjustable (bpmArc, true );
55- lv_obj_align (bpmArc, lv_scr_act (), LV_ALIGN_IN_TOP_MID, 0 , 7 );
35+ lv_obj_align (bpmArc, lv_scr_act (), LV_ALIGN_IN_TOP_MID, 0 , 0 );
5636
57- bpmValue = createLabel (std::to_string ( lv_arc_get_value (bpmArc)). c_str () , bpmArc, LV_ALIGN_IN_TOP_MID, &jetbrains_mono_76, 0 , 55 );
58- bpmLegend = createLabel (" bpm" , bpmValue, LV_ALIGN_OUT_BOTTOM_MID, &jetbrains_mono_bold_20, 0 , 0 );
37+ bpmValue = createLabel (" 120 " , bpmArc, LV_ALIGN_IN_TOP_MID, &jetbrains_mono_76, 0 , 55 );
38+ createLabel (" bpm" , bpmValue, LV_ALIGN_OUT_BOTTOM_MID, &jetbrains_mono_bold_20, 0 , 0 );
5939
6040 bpmTap = lv_btn_create (lv_scr_act (), nullptr );
6141 bpmTap->user_data = this ;
@@ -69,20 +49,23 @@ Metronome::Metronome(DisplayApp* app, Controllers::MotorController& motorControl
6949 lv_obj_set_event_cb (bpbDropdown, eventHandler);
7050 lv_obj_set_style_local_pad_left (bpbDropdown, LV_DROPDOWN_PART_MAIN, LV_STATE_DEFAULT, 20 );
7151 lv_obj_set_style_local_pad_left (bpbDropdown, LV_DROPDOWN_PART_LIST, LV_STATE_DEFAULT, 20 );
72- lv_obj_align (bpbDropdown, lv_scr_act (), LV_ALIGN_IN_BOTTOM_LEFT, 15 , -4 );
52+ lv_obj_set_size (bpbDropdown, 115 , 50 );
53+ lv_obj_align (bpbDropdown, lv_scr_act (), LV_ALIGN_IN_BOTTOM_LEFT, 0 , 0 );
7354 lv_dropdown_set_options (bpbDropdown, " 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9" );
7455 lv_dropdown_set_selected (bpbDropdown, bpb - 1 );
75- bpbLegend = lv_label_create (bpbDropdown, nullptr );
76- lv_label_set_text (bpbLegend, " bpb" );
77- lv_obj_align (bpbLegend, bpbDropdown, LV_ALIGN_IN_RIGHT_MID, -15 , 0 );
56+ lv_dropdown_set_show_selected (bpbDropdown, false );
57+ lv_dropdown_set_text (bpbDropdown, " " );
58+
59+ currentBpbText = lv_label_create (bpbDropdown, nullptr );
60+ lv_label_set_text_fmt (currentBpbText, " %d bpb" , bpb);
61+ lv_obj_align (currentBpbText, bpbDropdown, LV_ALIGN_CENTER, 0 , 0 );
7862
7963 playPause = lv_btn_create (lv_scr_act (), nullptr );
8064 playPause->user_data = this ;
8165 lv_obj_set_event_cb (playPause, eventHandler);
82- lv_obj_align (playPause, lv_scr_act (), LV_ALIGN_IN_BOTTOM_RIGHT, -15 , -10 );
83- lv_obj_set_height (playPause, 39 );
84- playPauseLabel = lv_label_create (playPause, nullptr );
85- lv_label_set_text (playPauseLabel, Symbols::play);
66+ lv_obj_set_size (playPause, 115 , 50 );
67+ lv_obj_align (playPause, lv_scr_act (), LV_ALIGN_IN_BOTTOM_RIGHT, 0 , 0 );
68+ lv_obj_set_style_local_value_str (playPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::play);
8669
8770 app->SetTouchMode (DisplayApp::TouchModes::Polling);
8871}
@@ -93,28 +76,17 @@ Metronome::~Metronome() {
9376 lv_obj_clean (lv_scr_act ());
9477}
9578
96- bool Metronome::OnTouchEvent (Pinetime::Applications::TouchEvents event) {
97- return true ;
98- }
99-
10079bool Metronome::Refresh () {
101- switch (currentState) {
102- case States::Stopped: {
103- break ;
104- }
105- case States::Running: {
106- if (calculateDelta (startTime, xTaskGetTickCount ()) >= (60.0 / bpm)) {
107- counter--;
108- startTime -= 60.0 / bpm;
109- startTime = xTaskGetTickCount ();
110- if (counter == 0 ) {
111- counter = bpb;
112- motorController.SetDuration (90 );
113- } else {
114- motorController.SetDuration (30 );
115- }
80+ if (metronomeStarted) {
81+ if (xTaskGetTickCount () - startTime > 60 * configTICK_RATE_HZ / bpm) {
82+ startTime += 60 * configTICK_RATE_HZ / bpm;
83+ counter--;
84+ if (counter == 0 ) {
85+ counter = bpb;
86+ motorController.SetDuration (90 );
87+ } else {
88+ motorController.SetDuration (30 );
11689 }
117- break ;
11890 }
11991 }
12092 return running;
@@ -128,42 +100,39 @@ void Metronome::OnEvent(lv_obj_t* obj, lv_event_t event) {
128100 lv_label_set_text_fmt (bpmValue, " %03d" , bpm);
129101 } else if (obj == bpbDropdown) {
130102 bpb = lv_dropdown_get_selected (obj) + 1 ;
103+ lv_label_set_text_fmt (currentBpbText, " %d bpb" , bpb);
104+ lv_obj_realign (currentBpbText);
131105 }
132106 break ;
133107 }
134108 case LV_EVENT_PRESSED: {
135109 if (obj == bpmTap) {
136- float timeDelta = calculateDelta (tappedTime, xTaskGetTickCount ());
137- if (tappedTime == 0 || timeDelta > 3 ) {
138- tappedTime = xTaskGetTickCount ();
139- } else {
140- bpm = ceil (60.0 / timeDelta);
110+ TickType_t delta = xTaskGetTickCount () - tappedTime;
111+ if (tappedTime != 0 && delta < configTICK_RATE_HZ * 3 ) {
112+ bpm = configTICK_RATE_HZ * 60 / delta;
141113 lv_arc_set_value (bpmArc, bpm);
142114 lv_label_set_text_fmt (bpmValue, " %03d" , bpm);
143- tappedTime = xTaskGetTickCount ();
144115 }
116+ tappedTime = xTaskGetTickCount ();
145117 }
146118 break ;
147119 }
148120 case LV_EVENT_CLICKED: {
149121 if (obj == playPause) {
150- currentState = (currentState == States::Stopped ? States::Running : States::Stopped);
151- switch (currentState) {
152- case States::Stopped: {
153- lv_label_set_text (playPauseLabel, Symbols::play);
154- systemTask.PushMessage (System::Messages::EnableSleeping);
155- break ;
156- }
157- case States::Running: {
158- lv_label_set_text (playPauseLabel, Symbols::pause);
159- systemTask.PushMessage (System::Messages::DisableSleeping);
160- startTime = xTaskGetTickCount ();
161- counter = 1 ;
162- break ;
163- }
122+ metronomeStarted = !metronomeStarted;
123+ if (metronomeStarted) {
124+ lv_obj_set_style_local_value_str (playPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::pause);
125+ systemTask.PushMessage (System::Messages::DisableSleeping);
126+ startTime = xTaskGetTickCount ();
127+ counter = 1 ;
128+ } else {
129+ lv_obj_set_style_local_value_str (playPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::play);
130+ systemTask.PushMessage (System::Messages::EnableSleeping);
164131 }
165132 }
166133 break ;
167134 }
135+ default :
136+ break ;
168137 }
169138}
0 commit comments