Merge branch 'develop' into new_touch_handler

This commit is contained in:
Riku Isokoski
2021-08-18 22:07:02 +03:00
40 changed files with 835 additions and 399 deletions

View File

@@ -843,7 +843,7 @@ target_compile_options(${EXECUTABLE_NAME} PUBLIC
set_target_properties(${EXECUTABLE_NAME} PROPERTIES
SUFFIX ".out"
LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_FILE_NAME}.map"
LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections -Wl,--print-memory-usage --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_FILE_NAME}.map"
)
add_custom_command(TARGET ${EXECUTABLE_NAME}
@@ -873,7 +873,7 @@ target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC
set_target_properties(${EXECUTABLE_MCUBOOT_NAME} PROPERTIES
SUFFIX ".out"
LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT_MCUBOOT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_MCUBOOT_FILE_NAME}.map"
LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT_MCUBOOT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections -Wl,--print-memory-usage --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_MCUBOOT_FILE_NAME}.map"
)
add_custom_command(TARGET ${EXECUTABLE_MCUBOOT_NAME}
@@ -910,7 +910,7 @@ target_compile_options(${EXECUTABLE_RECOVERY_NAME} PUBLIC
set_target_properties(${EXECUTABLE_RECOVERY_NAME} PROPERTIES
SUFFIX ".out"
LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_RECOVERY_FILE_NAME}.map"
LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections -Wl,--print-memory-usage --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_RECOVERY_FILE_NAME}.map"
)
add_custom_command(TARGET ${EXECUTABLE_RECOVERY_NAME}
@@ -940,7 +940,7 @@ target_compile_options(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC
set_target_properties(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PROPERTIES
SUFFIX ".out"
LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_GRAPHICS_FILE_NAME}.map"
LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections -Wl,--print-memory-usage --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_GRAPHICS_FILE_NAME}.map"
)
add_custom_command(TARGET ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}
@@ -981,7 +981,7 @@ add_dependencies(${EXECUTABLE_RECOVERYLOADER_NAME} ${EXECUTABLE_RECOVERY_MCUBOOT
set_target_properties(${EXECUTABLE_RECOVERYLOADER_NAME} PROPERTIES
SUFFIX ".out"
LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_RECOVERYLOADER_FILE_NAME}.map"
LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections -Wl,--print-memory-usage --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_RECOVERYLOADER_FILE_NAME}.map"
)
add_custom_command(TARGET ${EXECUTABLE_RECOVERYLOADER_NAME}
@@ -1014,7 +1014,7 @@ add_dependencies(${EXECUTABLE_MCUBOOT_RECOVERYLOADER_NAME} ${EXECUTABLE_RECOVERY
set_target_properties(${EXECUTABLE_MCUBOOT_RECOVERYLOADER_NAME} PROPERTIES
SUFFIX ".out"
LINK_FLAGS "-mthumb -mabi=aapcs -std=gnu++98 -std=c99 -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT_MCUBOOT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_MCUBOOT_RECOVERYLOADER_FILE_NAME}.map"
LINK_FLAGS "-mthumb -mabi=aapcs -std=gnu++98 -std=c99 -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT_MCUBOOT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections -Wl,--print-memory-usage --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_MCUBOOT_RECOVERYLOADER_FILE_NAME}.map"
)
add_custom_command(TARGET ${EXECUTABLE_MCUBOOT_RECOVERYLOADER_NAME}

View File

@@ -3,7 +3,8 @@
#include "systemtask/SystemTask.h"
#include "app_timer.h"
APP_TIMER_DEF(vibTimer);
APP_TIMER_DEF(shortVibTimer);
APP_TIMER_DEF(longVibTimer);
using namespace Pinetime::Controllers;
@@ -13,19 +14,39 @@ MotorController::MotorController(Controllers::Settings& settingsController) : se
void MotorController::Init() {
nrf_gpio_cfg_output(pinMotor);
nrf_gpio_pin_set(pinMotor);
app_timer_create(&vibTimer, APP_TIMER_MODE_SINGLE_SHOT, vibrate);
app_timer_init();
app_timer_create(&shortVibTimer, APP_TIMER_MODE_SINGLE_SHOT, StopMotor);
app_timer_create(&longVibTimer, APP_TIMER_MODE_REPEATED, Ring);
}
void MotorController::SetDuration(uint8_t motorDuration) {
void MotorController::Ring(void* p_context) {
auto* motorController = static_cast<MotorController*>(p_context);
motorController->RunForDuration(50);
}
if (settingsController.GetVibrationStatus() == Controllers::Settings::Vibration::OFF)
void MotorController::RunForDuration(uint8_t motorDuration) {
if (settingsController.GetVibrationStatus() == Controllers::Settings::Vibration::OFF) {
return;
}
nrf_gpio_pin_clear(pinMotor);
/* Start timer for motorDuration miliseconds and timer triggers vibrate() when it finishes*/
app_timer_start(vibTimer, APP_TIMER_TICKS(motorDuration), NULL);
app_timer_start(shortVibTimer, APP_TIMER_TICKS(motorDuration), nullptr);
}
void MotorController::vibrate(void* p_context) {
void MotorController::StartRinging() {
if (settingsController.GetVibrationStatus() == Controllers::Settings::Vibration::OFF) {
return;
}
Ring(this);
app_timer_start(longVibTimer, APP_TIMER_TICKS(1000), this);
}
void MotorController::StopRinging() {
app_timer_stop(longVibTimer);
nrf_gpio_pin_set(pinMotor);
}
}
void MotorController::StopMotor(void* p_context) {
nrf_gpio_pin_set(pinMotor);
}

View File

@@ -12,11 +12,14 @@ namespace Pinetime {
public:
MotorController(Controllers::Settings& settingsController);
void Init();
void SetDuration(uint8_t motorDuration);
void RunForDuration(uint8_t motorDuration);
void StartRinging();
static void StopRinging();
private:
static void Ring(void* p_context);
Controllers::Settings& settingsController;
static void vibrate(void* p_context);
static void StopMotor(void* p_context);
};
}
}

View File

@@ -328,12 +328,12 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
case Apps::Notifications:
currentScreen = std::make_unique<Screens::Notifications>(
this, notificationManager, systemTask->nimble().alertService(), Screens::Notifications::Modes::Normal);
this, notificationManager, systemTask->nimble().alertService(), motorController, Screens::Notifications::Modes::Normal);
ReturnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp);
break;
case Apps::NotificationsPreview:
currentScreen = std::make_unique<Screens::Notifications>(
this, notificationManager, systemTask->nimble().alertService(), Screens::Notifications::Modes::Preview);
this, notificationManager, systemTask->nimble().alertService(), motorController, Screens::Notifications::Modes::Preview);
ReturnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp);
break;
case Apps::Timer:

