2021-10-13 22:08:35 +02:00
|
|
|
#include "displayapp/screens/Metronome.h"
|
|
|
|
#include "displayapp/screens/Symbols.h"
|
2021-06-12 15:06:58 +02:00
|
|
|
|
|
|
|
using namespace Pinetime::Applications::Screens;
|
|
|
|
|
|
|
|
namespace {
|
2021-08-13 21:03:27 +02:00
|
|
|
void eventHandler(lv_obj_t* obj, lv_event_t event) {
|
|
|
|
auto* screen = static_cast<Metronome*>(obj->user_data);
|
2021-06-12 15:06:58 +02:00
|
|
|
screen->OnEvent(obj, event);
|
|
|
|
}
|
|
|
|
|
2021-08-13 21:03:27 +02:00
|
|
|
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) {
|
2021-06-12 15:06:58 +02:00
|
|
|
lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr);
|
|
|
|
lv_obj_set_style_local_text_font(label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font);
|
|
|
|
lv_obj_set_style_local_text_color(label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
|
|
|
|
lv_label_set_text(label, name);
|
|
|
|
lv_obj_align(label, reference, align, x, y);
|
|
|
|
|
|
|
|
return label;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Metronome::Metronome(DisplayApp* app, Controllers::MotorController& motorController, System::SystemTask& systemTask)
|
2021-08-13 21:03:27 +02:00
|
|
|
: Screen(app), motorController {motorController}, systemTask {systemTask} {
|
2021-06-12 15:06:58 +02:00
|
|
|
|
|
|
|
bpmArc = lv_arc_create(lv_scr_act(), nullptr);
|
|
|
|
bpmArc->user_data = this;
|
|
|
|
lv_obj_set_event_cb(bpmArc, eventHandler);
|
|
|
|
lv_arc_set_bg_angles(bpmArc, 0, 270);
|
|
|
|
lv_arc_set_rotation(bpmArc, 135);
|
|
|
|
lv_arc_set_range(bpmArc, 40, 220);
|
|
|
|
lv_arc_set_value(bpmArc, bpm);
|
|
|
|
lv_obj_set_size(bpmArc, 210, 210);
|
|
|
|
lv_arc_set_adjustable(bpmArc, true);
|
2021-08-13 21:03:27 +02:00
|
|
|
lv_obj_align(bpmArc, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0);
|
2021-06-12 15:06:58 +02:00
|
|
|
|
2021-08-13 21:03:27 +02:00
|
|
|
bpmValue = createLabel("120", bpmArc, LV_ALIGN_IN_TOP_MID, &jetbrains_mono_76, 0, 55);
|
|
|
|
createLabel("bpm", bpmValue, LV_ALIGN_OUT_BOTTOM_MID, &jetbrains_mono_bold_20, 0, 0);
|
2021-06-12 15:06:58 +02:00
|
|
|
|
|
|
|
bpmTap = lv_btn_create(lv_scr_act(), nullptr);
|
|
|
|
bpmTap->user_data = this;
|
|
|
|
lv_obj_set_event_cb(bpmTap, eventHandler);
|
|
|
|
lv_obj_set_style_local_bg_opa(bpmTap, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
|
|
|
|
lv_obj_set_height(bpmTap, 80);
|
|
|
|
lv_obj_align(bpmTap, bpmValue, LV_ALIGN_IN_TOP_MID, 0, 0);
|
|
|
|
|
|
|
|
bpbDropdown = lv_dropdown_create(lv_scr_act(), nullptr);
|
|
|
|
bpbDropdown->user_data = this;
|
|
|
|
lv_obj_set_event_cb(bpbDropdown, eventHandler);
|
|
|
|
lv_obj_set_style_local_pad_left(bpbDropdown, LV_DROPDOWN_PART_MAIN, LV_STATE_DEFAULT, 20);
|
|
|
|
lv_obj_set_style_local_pad_left(bpbDropdown, LV_DROPDOWN_PART_LIST, LV_STATE_DEFAULT, 20);
|
2021-08-13 21:03:27 +02:00
|
|
|
lv_obj_set_size(bpbDropdown, 115, 50);
|
|
|
|
lv_obj_align(bpbDropdown, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
|
2021-06-12 15:06:58 +02:00
|
|
|
lv_dropdown_set_options(bpbDropdown, "1\n2\n3\n4\n5\n6\n7\n8\n9");
|
|
|
|
lv_dropdown_set_selected(bpbDropdown, bpb - 1);
|
2021-08-13 21:03:27 +02:00
|
|
|
lv_dropdown_set_show_selected(bpbDropdown, false);
|
|
|
|
lv_dropdown_set_text(bpbDropdown, "");
|
|
|
|
|
|
|
|
currentBpbText = lv_label_create(bpbDropdown, nullptr);
|
|
|
|
lv_label_set_text_fmt(currentBpbText, "%d bpb", bpb);
|
|
|
|
lv_obj_align(currentBpbText, bpbDropdown, LV_ALIGN_CENTER, 0, 0);
|
2021-06-12 15:06:58 +02:00
|
|
|
|
|
|
|
playPause = lv_btn_create(lv_scr_act(), nullptr);
|
|
|
|
playPause->user_data = this;
|
|
|
|
lv_obj_set_event_cb(playPause, eventHandler);
|
2021-08-13 21:03:27 +02:00
|
|
|
lv_obj_set_size(playPause, 115, 50);
|
|
|
|
lv_obj_align(playPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
|
|
|
|
lv_obj_set_style_local_value_str(playPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::play);
|
2021-06-12 15:06:58 +02:00
|
|
|
|
2021-07-19 15:26:12 +02:00
|
|
|
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
|
2021-06-12 15:06:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Metronome::~Metronome() {
|
2021-07-19 15:26:12 +02:00
|
|
|
lv_task_del(taskRefresh);
|
2021-06-12 15:14:14 +02:00
|
|
|
systemTask.PushMessage(System::Messages::EnableSleeping);
|
2021-06-12 15:06:58 +02:00
|
|
|
lv_obj_clean(lv_scr_act());
|
|
|
|
}
|
|
|
|
|
2021-07-19 15:26:12 +02:00
|
|
|
void Metronome::Refresh() {
|
2021-08-13 21:03:27 +02:00
|
|
|
if (metronomeStarted) {
|
2021-09-13 22:33:21 +02:00
|
|
|
if (xTaskGetTickCount() - startTime > 60u * configTICK_RATE_HZ / static_cast<uint16_t>(bpm)) {
|
2021-08-13 21:03:27 +02:00
|
|
|
startTime += 60 * configTICK_RATE_HZ / bpm;
|
|
|
|
counter--;
|
|
|
|
if (counter == 0) {
|
|
|
|
counter = bpb;
|
2021-08-14 21:54:00 +02:00
|
|
|
motorController.RunForDuration(90);
|
2021-08-13 21:03:27 +02:00
|
|
|
} else {
|
2021-08-14 21:54:00 +02:00
|
|
|
motorController.RunForDuration(30);
|
2021-06-12 15:06:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Metronome::OnEvent(lv_obj_t* obj, lv_event_t event) {
|
|
|
|
switch (event) {
|
|
|
|
case LV_EVENT_VALUE_CHANGED: {
|
|
|
|
if (obj == bpmArc) {
|
|
|
|
bpm = lv_arc_get_value(bpmArc);
|
|
|
|
lv_label_set_text_fmt(bpmValue, "%03d", bpm);
|
|
|
|
} else if (obj == bpbDropdown) {
|
|
|
|
bpb = lv_dropdown_get_selected(obj) + 1;
|
2021-08-13 21:03:27 +02:00
|
|
|
lv_label_set_text_fmt(currentBpbText, "%d bpb", bpb);
|
|
|
|
lv_obj_realign(currentBpbText);
|
2021-06-12 15:06:58 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case LV_EVENT_PRESSED: {
|
|
|
|
if (obj == bpmTap) {
|
2021-08-13 21:03:27 +02:00
|
|
|
TickType_t delta = xTaskGetTickCount() - tappedTime;
|
|
|
|
if (tappedTime != 0 && delta < configTICK_RATE_HZ * 3) {
|
|
|
|
bpm = configTICK_RATE_HZ * 60 / delta;
|
2021-06-12 15:06:58 +02:00
|
|
|
lv_arc_set_value(bpmArc, bpm);
|
|
|
|
lv_label_set_text_fmt(bpmValue, "%03d", bpm);
|
|
|
|
}
|
2021-08-13 21:03:27 +02:00
|
|
|
tappedTime = xTaskGetTickCount();
|
2021-10-04 10:13:45 +02:00
|
|
|
allowExit = true;
|
2021-06-12 15:06:58 +02:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2021-10-04 10:13:45 +02:00
|
|
|
case LV_EVENT_RELEASED:
|
|
|
|
case LV_EVENT_PRESS_LOST:
|
|
|
|
if (obj == bpmTap) {
|
|
|
|
allowExit = false;
|
|
|
|
}
|
2021-10-04 10:32:50 +02:00
|
|
|
break;
|
2021-06-12 15:06:58 +02:00
|
|
|
case LV_EVENT_CLICKED: {
|
|
|
|
if (obj == playPause) {
|
2021-08-13 21:03:27 +02:00
|
|
|
metronomeStarted = !metronomeStarted;
|
|
|
|
if (metronomeStarted) {
|
|
|
|
lv_obj_set_style_local_value_str(playPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::pause);
|
|
|
|
systemTask.PushMessage(System::Messages::DisableSleeping);
|
|
|
|
startTime = xTaskGetTickCount();
|
|
|
|
counter = 1;
|
|
|
|
} else {
|
|
|
|
lv_obj_set_style_local_value_str(playPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::play);
|
|
|
|
systemTask.PushMessage(System::Messages::EnableSleeping);
|
2021-06-12 15:06:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2021-08-13 21:03:27 +02:00
|
|
|
default:
|
|
|
|
break;
|
2021-06-12 15:06:58 +02:00
|
|
|
}
|
|
|
|
}
|
2021-10-04 10:13:45 +02:00
|
|
|
|
|
|
|
bool Metronome::OnTouchEvent(TouchEvents event) {
|
|
|
|
if (event == TouchEvents::SwipeDown && allowExit) {
|
|
|
|
running = false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|