From c77634ce320cdb9bbd9de136e409bd9a0ca64153 Mon Sep 17 00:00:00 2001 From: timaios Date: Fri, 9 Jul 2021 14:11:20 +0200 Subject: [PATCH 01/50] Added new screen: SettingSetTime --- .../screens/settings/SettingSetTime.cpp | 174 ++++++++++++++++++ .../screens/settings/SettingSetTime.h | 38 ++++ 2 files changed, 212 insertions(+) create mode 100644 src/displayapp/screens/settings/SettingSetTime.cpp create mode 100644 src/displayapp/screens/settings/SettingSetTime.h diff --git a/src/displayapp/screens/settings/SettingSetTime.cpp b/src/displayapp/screens/settings/SettingSetTime.cpp new file mode 100644 index 00000000..22d1c011 --- /dev/null +++ b/src/displayapp/screens/settings/SettingSetTime.cpp @@ -0,0 +1,174 @@ +#include "SettingSetTime.h" +#include +#include +#include +#include "displayapp/DisplayApp.h" +#include "displayapp/screens/Symbols.h" + +using namespace Pinetime::Applications::Screens; + +namespace { + static void event_handler(lv_obj_t * obj, lv_event_t event) { + SettingSetTime* screen = static_cast(obj->user_data); + screen->HandleButtonPress(obj, event); + } +} + +SettingSetTime::SettingSetTime( + Pinetime::Applications::DisplayApp *app, Pinetime::Controllers::DateTime &dateTimeController) : + Screen(app), + dateTimeController {dateTimeController} +{ + + 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_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_pos(container1, 30, 60); + lv_obj_set_width(container1, LV_HOR_RES - 50); + lv_obj_set_height(container1, LV_VER_RES - 60); + lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT); + + lv_obj_t * title = lv_label_create(lv_scr_act(), NULL); + lv_label_set_text_static(title, "Set current time"); + lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); + lv_obj_align(title, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 15, 15); + + lv_obj_t * icon = lv_label_create(lv_scr_act(), NULL); + lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); + + lv_label_set_text_static(icon, Symbols::clock); + lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); + lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); + + hoursValue = static_cast(dateTimeController.Hours()); + lblHours = lv_label_create(lv_scr_act(), NULL); + lv_obj_set_style_local_text_font(lblHours, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); + lv_label_set_text_fmt(lblHours, "%02d", hoursValue); + lv_label_set_align(lblHours, LV_LABEL_ALIGN_CENTER); + lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, -72, -6); + + lv_obj_t * lblColon1 = lv_label_create(lv_scr_act(), NULL); + lv_obj_set_style_local_text_font(lblColon1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); + lv_label_set_text_static(lblColon1, ":"); + lv_label_set_align(lblColon1, LV_LABEL_ALIGN_CENTER); + lv_obj_align(lblColon1, lv_scr_act(), LV_ALIGN_CENTER, -36, -8); + + minutesValue = static_cast(dateTimeController.Minutes()); + lblMinutes = lv_label_create(lv_scr_act(), NULL); + lv_obj_set_style_local_text_font(lblMinutes, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); + lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); + lv_label_set_align(lblMinutes, LV_LABEL_ALIGN_CENTER); + lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, 0, -6); + + lv_obj_t * lblColon2 = lv_label_create(lv_scr_act(), NULL); + lv_obj_set_style_local_text_font(lblColon2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); + lv_label_set_text_static(lblColon2, ":"); + lv_label_set_align(lblColon2, LV_LABEL_ALIGN_CENTER); + lv_obj_align(lblColon2, lv_scr_act(), LV_ALIGN_CENTER, 36, -8); + + lv_obj_t * lblSeconds = lv_label_create(lv_scr_act(), NULL); + lv_obj_set_style_local_text_font(lblSeconds, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); + lv_label_set_text_static(lblSeconds, "00"); + lv_label_set_align(lblSeconds, LV_LABEL_ALIGN_CENTER); + lv_obj_align(lblSeconds, lv_scr_act(), LV_ALIGN_CENTER, 72, -6); + + btnHoursPlus = lv_btn_create(lv_scr_act(), NULL); + btnHoursPlus->user_data = this; + lv_obj_set_size(btnHoursPlus, 50, 40); + lv_obj_align(btnHoursPlus, lv_scr_act(), LV_ALIGN_CENTER, -72, -50); + lv_obj_set_style_local_value_str(btnHoursPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); + lv_obj_set_event_cb(btnHoursPlus, event_handler); + + btnHoursMinus = lv_btn_create(lv_scr_act(), NULL); + btnHoursMinus->user_data = this; + lv_obj_set_size(btnHoursMinus, 50, 40); + lv_obj_align(btnHoursMinus, lv_scr_act(), LV_ALIGN_CENTER, -72, 40); + lv_obj_set_style_local_value_str(btnHoursMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); + lv_obj_set_event_cb(btnHoursMinus, event_handler); + + btnMinutesPlus = lv_btn_create(lv_scr_act(), NULL); + btnMinutesPlus->user_data = this; + lv_obj_set_size(btnMinutesPlus, 50, 40); + lv_obj_align(btnMinutesPlus, lv_scr_act(), LV_ALIGN_CENTER, 0, -50); + lv_obj_set_style_local_value_str(btnMinutesPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); + lv_obj_set_event_cb(btnMinutesPlus, event_handler); + + btnMinutesMinus = lv_btn_create(lv_scr_act(), NULL); + btnMinutesMinus->user_data = this; + lv_obj_set_size(btnMinutesMinus, 50, 40); + lv_obj_align(btnMinutesMinus, lv_scr_act(), LV_ALIGN_CENTER, 0, 40); + lv_obj_set_style_local_value_str(btnMinutesMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); + lv_obj_set_event_cb(btnMinutesMinus, event_handler); + + btnSetTime = lv_btn_create(lv_scr_act(), NULL); + btnSetTime->user_data = this; + lv_obj_set_size(btnSetTime, 70, 40); + lv_obj_align(btnSetTime, lv_scr_act(), LV_ALIGN_CENTER, 0, 90); + lv_obj_set_style_local_value_str(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Set"); + lv_obj_set_event_cb(btnSetTime, event_handler); +} + +SettingSetTime::~SettingSetTime() { + lv_obj_clean(lv_scr_act()); +} + +bool SettingSetTime::Refresh() { + return running; +} + + +void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { + + if(object == btnHoursPlus && (event == LV_EVENT_PRESSED)) { + hoursValue++; + if (hoursValue > 23) + hoursValue = 0; + lv_label_set_text_fmt(lblHours, "%02d", hoursValue); + lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, -72, -6); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); + } + + if(object == btnHoursMinus && (event == LV_EVENT_PRESSED)) { + hoursValue--; + if (hoursValue < 0) + hoursValue = 23; + lv_label_set_text_fmt(lblHours, "%02d", hoursValue); + lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, -72, -6); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); + } + + if(object == btnMinutesPlus && (event == LV_EVENT_PRESSED)) { + minutesValue++; + if (minutesValue > 59) + minutesValue = 0; + lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); + lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, 0, -6); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); + } + + if(object == btnMinutesMinus && (event == LV_EVENT_PRESSED)) { + minutesValue--; + if (minutesValue < 0) + minutesValue = 59; + lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); + lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, 0, -6); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); + } + + if(object == btnSetTime && (event == LV_EVENT_PRESSED)) { + NRF_LOG_INFO("Setting time (manually) to %02d:%02d:00", hoursValue, minutesValue); + dateTimeController.SetTime(dateTimeController.Year(), + static_cast(dateTimeController.Month()), + dateTimeController.Day(), + static_cast(dateTimeController.DayOfWeek()), + static_cast(hoursValue), + static_cast(minutesValue), + 0, + nrf_rtc_counter_get(portNRF_RTC_REG)); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_DISABLED); + } +} diff --git a/src/displayapp/screens/settings/SettingSetTime.h b/src/displayapp/screens/settings/SettingSetTime.h new file mode 100644 index 00000000..da92d6e4 --- /dev/null +++ b/src/displayapp/screens/settings/SettingSetTime.h @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include "components/datetime/DateTimeController.h" +#include "displayapp/screens/Screen.h" + +namespace Pinetime { + + namespace Applications { + namespace Screens { + + class SettingSetTime : public Screen{ + public: + SettingSetTime(DisplayApp* app, Pinetime::Controllers::DateTime &dateTimeController); + ~SettingSetTime() override; + + bool Refresh() override; + void HandleButtonPress(lv_obj_t *object, lv_event_t event); + + private: + + Controllers::DateTime& dateTimeController; + + int hoursValue; + int minutesValue; + lv_obj_t * lblHours; + lv_obj_t * lblMinutes; + lv_obj_t * btnHoursPlus; + lv_obj_t * btnHoursMinus; + lv_obj_t * btnMinutesPlus; + lv_obj_t * btnMinutesMinus; + lv_obj_t * btnSetTime; + + }; + } + } +} From c396925766ebfd05f3f345bf426a4fa59305ec74 Mon Sep 17 00:00:00 2001 From: timaios Date: Fri, 9 Jul 2021 14:12:26 +0200 Subject: [PATCH 02/50] Added new screen: SettingSetDate --- .../screens/settings/SettingSetDate.cpp | 272 ++++++++++++++++++ .../screens/settings/SettingSetDate.h | 45 +++ 2 files changed, 317 insertions(+) create mode 100644 src/displayapp/screens/settings/SettingSetDate.cpp create mode 100644 src/displayapp/screens/settings/SettingSetDate.h diff --git a/src/displayapp/screens/settings/SettingSetDate.cpp b/src/displayapp/screens/settings/SettingSetDate.cpp new file mode 100644 index 00000000..5c1aec54 --- /dev/null +++ b/src/displayapp/screens/settings/SettingSetDate.cpp @@ -0,0 +1,272 @@ +#include "SettingSetDate.h" +#include +#include +#include +#include "displayapp/DisplayApp.h" +#include "displayapp/screens/Symbols.h" + +#define POS_X_DAY -72 +#define POS_X_MONTH 0 +#define POS_X_YEAR 72 +#define POS_Y_PLUS -50 +#define POS_Y_TEXT -6 +#define POS_Y_MINUS 40 + +using namespace Pinetime::Applications::Screens; + +namespace { + static void event_handler(lv_obj_t * obj, lv_event_t event) { + SettingSetDate* screen = static_cast(obj->user_data); + screen->HandleButtonPress(obj, event); + } +} + +SettingSetDate::SettingSetDate( + Pinetime::Applications::DisplayApp *app, Pinetime::Controllers::DateTime &dateTimeController) : + Screen(app), + dateTimeController {dateTimeController} +{ + + 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_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_pos(container1, 30, 60); + lv_obj_set_width(container1, LV_HOR_RES - 50); + lv_obj_set_height(container1, LV_VER_RES - 60); + lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT); + + lv_obj_t * title = lv_label_create(lv_scr_act(), NULL); + lv_label_set_text_static(title, "Set current date"); + lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); + lv_obj_align(title, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 15, 15); + + lv_obj_t * icon = lv_label_create(lv_scr_act(), NULL); + lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); + + lv_label_set_text_static(icon, Symbols::clock); + lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); + lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); + + dayValue = static_cast(dateTimeController.Day()); + lblDay = lv_label_create(lv_scr_act(), NULL); + //lv_obj_set_style_local_text_font(lblDay, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); + lv_label_set_text_fmt(lblDay, "%d", dayValue); + lv_label_set_align(lblDay, LV_LABEL_ALIGN_CENTER); + lv_obj_align(lblDay, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_TEXT); + + monthValue = static_cast(dateTimeController.Month()); + lblMonth = lv_label_create(lv_scr_act(), NULL); + //lv_obj_set_style_local_text_font(lblMonth, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); + UpdateMonthLabel(); + + yearValue = static_cast(dateTimeController.Year()); + if (yearValue < 2021) + yearValue = 2021; + lblYear = lv_label_create(lv_scr_act(), NULL); + //lv_obj_set_style_local_text_font(lblYear, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); + lv_label_set_text_fmt(lblYear, "%d", yearValue); + lv_label_set_align(lblYear, LV_LABEL_ALIGN_CENTER); + lv_obj_align(lblYear, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_TEXT); + + btnDayPlus = lv_btn_create(lv_scr_act(), NULL); + btnDayPlus->user_data = this; + lv_obj_set_size(btnDayPlus, 50, 40); + lv_obj_align(btnDayPlus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_PLUS); + lv_obj_set_style_local_value_str(btnDayPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); + lv_obj_set_event_cb(btnDayPlus, event_handler); + + btnDayMinus = lv_btn_create(lv_scr_act(), NULL); + btnDayMinus->user_data = this; + lv_obj_set_size(btnDayMinus, 50, 40); + lv_obj_align(btnDayMinus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_MINUS); + lv_obj_set_style_local_value_str(btnDayMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); + lv_obj_set_event_cb(btnDayMinus, event_handler); + + btnMonthPlus = lv_btn_create(lv_scr_act(), NULL); + btnMonthPlus->user_data = this; + lv_obj_set_size(btnMonthPlus, 50, 40); + lv_obj_align(btnMonthPlus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MONTH, POS_Y_PLUS); + lv_obj_set_style_local_value_str(btnMonthPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); + lv_obj_set_event_cb(btnMonthPlus, event_handler); + + btnMonthMinus = lv_btn_create(lv_scr_act(), NULL); + btnMonthMinus->user_data = this; + lv_obj_set_size(btnMonthMinus, 50, 40); + lv_obj_align(btnMonthMinus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MONTH, POS_Y_MINUS); + lv_obj_set_style_local_value_str(btnMonthMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); + lv_obj_set_event_cb(btnMonthMinus, event_handler); + + btnYearPlus = lv_btn_create(lv_scr_act(), NULL); + btnYearPlus->user_data = this; + lv_obj_set_size(btnYearPlus, 50, 40); + lv_obj_align(btnYearPlus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_PLUS); + lv_obj_set_style_local_value_str(btnYearPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); + lv_obj_set_event_cb(btnYearPlus, event_handler); + + btnYearMinus = lv_btn_create(lv_scr_act(), NULL); + btnYearMinus->user_data = this; + lv_obj_set_size(btnYearMinus, 50, 40); + lv_obj_align(btnYearMinus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_MINUS); + lv_obj_set_style_local_value_str(btnYearMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); + lv_obj_set_event_cb(btnYearMinus, event_handler); + + btnSetTime = lv_btn_create(lv_scr_act(), NULL); + btnSetTime->user_data = this; + lv_obj_set_size(btnSetTime, 70, 40); + lv_obj_align(btnSetTime, lv_scr_act(), LV_ALIGN_CENTER, 0, 90); + lv_obj_set_style_local_value_str(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Set"); + lv_obj_set_event_cb(btnSetTime, event_handler); +} + +SettingSetDate::~SettingSetDate() { + lv_obj_clean(lv_scr_act()); +} + +bool SettingSetDate::Refresh() { + return running; +} + + +void SettingSetDate::HandleButtonPress(lv_obj_t *object, lv_event_t event) { + + if(object == btnDayPlus && (event == LV_EVENT_PRESSED)) { + dayValue++; + if (dayValue > MaximumDayOfMonth()) + dayValue = 1; + lv_label_set_text_fmt(lblDay, "%d", dayValue); + lv_obj_align(lblDay, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_TEXT); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); + } + + if(object == btnDayMinus && (event == LV_EVENT_PRESSED)) { + dayValue--; + if (dayValue < 1) + dayValue = MaximumDayOfMonth(); + lv_label_set_text_fmt(lblDay, "%d", dayValue); + lv_obj_align(lblDay, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_TEXT); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); + } + + if(object == btnMonthPlus && (event == LV_EVENT_PRESSED)) { + monthValue++; + if (monthValue > 12) + monthValue = 1; + UpdateMonthLabel(); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); + CheckDay(); + } + + if(object == btnMonthMinus && (event == LV_EVENT_PRESSED)) { + monthValue--; + if (monthValue < 1) + monthValue = 12; + UpdateMonthLabel(); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); + CheckDay(); + } + + if(object == btnYearPlus && (event == LV_EVENT_PRESSED)) { + yearValue++; + lv_label_set_text_fmt(lblYear, "%d", yearValue); + lv_obj_align(lblYear, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_TEXT); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); + CheckDay(); + } + + if(object == btnYearMinus && (event == LV_EVENT_PRESSED)) { + yearValue--; + lv_label_set_text_fmt(lblYear, "%d", yearValue); + lv_obj_align(lblYear, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_TEXT); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); + CheckDay(); + } + + if(object == btnSetTime && (event == LV_EVENT_PRESSED)) { + NRF_LOG_INFO("Setting date (manually) to %04d-%02d-%02d", yearValue, monthValue, dayValue); + dateTimeController.SetTime(static_cast(yearValue), + static_cast(monthValue), + static_cast(dayValue), + 0, + dateTimeController.Hours(), + dateTimeController.Minutes(), + dateTimeController.Seconds(), + nrf_rtc_counter_get(portNRF_RTC_REG)); + lv_btn_set_state(btnSetTime, LV_BTN_STATE_DISABLED); + } +} + +int SettingSetDate::MaximumDayOfMonth() const { + switch (monthValue) { + case 2: + if ((((yearValue % 4) == 0) && ((yearValue % 100) != 0)) || ((yearValue % 400) == 0)) + return 29; + return 28; + case 4: + case 6: + case 9: + case 11: + return 30; + default: + return 31; + } +} + +void SettingSetDate::CheckDay() { + int maxDay = MaximumDayOfMonth(); + if (dayValue > maxDay) { + dayValue = maxDay; + lv_label_set_text_fmt(lblDay, "%d", dayValue); + lv_obj_align(lblDay, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_TEXT); + } +} + +void SettingSetDate::UpdateMonthLabel() { + switch (monthValue) { + case 1: + lv_label_set_text_static(lblMonth, "Jan"); + break; + case 2: + lv_label_set_text_static(lblMonth, "Feb"); + break; + case 3: + lv_label_set_text_static(lblMonth, "Mar"); + break; + case 4: + lv_label_set_text_static(lblMonth, "Apr"); + break; + case 5: + lv_label_set_text_static(lblMonth, "May"); + break; + case 6: + lv_label_set_text_static(lblMonth, "Jun"); + break; + case 7: + lv_label_set_text_static(lblMonth, "Jul"); + break; + case 8: + lv_label_set_text_static(lblMonth, "Aug"); + break; + case 9: + lv_label_set_text_static(lblMonth, "Sep"); + break; + case 10: + lv_label_set_text_static(lblMonth, "Oct"); + break; + case 11: + lv_label_set_text_static(lblMonth, "Nov"); + break; + case 12: + lv_label_set_text_static(lblMonth, "Dec"); + break; + default: + lv_label_set_text_static(lblMonth, "---"); + break; + } + lv_label_set_align(lblMonth, LV_LABEL_ALIGN_CENTER); + lv_obj_align(lblMonth, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MONTH, POS_Y_TEXT); +} + diff --git a/src/displayapp/screens/settings/SettingSetDate.h b/src/displayapp/screens/settings/SettingSetDate.h new file mode 100644 index 00000000..0944e986 --- /dev/null +++ b/src/displayapp/screens/settings/SettingSetDate.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include "components/datetime/DateTimeController.h" +#include "displayapp/screens/Screen.h" + +namespace Pinetime { + + namespace Applications { + namespace Screens { + + class SettingSetDate : public Screen{ + public: + SettingSetDate(DisplayApp* app, Pinetime::Controllers::DateTime &dateTimeController); + ~SettingSetDate() override; + + bool Refresh() override; + void HandleButtonPress(lv_obj_t *object, lv_event_t event); + + private: + + Controllers::DateTime& dateTimeController; + + int dayValue; + int monthValue; + int yearValue; + lv_obj_t * lblDay; + lv_obj_t * lblMonth; + lv_obj_t * lblYear; + lv_obj_t * btnDayPlus; + lv_obj_t * btnDayMinus; + lv_obj_t * btnMonthPlus; + lv_obj_t * btnMonthMinus; + lv_obj_t * btnYearPlus; + lv_obj_t * btnYearMinus; + lv_obj_t * btnSetTime; + + int MaximumDayOfMonth() const; + void CheckDay(); + void UpdateMonthLabel(); + }; + } + } +} From 07b3a507b4c685d54d21eb858f84aac23fa8ac1a Mon Sep 17 00:00:00 2001 From: timaios Date: Fri, 9 Jul 2021 14:14:17 +0200 Subject: [PATCH 03/50] Include new screens in CMakeLists.txt --- src/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index aca86543..8c6f964e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -420,6 +420,8 @@ list(APPEND SOURCE_FILES displayapp/screens/settings/SettingWakeUp.cpp displayapp/screens/settings/SettingDisplay.cpp displayapp/screens/settings/SettingSteps.cpp + displayapp/screens/settings/SettingSetDate.cpp + displayapp/screens/settings/SettingSetTime.cpp ## Watch faces displayapp/icons/bg_clock.c From 6b3be0f5a1c2793c24d00fc1c4473ca411b3f2e4 Mon Sep 17 00:00:00 2001 From: timaios Date: Fri, 9 Jul 2021 14:15:50 +0200 Subject: [PATCH 04/50] Added new screens to the list of applications --- src/displayapp/Apps.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index 684e3a46..c65a1d7b 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -30,7 +30,9 @@ namespace Pinetime { SettingTimeFormat, SettingDisplay, SettingWakeUp, - SettingSteps + SettingSteps, + SettingSetDate, + SettingSetTime }; } } From f3f5eb5739e1294e2953394a8744efd64ee58a28 Mon Sep 17 00:00:00 2001 From: timaios Date: Fri, 9 Jul 2021 14:19:38 +0200 Subject: [PATCH 05/50] Added new screens to DisplayApp.cpp --- src/displayapp/DisplayApp.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 04ebd2d3..5b78899b 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -42,6 +42,8 @@ #include "displayapp/screens/settings/SettingWakeUp.h" #include "displayapp/screens/settings/SettingDisplay.h" #include "displayapp/screens/settings/SettingSteps.h" +#include "displayapp/screens/settings/SettingSetDate.h" +#include "displayapp/screens/settings/SettingSetTime.h" using namespace Pinetime::Applications; using namespace Pinetime::Applications::Display; @@ -323,6 +325,14 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) currentScreen = std::make_unique(this, settingsController); ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); break; + case Apps::SettingSetDate: + currentScreen = std::make_unique(this, dateTimeController); + ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); + break; + case Apps::SettingSetTime: + currentScreen = std::make_unique(this, dateTimeController); + ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); + break; case Apps::BatteryInfo: currentScreen = std::make_unique(this, batteryController); ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); From 5ae4192d8d729c36b1a6713165913c7c40a23703 Mon Sep 17 00:00:00 2001 From: timaios Date: Fri, 9 Jul 2021 14:22:45 +0200 Subject: [PATCH 06/50] Added new menu entries to Settings page --- src/displayapp/screens/settings/Settings.cpp | 17 +++++++++++++++-- src/displayapp/screens/settings/Settings.h | 3 ++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/displayapp/screens/settings/Settings.cpp b/src/displayapp/screens/settings/Settings.cpp index e63a3584..be8fb4bb 100644 --- a/src/displayapp/screens/settings/Settings.cpp +++ b/src/displayapp/screens/settings/Settings.cpp @@ -18,6 +18,9 @@ Settings::Settings(Pinetime::Applications::DisplayApp* app, Pinetime::Controller }, [this]() -> std::unique_ptr { return CreateScreen2(); + }, + [this]() -> std::unique_ptr { + return CreateScreen3(); }}, Screens::ScreenListModes::UpDown} { } @@ -46,7 +49,7 @@ std::unique_ptr Settings::CreateScreen1() { {Symbols::clock, "Watch face", Apps::SettingWatchFace}, }}; - return std::make_unique(0, 2, app, settingsController, applications); + return std::make_unique(0, 3, app, settingsController, applications); } std::unique_ptr Settings::CreateScreen2() { @@ -58,5 +61,15 @@ std::unique_ptr Settings::CreateScreen2() { {Symbols::list, "About", Apps::SysInfo}, }}; - return std::make_unique(1, 2, app, settingsController, applications); + return std::make_unique(1, 3, app, settingsController, applications); +} + +std::unique_ptr Settings::CreateScreen3() { + + std::array applications {{ + {Symbols::clock, "Set date", Apps::SettingSetDate}, + {Symbols::clock, "Set time", Apps::SettingSetTime}, + }}; + + return std::make_unique(2, 3, app, settingsController, applications); } diff --git a/src/displayapp/screens/settings/Settings.h b/src/displayapp/screens/settings/Settings.h index 711a6be6..12dd0514 100644 --- a/src/displayapp/screens/settings/Settings.h +++ b/src/displayapp/screens/settings/Settings.h @@ -21,10 +21,11 @@ namespace Pinetime { private: Controllers::Settings& settingsController; - ScreenList<2> screens; + ScreenList<3> screens; std::unique_ptr CreateScreen1(); std::unique_ptr CreateScreen2(); + std::unique_ptr CreateScreen3(); }; } } From f78c9bfcab798b08491b15fe02d65211b824cfc8 Mon Sep 17 00:00:00 2001 From: Tim Taenny Date: Fri, 9 Jul 2021 16:57:59 +0200 Subject: [PATCH 07/50] Code optimizations in SettingSetDate --- .../screens/settings/SettingSetDate.cpp | 40 ++++++------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/src/displayapp/screens/settings/SettingSetDate.cpp b/src/displayapp/screens/settings/SettingSetDate.cpp index 5c1aec54..7fe0022e 100644 --- a/src/displayapp/screens/settings/SettingSetDate.cpp +++ b/src/displayapp/screens/settings/SettingSetDate.cpp @@ -26,19 +26,6 @@ SettingSetDate::SettingSetDate( Screen(app), dateTimeController {dateTimeController} { - - 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_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); - lv_obj_set_pos(container1, 30, 60); - lv_obj_set_width(container1, LV_HOR_RES - 50); - lv_obj_set_height(container1, LV_VER_RES - 60); - lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT); - lv_obj_t * title = lv_label_create(lv_scr_act(), NULL); lv_label_set_text_static(title, "Set current date"); lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); @@ -116,8 +103,8 @@ SettingSetDate::SettingSetDate( btnSetTime = lv_btn_create(lv_scr_act(), NULL); btnSetTime->user_data = this; - lv_obj_set_size(btnSetTime, 70, 40); - lv_obj_align(btnSetTime, lv_scr_act(), LV_ALIGN_CENTER, 0, 90); + lv_obj_set_size(btnSetTime, 120, 48); + lv_obj_align(btnSetTime, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); lv_obj_set_style_local_value_str(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Set"); lv_obj_set_event_cb(btnSetTime, event_handler); } @@ -133,7 +120,10 @@ bool SettingSetDate::Refresh() { void SettingSetDate::HandleButtonPress(lv_obj_t *object, lv_event_t event) { - if(object == btnDayPlus && (event == LV_EVENT_PRESSED)) { + if (event != LV_EVENT_CLICKED) + return; + + if (object == btnDayPlus) { dayValue++; if (dayValue > MaximumDayOfMonth()) dayValue = 1; @@ -141,8 +131,7 @@ void SettingSetDate::HandleButtonPress(lv_obj_t *object, lv_event_t event) { lv_obj_align(lblDay, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } - - if(object == btnDayMinus && (event == LV_EVENT_PRESSED)) { + else if (object == btnDayMinus) { dayValue--; if (dayValue < 1) dayValue = MaximumDayOfMonth(); @@ -150,8 +139,7 @@ void SettingSetDate::HandleButtonPress(lv_obj_t *object, lv_event_t event) { lv_obj_align(lblDay, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } - - if(object == btnMonthPlus && (event == LV_EVENT_PRESSED)) { + else if (object == btnMonthPlus) { monthValue++; if (monthValue > 12) monthValue = 1; @@ -159,8 +147,7 @@ void SettingSetDate::HandleButtonPress(lv_obj_t *object, lv_event_t event) { lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); CheckDay(); } - - if(object == btnMonthMinus && (event == LV_EVENT_PRESSED)) { + else if (object == btnMonthMinus) { monthValue--; if (monthValue < 1) monthValue = 12; @@ -168,24 +155,21 @@ void SettingSetDate::HandleButtonPress(lv_obj_t *object, lv_event_t event) { lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); CheckDay(); } - - if(object == btnYearPlus && (event == LV_EVENT_PRESSED)) { + else if (object == btnYearPlus) { yearValue++; lv_label_set_text_fmt(lblYear, "%d", yearValue); lv_obj_align(lblYear, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); CheckDay(); } - - if(object == btnYearMinus && (event == LV_EVENT_PRESSED)) { + else if (object == btnYearMinus) { yearValue--; lv_label_set_text_fmt(lblYear, "%d", yearValue); lv_obj_align(lblYear, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); CheckDay(); } - - if(object == btnSetTime && (event == LV_EVENT_PRESSED)) { + else if (object == btnSetTime) { NRF_LOG_INFO("Setting date (manually) to %04d-%02d-%02d", yearValue, monthValue, dayValue); dateTimeController.SetTime(static_cast(yearValue), static_cast(monthValue), From 06dfe1425173ffae81294cdce0fd271f1881f7ef Mon Sep 17 00:00:00 2001 From: Tim Taenny Date: Fri, 9 Jul 2021 17:13:29 +0200 Subject: [PATCH 08/50] Code optimizations in SettingSetTime --- .../screens/settings/SettingSetTime.cpp | 34 ++++++------------- 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/src/displayapp/screens/settings/SettingSetTime.cpp b/src/displayapp/screens/settings/SettingSetTime.cpp index 22d1c011..e8bc81ed 100644 --- a/src/displayapp/screens/settings/SettingSetTime.cpp +++ b/src/displayapp/screens/settings/SettingSetTime.cpp @@ -19,19 +19,6 @@ SettingSetTime::SettingSetTime( Screen(app), dateTimeController {dateTimeController} { - - 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_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); - lv_obj_set_pos(container1, 30, 60); - lv_obj_set_width(container1, LV_HOR_RES - 50); - lv_obj_set_height(container1, LV_VER_RES - 60); - lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT); - lv_obj_t * title = lv_label_create(lv_scr_act(), NULL); lv_label_set_text_static(title, "Set current time"); lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); @@ -106,8 +93,8 @@ SettingSetTime::SettingSetTime( btnSetTime = lv_btn_create(lv_scr_act(), NULL); btnSetTime->user_data = this; - lv_obj_set_size(btnSetTime, 70, 40); - lv_obj_align(btnSetTime, lv_scr_act(), LV_ALIGN_CENTER, 0, 90); + lv_obj_set_size(btnSetTime, 120, 48); + lv_obj_align(btnSetTime, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); lv_obj_set_style_local_value_str(btnSetTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Set"); lv_obj_set_event_cb(btnSetTime, event_handler); } @@ -123,7 +110,10 @@ bool SettingSetTime::Refresh() { void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { - if(object == btnHoursPlus && (event == LV_EVENT_PRESSED)) { + if (event != LV_EVENT_CLICKED) + return; + + if (object == btnHoursPlus) { hoursValue++; if (hoursValue > 23) hoursValue = 0; @@ -131,8 +121,7 @@ void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, -72, -6); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } - - if(object == btnHoursMinus && (event == LV_EVENT_PRESSED)) { + else if (object == btnHoursMinus) { hoursValue--; if (hoursValue < 0) hoursValue = 23; @@ -140,8 +129,7 @@ void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, -72, -6); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } - - if(object == btnMinutesPlus && (event == LV_EVENT_PRESSED)) { + else if (object == btnMinutesPlus) { minutesValue++; if (minutesValue > 59) minutesValue = 0; @@ -149,8 +137,7 @@ void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, 0, -6); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } - - if(object == btnMinutesMinus && (event == LV_EVENT_PRESSED)) { + else if (object == btnMinutesMinus) { minutesValue--; if (minutesValue < 0) minutesValue = 59; @@ -158,8 +145,7 @@ void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, 0, -6); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } - - if(object == btnSetTime && (event == LV_EVENT_PRESSED)) { + else if (object == btnSetTime) { NRF_LOG_INFO("Setting time (manually) to %02d:%02d:00", hoursValue, minutesValue); dateTimeController.SetTime(dateTimeController.Year(), static_cast(dateTimeController.Month()), From 899bee2cf57b658186806dfe0a834efb921b7fc5 Mon Sep 17 00:00:00 2001 From: Tim Taenny Date: Fri, 9 Jul 2021 17:32:48 +0200 Subject: [PATCH 09/50] Exposed Month and DayOfWeek texts in DateTimeController Added static methods to return the text of a given month or dayOfWeek. --- .../datetime/DateTimeController.cpp | 44 +++++++++++++++---- src/components/datetime/DateTimeController.h | 10 ++++- 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/src/components/datetime/DateTimeController.cpp b/src/components/datetime/DateTimeController.cpp index 28a70abc..0682f8f3 100644 --- a/src/components/datetime/DateTimeController.cpp +++ b/src/components/datetime/DateTimeController.cpp @@ -75,31 +75,59 @@ void DateTime::UpdateTime(uint32_t systickCounter) { } const char* DateTime::MonthShortToString() { - return DateTime::MonthsString[(uint8_t) month]; + return DateTime::MonthsString[static_cast(month)]; } const char* DateTime::MonthShortToStringLow() { - return DateTime::MonthsStringLow[(uint8_t) month]; + return DateTime::MonthsStringLow[static_cast(month)]; } const char* DateTime::MonthsToStringLow() { - return DateTime::MonthsLow[(uint8_t) month]; + return DateTime::MonthsLow[static_cast(month)]; } const char* DateTime::DayOfWeekToString() { - return DateTime::DaysString[(uint8_t) dayOfWeek]; + return DateTime::DaysString[static_cast(dayOfWeek)]; } const char* DateTime::DayOfWeekShortToString() { - return DateTime::DaysStringShort[(uint8_t) dayOfWeek]; + return DateTime::DaysStringShort[static_cast(dayOfWeek)]; } const char* DateTime::DayOfWeekToStringLow() { - return DateTime::DaysStringLow[(uint8_t) dayOfWeek]; + return DateTime::DaysStringLow[static_cast(dayOfWeek)]; } const char* DateTime::DayOfWeekShortToStringLow() { - return DateTime::DaysStringShortLow[(uint8_t) dayOfWeek]; + return DateTime::DaysStringShortLow[static_cast(dayOfWeek)]; +} + +const char* DateTime::MonthShortToString(Months month) { + return DateTime::MonthsString[static_cast(month)]; +} + +const char* DateTime::MonthShortToStringLow(Months month) { + return DateTime::MonthsStringLow[static_cast(month)]; +} + +const char* DateTime::MonthsToStringLow(Months month) { + return DateTime::MonthsLow[static_cast(month)]; +} + +const char* DateTime::DayOfWeekToString(Days dayOfWeek) { + return DateTime::DaysString[static_cast(dayOfWeek)]; +} + +const char* DateTime::DayOfWeekShortToString(Days dayOfWeek) { + return DateTime::DaysStringShort[static_cast(dayOfWeek)]; +} + +const char* DateTime::DayOfWeekToStringLow(Days dayOfWeek) { + return DateTime::DaysStringLow[static_cast(dayOfWeek)]; +} + +const char* DateTime::DayOfWeekShortToStringLow(Days dayOfWeek) { + return DateTime::DaysStringShortLow[static_cast(dayOfWeek)]; } void DateTime::Register(Pinetime::System::SystemTask* systemTask) { @@ -119,4 +147,4 @@ char const* DateTime::MonthsString[] = {"--", "JAN", "FEB", "MAR", "APR", "MAY", char const* DateTime::MonthsStringLow[] = {"--", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; char const* DateTime::MonthsLow[] = { - "--", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; \ No newline at end of file + "--", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; diff --git a/src/components/datetime/DateTimeController.h b/src/components/datetime/DateTimeController.h index 265d6e9d..66ccaa94 100644 --- a/src/components/datetime/DateTimeController.h +++ b/src/components/datetime/DateTimeController.h @@ -66,6 +66,14 @@ namespace Pinetime { const char* DayOfWeekToStringLow(); const char* DayOfWeekShortToStringLow(); + static const char* MonthShortToString(Months month); + static const char* MonthShortToStringLow(Months month); + static const char* MonthsToStringLow(Months month); + static const char* DayOfWeekToString(Days dayOfWeek); + static const char* DayOfWeekShortToString(Days dayOfWeek); + static const char* DayOfWeekToStringLow(Days dayOfWeek); + static const char* DayOfWeekShortToStringLow(Days dayOfWeek); + std::chrono::time_point CurrentDateTime() const { return currentDateTime; } @@ -100,4 +108,4 @@ namespace Pinetime { static char const* MonthsLow[]; }; } -} \ No newline at end of file +} From 3e5ad49e3a27e0238dc8cd473f8743bf2e8d73b0 Mon Sep 17 00:00:00 2001 From: Tim Taenny Date: Fri, 9 Jul 2021 17:46:17 +0200 Subject: [PATCH 10/50] Code optimizations in SettingSetDate Using static method of DateTimeController for retrieving month texts instead of implementing it in SettingSetDate again. --- .../screens/settings/SettingSetDate.cpp | 43 +------------------ 1 file changed, 2 insertions(+), 41 deletions(-) diff --git a/src/displayapp/screens/settings/SettingSetDate.cpp b/src/displayapp/screens/settings/SettingSetDate.cpp index 7fe0022e..fe71cd85 100644 --- a/src/displayapp/screens/settings/SettingSetDate.cpp +++ b/src/displayapp/screens/settings/SettingSetDate.cpp @@ -209,47 +209,8 @@ void SettingSetDate::CheckDay() { } void SettingSetDate::UpdateMonthLabel() { - switch (monthValue) { - case 1: - lv_label_set_text_static(lblMonth, "Jan"); - break; - case 2: - lv_label_set_text_static(lblMonth, "Feb"); - break; - case 3: - lv_label_set_text_static(lblMonth, "Mar"); - break; - case 4: - lv_label_set_text_static(lblMonth, "Apr"); - break; - case 5: - lv_label_set_text_static(lblMonth, "May"); - break; - case 6: - lv_label_set_text_static(lblMonth, "Jun"); - break; - case 7: - lv_label_set_text_static(lblMonth, "Jul"); - break; - case 8: - lv_label_set_text_static(lblMonth, "Aug"); - break; - case 9: - lv_label_set_text_static(lblMonth, "Sep"); - break; - case 10: - lv_label_set_text_static(lblMonth, "Oct"); - break; - case 11: - lv_label_set_text_static(lblMonth, "Nov"); - break; - case 12: - lv_label_set_text_static(lblMonth, "Dec"); - break; - default: - lv_label_set_text_static(lblMonth, "---"); - break; - } + lv_label_set_text_static(lblMonth, + Pinetime::Controllers::DateTime::MonthShortToStringLow(static_cast(monthValue))); lv_label_set_align(lblMonth, LV_LABEL_ALIGN_CENTER); lv_obj_align(lblMonth, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MONTH, POS_Y_TEXT); } From 0842a1333966863b0a043b45c629b1f7b1d6c511 Mon Sep 17 00:00:00 2001 From: Tim Taenny Date: Fri, 9 Jul 2021 17:49:35 +0200 Subject: [PATCH 11/50] Modified Settings menu as per suggestion Moved "Set date" and "Set time" to the second page of the Settings menu. --- src/displayapp/screens/settings/Settings.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/displayapp/screens/settings/Settings.cpp b/src/displayapp/screens/settings/Settings.cpp index be8fb4bb..f4240ae1 100644 --- a/src/displayapp/screens/settings/Settings.cpp +++ b/src/displayapp/screens/settings/Settings.cpp @@ -56,9 +56,9 @@ std::unique_ptr Settings::CreateScreen2() { std::array applications {{ {Symbols::shoe, "Steps", Apps::SettingSteps}, + {Symbols::clock, "Set date", Apps::SettingSetDate}, + {Symbols::clock, "Set time", Apps::SettingSetTime}, {Symbols::batteryHalf, "Battery", Apps::BatteryInfo}, - {Symbols::check, "Firmware", Apps::FirmwareValidation}, - {Symbols::list, "About", Apps::SysInfo}, }}; return std::make_unique(1, 3, app, settingsController, applications); @@ -67,8 +67,8 @@ std::unique_ptr Settings::CreateScreen2() { std::unique_ptr Settings::CreateScreen3() { std::array applications {{ - {Symbols::clock, "Set date", Apps::SettingSetDate}, - {Symbols::clock, "Set time", Apps::SettingSetTime}, + {Symbols::check, "Firmware", Apps::FirmwareValidation}, + {Symbols::list, "About", Apps::SysInfo}, }}; return std::make_unique(2, 3, app, settingsController, applications); From da36d4a5a1322dd7699dbe445bb25962b0819f0a Mon Sep 17 00:00:00 2001 From: Tim Taenny Date: Fri, 9 Jul 2021 20:17:47 +0200 Subject: [PATCH 12/50] Code optimizations in SettingSetTime The positions of the labels are controlled by #define's, just like in SettingSetDate. --- .../screens/settings/SettingSetTime.cpp | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/displayapp/screens/settings/SettingSetTime.cpp b/src/displayapp/screens/settings/SettingSetTime.cpp index e8bc81ed..122a537a 100644 --- a/src/displayapp/screens/settings/SettingSetTime.cpp +++ b/src/displayapp/screens/settings/SettingSetTime.cpp @@ -5,6 +5,14 @@ #include "displayapp/DisplayApp.h" #include "displayapp/screens/Symbols.h" +#define POS_X_HOURS -72 +#define POS_X_MINUTES 0 +#define POS_X_SECONDS 72 +#define POS_Y_PLUS -50 +#define POS_Y_TEXT -6 +#define POS_Y_MINUS 40 +#define OFS_Y_COLON -2 + using namespace Pinetime::Applications::Screens; namespace { @@ -36,32 +44,32 @@ SettingSetTime::SettingSetTime( lv_obj_set_style_local_text_font(lblHours, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_fmt(lblHours, "%02d", hoursValue); lv_label_set_align(lblHours, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, -72, -6); + lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, POS_X_HOURS, POS_Y_TEXT); lv_obj_t * lblColon1 = lv_label_create(lv_scr_act(), NULL); lv_obj_set_style_local_text_font(lblColon1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_static(lblColon1, ":"); lv_label_set_align(lblColon1, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblColon1, lv_scr_act(), LV_ALIGN_CENTER, -36, -8); + lv_obj_align(lblColon1, lv_scr_act(), LV_ALIGN_CENTER, (POS_X_HOURS + POS_X_MINUTES) / 2, POS_Y_TEXT + OFS_Y_COLON); minutesValue = static_cast(dateTimeController.Minutes()); lblMinutes = lv_label_create(lv_scr_act(), NULL); lv_obj_set_style_local_text_font(lblMinutes, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); lv_label_set_align(lblMinutes, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, 0, -6); + lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MINUTES, POS_Y_TEXT); lv_obj_t * lblColon2 = lv_label_create(lv_scr_act(), NULL); lv_obj_set_style_local_text_font(lblColon2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_static(lblColon2, ":"); lv_label_set_align(lblColon2, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblColon2, lv_scr_act(), LV_ALIGN_CENTER, 36, -8); + lv_obj_align(lblColon2, lv_scr_act(), LV_ALIGN_CENTER, (POS_X_MINUTES + POS_X_SECONDS) / 2, POS_Y_TEXT + OFS_Y_COLON); lv_obj_t * lblSeconds = lv_label_create(lv_scr_act(), NULL); lv_obj_set_style_local_text_font(lblSeconds, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_static(lblSeconds, "00"); lv_label_set_align(lblSeconds, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblSeconds, lv_scr_act(), LV_ALIGN_CENTER, 72, -6); + lv_obj_align(lblSeconds, lv_scr_act(), LV_ALIGN_CENTER, POS_X_SECONDS, POS_Y_TEXT); btnHoursPlus = lv_btn_create(lv_scr_act(), NULL); btnHoursPlus->user_data = this; @@ -118,7 +126,7 @@ void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { if (hoursValue > 23) hoursValue = 0; lv_label_set_text_fmt(lblHours, "%02d", hoursValue); - lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, -72, -6); + lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, POS_X_HOURS, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } else if (object == btnHoursMinus) { @@ -126,7 +134,7 @@ void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { if (hoursValue < 0) hoursValue = 23; lv_label_set_text_fmt(lblHours, "%02d", hoursValue); - lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, -72, -6); + lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, POS_X_HOURS, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } else if (object == btnMinutesPlus) { @@ -134,7 +142,7 @@ void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { if (minutesValue > 59) minutesValue = 0; lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); - lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, 0, -6); + lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MINUTES, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } else if (object == btnMinutesMinus) { @@ -142,7 +150,7 @@ void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { if (minutesValue < 0) minutesValue = 59; lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); - lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, 0, -6); + lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MINUTES, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } else if (object == btnSetTime) { From ffa51612fc6884ccfeb4f23453acc451692c18b3 Mon Sep 17 00:00:00 2001 From: Tim Taenny Date: Fri, 9 Jul 2021 20:35:48 +0200 Subject: [PATCH 13/50] Code optimizations in SettingSetDate and SettingSetTime Instead of calling lv_obj_align after each button click, the labels have their auto_realign property set. --- src/displayapp/screens/settings/SettingSetDate.cpp | 14 +++++--------- src/displayapp/screens/settings/SettingSetTime.cpp | 6 ++---- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/displayapp/screens/settings/SettingSetDate.cpp b/src/displayapp/screens/settings/SettingSetDate.cpp index fe71cd85..69766a4e 100644 --- a/src/displayapp/screens/settings/SettingSetDate.cpp +++ b/src/displayapp/screens/settings/SettingSetDate.cpp @@ -40,24 +40,26 @@ SettingSetDate::SettingSetDate( dayValue = static_cast(dateTimeController.Day()); lblDay = lv_label_create(lv_scr_act(), NULL); - //lv_obj_set_style_local_text_font(lblDay, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_fmt(lblDay, "%d", dayValue); lv_label_set_align(lblDay, LV_LABEL_ALIGN_CENTER); lv_obj_align(lblDay, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_TEXT); + lv_obj_set_auto_realign(lblDay, true); monthValue = static_cast(dateTimeController.Month()); lblMonth = lv_label_create(lv_scr_act(), NULL); - //lv_obj_set_style_local_text_font(lblMonth, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); UpdateMonthLabel(); + lv_label_set_align(lblMonth, LV_LABEL_ALIGN_CENTER); + lv_obj_align(lblMonth, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MONTH, POS_Y_TEXT); + lv_obj_set_auto_realign(lblMonth, true); yearValue = static_cast(dateTimeController.Year()); if (yearValue < 2021) yearValue = 2021; lblYear = lv_label_create(lv_scr_act(), NULL); - //lv_obj_set_style_local_text_font(lblYear, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_fmt(lblYear, "%d", yearValue); lv_label_set_align(lblYear, LV_LABEL_ALIGN_CENTER); lv_obj_align(lblYear, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_TEXT); + lv_obj_set_auto_realign(lblYear, true); btnDayPlus = lv_btn_create(lv_scr_act(), NULL); btnDayPlus->user_data = this; @@ -128,7 +130,6 @@ void SettingSetDate::HandleButtonPress(lv_obj_t *object, lv_event_t event) { if (dayValue > MaximumDayOfMonth()) dayValue = 1; lv_label_set_text_fmt(lblDay, "%d", dayValue); - lv_obj_align(lblDay, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } else if (object == btnDayMinus) { @@ -136,7 +137,6 @@ void SettingSetDate::HandleButtonPress(lv_obj_t *object, lv_event_t event) { if (dayValue < 1) dayValue = MaximumDayOfMonth(); lv_label_set_text_fmt(lblDay, "%d", dayValue); - lv_obj_align(lblDay, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } else if (object == btnMonthPlus) { @@ -158,14 +158,12 @@ void SettingSetDate::HandleButtonPress(lv_obj_t *object, lv_event_t event) { else if (object == btnYearPlus) { yearValue++; lv_label_set_text_fmt(lblYear, "%d", yearValue); - lv_obj_align(lblYear, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); CheckDay(); } else if (object == btnYearMinus) { yearValue--; lv_label_set_text_fmt(lblYear, "%d", yearValue); - lv_obj_align(lblYear, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); CheckDay(); } @@ -211,7 +209,5 @@ void SettingSetDate::CheckDay() { void SettingSetDate::UpdateMonthLabel() { lv_label_set_text_static(lblMonth, Pinetime::Controllers::DateTime::MonthShortToStringLow(static_cast(monthValue))); - lv_label_set_align(lblMonth, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lblMonth, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MONTH, POS_Y_TEXT); } diff --git a/src/displayapp/screens/settings/SettingSetTime.cpp b/src/displayapp/screens/settings/SettingSetTime.cpp index 122a537a..eae11f5e 100644 --- a/src/displayapp/screens/settings/SettingSetTime.cpp +++ b/src/displayapp/screens/settings/SettingSetTime.cpp @@ -45,6 +45,7 @@ SettingSetTime::SettingSetTime( lv_label_set_text_fmt(lblHours, "%02d", hoursValue); lv_label_set_align(lblHours, LV_LABEL_ALIGN_CENTER); lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, POS_X_HOURS, POS_Y_TEXT); + lv_obj_set_auto_realign(lblHours, true); lv_obj_t * lblColon1 = lv_label_create(lv_scr_act(), NULL); lv_obj_set_style_local_text_font(lblColon1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); @@ -58,6 +59,7 @@ SettingSetTime::SettingSetTime( lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); lv_label_set_align(lblMinutes, LV_LABEL_ALIGN_CENTER); lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MINUTES, POS_Y_TEXT); + lv_obj_set_auto_realign(lblMinutes, true); lv_obj_t * lblColon2 = lv_label_create(lv_scr_act(), NULL); lv_obj_set_style_local_text_font(lblColon2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); @@ -126,7 +128,6 @@ void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { if (hoursValue > 23) hoursValue = 0; lv_label_set_text_fmt(lblHours, "%02d", hoursValue); - lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, POS_X_HOURS, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } else if (object == btnHoursMinus) { @@ -134,7 +135,6 @@ void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { if (hoursValue < 0) hoursValue = 23; lv_label_set_text_fmt(lblHours, "%02d", hoursValue); - lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, POS_X_HOURS, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } else if (object == btnMinutesPlus) { @@ -142,7 +142,6 @@ void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { if (minutesValue > 59) minutesValue = 0; lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); - lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MINUTES, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } else if (object == btnMinutesMinus) { @@ -150,7 +149,6 @@ void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { if (minutesValue < 0) minutesValue = 59; lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); - lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MINUTES, POS_Y_TEXT); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); } else if (object == btnSetTime) { From 5bc40c9287f06d2c2bb24a5691175f1d29a17c1b Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Wed, 14 Jul 2021 17:11:16 +0300 Subject: [PATCH 14/50] Update touchpad driver --- src/displayapp/DisplayApp.cpp | 4 +-- src/displayapp/screens/SystemInfo.cpp | 12 ++++++--- src/displayapp/screens/SystemInfo.h | 6 +++-- src/drivers/Cst816s.cpp | 39 ++++++++++++++++----------- src/drivers/Cst816s.h | 36 ++++++++++++++++--------- src/systemtask/SystemTask.cpp | 2 +- 6 files changed, 63 insertions(+), 36 deletions(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 6d66afe5..7949e700 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -336,7 +336,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) break; case Apps::SysInfo: currentScreen = - std::make_unique(this, dateTimeController, batteryController, brightnessController, bleController, watchdog, motionController); + std::make_unique(this, dateTimeController, batteryController, brightnessController, bleController, watchdog, motionController, touchPanel); ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); break; case Apps::FlashLight: @@ -395,7 +395,7 @@ void DisplayApp::PushMessage(Messages msg) { TouchEvents DisplayApp::OnTouchEvent() { auto info = touchPanel.GetTouchInfo(); - if (info.isTouch) { + if (info.isValid) { switch (info.gesture) { case Pinetime::Drivers::Cst816S::Gestures::SingleTap: if (touchMode == TouchModes::Gestures) { diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index f5bf0cc9..d1df579c 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -31,7 +31,8 @@ SystemInfo::SystemInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::BrightnessController& brightnessController, Pinetime::Controllers::Ble& bleController, Pinetime::Drivers::WatchdogView& watchdog, - Pinetime::Controllers::MotionController& motionController) + Pinetime::Controllers::MotionController& motionController, + Pinetime::Drivers::Cst816S& touchPanel) : Screen(app), dateTimeController {dateTimeController}, batteryController {batteryController}, @@ -39,6 +40,7 @@ SystemInfo::SystemInfo(Pinetime::Applications::DisplayApp* app, bleController {bleController}, watchdog {watchdog}, motionController{motionController}, + touchPanel{touchPanel}, screens {app, 0, {[this]() -> std::unique_ptr { @@ -151,7 +153,8 @@ std::unique_ptr SystemInfo::CreateScreen2() { "#444444 Battery# %d%%/%03imV\n" "#444444 Backlight# %s\n" "#444444 Last reset# %s\n" - "#444444 Accel.# %s\n", + "#444444 Accel.# %s\n" + "#444444 Touch.# %x.%x.%x\n", dateTimeController.Day(), static_cast(dateTimeController.Month()), dateTimeController.Year(), @@ -166,7 +169,10 @@ std::unique_ptr SystemInfo::CreateScreen2() { batteryController.Voltage(), brightnessController.ToString(), resetReason, - ToString(motionController.DeviceType())); + ToString(motionController.DeviceType()), + touchPanel.GetChipId(), + touchPanel.GetVendorId(), + touchPanel.GetFwVersion()); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); return std::make_unique(1, 5, app, label); } diff --git a/src/displayapp/screens/SystemInfo.h b/src/displayapp/screens/SystemInfo.h index 9d471f61..88984dfe 100644 --- a/src/displayapp/screens/SystemInfo.h +++ b/src/displayapp/screens/SystemInfo.h @@ -28,7 +28,8 @@ namespace Pinetime { Pinetime::Controllers::BrightnessController& brightnessController, Pinetime::Controllers::Ble& bleController, Pinetime::Drivers::WatchdogView& watchdog, - Pinetime::Controllers::MotionController& motionController); + Pinetime::Controllers::MotionController& motionController, + Pinetime::Drivers::Cst816S& touchPanel); ~SystemInfo() override; bool Refresh() override; bool OnButtonPushed() override; @@ -43,6 +44,7 @@ namespace Pinetime { Pinetime::Controllers::Ble& bleController; Pinetime::Drivers::WatchdogView& watchdog; Pinetime::Controllers::MotionController& motionController; + Pinetime::Drivers::Cst816S& touchPanel; ScreenList<5> screens; @@ -56,4 +58,4 @@ namespace Pinetime { }; } } -} \ No newline at end of file +} diff --git a/src/drivers/Cst816s.cpp b/src/drivers/Cst816s.cpp index fd9792b3..2a6809b1 100644 --- a/src/drivers/Cst816s.cpp +++ b/src/drivers/Cst816s.cpp @@ -40,38 +40,45 @@ void Cst816S::Init() { */ static constexpr uint8_t motionMask = 0b00000101; twiMaster.Write(twiAddress, 0xEC, &motionMask, 1); + + // There's mixed information about which register contains which information + if (twiMaster.Read(twiAddress, 0xA7, &chipId, 1) == TwiMaster::ErrorCodes::TransactionFailed) { + chipId = 0xFF; + } + if (twiMaster.Read(twiAddress, 0xA8, &vendorId, 1) == TwiMaster::ErrorCodes::TransactionFailed) { + vendorId = 0xFF; + } + if (twiMaster.Read(twiAddress, 0xA9, &fwVersion, 1) == TwiMaster::ErrorCodes::TransactionFailed) { + fwVersion = 0xFF; + } } Cst816S::TouchInfos Cst816S::GetTouchInfo() { Cst816S::TouchInfos info; auto ret = twiMaster.Read(twiAddress, 0, touchData, sizeof(touchData)); - if (ret != TwiMaster::ErrorCodes::NoError) - return {}; - - auto nbTouchPoints = touchData[2] & 0x0f; - - uint8_t i = 0; - - uint8_t pointId = (touchData[touchIdIndex + (touchStep * i)]) >> 4; - if (nbTouchPoints == 0 && pointId == lastTouchId) + if (ret != TwiMaster::ErrorCodes::NoError) { + info.isValid = false; return info; + } - info.isTouch = true; + // This can only be 0 or 1 + auto nbTouchPoints = touchData[touchPointNumIndex] & 0x0f; - auto xHigh = touchData[touchXHighIndex + (touchStep * i)] & 0x0f; - auto xLow = touchData[touchXLowIndex + (touchStep * i)]; + auto xHigh = touchData[touchXHighIndex] & 0x0f; + auto xLow = touchData[touchXLowIndex]; uint16_t x = (xHigh << 8) | xLow; - auto yHigh = touchData[touchYHighIndex + (touchStep * i)] & 0x0f; - auto yLow = touchData[touchYLowIndex + (touchStep * i)]; + auto yHigh = touchData[touchYHighIndex] & 0x0f; + auto yLow = touchData[touchYLowIndex]; uint16_t y = (yHigh << 8) | yLow; - auto action = touchData[touchEventIndex + (touchStep * i)] >> 6; /* 0 = Down, 1 = Up, 2 = contact*/ + auto action = touchData[touchEventIndex] >> 6; /* 0 = Down, 1 = Up, 2 = contact*/ info.x = x; info.y = y; info.action = action; + info.touching = (nbTouchPoints > 0); info.gesture = static_cast(touchData[gestureIndex]); return info; @@ -90,4 +97,4 @@ void Cst816S::Sleep() { void Cst816S::Wakeup() { Init(); NRF_LOG_INFO("[TOUCHPANEL] Wakeup"); -} \ No newline at end of file +} diff --git a/src/drivers/Cst816s.h b/src/drivers/Cst816s.h index 14c296ea..394cc40f 100644 --- a/src/drivers/Cst816s.h +++ b/src/drivers/Cst816s.h @@ -20,11 +20,9 @@ namespace Pinetime { uint16_t x = 0; uint16_t y = 0; uint8_t action = 0; - uint8_t finger = 0; - uint8_t pressure = 0; - uint8_t area = 0; + bool touching = false; Gestures gesture = Gestures::None; - bool isTouch = false; + bool isValid = true; }; Cst816S(TwiMaster& twiMaster, uint8_t twiAddress); @@ -38,26 +36,40 @@ namespace Pinetime { void Sleep(); void Wakeup(); + uint8_t GetChipId() const { + return chipId; + } + uint8_t GetVendorId() const { + return vendorId; + } + uint8_t GetFwVersion() const { + return fwVersion; + } private: static constexpr uint8_t pinIrq = 28; static constexpr uint8_t pinReset = 10; - static constexpr uint8_t lastTouchId = 0x0f; + + // Unused/Unavailable commented out + static constexpr uint8_t gestureIndex = 1; static constexpr uint8_t touchPointNumIndex = 2; - static constexpr uint8_t touchMiscIndex = 8; - static constexpr uint8_t touchXYIndex = 7; static constexpr uint8_t touchEventIndex = 3; static constexpr uint8_t touchXHighIndex = 3; static constexpr uint8_t touchXLowIndex = 4; + //static constexpr uint8_t touchIdIndex = 5; static constexpr uint8_t touchYHighIndex = 5; static constexpr uint8_t touchYLowIndex = 6; - static constexpr uint8_t touchIdIndex = 5; - static constexpr uint8_t touchStep = 6; - static constexpr uint8_t gestureIndex = 1; + //static constexpr uint8_t touchStep = 6; + //static constexpr uint8_t touchXYIndex = 7; + //static constexpr uint8_t touchMiscIndex = 8; - uint8_t touchData[10]; + uint8_t touchData[7]; TwiMaster& twiMaster; uint8_t twiAddress; + + uint8_t chipId; + uint8_t vendorId; + uint8_t fwVersion; }; } -} \ No newline at end of file +} diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index eb29638a..6a851e75 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -231,7 +231,7 @@ void SystemTask::Work() { twiMaster.Wakeup(); auto touchInfo = touchPanel.GetTouchInfo(); twiMaster.Sleep(); - if (touchInfo.isTouch and ((touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap and + if (touchInfo.isValid and ((touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap and settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::DoubleTap) or (touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::SingleTap and settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::SingleTap))) { From 93893511f1e0bb224f5002dd9738738f92e25eb6 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Wed, 21 Jul 2021 14:41:29 +0300 Subject: [PATCH 15/50] Fit more tasks in SystemInfo --- src/displayapp/screens/SystemInfo.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index f5bf0cc9..69a0d1a0 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -210,11 +210,14 @@ bool SystemInfo::sortById(const TaskStatus_t& lhs, const TaskStatus_t& rhs) { } std::unique_ptr SystemInfo::CreateScreen4() { - TaskStatus_t tasksStatus[7]; + static constexpr uint8_t maxTaskCount = 9; + TaskStatus_t tasksStatus[maxTaskCount]; + lv_obj_t* infoTask = lv_table_create(lv_scr_act(), NULL); lv_table_set_col_cnt(infoTask, 3); - lv_table_set_row_cnt(infoTask, 8); - lv_obj_set_pos(infoTask, 10, 10); + lv_table_set_row_cnt(infoTask, maxTaskCount + 1); + lv_obj_set_style_local_pad_all(infoTask, LV_TABLE_PART_CELL1, LV_STATE_DEFAULT, 0); + lv_obj_set_style_local_border_color(infoTask, LV_TABLE_PART_CELL1, LV_STATE_DEFAULT, LV_COLOR_GRAY); lv_table_set_cell_value(infoTask, 0, 0, "#"); lv_table_set_col_width(infoTask, 0, 50); @@ -223,8 +226,9 @@ std::unique_ptr SystemInfo::CreateScreen4() { lv_table_set_cell_value(infoTask, 0, 2, "Free"); lv_table_set_col_width(infoTask, 2, 90); - auto nb = uxTaskGetSystemState(tasksStatus, 7, nullptr); + auto nb = uxTaskGetSystemState(tasksStatus, maxTaskCount, nullptr); std::sort(tasksStatus, tasksStatus + nb, sortById); + for (uint8_t i = 0; i < nb; i++) { lv_table_set_cell_value(infoTask, i + 1, 0, std::to_string(tasksStatus[i].xTaskNumber).c_str()); From 12b14176ec965f2553e4cad16e291d54704128f3 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Wed, 21 Jul 2021 14:46:27 +0300 Subject: [PATCH 16/50] Fix --- src/displayapp/screens/SystemInfo.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index 69a0d1a0..3294ebe3 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -228,8 +228,7 @@ std::unique_ptr SystemInfo::CreateScreen4() { auto nb = uxTaskGetSystemState(tasksStatus, maxTaskCount, nullptr); std::sort(tasksStatus, tasksStatus + nb, sortById); - - for (uint8_t i = 0; i < nb; i++) { + for (uint8_t i = 0; i < nb && i < maxTaskCount; i++) { lv_table_set_cell_value(infoTask, i + 1, 0, std::to_string(tasksStatus[i].xTaskNumber).c_str()); lv_table_set_cell_value(infoTask, i + 1, 1, tasksStatus[i].pcTaskName); From 54ccd2cc072d32563d01080ed21c5fd1bd7a695c Mon Sep 17 00:00:00 2001 From: Jonathan Vander Mey Date: Sat, 24 Jul 2021 11:07:06 -0400 Subject: [PATCH 17/50] Update Navigation UUID documentation Fixed mismatch between the service and characteristic IDs in the navigation service comments and documentation. They had old values not reflecting the current code and changes in doc/ble.md --- doc/NavigationService.md | 10 +++++----- src/components/ble/NavigationService.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/NavigationService.md b/doc/NavigationService.md index d0899817..fd81d0bf 100644 --- a/doc/NavigationService.md +++ b/doc/NavigationService.md @@ -9,19 +9,19 @@ manDist (string) - Manouvre Distance, the distance to the upcoming change progress (uint8) - Percent complete of total route, value 0-100 ## Service -The service UUID is c7e60001-78fc-48fe-8e23-433b3a1942d0 +The service UUID is 00010000-78fc-48fe-8e23-433b3a1942d0 ## Characteristics -## Flags (UUID c7e60002-78fc-48fe-8e23-433b3a1942d0) +## Flags (UUID 00010001-78fc-48fe-8e23-433b3a1942d0) All included icons are from pure-maps, which provides the actual routing from the client. The icon names ultimately come from the mapbox project "direction-icons", See https://github.com/rinigus/pure-maps/tree/master/qml/icons/navigation See the end of this document for the full lsit of supported icon names. -## Narrative (UUID c7e60003-78fc-48fe-8e23-433b3a1942d0) +## Narrative (UUID 00010002-78fc-48fe-8e23-433b3a1942d0) This is a client supplied string describing the upcoming instruction such as "At the roundabout take the first exit". -## Man Dist (UUID c7e60004-78fc-48fe-8e23-433b3a1942d0) +## Man Dist (UUID 00010003-78fc-48fe-8e23-433b3a1942d0) This is a short string describing the distance to the upcoming instruction such as "50 m". -## Progress (UUID c7e60001=5-78fc-48fe-8e23-433b3a1942d0) +## Progress (UUID 00010004-78fc-48fe-8e23-433b3a1942d0) The percent complete in a uint8. The watch displays this as an overall progress in a progress bar. ## Full icon list diff --git a/src/components/ble/NavigationService.h b/src/components/ble/NavigationService.h index 5aab263c..7972308c 100644 --- a/src/components/ble/NavigationService.h +++ b/src/components/ble/NavigationService.h @@ -26,7 +26,7 @@ #undef max #undef min -// c7e60000-78fc-48fe-8e23-433b3a1942d0 +// 00010000-78fc-48fe-8e23-433b3a1942d0 #define NAVIGATION_SERVICE_UUID_BASE \ { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00 } From 6b95fd841f9a4fee3f2c07b620db182c46228177 Mon Sep 17 00:00:00 2001 From: Jonathan Vander Mey Date: Sat, 24 Jul 2021 11:09:56 -0400 Subject: [PATCH 18/50] Set navigation service id is base UUID macro Avoids the need to copy the same ID into every characteristic UUID genereated from it. --- src/components/ble/NavigationService.cpp | 11 ----------- src/components/ble/NavigationService.h | 3 +-- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/components/ble/NavigationService.cpp b/src/components/ble/NavigationService.cpp index e1c20bf1..b9d51d32 100644 --- a/src/components/ble/NavigationService.cpp +++ b/src/components/ble/NavigationService.cpp @@ -26,28 +26,17 @@ int NAVCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_acce } Pinetime::Controllers::NavigationService::NavigationService(Pinetime::System::SystemTask& system) : m_system(system) { - navUuid.value[14] = navId[0]; - navUuid.value[15] = navId[1]; - navFlagCharUuid.value[12] = navFlagCharId[0]; navFlagCharUuid.value[13] = navFlagCharId[1]; - navFlagCharUuid.value[14] = navId[0]; - navFlagCharUuid.value[15] = navId[1]; navNarrativeCharUuid.value[12] = navNarrativeCharId[0]; navNarrativeCharUuid.value[13] = navNarrativeCharId[1]; - navNarrativeCharUuid.value[14] = navId[0]; - navNarrativeCharUuid.value[15] = navId[1]; navManDistCharUuid.value[12] = navManDistCharId[0]; navManDistCharUuid.value[13] = navManDistCharId[1]; - navManDistCharUuid.value[14] = navId[0]; - navManDistCharUuid.value[15] = navId[1]; navProgressCharUuid.value[12] = navProgressCharId[0]; navProgressCharUuid.value[13] = navProgressCharId[1]; - navProgressCharUuid.value[14] = navId[0]; - navProgressCharUuid.value[15] = navId[1]; characteristicDefinition[0] = { .uuid = (ble_uuid_t*) (&navFlagCharUuid), .access_cb = NAVCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; diff --git a/src/components/ble/NavigationService.h b/src/components/ble/NavigationService.h index 7972308c..caa194db 100644 --- a/src/components/ble/NavigationService.h +++ b/src/components/ble/NavigationService.h @@ -28,7 +28,7 @@ // 00010000-78fc-48fe-8e23-433b3a1942d0 #define NAVIGATION_SERVICE_UUID_BASE \ - { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00 } + { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x01, 0x00 } namespace Pinetime { namespace System { @@ -53,7 +53,6 @@ namespace Pinetime { int getProgress(); private: - static constexpr uint8_t navId[2] = {0x01, 0x00}; static constexpr uint8_t navFlagCharId[2] = {0x01, 0x00}; static constexpr uint8_t navNarrativeCharId[2] = {0x02, 0x00}; static constexpr uint8_t navManDistCharId[2] = {0x03, 0x00}; From 1bdaf581a3e58c33ceb8fd766cc5f25c978f9cb5 Mon Sep 17 00:00:00 2001 From: Jonathan Vander Mey Date: Sat, 24 Jul 2021 11:18:17 -0400 Subject: [PATCH 19/50] Update nav service UUID macro to constexpr functions --- src/components/ble/NavigationService.cpp | 32 +++++++++++++++--------- src/components/ble/NavigationService.h | 16 ------------ 2 files changed, 20 insertions(+), 28 deletions(-) diff --git a/src/components/ble/NavigationService.cpp b/src/components/ble/NavigationService.cpp index b9d51d32..0ab1fa9b 100644 --- a/src/components/ble/NavigationService.cpp +++ b/src/components/ble/NavigationService.cpp @@ -20,24 +20,32 @@ #include "systemtask/SystemTask.h" +namespace { + // 0001yyxx-78fc-48fe-8e23-433b3a1942d0 + constexpr ble_uuid128_t CharUuid(uint8_t x, uint8_t y) { + return ble_uuid128_t {.u = {.type = BLE_UUID_TYPE_128}, + .value = {0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, x, y, 0x01, 0x00}}; + } + + // 00010000-78fc-48fe-8e23-433b3a1942d0 + constexpr ble_uuid128_t BaseUuid() { + return CharUuid(0x00, 0x00); + } + + constexpr ble_uuid128_t navUuid {BaseUuid()}; + + constexpr ble_uuid128_t navFlagCharUuid {CharUuid(0x01, 0x00)}; + constexpr ble_uuid128_t navNarrativeCharUuid {CharUuid(0x02, 0x00)}; + constexpr ble_uuid128_t navManDistCharUuid {CharUuid(0x03, 0x00)}; + constexpr ble_uuid128_t navProgressCharUuid {CharUuid(0x04, 0x00)}; +} // namespace + int NAVCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) { auto navService = static_cast(arg); return navService->OnCommand(conn_handle, attr_handle, ctxt); } Pinetime::Controllers::NavigationService::NavigationService(Pinetime::System::SystemTask& system) : m_system(system) { - navFlagCharUuid.value[12] = navFlagCharId[0]; - navFlagCharUuid.value[13] = navFlagCharId[1]; - - navNarrativeCharUuid.value[12] = navNarrativeCharId[0]; - navNarrativeCharUuid.value[13] = navNarrativeCharId[1]; - - navManDistCharUuid.value[12] = navManDistCharId[0]; - navManDistCharUuid.value[13] = navManDistCharId[1]; - - navProgressCharUuid.value[12] = navProgressCharId[0]; - navProgressCharUuid.value[13] = navProgressCharId[1]; - characteristicDefinition[0] = { .uuid = (ble_uuid_t*) (&navFlagCharUuid), .access_cb = NAVCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; diff --git a/src/components/ble/NavigationService.h b/src/components/ble/NavigationService.h index caa194db..c0c77f35 100644 --- a/src/components/ble/NavigationService.h +++ b/src/components/ble/NavigationService.h @@ -26,10 +26,6 @@ #undef max #undef min -// 00010000-78fc-48fe-8e23-433b3a1942d0 -#define NAVIGATION_SERVICE_UUID_BASE \ - { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x01, 0x00 } - namespace Pinetime { namespace System { class SystemTask; @@ -53,18 +49,6 @@ namespace Pinetime { int getProgress(); private: - static constexpr uint8_t navFlagCharId[2] = {0x01, 0x00}; - static constexpr uint8_t navNarrativeCharId[2] = {0x02, 0x00}; - static constexpr uint8_t navManDistCharId[2] = {0x03, 0x00}; - static constexpr uint8_t navProgressCharId[2] = {0x04, 0x00}; - - ble_uuid128_t navUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE}; - - ble_uuid128_t navFlagCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE}; - ble_uuid128_t navNarrativeCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE}; - ble_uuid128_t navManDistCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE}; - ble_uuid128_t navProgressCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE}; - struct ble_gatt_chr_def characteristicDefinition[5]; struct ble_gatt_svc_def serviceDefinition[2]; From 487ae478adf4f4c8be0ff61f8433e7018426b661 Mon Sep 17 00:00:00 2001 From: Jonathan Vander Mey Date: Sat, 24 Jul 2021 11:40:06 -0400 Subject: [PATCH 20/50] Remove unnecessary C-style casts with BLE UUIDs Instead of casting the UUID object to the ble_uuid_t* used throughout the NimBLE API just pass the address of the ble_uuid_t member that's at the start of each of the UUID structs. --- .../ble/AlertNotificationClient.cpp | 14 ++++----- .../ble/AlertNotificationService.cpp | 11 +++---- .../ble/BatteryInformationService.cpp | 4 +-- src/components/ble/CurrentTimeClient.cpp | 4 +-- src/components/ble/CurrentTimeService.cpp | 4 +-- .../ble/DeviceInformationService.cpp | 14 ++++----- src/components/ble/DfuService.cpp | 26 ++++++++-------- src/components/ble/HeartRateService.cpp | 4 +-- src/components/ble/ImmediateAlertService.cpp | 6 ++-- src/components/ble/NavigationService.cpp | 30 ++++++++----------- 10 files changed, 54 insertions(+), 63 deletions(-) diff --git a/src/components/ble/AlertNotificationClient.cpp b/src/components/ble/AlertNotificationClient.cpp index c3d1d69a..5e5c25cf 100644 --- a/src/components/ble/AlertNotificationClient.cpp +++ b/src/components/ble/AlertNotificationClient.cpp @@ -55,7 +55,7 @@ bool AlertNotificationClient::OnDiscoveryEvent(uint16_t connectionHandle, const return true; } - if (service != nullptr && ble_uuid_cmp(((ble_uuid_t*) &ansServiceUuid), &service->uuid.u) == 0) { + if (service != nullptr && ble_uuid_cmp(&ansServiceUuid.u, &service->uuid.u) == 0) { NRF_LOG_INFO("ANS discovered : 0x%x - 0x%x", service->start_handle, service->end_handle); ansStartHandle = service->start_handle; ansEndHandle = service->end_handle; @@ -80,21 +80,21 @@ int AlertNotificationClient::OnCharacteristicsDiscoveryEvent(uint16_t connection } else onServiceDiscovered(connectionHandle); } else { - if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &supportedNewAlertCategoryUuid), &characteristic->uuid.u) == 0) { + if (characteristic != nullptr && ble_uuid_cmp(&supportedNewAlertCategoryUuid.u, &characteristic->uuid.u) == 0) { NRF_LOG_INFO("ANS Characteristic discovered : supportedNewAlertCategoryUuid"); supportedNewAlertCategoryHandle = characteristic->val_handle; - } else if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &supportedUnreadAlertCategoryUuid), &characteristic->uuid.u) == 0) { + } else if (characteristic != nullptr && ble_uuid_cmp(&supportedUnreadAlertCategoryUuid.u, &characteristic->uuid.u) == 0) { NRF_LOG_INFO("ANS Characteristic discovered : supportedUnreadAlertCategoryUuid"); supportedUnreadAlertCategoryHandle = characteristic->val_handle; - } else if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &newAlertUuid), &characteristic->uuid.u) == 0) { + } else if (characteristic != nullptr && ble_uuid_cmp(&newAlertUuid.u, &characteristic->uuid.u) == 0) { NRF_LOG_INFO("ANS Characteristic discovered : newAlertUuid"); newAlertHandle = characteristic->val_handle; newAlertDefHandle = characteristic->def_handle; isCharacteristicDiscovered = true; - } else if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &unreadAlertStatusUuid), &characteristic->uuid.u) == 0) { + } else if (characteristic != nullptr && ble_uuid_cmp(&unreadAlertStatusUuid.u, &characteristic->uuid.u) == 0) { NRF_LOG_INFO("ANS Characteristic discovered : unreadAlertStatusUuid"); unreadAlertStatusHandle = characteristic->val_handle; - } else if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &controlPointUuid), &characteristic->uuid.u) == 0) { + } else if (characteristic != nullptr && ble_uuid_cmp(&controlPointUuid.u, &characteristic->uuid.u) == 0) { NRF_LOG_INFO("ANS Characteristic discovered : controlPointUuid"); controlPointHandle = characteristic->val_handle; } else @@ -119,7 +119,7 @@ int AlertNotificationClient::OnDescriptorDiscoveryEventCallback(uint16_t connect uint16_t characteristicValueHandle, const ble_gatt_dsc* descriptor) { if (error->status == 0) { - if (characteristicValueHandle == newAlertHandle && ble_uuid_cmp(((ble_uuid_t*) &newAlertUuid), &descriptor->uuid.u)) { + if (characteristicValueHandle == newAlertHandle && ble_uuid_cmp(&newAlertUuid.u, &descriptor->uuid.u)) { if (newAlertDescriptorHandle == 0) { NRF_LOG_INFO("ANS Descriptor discovered : %d", descriptor->handle); newAlertDescriptorHandle = descriptor->handle; diff --git a/src/components/ble/AlertNotificationService.cpp b/src/components/ble/AlertNotificationService.cpp index d5fc7f65..56fc595f 100644 --- a/src/components/ble/AlertNotificationService.cpp +++ b/src/components/ble/AlertNotificationService.cpp @@ -26,11 +26,8 @@ void AlertNotificationService::Init() { } AlertNotificationService::AlertNotificationService(System::SystemTask& systemTask, NotificationManager& notificationManager) - : characteristicDefinition {{.uuid = (ble_uuid_t*) &ansCharUuid, - .access_cb = AlertNotificationCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_WRITE}, - {.uuid = (ble_uuid_t*) ¬ificationEventUuid, + : characteristicDefinition {{.uuid = &ansCharUuid.u, .access_cb = AlertNotificationCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE}, + {.uuid = ¬ificationEventUuid.u, .access_cb = AlertNotificationCallback, .arg = this, .flags = BLE_GATT_CHR_F_NOTIFY, @@ -39,7 +36,7 @@ AlertNotificationService::AlertNotificationService(System::SystemTask& systemTas serviceDefinition { {/* Device Information Service */ .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = (ble_uuid_t*) &ansUuid, + .uuid = &ansUuid.u, .characteristics = characteristicDefinition}, {0}, }, @@ -123,4 +120,4 @@ void AlertNotificationService::MuteIncomingCall() { } ble_gattc_notify_custom(connectionHandle, eventHandle, om); -} \ No newline at end of file +} diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp index 7f176904..39f18954 100644 --- a/src/components/ble/BatteryInformationService.cpp +++ b/src/components/ble/BatteryInformationService.cpp @@ -14,7 +14,7 @@ int BatteryInformationServiceCallback(uint16_t conn_handle, uint16_t attr_handle BatteryInformationService::BatteryInformationService(Controllers::Battery& batteryController) : batteryController {batteryController}, - characteristicDefinition {{.uuid = (ble_uuid_t*) &batteryLevelUuid, + characteristicDefinition {{.uuid = &batteryLevelUuid.u, .access_cb = BatteryInformationServiceCallback, .arg = this, .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, @@ -23,7 +23,7 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte serviceDefinition { {/* Device Information Service */ .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = (ble_uuid_t*) &batteryInformationServiceUuid, + .uuid = &batteryInformationServiceUuid.u, .characteristics = characteristicDefinition}, {0}, } { diff --git a/src/components/ble/CurrentTimeClient.cpp b/src/components/ble/CurrentTimeClient.cpp index c6e68312..90d1f0c7 100644 --- a/src/components/ble/CurrentTimeClient.cpp +++ b/src/components/ble/CurrentTimeClient.cpp @@ -47,7 +47,7 @@ bool CurrentTimeClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_ga return true; } - if (service != nullptr && ble_uuid_cmp(((ble_uuid_t*) &ctsServiceUuid), &service->uuid.u) == 0) { + if (service != nullptr && ble_uuid_cmp(&ctsServiceUuid.u, &service->uuid.u) == 0) { NRF_LOG_INFO("CTS discovered : 0x%x - 0x%x", service->start_handle, service->end_handle); isDiscovered = true; ctsStartHandle = service->start_handle; @@ -72,7 +72,7 @@ int CurrentTimeClient::OnCharacteristicDiscoveryEvent(uint16_t conn_handle, return 0; } - if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) ¤tTimeCharacteristicUuid), &characteristic->uuid.u) == 0) { + if (characteristic != nullptr && ble_uuid_cmp(¤tTimeCharacteristicUuid.u, &characteristic->uuid.u) == 0) { NRF_LOG_INFO("CTS Characteristic discovered : 0x%x", characteristic->val_handle); isCharacteristicDiscovered = true; currentTimeHandle = characteristic->val_handle; diff --git a/src/components/ble/CurrentTimeService.cpp b/src/components/ble/CurrentTimeService.cpp index b49be39c..eefb7ec1 100644 --- a/src/components/ble/CurrentTimeService.cpp +++ b/src/components/ble/CurrentTimeService.cpp @@ -53,7 +53,7 @@ int CurrentTimeService::OnTimeAccessed(uint16_t conn_handle, uint16_t attr_handl } CurrentTimeService::CurrentTimeService(DateTime& dateTimeController) - : characteristicDefinition {{.uuid = (ble_uuid_t*) &ctChrUuid, + : characteristicDefinition {{.uuid = &ctChrUuid.u, .access_cb = CTSCallback, .arg = this, @@ -62,7 +62,7 @@ CurrentTimeService::CurrentTimeService(DateTime& dateTimeController) serviceDefinition { {/* Device Information Service */ .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = (ble_uuid_t*) &ctsUuid, + .uuid = &ctsUuid.u, .characteristics = characteristicDefinition}, {0}, }, diff --git a/src/components/ble/DeviceInformationService.cpp b/src/components/ble/DeviceInformationService.cpp index cf482079..778d6e35 100644 --- a/src/components/ble/DeviceInformationService.cpp +++ b/src/components/ble/DeviceInformationService.cpp @@ -56,37 +56,37 @@ int DeviceInformationService::OnDeviceInfoRequested(uint16_t conn_handle, uint16 DeviceInformationService::DeviceInformationService() : characteristicDefinition {{ - .uuid = (ble_uuid_t*) &manufacturerNameUuid, + .uuid = &manufacturerNameUuid.u, .access_cb = DeviceInformationCallback, .arg = this, .flags = BLE_GATT_CHR_F_READ, }, { - .uuid = (ble_uuid_t*) &modelNumberUuid, + .uuid = &modelNumberUuid.u, .access_cb = DeviceInformationCallback, .arg = this, .flags = BLE_GATT_CHR_F_READ, }, { - .uuid = (ble_uuid_t*) &serialNumberUuid, + .uuid = &serialNumberUuid.u, .access_cb = DeviceInformationCallback, .arg = this, .flags = BLE_GATT_CHR_F_READ, }, { - .uuid = (ble_uuid_t*) &fwRevisionUuid, + .uuid = &fwRevisionUuid.u, .access_cb = DeviceInformationCallback, .arg = this, .flags = BLE_GATT_CHR_F_READ, }, { - .uuid = (ble_uuid_t*) &hwRevisionUuid, + .uuid = &hwRevisionUuid.u, .access_cb = DeviceInformationCallback, .arg = this, .flags = BLE_GATT_CHR_F_READ, }, { - .uuid = (ble_uuid_t*) &swRevisionUuid, + .uuid = &swRevisionUuid.u, .access_cb = DeviceInformationCallback, .arg = this, .flags = BLE_GATT_CHR_F_READ, @@ -95,7 +95,7 @@ DeviceInformationService::DeviceInformationService() serviceDefinition { {/* Device Information Service */ .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = (ble_uuid_t*) &deviceInfoUuid, + .uuid = &deviceInfoUuid.u, .characteristics = characteristicDefinition}, {0}, } { diff --git a/src/components/ble/DfuService.cpp b/src/components/ble/DfuService.cpp index 4179994d..3d6416fa 100644 --- a/src/components/ble/DfuService.cpp +++ b/src/components/ble/DfuService.cpp @@ -33,21 +33,21 @@ DfuService::DfuService(Pinetime::System::SystemTask& systemTask, bleController {bleController}, dfuImage {spiNorFlash}, characteristicDefinition {{ - .uuid = (ble_uuid_t*) &packetCharacteristicUuid, + .uuid = &packetCharacteristicUuid.u, .access_cb = DfuServiceCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, .val_handle = nullptr, }, { - .uuid = (ble_uuid_t*) &controlPointCharacteristicUuid, + .uuid = &controlPointCharacteristicUuid.u, .access_cb = DfuServiceCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_NOTIFY, .val_handle = nullptr, }, { - .uuid = (ble_uuid_t*) &revisionCharacteristicUuid, + .uuid = &revisionCharacteristicUuid.u, .access_cb = DfuServiceCallback, .arg = this, .flags = BLE_GATT_CHR_F_READ, @@ -60,7 +60,7 @@ DfuService::DfuService(Pinetime::System::SystemTask& systemTask, serviceDefinition { {/* Device Information Service */ .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = (ble_uuid_t*) &serviceUuid, + .uuid = &serviceUuid.u, .characteristics = characteristicDefinition}, {0}, } { @@ -81,9 +81,9 @@ int DfuService::OnServiceData(uint16_t connectionHandle, uint16_t attributeHandl xTimerStart(timeoutTimer, 0); } - ble_gatts_find_chr((ble_uuid_t*) &serviceUuid, (ble_uuid_t*) &packetCharacteristicUuid, nullptr, &packetCharacteristicHandle); - ble_gatts_find_chr((ble_uuid_t*) &serviceUuid, (ble_uuid_t*) &controlPointCharacteristicUuid, nullptr, &controlPointCharacteristicHandle); - ble_gatts_find_chr((ble_uuid_t*) &serviceUuid, (ble_uuid_t*) &revisionCharacteristicUuid, nullptr, &revisionCharacteristicHandle); + ble_gatts_find_chr(&serviceUuid.u, &packetCharacteristicUuid.u, nullptr, &packetCharacteristicHandle); + ble_gatts_find_chr(&serviceUuid.u, &controlPointCharacteristicUuid.u, nullptr, &controlPointCharacteristicHandle); + ble_gatts_find_chr(&serviceUuid.u, &revisionCharacteristicUuid.u, nullptr, &revisionCharacteristicHandle); if (attributeHandle == packetCharacteristicHandle) { if (context->op == BLE_GATT_ACCESS_OP_WRITE_CHR) @@ -164,10 +164,10 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf* om) { if ((nbPacketReceived % nbPacketsToNotify) == 0 && bytesReceived != applicationSize) { uint8_t data[5] {static_cast(Opcodes::PacketReceiptNotification), - (uint8_t) (bytesReceived & 0x000000FFu), - (uint8_t) (bytesReceived >> 8u), - (uint8_t) (bytesReceived >> 16u), - (uint8_t) (bytesReceived >> 24u)}; + (uint8_t)(bytesReceived & 0x000000FFu), + (uint8_t)(bytesReceived >> 8u), + (uint8_t)(bytesReceived >> 16u), + (uint8_t)(bytesReceived >> 24u)}; NRF_LOG_INFO("[DFU] -> Send packet notification: %d bytes received", bytesReceived); notificationManager.Send(connectionHandle, controlPointCharacteristicHandle, data, 5); } @@ -422,9 +422,9 @@ uint16_t DfuService::DfuImage::ComputeCrc(uint8_t const* p_data, uint32_t size, uint16_t crc = (p_crc == NULL) ? 0xFFFF : *p_crc; for (uint32_t i = 0; i < size; i++) { - crc = (uint8_t) (crc >> 8) | (crc << 8); + crc = (uint8_t)(crc >> 8) | (crc << 8); crc ^= p_data[i]; - crc ^= (uint8_t) (crc & 0xFF) >> 4; + crc ^= (uint8_t)(crc & 0xFF) >> 4; crc ^= (crc << 8) << 4; crc ^= ((crc & 0xFF) << 4) << 1; } diff --git a/src/components/ble/HeartRateService.cpp b/src/components/ble/HeartRateService.cpp index c556566b..5b00f492 100644 --- a/src/components/ble/HeartRateService.cpp +++ b/src/components/ble/HeartRateService.cpp @@ -18,7 +18,7 @@ namespace { HeartRateService::HeartRateService(Pinetime::System::SystemTask& system, Controllers::HeartRateController& heartRateController) : system {system}, heartRateController {heartRateController}, - characteristicDefinition {{.uuid = (ble_uuid_t*) &heartRateMeasurementUuid, + characteristicDefinition {{.uuid = &heartRateMeasurementUuid.u, .access_cb = HeartRateServiceServiceCallback, .arg = this, .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, @@ -27,7 +27,7 @@ HeartRateService::HeartRateService(Pinetime::System::SystemTask& system, Control serviceDefinition { {/* Device Information Service */ .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = (ble_uuid_t*) &heartRateServiceUuid, + .uuid = &heartRateServiceUuid.u, .characteristics = characteristicDefinition}, {0}, } { diff --git a/src/components/ble/ImmediateAlertService.cpp b/src/components/ble/ImmediateAlertService.cpp index 820d3b6e..17ed1a96 100644 --- a/src/components/ble/ImmediateAlertService.cpp +++ b/src/components/ble/ImmediateAlertService.cpp @@ -32,7 +32,7 @@ ImmediateAlertService::ImmediateAlertService(Pinetime::System::SystemTask& syste Pinetime::Controllers::NotificationManager& notificationManager) : systemTask {systemTask}, notificationManager {notificationManager}, - characteristicDefinition {{.uuid = (ble_uuid_t*) &alertLevelUuid, + characteristicDefinition {{.uuid = &alertLevelUuid.u, .access_cb = AlertLevelCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE_NO_RSP, @@ -41,7 +41,7 @@ ImmediateAlertService::ImmediateAlertService(Pinetime::System::SystemTask& syste serviceDefinition { {/* Device Information Service */ .type = BLE_GATT_SVC_TYPE_PRIMARY, - .uuid = (ble_uuid_t*) &immediateAlertServiceUuid, + .uuid = &immediateAlertServiceUuid.u, .characteristics = characteristicDefinition}, {0}, } { @@ -72,4 +72,4 @@ int ImmediateAlertService::OnAlertLevelChanged(uint16_t connectionHandle, uint16 } return 0; -} \ No newline at end of file +} diff --git a/src/components/ble/NavigationService.cpp b/src/components/ble/NavigationService.cpp index e1c20bf1..d93c85d1 100644 --- a/src/components/ble/NavigationService.cpp +++ b/src/components/ble/NavigationService.cpp @@ -50,24 +50,18 @@ Pinetime::Controllers::NavigationService::NavigationService(Pinetime::System::Sy navProgressCharUuid.value[15] = navId[1]; characteristicDefinition[0] = { - .uuid = (ble_uuid_t*) (&navFlagCharUuid), .access_cb = NAVCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; + .uuid = &navFlagCharUuid.u, .access_cb = NAVCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; - characteristicDefinition[1] = {.uuid = (ble_uuid_t*) (&navNarrativeCharUuid), - .access_cb = NAVCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; - characteristicDefinition[2] = {.uuid = (ble_uuid_t*) (&navManDistCharUuid), - .access_cb = NAVCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; - characteristicDefinition[3] = {.uuid = (ble_uuid_t*) (&navProgressCharUuid), - .access_cb = NAVCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; + characteristicDefinition[1] = { + .uuid = &navNarrativeCharUuid.u, .access_cb = NAVCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; + characteristicDefinition[2] = { + .uuid = &navManDistCharUuid.u, .access_cb = NAVCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; + characteristicDefinition[3] = { + .uuid = &navProgressCharUuid.u, .access_cb = NAVCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}; characteristicDefinition[4] = {0}; - serviceDefinition[0] = {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = (ble_uuid_t*) &navUuid, .characteristics = characteristicDefinition}; + serviceDefinition[0] = {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &navUuid.u, .characteristics = characteristicDefinition}; serviceDefinition[1] = {0}; m_progress = 0; @@ -90,13 +84,13 @@ int Pinetime::Controllers::NavigationService::OnCommand(uint16_t conn_handle, ui data[notifSize] = '\0'; os_mbuf_copydata(ctxt->om, 0, notifSize, data); char* s = (char*) &data[0]; - if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &navFlagCharUuid) == 0) { + if (ble_uuid_cmp(ctxt->chr->uuid, &navFlagCharUuid.u) == 0) { m_flag = s; - } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &navNarrativeCharUuid) == 0) { + } else if (ble_uuid_cmp(ctxt->chr->uuid, &navNarrativeCharUuid.u) == 0) { m_narrative = s; - } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &navManDistCharUuid) == 0) { + } else if (ble_uuid_cmp(ctxt->chr->uuid, &navManDistCharUuid.u) == 0) { m_manDist = s; - } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &navProgressCharUuid) == 0) { + } else if (ble_uuid_cmp(ctxt->chr->uuid, &navProgressCharUuid.u) == 0) { m_progress = data[0]; } } From 7cc73b7832d758e36a0f5b126aeb1e71a259a72d Mon Sep 17 00:00:00 2001 From: Jonathan Vander Mey Date: Sat, 24 Jul 2021 13:02:43 -0400 Subject: [PATCH 21/50] Move callback function into anonymous namespace --- src/components/ble/NavigationService.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/ble/NavigationService.cpp b/src/components/ble/NavigationService.cpp index 0ab1fa9b..4bbe8b45 100644 --- a/src/components/ble/NavigationService.cpp +++ b/src/components/ble/NavigationService.cpp @@ -38,12 +38,12 @@ namespace { constexpr ble_uuid128_t navNarrativeCharUuid {CharUuid(0x02, 0x00)}; constexpr ble_uuid128_t navManDistCharUuid {CharUuid(0x03, 0x00)}; constexpr ble_uuid128_t navProgressCharUuid {CharUuid(0x04, 0x00)}; -} // namespace -int NAVCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) { - auto navService = static_cast(arg); - return navService->OnCommand(conn_handle, attr_handle, ctxt); -} + int NAVCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) { + auto navService = static_cast(arg); + return navService->OnCommand(conn_handle, attr_handle, ctxt); + } +} // namespace Pinetime::Controllers::NavigationService::NavigationService(Pinetime::System::SystemTask& system) : m_system(system) { characteristicDefinition[0] = { From 9c175e2f0cd90b56818953b748c8cad3eec2eb89 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Tue, 17 Aug 2021 16:01:18 +0300 Subject: [PATCH 22/50] Fix after merge --- src/displayapp/DisplayApp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 4b73a201..7fe69397 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -54,7 +54,7 @@ namespace { } TouchEvents Convert(Pinetime::Drivers::Cst816S::TouchInfos info) { - if (info.isTouch) { + if (info.isValid) { switch (info.gesture) { case Pinetime::Drivers::Cst816S::Gestures::SingleTap: return TouchEvents::Tap; From 780a811f0559a9abd000f36d3fe49cbbb233b632 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Wed, 18 Aug 2021 15:23:30 +0300 Subject: [PATCH 23/50] Automatic error detection --- src/BootErrors.h | 10 ++++++ src/CMakeLists.txt | 1 + src/displayapp/Apps.h | 3 +- src/displayapp/DisplayApp.cpp | 17 ++++++++-- src/displayapp/DisplayApp.h | 5 ++- src/displayapp/screens/Error.cpp | 54 ++++++++++++++++++++++++++++++++ src/displayapp/screens/Error.h | 22 +++++++++++++ src/drivers/Cst816s.cpp | 7 ++++- src/drivers/Cst816s.h | 2 +- src/systemtask/SystemTask.cpp | 9 ++++-- 10 files changed, 121 insertions(+), 9 deletions(-) create mode 100644 src/BootErrors.h create mode 100644 src/displayapp/screens/Error.cpp create mode 100644 src/displayapp/screens/Error.h diff --git a/src/BootErrors.h b/src/BootErrors.h new file mode 100644 index 00000000..d00418cc --- /dev/null +++ b/src/BootErrors.h @@ -0,0 +1,10 @@ +#pragma once + +namespace Pinetime { + namespace System { + enum class BootErrors { + None, + TouchController, + }; + } +} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 40e1f2a5..0d41a244 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -418,6 +418,7 @@ list(APPEND SOURCE_FILES displayapp/screens/BatteryInfo.cpp displayapp/screens/Steps.cpp displayapp/screens/Timer.cpp + displayapp/screens/Error.cpp ## Settings displayapp/screens/settings/QuickSettings.cpp diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index 684e3a46..0b102100 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -30,7 +30,8 @@ namespace Pinetime { SettingTimeFormat, SettingDisplay, SettingWakeUp, - SettingSteps + SettingSteps, + Error, }; } } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 7fe69397..41fa7d80 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -28,6 +28,7 @@ #include "displayapp/screens/FlashLight.h" #include "displayapp/screens/BatteryInfo.h" #include "displayapp/screens/Steps.h" +#include "displayapp/screens/Error.h" #include "drivers/Cst816s.h" #include "drivers/St7789.h" @@ -107,11 +108,16 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, timerController {timerController} { } -void DisplayApp::Start() { +void DisplayApp::Start(System::BootErrors error) { msgQueue = xQueueCreate(queueSize, itemSize); - // Start clock when smartwatch boots - LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::None); + bootError = error; + + if (error == System::BootErrors::TouchController) { + LoadApp(Apps::Error, DisplayApp::FullRefreshDirections::None); + } else { + LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::None); + } if (pdPASS != xTaskCreate(DisplayApp::Process, "displayapp", 800, this, 0, &taskHandle)) { APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); @@ -325,6 +331,11 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) motionController); break; + case Apps::Error: + currentScreen = std::make_unique(this, bootError); + ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None); + break; + case Apps::FirmwareValidation: currentScreen = std::make_unique(this, validator); ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index 574be63f..ba119133 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -15,6 +15,7 @@ #include "displayapp/screens/Screen.h" #include "components/timer/TimerController.h" #include "Messages.h" +#include "BootErrors.h" namespace Pinetime { @@ -56,7 +57,7 @@ namespace Pinetime { Pinetime::Controllers::MotorController& motorController, Pinetime::Controllers::MotionController& motionController, Pinetime::Controllers::TimerController& timerController); - void Start(); + void Start(System::BootErrors error); void PushMessage(Display::Messages msg); void StartApp(Apps app, DisplayApp::FullRefreshDirections direction); @@ -114,6 +115,8 @@ namespace Pinetime { Apps nextApp = Apps::None; DisplayApp::FullRefreshDirections nextDirection; TickType_t lastWakeTime; + + System::BootErrors bootError; }; } } diff --git a/src/displayapp/screens/Error.cpp b/src/displayapp/screens/Error.cpp new file mode 100644 index 00000000..7ad52ade --- /dev/null +++ b/src/displayapp/screens/Error.cpp @@ -0,0 +1,54 @@ +#include "Error.h" + +using namespace Pinetime::Applications::Screens; + +namespace { + void ButtonEventCallback(lv_obj_t* obj, lv_event_t /*event*/) { + auto* errorScreen = static_cast(obj->user_data); + errorScreen->ButtonEventHandler(); + } +} + +Error::Error(Pinetime::Applications::DisplayApp* app, System::BootErrors error) + : Screen(app) { + + lv_obj_t* warningLabel = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(warningLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); + lv_label_set_text_static(warningLabel, "Warning"); + lv_obj_align(warningLabel, nullptr, LV_ALIGN_IN_TOP_MID, 0, 0); + + lv_obj_t* causeLabel = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_long_mode(causeLabel, LV_LABEL_LONG_BREAK); + lv_obj_set_width(causeLabel, LV_HOR_RES); + lv_obj_align(causeLabel, warningLabel, LV_ALIGN_OUT_BOTTOM_MID, 0, 0); + + if (error == System::BootErrors::TouchController) { + lv_label_set_text_static(causeLabel, "Touch controller error detected."); + } + + lv_obj_t* tipLabel = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_long_mode(tipLabel, LV_LABEL_LONG_BREAK); + lv_obj_set_width(tipLabel, LV_HOR_RES); + lv_label_set_text_static(tipLabel, "If you encounter problems and your device is under warranty, contact the devices seller."); + lv_obj_align(tipLabel, causeLabel, LV_ALIGN_OUT_BOTTOM_MID, 0, 0); + + btnOk = lv_btn_create(lv_scr_act(), nullptr); + btnOk->user_data = this; + lv_obj_set_event_cb(btnOk, ButtonEventCallback); + lv_obj_set_size(btnOk, LV_HOR_RES, 50); + lv_obj_align(btnOk, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); + lv_obj_set_style_local_value_str(btnOk, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Proceed"); + lv_obj_set_style_local_bg_color(btnOk, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); +} + +void Error::ButtonEventHandler() { + running = false; +} + +Error::~Error() { + lv_obj_clean(lv_scr_act()); +} + +bool Error::Refresh() { + return running; +} diff --git a/src/displayapp/screens/Error.h b/src/displayapp/screens/Error.h new file mode 100644 index 00000000..58016d82 --- /dev/null +++ b/src/displayapp/screens/Error.h @@ -0,0 +1,22 @@ +#pragma once + +#include "Screen.h" +#include "BootErrors.h" +#include + +namespace Pinetime { + namespace Applications { + namespace Screens { + class Error : public Screen { + public: + Error(DisplayApp* app, System::BootErrors error); + ~Error() override; + + bool Refresh() override; + void ButtonEventHandler(); + private: + lv_obj_t* btnOk; + }; + } + } +} diff --git a/src/drivers/Cst816s.cpp b/src/drivers/Cst816s.cpp index 2a6809b1..3db712e6 100644 --- a/src/drivers/Cst816s.cpp +++ b/src/drivers/Cst816s.cpp @@ -17,7 +17,7 @@ using namespace Pinetime::Drivers; Cst816S::Cst816S(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster {twiMaster}, twiAddress {twiAddress} { } -void Cst816S::Init() { +bool Cst816S::Init() { nrf_gpio_cfg_output(pinReset); nrf_gpio_pin_set(pinReset); vTaskDelay(50); @@ -44,13 +44,18 @@ void Cst816S::Init() { // There's mixed information about which register contains which information if (twiMaster.Read(twiAddress, 0xA7, &chipId, 1) == TwiMaster::ErrorCodes::TransactionFailed) { chipId = 0xFF; + return false; } if (twiMaster.Read(twiAddress, 0xA8, &vendorId, 1) == TwiMaster::ErrorCodes::TransactionFailed) { vendorId = 0xFF; + return false; } if (twiMaster.Read(twiAddress, 0xA9, &fwVersion, 1) == TwiMaster::ErrorCodes::TransactionFailed) { fwVersion = 0xFF; + return false; } + + return chipId == 0xb4 && vendorId == 0 && fwVersion == 1; } Cst816S::TouchInfos Cst816S::GetTouchInfo() { diff --git a/src/drivers/Cst816s.h b/src/drivers/Cst816s.h index 394cc40f..5b2e4e46 100644 --- a/src/drivers/Cst816s.h +++ b/src/drivers/Cst816s.h @@ -31,7 +31,7 @@ namespace Pinetime { Cst816S(Cst816S&&) = delete; Cst816S& operator=(Cst816S&&) = delete; - void Init(); + bool Init(); TouchInfos GetTouchInfo(); void Sleep(); void Wakeup(); diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 500bc8b8..718e6ccd 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -22,6 +22,7 @@ #include "drivers/TwiMaster.h" #include "drivers/Hrs3300.h" #include "main.h" +#include "BootErrors.h" #include @@ -106,6 +107,8 @@ void SystemTask::Process(void* instance) { } void SystemTask::Work() { + BootErrors bootError = BootErrors::None; + watchdog.Setup(7); watchdog.Start(); NRF_LOG_INFO("Last reset reason : %s", Pinetime::Drivers::Watchdog::ResetReasonToString(watchdog.ResetReason())); @@ -124,7 +127,9 @@ void SystemTask::Work() { lcd.Init(); twiMaster.Init(); - touchPanel.Init(); + if (!touchPanel.Init()) { + bootError = BootErrors::TouchController; + } dateTimeController.Register(this); batteryController.Init(); motorController.Init(); @@ -141,7 +146,7 @@ void SystemTask::Work() { settingsController.Init(); displayApp.Register(this); - displayApp.Start(); + displayApp.Start(bootError); displayApp.PushMessage(Pinetime::Applications::Display::Messages::UpdateBatteryLevel); From 8f0771183c3872343100a2e974f37c91237da277 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Wed, 15 Sep 2021 12:25:41 +0300 Subject: [PATCH 24/50] Fix Error screen and optimize GetTouchInfo --- src/displayapp/screens/Error.cpp | 4 ---- src/displayapp/screens/Error.h | 1 - src/drivers/Cst816s.cpp | 17 ++++++++--------- src/drivers/Cst816s.h | 1 - 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/src/displayapp/screens/Error.cpp b/src/displayapp/screens/Error.cpp index 7ad52ade..75946aba 100644 --- a/src/displayapp/screens/Error.cpp +++ b/src/displayapp/screens/Error.cpp @@ -48,7 +48,3 @@ void Error::ButtonEventHandler() { Error::~Error() { lv_obj_clean(lv_scr_act()); } - -bool Error::Refresh() { - return running; -} diff --git a/src/displayapp/screens/Error.h b/src/displayapp/screens/Error.h index 58016d82..20dde7ee 100644 --- a/src/displayapp/screens/Error.h +++ b/src/displayapp/screens/Error.h @@ -12,7 +12,6 @@ namespace Pinetime { Error(DisplayApp* app, System::BootErrors error); ~Error() override; - bool Refresh() override; void ButtonEventHandler(); private: lv_obj_t* btnOk; diff --git a/src/drivers/Cst816s.cpp b/src/drivers/Cst816s.cpp index 5feb17b0..49d6ed0e 100644 --- a/src/drivers/Cst816s.cpp +++ b/src/drivers/Cst816s.cpp @@ -71,6 +71,7 @@ bool Cst816S::Init() { Cst816S::TouchInfos Cst816S::GetTouchInfo() { Cst816S::TouchInfos info; + uint8_t touchData[7]; auto ret = twiMaster.Read(twiAddress, 0, touchData, sizeof(touchData)); if (ret != TwiMaster::ErrorCodes::NoError) { @@ -79,18 +80,16 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() { } // This can only be 0 or 1 - auto nbTouchPoints = touchData[touchPointNumIndex] & 0x0f; + uint8_t nbTouchPoints = touchData[touchPointNumIndex] & 0x0f; - auto xHigh = touchData[touchXHighIndex] & 0x0f; - auto xLow = touchData[touchXLowIndex]; - uint16_t x = (xHigh << 8) | xLow; + uint8_t xHigh = touchData[touchXHighIndex] & 0x0f; + uint8_t xLow = touchData[touchXLowIndex]; + info.x = (xHigh << 8) | xLow; - auto yHigh = touchData[touchYHighIndex] & 0x0f; - auto yLow = touchData[touchYLowIndex]; - uint16_t y = (yHigh << 8) | yLow; + uint8_t yHigh = touchData[touchYHighIndex] & 0x0f; + uint8_t yLow = touchData[touchYLowIndex]; + info.y = (yHigh << 8) | yLow; - info.x = x; - info.y = y; info.touching = (nbTouchPoints > 0); info.gesture = static_cast(touchData[gestureIndex]); diff --git a/src/drivers/Cst816s.h b/src/drivers/Cst816s.h index d15ce06d..0fec8419 100644 --- a/src/drivers/Cst816s.h +++ b/src/drivers/Cst816s.h @@ -58,7 +58,6 @@ namespace Pinetime { //static constexpr uint8_t touchXYIndex = 7; //static constexpr uint8_t touchMiscIndex = 8; - uint8_t touchData[7]; TwiMaster& twiMaster; uint8_t twiAddress; From d86ae69961231aaa177ed146ad829c93943f600c Mon Sep 17 00:00:00 2001 From: Maxim Leshchenko Date: Tue, 28 Sep 2021 22:50:09 +0300 Subject: [PATCH 25/50] Alarm: Close the popup with information about the time until alarm with the back button Previously, pressing the back button would close the alarm app anyway. Now if you press on it and the popup with information is open, it will first close and the second press will close the application --- src/displayapp/screens/Alarm.cpp | 11 +++++++++++ src/displayapp/screens/Alarm.h | 1 + 2 files changed, 12 insertions(+) diff --git a/src/displayapp/screens/Alarm.cpp b/src/displayapp/screens/Alarm.cpp index 959cb0b2..371593a2 100644 --- a/src/displayapp/screens/Alarm.cpp +++ b/src/displayapp/screens/Alarm.cpp @@ -174,6 +174,17 @@ void Alarm::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { } } +bool Alarm::OnButtonPushed() { + if (txtMessage != nullptr && btnMessage != nullptr) { + lv_obj_del(txtMessage); + lv_obj_del(btnMessage); + txtMessage = nullptr; + btnMessage = nullptr; + return true; + } + return false; +} + void Alarm::UpdateAlarmTime() { lv_label_set_text_fmt(time, "%02d:%02d", alarmHours, alarmMinutes); alarmController.SetAlarmTime(alarmHours, alarmMinutes); diff --git a/src/displayapp/screens/Alarm.h b/src/displayapp/screens/Alarm.h index abf97eba..edd211b5 100644 --- a/src/displayapp/screens/Alarm.h +++ b/src/displayapp/screens/Alarm.h @@ -31,6 +31,7 @@ namespace Pinetime { ~Alarm() override; void SetAlerting(); void OnButtonEvent(lv_obj_t* obj, lv_event_t event); + bool OnButtonPushed() override; private: bool running; From 05f8850acf163f255d58e6224a3f9382b42e6ed4 Mon Sep 17 00:00:00 2001 From: Maxim Leshchenko Date: Wed, 29 Sep 2021 19:15:23 +0300 Subject: [PATCH 26/50] Fixes based on code reviews --- src/displayapp/screens/Alarm.cpp | 16 ++++++++-------- src/displayapp/screens/Alarm.h | 1 + 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/displayapp/screens/Alarm.cpp b/src/displayapp/screens/Alarm.cpp index 371593a2..6b45a36e 100644 --- a/src/displayapp/screens/Alarm.cpp +++ b/src/displayapp/screens/Alarm.cpp @@ -120,10 +120,7 @@ void Alarm::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { return; } if (obj == btnMessage) { - lv_obj_del(txtMessage); - lv_obj_del(btnMessage); - txtMessage = nullptr; - btnMessage = nullptr; + HideInfo(); return; } // If any other button was pressed, disable the alarm @@ -176,10 +173,7 @@ void Alarm::OnButtonEvent(lv_obj_t* obj, lv_event_t event) { bool Alarm::OnButtonPushed() { if (txtMessage != nullptr && btnMessage != nullptr) { - lv_obj_del(txtMessage); - lv_obj_del(btnMessage); - txtMessage = nullptr; - btnMessage = nullptr; + HideInfo(); return true; } return false; @@ -235,6 +229,12 @@ void Alarm::ShowInfo() { } } +void Alarm::HideInfo() { + lv_obj_del(btnMessage); + txtMessage = nullptr; + btnMessage = nullptr; +} + void Alarm::SetRecurButtonState() { using Pinetime::Controllers::AlarmController; switch (alarmController.Recurrence()) { diff --git a/src/displayapp/screens/Alarm.h b/src/displayapp/screens/Alarm.h index edd211b5..32a14d2f 100644 --- a/src/displayapp/screens/Alarm.h +++ b/src/displayapp/screens/Alarm.h @@ -47,6 +47,7 @@ namespace Pinetime { void SetRecurButtonState(); void SetAlarm(); void ShowInfo(); + void HideInfo(); void ToggleRecurrence(); void UpdateAlarmTime(); }; From de89c86ca9e5a4f9807c81d55448d364275a86c4 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Thu, 30 Sep 2021 08:44:11 +0100 Subject: [PATCH 27/50] Add templates for bug reports and feature requests --- .github/ISSUE_TEMPLATE/bug-report.yaml | 59 +++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature-request.yaml | 41 ++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug-report.yaml create mode 100644 .github/ISSUE_TEMPLATE/feature-request.yaml diff --git a/.github/ISSUE_TEMPLATE/bug-report.yaml b/.github/ISSUE_TEMPLATE/bug-report.yaml new file mode 100644 index 00000000..efcba56c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yaml @@ -0,0 +1,59 @@ +name: Bug Report +description: File a bug report +title: "[Bug]: " +labels: ["bug"] +body: + - type: markdown + attributes: + value: | + **Thanks for taking the time to fill out this bug report!** + *Please, before opening a bug report, check if similar issues already exist. In that case, use those issues to provide your feedback instead.* + - type: checkboxes + attributes: + options: + - label: I searched for similar bug reports and found none was relevant. + required: true + - type: input + id: desc-brief + attributes: + label: What happened? + description: A one-line description of the bug. + placeholder: "Ex. I woke up as a Kafkian insect this morning." + validations: + required: true + - type: input + id: desc-expected + attributes: + label: What should happen instead? + description: The behaviour you were expecting to see. + placeholder: "Ex. I was expecting to wake up as a human." + - type: textarea + id: desc-steps + attributes: + label: Reproduction steps + description: "How do you trigger this bug? Please walk us through it step by step." + validations: + required: true + - type: textarea + id: desc-long + attributes: + label: More details? + description: Give us more details about the bug and any personal attempts you made to fix it. + placeholder: Tell us more! + - type: input + id: version + attributes: + label: Version + description: | + What [version of the firmware](https://github.com/JF002/InfiniTime/blob/develop/doc/gettingStarted/gettingStarted-1.0.md#how-to-check-the-version-of-infinitime-and-the-bootloader) are you running? + If you are running an older version, please consider [updating to the latest firmware](https://github.com/JF002/InfiniTime/blob/develop/doc/gettingStarted/gettingStarted-1.0.md#how-to-update-your-pinetime). + If you are running directly from git, specify the branch or the commit hash directly. + placeholder: "Ex. v1.6.0 or develop or fc922b60" + validations: + required: true + - type: input + id: companion-app + attributes: + label: Companion app + description: Which companion app are you using (if relevant)? + placeholder: "Ex. Gadgetbridge v0.60.0, Siglo v0.9.4" diff --git a/.github/ISSUE_TEMPLATE/feature-request.yaml b/.github/ISSUE_TEMPLATE/feature-request.yaml new file mode 100644 index 00000000..33b059c0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-request.yaml @@ -0,0 +1,41 @@ +name: Feature Request +description: File a feature request +title: "[Feature Request]: " +labels: ["feature-request"] +body: + - type: markdown + attributes: + value: | + **Thanks for taking the time to fill out this feature request!** + *Please, before opening a feature request, check if similar issues already exist. In that case, use those issues to provide your feedback instead.* + - type: checkboxes + attributes: + options: + - label: I searched for similar feature request and found none was relevant. + required: true + - type: markdown + attributes: + value: | + **Note:** keep in mind that, while InfiniTime is usable, it is still under heavy development and as such it is continuously evolving. + Some features you want to see implemented might not be compatible with the current state of the project, or might not even be suitable to include *in the firmware* of the watch. + - type: input + id: desc-brief + attributes: + label: Pitch us your idea! + description: A one-line elevator pitch of the feature you'd like to see implemented. + placeholder: "Ex. My dog wants InfiniTime on its smart collar." + validations: + required: true + - type: textarea + id: desc-long + attributes: + label: Description + description: | + Give us a detailed description of the feature you are proposing. Mockups or a description of the possible use cases are highly appreciated. + Tell us why this should be included in the firmware. + placeholder: "Ex. Here is a drawing of my dog wearing an InfiniTime collar and smiling." + - type: markdown + id: companion-app + attributes: + value: | + If this requires features missing from other software (for example a companion app), please take care of opening any relevant feature request over there as well. From 2aebbe3f474bfaa5058879bde045146f5561fb66 Mon Sep 17 00:00:00 2001 From: hubmartin Date: Sun, 3 Oct 2021 16:47:01 +0200 Subject: [PATCH 28/50] GPIOTE fix of button and power detection experiment --- src/systemtask/SystemTask.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 5441c162..a2ff60f8 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -158,19 +158,21 @@ void SystemTask::Work() { heartRateSensor.Disable(); heartRateApp.Start(); - nrf_gpio_cfg_sense_input(PinMap::Button, (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pulldown, (nrf_gpio_pin_sense_t) GPIO_PIN_CNF_SENSE_High); + // Button nrf_gpio_cfg_output(15); nrf_gpio_pin_set(15); nrfx_gpiote_in_config_t pinConfig; - pinConfig.skip_gpio_setup = true; + pinConfig.skip_gpio_setup = false; pinConfig.hi_accuracy = false; pinConfig.is_watcher = false; - pinConfig.sense = (nrf_gpiote_polarity_t) NRF_GPIOTE_POLARITY_HITOLO; + pinConfig.sense = (nrf_gpiote_polarity_t) NRF_GPIOTE_POLARITY_TOGGLE; pinConfig.pull = (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pulldown; nrfx_gpiote_in_init(PinMap::Button, &pinConfig, nrfx_gpiote_evt_handler); + nrfx_gpiote_in_event_enable(PinMap::Button, true); + // Touchscreen nrf_gpio_cfg_sense_input(PinMap::Cst816sIrq, (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pullup, (nrf_gpio_pin_sense_t) GPIO_PIN_CNF_SENSE_Low); pinConfig.skip_gpio_setup = true; @@ -181,18 +183,20 @@ void SystemTask::Work() { nrfx_gpiote_in_init(PinMap::Cst816sIrq, &pinConfig, nrfx_gpiote_evt_handler); + // Power present pinConfig.sense = NRF_GPIOTE_POLARITY_TOGGLE; pinConfig.pull = NRF_GPIO_PIN_NOPULL; pinConfig.is_watcher = false; pinConfig.hi_accuracy = false; - pinConfig.skip_gpio_setup = true; + pinConfig.skip_gpio_setup = false; nrfx_gpiote_in_init(PinMap::PowerPresent, &pinConfig, nrfx_gpiote_evt_handler); + nrfx_gpiote_in_event_enable(PinMap::PowerPresent, true); - if (nrf_gpio_pin_read(PinMap::PowerPresent)) { - nrf_gpio_cfg_sense_input(PinMap::PowerPresent, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW); - } else { - nrf_gpio_cfg_sense_input(PinMap::PowerPresent, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH); - } + // if (nrf_gpio_pin_read(PinMap::PowerPresent)) { + // nrf_gpio_cfg_sense_input(PinMap::PowerPresent, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW); + // } else { + // nrf_gpio_cfg_sense_input(PinMap::PowerPresent, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH); + // } idleTimer = xTimerCreate("idleTimer", pdMS_TO_TICKS(2000), pdFALSE, this, IdleTimerCallback); dimTimer = xTimerCreate("dimTimer", pdMS_TO_TICKS(settingsController.GetScreenTimeOut() - 2000), pdFALSE, this, DimTimerCallback); From f5725714d13a66407b0556f8ac3cbd7e6db8901f Mon Sep 17 00:00:00 2001 From: hubmartin Date: Sun, 3 Oct 2021 17:00:38 +0200 Subject: [PATCH 29/50] Call battery controller update --- src/systemtask/SystemTask.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index a2ff60f8..fc2c5cfd 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -136,7 +136,6 @@ void SystemTask::Work() { touchPanel.Init(); dateTimeController.Register(this); batteryController.Register(this); - batteryController.Update(); motorController.Init(); motionSensor.SoftReset(); timerController.Register(this); @@ -197,6 +196,9 @@ void SystemTask::Work() { // } else { // nrf_gpio_cfg_sense_input(PinMap::PowerPresent, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH); // } + + // Update controller based on current gpio pin state, needs to be called after gpio config + batteryController.Update(); idleTimer = xTimerCreate("idleTimer", pdMS_TO_TICKS(2000), pdFALSE, this, IdleTimerCallback); dimTimer = xTimerCreate("dimTimer", pdMS_TO_TICKS(settingsController.GetScreenTimeOut() - 2000), pdFALSE, this, DimTimerCallback); From 9ef1babb9dfea4be0ef2179254dc3dd8afd1d7e1 Mon Sep 17 00:00:00 2001 From: hubmartin Date: Sun, 3 Oct 2021 17:03:08 +0200 Subject: [PATCH 30/50] Code cleanup --- src/systemtask/SystemTask.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index fc2c5cfd..8412540f 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -191,12 +191,6 @@ void SystemTask::Work() { nrfx_gpiote_in_init(PinMap::PowerPresent, &pinConfig, nrfx_gpiote_evt_handler); nrfx_gpiote_in_event_enable(PinMap::PowerPresent, true); - // if (nrf_gpio_pin_read(PinMap::PowerPresent)) { - // nrf_gpio_cfg_sense_input(PinMap::PowerPresent, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW); - // } else { - // nrf_gpio_cfg_sense_input(PinMap::PowerPresent, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH); - // } - // Update controller based on current gpio pin state, needs to be called after gpio config batteryController.Update(); From a9f7153fdf92b097b14143b77645f6608ac1bf9c Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 4 Oct 2021 01:41:38 +0300 Subject: [PATCH 31/50] Improve battery percentage calculation and reporting While charging, percentage should only go up, and while discharging, percentage should only go down. --- src/components/battery/BatteryController.cpp | 15 ++++++++++----- src/components/battery/BatteryController.h | 1 + src/systemtask/Messages.h | 2 +- src/systemtask/SystemTask.cpp | 8 ++------ src/systemtask/SystemTask.h | 2 -- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/components/battery/BatteryController.cpp b/src/components/battery/BatteryController.cpp index b43b229f..0ef4ff1a 100644 --- a/src/components/battery/BatteryController.cpp +++ b/src/components/battery/BatteryController.cpp @@ -69,18 +69,23 @@ void Battery::SaadcEventHandler(nrfx_saadc_evt_t const* p_event) { // p_event->data.done.p_buffer[0] = (adc_voltage / reference_voltage) * 1024 voltage = p_event->data.done.p_buffer[0] * (8 * 600) / 1024; + uint8_t newPercent; if (isFull) { - percentRemaining = 100; + newPercent = 100; } else if (voltage < battery_min) { - percentRemaining = 0; + newPercent = 0; } else { - percentRemaining = std::min((voltage - battery_min) * 100 / (battery_max - battery_min), isCharging ? 99 : 100); + newPercent = std::min((voltage - battery_min) * 100 / (battery_max - battery_min), isCharging ? 99 : 100); + } + + if ((isPowerPresent && newPercent > percentRemaining) || (!isPowerPresent && newPercent < percentRemaining) || firstMeasurement) { + firstMeasurement = false; + percentRemaining = newPercent; + systemTask->PushMessage(System::Messages::BatteryPercentageUpdated); } nrfx_saadc_uninit(); isReading = false; - - systemTask->PushMessage(System::Messages::BatteryMeasurementDone); } } diff --git a/src/components/battery/BatteryController.h b/src/components/battery/BatteryController.h index c78ffb3f..55c26309 100644 --- a/src/components/battery/BatteryController.h +++ b/src/components/battery/BatteryController.h @@ -42,6 +42,7 @@ namespace Pinetime { bool isFull = false; bool isCharging = false; bool isPowerPresent = false; + bool firstMeasurement = true; void SaadcInit(); diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h index bd1de234..5aa218d2 100644 --- a/src/systemtask/Messages.h +++ b/src/systemtask/Messages.h @@ -24,7 +24,7 @@ namespace Pinetime { SetOffAlarm, StopRinging, MeasureBatteryTimerExpired, - BatteryMeasurementDone, + BatteryPercentageUpdated, }; } } diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 5441c162..0a53101f 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -349,14 +349,10 @@ void SystemTask::Work() { motorController.RunForDuration(15); break; case Messages::MeasureBatteryTimerExpired: - sendBatteryNotification = true; batteryController.Update(); break; - case Messages::BatteryMeasurementDone: - if (sendBatteryNotification) { - sendBatteryNotification = false; - nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining()); - } + case Messages::BatteryPercentageUpdated: + nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining()); break; default: diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index 1fcfeb8a..879c1be8 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -133,14 +133,12 @@ namespace Pinetime { TimerHandle_t dimTimer; TimerHandle_t idleTimer; TimerHandle_t measureBatteryTimer; - bool sendBatteryNotification = false; bool doNotGoToSleep = false; void GoToRunning(); void UpdateMotion(); bool stepCounterMustBeReset = false; static constexpr TickType_t batteryMeasurementPeriod = pdMS_TO_TICKS(10 * 60 * 1000); - TickType_t lastBatteryNotificationTime = 0; #if configUSE_TRACE_FACILITY == 1 SystemMonitor monitor; From aa83fa2dcfa096e86290c9742e8498bec411732b Mon Sep 17 00:00:00 2001 From: Clemens von Molo Date: Tue, 5 Oct 2021 15:19:44 +0200 Subject: [PATCH 32/50] Add docs for app creation and code structure --- README.md | 3 +- doc/code/Apps.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++ doc/code/Intro.md | 20 ++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 doc/code/Apps.md create mode 100644 doc/code/Intro.md diff --git a/README.md b/README.md index 9b9c3287..ee1fad00 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,8 @@ As of now, here is the list of achievements of this project: ## Documentation ### Develop - + - [Rough structure of the code](doc/code/Intro.md) + - [How to implement an application](doc/code/Apps.md) - [Generate the fonts and symbols](src/displayapp/fonts/README.md) - [Creating a stopwatch in Pinetime(article)](https://pankajraghav.com/2021/04/03/PINETIME-STOPCLOCK.html) diff --git a/doc/code/Apps.md b/doc/code/Apps.md new file mode 100644 index 00000000..b19d596d --- /dev/null +++ b/doc/code/Apps.md @@ -0,0 +1,70 @@ +# Apps +This page will teach you: +- what apps in InfiniTime are +- how to implement your own app + +## Theory +Apps are the things you can lauch from the app selection you get by swiping down, but also the app launcher itself or the clock. Settings are also implemented as apps. Most screens you see are their own app, except for apps that have multiple screens (settings launcher, app launcher). +Every app in InfiniTime is it's own class. An object of the class is created when the app is launched and destroyed when the user exits the app. They run inside the "displayapp" task (briefly discussed [here](./Intro.md)). They are responsible for everything drawn on the screen when they are running. By default, apps only do something (as in a function is executed) when they are created or when a touch event is detected. + +## Interface +Every app class is has to be inside the namespace `Pinetime::Applications::Screens` and inherit from `Screen`. The constructor should have at least one parameter `DisplayApp* app`, which it needs for the constructor of its parent class Screen. Other parameters should be references to controllers that the app needs. A deconstructor is needed to clean up LVGL and restore any changes (for example re-enable sleeping). App classes can override `bool OnButtonPushed()`, `bool OnTouchEvent(TouchEvents event)` and `bool OnTouchEvent(uint16_t x, uint16_t y)` to implement their own functionality for those events. If an app only needs to display some text and do something upon a touch screen button press, it does not need to override any of these functions, as LVGL can also handle touch events for you. If your app needs to be updated continuously, yo can do so by adding a `Refresh()` function to your class and calling `lv_task_create` inside the constructor. + +## Creating your own app +A minimal app could look like this:
+MyApp.h: +```cpp +#pragma once + +#include +#include "displayapp/screens/Screen.h" + +namespace PineTime { + namespace Applications { + namespace Screens { + class MyApp : public Screen { + public: + MyApp(DisplayApp* app); + ~MyApp() override; + } + } + } +} +``` + +MyApp.cpp: +```cpp +#include "MyApp.h" +#include "displayapp/DisplayApp.h" + +using namespace Pinetime::Applications::Screens; + +MyApp::MyApp(DisplayApp* app) : Screen(app) { + lv_obj_t * container1 = lv_cont_create(lv_scr_act(), nullptr); + 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_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); + lv_obj_set_pos(container1, 30, 60); + lv_obj_set_width(container1, LV_HOR_RES - 50); + lv_obj_set_height(container1, LV_VER_RES - 60); + lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT); + + lv_obj_t * title = lv_label_create(lv_scr_act(), NULL); + lv_label_set_text_static(title,"My test application"); + lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); + lv_obj_align(title, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 15, 15); +} + +MyApp::~MyApp() { + lv_obj_clean(lv_scr_act()); +} +``` +Both of these files should be in displayapp/screens/ or displayapp/screens/settings if it's a setting app. + +Now we have our very own app, but InfiniTime does not know about it yet. The first step is to include it in the compilation by adding it to CMakeLists.txt . The next step to making it launchable is to give your app an id. To do this, add an entry in the enum class `Pinetime::Applications::Apps`. Name this entry after your app. Add `#include "displayapp/screens/MyApp.h"` to the file displayapp/DisplayApp.cpp . Now, go to the function `DisplayApp::LoadApp` and add another case to the switch statement. The case will be the id you gave your app earlier. If your app needs any additional arguments, this is the place to pass them.
+ +If you want your app to be launched from the regular app launcher, go to displayapp/screens/ApplicationList.cpp. Add your app to one of the `CreateScreen` functions, or add another `CreateScreen` function if there are no empty spaces for your app.
+If your app is a setting, do the same procedure in displayapp/screens/settings/Settings.cpp . + +You should now be able to [build](../buildAndProgram.md) the firmware and flash it to your PineTime. Yay! diff --git a/doc/code/Intro.md b/doc/code/Intro.md new file mode 100644 index 00000000..3c7fee04 --- /dev/null +++ b/doc/code/Intro.md @@ -0,0 +1,20 @@ +# Introduction to the code +This page is meant to guide you through the source code, so you can find the relevant files for what you're working on. + +## FreeRTOS +Infinitime is based on FreeRTOS, a real-time operating system. FreeRTOS provides several quality of life abstractions (for example easy software timers) and most importantly supports multiple tasks. You can sort of imagine them as processes or threads on a full operating system. The main "process" creates at least one task and then starts the FreeRTOS task scheduler. This main "process" is the standard main() function inside main.cpp . The task scheduler is responsible for giving every task enough cpu time. As there is only one core on the SoC of the PineTime, real concurrency is impossible and the scheduler has to swap tasks in and out to emulate it. + +### Tasks +Tasks are created by calling `xTaskCreate` and passing a function with the signature `void functionName(void*)`. For more info on task creation see the [FreeRTOS Documentation](https://www.freertos.org/a00125.html). +In our case, main calls `systemTask.Start()`, which creates the **"MAIN" task**. The function running inside that task is `SystemTask::Work()`. Both functions are located inside systemtask/SystemTask.cpp . `SystemTask::Work()` initializes all the driver and controller objects. It also starts the **task "displayapp"**, which is responsible for launching and running apps, controlling the screen and handling touch events (or forwarding them to the active app). You can find the "displayapp" task inside displayapp/DisplayApp.cpp . +There are also other tasks that are responsible for Bluetooth ("ll" and "ble" inside libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c) and periodic tasks like heartrate measurements (heartratetask/HeartRateTask.cpp). + +## Controllers +Controllers in InfiniTime are singleton objects that can provide access to certain resources to apps. Some of them interface with drivers, others are the driver for the resource. The resources provided don't have to be hardware-based. They are declared in main.cpp and initialized in systemtask/SystemTask.cpp . Some controllers can be passed by reference to apps that need access to the resource (for example vibration motor). +They reside in components inside their own subfolder. + +## Apps +For more detail see the [Apps page](./Apps.md) + +## Bluetooth +Header files with short documentation for the functions are inside libs/mynewt-nimble/nimble/host/include/host/ . From b2141a9050c02bff6acd09b2f8dd824b2b5f8c34 Mon Sep 17 00:00:00 2001 From: Clemens von Molo Date: Tue, 5 Oct 2021 18:55:02 +0200 Subject: [PATCH 33/50] advise against unecessary additional tasks in docs --- doc/code/Intro.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/code/Intro.md b/doc/code/Intro.md index 3c7fee04..b7371f0b 100644 --- a/doc/code/Intro.md +++ b/doc/code/Intro.md @@ -6,8 +6,9 @@ Infinitime is based on FreeRTOS, a real-time operating system. FreeRTOS provides ### Tasks Tasks are created by calling `xTaskCreate` and passing a function with the signature `void functionName(void*)`. For more info on task creation see the [FreeRTOS Documentation](https://www.freertos.org/a00125.html). -In our case, main calls `systemTask.Start()`, which creates the **"MAIN" task**. The function running inside that task is `SystemTask::Work()`. Both functions are located inside systemtask/SystemTask.cpp . `SystemTask::Work()` initializes all the driver and controller objects. It also starts the **task "displayapp"**, which is responsible for launching and running apps, controlling the screen and handling touch events (or forwarding them to the active app). You can find the "displayapp" task inside displayapp/DisplayApp.cpp . -There are also other tasks that are responsible for Bluetooth ("ll" and "ble" inside libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c) and periodic tasks like heartrate measurements (heartratetask/HeartRateTask.cpp). +In our case, main calls `systemTask.Start()`, which creates the **"MAIN" task**. The function running inside that task is `SystemTask::Work()`. You may also see this task being referred to as the **work task**. Both functions are located inside systemtask/SystemTask.cpp . `SystemTask::Work()` initializes all the driver and controller objects. It also starts the **task "displayapp"**, which is responsible for launching and running apps, controlling the screen and handling touch events (or forwarding them to the active app). You can find the "displayapp" task inside displayapp/DisplayApp.cpp . +There are also other tasks that are responsible for Bluetooth ("ll" and "ble" inside libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c) and periodic tasks like heartrate measurements (heartratetask/HeartRateTask.cpp).
+While it is possible for you to create your own task when you need it, it is recommended to just add functionality to `SystemTask::Work()` if possible. If you absolutely need to create another task, try to guess how much stack space (in words/4-byte packets) it will need instead of just typing in a large-ish number. You can use the define `configMINIMAL_STACK_SIZE` which is currently set to 120 words. ## Controllers Controllers in InfiniTime are singleton objects that can provide access to certain resources to apps. Some of them interface with drivers, others are the driver for the resource. The resources provided don't have to be hardware-based. They are declared in main.cpp and initialized in systemtask/SystemTask.cpp . Some controllers can be passed by reference to apps that need access to the resource (for example vibration motor). From 90fdea29b80016c6d0e6d518853c9251555ea695 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Tue, 5 Oct 2021 19:58:58 +0200 Subject: [PATCH 34/50] Fixed feature request template according to https://github.com/InfiniTimeOrg/InfiniTime/pull/705#issuecomment-933820293 --- .github/ISSUE_TEMPLATE/feature-request.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/feature-request.yaml b/.github/ISSUE_TEMPLATE/feature-request.yaml index 33b059c0..31b5e272 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yaml +++ b/.github/ISSUE_TEMPLATE/feature-request.yaml @@ -1,7 +1,7 @@ name: Feature Request description: File a feature request title: "[Feature Request]: " -labels: ["feature-request"] +labels: ["feature request"] body: - type: markdown attributes: From f1aae6af49c212d98afeb6e86615c6ee90ae771c Mon Sep 17 00:00:00 2001 From: Clemens von Molo Date: Wed, 6 Oct 2021 14:30:16 +0200 Subject: [PATCH 35/50] multiple improvements to code docs --- doc/code/Apps.md | 62 ++++++++++++++++++++++++----------------------- doc/code/Intro.md | 14 +++++------ 2 files changed, 39 insertions(+), 37 deletions(-) diff --git a/doc/code/Apps.md b/doc/code/Apps.md index b19d596d..6b4c383f 100644 --- a/doc/code/Apps.md +++ b/doc/code/Apps.md @@ -4,11 +4,21 @@ This page will teach you: - how to implement your own app ## Theory -Apps are the things you can lauch from the app selection you get by swiping down, but also the app launcher itself or the clock. Settings are also implemented as apps. Most screens you see are their own app, except for apps that have multiple screens (settings launcher, app launcher). +Apps are the things you can launch from the app selection you get by swiping up. +At the moment, settings and even the app launcher itself or the clock are implemented very similarly, this might change in the future though. Every app in InfiniTime is it's own class. An object of the class is created when the app is launched and destroyed when the user exits the app. They run inside the "displayapp" task (briefly discussed [here](./Intro.md)). They are responsible for everything drawn on the screen when they are running. By default, apps only do something (as in a function is executed) when they are created or when a touch event is detected. ## Interface -Every app class is has to be inside the namespace `Pinetime::Applications::Screens` and inherit from `Screen`. The constructor should have at least one parameter `DisplayApp* app`, which it needs for the constructor of its parent class Screen. Other parameters should be references to controllers that the app needs. A deconstructor is needed to clean up LVGL and restore any changes (for example re-enable sleeping). App classes can override `bool OnButtonPushed()`, `bool OnTouchEvent(TouchEvents event)` and `bool OnTouchEvent(uint16_t x, uint16_t y)` to implement their own functionality for those events. If an app only needs to display some text and do something upon a touch screen button press, it does not need to override any of these functions, as LVGL can also handle touch events for you. If your app needs to be updated continuously, yo can do so by adding a `Refresh()` function to your class and calling `lv_task_create` inside the constructor. +Every app class has to be inside the namespace `Pinetime::Applications::Screens` and inherit from `Screen`. The constructor should have at least one parameter `DisplayApp* app`, which it needs for the constructor of its parent class Screen. Other parameters should be references to controllers that the app needs. A deconstructor is needed to clean up LVGL and restore any changes (for example re-enable sleeping). App classes can override `bool OnButtonPushed()`, `bool OnTouchEvent(TouchEvents event)` and `bool OnTouchEvent(uint16_t x, uint16_t y)` to implement their own functionality for those events. If an app only needs to display some text and do something upon a touch screen button press, it does not need to override any of these functions, as LVGL can also handle touch events for you. If you have any doubts, you can always look at how the other apps are doing things. + +### Continuous updating +If your app needs to be updated continuously, yo can do so by adding a `Refresh()` function to your class and calling `lv_task_create` inside the constructor. An example call could look like this:
+`taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);`
+With `taskRefresh` being a member variable of your class and of type `lv_task_t*`. Remember to delete the task again using `lv_task_del`. The function `RefreshTaskCallback` is inherited from screen and just calls your `Refresh` function. + +### Apps with multiple screens +InfiniTime provides a mini-library in [displayapp/screens/ScreenList.h](/src/displayapp/screens/ScreenList.h) which makes it relatively easy to add multiple screens to your app. To use it, #include it in the header file of your app and add a ScreenList member to your class. The template argument should be the number of screens you need. You will also need to add `CreateScreen` functions that return `std::unique_ptr` to your class, one for every screen you have. There are still some things left to to that I won't cover here. To figure them out, have a look at the "apps" ApplicationList, Settings and SystemInfo. + ## Creating your own app A minimal app could look like this:
@@ -16,19 +26,19 @@ MyApp.h: ```cpp #pragma once -#include #include "displayapp/screens/Screen.h" +#include namespace PineTime { - namespace Applications { - namespace Screens { - class MyApp : public Screen { - public: - MyApp(DisplayApp* app); - ~MyApp() override; - } - } + namespace Applications { + namespace Screens { + class MyApp : public Screen { + public: + MyApp(DisplayApp* app); + ~MyApp() override; + } } + } } ``` @@ -40,31 +50,23 @@ MyApp.cpp: using namespace Pinetime::Applications::Screens; MyApp::MyApp(DisplayApp* app) : Screen(app) { - lv_obj_t * container1 = lv_cont_create(lv_scr_act(), nullptr); - 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_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0); - lv_obj_set_pos(container1, 30, 60); - lv_obj_set_width(container1, LV_HOR_RES - 50); - lv_obj_set_height(container1, LV_VER_RES - 60); - lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT); - - lv_obj_t * title = lv_label_create(lv_scr_act(), NULL); - lv_label_set_text_static(title,"My test application"); - lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); - lv_obj_align(title, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 15, 15); + lv_obj_t * title = lv_label_create(lv_scr_act(), NULL); + lv_label_set_text_static(title,"My test application"); + lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); + lv_obj_align(title, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); } MyApp::~MyApp() { - lv_obj_clean(lv_scr_act()); + lv_obj_clean(lv_scr_act()); } ``` -Both of these files should be in displayapp/screens/ or displayapp/screens/settings if it's a setting app. +Both of these files should be in [displayapp/screens/](/src/displayapp/screens/) or [displayapp/screens/settings/](/src/displayapp/screens/settings/) if it's a setting app. -Now we have our very own app, but InfiniTime does not know about it yet. The first step is to include it in the compilation by adding it to CMakeLists.txt . The next step to making it launchable is to give your app an id. To do this, add an entry in the enum class `Pinetime::Applications::Apps`. Name this entry after your app. Add `#include "displayapp/screens/MyApp.h"` to the file displayapp/DisplayApp.cpp . Now, go to the function `DisplayApp::LoadApp` and add another case to the switch statement. The case will be the id you gave your app earlier. If your app needs any additional arguments, this is the place to pass them.
+Now we have our very own app, but InfiniTime does not know about it yet. The first step is to include your MyApp.cpp (or any new cpp files for that matter) in the compilation by adding it to [CMakeLists.txt](/CMakeLists.txt). +The next step to making it launchable is to give your app an id. To do this, add an entry in the enum class `Pinetime::Applications::Apps` ([displayapp/Apps.h](/src/displayapp/Apps.h)). +Name this entry after your app. Add `#include "displayapp/screens/MyApp.h"` to the file [displayapp/DisplayApp.cpp](/src/displayapp/DisplayApp.cpp). Now, go to the function `DisplayApp::LoadApp` and add another case to the switch statement. The case will be the id you gave your app earlier. If your app needs any additional arguments, this is the place to pass them. -If you want your app to be launched from the regular app launcher, go to displayapp/screens/ApplicationList.cpp. Add your app to one of the `CreateScreen` functions, or add another `CreateScreen` function if there are no empty spaces for your app.
-If your app is a setting, do the same procedure in displayapp/screens/settings/Settings.cpp . +If you want your app to be launched from the regular app launcher, go to [displayapp/screens/ApplicationList.cpp](/src/displayapp/screens/ApplicationList.cpp). Add your app to one of the `CreateScreen` functions, or add another `CreateScreen` function if there are no empty spaces for your app.
+If your app is a setting, do the same procedure in [displayapp/screens/settings/Settings.cpp](/src/displayapp/screens/settings/Settings.cpp). You should now be able to [build](../buildAndProgram.md) the firmware and flash it to your PineTime. Yay! diff --git a/doc/code/Intro.md b/doc/code/Intro.md index b7371f0b..87253516 100644 --- a/doc/code/Intro.md +++ b/doc/code/Intro.md @@ -2,20 +2,20 @@ This page is meant to guide you through the source code, so you can find the relevant files for what you're working on. ## FreeRTOS -Infinitime is based on FreeRTOS, a real-time operating system. FreeRTOS provides several quality of life abstractions (for example easy software timers) and most importantly supports multiple tasks. You can sort of imagine them as processes or threads on a full operating system. The main "process" creates at least one task and then starts the FreeRTOS task scheduler. This main "process" is the standard main() function inside main.cpp . The task scheduler is responsible for giving every task enough cpu time. As there is only one core on the SoC of the PineTime, real concurrency is impossible and the scheduler has to swap tasks in and out to emulate it. +Infinitime is based on FreeRTOS, a real-time operating system. FreeRTOS provides several quality of life abstractions (for example easy software timers) and most importantly supports multiple tasks. If you want to read up on real-time operating systems, you can look [here](https://www.freertos.org/implementation/a00002.html) and [here](https://www.freertos.org/features.html). The main "process" creates at least one task and then starts the FreeRTOS task scheduler. This main "process" is the standard main() function inside [main.cpp](/src/main.cpp). The task scheduler is responsible for giving every task enough cpu time. As there is only one core on the SoC of the PineTime, real concurrency is impossible and the scheduler has to swap tasks in and out to emulate it. ### Tasks Tasks are created by calling `xTaskCreate` and passing a function with the signature `void functionName(void*)`. For more info on task creation see the [FreeRTOS Documentation](https://www.freertos.org/a00125.html). -In our case, main calls `systemTask.Start()`, which creates the **"MAIN" task**. The function running inside that task is `SystemTask::Work()`. You may also see this task being referred to as the **work task**. Both functions are located inside systemtask/SystemTask.cpp . `SystemTask::Work()` initializes all the driver and controller objects. It also starts the **task "displayapp"**, which is responsible for launching and running apps, controlling the screen and handling touch events (or forwarding them to the active app). You can find the "displayapp" task inside displayapp/DisplayApp.cpp . -There are also other tasks that are responsible for Bluetooth ("ll" and "ble" inside libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c) and periodic tasks like heartrate measurements (heartratetask/HeartRateTask.cpp).
-While it is possible for you to create your own task when you need it, it is recommended to just add functionality to `SystemTask::Work()` if possible. If you absolutely need to create another task, try to guess how much stack space (in words/4-byte packets) it will need instead of just typing in a large-ish number. You can use the define `configMINIMAL_STACK_SIZE` which is currently set to 120 words. +In our case, main calls `systemTask.Start()`, which creates the **"MAIN" task**. The function running inside that task is `SystemTask::Work()`. You may also see this task being referred to as the **work task**. Both functions are located inside [systemtask/SystemTask.cpp](/src/systemtask/SystemTask.cpp). `SystemTask::Work()` initializes all the driver and controller objects. It also starts the **task "displayapp"**, which is responsible for launching and running apps, controlling the screen and handling touch events (or forwarding them to the active app). You can find the "displayapp" task inside [displayapp/DisplayApp.cpp](/src/displayapp/DisplayApp.cpp). +There are also other tasks that are responsible for Bluetooth ("ll" and "ble" inside [libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c](/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c)) and periodic tasks like heartrate measurements ([heartratetask/HeartRateTask.cpp](/src/heartratetask/HeartRateTask.cpp)).
+While it is possible for you to create your own task when you need it, it is recommended to just add functionality to `SystemTask::Work()` if possible. If you absolutely need to create another task, try to guess how much [stack space](https://www.freertos.org/FAQMem.html#StackSize) (in words/4-byte packets) it will need instead of just typing in a large-ish number. You can use the define `configMINIMAL_STACK_SIZE` which is currently set to 120 words. ## Controllers -Controllers in InfiniTime are singleton objects that can provide access to certain resources to apps. Some of them interface with drivers, others are the driver for the resource. The resources provided don't have to be hardware-based. They are declared in main.cpp and initialized in systemtask/SystemTask.cpp . Some controllers can be passed by reference to apps that need access to the resource (for example vibration motor). -They reside in components inside their own subfolder. +Controllers in InfiniTime are singleton objects that can provide access to certain resources to apps. Some of them interface with drivers, others are the driver for the resource. The resources provided don't have to be hardware-based. They are declared in main.cpp and initialized in [systemtask/SystemTask.cpp](/src/systemtask/SystemTask.cpp). Some controllers can be passed by reference to apps that need access to the resource (for example vibration motor). +They reside in [components/](/src/components/) inside their own subfolder. ## Apps For more detail see the [Apps page](./Apps.md) ## Bluetooth -Header files with short documentation for the functions are inside libs/mynewt-nimble/nimble/host/include/host/ . +Header files with short documentation for the functions are inside [libs/mynewt-nimble/nimble/host/include/host/](/src/libs/mynewt-nimble/nimble/host/include/host/). From 884c89c61cf6568ddbc79346110494aacae1176b Mon Sep 17 00:00:00 2001 From: Clemens von Molo Date: Wed, 6 Oct 2021 18:29:52 +0200 Subject: [PATCH 36/50] minor corrections and notice about ui guidelines in docs --- doc/code/Apps.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/code/Apps.md b/doc/code/Apps.md index 6b4c383f..41c945a8 100644 --- a/doc/code/Apps.md +++ b/doc/code/Apps.md @@ -6,13 +6,13 @@ This page will teach you: ## Theory Apps are the things you can launch from the app selection you get by swiping up. At the moment, settings and even the app launcher itself or the clock are implemented very similarly, this might change in the future though. -Every app in InfiniTime is it's own class. An object of the class is created when the app is launched and destroyed when the user exits the app. They run inside the "displayapp" task (briefly discussed [here](./Intro.md)). They are responsible for everything drawn on the screen when they are running. By default, apps only do something (as in a function is executed) when they are created or when a touch event is detected. +Every app in InfiniTime is it's own class. An instance of the class is created when the app is launched and destroyed when the user exits the app. They run inside the "displayapp" task (briefly discussed [here](./Intro.md)). They are responsible for everything drawn on the screen when they are running. By default, apps only do something (as in a function is executed) when they are created or when a touch event is detected. ## Interface Every app class has to be inside the namespace `Pinetime::Applications::Screens` and inherit from `Screen`. The constructor should have at least one parameter `DisplayApp* app`, which it needs for the constructor of its parent class Screen. Other parameters should be references to controllers that the app needs. A deconstructor is needed to clean up LVGL and restore any changes (for example re-enable sleeping). App classes can override `bool OnButtonPushed()`, `bool OnTouchEvent(TouchEvents event)` and `bool OnTouchEvent(uint16_t x, uint16_t y)` to implement their own functionality for those events. If an app only needs to display some text and do something upon a touch screen button press, it does not need to override any of these functions, as LVGL can also handle touch events for you. If you have any doubts, you can always look at how the other apps are doing things. ### Continuous updating -If your app needs to be updated continuously, yo can do so by adding a `Refresh()` function to your class and calling `lv_task_create` inside the constructor. An example call could look like this:
+If your app needs to be updated continuously, yo can do so by overriding the `Refresh()` function in your class and calling `lv_task_create` inside the constructor. An example call could look like this:
`taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);`
With `taskRefresh` being a member variable of your class and of type `lv_task_t*`. Remember to delete the task again using `lv_task_del`. The function `RefreshTaskCallback` is inherited from screen and just calls your `Refresh` function. @@ -50,8 +50,8 @@ MyApp.cpp: using namespace Pinetime::Applications::Screens; MyApp::MyApp(DisplayApp* app) : Screen(app) { - lv_obj_t * title = lv_label_create(lv_scr_act(), NULL); - lv_label_set_text_static(title,"My test application"); + lv_obj_t* title = lv_label_create(lv_scr_act(), NULL); + lv_label_set_text_static(title, "My test application"); lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); lv_obj_align(title, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); } @@ -70,3 +70,5 @@ If you want your app to be launched from the regular app launcher, go to [displa If your app is a setting, do the same procedure in [displayapp/screens/settings/Settings.cpp](/src/displayapp/screens/settings/Settings.cpp). You should now be able to [build](../buildAndProgram.md) the firmware and flash it to your PineTime. Yay! + +Please remember to pay attention to the [UI guidelines](../ui_guidelines.md) when designing an app that you want to include in mainstream InfiniTime. From c3cc83ae17d7cbdd2707df12e89a600d76e5836d Mon Sep 17 00:00:00 2001 From: Clemens von Molo Date: Fri, 8 Oct 2021 14:59:45 +0200 Subject: [PATCH 37/50] More reasonable line lengths in Apps.md and Intro.md --- doc/code/Apps.md | 56 +++++++++++++++++++++++++++++++++++++---------- doc/code/Intro.md | 33 +++++++++++++++++++++++----- 2 files changed, 71 insertions(+), 18 deletions(-) diff --git a/doc/code/Apps.md b/doc/code/Apps.md index 41c945a8..b3bab042 100644 --- a/doc/code/Apps.md +++ b/doc/code/Apps.md @@ -6,18 +6,40 @@ This page will teach you: ## Theory Apps are the things you can launch from the app selection you get by swiping up. At the moment, settings and even the app launcher itself or the clock are implemented very similarly, this might change in the future though. -Every app in InfiniTime is it's own class. An instance of the class is created when the app is launched and destroyed when the user exits the app. They run inside the "displayapp" task (briefly discussed [here](./Intro.md)). They are responsible for everything drawn on the screen when they are running. By default, apps only do something (as in a function is executed) when they are created or when a touch event is detected. +Every app in InfiniTime is it's own class. +An instance of the class is created when the app is launched and destroyed when the user exits the app. +They run inside the "displayapp" task (briefly discussed [here](./Intro.md)). +Apps are responsible for everything drawn on the screen when they are running. +By default, apps only do something (as in a function is executed) when they are created or when a touch event is detected. ## Interface -Every app class has to be inside the namespace `Pinetime::Applications::Screens` and inherit from `Screen`. The constructor should have at least one parameter `DisplayApp* app`, which it needs for the constructor of its parent class Screen. Other parameters should be references to controllers that the app needs. A deconstructor is needed to clean up LVGL and restore any changes (for example re-enable sleeping). App classes can override `bool OnButtonPushed()`, `bool OnTouchEvent(TouchEvents event)` and `bool OnTouchEvent(uint16_t x, uint16_t y)` to implement their own functionality for those events. If an app only needs to display some text and do something upon a touch screen button press, it does not need to override any of these functions, as LVGL can also handle touch events for you. If you have any doubts, you can always look at how the other apps are doing things. +Every app class has to be inside the namespace `Pinetime::Applications::Screens` and inherit from `Screen`. +The constructor should have at least one parameter `DisplayApp* app`, which it needs for the constructor of its parent class Screen. +Other parameters should be references to controllers that the app needs. +A destructor is needed to clean up LVGL and restore any changes (for example re-enable sleeping). +App classes can override `bool OnButtonPushed()`, `bool OnTouchEvent(TouchEvents event)` and `bool OnTouchEvent(uint16_t x, uint16_t y)` to implement their own functionality for those events. +If an app only needs to display some text and do something upon a touch screen button press, +it does not need to override any of these functions, as LVGL can also handle touch events for you. +If you have any doubts, you can always look at how the other apps are doing things. ### Continuous updating -If your app needs to be updated continuously, yo can do so by overriding the `Refresh()` function in your class and calling `lv_task_create` inside the constructor. An example call could look like this:
+If your app needs to be updated continuously, yo can do so by overriding the `Refresh()` function in your class +and calling `lv_task_create` inside the constructor. +An example call could look like this:
`taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);`
-With `taskRefresh` being a member variable of your class and of type `lv_task_t*`. Remember to delete the task again using `lv_task_del`. The function `RefreshTaskCallback` is inherited from screen and just calls your `Refresh` function. +With `taskRefresh` being a member variable of your class and of type `lv_task_t*`. +Remember to delete the task again using `lv_task_del`. +The function `RefreshTaskCallback` is inherited from screen and just calls your `Refresh` function. ### Apps with multiple screens -InfiniTime provides a mini-library in [displayapp/screens/ScreenList.h](/src/displayapp/screens/ScreenList.h) which makes it relatively easy to add multiple screens to your app. To use it, #include it in the header file of your app and add a ScreenList member to your class. The template argument should be the number of screens you need. You will also need to add `CreateScreen` functions that return `std::unique_ptr` to your class, one for every screen you have. There are still some things left to to that I won't cover here. To figure them out, have a look at the "apps" ApplicationList, Settings and SystemInfo. +InfiniTime provides a mini-library in [displayapp/screens/ScreenList.h](/src/displayapp/screens/ScreenList.h) +which makes it relatively easy to add multiple screens to your app. +To use it, #include it in the header file of your app and add a ScreenList member to your class. +The template argument should be the number of screens you need. +You will also need to add `CreateScreen` functions that return `std::unique_ptr` +to your class, one for every screen you have. +There are still some things left to to that I won't cover here. +To figure them out, have a look at the "apps" ApplicationList, Settings and SystemInfo. ## Creating your own app @@ -60,15 +82,25 @@ MyApp::~MyApp() { lv_obj_clean(lv_scr_act()); } ``` -Both of these files should be in [displayapp/screens/](/src/displayapp/screens/) or [displayapp/screens/settings/](/src/displayapp/screens/settings/) if it's a setting app. +Both of these files should be in [displayapp/screens/](/src/displayapp/screens/) +or [displayapp/screens/settings/](/src/displayapp/screens/settings/) if it's a setting app. -Now we have our very own app, but InfiniTime does not know about it yet. The first step is to include your MyApp.cpp (or any new cpp files for that matter) in the compilation by adding it to [CMakeLists.txt](/CMakeLists.txt). -The next step to making it launchable is to give your app an id. To do this, add an entry in the enum class `Pinetime::Applications::Apps` ([displayapp/Apps.h](/src/displayapp/Apps.h)). -Name this entry after your app. Add `#include "displayapp/screens/MyApp.h"` to the file [displayapp/DisplayApp.cpp](/src/displayapp/DisplayApp.cpp). Now, go to the function `DisplayApp::LoadApp` and add another case to the switch statement. The case will be the id you gave your app earlier. If your app needs any additional arguments, this is the place to pass them. +Now we have our very own app, but InfiniTime does not know about it yet. +The first step is to include your MyApp.cpp (or any new cpp files for that matter) +in the compilation by adding it to [CMakeLists.txt](/CMakeLists.txt). +The next step to making it launchable is to give your app an id. +To do this, add an entry in the enum class `Pinetime::Applications::Apps` ([displayapp/Apps.h](/src/displayapp/Apps.h)). +Name this entry after your app. Add `#include "displayapp/screens/MyApp.h"` to the file [displayapp/DisplayApp.cpp](/src/displayapp/DisplayApp.cpp). +Now, go to the function `DisplayApp::LoadApp` and add another case to the switch statement. +The case will be the id you gave your app earlier. +If your app needs any additional arguments, this is the place to pass them. -If you want your app to be launched from the regular app launcher, go to [displayapp/screens/ApplicationList.cpp](/src/displayapp/screens/ApplicationList.cpp). Add your app to one of the `CreateScreen` functions, or add another `CreateScreen` function if there are no empty spaces for your app.
+If you want your app to be launched from the regular app launcher, go to [displayapp/screens/ApplicationList.cpp](/src/displayapp/screens/ApplicationList.cpp). +Add your app to one of the `CreateScreen` functions, or add another `CreateScreen` function if there are no empty spaces for your app.
If your app is a setting, do the same procedure in [displayapp/screens/settings/Settings.cpp](/src/displayapp/screens/settings/Settings.cpp). -You should now be able to [build](../buildAndProgram.md) the firmware and flash it to your PineTime. Yay! +You should now be able to [build](../buildAndProgram.md) the firmware +and flash it to your PineTime. Yay! -Please remember to pay attention to the [UI guidelines](../ui_guidelines.md) when designing an app that you want to include in mainstream InfiniTime. +Please remember to pay attention to the [UI guidelines](../ui_guidelines.md) +when designing an app that you want to include in mainstream InfiniTime. diff --git a/doc/code/Intro.md b/doc/code/Intro.md index 87253516..762102fe 100644 --- a/doc/code/Intro.md +++ b/doc/code/Intro.md @@ -2,16 +2,37 @@ This page is meant to guide you through the source code, so you can find the relevant files for what you're working on. ## FreeRTOS -Infinitime is based on FreeRTOS, a real-time operating system. FreeRTOS provides several quality of life abstractions (for example easy software timers) and most importantly supports multiple tasks. If you want to read up on real-time operating systems, you can look [here](https://www.freertos.org/implementation/a00002.html) and [here](https://www.freertos.org/features.html). The main "process" creates at least one task and then starts the FreeRTOS task scheduler. This main "process" is the standard main() function inside [main.cpp](/src/main.cpp). The task scheduler is responsible for giving every task enough cpu time. As there is only one core on the SoC of the PineTime, real concurrency is impossible and the scheduler has to swap tasks in and out to emulate it. +Infinitime is based on FreeRTOS, a real-time operating system. +FreeRTOS provides several quality of life abstractions (for example easy software timers) +and most importantly supports multiple tasks. +If you want to read up on real-time operating systems, you can look [here](https://www.freertos.org/implementation/a00002.html) and [here](https://www.freertos.org/features.html). +The main "process" creates at least one task and then starts the FreeRTOS task scheduler. +This main "process" is the standard main() function inside [main.cpp](/src/main.cpp). +The task scheduler is responsible for giving every task enough cpu time. +As there is only one core on the SoC of the PineTime, real concurrency is impossible and the scheduler has to swap tasks in and out to emulate it. ### Tasks -Tasks are created by calling `xTaskCreate` and passing a function with the signature `void functionName(void*)`. For more info on task creation see the [FreeRTOS Documentation](https://www.freertos.org/a00125.html). -In our case, main calls `systemTask.Start()`, which creates the **"MAIN" task**. The function running inside that task is `SystemTask::Work()`. You may also see this task being referred to as the **work task**. Both functions are located inside [systemtask/SystemTask.cpp](/src/systemtask/SystemTask.cpp). `SystemTask::Work()` initializes all the driver and controller objects. It also starts the **task "displayapp"**, which is responsible for launching and running apps, controlling the screen and handling touch events (or forwarding them to the active app). You can find the "displayapp" task inside [displayapp/DisplayApp.cpp](/src/displayapp/DisplayApp.cpp). -There are also other tasks that are responsible for Bluetooth ("ll" and "ble" inside [libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c](/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c)) and periodic tasks like heartrate measurements ([heartratetask/HeartRateTask.cpp](/src/heartratetask/HeartRateTask.cpp)).
-While it is possible for you to create your own task when you need it, it is recommended to just add functionality to `SystemTask::Work()` if possible. If you absolutely need to create another task, try to guess how much [stack space](https://www.freertos.org/FAQMem.html#StackSize) (in words/4-byte packets) it will need instead of just typing in a large-ish number. You can use the define `configMINIMAL_STACK_SIZE` which is currently set to 120 words. +Tasks are created by calling `xTaskCreate` and passing a function with the signature `void functionName(void*)`. +For more info on task creation see the [FreeRTOS Documentation](https://www.freertos.org/a00125.html). +In our case, main calls `systemTask.Start()`, which creates the **"MAIN" task**. +The function running inside that task is `SystemTask::Work()`. +You may also see this task being referred to as the **work task**. +Both functions are located inside [systemtask/SystemTask.cpp](/src/systemtask/SystemTask.cpp). `SystemTask::Work()` initializes all the driver and controller objects. +It also starts the **task "displayapp"**, which is responsible for launching and running apps, controlling the screen and handling touch events (or forwarding them to the active app). +You can find the "displayapp" task inside [displayapp/DisplayApp.cpp](/src/displayapp/DisplayApp.cpp). +There are also other tasks that are responsible for Bluetooth ("ll" and "ble" inside [libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c](/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c)) +and periodic tasks like heartrate measurements ([heartratetask/HeartRateTask.cpp](/src/heartratetask/HeartRateTask.cpp)).
+While it is possible for you to create your own task when you need it, it is recommended to just add functionality to `SystemTask::Work()` if possible. +If you absolutely need to create another task, try to guess how much [stack space](https://www.freertos.org/FAQMem.html#StackSize) (in words/4-byte packets) +it will need instead of just typing in a large-ish number. +You can use the define `configMINIMAL_STACK_SIZE` which is currently set to 120 words. ## Controllers -Controllers in InfiniTime are singleton objects that can provide access to certain resources to apps. Some of them interface with drivers, others are the driver for the resource. The resources provided don't have to be hardware-based. They are declared in main.cpp and initialized in [systemtask/SystemTask.cpp](/src/systemtask/SystemTask.cpp). Some controllers can be passed by reference to apps that need access to the resource (for example vibration motor). +Controllers in InfiniTime are singleton objects that can provide access to certain resources to apps. +Some of them interface with drivers, others are the driver for the resource. +The resources provided don't have to be hardware-based. +They are declared in main.cpp and initialized in [systemtask/SystemTask.cpp](/src/systemtask/SystemTask.cpp). +Some controllers can be passed by reference to apps that need access to the resource (for example vibration motor). They reside in [components/](/src/components/) inside their own subfolder. ## Apps From fc2241fbf47d90510c8c01c3666f9fae5e56754b Mon Sep 17 00:00:00 2001 From: hubmartin Date: Fri, 8 Oct 2021 16:53:49 +0200 Subject: [PATCH 38/50] Add wake on charge event --- src/systemtask/SystemTask.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 5441c162..59c73d96 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -347,6 +347,9 @@ void SystemTask::Work() { case Messages::OnChargingEvent: batteryController.Update(); motorController.RunForDuration(15); + if (isSleeping && !isWakingUp) { + GoToRunning(); + } break; case Messages::MeasureBatteryTimerExpired: sendBatteryNotification = true; From 98e74a32179420a74527532c902516db28795c29 Mon Sep 17 00:00:00 2001 From: hubmartin Date: Fri, 8 Oct 2021 17:01:27 +0200 Subject: [PATCH 39/50] Call also ReloadIdleTimer --- src/systemtask/SystemTask.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 59c73d96..09c7e88d 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -347,6 +347,7 @@ void SystemTask::Work() { case Messages::OnChargingEvent: batteryController.Update(); motorController.RunForDuration(15); + ReloadIdleTimer(); if (isSleeping && !isWakingUp) { GoToRunning(); } From 4f7c675ae3dac0a3d47a0c58d9481f080d53092d Mon Sep 17 00:00:00 2001 From: Avamander Date: Fri, 8 Oct 2021 18:38:45 +0300 Subject: [PATCH 40/50] Removed the title prefix --- .github/ISSUE_TEMPLATE/feature-request.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/feature-request.yaml b/.github/ISSUE_TEMPLATE/feature-request.yaml index 31b5e272..092ef909 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yaml +++ b/.github/ISSUE_TEMPLATE/feature-request.yaml @@ -1,6 +1,6 @@ name: Feature Request description: File a feature request -title: "[Feature Request]: " +title: "" labels: ["feature request"] body: - type: markdown From 516f9de3e4926149d0cdae0d6e320b4bbbd072e2 Mon Sep 17 00:00:00 2001 From: coxtor Date: Fri, 8 Oct 2021 20:05:39 +0200 Subject: [PATCH 41/50] Add configuration instructions for Ubuntu devcontainers --- doc/buildWithVScode.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/doc/buildWithVScode.md b/doc/buildWithVScode.md index c1df17b7..23c97145 100644 --- a/doc/buildWithVScode.md +++ b/doc/buildWithVScode.md @@ -36,7 +36,17 @@ Using the [Remote-Containers](https://marketplace.visualstudio.com/items?itemNam More documentation is available in the [readme in .devcontainer](.devcontainer/readme.md) - +### DevContainer on Ubuntu +To use the DevContainer configuration on Ubuntu based systems two changes need to be made: + +1. Modify the file ``.devcontainer/devcontainer.json`` and add the argument ``"--net=host"`` to the ``"runArgs"`` parameter making the line look like this: +`` "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", "seccomp=unconfined", "--net=host"], +`` +2. Modify the file ``.vscode/launch.json`` and change the argument of ``"gdbTarget"`` to ``"127.0.0.1:3333"``, making the line look like: +``"gdbTarget": "127.0.0.1:3333",`` +3. To start debugging launch openocd on your host system with the appropriate configuration, for example with a stlink-v2 the command is: +``openocd -f interface/stlink.cfg -f target/nrf52.cfg``. This launches openocd with the default ports ``3333``, ``4444`` and ``6666``. +4. In VsCode go to the Debug pane on the left of the screen and select the configuration ``Debug - Openocd docker Remote`` and hit the play button on the left. From 1777b9dee8f1189df29f627707b970995f0d4afe Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Sat, 9 Oct 2021 13:39:27 +0300 Subject: [PATCH 42/50] Don't measure and notify percentage on charging event. --- src/components/battery/BatteryController.cpp | 6 +++++- src/components/battery/BatteryController.h | 3 ++- src/systemtask/SystemTask.cpp | 7 ++++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/components/battery/BatteryController.cpp b/src/components/battery/BatteryController.cpp index 0ef4ff1a..e807f033 100644 --- a/src/components/battery/BatteryController.cpp +++ b/src/components/battery/BatteryController.cpp @@ -13,7 +13,7 @@ Battery::Battery() { nrf_gpio_cfg_input(PinMap::Charging, static_cast GPIO_PIN_CNF_PULL_Disabled); } -void Battery::Update() { +void Battery::ReadPowerState() { isCharging = !nrf_gpio_pin_read(PinMap::Charging); isPowerPresent = !nrf_gpio_pin_read(PinMap::PowerPresent); @@ -22,6 +22,10 @@ void Battery::Update() { } else if (!isPowerPresent) { isFull = false; } +} + +void Battery::MeasureVoltage() { + ReadPowerState(); if (isReading) { return; diff --git a/src/components/battery/BatteryController.h b/src/components/battery/BatteryController.h index 55c26309..5a7394c4 100644 --- a/src/components/battery/BatteryController.h +++ b/src/components/battery/BatteryController.h @@ -10,7 +10,8 @@ namespace Pinetime { public: Battery(); - void Update(); + void ReadPowerState(); + void MeasureVoltage(); void Register(System::SystemTask* systemTask); uint8_t PercentRemaining() const { diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 0a53101f..ec8b5e4e 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -136,7 +136,6 @@ void SystemTask::Work() { touchPanel.Init(); dateTimeController.Register(this); batteryController.Register(this); - batteryController.Update(); motorController.Init(); motionSensor.SoftReset(); timerController.Register(this); @@ -194,6 +193,8 @@ void SystemTask::Work() { nrf_gpio_cfg_sense_input(PinMap::PowerPresent, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH); } + batteryController.MeasureVoltage(); + idleTimer = xTimerCreate("idleTimer", pdMS_TO_TICKS(2000), pdFALSE, this, IdleTimerCallback); dimTimer = xTimerCreate("dimTimer", pdMS_TO_TICKS(settingsController.GetScreenTimeOut() - 2000), pdFALSE, this, DimTimerCallback); measureBatteryTimer = xTimerCreate("measureBattery", batteryMeasurementPeriod, pdTRUE, this, MeasureBatteryTimerCallback); @@ -345,11 +346,11 @@ void SystemTask::Work() { stepCounterMustBeReset = true; break; case Messages::OnChargingEvent: - batteryController.Update(); + batteryController.ReadPowerState(); motorController.RunForDuration(15); break; case Messages::MeasureBatteryTimerExpired: - batteryController.Update(); + batteryController.MeasureVoltage(); break; case Messages::BatteryPercentageUpdated: nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining()); From 977faebcb8b26212e0868b30e1af5c38076ff6cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Sat, 9 Oct 2021 21:17:59 +0200 Subject: [PATCH 43/50] Remove call to `batteryController.Update();` which was replaced by `batteryController.MeasureVoltage()`. --- src/systemtask/SystemTask.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 86740532..12388290 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -191,9 +191,6 @@ void SystemTask::Work() { nrfx_gpiote_in_init(PinMap::PowerPresent, &pinConfig, nrfx_gpiote_evt_handler); nrfx_gpiote_in_event_enable(PinMap::PowerPresent, true); - // Update controller based on current gpio pin state, needs to be called after gpio config - batteryController.Update(); - batteryController.MeasureVoltage(); idleTimer = xTimerCreate("idleTimer", pdMS_TO_TICKS(2000), pdFALSE, this, IdleTimerCallback); From 7cbd56896aebcebaacae864403b91473986782a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Sun, 10 Oct 2021 16:08:19 +0200 Subject: [PATCH 44/50] DateTimeController : remove unused methods and variables. --- .../datetime/DateTimeController.cpp | 70 +++---------------- src/components/datetime/DateTimeController.h | 20 ------ 2 files changed, 9 insertions(+), 81 deletions(-) diff --git a/src/components/datetime/DateTimeController.cpp b/src/components/datetime/DateTimeController.cpp index 26b69a27..e9c5d870 100644 --- a/src/components/datetime/DateTimeController.cpp +++ b/src/components/datetime/DateTimeController.cpp @@ -5,6 +5,12 @@ using namespace Pinetime::Controllers; +namespace { + char const* DaysStringShort[] = {"--", "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"}; + char const* MonthsString[] = {"--", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"}; + char const* MonthsStringLow[] = {"--", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; +} + void DateTime::SetCurrentTime(std::chrono::time_point t) { this->currentDateTime = t; UpdateTime(previousSystickCounter); // Update internal state without updating the time @@ -80,76 +86,18 @@ void DateTime::UpdateTime(uint32_t systickCounter) { } const char* DateTime::MonthShortToString() { - return DateTime::MonthsString[static_cast(month)]; -} - -const char* DateTime::MonthShortToStringLow() { - return DateTime::MonthsStringLow[static_cast(month)]; -} - -const char* DateTime::MonthsToStringLow() { - return DateTime::MonthsLow[static_cast(month)]; -} - -const char* DateTime::DayOfWeekToString() { - return DateTime::DaysString[static_cast(dayOfWeek)]; + return MonthsString[static_cast(month)]; } const char* DateTime::DayOfWeekShortToString() { - return DateTime::DaysStringShort[static_cast(dayOfWeek)]; -} - -const char* DateTime::DayOfWeekToStringLow() { - return DateTime::DaysStringLow[static_cast(dayOfWeek)]; -} - -const char* DateTime::DayOfWeekShortToStringLow() { - return DateTime::DaysStringShortLow[static_cast(dayOfWeek)]; -} - -const char* DateTime::MonthShortToString(Months month) { - return DateTime::MonthsString[static_cast(month)]; + return DaysStringShort[static_cast(dayOfWeek)]; } const char* DateTime::MonthShortToStringLow(Months month) { - return DateTime::MonthsStringLow[static_cast(month)]; -} - -const char* DateTime::MonthsToStringLow(Months month) { - return DateTime::MonthsLow[static_cast(month)]; -} - -const char* DateTime::DayOfWeekToString(Days dayOfWeek) { - return DateTime::DaysString[static_cast(dayOfWeek)]; -} - -const char* DateTime::DayOfWeekShortToString(Days dayOfWeek) { - return DateTime::DaysStringShort[static_cast(dayOfWeek)]; -} - -const char* DateTime::DayOfWeekToStringLow(Days dayOfWeek) { - return DateTime::DaysStringLow[static_cast(dayOfWeek)]; -} - -const char* DateTime::DayOfWeekShortToStringLow(Days dayOfWeek) { - return DateTime::DaysStringShortLow[static_cast(dayOfWeek)]; + return MonthsStringLow[static_cast(month)]; } void DateTime::Register(Pinetime::System::SystemTask* systemTask) { this->systemTask = systemTask; } -char const* DateTime::DaysStringLow[] = {"--", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}; - -char const* DateTime::DaysStringShortLow[] = {"--", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"}; - -char const* DateTime::DaysStringShort[] = {"--", "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"}; - -char const* DateTime::DaysString[] = {"--", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"}; - -char const* DateTime::MonthsString[] = {"--", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"}; - -char const* DateTime::MonthsStringLow[] = {"--", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; - -char const* DateTime::MonthsLow[] = { - "--", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; diff --git a/src/components/datetime/DateTimeController.h b/src/components/datetime/DateTimeController.h index c5f218d8..77ed68e8 100644 --- a/src/components/datetime/DateTimeController.h +++ b/src/components/datetime/DateTimeController.h @@ -59,20 +59,8 @@ namespace Pinetime { } const char* MonthShortToString(); - const char* MonthShortToStringLow(); - const char* MonthsToStringLow(); - const char* DayOfWeekToString(); const char* DayOfWeekShortToString(); - const char* DayOfWeekToStringLow(); - const char* DayOfWeekShortToStringLow(); - - static const char* MonthShortToString(Months month); static const char* MonthShortToStringLow(Months month); - static const char* MonthsToStringLow(Months month); - static const char* DayOfWeekToString(Days dayOfWeek); - static const char* DayOfWeekShortToString(Days dayOfWeek); - static const char* DayOfWeekToStringLow(Days dayOfWeek); - static const char* DayOfWeekShortToStringLow(Days dayOfWeek); std::chrono::time_point CurrentDateTime() const { return currentDateTime; @@ -99,14 +87,6 @@ namespace Pinetime { bool isMidnightAlreadyNotified = false; System::SystemTask* systemTask = nullptr; - - static char const* DaysString[]; - static char const* DaysStringShort[]; - static char const* DaysStringLow[]; - static char const* DaysStringShortLow[]; - static char const* MonthsString[]; - static char const* MonthsStringLow[]; - static char const* MonthsLow[]; }; } } From f2357b36e5142f3f143f466cac62aafcf7261d5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Sun, 10 Oct 2021 16:18:14 +0200 Subject: [PATCH 45/50] Setting SetDate/SetTime : replace #defines by constexpr variables, NULL by nullptr and other small cleanings. --- .../screens/settings/SettingSetDate.cpp | 72 ++++++++----------- .../screens/settings/SettingSetDate.h | 5 +- .../screens/settings/SettingSetTime.cpp | 63 ++++++++-------- .../screens/settings/SettingSetTime.h | 6 +- 4 files changed, 61 insertions(+), 85 deletions(-) diff --git a/src/displayapp/screens/settings/SettingSetDate.cpp b/src/displayapp/screens/settings/SettingSetDate.cpp index 705b7a95..ba3413ef 100644 --- a/src/displayapp/screens/settings/SettingSetDate.cpp +++ b/src/displayapp/screens/settings/SettingSetDate.cpp @@ -5,33 +5,31 @@ #include "displayapp/DisplayApp.h" #include "displayapp/screens/Symbols.h" -#define POS_X_DAY -72 -#define POS_X_MONTH 0 -#define POS_X_YEAR 72 -#define POS_Y_PLUS -50 -#define POS_Y_TEXT -6 -#define POS_Y_MINUS 40 - using namespace Pinetime::Applications::Screens; namespace { - static void event_handler(lv_obj_t * obj, lv_event_t event) { - SettingSetDate* screen = static_cast(obj->user_data); + constexpr int16_t POS_X_DAY = -72; + constexpr int16_t POS_X_MONTH = 0; + constexpr int16_t POS_X_YEAR = 72; + constexpr int16_t POS_Y_PLUS = -50; + constexpr int16_t POS_Y_TEXT = -6; + constexpr int16_t POS_Y_MINUS = 40; + + void event_handler(lv_obj_t * obj, lv_event_t event) { + auto* screen = static_cast(obj->user_data); screen->HandleButtonPress(obj, event); } } -SettingSetDate::SettingSetDate( - Pinetime::Applications::DisplayApp *app, Pinetime::Controllers::DateTime &dateTimeController) : +SettingSetDate::SettingSetDate(Pinetime::Applications::DisplayApp *app, Pinetime::Controllers::DateTime &dateTimeController) : Screen(app), - dateTimeController {dateTimeController} -{ - lv_obj_t * title = lv_label_create(lv_scr_act(), NULL); + dateTimeController {dateTimeController} { + lv_obj_t * title = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(title, "Set current date"); lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); lv_obj_align(title, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 15, 15); - lv_obj_t * icon = lv_label_create(lv_scr_act(), NULL); + lv_obj_t * icon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); lv_label_set_text_static(icon, Symbols::clock); @@ -39,14 +37,14 @@ SettingSetDate::SettingSetDate( lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); dayValue = static_cast(dateTimeController.Day()); - lblDay = lv_label_create(lv_scr_act(), NULL); + lblDay = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_fmt(lblDay, "%d", dayValue); lv_label_set_align(lblDay, LV_LABEL_ALIGN_CENTER); lv_obj_align(lblDay, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_TEXT); lv_obj_set_auto_realign(lblDay, true); monthValue = static_cast(dateTimeController.Month()); - lblMonth = lv_label_create(lv_scr_act(), NULL); + lblMonth = lv_label_create(lv_scr_act(), nullptr); UpdateMonthLabel(); lv_label_set_align(lblMonth, LV_LABEL_ALIGN_CENTER); lv_obj_align(lblMonth, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MONTH, POS_Y_TEXT); @@ -55,55 +53,55 @@ SettingSetDate::SettingSetDate( yearValue = static_cast(dateTimeController.Year()); if (yearValue < 2021) yearValue = 2021; - lblYear = lv_label_create(lv_scr_act(), NULL); + lblYear = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_fmt(lblYear, "%d", yearValue); lv_label_set_align(lblYear, LV_LABEL_ALIGN_CENTER); lv_obj_align(lblYear, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_TEXT); lv_obj_set_auto_realign(lblYear, true); - btnDayPlus = lv_btn_create(lv_scr_act(), NULL); + btnDayPlus = lv_btn_create(lv_scr_act(), nullptr); btnDayPlus->user_data = this; lv_obj_set_size(btnDayPlus, 50, 40); lv_obj_align(btnDayPlus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_PLUS); lv_obj_set_style_local_value_str(btnDayPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); lv_obj_set_event_cb(btnDayPlus, event_handler); - btnDayMinus = lv_btn_create(lv_scr_act(), NULL); + btnDayMinus = lv_btn_create(lv_scr_act(), nullptr); btnDayMinus->user_data = this; lv_obj_set_size(btnDayMinus, 50, 40); lv_obj_align(btnDayMinus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_DAY, POS_Y_MINUS); lv_obj_set_style_local_value_str(btnDayMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); lv_obj_set_event_cb(btnDayMinus, event_handler); - btnMonthPlus = lv_btn_create(lv_scr_act(), NULL); + btnMonthPlus = lv_btn_create(lv_scr_act(), nullptr); btnMonthPlus->user_data = this; lv_obj_set_size(btnMonthPlus, 50, 40); lv_obj_align(btnMonthPlus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MONTH, POS_Y_PLUS); lv_obj_set_style_local_value_str(btnMonthPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); lv_obj_set_event_cb(btnMonthPlus, event_handler); - btnMonthMinus = lv_btn_create(lv_scr_act(), NULL); + btnMonthMinus = lv_btn_create(lv_scr_act(), nullptr); btnMonthMinus->user_data = this; lv_obj_set_size(btnMonthMinus, 50, 40); lv_obj_align(btnMonthMinus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MONTH, POS_Y_MINUS); lv_obj_set_style_local_value_str(btnMonthMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); lv_obj_set_event_cb(btnMonthMinus, event_handler); - btnYearPlus = lv_btn_create(lv_scr_act(), NULL); + btnYearPlus = lv_btn_create(lv_scr_act(), nullptr); btnYearPlus->user_data = this; lv_obj_set_size(btnYearPlus, 50, 40); lv_obj_align(btnYearPlus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_PLUS); lv_obj_set_style_local_value_str(btnYearPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); lv_obj_set_event_cb(btnYearPlus, event_handler); - btnYearMinus = lv_btn_create(lv_scr_act(), NULL); + btnYearMinus = lv_btn_create(lv_scr_act(), nullptr); btnYearMinus->user_data = this; lv_obj_set_size(btnYearMinus, 50, 40); lv_obj_align(btnYearMinus, lv_scr_act(), LV_ALIGN_CENTER, POS_X_YEAR, POS_Y_MINUS); lv_obj_set_style_local_value_str(btnYearMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); lv_obj_set_event_cb(btnYearMinus, event_handler); - btnSetTime = lv_btn_create(lv_scr_act(), NULL); + btnSetTime = lv_btn_create(lv_scr_act(), nullptr); btnSetTime->user_data = this; lv_obj_set_size(btnSetTime, 120, 48); lv_obj_align(btnSetTime, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); @@ -116,7 +114,6 @@ SettingSetDate::~SettingSetDate() { } void SettingSetDate::HandleButtonPress(lv_obj_t *object, lv_event_t event) { - if (event != LV_EVENT_CLICKED) return; @@ -126,43 +123,37 @@ void SettingSetDate::HandleButtonPress(lv_obj_t *object, lv_event_t event) { dayValue = 1; lv_label_set_text_fmt(lblDay, "%d", dayValue); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - } - else if (object == btnDayMinus) { + } else if (object == btnDayMinus) { dayValue--; if (dayValue < 1) dayValue = MaximumDayOfMonth(); lv_label_set_text_fmt(lblDay, "%d", dayValue); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - } - else if (object == btnMonthPlus) { + } else if (object == btnMonthPlus) { monthValue++; if (monthValue > 12) monthValue = 1; UpdateMonthLabel(); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); CheckDay(); - } - else if (object == btnMonthMinus) { + } else if (object == btnMonthMinus) { monthValue--; if (monthValue < 1) monthValue = 12; UpdateMonthLabel(); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); CheckDay(); - } - else if (object == btnYearPlus) { + } else if (object == btnYearPlus) { yearValue++; lv_label_set_text_fmt(lblYear, "%d", yearValue); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); CheckDay(); - } - else if (object == btnYearMinus) { + } else if (object == btnYearMinus) { yearValue--; lv_label_set_text_fmt(lblYear, "%d", yearValue); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); CheckDay(); - } - else if (object == btnSetTime) { + } else if (object == btnSetTime) { NRF_LOG_INFO("Setting date (manually) to %04d-%02d-%02d", yearValue, monthValue, dayValue); dateTimeController.SetTime(static_cast(yearValue), static_cast(monthValue), @@ -202,7 +193,6 @@ void SettingSetDate::CheckDay() { } void SettingSetDate::UpdateMonthLabel() { - lv_label_set_text_static(lblMonth, - Pinetime::Controllers::DateTime::MonthShortToStringLow(static_cast(monthValue))); + lv_label_set_text_static( + lblMonth, Pinetime::Controllers::DateTime::MonthShortToStringLow(static_cast(monthValue))); } - diff --git a/src/displayapp/screens/settings/SettingSetDate.h b/src/displayapp/screens/settings/SettingSetDate.h index 0f6317d3..477337ff 100644 --- a/src/displayapp/screens/settings/SettingSetDate.h +++ b/src/displayapp/screens/settings/SettingSetDate.h @@ -6,10 +6,8 @@ #include "displayapp/screens/Screen.h" namespace Pinetime { - namespace Applications { namespace Screens { - class SettingSetDate : public Screen{ public: SettingSetDate(DisplayApp* app, Pinetime::Controllers::DateTime &dateTimeController); @@ -17,8 +15,7 @@ namespace Pinetime { void HandleButtonPress(lv_obj_t *object, lv_event_t event); - private: - + private: Controllers::DateTime& dateTimeController; int dayValue; diff --git a/src/displayapp/screens/settings/SettingSetTime.cpp b/src/displayapp/screens/settings/SettingSetTime.cpp index 7083b80f..194bf5eb 100644 --- a/src/displayapp/screens/settings/SettingSetTime.cpp +++ b/src/displayapp/screens/settings/SettingSetTime.cpp @@ -5,34 +5,32 @@ #include "displayapp/DisplayApp.h" #include "displayapp/screens/Symbols.h" -#define POS_X_HOURS -72 -#define POS_X_MINUTES 0 -#define POS_X_SECONDS 72 -#define POS_Y_PLUS -50 -#define POS_Y_TEXT -6 -#define POS_Y_MINUS 40 -#define OFS_Y_COLON -2 - using namespace Pinetime::Applications::Screens; namespace { - static void event_handler(lv_obj_t * obj, lv_event_t event) { - SettingSetTime* screen = static_cast(obj->user_data); + constexpr int16_t POS_X_HOURS = -72; + constexpr int16_t POS_X_MINUTES = 0; + constexpr int16_t POS_X_SECONDS = 72; + constexpr int16_t POS_Y_PLUS = -50; + constexpr int16_t POS_Y_TEXT = -6; + constexpr int16_t POS_Y_MINUS = 40; + constexpr int16_t OFS_Y_COLON = -2; + + void event_handler(lv_obj_t * obj, lv_event_t event) { + auto* screen = static_cast(obj->user_data); screen->HandleButtonPress(obj, event); } } -SettingSetTime::SettingSetTime( - Pinetime::Applications::DisplayApp *app, Pinetime::Controllers::DateTime &dateTimeController) : +SettingSetTime::SettingSetTime(Pinetime::Applications::DisplayApp *app, Pinetime::Controllers::DateTime &dateTimeController) : Screen(app), - dateTimeController {dateTimeController} -{ - lv_obj_t * title = lv_label_create(lv_scr_act(), NULL); + dateTimeController {dateTimeController} { + lv_obj_t * title = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(title, "Set current time"); lv_label_set_align(title, LV_LABEL_ALIGN_CENTER); lv_obj_align(title, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 15, 15); - lv_obj_t * icon = lv_label_create(lv_scr_act(), NULL); + lv_obj_t * icon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE); lv_label_set_text_static(icon, Symbols::clock); @@ -40,68 +38,68 @@ SettingSetTime::SettingSetTime( lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); hoursValue = static_cast(dateTimeController.Hours()); - lblHours = lv_label_create(lv_scr_act(), NULL); + lblHours = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(lblHours, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_fmt(lblHours, "%02d", hoursValue); lv_label_set_align(lblHours, LV_LABEL_ALIGN_CENTER); lv_obj_align(lblHours, lv_scr_act(), LV_ALIGN_CENTER, POS_X_HOURS, POS_Y_TEXT); lv_obj_set_auto_realign(lblHours, true); - lv_obj_t * lblColon1 = lv_label_create(lv_scr_act(), NULL); + lv_obj_t * lblColon1 = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(lblColon1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_static(lblColon1, ":"); lv_label_set_align(lblColon1, LV_LABEL_ALIGN_CENTER); lv_obj_align(lblColon1, lv_scr_act(), LV_ALIGN_CENTER, (POS_X_HOURS + POS_X_MINUTES) / 2, POS_Y_TEXT + OFS_Y_COLON); minutesValue = static_cast(dateTimeController.Minutes()); - lblMinutes = lv_label_create(lv_scr_act(), NULL); + lblMinutes = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(lblMinutes, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); lv_label_set_align(lblMinutes, LV_LABEL_ALIGN_CENTER); lv_obj_align(lblMinutes, lv_scr_act(), LV_ALIGN_CENTER, POS_X_MINUTES, POS_Y_TEXT); lv_obj_set_auto_realign(lblMinutes, true); - lv_obj_t * lblColon2 = lv_label_create(lv_scr_act(), NULL); + lv_obj_t * lblColon2 = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(lblColon2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_static(lblColon2, ":"); lv_label_set_align(lblColon2, LV_LABEL_ALIGN_CENTER); lv_obj_align(lblColon2, lv_scr_act(), LV_ALIGN_CENTER, (POS_X_MINUTES + POS_X_SECONDS) / 2, POS_Y_TEXT + OFS_Y_COLON); - lv_obj_t * lblSeconds = lv_label_create(lv_scr_act(), NULL); + lv_obj_t * lblSeconds = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(lblSeconds, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_static(lblSeconds, "00"); lv_label_set_align(lblSeconds, LV_LABEL_ALIGN_CENTER); lv_obj_align(lblSeconds, lv_scr_act(), LV_ALIGN_CENTER, POS_X_SECONDS, POS_Y_TEXT); - btnHoursPlus = lv_btn_create(lv_scr_act(), NULL); + btnHoursPlus = lv_btn_create(lv_scr_act(), nullptr); btnHoursPlus->user_data = this; lv_obj_set_size(btnHoursPlus, 50, 40); lv_obj_align(btnHoursPlus, lv_scr_act(), LV_ALIGN_CENTER, -72, -50); lv_obj_set_style_local_value_str(btnHoursPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); lv_obj_set_event_cb(btnHoursPlus, event_handler); - btnHoursMinus = lv_btn_create(lv_scr_act(), NULL); + btnHoursMinus = lv_btn_create(lv_scr_act(), nullptr); btnHoursMinus->user_data = this; lv_obj_set_size(btnHoursMinus, 50, 40); lv_obj_align(btnHoursMinus, lv_scr_act(), LV_ALIGN_CENTER, -72, 40); lv_obj_set_style_local_value_str(btnHoursMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); lv_obj_set_event_cb(btnHoursMinus, event_handler); - btnMinutesPlus = lv_btn_create(lv_scr_act(), NULL); + btnMinutesPlus = lv_btn_create(lv_scr_act(), nullptr); btnMinutesPlus->user_data = this; lv_obj_set_size(btnMinutesPlus, 50, 40); lv_obj_align(btnMinutesPlus, lv_scr_act(), LV_ALIGN_CENTER, 0, -50); lv_obj_set_style_local_value_str(btnMinutesPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); lv_obj_set_event_cb(btnMinutesPlus, event_handler); - btnMinutesMinus = lv_btn_create(lv_scr_act(), NULL); + btnMinutesMinus = lv_btn_create(lv_scr_act(), nullptr); btnMinutesMinus->user_data = this; lv_obj_set_size(btnMinutesMinus, 50, 40); lv_obj_align(btnMinutesMinus, lv_scr_act(), LV_ALIGN_CENTER, 0, 40); lv_obj_set_style_local_value_str(btnMinutesMinus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "-"); lv_obj_set_event_cb(btnMinutesMinus, event_handler); - btnSetTime = lv_btn_create(lv_scr_act(), NULL); + btnSetTime = lv_btn_create(lv_scr_act(), nullptr); btnSetTime->user_data = this; lv_obj_set_size(btnSetTime, 120, 48); lv_obj_align(btnSetTime, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); @@ -114,7 +112,6 @@ SettingSetTime::~SettingSetTime() { } void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { - if (event != LV_EVENT_CLICKED) return; @@ -124,29 +121,25 @@ void SettingSetTime::HandleButtonPress(lv_obj_t *object, lv_event_t event) { hoursValue = 0; lv_label_set_text_fmt(lblHours, "%02d", hoursValue); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - } - else if (object == btnHoursMinus) { + } else if (object == btnHoursMinus) { hoursValue--; if (hoursValue < 0) hoursValue = 23; lv_label_set_text_fmt(lblHours, "%02d", hoursValue); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - } - else if (object == btnMinutesPlus) { + } else if (object == btnMinutesPlus) { minutesValue++; if (minutesValue > 59) minutesValue = 0; lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - } - else if (object == btnMinutesMinus) { + } else if (object == btnMinutesMinus) { minutesValue--; if (minutesValue < 0) minutesValue = 59; lv_label_set_text_fmt(lblMinutes, "%02d", minutesValue); lv_btn_set_state(btnSetTime, LV_BTN_STATE_RELEASED); - } - else if (object == btnSetTime) { + } else if (object == btnSetTime) { NRF_LOG_INFO("Setting time (manually) to %02d:%02d:00", hoursValue, minutesValue); dateTimeController.SetTime(dateTimeController.Year(), static_cast(dateTimeController.Month()), diff --git a/src/displayapp/screens/settings/SettingSetTime.h b/src/displayapp/screens/settings/SettingSetTime.h index 63fb7d3e..8ba41eae 100644 --- a/src/displayapp/screens/settings/SettingSetTime.h +++ b/src/displayapp/screens/settings/SettingSetTime.h @@ -6,10 +6,8 @@ #include "displayapp/screens/Screen.h" namespace Pinetime { - namespace Applications { namespace Screens { - class SettingSetTime : public Screen{ public: SettingSetTime(DisplayApp* app, Pinetime::Controllers::DateTime &dateTimeController); @@ -17,8 +15,7 @@ namespace Pinetime { void HandleButtonPress(lv_obj_t *object, lv_event_t event); - private: - + private: Controllers::DateTime& dateTimeController; int hoursValue; @@ -30,7 +27,6 @@ namespace Pinetime { lv_obj_t * btnMinutesPlus; lv_obj_t * btnMinutesMinus; lv_obj_t * btnSetTime; - }; } } From 7cd4929bfdb7f82778af8c3f6fed5fb107f1152b Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Thu, 9 Sep 2021 22:50:43 +0200 Subject: [PATCH 46/50] Paddle: compare ballX coordinate with horizontal resolution Fix the comment as the comparison checks if the ball is at the right side of the screen. Compare the x coordinate of the ball with the horizontal resolution of the screen, instead of the vertical resolution. On the PinePhone this does make no difference as we have square 240x240 screen. Change it anyways to be completely correct. --- src/displayapp/screens/Paddle.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/displayapp/screens/Paddle.cpp b/src/displayapp/screens/Paddle.cpp index 3b6d60e3..26c2368b 100644 --- a/src/displayapp/screens/Paddle.cpp +++ b/src/displayapp/screens/Paddle.cpp @@ -47,8 +47,8 @@ void Paddle::Refresh() { dy *= -1; } - // checks if it has touched the side (left side) - if (ballX >= LV_VER_RES - ballSize - 1) { + // checks if it has touched the side (right side) + if (ballX >= LV_HOR_RES - ballSize - 1) { dx *= -1; } From 59ce48a3f3d01288eedf1d0f7e39fc6fabe7984e Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Tue, 7 Sep 2021 20:38:48 +0100 Subject: [PATCH 47/50] Make new notifications refresh idle timer --- src/systemtask/SystemTask.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index f79fd8e5..f1c5165a 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -250,12 +250,13 @@ void SystemTask::Work() { isDimmed = false; break; case Messages::TouchWakeUp: { - if(touchHandler.GetNewTouchInfo()) { + if (touchHandler.GetNewTouchInfo()) { auto gesture = touchHandler.GestureGet(); - if (gesture != Pinetime::Drivers::Cst816S::Gestures::None and ((gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap and - settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) or - (gesture == Pinetime::Drivers::Cst816S::Gestures::SingleTap and - settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) { + if (gesture != Pinetime::Drivers::Cst816S::Gestures::None and + ((gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap and + settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) or + (gesture == Pinetime::Drivers::Cst816S::Gestures::SingleTap and + settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) { GoToRunning(); } } @@ -276,6 +277,8 @@ void SystemTask::Work() { if (settingsController.GetNotificationStatus() == Pinetime::Controllers::Settings::Notification::ON) { if (isSleeping && !isWakingUp) { GoToRunning(); + } else { + ReloadIdleTimer(); } displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification); } From 4a59e544ba7a2ccd051604acece0f03c5e5222e7 Mon Sep 17 00:00:00 2001 From: Quantum-cross <7065792+Quantum-cross@users.noreply.github.com> Date: Mon, 11 Oct 2021 17:12:36 -0400 Subject: [PATCH 48/50] fix building of Recovery image. --- src/displayapp/DisplayAppRecovery.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h index 425e0aca..9f5fb130 100644 --- a/src/displayapp/DisplayAppRecovery.h +++ b/src/displayapp/DisplayAppRecovery.h @@ -10,6 +10,7 @@ #include #include #include +#include #include "TouchEvents.h" #include "Apps.h" #include "Messages.h" @@ -58,6 +59,7 @@ namespace Pinetime { Pinetime::Controllers::AlarmController& alarmController, Pinetime::Controllers::TouchHandler& touchHandler); void Start(); + void Start(Pinetime::System::BootErrors){ Start(); }; void PushMessage(Pinetime::Applications::Display::Messages msg); void Register(Pinetime::System::SystemTask* systemTask); From 1d76d9170e367b4d1f97f9a5e43bd6801724dfd3 Mon Sep 17 00:00:00 2001 From: mabuch Date: Fri, 15 Oct 2021 18:03:10 +0200 Subject: [PATCH 49/50] Replaced "JF002" in github URLs with "InfiniTimeOrg" --- README.md | 2 +- doc/MemoryAnalysis.md | 18 +++++++++--------- doc/buildAndProgram.md | 6 +++--- doc/contribute.md | 2 +- doc/filesInReleaseNotes.md | 4 ++-- doc/gettingStarted/gettingStarted-1.0.md | 12 ++++++------ .../ota-gadgetbridge-nrfconnect.md | 2 +- src/displayapp/screens/PineTimeStyle.cpp | 2 +- src/displayapp/screens/SystemInfo.cpp | 3 ++- 9 files changed, 26 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index ee1fad00..6719aa3e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # InfiniTime -[![Build PineTime Firmware](https://github.com/JF002/InfiniTime/workflows/Build%20PineTime%20Firmware/badge.svg?branch=master)](https://github.com/JF002/InfiniTime/actions) +[![Build PineTime Firmware](https://github.com/InfiniTimeOrg/InfiniTime/workflows/Build%20PineTime%20Firmware/badge.svg?branch=master)](https://github.com/InfiniTimeOrg/InfiniTime/actions) ![InfiniTime logo](images/infinitime-logo.jpg "InfiniTime Logo") diff --git a/doc/MemoryAnalysis.md b/doc/MemoryAnalysis.md index 3251c98d..7304e3f3 100644 --- a/doc/MemoryAnalysis.md +++ b/doc/MemoryAnalysis.md @@ -6,7 +6,7 @@ The PineTime is equipped with the following memories: Note that the NRF52832 cannot execute code stored in the external flash : we need to store the whole firmware in the internal flash memory, and use the external one to store graphicals assets, fonts... -This document describes how the RAM and Flash memories are used in InfiniTime and how to analyze and monitor their usage. It was written in the context of [this memory analysis effort](https://github.com/JF002/InfiniTime/issues/313). +This document describes how the RAM and Flash memories are used in InfiniTime and how to analyze and monitor their usage. It was written in the context of [this memory analysis effort](https://github.com/InfiniTimeOrg/InfiniTime/issues/313). ## Code sections A binary is composed of multiple sections. Most of the time, these sections are : .text, .rodata, .data and .bss but more sections can be defined in the linker script. @@ -38,7 +38,7 @@ In this analysis, I used [Linkermapviz](https://github.com/PromyLOPh/linkermapvi Using this tool, you can easily see the size of each symbol relative to the other one, and check what is using most of the space,... -Also, as Linkermapviz is written in Python, you can easily modify it to adapt it to your firmware, export data in another format,... For example, [I modified it to parse the contents of the MAP file and export it in a CSV file](https://github.com/JF002/InfiniTime/issues/313#issuecomment-842338620). I could later on open this file in LibreOffice Calc and use sort/filter functionality to search for specific symbols in specific files... +Also, as Linkermapviz is written in Python, you can easily modify it to adapt it to your firmware, export data in another format,... For example, [I modified it to parse the contents of the MAP file and export it in a CSV file](https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-842338620). I could later on open this file in LibreOffice Calc and use sort/filter functionality to search for specific symbols in specific files... ### Puncover [Puncover](https://github.com/HBehrens/puncover) is another useful tools that analyses the binary file generated by the compiler (the .out file that contains all debug information). It provides valuable information about the symbols (data and code): name, position, size, max stack of each functions, callers, callees... @@ -69,8 +69,8 @@ This way, you can easily check what needs to be optimized : we should find a way It's always a good idea to check the flash memory space when working on the project : this way, you can easily check that your developments are using a reasonable amount of space. ### Links - - Analysis with linkermapviz : https://github.com/JF002/InfiniTime/issues/313#issuecomment-842338620 - - Analysis with Puncover : https://github.com/JF002/InfiniTime/issues/313#issuecomment-847311392 + - Analysis with linkermapviz : https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-842338620 + - Analysis with Puncover : https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-847311392 ## RAM RAM memory contains all the data that can be modified at run-time: variables, stack, heap... @@ -93,7 +93,7 @@ int main() { In Infinitime 1.1, the biggest buffers are the buffers allocated for LVGL (14KB) and the one for FreeRTOS (16KB). Nimble also allocated 9KB of RAM. ### Stack -The stack will be used for everything except tasks, which have their own stack allocated by FreeRTOS. The stack is 8192B and is allocated in the [linker script](https://github.com/JF002/InfiniTime/blob/develop/nrf_common.ld#L148). +The stack will be used for everything except tasks, which have their own stack allocated by FreeRTOS. The stack is 8192B and is allocated in the [linker script](https://github.com/InfiniTimeOrg/InfiniTime/blob/develop/nrf_common.ld#L148). An easy way to monitor its usage is by filling the section with a known pattern at boot time, then use the firmware and dump the memory. You can then check the maximum stack usage by checking the address from the beginning of the stack that were overwritten. #### Fill the stack section by a known pattern: @@ -197,10 +197,10 @@ On the following dump, the maximum stack usage is 520 bytes (0xFFFF - 0xFDF8): According to my experimentations, we don't use the stack that much, and 8192 bytes is probably way too big for InfiniTime! #### Links - - https://github.com/JF002/InfiniTime/issues/313#issuecomment-851035070 + - https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-851035070 ### Heap -The heap is declared in the [linker script](https://github.com/JF002/InfiniTime/blob/develop/nrf_common.ld#L136) and its current size is 8192 bytes. The heap is used for dynamic memory allocation(`malloc()`, `new`...). +The heap is declared in the [linker script](https://github.com/InfiniTimeOrg/InfiniTime/blob/develop/nrf_common.ld#L136) and its current size is 8192 bytes. The heap is used for dynamic memory allocation(`malloc()`, `new`...). Heap monitoring is not easy, but it seems that we can use the following code to know the current usage of the heap: @@ -239,7 +239,7 @@ Using this technique, I was able to trace all malloc calls at boot (boot -> digi - hr task = 304 #### Links - - https://github.com/JF002/InfiniTime/issues/313#issuecomment-851035625 + - https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-851035625 - https://www.embedded.com/mastering-stack-and-heap-for-system-reliability-part-1-calculating-stack-size/ - https://www.embedded.com/mastering-stack-and-heap-for-system-reliability-part-2-properly-allocating-stacks/ - https://www.embedded.com/mastering-stack-and-heap-for-system-reliability-part-3-avoiding-heap-errors/ @@ -263,7 +263,7 @@ For example a simple lv_label needs **~140 bytes** of memory. I tried to monitor this max value while going through all the apps of InfiniTime 1.1 : the max value I've seen is **5660 bytes**. It means that we could probably **reduce the size of the buffer from 14KB to 6 - 10 KB** (we have to take the fragmentation of the memory into account). ### Links - - https://github.com/JF002/InfiniTime/issues/313#issuecomment-850890064 + - https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-850890064 ## FreeRTOS heap and task stack diff --git a/doc/buildAndProgram.md b/doc/buildAndProgram.md index e97bb30d..feae8d76 100644 --- a/doc/buildAndProgram.md +++ b/doc/buildAndProgram.md @@ -9,7 +9,7 @@ To build this project, you'll need: ## Build steps ### Clone the repo ``` -git clone https://github.com/JF002/InfiniTime.git +git clone https://github.com/InfiniTimeOrg/InfiniTime.git cd InfiniTime git submodule update --init mkdir build @@ -31,9 +31,9 @@ CMake configures the project according to variables you specify the command line **WATCH_COLMI_P8**|Use pin configuration for Colmi P8 watch|`-DWATCH_COLMI_P8=1` ####(**) Note about **CMAKE_BUILD_TYPE**: -By default, this variable is set to *Release*. It compiles the code with size and speed optimizations. We use this value for all the binaries we publish when we [release](https://github.com/JF002/InfiniTime/releases) new versions of InfiniTime. +By default, this variable is set to *Release*. It compiles the code with size and speed optimizations. We use this value for all the binaries we publish when we [release](https://github.com/InfiniTimeOrg/InfiniTime/releases) new versions of InfiniTime. -The *Debug* mode disables all optimizations, which makes the code easier to debug. However, the binary size will likely be too big to fit in the internal flash memory. If you want to build and debug a *Debug* binary, you'll need to disable some parts of the code. For example, the icons for the **Navigation** app use a lot of memory space. You can comment the content of `m_iconMap` in the [Navigation](https://github.com/JF002/InfiniTime/blob/develop/src/displayapp/screens/Navigation.h#L148) application to free some memory. +The *Debug* mode disables all optimizations, which makes the code easier to debug. However, the binary size will likely be too big to fit in the internal flash memory. If you want to build and debug a *Debug* binary, you'll need to disable some parts of the code. For example, the icons for the **Navigation** app use a lot of memory space. You can comment the content of `m_iconMap` in the [Navigation](https://github.com/InfiniTimeOrg/InfiniTime/blob/develop/src/displayapp/screens/Navigation.h#L148) application to free some memory. ####(**) Note about **BUILD_DFU**: DFU files are the files you'll need to install your build of InfiniTime using OTA (over-the-air) mecanism. To generate the DFU file, the Python tool [adafruit-nrfutil](https://github.com/adafruit/Adafruit_nRF52_nrfutil) is needed on your system. Check that this tool is properly installed before enabling this option. diff --git a/doc/contribute.md b/doc/contribute.md index b84d6c9c..21746433 100644 --- a/doc/contribute.md +++ b/doc/contribute.md @@ -2,7 +2,7 @@ ## Report bugs -Have you found a bug in the firmware? [Create an issue on Github](https://github.com/JF002/InfiniTime/issues) explaining the bug, how to reproduce it, the version of the firmware you use... +Have you found a bug in the firmware? [Create an issue on Github](https://github.com/InfiniTimeOrg/InfiniTime/issues) explaining the bug, how to reproduce it, the version of the firmware you use... ## Write and improve documentation diff --git a/doc/filesInReleaseNotes.md b/doc/filesInReleaseNotes.md index 1a37fefb..6a5873c0 100644 --- a/doc/filesInReleaseNotes.md +++ b/doc/filesInReleaseNotes.md @@ -1,9 +1,9 @@ # Using the releases -For each new *stable* version of IniniTime, a [release note](https://github.com/JF002/InfiniTime/releases) is created. It contains a description of the main changes in the release and some files you can use to flash the firmware to your Pinetime. +For each new *stable* version of IniniTime, a [release note](https://github.com/InfiniTimeOrg/InfiniTime/releases) is created. It contains a description of the main changes in the release and some files you can use to flash the firmware to your Pinetime. This page describes the files from the release notes and how to use them. -**NOTE :** the files included in different Releases could be different. This page describes the release notes of [version 0.7.1](https://github.com/JF002/InfiniTime/releases/tag/0.7.1), which is the version that is pre-programmed for the last batches of pinetimes but will be replaced with [1.0.0](https://github.com/jF002/infiniTime/releases/tag/1.0.0) around june 2021. +**NOTE :** the files included in different Releases could be different. This page describes the release notes of [version 0.7.1](https://github.com/InfiniTimeOrg/InfiniTime/releases/tag/0.7.1), which is the version that is pre-programmed for the last batches of pinetimes but will be replaced with [1.0.0](https://github.com/jF002/infiniTime/releases/tag/1.0.0) around june 2021. ## Files included in the release notes diff --git a/doc/gettingStarted/gettingStarted-1.0.md b/doc/gettingStarted/gettingStarted-1.0.md index 88ff2072..3f8f38f6 100644 --- a/doc/gettingStarted/gettingStarted-1.0.md +++ b/doc/gettingStarted/gettingStarted-1.0.md @@ -8,15 +8,15 @@ You might have already seen these words by reading the announcement, release not Basically, a **firmware** is just a software running on the embedded hardware of a device, the PineTime in this case. **InfiniTime** is based on 3 distinct **firmwares**: - - **[InfiniTime](https://github.com/JF002/InfiniTime)** itself, this is the *application firmware* running on the PineTime. This is the main firmware which provides most of the functionalities you'll use on a daily basis : bluetooth low-energy (BLE) connectivity, applications, watchfaces,... + - **[InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime)** itself, this is the *application firmware* running on the PineTime. This is the main firmware which provides most of the functionalities you'll use on a daily basis : bluetooth low-energy (BLE) connectivity, applications, watchfaces,... - **[The bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader)** is responsible for safely applying **updates** of the *application firmware*, reverting them in case of issues and load the recovery firmware when requested. - - **The recovery firmware** is a specific *application firmware* than can be loaded by the bootloader on user request. This firmware can be useful in case of serious issue, when the main application firmware cannot perform an OTA update correctly. Currently, this recovery firmware is based on [InfiniTime 0.14.1](https://github.com/JF002/InfiniTime/releases/tag/0.14.1). + - **The recovery firmware** is a specific *application firmware* than can be loaded by the bootloader on user request. This firmware can be useful in case of serious issue, when the main application firmware cannot perform an OTA update correctly. Currently, this recovery firmware is based on [InfiniTime 0.14.1](https://github.com/InfiniTimeOrg/InfiniTime/releases/tag/0.14.1). **OTA** and **DFU** refer to the update of the firmware over BLE (**B**luetooth **L**ow **E**nergy). **OTA** means **O**ver **T**he **A**ir, this is a functionality that allows the user to update the firmware how their device using a wireless communication like BLE. When we talk about **DFU** (**D**igital **F**irmware **U**pdate), we refer to the file format and protocol used to send the update of the firmware to the watch over-the-air. InfiniTime implement the (legacy) DFU protocol from Nordic Semiconductor (NRF). ## How to check the version of InfiniTime and the bootloader? -Since September 2020, all PineTimes (devkits or sealed) are flashed using the **[first iteration of the bootloader](https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.7)** and **[InfiniTime 0.7.1](https://github.com/JF002/InfiniTime/releases/tag/0.7.1)**. There was no recovery firmware at that time. +Since September 2020, all PineTimes (devkits or sealed) are flashed using the **[first iteration of the bootloader](https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.7)** and **[InfiniTime 0.7.1](https://github.com/InfiniTimeOrg/InfiniTime/releases/tag/0.7.1)**. There was no recovery firmware at that time. The bootloader only runs when the watch starts (from an empty battery, for example) or after a reset (after a successful OTA or a manual reset - long push on the button). @@ -33,7 +33,7 @@ And for version >= 1.0 : ![InfiniTime 1.0 version](version-1.0.jpg) -PineTime shipped from June 2021 (to be confirmed) will be flashed with the [new version of the bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader/releases/tag/1.0.0), the [recovery firmware](https://github.com/JF002/InfiniTime/releases/tag/0.14.1) and [InfiniTime 1.0](https://github.com/JF002/InfiniTime/releases/tag/1.0.0). +PineTime shipped from June 2021 (to be confirmed) will be flashed with the [new version of the bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader/releases/tag/1.0.0), the [recovery firmware](https://github.com/InfiniTimeOrg/InfiniTime/releases/tag/0.14.1) and [InfiniTime 1.0](https://github.com/InfiniTimeOrg/InfiniTime/releases/tag/1.0.0). The bootloader is easily recognizable with it white pine cone that is progressively drawn in green. It also displays its own version on the bottom (1.0.0 as of now). @@ -56,9 +56,9 @@ If your PineTime is currently running InfiniTime 0.7.1 and the old bootloader, w Using the companion app of your choice, you'll need to apply the OTA procedure for these 3 firmwares in this sequence (failing to follow this specific order might temporarily or permanently brick your device): - 1. Flash the latest version of InfiniTime. The file to upload is named **pinetime-mcuboot-app-dfu-x.y.z.zip**. Here is the link to [InfiniTime 1.0](https://github.com/JF002/InfiniTime/releases/download/1.0.0/pinetime-mcuboot-app-dfu-1.0.0.zip). + 1. Flash the latest version of InfiniTime. The file to upload is named **pinetime-mcuboot-app-dfu-x.y.z.zip**. Here is the link to [InfiniTime 1.0](https://github.com/InfiniTimeOrg/InfiniTime/releases/download/1.0.0/pinetime-mcuboot-app-dfu-1.0.0.zip). 2. Update the bootloader by applying the OTA procedure with the file named [**reloader-mcuboot.zip** from the repo of the bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader/releases/download/1.0.0/reloader-mcuboot.zip). - 3. Install the recovery firmware by applying the OTA procedure with the file named [**pinetime-mcuboot-recovery-loader-dfu-0.14.1.zip** from the version 0.14.1 of InfiniTime](https://github.com/JF002/InfiniTime/releases/download/0.14.1/pinetime-mcuboot-recovery-loader-dfu-0.14.1.zip). + 3. Install the recovery firmware by applying the OTA procedure with the file named [**pinetime-mcuboot-recovery-loader-dfu-0.14.1.zip** from the version 0.14.1 of InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime/releases/download/0.14.1/pinetime-mcuboot-recovery-loader-dfu-0.14.1.zip). You'll find more info about this process in [this wiki page](https://wiki.pine64.org/wiki/Upgrade_PineTime_to_InfiniTime_1.0.0). You can also see the procedure in video [here](https://video.codingfield.com/videos/watch/831077c5-16f3-47b4-9b2b-c4bbfecc6529) and [here (from Amazfish)](https://video.codingfield.com/videos/watch/f7bffb3d-a6a1-43c4-8f01-f4aeff4adf9e) diff --git a/doc/gettingStarted/ota-gadgetbridge-nrfconnect.md b/doc/gettingStarted/ota-gadgetbridge-nrfconnect.md index ffc27ed8..57d16218 100644 --- a/doc/gettingStarted/ota-gadgetbridge-nrfconnect.md +++ b/doc/gettingStarted/ota-gadgetbridge-nrfconnect.md @@ -8,7 +8,7 @@ If you just want to flash or upgrade InfiniTime on your PineTime, this page is f - [How to flash InfiniTime using the SWD interface](#how-to-flash-infinitime-using-the-swd-interface) ## InfiniTime releases and versions -All releases of InfiniTime are available on the [release page of the GitHub repo](https://github.com/JF002/InfiniTime/releases). +All releases of InfiniTime are available on the [release page of the GitHub repo](https://github.com/InfiniTimeOrg/InfiniTime/releases). Versions that are tagged as **RELEASE CANDIDATE** are pre-release versions, that are available for testing before actually releasing a new stable version. If you want to help us debug the project and provide stable versions to other user, you can use them. If you want stable and tested version, you should not flash these release candidate version. diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index 6766ecb0..fa88d459 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -1,5 +1,5 @@ /* - * This file is part of the Infinitime distribution (https://github.com/JF002/Infinitime). + * This file is part of the Infinitime distribution (https://github.com/InfiniTimeOrg/Infinitime). * Copyright (c) 2021 Kieran Cawthray. * * This program is free software: you can redistribute it and/or modify diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index 475fbb88..cda0a487 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -267,7 +267,8 @@ std::unique_ptr SystemInfo::CreateScreen5() { "Public License v3\n" "#444444 Source code#\n" "#FFFF00 https://github.com/#\n" - "#FFFF00 JF002/InfiniTime#"); + "#FFFF00 InfiniTimeOrg/#\n" + "#FFFF00 InfiniTime#"); lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); return std::make_unique(4, 5, app, label); From c4b8ff314abd436d0444ea884ccf142a0b82c8c8 Mon Sep 17 00:00:00 2001 From: carlosperate Date: Sun, 17 Oct 2021 00:31:21 +0100 Subject: [PATCH 50/50] Update git URLS, MCUboot is now independent w/ different GitHub org. --- .devcontainer/Dockerfile | 2 +- .devcontainer/build.sh | 2 +- bootloader/README.md | 4 ++-- docker/build.sh | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 1dd68f24..46e2facb 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -55,7 +55,7 @@ RUN unzip -q /tmp/nRF5_SDK_15.3.0_59ac345 -d /opt RUN rm /tmp/nRF5_SDK_15.3.0_59ac345 # McuBoot # RUN bash -c "source /opt/build.sh; GetMcuBoot;" -RUN git clone https://github.com/JuulLabs-OSS/mcuboot.git +RUN git clone https://github.com/mcu-tools/mcuboot.git RUN pip3 install -r ./mcuboot/scripts/requirements.txt RUN adduser infinitime diff --git a/.devcontainer/build.sh b/.devcontainer/build.sh index 8f0d0fa9..5dcdf91d 100644 --- a/.devcontainer/build.sh +++ b/.devcontainer/build.sh @@ -43,7 +43,7 @@ GetGcc() { } GetMcuBoot() { - git clone https://github.com/JuulLabs-OSS/mcuboot.git "$TOOLS_DIR/mcuboot" + git clone https://github.com/mcu-tools/mcuboot.git "$TOOLS_DIR/mcuboot" pip3 install -r "$TOOLS_DIR/mcuboot/scripts/requirements.txt" } diff --git a/bootloader/README.md b/bootloader/README.md index c04e0e34..9f99602b 100644 --- a/bootloader/README.md +++ b/bootloader/README.md @@ -1,5 +1,5 @@ # About this bootloader -The [bootloader](https://github.com/lupyuen/pinetime-rust-mynewt/tree/master/libs/pinetime_boot/src) is mostly developed by [Lup Yuen](https://github.com/lupyuen). It is based on [MCUBoot](https://juullabs-oss.github.io/mcuboot/) and [Mynewt](https://mynewt.apache.org/). +The [bootloader](https://github.com/lupyuen/pinetime-rust-mynewt/tree/master/libs/pinetime_boot/src) is mostly developed by [Lup Yuen](https://github.com/lupyuen). It is based on [MCUBoot](https://www.mcuboot.com) and [Mynewt](https://mynewt.apache.org/). The goal of this project is to provide a common bootloader for multiple (all?) Pinetime projects. It allows to upgrade the current bootloader and even replace the current application by another one that supports the same bootloader. @@ -86,7 +86,7 @@ make pinetime-mcuboot-app The binary is located in */src/pinetime-mcuboot-app.bin*. -It must me converted into a MCUBoot image using *imgtool.py* from [MCUBoot](https://github.com/JuulLabs-OSS/mcuboot/tree/master/scripts). Simply checkout the project and run the script /scripts/imgtool.py with the following command line: +It must me converted into a MCUBoot image using *imgtool.py* from [MCUBoot](https://github.com/mcu-tools/mcuboot/tree/master/scripts). Simply checkout the project and run the script /scripts/imgtool.py with the following command line: ` imgtool.py create --align 4 --version 1.0.0 --header-size 32 --slot-size 475136 --pad-header /src/pinetime-mcuboot-app.bin image.bin diff --git a/docker/build.sh b/docker/build.sh index 2fa7d920..d86e7c21 100755 --- a/docker/build.sh +++ b/docker/build.sh @@ -43,7 +43,7 @@ GetGcc() { } GetMcuBoot() { - git clone https://github.com/JuulLabs-OSS/mcuboot.git "$TOOLS_DIR/mcuboot" + git clone https://github.com/mcu-tools/mcuboot.git "$TOOLS_DIR/mcuboot" pip3 install -r "$TOOLS_DIR/mcuboot/scripts/requirements.txt" }