View File

@@ -38,8 +38,9 @@ FirmwareValidation::FirmwareValidation(Pinetime::Applications::DisplayApp* app,
lv_label_set_text(labelIsValidated, "Please #00ff00 Validate# this version or\n#ff0000 Reset# to rollback to the previous version.");
buttonValidate = lv_btn_create(lv_scr_act(), nullptr);
lv_obj_align(buttonValidate, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
buttonValidate->user_data = this;
lv_obj_set_size(buttonValidate, 115, 50);
lv_obj_align(buttonValidate, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
lv_obj_set_event_cb(buttonValidate, ButtonEventHandler);
lv_obj_set_style_local_bg_color(buttonValidate, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x009900));
@@ -48,6 +49,7 @@ FirmwareValidation::FirmwareValidation(Pinetime::Applications::DisplayApp* app,
buttonReset = lv_btn_create(lv_scr_act(), nullptr);
buttonReset->user_data = this;
lv_obj_set_size(buttonReset, 115, 50);
lv_obj_align(buttonReset, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
lv_obj_set_style_local_bg_color(buttonReset, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x990000));
lv_obj_set_event_cb(buttonReset, ButtonEventHandler);

View File

@@ -6,10 +6,10 @@ Label::Label(uint8_t screenID, uint8_t numScreens, Pinetime::Applications::Displ
: Screen(app), labelText {labelText} {
if (numScreens > 1) {
pageIndicatorBasePoints[0].x = 240 - 1;
pageIndicatorBasePoints[0].y = 6;
pageIndicatorBasePoints[1].x = 240 - 1;
pageIndicatorBasePoints[1].y = 240 - 6;
pageIndicatorBasePoints[0].x = LV_HOR_RES - 1;
pageIndicatorBasePoints[0].y = 0;
pageIndicatorBasePoints[1].x = LV_HOR_RES - 1;
pageIndicatorBasePoints[1].y = LV_VER_RES;
pageIndicatorBase = lv_line_create(lv_scr_act(), NULL);
lv_obj_set_style_local_line_width(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3);
@@ -17,13 +17,13 @@ Label::Label(uint8_t screenID, uint8_t numScreens, Pinetime::Applications::Displ
lv_obj_set_style_local_line_rounded(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, true);
lv_line_set_points(pageIndicatorBase, pageIndicatorBasePoints, 2);
uint16_t indicatorSize = 228 / numScreens;
uint16_t indicatorSize = LV_VER_RES / numScreens;
uint16_t indicatorPos = indicatorSize * screenID;
pageIndicatorPoints[0].x = 240 - 1;
pageIndicatorPoints[0].y = (6 + indicatorPos);
pageIndicatorPoints[1].x = 240 - 1;
pageIndicatorPoints[1].y = (6 + indicatorPos) + indicatorSize;
pageIndicatorPoints[0].x = LV_HOR_RES - 1;
pageIndicatorPoints[0].y = indicatorPos;
pageIndicatorPoints[1].x = LV_HOR_RES - 1;
pageIndicatorPoints[1].y = indicatorPos + indicatorSize;
pageIndicator = lv_line_create(lv_scr_act(), NULL);
lv_obj_set_style_local_line_width(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3);

View File

@@ -25,42 +25,38 @@ List::List(uint8_t screenID,
settingsController.SetSettingsMenu(screenID);
if (numScreens > 1) {
pageIndicatorBasePoints[0].x = 240 - 1;
pageIndicatorBasePoints[0].y = 6;
pageIndicatorBasePoints[1].x = 240 - 1;
pageIndicatorBasePoints[1].y = 240 - 6;
pageIndicatorBasePoints[0].x = LV_HOR_RES - 1;
pageIndicatorBasePoints[0].y = 0;
pageIndicatorBasePoints[1].x = LV_HOR_RES - 1;
pageIndicatorBasePoints[1].y = LV_VER_RES;
pageIndicatorBase = lv_line_create(lv_scr_act(), NULL);
lv_obj_set_style_local_line_width(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3);
lv_obj_set_style_local_line_color(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111));
lv_obj_set_style_local_line_rounded(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, true);
lv_line_set_points(pageIndicatorBase, pageIndicatorBasePoints, 2);
uint16_t indicatorSize = 228 / numScreens;
uint16_t indicatorPos = indicatorSize * screenID;
const uint16_t indicatorSize = LV_VER_RES / numScreens;
const uint16_t indicatorPos = indicatorSize * screenID;
pageIndicatorPoints[0].x = 240 - 1;
pageIndicatorPoints[0].y = 6 + indicatorPos;
pageIndicatorPoints[1].x = 240 - 1;
pageIndicatorPoints[1].y = 6 + indicatorPos + indicatorSize;
pageIndicatorPoints[0].x = LV_HOR_RES - 1;
pageIndicatorPoints[0].y = indicatorPos;
pageIndicatorPoints[1].x = LV_HOR_RES - 1;
pageIndicatorPoints[1].y = indicatorPos + indicatorSize;
pageIndicator = lv_line_create(lv_scr_act(), NULL);
lv_obj_set_style_local_line_width(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3);
lv_obj_set_style_local_line_color(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
lv_obj_set_style_local_line_rounded(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, true);
lv_line_set_points(pageIndicator, pageIndicatorPoints, 2);
}
lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr);
// lv_obj_set_style_local_bg_color(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111));
lv_obj_set_style_local_bg_opa(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
lv_obj_set_style_local_pad_all(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 10);
lv_obj_set_style_local_pad_inner(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5);
lv_obj_set_style_local_pad_inner(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 4);
lv_obj_set_style_local_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
lv_obj_set_pos(container1, 0, 0);
lv_obj_set_width(container1, LV_HOR_RES - 15);
lv_obj_set_width(container1, LV_HOR_RES - 8);
lv_obj_set_height(container1, LV_VER_RES);
lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT);
@@ -73,11 +69,11 @@ List::List(uint8_t screenID,
itemApps[i] = lv_btn_create(container1, nullptr);
lv_obj_set_style_local_bg_opa(itemApps[i], LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_20);
lv_obj_set_style_local_radius(itemApps[i], LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20);
lv_obj_set_style_local_radius(itemApps[i], LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 57);
lv_obj_set_style_local_bg_color(itemApps[i], LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_obj_set_width(itemApps[i], LV_HOR_RES - 25);
lv_obj_set_height(itemApps[i], 52);
lv_obj_set_width(itemApps[i], LV_HOR_RES - 8);
lv_obj_set_height(itemApps[i], 57);
lv_obj_set_event_cb(itemApps[i], ButtonEventHandler);
lv_btn_set_layout(itemApps[i], LV_LAYOUT_ROW_MID);
itemApps[i]->user_data = this;

View File

@@ -1,35 +1,15 @@
#include "Metronome.h"
#include "Screen.h"
#include "Symbols.h"
#include "lvgl/lvgl.h"
#include "FreeRTOSConfig.h"
#include "task.h"
#include <string>
#include <tuple>
using namespace Pinetime::Applications::Screens;
namespace {
float calculateDelta(const TickType_t startTime, const TickType_t currentTime) {
TickType_t delta = 0;
// Take care of overflow
if (startTime > currentTime) {
delta = 0xffffffff - startTime;
delta += (currentTime + 1);
} else {
delta = currentTime - startTime;
}
return static_cast<float>(delta) / static_cast<float>(configTICK_RATE_HZ);
}
static void eventHandler(lv_obj_t* obj, lv_event_t event) {
Metronome* screen = static_cast<Metronome*>(obj->user_data);
void eventHandler(lv_obj_t* obj, lv_event_t event) {
auto* screen = static_cast<Metronome*>(obj->user_data);
screen->OnEvent(obj, event);
}
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) {
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) {
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);
@@ -41,7 +21,7 @@ namespace {
}
Metronome::Metronome(DisplayApp* app, Controllers::MotorController& motorController, System::SystemTask& systemTask)
: Screen(app), running {true}, currentState {States::Stopped}, startTime {}, motorController {motorController}, systemTask {systemTask} {
: Screen(app), motorController {motorController}, systemTask {systemTask} {
bpmArc = lv_arc_create(lv_scr_act(), nullptr);
bpmArc->user_data = this;
@@ -52,10 +32,10 @@ Metronome::Metronome(DisplayApp* app, Controllers::MotorController& motorControl
lv_arc_set_value(bpmArc, bpm);
lv_obj_set_size(bpmArc, 210, 210);
lv_arc_set_adjustable(bpmArc, true);
lv_obj_align(bpmArc, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 7);
lv_obj_align(bpmArc, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0);
bpmValue = createLabel(std::to_string(lv_arc_get_value(bpmArc)).c_str(), bpmArc, LV_ALIGN_IN_TOP_MID, &jetbrains_mono_76, 0, 55);
bpmLegend = createLabel("bpm", bpmValue, LV_ALIGN_OUT_BOTTOM_MID, &jetbrains_mono_bold_20, 0, 0);
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);
bpmTap = lv_btn_create(lv_scr_act(), nullptr);
bpmTap->user_data = this;
@@ -69,20 +49,23 @@ Metronome::Metronome(DisplayApp* app, Controllers::MotorController& motorControl
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);
lv_obj_align(bpbDropdown, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 15, -4);
lv_obj_set_size(bpbDropdown, 115, 50);
lv_obj_align(bpbDropdown, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
lv_dropdown_set_options(bpbDropdown, "1\n2\n3\n4\n5\n6\n7\n8\n9");
lv_dropdown_set_selected(bpbDropdown, bpb - 1);
bpbLegend = lv_label_create(bpbDropdown, nullptr);
lv_label_set_text(bpbLegend, "bpb");
lv_obj_align(bpbLegend, bpbDropdown, LV_ALIGN_IN_RIGHT_MID, -15, 0);
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);
playPause = lv_btn_create(lv_scr_act(), nullptr);
playPause->user_data = this;
lv_obj_set_event_cb(playPause, eventHandler);
lv_obj_align(playPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -15, -10);
lv_obj_set_height(playPause, 39);
playPauseLabel = lv_label_create(playPause, nullptr);
lv_label_set_text(playPauseLabel, Symbols::play);
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);
}
Metronome::~Metronome() {
@@ -90,28 +73,17 @@ Metronome::~Metronome() {
lv_obj_clean(lv_scr_act());
}
bool Metronome::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
return false;
}
bool Metronome::Refresh() {
switch (currentState) {
case States::Stopped: {
break;
}
case States::Running: {
if (calculateDelta(startTime, xTaskGetTickCount()) >= (60.0 / bpm)) {
counter--;
startTime -= 60.0 / bpm;
startTime = xTaskGetTickCount();
if (counter == 0) {
counter = bpb;
motorController.SetDuration(90);
} else {
motorController.SetDuration(30);
}
if (metronomeStarted) {
if (xTaskGetTickCount() - startTime > 60 * configTICK_RATE_HZ / bpm) {
startTime += 60 * configTICK_RATE_HZ / bpm;
counter--;
if (counter == 0) {
counter = bpb;
motorController.RunForDuration(90);
} else {
motorController.RunForDuration(30);
}
break;
}
}
return running;
@@ -125,42 +97,39 @@ void Metronome::OnEvent(lv_obj_t* obj, lv_event_t event) {
lv_label_set_text_fmt(bpmValue, "%03d", bpm);
} else if (obj == bpbDropdown) {
bpb = lv_dropdown_get_selected(obj) + 1;
lv_label_set_text_fmt(currentBpbText, "%d bpb", bpb);
lv_obj_realign(currentBpbText);
}
break;
}
case LV_EVENT_PRESSED: {
if (obj == bpmTap) {
float timeDelta = calculateDelta(tappedTime, xTaskGetTickCount());
if (tappedTime == 0 || timeDelta > 3) {
tappedTime = xTaskGetTickCount();
} else {
bpm = ceil(60.0 / timeDelta);
TickType_t delta = xTaskGetTickCount() - tappedTime;
if (tappedTime != 0 && delta < configTICK_RATE_HZ * 3) {
bpm = configTICK_RATE_HZ * 60 / delta;
lv_arc_set_value(bpmArc, bpm);
lv_label_set_text_fmt(bpmValue, "%03d", bpm);
tappedTime = xTaskGetTickCount();
}
tappedTime = xTaskGetTickCount();
}
break;
}
case LV_EVENT_CLICKED: {
if (obj == playPause) {
currentState = (currentState == States::Stopped ? States::Running : States::Stopped);
switch (currentState) {
case States::Stopped: {
lv_label_set_text(playPauseLabel, Symbols::play);
systemTask.PushMessage(System::Messages::EnableSleeping);
break;
}
case States::Running: {
lv_label_set_text(playPauseLabel, Symbols::pause);
systemTask.PushMessage(System::Messages::DisableSleeping);
startTime = xTaskGetTickCount();
counter = 1;
break;
}
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);
}
}
break;
}
default:
break;
}
}

View File

@@ -3,32 +3,32 @@
#include "systemtask/SystemTask.h"
#include "components/motor/MotorController.h"
#include <array>
namespace Pinetime {
namespace Applications {
namespace Screens {
namespace Pinetime::Applications::Screens {
class Metronome : public Screen {
public:
Metronome(DisplayApp* app, Controllers::MotorController& motorController, System::SystemTask& systemTask);
~Metronome() override;
bool Refresh() override;
void OnEvent(lv_obj_t* obj, lv_event_t event);
class Metronome : public Screen {
public:
Metronome(DisplayApp* app, Controllers::MotorController& motorController, System::SystemTask& systemTask);
~Metronome() override;
bool Refresh() override;
bool OnTouchEvent(TouchEvents event) override;
void OnEvent(lv_obj_t* obj, lv_event_t event);
enum class States { Running, Stopped };
private:
TickType_t startTime = 0;
TickType_t tappedTime = 0;
Controllers::MotorController& motorController;
System::SystemTask& systemTask;
int16_t bpm = 120;
uint8_t bpb = 4;
uint8_t counter = 1;
private:
bool running;
States currentState;
TickType_t startTime;
TickType_t tappedTime = 0;
Controllers::MotorController& motorController;
System::SystemTask& systemTask;
uint16_t bpm = 120;
uint8_t bpb = 4;
uint8_t counter = 1;
bool metronomeStarted = false;
lv_obj_t *bpmArc, *bpmTap, *bpmValue, *bpmLegend;
lv_obj_t *bpbDropdown, *bpbLegend;
lv_obj_t *playPause, *playPauseLabel;
};
lv_obj_t *bpmArc, *bpmTap, *bpmValue;
lv_obj_t *bpbDropdown, *currentBpbText;
lv_obj_t *playPause;
};
}
}
}

View File

@@ -50,60 +50,55 @@ inline void lv_img_set_src_arr(lv_obj_t* img, const lv_img_dsc_t* src_img) {
Music::Music(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::MusicService& music) : Screen(app), musicService(music) {
lv_obj_t* label;
lv_style_init(&btn_style);
lv_style_set_radius(&btn_style, LV_STATE_DEFAULT, 20);
lv_style_set_bg_color(&btn_style, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_style_set_bg_opa(&btn_style, LV_STATE_DEFAULT, LV_OPA_20);
btnVolDown = lv_btn_create(lv_scr_act(), nullptr);
btnVolDown->user_data = this;
lv_obj_set_event_cb(btnVolDown, event_handler);
lv_obj_set_size(btnVolDown, 65, 75);
lv_obj_align(btnVolDown, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 15, -10);
lv_obj_set_style_local_radius(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20);
lv_obj_set_style_local_bg_color(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_obj_set_style_local_bg_opa(btnVolDown, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_20);
lv_obj_set_size(btnVolDown, 76, 76);
lv_obj_align(btnVolDown, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
lv_obj_add_style(btnVolDown, LV_STATE_DEFAULT, &btn_style);
label = lv_label_create(btnVolDown, nullptr);
lv_label_set_text(label, Symbols::volumDown);
lv_obj_set_hidden(btnVolDown, !displayVolumeButtons);
lv_obj_set_hidden(btnVolDown, true);
btnVolUp = lv_btn_create(lv_scr_act(), nullptr);
btnVolUp->user_data = this;
lv_obj_set_event_cb(btnVolUp, event_handler);
lv_obj_set_size(btnVolUp, 65, 75);
lv_obj_align(btnVolUp, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, -15, -10);
lv_obj_set_style_local_radius(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20);
lv_obj_set_style_local_bg_color(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_obj_set_style_local_bg_opa(btnVolUp, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_20);
lv_obj_set_size(btnVolUp, 76, 76);
lv_obj_align(btnVolUp, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
lv_obj_add_style(btnVolUp, LV_STATE_DEFAULT, &btn_style);
label = lv_label_create(btnVolUp, nullptr);
lv_label_set_text(label, Symbols::volumUp);
lv_obj_set_hidden(btnVolUp, !displayVolumeButtons);
lv_obj_set_hidden(btnVolUp, true);
btnPrev = lv_btn_create(lv_scr_act(), nullptr);
btnPrev->user_data = this;
lv_obj_set_event_cb(btnPrev, event_handler);
lv_obj_set_size(btnPrev, 65, 75);
lv_obj_align(btnPrev, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 15, -10);
lv_obj_set_style_local_radius(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20);
lv_obj_set_style_local_bg_color(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_obj_set_style_local_bg_opa(btnPrev, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_20);
lv_obj_set_size(btnPrev, 76, 76);
lv_obj_align(btnPrev, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
lv_obj_add_style(btnPrev, LV_STATE_DEFAULT, &btn_style);
label = lv_label_create(btnPrev, nullptr);
lv_label_set_text(label, Symbols::stepBackward);
btnNext = lv_btn_create(lv_scr_act(), nullptr);
btnNext->user_data = this;
lv_obj_set_event_cb(btnNext, event_handler);
lv_obj_set_size(btnNext, 65, 75);
lv_obj_align(btnNext, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, -15, -10);
lv_obj_set_style_local_radius(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20);
lv_obj_set_style_local_bg_color(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_obj_set_style_local_bg_opa(btnNext, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_20);
lv_obj_set_size(btnNext, 76, 76);
lv_obj_align(btnNext, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
lv_obj_add_style(btnNext, LV_STATE_DEFAULT, &btn_style);
label = lv_label_create(btnNext, nullptr);
lv_label_set_text(label, Symbols::stepForward);
btnPlayPause = lv_btn_create(lv_scr_act(), nullptr);
btnPlayPause->user_data = this;
lv_obj_set_event_cb(btnPlayPause, event_handler);
lv_obj_set_size(btnPlayPause, 65, 75);
lv_obj_align(btnPlayPause, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, -10);
lv_obj_set_style_local_radius(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20);
lv_obj_set_style_local_bg_color(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_obj_set_style_local_bg_opa(btnPlayPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_20);
lv_obj_set_size(btnPlayPause, 76, 76);
lv_obj_align(btnPlayPause, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
lv_obj_add_style(btnPlayPause, LV_STATE_DEFAULT, &btn_style);
txtPlayPause = lv_label_create(btnPlayPause, nullptr);
lv_label_set_text(txtPlayPause, Symbols::play);
@@ -147,6 +142,7 @@ Music::Music(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Mus
}
Music::~Music() {
lv_style_reset(&btn_style);
lv_obj_clean(lv_scr_act());
}
@@ -272,21 +268,19 @@ void Music::OnObjectEvent(lv_obj_t* obj, lv_event_t event) {
bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
switch (event) {
case TouchEvents::SwipeUp: {
displayVolumeButtons = true;
lv_obj_set_hidden(btnVolDown, !displayVolumeButtons);
lv_obj_set_hidden(btnVolUp, !displayVolumeButtons);
lv_obj_set_hidden(btnVolDown, false);
lv_obj_set_hidden(btnVolUp, false);
lv_obj_set_hidden(btnNext, displayVolumeButtons);
lv_obj_set_hidden(btnPrev, displayVolumeButtons);
lv_obj_set_hidden(btnNext, true);
lv_obj_set_hidden(btnPrev, true);
return true;
}
case TouchEvents::SwipeDown: {
displayVolumeButtons = false;
lv_obj_set_hidden(btnNext, displayVolumeButtons);
lv_obj_set_hidden(btnPrev, displayVolumeButtons);
lv_obj_set_hidden(btnNext, false);
lv_obj_set_hidden(btnPrev, false);
lv_obj_set_hidden(btnVolDown, !displayVolumeButtons);
lv_obj_set_hidden(btnVolUp, !displayVolumeButtons);
lv_obj_set_hidden(btnVolDown, true);
lv_obj_set_hidden(btnVolUp, true);
return true;
}
case TouchEvents::SwipeLeft: {
@@ -298,7 +292,7 @@ bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
return true;
}
default: {
return true;
return false;
}
}
}

View File

@@ -57,10 +57,11 @@ namespace Pinetime {
lv_obj_t* imgDiscAnim;
lv_obj_t* txtTrackDuration;
lv_style_t btn_style;
/** For the spinning disc animation */
bool frameB;
bool displayVolumeButtons = false;
Pinetime::Controllers::MusicService& musicService;
std::string artist;

View File

@@ -11,6 +11,7 @@ extern lv_font_t jetbrains_mono_bold_20;
Notifications::Notifications(DisplayApp* app,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::AlertNotificationService& alertNotificationService,
Pinetime::Controllers::MotorController& motorController,
Modes mode)
: Screen(app), notificationManager {notificationManager}, alertNotificationService {alertNotificationService}, mode {mode} {
notificationManager.ClearNewNotificationFlag();
@@ -36,25 +37,31 @@ Notifications::Notifications(DisplayApp* app,
}
if (mode == Modes::Preview) {
if (notification.category == Controllers::NotificationManager::Categories::IncomingCall) {
motorController.StartRinging();
} else {
motorController.RunForDuration(35);
timeoutLine = lv_line_create(lv_scr_act(), nullptr);
timeoutLine = lv_line_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_line_width(timeoutLine, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3);
lv_obj_set_style_local_line_color(timeoutLine, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
lv_obj_set_style_local_line_rounded(timeoutLine, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, true);
lv_obj_set_style_local_line_width(timeoutLine, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3);
lv_obj_set_style_local_line_color(timeoutLine, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
lv_obj_set_style_local_line_rounded(timeoutLine, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, true);
lv_line_set_points(timeoutLine, timeoutLinePoints, 2);
timeoutTickCountStart = xTaskGetTickCount();
timeoutTickCountEnd = timeoutTickCountStart + (5 * 1024);
lv_line_set_points(timeoutLine, timeoutLinePoints, 2);
timeoutTickCountStart = xTaskGetTickCount();
timeoutTickCountEnd = timeoutTickCountStart + (5 * 1024);
}
}
}
Notifications::~Notifications() {
// make sure we stop any vibrations before exiting
Controllers::MotorController::StopRinging();
lv_obj_clean(lv_scr_act());
}
bool Notifications::Refresh() {
if (mode == Modes::Preview) {
if (mode == Modes::Preview && timeoutLine != nullptr) {
auto tick = xTaskGetTickCount();
int32_t pos = 240 - ((tick - timeoutTickCountStart) / ((timeoutTickCountEnd - timeoutTickCountStart) / 240));
if (pos < 0)
@@ -63,13 +70,13 @@ bool Notifications::Refresh() {
timeoutLinePoints[1].x = pos;
lv_line_set_points(timeoutLine, timeoutLinePoints, 2);
}
return running;
return running && currentItem->IsRunning();
}
bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
if (mode != Modes::Normal)
return true;
if (mode != Modes::Normal) {
return false;
}
switch (event) {
case Pinetime::Applications::TouchEvents::SwipeDown: {
@@ -130,19 +137,9 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
}
namespace {
static void AcceptIncomingCallEventHandler(lv_obj_t* obj, lv_event_t event) {
void CallEventHandler(lv_obj_t* obj, lv_event_t event) {
auto* item = static_cast<Notifications::NotificationItem*>(obj->user_data);
item->OnAcceptIncomingCall(event);
}
static void MuteIncomingCallEventHandler(lv_obj_t* obj, lv_event_t event) {
auto* item = static_cast<Notifications::NotificationItem*>(obj->user_data);
item->OnMuteIncomingCall(event);
}
static void RejectIncomingCallEventHandler(lv_obj_t* obj, lv_event_t event) {
auto* item = static_cast<Notifications::NotificationItem*>(obj->user_data);
item->OnRejectIncomingCall(event);
item->OnCallButtonEvent(obj, event);
}
}
@@ -154,7 +151,6 @@ Notifications::NotificationItem::NotificationItem(const char* title,
Modes mode,
Pinetime::Controllers::AlertNotificationService& alertNotificationService)
: notifNr {notifNr}, notifNb {notifNb}, mode {mode}, alertNotificationService {alertNotificationService} {
lv_obj_t* container1 = lv_cont_create(lv_scr_act(), NULL);
lv_obj_set_style_local_bg_color(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x222222));
@@ -212,7 +208,7 @@ Notifications::NotificationItem::NotificationItem(const char* title,
bt_accept = lv_btn_create(lv_scr_act(), nullptr);
bt_accept->user_data = this;
lv_obj_set_event_cb(bt_accept, AcceptIncomingCallEventHandler);
lv_obj_set_event_cb(bt_accept, CallEventHandler);
lv_obj_set_size(bt_accept, 76, 76);
lv_obj_align(bt_accept, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
label_accept = lv_label_create(bt_accept, nullptr);
@@ -221,7 +217,7 @@ Notifications::NotificationItem::NotificationItem(const char* title,
bt_reject = lv_btn_create(lv_scr_act(), nullptr);
bt_reject->user_data = this;
lv_obj_set_event_cb(bt_reject, RejectIncomingCallEventHandler);
lv_obj_set_event_cb(bt_reject, CallEventHandler);
lv_obj_set_size(bt_reject, 76, 76);
lv_obj_align(bt_reject, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
label_reject = lv_label_create(bt_reject, nullptr);
@@ -230,7 +226,7 @@ Notifications::NotificationItem::NotificationItem(const char* title,
bt_mute = lv_btn_create(lv_scr_act(), nullptr);
bt_mute->user_data = this;
lv_obj_set_event_cb(bt_mute, MuteIncomingCallEventHandler);
lv_obj_set_event_cb(bt_mute, CallEventHandler);
lv_obj_set_size(bt_mute, 76, 76);
lv_obj_align(bt_mute, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
label_mute = lv_label_create(bt_mute, nullptr);
@@ -246,25 +242,22 @@ Notifications::NotificationItem::NotificationItem(const char* title,
lv_label_set_text(backgroundLabel, "");
}
void Notifications::NotificationItem::OnAcceptIncomingCall(lv_event_t event) {
if (event != LV_EVENT_CLICKED)
void Notifications::NotificationItem::OnCallButtonEvent(lv_obj_t* obj, lv_event_t event) {
if (event != LV_EVENT_CLICKED) {
return;
}
alertNotificationService.AcceptIncomingCall();
}
Controllers::MotorController::StopRinging();
void Notifications::NotificationItem::OnMuteIncomingCall(lv_event_t event) {
if (event != LV_EVENT_CLICKED)
return;
if (obj == bt_accept) {
alertNotificationService.AcceptIncomingCall();
} else if (obj == bt_reject) {
alertNotificationService.RejectIncomingCall();
} else if (obj == bt_mute) {
alertNotificationService.MuteIncomingCall();
}
alertNotificationService.MuteIncomingCall();
}
void Notifications::NotificationItem::OnRejectIncomingCall(lv_event_t event) {
if (event != LV_EVENT_CLICKED)
return;
alertNotificationService.RejectIncomingCall();
running = false;
}
Notifications::NotificationItem::~NotificationItem() {

View File

@@ -5,6 +5,7 @@
#include <memory>
#include "Screen.h"
#include "components/ble/NotificationManager.h"
#include "components/motor/MotorController.h"
namespace Pinetime {
namespace Controllers {
@@ -19,6 +20,7 @@ namespace Pinetime {
explicit Notifications(DisplayApp* app,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::AlertNotificationService& alertNotificationService,
Pinetime::Controllers::MotorController& motorController,
Modes mode);
~Notifications() override;
@@ -35,12 +37,10 @@ namespace Pinetime {
Modes mode,
Pinetime::Controllers::AlertNotificationService& alertNotificationService);
~NotificationItem();
bool Refresh() {
return false;
bool IsRunning() const {
return running;
}
void OnAcceptIncomingCall(lv_event_t event);
void OnMuteIncomingCall(lv_event_t event);
void OnRejectIncomingCall(lv_event_t event);
void OnCallButtonEvent(lv_obj_t*, lv_event_t event);
private:
uint8_t notifNr = 0;
@@ -60,6 +60,7 @@ namespace Pinetime {
lv_obj_t* bottomPlaceholder;
Modes mode;
Pinetime::Controllers::AlertNotificationService& alertNotificationService;
bool running = true;
};
private:
@@ -75,7 +76,7 @@ namespace Pinetime {
bool validDisplay = false;
lv_point_t timeoutLinePoints[2] {{0, 1}, {239, 1}};
lv_obj_t* timeoutLine;
lv_obj_t* timeoutLine = nullptr;
uint32_t timeoutTickCountStart;
uint32_t timeoutTickCountEnd;
};

View File

@@ -35,37 +35,35 @@ Tile::Tile(uint8_t screenID,
label_time = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_fmt(label_time, "%02i:%02i", dateTimeController.Hours(), dateTimeController.Minutes());
lv_label_set_align(label_time, LV_LABEL_ALIGN_CENTER);
lv_obj_align(label_time, nullptr, LV_ALIGN_IN_TOP_LEFT, 15, 6);
lv_obj_align(label_time, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0);
// Battery
batteryIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryController.PercentRemaining()));
lv_obj_align(batteryIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, -15, 6);
lv_obj_align(batteryIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, -8, 0);
if (numScreens > 1) {
pageIndicatorBasePoints[0].x = 240 - 1;
pageIndicatorBasePoints[0].y = 6;
pageIndicatorBasePoints[1].x = 240 - 1;
pageIndicatorBasePoints[1].y = 240 - 6;
pageIndicatorBasePoints[0].x = LV_HOR_RES - 1;
pageIndicatorBasePoints[0].y = 0;
pageIndicatorBasePoints[1].x = LV_HOR_RES - 1;
pageIndicatorBasePoints[1].y = LV_VER_RES;
pageIndicatorBase = lv_line_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_line_width(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3);
lv_obj_set_style_local_line_color(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111));
lv_obj_set_style_local_line_rounded(pageIndicatorBase, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, true);
lv_line_set_points(pageIndicatorBase, pageIndicatorBasePoints, 2);
uint16_t indicatorSize = 228 / numScreens;
uint16_t indicatorPos = indicatorSize * screenID;
const uint16_t indicatorSize = LV_VER_RES / numScreens;
const uint16_t indicatorPos = indicatorSize * screenID;
pageIndicatorPoints[0].x = 240 - 1;
pageIndicatorPoints[0].y = 6 + indicatorPos;
pageIndicatorPoints[1].x = 240 - 1;
pageIndicatorPoints[1].y = 6 + indicatorPos + indicatorSize;
pageIndicatorPoints[0].x = LV_HOR_RES - 1;
pageIndicatorPoints[0].y = indicatorPos;
pageIndicatorPoints[1].x = LV_HOR_RES - 1;
pageIndicatorPoints[1].y = indicatorPos + indicatorSize;
pageIndicator = lv_line_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_line_width(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 3);
lv_obj_set_style_local_line_color(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
lv_obj_set_style_local_line_rounded(pageIndicator, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, true);
lv_line_set_points(pageIndicator, pageIndicatorPoints, 2);
}
@@ -85,7 +83,7 @@ Tile::Tile(uint8_t screenID,
btnm1 = lv_btnmatrix_create(lv_scr_act(), nullptr);
lv_btnmatrix_set_map(btnm1, btnmMap);
lv_obj_set_size(btnm1, LV_HOR_RES - 10, LV_VER_RES - 60);
lv_obj_set_size(btnm1, LV_HOR_RES - 16, LV_VER_RES - 60);
lv_obj_align(btnm1, NULL, LV_ALIGN_CENTER, 0, 10);
lv_obj_set_style_local_radius(btnm1, LV_BTNMATRIX_PART_BTN, LV_STATE_DEFAULT, 20);
@@ -93,6 +91,8 @@ Tile::Tile(uint8_t screenID,
lv_obj_set_style_local_bg_color(btnm1, LV_BTNMATRIX_PART_BTN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
lv_obj_set_style_local_bg_opa(btnm1, LV_BTNMATRIX_PART_BTN, LV_STATE_DISABLED, LV_OPA_20);
lv_obj_set_style_local_bg_color(btnm1, LV_BTNMATRIX_PART_BTN, LV_STATE_DISABLED, lv_color_hex(0x111111));
lv_obj_set_style_local_pad_all(btnm1, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 0);
lv_obj_set_style_local_pad_inner(btnm1, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 10);
for (uint8_t i = 0; i < 6; i++) {
lv_btnmatrix_set_btn_ctrl(btnm1, i, LV_BTNMATRIX_CTRL_CLICK_TRIG);

View File

@@ -67,12 +67,12 @@ WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app,
batteryIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(batteryIcon, Symbols::batteryHalf);
lv_obj_align(batteryIcon, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, -8, -4);
lv_obj_align(batteryIcon, NULL, LV_ALIGN_IN_TOP_RIGHT, 0, 0);
notificationIcon = lv_label_create(lv_scr_act(), NULL);
lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00));
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false));
lv_obj_align(notificationIcon, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 8, -4);
lv_obj_align(notificationIcon, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
// Date - Day / Week day

View File

@@ -35,7 +35,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
batteryIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(batteryIcon, Symbols::batteryFull);
lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 2);
lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0);
batteryPlug = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(batteryPlug, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFF0000));
@@ -50,7 +50,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
notificationIcon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00));
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false));
lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 10, 0);
lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0);
label_date = lv_label_create(lv_scr_act(), nullptr);
lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_CENTER, 0, 60);
@@ -75,7 +75,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
heartbeatIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(heartbeatIcon, Symbols::heartBeat);
lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B));
lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2);
lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
heartbeatValue = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B));
@@ -85,7 +85,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
stepValue = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FFE7));
lv_label_set_text(stepValue, "0");
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2);
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
stepIcon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FFE7));
@@ -110,7 +110,7 @@ bool WatchFaceDigital::Refresh() {
if (bleState.IsUpdated()) {
lv_label_set_text(bleIcon, BleIcon::GetIcon(bleState.Get()));
}
lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 5);
lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0);
lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0);
lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0);
@@ -208,7 +208,7 @@ bool WatchFaceDigital::Refresh() {
lv_label_set_text_static(heartbeatValue, "");
}
lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2);
lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
}
@@ -216,7 +216,7 @@ bool WatchFaceDigital::Refresh() {
motionSensorOk = motionController.IsSensorOk();
if (stepCount.IsUpdated() || motionSensorOk.IsUpdated()) {
lv_label_set_text_fmt(stepValue, "%lu", stepCount.Get());
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2);
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0);
}

View File

@@ -30,27 +30,35 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
motorController {motorController},
settingsController {settingsController} {
// This is the distance (padding) between all objects on this screen.
static constexpr uint8_t innerDistance = 10;
// Time
label_time = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_fmt(label_time, "%02i:%02i", dateTimeController.Hours(), dateTimeController.Minutes());
lv_label_set_align(label_time, LV_LABEL_ALIGN_CENTER);
lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 15, 4);
lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, 0);
batteryIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryController.PercentRemaining()));
lv_obj_align(batteryIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, -15, 4);
lv_obj_align(batteryIcon, nullptr, LV_ALIGN_IN_TOP_RIGHT, 0, 0);
lv_obj_t* lbl_btn;
static constexpr uint8_t barHeight = 20 + innerDistance;
static constexpr uint8_t buttonHeight = (LV_VER_RES_MAX - barHeight - innerDistance) / 2;
static constexpr uint8_t buttonWidth = (LV_HOR_RES_MAX - innerDistance) / 2; // wide buttons
//static constexpr uint8_t buttonWidth = buttonHeight; // square buttons
static constexpr uint8_t buttonXOffset = (LV_HOR_RES_MAX - buttonWidth * 2 - innerDistance) / 2;
lv_style_init(&btn_style);
lv_style_set_radius(&btn_style, LV_STATE_DEFAULT, buttonHeight / 4);
lv_style_set_bg_color(&btn_style, LV_STATE_DEFAULT, lv_color_hex(0x111111));
btn1 = lv_btn_create(lv_scr_act(), nullptr);
btn1->user_data = this;
lv_obj_set_event_cb(btn1, ButtonEventHandler);
lv_obj_align(btn1, nullptr, LV_ALIGN_CENTER, -50, -30);
lv_obj_set_style_local_radius(btn1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20);
lv_obj_set_style_local_bg_color(btn1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111));
lv_obj_set_style_local_bg_grad_dir(btn1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_GRAD_DIR_NONE);
lv_btn_set_fit2(btn1, LV_FIT_TIGHT, LV_FIT_TIGHT);
lv_obj_add_style(btn1, LV_BTN_PART_MAIN, &btn_style);
lv_obj_set_size(btn1, buttonWidth, buttonHeight);
lv_obj_align(btn1, nullptr, LV_ALIGN_IN_TOP_LEFT, buttonXOffset, barHeight);
btn1_lvl = lv_label_create(btn1, nullptr);
lv_obj_set_style_local_text_font(btn1_lvl, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48);
@@ -59,12 +67,11 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
btn2 = lv_btn_create(lv_scr_act(), nullptr);
btn2->user_data = this;
lv_obj_set_event_cb(btn2, ButtonEventHandler);
lv_obj_align(btn2, nullptr, LV_ALIGN_CENTER, 50, -30);
lv_obj_set_style_local_radius(btn2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20);
lv_obj_set_style_local_bg_color(btn2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111));
lv_obj_set_style_local_bg_grad_dir(btn2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_GRAD_DIR_NONE);
lv_btn_set_fit2(btn2, LV_FIT_TIGHT, LV_FIT_TIGHT);
lv_obj_add_style(btn2, LV_BTN_PART_MAIN, &btn_style);
lv_obj_set_size(btn2, buttonWidth, buttonHeight);
lv_obj_align(btn2, nullptr, LV_ALIGN_IN_TOP_RIGHT, - buttonXOffset, barHeight);
lv_obj_t* lbl_btn;
lbl_btn = lv_label_create(btn2, nullptr);
lv_obj_set_style_local_text_font(lbl_btn, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48);
lv_label_set_text_static(lbl_btn, Symbols::highlight);
@@ -72,14 +79,11 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
btn3 = lv_btn_create(lv_scr_act(), nullptr);
btn3->user_data = this;
lv_obj_set_event_cb(btn3, ButtonEventHandler);
lv_obj_align(btn3, nullptr, LV_ALIGN_CENTER, -50, 60);
lv_btn_set_checkable(btn3, true);
lv_obj_set_style_local_radius(btn3, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20);
lv_obj_set_style_local_bg_color(btn3, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111));
lv_obj_set_style_local_bg_grad_dir(btn3, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_GRAD_DIR_NONE);
lv_obj_add_style(btn3, LV_BTN_PART_MAIN, &btn_style);
lv_obj_set_style_local_bg_color(btn3, LV_BTN_PART_MAIN, LV_STATE_CHECKED, LV_COLOR_GREEN);
lv_obj_set_style_local_bg_grad_dir(btn1, LV_BTN_PART_MAIN, LV_STATE_CHECKED, LV_GRAD_DIR_NONE);
lv_btn_set_fit2(btn3, LV_FIT_TIGHT, LV_FIT_TIGHT);
lv_obj_set_size(btn3, buttonWidth, buttonHeight);
lv_obj_align(btn3, nullptr, LV_ALIGN_IN_BOTTOM_LEFT, buttonXOffset, 0);
btn3_lvl = lv_label_create(btn3, nullptr);
lv_obj_set_style_local_text_font(btn3_lvl, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48);
@@ -94,11 +98,9 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
btn4 = lv_btn_create(lv_scr_act(), nullptr);
btn4->user_data = this;
lv_obj_set_event_cb(btn4, ButtonEventHandler);
lv_obj_align(btn4, nullptr, LV_ALIGN_CENTER, 50, 60);
lv_obj_set_style_local_radius(btn4, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 20);
lv_obj_set_style_local_bg_color(btn4, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111));
lv_obj_set_style_local_bg_grad_dir(btn4, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_GRAD_DIR_NONE);
lv_btn_set_fit2(btn4, LV_FIT_TIGHT, LV_FIT_TIGHT);
lv_obj_add_style(btn4, LV_BTN_PART_MAIN, &btn_style);
lv_obj_set_size(btn4, buttonWidth, buttonHeight);
lv_obj_align(btn4, nullptr, LV_ALIGN_IN_BOTTOM_RIGHT, - buttonXOffset, 0);
lbl_btn = lv_label_create(btn4, nullptr);
lv_obj_set_style_local_text_font(lbl_btn, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48);
@@ -114,6 +116,7 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
}
QuickSettings::~QuickSettings() {
lv_style_reset(&btn_style);
lv_task_del(taskUpdate);
lv_obj_clean(lv_scr_act());
settingsController.SaveSettings();
@@ -140,7 +143,7 @@ void QuickSettings::OnButtonEvent(lv_obj_t* object, lv_event_t event) {
if (lv_obj_get_state(btn3, LV_BTN_PART_MAIN) & LV_STATE_CHECKED) {
settingsController.SetVibrationStatus(Controllers::Settings::Vibration::ON);
motorController.SetDuration(35);
motorController.RunForDuration(35);
lv_label_set_text_static(btn3_lvl, Symbols::notificationsOn);
} else {
settingsController.SetVibrationStatus(Controllers::Settings::Vibration::OFF);

View File

@@ -44,6 +44,8 @@ namespace Pinetime {
lv_obj_t* batteryIcon;
lv_obj_t* label_time;
lv_style_t btn_style;
lv_obj_t* btn1;
lv_obj_t* btn1_lvl;
lv_obj_t* btn2;

View File

@@ -5,6 +5,7 @@
#include <libraries/gpiote/app_gpiote.h>
#include <libraries/timer/app_timer.h>
#include <softdevice/common/nrf_sdh.h>
#include <nrf_delay.h>
// nimble
#define min // workaround: nimble's min/max macros conflict with libstdc++
@@ -304,6 +305,20 @@ int main(void) {
nrf_drv_clock_init();
// Unblock i2c?
nrf_gpio_cfg(pinTwiScl,
NRF_GPIO_PIN_DIR_OUTPUT,
NRF_GPIO_PIN_INPUT_DISCONNECT,
NRF_GPIO_PIN_NOPULL,
NRF_GPIO_PIN_S0D1,
NRF_GPIO_PIN_NOSENSE);
nrf_gpio_pin_set(pinTwiScl);
for (uint8_t i = 0; i < 16; i++) {
nrf_gpio_pin_toggle(pinTwiScl);
nrf_delay_us(5);
}
nrf_gpio_cfg_default(pinTwiScl);
debounceTimer = xTimerCreate("debounceTimer", 200, pdFALSE, (void*) 0, DebounceTimerCallback);
debounceChargeTimer = xTimerCreate("debounceTimerCharge", 200, pdFALSE, (void*) 0, DebounceTimerChargeCallback);

View File

@@ -269,14 +269,13 @@ void SystemTask::Work() {
if (isSleeping && !isWakingUp) {
GoToRunning();
}
motorController.SetDuration(35);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification);
break;
case Messages::OnTimerDone:
if (isSleeping && !isWakingUp) {
GoToRunning();
}
motorController.SetDuration(35);
motorController.RunForDuration(35);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::TimerDone);
break;
case Messages::BleConnected:
@@ -332,7 +331,7 @@ void SystemTask::Work() {
stepCounterMustBeReset = true;
break;
case Messages::OnChargingEvent:
motorController.SetDuration(15);
motorController.RunForDuration(15);
// Battery level is updated on every message - there's no need to do anything
break;