From 3320eae95cb334b62994ad8ca3a364aae08c653a Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Sun, 3 Oct 2021 20:01:46 +0200 Subject: Initial commit diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index 6766ecb..e035f39 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -37,6 +37,13 @@ using namespace Pinetime::Applications::Screens; +namespace { + static void event_handler(lv_obj_t* obj, lv_event_t event) { + PineTimeStyle* screen = static_cast(obj->user_data); + screen->UpdateSelected(obj, event); + } +} + PineTimeStyle::PineTimeStyle(DisplayApp* app, Controllers::DateTime& dateTimeController, Controllers::Battery& batteryController, @@ -53,16 +60,13 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app, settingsController {settingsController}, motionController {motionController} { - // This sets the watchface number to return to after leaving the menu - settingsController.SetClockFace(2); - displayedChar[0] = 0; displayedChar[1] = 0; displayedChar[2] = 0; displayedChar[3] = 0; displayedChar[4] = 0; - //Create a 200px wide background rectangle + // Create a 200px wide background rectangle timebar = lv_obj_create(lv_scr_act(), nullptr); lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(settingsController.GetPTSColorBG())); lv_obj_set_style_local_radius(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); @@ -97,69 +101,69 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app, // Display icons batteryIcon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_label_set_text(batteryIcon, Symbols::batteryFull); lv_obj_align(batteryIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 2); lv_obj_set_auto_realign(batteryIcon, true); bleIcon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); notificationIcon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 40); // Calendar icon calendarOuter = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_bg_color(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_obj_set_style_local_radius(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); lv_obj_set_size(calendarOuter, 34, 34); lv_obj_align(calendarOuter, sidebar, LV_ALIGN_CENTER, 0, 0); calendarInner = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(calendarInner, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xffffff)); + lv_obj_set_style_local_bg_color(calendarInner, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); lv_obj_set_style_local_radius(calendarInner, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); lv_obj_set_size(calendarInner, 27, 27); lv_obj_align(calendarInner, calendarOuter, LV_ALIGN_CENTER, 0, 0); calendarBar1 = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(calendarBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_bg_color(calendarBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_obj_set_style_local_radius(calendarBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); lv_obj_set_size(calendarBar1, 3, 12); lv_obj_align(calendarBar1, calendarOuter, LV_ALIGN_IN_TOP_MID, -6, -3); calendarBar2 = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(calendarBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_bg_color(calendarBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_obj_set_style_local_radius(calendarBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); lv_obj_set_size(calendarBar2, 3, 12); lv_obj_align(calendarBar2, calendarOuter, LV_ALIGN_IN_TOP_MID, 6, -3); calendarCrossBar1 = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(calendarCrossBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_bg_color(calendarCrossBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_obj_set_style_local_radius(calendarCrossBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); lv_obj_set_size(calendarCrossBar1, 8, 3); lv_obj_align(calendarCrossBar1, calendarBar1, LV_ALIGN_IN_BOTTOM_MID, 0, 0); calendarCrossBar2 = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(calendarCrossBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_bg_color(calendarCrossBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_obj_set_style_local_radius(calendarCrossBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); lv_obj_set_size(calendarCrossBar2, 8, 3); lv_obj_align(calendarCrossBar2, calendarBar2, LV_ALIGN_IN_BOTTOM_MID, 0, 0); // Display date dateDayOfWeek = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(dateDayOfWeek, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_text_color(dateDayOfWeek, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_label_set_text(dateDayOfWeek, "THU"); lv_obj_align(dateDayOfWeek, sidebar, LV_ALIGN_CENTER, 0, -34); dateDay = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(dateDay, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_text_color(dateDay, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_label_set_text(dateDay, "25"); lv_obj_align(dateDay, sidebar, LV_ALIGN_CENTER, 0, 3); dateMonth = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(dateMonth, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_text_color(dateMonth, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); lv_label_set_text(dateMonth, "MAR"); lv_obj_align(dateMonth, sidebar, LV_ALIGN_CENTER, 0, 32); @@ -193,6 +197,100 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app, lv_obj_set_pos(backgroundLabel, 0, 0); lv_label_set_text(backgroundLabel, ""); + btnNextTime = lv_btn_create(lv_scr_act(), nullptr); + btnNextTime->user_data = this; + lv_obj_set_size(btnNextTime, 60, 60); + lv_obj_align(btnNextTime, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -15, -80); + lv_obj_set_style_local_bg_opa(btnNextTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); + lv_obj_set_style_local_value_str(btnNextTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, ">"); + lv_obj_set_event_cb(btnNextTime, event_handler); + lv_obj_set_hidden(btnNextTime, true); + + btnPrevTime = lv_btn_create(lv_scr_act(), nullptr); + btnPrevTime->user_data = this; + lv_obj_set_size(btnPrevTime, 60, 60); + lv_obj_align(btnPrevTime, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 15, -80); + lv_obj_set_style_local_bg_opa(btnPrevTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); + lv_obj_set_style_local_value_str(btnPrevTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "<"); + lv_obj_set_event_cb(btnPrevTime, event_handler); + lv_obj_set_hidden(btnPrevTime, true); + + btnNextBar = lv_btn_create(lv_scr_act(), nullptr); + btnNextBar->user_data = this; + lv_obj_set_size(btnNextBar, 60, 60); + lv_obj_align(btnNextBar, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -15, 0); + lv_obj_set_style_local_bg_opa(btnNextBar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); + lv_obj_set_style_local_value_str(btnNextBar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, ">"); + lv_obj_set_event_cb(btnNextBar, event_handler); + lv_obj_set_hidden(btnNextBar, true); + + btnPrevBar = lv_btn_create(lv_scr_act(), nullptr); + btnPrevBar->user_data = this; + lv_obj_set_size(btnPrevBar, 60, 60); + lv_obj_align(btnPrevBar, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 15, 0); + lv_obj_set_style_local_bg_opa(btnPrevBar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); + lv_obj_set_style_local_value_str(btnPrevBar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "<"); + lv_obj_set_event_cb(btnPrevBar, event_handler); + lv_obj_set_hidden(btnPrevBar, true); + + btnNextBG = lv_btn_create(lv_scr_act(), nullptr); + btnNextBG->user_data = this; + lv_obj_set_size(btnNextBG, 60, 60); + lv_obj_align(btnNextBG, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -15, 80); + lv_obj_set_style_local_bg_opa(btnNextBG, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); + lv_obj_set_style_local_value_str(btnNextBG, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, ">"); + lv_obj_set_event_cb(btnNextBG, event_handler); + lv_obj_set_hidden(btnNextBG, true); + + btnPrevBG = lv_btn_create(lv_scr_act(), nullptr); + btnPrevBG->user_data = this; + lv_obj_set_size(btnPrevBG, 60, 60); + lv_obj_align(btnPrevBG, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 15, 80); + lv_obj_set_style_local_bg_opa(btnPrevBG, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); + lv_obj_set_style_local_value_str(btnPrevBG, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "<"); + lv_obj_set_event_cb(btnPrevBG, event_handler); + lv_obj_set_hidden(btnPrevBG, true); + + btnReset = lv_btn_create(lv_scr_act(), nullptr); + btnReset->user_data = this; + lv_obj_set_size(btnReset, 60, 60); + lv_obj_align(btnReset, lv_scr_act(), LV_ALIGN_CENTER, 0, 80); + lv_obj_set_style_local_bg_opa(btnReset, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); + lv_obj_set_style_local_value_str(btnReset, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Rst"); + lv_obj_set_event_cb(btnReset, event_handler); + lv_obj_set_hidden(btnReset, true); + + btnRandom = lv_btn_create(lv_scr_act(), nullptr); + btnRandom->user_data = this; + lv_obj_set_size(btnRandom, 60, 60); + lv_obj_align(btnRandom, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_bg_opa(btnRandom, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); + lv_obj_set_style_local_value_str(btnRandom, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Rnd"); + lv_obj_set_event_cb(btnRandom, event_handler); + lv_obj_set_hidden(btnRandom, true); + + btnClose = lv_btn_create(lv_scr_act(), nullptr); + btnClose->user_data = this; + lv_obj_set_size(btnClose, 60, 60); + lv_obj_align(btnClose, lv_scr_act(), LV_ALIGN_CENTER, 0, -80); + lv_obj_set_style_local_bg_opa(btnClose, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); + lv_obj_set_style_local_value_str(btnClose, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "X"); + lv_obj_set_event_cb(btnClose, event_handler); + lv_obj_set_hidden(btnClose, true); + + btnSet = lv_btn_create(lv_scr_act(), nullptr); + btnSet->user_data = this; + lv_obj_set_height(btnSet, 150); + lv_obj_set_width(btnSet, 150); + lv_obj_align(btnSet, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + lv_obj_set_style_local_radius(btnSet, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 30); + lv_obj_set_style_local_bg_opa(btnSet, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50); + lv_obj_set_event_cb(btnSet, event_handler); + lbl_btnSet = lv_label_create(btnSet, nullptr); + lv_obj_set_style_local_text_font(lbl_btnSet, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48); + lv_label_set_text_static(lbl_btnSet, Symbols::settings); + lv_obj_set_hidden(btnSet, true); + taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); Refresh(); } @@ -202,6 +300,15 @@ PineTimeStyle::~PineTimeStyle() { lv_obj_clean(lv_scr_act()); } +bool PineTimeStyle::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + if (event == Pinetime::Applications::TouchEvents::LongTap) { + lv_obj_set_hidden(btnSet, false); + savedTick = lv_tick_get(); + return true; + } + return false; +} + void PineTimeStyle::SetBatteryIcon() { auto batteryPercent = batteryPercentRemaining.Get(); lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent)); @@ -312,4 +419,135 @@ void PineTimeStyle::Refresh() { lv_obj_set_style_local_scale_grad_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); } } + if (lv_obj_is_visible(btnSet) == true) { + if ((savedTick > 0) && (lv_tick_get() - savedTick > 5000)) { + lv_obj_set_hidden(btnSet, true); + savedTick = 0; + } + } } + +void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { + auto valueTime = settingsController.GetPTSColorTime(); + auto valueBar = settingsController.GetPTSColorBar(); + auto valueBG = settingsController.GetPTSColorBG(); + + if (event == LV_EVENT_CLICKED) { + if (object == btnNextTime) { + valueTime = GetNext(valueTime); + + settingsController.SetPTSColorTime(valueTime); + lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); + lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); + lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); + } + if (object == btnPrevTime) { + valueTime = GetPrevious(valueTime); + settingsController.SetPTSColorTime(valueTime); + lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); + lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); + lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); + } + if (object == btnNextBar) { + valueBar = GetNext(valueBar); + if(valueBar == Controllers::Settings::Colors::Black) + valueBar = GetNext(valueBar); + settingsController.SetPTSColorBar(valueBar); + lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBar)); + } + if (object == btnPrevBar) { + valueBar = GetPrevious(valueBar); + if(valueBar == Controllers::Settings::Colors::Black) + valueBar = GetPrevious(valueBar); + settingsController.SetPTSColorBar(valueBar); + lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBar)); + } + if (object == btnNextBG) { + valueBG = GetNext(valueBG); + settingsController.SetPTSColorBG(valueBG); + lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBG)); + } + if (object == btnPrevBG) { + valueBG = GetPrevious(valueBG); + settingsController.SetPTSColorBG(valueBG); + lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBG)); + } + if (object == btnReset) { + settingsController.SetPTSColorTime(Controllers::Settings::Colors::Teal); + lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Teal)); + lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Teal)); + lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Teal)); + settingsController.SetPTSColorBar(Controllers::Settings::Colors::Teal); + lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Teal)); + settingsController.SetPTSColorBG(Controllers::Settings::Colors::Black); + lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Black)); + } + if (object == btnRandom) { + uint8_t randTime = rand() % 17; + uint8_t randBar = rand() % 17; + uint8_t randBG = rand() % 17; + // Check if the time color is the same as its background, or if the sidebar is black. If so, change them to more useful values. + if (randTime == randBG) { + randBG += 1; + } + if (randBar == 3) { + randBar -= 1; + } + settingsController.SetPTSColorTime(static_cast(randTime)); + lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randTime))); + lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randTime))); + lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randTime))); + settingsController.SetPTSColorBar(static_cast(randBar)); + lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randBar))); + settingsController.SetPTSColorBG(static_cast(randBG)); + lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randBG))); + } + if (object == btnClose) { + settingsController.SaveSettings(); + lv_obj_set_hidden(btnNextTime, true); + lv_obj_set_hidden(btnPrevTime, true); + lv_obj_set_hidden(btnNextBar, true); + lv_obj_set_hidden(btnPrevBar, true); + lv_obj_set_hidden(btnNextBG, true); + lv_obj_set_hidden(btnPrevBG, true); + lv_obj_set_hidden(btnReset, true); + lv_obj_set_hidden(btnRandom, true); + lv_obj_set_hidden(btnClose, true); + } + if (object == btnSet) { + lv_obj_set_hidden(btnSet, true); + lv_obj_set_hidden(btnNextTime, false); + lv_obj_set_hidden(btnPrevTime, false); + lv_obj_set_hidden(btnNextBar, false); + lv_obj_set_hidden(btnPrevBar, false); + lv_obj_set_hidden(btnNextBG, false); + lv_obj_set_hidden(btnPrevBG, false); + lv_obj_set_hidden(btnReset, false); + lv_obj_set_hidden(btnRandom, false); + lv_obj_set_hidden(btnClose, false); + } + } +} + +Pinetime::Controllers::Settings::Colors PineTimeStyle::GetNext(Pinetime::Controllers::Settings::Colors color) { + auto colorAsInt = static_cast(color); + Pinetime::Controllers::Settings::Colors nextColor; + if (colorAsInt < 16) { + nextColor = static_cast(colorAsInt + 1); + } else { + nextColor = static_cast(0); + } + return nextColor; +} + +Pinetime::Controllers::Settings::Colors PineTimeStyle::GetPrevious(Pinetime::Controllers::Settings::Colors color) { + auto colorAsInt = static_cast(color); + Pinetime::Controllers::Settings::Colors prevColor; + + if (colorAsInt > 0) { + prevColor = static_cast(colorAsInt - 1); + } else { + prevColor = static_cast(16); + } + return prevColor; +} \ No newline at end of file diff --git a/src/displayapp/screens/PineTimeStyle.h b/src/displayapp/screens/PineTimeStyle.h index ba47380..5274d0c 100644 --- a/src/displayapp/screens/PineTimeStyle.h +++ b/src/displayapp/screens/PineTimeStyle.h @@ -30,8 +30,12 @@ namespace Pinetime { Controllers::MotionController& motionController); ~PineTimeStyle() override; + bool OnTouchEvent(TouchEvents event) override; + void Refresh() override; + void UpdateSelected(lv_obj_t *object, lv_event_t event); + private: char displayedChar[5]; @@ -39,6 +43,7 @@ namespace Pinetime { Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown; Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown; uint8_t currentDay = 0; + uint32_t savedTick = 0; DirtyValue batteryPercentRemaining {}; DirtyValue isCharging {}; @@ -48,6 +53,18 @@ namespace Pinetime { DirtyValue stepCount {}; DirtyValue notificationState {}; + Pinetime::Controllers::Settings::Colors GetNext(Controllers::Settings::Colors color); + Pinetime::Controllers::Settings::Colors GetPrevious(Controllers::Settings::Colors color); + + lv_obj_t* btnNextTime; + lv_obj_t* btnPrevTime; + lv_obj_t* btnNextBar; + lv_obj_t* btnPrevBar; + lv_obj_t* btnNextBG; + lv_obj_t* btnPrevBG; + lv_obj_t* btnReset; + lv_obj_t* btnRandom; + lv_obj_t* btnClose; lv_obj_t* timebar; lv_obj_t* sidebar; lv_obj_t* timeDD1; @@ -67,6 +84,8 @@ namespace Pinetime { lv_obj_t* calendarCrossBar2; lv_obj_t* notificationIcon; lv_obj_t* stepGauge; + lv_obj_t* btnSet; + lv_obj_t* lbl_btnSet; lv_color_t needle_colors[1]; Controllers::DateTime& dateTimeController; @@ -82,4 +101,4 @@ namespace Pinetime { }; } } -} +} \ No newline at end of file -- cgit v0.10.2 From 7d1da9f1f9f507bdee3e9ea7d0f7ad90a905f7d2 Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Sun, 3 Oct 2021 20:11:04 +0200 Subject: Remove old PineTimeStyle settings app diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 37ee084..52f0bc8 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -432,7 +432,6 @@ list(APPEND SOURCE_FILES displayapp/screens/settings/SettingWakeUp.cpp displayapp/screens/settings/SettingDisplay.cpp displayapp/screens/settings/SettingSteps.cpp - displayapp/screens/settings/SettingPineTimeStyle.cpp ## Watch faces displayapp/icons/bg_clock.c diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index e3aca8c..6cc3614 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -31,8 +31,7 @@ namespace Pinetime { SettingTimeFormat, SettingDisplay, SettingWakeUp, - SettingSteps, - SettingPineTimeStyle + SettingSteps }; } } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 837082d..cdfe0b8 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -43,7 +43,6 @@ #include "displayapp/screens/settings/SettingWakeUp.h" #include "displayapp/screens/settings/SettingDisplay.h" #include "displayapp/screens/settings/SettingSteps.h" -#include "displayapp/screens/settings/SettingPineTimeStyle.h" #include "libs/lv_conf.h" @@ -365,10 +364,6 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) currentScreen = std::make_unique(this, settingsController); ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); break; - case Apps::SettingPineTimeStyle: - currentScreen = std::make_unique(this, settingsController); - ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); - break; case Apps::BatteryInfo: currentScreen = std::make_unique(this, batteryController); ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); diff --git a/src/displayapp/screens/settings/SettingPineTimeStyle.cpp b/src/displayapp/screens/settings/SettingPineTimeStyle.cpp deleted file mode 100644 index c9af19b..0000000 --- a/src/displayapp/screens/settings/SettingPineTimeStyle.cpp +++ /dev/null @@ -1,318 +0,0 @@ -#include "SettingPineTimeStyle.h" -#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) { - SettingPineTimeStyle* screen = static_cast(obj->user_data); - screen->UpdateSelected(obj, event); - } -} - -SettingPineTimeStyle::SettingPineTimeStyle(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) - : Screen(app), settingsController {settingsController} { - timebar = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(settingsController.GetPTSColorBG())); - lv_obj_set_style_local_radius(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); - lv_obj_set_size(timebar, 200, 240); - lv_obj_align(timebar, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 5, 0); - - // Display the time - - timeDD1 = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_font(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &open_sans_light); - lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(settingsController.GetPTSColorTime())); - lv_label_set_text(timeDD1, "12"); - lv_obj_align(timeDD1, timebar, LV_ALIGN_IN_TOP_MID, 5, 5); - - timeDD2 = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_font(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &open_sans_light); - lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(settingsController.GetPTSColorTime())); - lv_label_set_text(timeDD2, "34"); - lv_obj_align(timeDD2, timebar, LV_ALIGN_IN_BOTTOM_MID, 5, -5); - - timeAMPM = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(settingsController.GetPTSColorTime())); - lv_obj_set_style_local_text_line_space(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, -3); - lv_label_set_text(timeAMPM, "A\nM"); - lv_obj_align(timeAMPM, timebar, LV_ALIGN_IN_BOTTOM_LEFT, 2, -20); - - // Create a 40px wide bar down the right side of the screen - - sidebar = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(settingsController.GetPTSColorBar())); - lv_obj_set_style_local_radius(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); - lv_obj_set_size(sidebar, 40, 240); - lv_obj_align(sidebar, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0); - - // Display icons - - batteryIcon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); - lv_label_set_text(batteryIcon, Symbols::batteryFull); - lv_obj_align(batteryIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 2); - - bleIcon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); - lv_label_set_text(bleIcon, Symbols::bluetooth); - lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); - - // Calendar icon - - calendarOuter = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); - lv_obj_set_style_local_radius(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); - lv_obj_set_size(calendarOuter, 34, 34); - lv_obj_align(calendarOuter, sidebar, LV_ALIGN_CENTER, 0, 0); - - calendarInner = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(calendarInner, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xffffff)); - lv_obj_set_style_local_radius(calendarInner, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); - lv_obj_set_size(calendarInner, 27, 27); - lv_obj_align(calendarInner, calendarOuter, LV_ALIGN_CENTER, 0, 0); - - calendarBar1 = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(calendarBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); - lv_obj_set_style_local_radius(calendarBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); - lv_obj_set_size(calendarBar1, 3, 12); - lv_obj_align(calendarBar1, calendarOuter, LV_ALIGN_IN_TOP_MID, -6, -3); - - calendarBar2 = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(calendarBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); - lv_obj_set_style_local_radius(calendarBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); - lv_obj_set_size(calendarBar2, 3, 12); - lv_obj_align(calendarBar2, calendarOuter, LV_ALIGN_IN_TOP_MID, 6, -3); - - calendarCrossBar1 = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(calendarCrossBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); - lv_obj_set_style_local_radius(calendarCrossBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); - lv_obj_set_size(calendarCrossBar1, 8, 3); - lv_obj_align(calendarCrossBar1, calendarBar1, LV_ALIGN_IN_BOTTOM_MID, 0, 0); - - calendarCrossBar2 = lv_obj_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_bg_color(calendarCrossBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); - lv_obj_set_style_local_radius(calendarCrossBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); - lv_obj_set_size(calendarCrossBar2, 8, 3); - lv_obj_align(calendarCrossBar2, calendarBar2, LV_ALIGN_IN_BOTTOM_MID, 0, 0); - - // Display date - - dateDayOfWeek = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(dateDayOfWeek, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); - lv_label_set_text(dateDayOfWeek, "THU"); - lv_obj_align(dateDayOfWeek, sidebar, LV_ALIGN_CENTER, 0, -34); - - dateDay = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(dateDay, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); - lv_label_set_text(dateDay, "25"); - lv_obj_align(dateDay, sidebar, LV_ALIGN_CENTER, 0, 3); - - dateMonth = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(dateMonth, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); - lv_label_set_text(dateMonth, "MAR"); - lv_obj_align(dateMonth, sidebar, LV_ALIGN_CENTER, 0, 32); - - // Step count gauge - needle_colors[0] = LV_COLOR_WHITE; - stepGauge = lv_gauge_create(lv_scr_act(), nullptr); - lv_gauge_set_needle_count(stepGauge, 1, needle_colors); - lv_obj_set_size(stepGauge, 40, 40); - lv_obj_align(stepGauge, sidebar, LV_ALIGN_IN_BOTTOM_MID, 0, 0); - lv_gauge_set_scale(stepGauge, 360, 11, 0); - lv_gauge_set_angle_offset(stepGauge, 180); - lv_gauge_set_critical_value(stepGauge, (100)); - lv_gauge_set_range(stepGauge, 0, (100)); - lv_gauge_set_value(stepGauge, 0, 0); - - lv_obj_set_style_local_pad_right(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 3); - lv_obj_set_style_local_pad_left(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 3); - lv_obj_set_style_local_pad_bottom(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 3); - lv_obj_set_style_local_line_opa(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER); - lv_obj_set_style_local_scale_width(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 4); - lv_obj_set_style_local_line_width(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 4); - lv_obj_set_style_local_line_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); - lv_obj_set_style_local_line_opa(stepGauge, LV_GAUGE_PART_NEEDLE, LV_STATE_DEFAULT, LV_OPA_COVER); - lv_obj_set_style_local_line_width(stepGauge, LV_GAUGE_PART_NEEDLE, LV_STATE_DEFAULT, 3); - lv_obj_set_style_local_pad_inner(stepGauge, LV_GAUGE_PART_NEEDLE, LV_STATE_DEFAULT, 4); - - backgroundLabel = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_click(backgroundLabel, true); - lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP); - lv_obj_set_size(backgroundLabel, 240, 240); - lv_obj_set_pos(backgroundLabel, 0, 0); - lv_label_set_text(backgroundLabel, ""); - - btnNextTime = lv_btn_create(lv_scr_act(), nullptr); - btnNextTime->user_data = this; - lv_obj_set_size(btnNextTime, 60, 60); - lv_obj_align(btnNextTime, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -15, -80); - lv_obj_set_style_local_bg_opa(btnNextTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_30); - lv_obj_set_style_local_value_str(btnNextTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, ">"); - lv_obj_set_event_cb(btnNextTime, event_handler); - - btnPrevTime = lv_btn_create(lv_scr_act(), nullptr); - btnPrevTime->user_data = this; - lv_obj_set_size(btnPrevTime, 60, 60); - lv_obj_align(btnPrevTime, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 15, -80); - lv_obj_set_style_local_bg_opa(btnPrevTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_30); - lv_obj_set_style_local_value_str(btnPrevTime, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "<"); - lv_obj_set_event_cb(btnPrevTime, event_handler); - - btnNextBar = lv_btn_create(lv_scr_act(), nullptr); - btnNextBar->user_data = this; - lv_obj_set_size(btnNextBar, 60, 60); - lv_obj_align(btnNextBar, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -15, 0); - lv_obj_set_style_local_bg_opa(btnNextBar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_30); - lv_obj_set_style_local_value_str(btnNextBar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, ">"); - lv_obj_set_event_cb(btnNextBar, event_handler); - - btnPrevBar = lv_btn_create(lv_scr_act(), nullptr); - btnPrevBar->user_data = this; - lv_obj_set_size(btnPrevBar, 60, 60); - lv_obj_align(btnPrevBar, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 15, 0); - lv_obj_set_style_local_bg_opa(btnPrevBar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_30); - lv_obj_set_style_local_value_str(btnPrevBar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "<"); - lv_obj_set_event_cb(btnPrevBar, event_handler); - - btnNextBG = lv_btn_create(lv_scr_act(), nullptr); - btnNextBG->user_data = this; - lv_obj_set_size(btnNextBG, 60, 60); - lv_obj_align(btnNextBG, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -15, 80); - lv_obj_set_style_local_bg_opa(btnNextBG, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_30); - lv_obj_set_style_local_value_str(btnNextBG, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, ">"); - lv_obj_set_event_cb(btnNextBG, event_handler); - - btnPrevBG = lv_btn_create(lv_scr_act(), nullptr); - btnPrevBG->user_data = this; - lv_obj_set_size(btnPrevBG, 60, 60); - lv_obj_align(btnPrevBG, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 15, 80); - lv_obj_set_style_local_bg_opa(btnPrevBG, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_30); - lv_obj_set_style_local_value_str(btnPrevBG, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "<"); - lv_obj_set_event_cb(btnPrevBG, event_handler); - - btnReset = lv_btn_create(lv_scr_act(), nullptr); - btnReset->user_data = this; - lv_obj_set_size(btnReset, 60, 60); - lv_obj_align(btnReset, lv_scr_act(), LV_ALIGN_CENTER, 0, 80); - lv_obj_set_style_local_bg_opa(btnReset, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_30); - lv_obj_set_style_local_value_str(btnReset, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Rst"); - lv_obj_set_event_cb(btnReset, event_handler); - - btnRandom = lv_btn_create(lv_scr_act(), nullptr); - btnRandom->user_data = this; - lv_obj_set_size(btnRandom, 60, 60); - lv_obj_align(btnRandom, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); - lv_obj_set_style_local_bg_opa(btnRandom, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_30); - lv_obj_set_style_local_value_str(btnRandom, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "Rnd"); - lv_obj_set_event_cb(btnRandom, event_handler); -} - -SettingPineTimeStyle::~SettingPineTimeStyle() { - lv_obj_clean(lv_scr_act()); - settingsController.SaveSettings(); -} - -void SettingPineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { - auto valueTime = settingsController.GetPTSColorTime(); - auto valueBar = settingsController.GetPTSColorBar(); - auto valueBG = settingsController.GetPTSColorBG(); - - if (event == LV_EVENT_CLICKED) { - if (object == btnNextTime) { - valueTime = GetNext(valueTime); - - settingsController.SetPTSColorTime(valueTime); - lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); - lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); - lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); - } - if (object == btnPrevTime) { - valueTime = GetPrevious(valueTime); - settingsController.SetPTSColorTime(valueTime); - lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); - lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); - lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); - } - if (object == btnNextBar) { - valueBar = GetNext(valueBar); - if(valueBar == Controllers::Settings::Colors::Black) - valueBar = GetNext(valueBar); - settingsController.SetPTSColorBar(valueBar); - lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBar)); - } - if (object == btnPrevBar) { - valueBar = GetPrevious(valueBar); - if(valueBar == Controllers::Settings::Colors::Black) - valueBar = GetPrevious(valueBar); - settingsController.SetPTSColorBar(valueBar); - lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBar)); - } - if (object == btnNextBG) { - valueBG = GetNext(valueBG); - settingsController.SetPTSColorBG(valueBG); - lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBG)); - } - if (object == btnPrevBG) { - valueBG = GetPrevious(valueBG); - settingsController.SetPTSColorBG(valueBG); - lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBG)); - } - if (object == btnReset) { - settingsController.SetPTSColorTime(Controllers::Settings::Colors::Teal); - lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Teal)); - lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Teal)); - lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Teal)); - settingsController.SetPTSColorBar(Controllers::Settings::Colors::Teal); - lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Teal)); - settingsController.SetPTSColorBG(Controllers::Settings::Colors::Black); - lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Black)); - } - if (object == btnRandom) { - uint8_t randTime = rand() % 17; - uint8_t randBar = rand() % 17; - uint8_t randBG = rand() % 17; - // Check if the time color is the same as its background, or if the sidebar is black. If so, change them to more useful values. - if (randTime == randBG) { - randBG += 1; - } - if (randBar == 3) { - randBar -= 1; - } - settingsController.SetPTSColorTime(static_cast(randTime)); - lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randTime))); - lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randTime))); - lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randTime))); - settingsController.SetPTSColorBar(static_cast(randBar)); - lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randBar))); - settingsController.SetPTSColorBG(static_cast(randBG)); - lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randBG))); - } - } -} - -Pinetime::Controllers::Settings::Colors SettingPineTimeStyle::GetNext(Pinetime::Controllers::Settings::Colors color) { - auto colorAsInt = static_cast(color); - Pinetime::Controllers::Settings::Colors nextColor; - if (colorAsInt < 16) { - nextColor = static_cast(colorAsInt + 1); - } else { - nextColor = static_cast(0); - } - return nextColor; -} - -Pinetime::Controllers::Settings::Colors SettingPineTimeStyle::GetPrevious(Pinetime::Controllers::Settings::Colors color) { - auto colorAsInt = static_cast(color); - Pinetime::Controllers::Settings::Colors prevColor; - - if (colorAsInt > 0) { - prevColor = static_cast(colorAsInt - 1); - } else { - prevColor = static_cast(16); - } - return prevColor; -} diff --git a/src/displayapp/screens/settings/SettingPineTimeStyle.h b/src/displayapp/screens/settings/SettingPineTimeStyle.h deleted file mode 100644 index 397bd86..0000000 --- a/src/displayapp/screens/settings/SettingPineTimeStyle.h +++ /dev/null @@ -1,56 +0,0 @@ -#pragma once - -#include -#include -#include "components/settings/Settings.h" -#include "displayapp/screens/Screen.h" - -namespace Pinetime { - - namespace Applications { - namespace Screens { - - class SettingPineTimeStyle : public Screen{ - public: - SettingPineTimeStyle(DisplayApp* app, Pinetime::Controllers::Settings &settingsController); - ~SettingPineTimeStyle() override; - - void UpdateSelected(lv_obj_t *object, lv_event_t event); - - private: - Controllers::Settings& settingsController; - - Pinetime::Controllers::Settings::Colors GetNext(Controllers::Settings::Colors color); - Pinetime::Controllers::Settings::Colors GetPrevious(Controllers::Settings::Colors color); - - lv_obj_t * btnNextTime; - lv_obj_t * btnPrevTime; - lv_obj_t * btnNextBar; - lv_obj_t * btnPrevBar; - lv_obj_t * btnNextBG; - lv_obj_t * btnPrevBG; - lv_obj_t * btnReset; - lv_obj_t * btnRandom; - lv_obj_t * timebar; - lv_obj_t * sidebar; - lv_obj_t * timeDD1; - lv_obj_t * timeDD2; - lv_obj_t * timeAMPM; - lv_obj_t * dateDayOfWeek; - lv_obj_t * dateDay; - lv_obj_t * dateMonth; - lv_obj_t * backgroundLabel; - lv_obj_t * batteryIcon; - lv_obj_t * bleIcon; - lv_obj_t * calendarOuter; - lv_obj_t * calendarInner; - lv_obj_t * calendarBar1; - lv_obj_t * calendarBar2; - lv_obj_t * calendarCrossBar1; - lv_obj_t * calendarCrossBar2; - lv_obj_t * stepGauge; - lv_color_t needle_colors[1]; - }; - } - } -} diff --git a/src/displayapp/screens/settings/Settings.cpp b/src/displayapp/screens/settings/Settings.cpp index e3319f0..aa422e2 100644 --- a/src/displayapp/screens/settings/Settings.cpp +++ b/src/displayapp/screens/settings/Settings.cpp @@ -18,9 +18,6 @@ Settings::Settings(Pinetime::Applications::DisplayApp* app, Pinetime::Controller }, [this]() -> std::unique_ptr { return CreateScreen2(); - }, - [this]() -> std::unique_ptr { - return CreateScreen3(); }}, Screens::ScreenListModes::UpDown} { } @@ -42,7 +39,7 @@ std::unique_ptr Settings::CreateScreen1() { {Symbols::home, "Watch face", Apps::SettingWatchFace}, }}; - return std::make_unique(0, 3, app, settingsController, applications); + return std::make_unique(0, 2, app, settingsController, applications); } std::unique_ptr Settings::CreateScreen2() { @@ -50,21 +47,9 @@ std::unique_ptr Settings::CreateScreen2() { std::array applications {{ {Symbols::shoe, "Steps", Apps::SettingSteps}, {Symbols::batteryHalf, "Battery", Apps::BatteryInfo}, - {Symbols::paintbrush, "PTS Colors", Apps::SettingPineTimeStyle}, {Symbols::check, "Firmware", Apps::FirmwareValidation}, - }}; - - return std::make_unique(1, 3, app, settingsController, applications); -} - -std::unique_ptr Settings::CreateScreen3() { - - std::array applications {{ {Symbols::list, "About", Apps::SysInfo}, - {Symbols::none, "None", Apps::None}, - {Symbols::none, "None", Apps::None}, - {Symbols::none, "None", Apps::None}, }}; - return std::make_unique(2, 3, app, settingsController, applications); -} + return std::make_unique(1, 2, app, settingsController, applications); +} \ No newline at end of file -- cgit v0.10.2 From 1c86796eac20f6f8c3e6c1973fa080ef15bd7f3f Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Mon, 18 Oct 2021 22:52:53 +0200 Subject: More duplicate color dodging diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index e035f39..ad1b45e 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -419,8 +419,8 @@ void PineTimeStyle::Refresh() { lv_obj_set_style_local_scale_grad_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); } } - if (lv_obj_is_visible(btnSet) == true) { - if ((savedTick > 0) && (lv_tick_get() - savedTick > 5000)) { + if (lv_obj_get_hidden(btnSet) == false) { + if ((savedTick > 0) && (lv_tick_get() - savedTick > 3000)) { lv_obj_set_hidden(btnSet, true); savedTick = 0; } @@ -435,7 +435,8 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { if (event == LV_EVENT_CLICKED) { if (object == btnNextTime) { valueTime = GetNext(valueTime); - + if(valueTime == valueBG) + valueTime = GetNext(valueTime); settingsController.SetPTSColorTime(valueTime); lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); @@ -443,6 +444,8 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { } if (object == btnPrevTime) { valueTime = GetPrevious(valueTime); + if(valueTime == valueBG) + valueTime = GetPrevious(valueTime); settingsController.SetPTSColorTime(valueTime); lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); @@ -464,11 +467,15 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { } if (object == btnNextBG) { valueBG = GetNext(valueBG); + if(valueBG == valueTime) + valueBG = GetNext(valueBG); settingsController.SetPTSColorBG(valueBG); lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBG)); } if (object == btnPrevBG) { valueBG = GetPrevious(valueBG); + if(valueBG == valueTime) + valueBG = GetPrevious(valueBG); settingsController.SetPTSColorBG(valueBG); lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBG)); } -- cgit v0.10.2 From c4ab17f58707771256c6fffd8db63d32e2831610 Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Mon, 18 Oct 2021 23:04:12 +0200 Subject: Disable DoubleTap when settings buttons are displayed diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index ad1b45e..6dd8f48 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -306,6 +306,9 @@ bool PineTimeStyle::OnTouchEvent(Pinetime::Applications::TouchEvents event) { savedTick = lv_tick_get(); return true; } + if ((event == Pinetime::Applications::TouchEvents::DoubleTap) && (lv_obj_get_hidden(btnRandom) == false)) { + return true; + } return false; } -- cgit v0.10.2 From 1c3372b3195168897a0d563690df302848d32f86 Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Mon, 18 Oct 2021 23:29:41 +0200 Subject: Fix settings merge error diff --git a/src/displayapp/screens/settings/Settings.cpp b/src/displayapp/screens/settings/Settings.cpp index 46fa50a..2d05dde 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} { } @@ -39,7 +42,7 @@ std::unique_ptr Settings::CreateScreen1() { {Symbols::home, "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() { @@ -63,5 +66,5 @@ std::unique_ptr Settings::CreateScreen3() { {Symbols::none, "None", Apps::None} }}; - return std::make_unique(1, 2, app, settingsController, applications); + return std::make_unique(2, 3, app, settingsController, applications); } \ No newline at end of file -- cgit v0.10.2 From 994f373a1428d3d82f12ada60ab5bd05dc99f708 Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Tue, 19 Oct 2021 00:22:45 +0200 Subject: Change gauge needle color when background is white diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index 6d4855d..21599cc 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -168,7 +168,11 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app, lv_obj_align(dateMonth, sidebar, LV_ALIGN_CENTER, 0, 32); // Step count gauge - needle_colors[0] = LV_COLOR_WHITE; + if (settingsController.GetPTSColorBar() == Pinetime::Controllers::Settings::Colors::White) { + needle_colors[0] = LV_COLOR_BLACK; + } else { + needle_colors[0] = LV_COLOR_WHITE; + } stepGauge = lv_gauge_create(lv_scr_act(), nullptr); lv_gauge_set_needle_count(stepGauge, 1, needle_colors); lv_obj_set_size(stepGauge, 40, 40); @@ -458,6 +462,11 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { valueBar = GetNext(valueBar); if(valueBar == Controllers::Settings::Colors::Black) valueBar = GetNext(valueBar); + if(valueBar == Controllers::Settings::Colors::White) { + needle_colors[0] = LV_COLOR_BLACK; + } else { + needle_colors[0] = LV_COLOR_WHITE; + } settingsController.SetPTSColorBar(valueBar); lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBar)); } @@ -465,6 +474,11 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { valueBar = GetPrevious(valueBar); if(valueBar == Controllers::Settings::Colors::Black) valueBar = GetPrevious(valueBar); + if(valueBar == Controllers::Settings::Colors::White) { + needle_colors[0] = LV_COLOR_BLACK; + } else { + needle_colors[0] = LV_COLOR_WHITE; + } settingsController.SetPTSColorBar(valueBar); lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBar)); } -- cgit v0.10.2 From f45e094adf4dee6b226ba122aae9e53f47e1b4d6 Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Wed, 20 Oct 2021 11:25:06 +0200 Subject: Ensure needle color is visible one reset/randomize diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index 21599cc..98f15ef 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -497,6 +497,7 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBG)); } if (object == btnReset) { + needle_colors[0] = LV_COLOR_WHITE; settingsController.SetPTSColorTime(Controllers::Settings::Colors::Teal); lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Teal)); lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Teal)); @@ -517,6 +518,11 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { if (randBar == 3) { randBar -= 1; } + if (randBar == 0) { + needle_colors[0] = LV_COLOR_BLACK; + } else { + needle_colors[0] = LV_COLOR_WHITE; + } settingsController.SetPTSColorTime(static_cast(randTime)); lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randTime))); lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randTime))); -- cgit v0.10.2 From 074d3420c812e89e23c95cc36db78749ff553428 Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Wed, 20 Oct 2021 11:30:06 +0200 Subject: Ensure needle color is visible on reset/randomize diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index 21599cc..98f15ef 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -497,6 +497,7 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBG)); } if (object == btnReset) { + needle_colors[0] = LV_COLOR_WHITE; settingsController.SetPTSColorTime(Controllers::Settings::Colors::Teal); lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Teal)); lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Teal)); @@ -517,6 +518,11 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { if (randBar == 3) { randBar -= 1; } + if (randBar == 0) { + needle_colors[0] = LV_COLOR_BLACK; + } else { + needle_colors[0] = LV_COLOR_WHITE; + } settingsController.SetPTSColorTime(static_cast(randTime)); lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randTime))); lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randTime))); -- cgit v0.10.2 From 32978b6a06330dcc5b7e757a4ba9d9b5349277f2 Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Wed, 20 Oct 2021 15:36:28 +0200 Subject: Restore settings order diff --git a/src/displayapp/screens/settings/Settings.cpp b/src/displayapp/screens/settings/Settings.cpp index 2d05dde..40a5a66 100644 --- a/src/displayapp/screens/settings/Settings.cpp +++ b/src/displayapp/screens/settings/Settings.cpp @@ -49,9 +49,9 @@ std::unique_ptr Settings::CreateScreen2() { std::array applications {{ {Symbols::shoe, "Steps", Apps::SettingSteps}, - {Symbols::batteryHalf, "Battery", Apps::BatteryInfo}, {Symbols::clock, "Set date", Apps::SettingSetDate}, - {Symbols::clock, "Set time", Apps::SettingSetTime} + {Symbols::clock, "Set time", Apps::SettingSetTime}, + {Symbols::batteryHalf, "Battery", Apps::BatteryInfo} }}; return std::make_unique(1, 3, app, settingsController, applications); -- cgit v0.10.2 From 3ed01b33e7303a64615bfc0db2e9d42bb2624bb6 Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Wed, 20 Oct 2021 17:44:10 +0200 Subject: Improve random color selection, disable longpress when settings are visible diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index 98f15ef..fa9aec1 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -305,7 +305,7 @@ PineTimeStyle::~PineTimeStyle() { } bool PineTimeStyle::OnTouchEvent(Pinetime::Applications::TouchEvents event) { - if (event == Pinetime::Applications::TouchEvents::LongTap) { + if ((event == Pinetime::Applications::TouchEvents::LongTap) && (lv_obj_get_hidden(btnRandom) == true)) { lv_obj_set_hidden(btnSet, false); savedTick = lv_tick_get(); return true; @@ -508,29 +508,28 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(Controllers::Settings::Colors::Black)); } if (object == btnRandom) { - uint8_t randTime = rand() % 17; - uint8_t randBar = rand() % 17; - uint8_t randBG = rand() % 17; - // Check if the time color is the same as its background, or if the sidebar is black. If so, change them to more useful values. - if (randTime == randBG) { - randBG += 1; + valueTime = static_cast(rand() % 17); + valueBar = static_cast(rand() % 17); + valueBG = static_cast(rand() % 17); + if (valueTime == valueBG) { + valueBG = GetNext(valueBG); } - if (randBar == 3) { - randBar -= 1; + if (valueBar == Controllers::Settings::Colors::Black) { + valueBar = GetPrevious(valueBar); } - if (randBar == 0) { + if (valueBar == Controllers::Settings::Colors::White) { needle_colors[0] = LV_COLOR_BLACK; } else { needle_colors[0] = LV_COLOR_WHITE; } - settingsController.SetPTSColorTime(static_cast(randTime)); - lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randTime))); - lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randTime))); - lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randTime))); - settingsController.SetPTSColorBar(static_cast(randBar)); - lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randBar))); - settingsController.SetPTSColorBG(static_cast(randBG)); - lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(static_cast(randBG))); + settingsController.SetPTSColorTime(static_cast(valueTime)); + lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); + lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); + lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); + settingsController.SetPTSColorBar(static_cast(valueBar)); + lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBar)); + settingsController.SetPTSColorBG(static_cast(valueBG)); + lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBG)); } if (object == btnClose) { settingsController.SaveSettings(); -- cgit v0.10.2 From 411c10ec317464a79c353dc5c18b805cf4bdf7d0 Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Wed, 20 Oct 2021 18:07:08 +0200 Subject: Update GetNext/GetPrevious diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index fa9aec1..a2b94b5 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -561,22 +561,13 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { Pinetime::Controllers::Settings::Colors PineTimeStyle::GetNext(Pinetime::Controllers::Settings::Colors color) { auto colorAsInt = static_cast(color); Pinetime::Controllers::Settings::Colors nextColor; - if (colorAsInt < 16) { - nextColor = static_cast(colorAsInt + 1); - } else { - nextColor = static_cast(0); - } + nextColor = static_cast((colorAsInt + 1) % 17); return nextColor; } Pinetime::Controllers::Settings::Colors PineTimeStyle::GetPrevious(Pinetime::Controllers::Settings::Colors color) { auto colorAsInt = static_cast(color); Pinetime::Controllers::Settings::Colors prevColor; - - if (colorAsInt > 0) { - prevColor = static_cast(colorAsInt - 1); - } else { - prevColor = static_cast(16); - } + prevColor = static_cast((colorAsInt - 1) % 17); return prevColor; } \ No newline at end of file -- cgit v0.10.2 From 85d494a987e8edfd51fbb0eb6dfa04ea108cbb48 Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Sat, 23 Oct 2021 18:12:41 +0200 Subject: Revert "Update GetNext/GetPrevious" This reverts commit 411c10ec317464a79c353dc5c18b805cf4bdf7d0. diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index a2b94b5..fa9aec1 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -561,13 +561,22 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { Pinetime::Controllers::Settings::Colors PineTimeStyle::GetNext(Pinetime::Controllers::Settings::Colors color) { auto colorAsInt = static_cast(color); Pinetime::Controllers::Settings::Colors nextColor; - nextColor = static_cast((colorAsInt + 1) % 17); + if (colorAsInt < 16) { + nextColor = static_cast(colorAsInt + 1); + } else { + nextColor = static_cast(0); + } return nextColor; } Pinetime::Controllers::Settings::Colors PineTimeStyle::GetPrevious(Pinetime::Controllers::Settings::Colors color) { auto colorAsInt = static_cast(color); Pinetime::Controllers::Settings::Colors prevColor; - prevColor = static_cast((colorAsInt - 1) % 17); + + if (colorAsInt > 0) { + prevColor = static_cast(colorAsInt - 1); + } else { + prevColor = static_cast(16); + } return prevColor; } \ No newline at end of file -- cgit v0.10.2 From d5dfa8087679b644c13e1d420b8ef2fc894b3b51 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 25 Oct 2021 12:53:14 +0300 Subject: Newer buttonhandler diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a839e08..e727b2b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -507,6 +507,7 @@ list(APPEND SOURCE_FILES components/heartrate/Ptagc.cpp components/heartrate/HeartRateController.cpp + buttonhandler/ButtonHandler.cpp touchhandler/TouchHandler.cpp ) @@ -567,6 +568,7 @@ list(APPEND RECOVERY_SOURCE_FILES components/heartrate/Ptagc.cpp components/motor/MotorController.cpp components/fs/FS.cpp + buttonhandler/ButtonHandler.cpp touchhandler/TouchHandler.cpp ) @@ -681,6 +683,7 @@ set(INCLUDE_FILES components/heartrate/Ptagc.h components/heartrate/HeartRateController.h components/motor/MotorController.h + buttonhandler/ButtonHandler.h touchhandler/TouchHandler.h ) diff --git a/src/buttonhandler/ButtonHandler.cpp b/src/buttonhandler/ButtonHandler.cpp new file mode 100644 index 0000000..997409e --- /dev/null +++ b/src/buttonhandler/ButtonHandler.cpp @@ -0,0 +1,85 @@ +#include "ButtonHandler.h" + +using namespace Pinetime::Controllers; + +void ButtonTimerCallback(TimerHandle_t xTimer) { + auto* buttonHandler = static_cast(pvTimerGetTimerID(xTimer)); + buttonHandler->HandleEvent(ButtonHandler::Timer); +} + +void ButtonHandler::Init(Pinetime::System::SystemTask* systemTask) { + this->systemTask = systemTask; + buttonTimer = xTimerCreate("buttonTimer", 0, pdFALSE, this, ButtonTimerCallback); +} + +void ButtonHandler::HandleEvent(events event) { + static constexpr TickType_t doubleClickTime = pdMS_TO_TICKS(200); + static constexpr TickType_t longPressTime = pdMS_TO_TICKS(400); + static constexpr TickType_t longerPressTime = pdMS_TO_TICKS(2000); + + if (systemTask->IsSleeping()) { + // This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping + systemTask->PushMessage(System::Messages::GoToRunning); + } else { + systemTask->PushMessage(System::Messages::ReloadIdleTimer); + } + + if (event == Press) { + buttonPressed = true; + } else if (event == Release) { + releaseTime = xTaskGetTickCount(); + buttonPressed = false; + } + + switch (state) { + case Idle: + if (event == Press) { + xTimerChangePeriod(buttonTimer, doubleClickTime, 0); + xTimerStart(buttonTimer, 0); + state = Pressed; + } + break; + case Pressed: + if (event == Press) { + if (xTaskGetTickCount() - releaseTime < doubleClickTime) { + systemTask->PushMessage(System::Messages::OnButtonDoubleClicked); + xTimerStop(buttonTimer, 0); + state = Idle; + } + } else if (event == Release) { + xTimerChangePeriod(buttonTimer, doubleClickTime, 0); + xTimerStart(buttonTimer, 0); + } else if (event == Timer) { + if (buttonPressed) { + xTimerChangePeriod(buttonTimer, longPressTime - doubleClickTime, 0); + xTimerStart(buttonTimer, 0); + state = Holding; + } else { + systemTask->PushMessage(System::Messages::OnButtonPushed); + state = Idle; + } + } + break; + case Holding: + if (event == Release) { + systemTask->PushMessage(System::Messages::OnButtonPushed); + xTimerStop(buttonTimer, 0); + state = Idle; + } else if (event == Timer) { + xTimerChangePeriod(buttonTimer, longerPressTime - longPressTime - doubleClickTime, 0); + xTimerStart(buttonTimer, 0); + systemTask->PushMessage(System::Messages::OnButtonLongPressed); + state = LongHeld; + } + break; + case LongHeld: + if (event == Release) { + xTimerStop(buttonTimer, 0); + state = Idle; + } else if (event == Timer) { + systemTask->PushMessage(System::Messages::OnButtonLongerPressed); + state = Idle; + } + break; + } +} diff --git a/src/buttonhandler/ButtonHandler.h b/src/buttonhandler/ButtonHandler.h new file mode 100644 index 0000000..5d5b57e --- /dev/null +++ b/src/buttonhandler/ButtonHandler.h @@ -0,0 +1,24 @@ +#pragma once + +#include "systemtask/SystemTask.h" +#include +#include + +namespace Pinetime { + namespace Controllers { + class ButtonHandler { + public: + enum events { Press, Release, Timer }; + void Init(Pinetime::System::SystemTask* systemTask); + void HandleEvent(events event); + + private: + Pinetime::System::SystemTask* systemTask = nullptr; + TickType_t releaseTime = 0; + TimerHandle_t buttonTimer; + bool buttonPressed = false; + enum states { Idle, Pressed, Holding, LongHeld }; + states state = Idle; + }; + } +} diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index abe5851..13ee004 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -260,6 +260,20 @@ void DisplayApp::Refresh() { } } break; + case Messages::ButtonLongPressed: + if (currentApp != Apps::Clock) { + LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::Down); + } + break; + case Messages::ButtonLongerPressed: + // Create reboot app and open it instead + LoadApp(Apps::SysInfo, DisplayApp::FullRefreshDirections::Up); + break; + case Messages::ButtonDoubleClicked: + if (currentApp != Apps::Notifications && currentApp != Apps::NotificationsPreview) { + LoadApp(Apps::Notifications, DisplayApp::FullRefreshDirections::Down); + } + break; case Messages::BleFirmwareUpdateStarted: LoadApp(Apps::FirmwareUpdate, DisplayApp::FullRefreshDirections::Down); diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index d48b646..ab0a060 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -9,6 +9,9 @@ namespace Pinetime { UpdateBleConnection, TouchEvent, ButtonPushed, + ButtonLongPressed, + ButtonLongerPressed, + ButtonDoubleClicked, NewNotification, TimerDone, BleFirmwareUpdateStarted, diff --git a/src/main.cpp b/src/main.cpp index fc77235..b942fd4 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -47,6 +47,7 @@ #include "systemtask/SystemTask.h" #include "drivers/PinMap.h" #include "touchhandler/TouchHandler.h" +#include "buttonhandler/ButtonHandler.h" #if NRF_LOG_ENABLED #include "logging/NrfLogger.h" @@ -96,8 +97,6 @@ TimerHandle_t debounceTimer; TimerHandle_t debounceChargeTimer; Pinetime::Controllers::Battery batteryController; Pinetime::Controllers::Ble bleController; -static constexpr uint8_t pinTouchIrq = Pinetime::PinMap::Cst816sIrq; -static constexpr uint8_t pinPowerPresentIrq = Pinetime::PinMap::PowerPresent; Pinetime::Controllers::HeartRateController heartRateController; Pinetime::Applications::HeartRateTask heartRateApp(heartRateSensor, heartRateController); @@ -110,6 +109,7 @@ Pinetime::Controllers::MotionController motionController; Pinetime::Controllers::TimerController timerController; Pinetime::Controllers::AlarmController alarmController {dateTimeController}; Pinetime::Controllers::TouchHandler touchHandler(touchPanel, lvgl); +Pinetime::Controllers::ButtonHandler buttonHandler; Pinetime::Controllers::FS fs {spiNorFlash}; Pinetime::Controllers::Settings settingsController {fs}; @@ -153,7 +153,8 @@ Pinetime::System::SystemTask systemTask(spi, displayApp, heartRateApp, fs, - touchHandler); + touchHandler, + buttonHandler); /* Variable Declarations for variables in noinit SRAM Increment NoInit_MagicValue upon adding variables to this area @@ -176,11 +177,11 @@ void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action if (pin == Pinetime::PinMap::PowerPresent and action == NRF_GPIOTE_POLARITY_TOGGLE) { xTimerStartFromISR(debounceChargeTimer, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); - return; + } else if (pin == Pinetime::PinMap::Button) { + // This activates on button release as well due to bouncing + xTimerStartFromISR(debounceTimer, &xHigherPriorityTaskWoken); + portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } - - xTimerStartFromISR(debounceTimer, &xHigherPriorityTaskWoken); - portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } void DebounceTimerChargeCallback(TimerHandle_t xTimer) { @@ -188,9 +189,8 @@ void DebounceTimerChargeCallback(TimerHandle_t xTimer) { systemTask.PushMessage(Pinetime::System::Messages::OnChargingEvent); } -void DebounceTimerCallback(TimerHandle_t xTimer) { - xTimerStop(xTimer, 0); - systemTask.OnButtonPushed(); +void DebounceTimerCallback(TimerHandle_t /*unused*/) { + systemTask.PushMessage(Pinetime::System::Messages::HandleButtonEvent); } void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) { @@ -319,8 +319,8 @@ int main(void) { } nrf_gpio_cfg_default(Pinetime::PinMap::TwiScl); - debounceTimer = xTimerCreate("debounceTimer", 200, pdFALSE, (void*) 0, DebounceTimerCallback); - debounceChargeTimer = xTimerCreate("debounceTimerCharge", 200, pdFALSE, (void*) 0, DebounceTimerChargeCallback); + debounceTimer = xTimerCreate("debounceTimer", 10, pdFALSE, nullptr, DebounceTimerCallback); + debounceChargeTimer = xTimerCreate("debounceTimerCharge", 200, pdFALSE, nullptr, DebounceTimerChargeCallback); // retrieve version stored by bootloader Pinetime::BootloaderVersion::SetVersion(NRF_TIMER2->CC[0]); diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h index 5aa218d..b0bdbf3 100644 --- a/src/systemtask/Messages.h +++ b/src/systemtask/Messages.h @@ -15,12 +15,17 @@ namespace Pinetime { BleFirmwareUpdateStarted, BleFirmwareUpdateFinished, OnTouchEvent, - OnButtonEvent, + OnButtonPushed, + OnButtonLongPressed, + OnButtonLongerPressed, + OnButtonDoubleClicked, + HandleButtonEvent, OnDisplayTaskSleeping, EnableSleeping, DisableSleeping, OnNewDay, OnChargingEvent, + ReloadIdleTimer, SetOffAlarm, StopRinging, MeasureBatteryTimerExpired, diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index e0a5907..b7db0b9 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -25,7 +25,6 @@ #include "main.h" #include "BootErrors.h" - #include using namespace Pinetime::System; @@ -77,7 +76,8 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi, Pinetime::Applications::DisplayApp& displayApp, Pinetime::Applications::HeartRateTask& heartRateApp, Pinetime::Controllers::FS& fs, - Pinetime::Controllers::TouchHandler& touchHandler) + Pinetime::Controllers::TouchHandler& touchHandler, + Pinetime::Controllers::ButtonHandler& buttonHandler) : spi {spi}, lcd {lcd}, spiNorFlash {spiNorFlash}, @@ -101,8 +101,15 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi, heartRateApp(heartRateApp), fs {fs}, touchHandler {touchHandler}, - nimbleController(*this, bleController, dateTimeController, notificationManager, - batteryController, spiNorFlash, heartRateController, motionController) { + buttonHandler {buttonHandler}, + nimbleController(*this, + bleController, + dateTimeController, + notificationManager, + batteryController, + spiNorFlash, + heartRateController, + motionController) { } void SystemTask::Start() { @@ -163,6 +170,8 @@ void SystemTask::Work() { heartRateSensor.Disable(); heartRateApp.Start(); + buttonHandler.Init(this); + // Button nrf_gpio_cfg_output(15); nrf_gpio_pin_set(15); @@ -326,9 +335,32 @@ void SystemTask::Work() { ReloadIdleTimer(); displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent); break; - case Messages::OnButtonEvent: - ReloadIdleTimer(); - displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonPushed); + case Messages::OnButtonPushed: + if (!isSleeping && !isGoingToSleep) { + displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonPushed); + } + break; + case Messages::OnButtonLongPressed: + if (!isSleeping) { + displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonLongPressed); + } + break; + case Messages::OnButtonLongerPressed: + if (!isSleeping) { + displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonLongerPressed); + } + break; + case Messages::OnButtonDoubleClicked: + if (!isSleeping) { + displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonDoubleClicked); + } + break; + case Messages::HandleButtonEvent: + if (nrf_gpio_pin_read(Pinetime::PinMap::Button) == 0) { + buttonHandler.HandleEvent(Pinetime::Controllers::ButtonHandler::Release); + } else { + buttonHandler.HandleEvent(Pinetime::Controllers::ButtonHandler::Press); + } break; case Messages::OnDisplayTaskSleeping: if (BootloaderVersion::IsValid()) { @@ -366,6 +398,9 @@ void SystemTask::Work() { case Messages::BatteryPercentageUpdated: nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining()); break; + case Messages::ReloadIdleTimer: + ReloadIdleTimer(); + break; default: break; @@ -414,20 +449,6 @@ void SystemTask::UpdateMotion() { } } -void SystemTask::OnButtonPushed() { - if (isGoingToSleep) - return; - if (!isSleeping) { - NRF_LOG_INFO("[systemtask] Button pushed"); - PushMessage(Messages::OnButtonEvent); - } else { - if (!isWakingUp) { - NRF_LOG_INFO("[systemtask] Button pushed, waking up"); - GoToRunning(); - } - } -} - void SystemTask::GoToRunning() { if (isGoingToSleep or (not isSleeping) or isWakingUp) return; diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index 879c1be..9967f75 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -20,6 +20,7 @@ #include "components/alarm/AlarmController.h" #include "components/fs/FS.h" #include "touchhandler/TouchHandler.h" +#include "buttonhandler/ButtonHandler.h" #ifdef PINETIME_IS_RECOVERY #include "displayapp/DisplayAppRecovery.h" @@ -45,6 +46,7 @@ namespace Pinetime { } namespace Controllers { class TouchHandler; + class ButtonHandler; } namespace System { class SystemTask { @@ -71,12 +73,12 @@ namespace Pinetime { Pinetime::Applications::DisplayApp& displayApp, Pinetime::Applications::HeartRateTask& heartRateApp, Pinetime::Controllers::FS& fs, - Pinetime::Controllers::TouchHandler& touchHandler); + Pinetime::Controllers::TouchHandler& touchHandler, + Pinetime::Controllers::ButtonHandler& buttonHandler); void Start(); void PushMessage(Messages msg); - void OnButtonPushed(); void OnTouchEvent(); void OnIdle(); @@ -123,6 +125,7 @@ namespace Pinetime { Pinetime::Applications::HeartRateTask& heartRateApp; Pinetime::Controllers::FS& fs; Pinetime::Controllers::TouchHandler& touchHandler; + Pinetime::Controllers::ButtonHandler& buttonHandler; Pinetime::Controllers::NimbleController nimbleController; static void Process(void* instance); -- cgit v0.10.2 From b19a2a760b74f27c8d3db262bf43437f722f74bd Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 25 Oct 2021 13:40:43 +0300 Subject: Use enum classes, remove old comment diff --git a/src/buttonhandler/ButtonHandler.cpp b/src/buttonhandler/ButtonHandler.cpp index 997409e..b6067d2 100644 --- a/src/buttonhandler/ButtonHandler.cpp +++ b/src/buttonhandler/ButtonHandler.cpp @@ -4,7 +4,7 @@ using namespace Pinetime::Controllers; void ButtonTimerCallback(TimerHandle_t xTimer) { auto* buttonHandler = static_cast(pvTimerGetTimerID(xTimer)); - buttonHandler->HandleEvent(ButtonHandler::Timer); + buttonHandler->HandleEvent(ButtonHandler::Events::Timer); } void ButtonHandler::Init(Pinetime::System::SystemTask* systemTask) { @@ -12,7 +12,7 @@ void ButtonHandler::Init(Pinetime::System::SystemTask* systemTask) { buttonTimer = xTimerCreate("buttonTimer", 0, pdFALSE, this, ButtonTimerCallback); } -void ButtonHandler::HandleEvent(events event) { +void ButtonHandler::HandleEvent(Events event) { static constexpr TickType_t doubleClickTime = pdMS_TO_TICKS(200); static constexpr TickType_t longPressTime = pdMS_TO_TICKS(400); static constexpr TickType_t longerPressTime = pdMS_TO_TICKS(2000); @@ -24,61 +24,61 @@ void ButtonHandler::HandleEvent(events event) { systemTask->PushMessage(System::Messages::ReloadIdleTimer); } - if (event == Press) { + if (event == Events::Press) { buttonPressed = true; - } else if (event == Release) { + } else if (event == Events::Release) { releaseTime = xTaskGetTickCount(); buttonPressed = false; } switch (state) { - case Idle: - if (event == Press) { + case States::Idle: + if (event == Events::Press) { xTimerChangePeriod(buttonTimer, doubleClickTime, 0); xTimerStart(buttonTimer, 0); - state = Pressed; + state = States::Pressed; } break; - case Pressed: - if (event == Press) { + case States::Pressed: + if (event == Events::Press) { if (xTaskGetTickCount() - releaseTime < doubleClickTime) { systemTask->PushMessage(System::Messages::OnButtonDoubleClicked); xTimerStop(buttonTimer, 0); - state = Idle; + state = States::Idle; } - } else if (event == Release) { + } else if (event == Events::Release) { xTimerChangePeriod(buttonTimer, doubleClickTime, 0); xTimerStart(buttonTimer, 0); - } else if (event == Timer) { + } else if (event == Events::Timer) { if (buttonPressed) { xTimerChangePeriod(buttonTimer, longPressTime - doubleClickTime, 0); xTimerStart(buttonTimer, 0); - state = Holding; + state = States::Holding; } else { systemTask->PushMessage(System::Messages::OnButtonPushed); - state = Idle; + state = States::Idle; } } break; - case Holding: - if (event == Release) { + case States::Holding: + if (event == Events::Release) { systemTask->PushMessage(System::Messages::OnButtonPushed); xTimerStop(buttonTimer, 0); - state = Idle; - } else if (event == Timer) { + state = States::Idle; + } else if (event == Events::Timer) { xTimerChangePeriod(buttonTimer, longerPressTime - longPressTime - doubleClickTime, 0); xTimerStart(buttonTimer, 0); systemTask->PushMessage(System::Messages::OnButtonLongPressed); - state = LongHeld; + state = States::LongHeld; } break; - case LongHeld: - if (event == Release) { + case States::LongHeld: + if (event == Events::Release) { xTimerStop(buttonTimer, 0); - state = Idle; - } else if (event == Timer) { + state = States::Idle; + } else if (event == Events::Timer) { systemTask->PushMessage(System::Messages::OnButtonLongerPressed); - state = Idle; + state = States::Idle; } break; } diff --git a/src/buttonhandler/ButtonHandler.h b/src/buttonhandler/ButtonHandler.h index 5d5b57e..b4c36bd 100644 --- a/src/buttonhandler/ButtonHandler.h +++ b/src/buttonhandler/ButtonHandler.h @@ -8,17 +8,17 @@ namespace Pinetime { namespace Controllers { class ButtonHandler { public: - enum events { Press, Release, Timer }; + enum class Events : uint8_t { Press, Release, Timer }; void Init(Pinetime::System::SystemTask* systemTask); - void HandleEvent(events event); + void HandleEvent(Events event); private: + enum class States : uint8_t { Idle, Pressed, Holding, LongHeld }; Pinetime::System::SystemTask* systemTask = nullptr; TickType_t releaseTime = 0; TimerHandle_t buttonTimer; bool buttonPressed = false; - enum states { Idle, Pressed, Holding, LongHeld }; - states state = Idle; + States state = States::Idle; }; } } diff --git a/src/main.cpp b/src/main.cpp index b942fd4..53f78ce 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -178,7 +178,6 @@ void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action xTimerStartFromISR(debounceChargeTimer, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } else if (pin == Pinetime::PinMap::Button) { - // This activates on button release as well due to bouncing xTimerStartFromISR(debounceTimer, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index b7db0b9..8a4f894 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -357,9 +357,9 @@ void SystemTask::Work() { break; case Messages::HandleButtonEvent: if (nrf_gpio_pin_read(Pinetime::PinMap::Button) == 0) { - buttonHandler.HandleEvent(Pinetime::Controllers::ButtonHandler::Release); + buttonHandler.HandleEvent(Pinetime::Controllers::ButtonHandler::Events::Release); } else { - buttonHandler.HandleEvent(Pinetime::Controllers::ButtonHandler::Press); + buttonHandler.HandleEvent(Pinetime::Controllers::ButtonHandler::Events::Press); } break; case Messages::OnDisplayTaskSleeping: -- cgit v0.10.2 From 351c60a13167c05dfdbb0516f84077a4cd6adeec Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 25 Oct 2021 16:57:29 +0300 Subject: Return button action instead of pushing messages diff --git a/src/buttonhandler/ButtonActions.h b/src/buttonhandler/ButtonActions.h new file mode 100644 index 0000000..21be441 --- /dev/null +++ b/src/buttonhandler/ButtonActions.h @@ -0,0 +1,7 @@ +#pragma once + +namespace Pinetime { + namespace Controllers { + enum class ButtonActions { None, Click, DoubleClick, LongPress, LongerPress }; + } +} diff --git a/src/buttonhandler/ButtonHandler.cpp b/src/buttonhandler/ButtonHandler.cpp index b6067d2..91e8bbd 100644 --- a/src/buttonhandler/ButtonHandler.cpp +++ b/src/buttonhandler/ButtonHandler.cpp @@ -3,27 +3,19 @@ using namespace Pinetime::Controllers; void ButtonTimerCallback(TimerHandle_t xTimer) { - auto* buttonHandler = static_cast(pvTimerGetTimerID(xTimer)); - buttonHandler->HandleEvent(ButtonHandler::Events::Timer); + auto* sysTask = static_cast(pvTimerGetTimerID(xTimer)); + sysTask->PushMessage(Pinetime::System::Messages::HandleButtonTimerEvent); } void ButtonHandler::Init(Pinetime::System::SystemTask* systemTask) { - this->systemTask = systemTask; - buttonTimer = xTimerCreate("buttonTimer", 0, pdFALSE, this, ButtonTimerCallback); + buttonTimer = xTimerCreate("buttonTimer", 0, pdFALSE, systemTask, ButtonTimerCallback); } -void ButtonHandler::HandleEvent(Events event) { +ButtonActions ButtonHandler::HandleEvent(Events event) { static constexpr TickType_t doubleClickTime = pdMS_TO_TICKS(200); static constexpr TickType_t longPressTime = pdMS_TO_TICKS(400); static constexpr TickType_t longerPressTime = pdMS_TO_TICKS(2000); - if (systemTask->IsSleeping()) { - // This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping - systemTask->PushMessage(System::Messages::GoToRunning); - } else { - systemTask->PushMessage(System::Messages::ReloadIdleTimer); - } - if (event == Events::Press) { buttonPressed = true; } else if (event == Events::Release) { @@ -42,9 +34,9 @@ void ButtonHandler::HandleEvent(Events event) { case States::Pressed: if (event == Events::Press) { if (xTaskGetTickCount() - releaseTime < doubleClickTime) { - systemTask->PushMessage(System::Messages::OnButtonDoubleClicked); xTimerStop(buttonTimer, 0); state = States::Idle; + return ButtonActions::DoubleClick; } } else if (event == Events::Release) { xTimerChangePeriod(buttonTimer, doubleClickTime, 0); @@ -55,21 +47,21 @@ void ButtonHandler::HandleEvent(Events event) { xTimerStart(buttonTimer, 0); state = States::Holding; } else { - systemTask->PushMessage(System::Messages::OnButtonPushed); state = States::Idle; + return ButtonActions::Click; } } break; case States::Holding: if (event == Events::Release) { - systemTask->PushMessage(System::Messages::OnButtonPushed); xTimerStop(buttonTimer, 0); state = States::Idle; + return ButtonActions::Click; } else if (event == Events::Timer) { xTimerChangePeriod(buttonTimer, longerPressTime - longPressTime - doubleClickTime, 0); xTimerStart(buttonTimer, 0); - systemTask->PushMessage(System::Messages::OnButtonLongPressed); state = States::LongHeld; + return ButtonActions::LongPress; } break; case States::LongHeld: @@ -77,9 +69,10 @@ void ButtonHandler::HandleEvent(Events event) { xTimerStop(buttonTimer, 0); state = States::Idle; } else if (event == Events::Timer) { - systemTask->PushMessage(System::Messages::OnButtonLongerPressed); state = States::Idle; + return ButtonActions::LongerPress; } break; } + return ButtonActions::None; } diff --git a/src/buttonhandler/ButtonHandler.h b/src/buttonhandler/ButtonHandler.h index b4c36bd..44b20f1 100644 --- a/src/buttonhandler/ButtonHandler.h +++ b/src/buttonhandler/ButtonHandler.h @@ -1,5 +1,6 @@ #pragma once +#include "ButtonActions.h" #include "systemtask/SystemTask.h" #include #include @@ -10,11 +11,10 @@ namespace Pinetime { public: enum class Events : uint8_t { Press, Release, Timer }; void Init(Pinetime::System::SystemTask* systemTask); - void HandleEvent(Events event); + ButtonActions HandleEvent(Events event); private: enum class States : uint8_t { Idle, Pressed, Holding, LongHeld }; - Pinetime::System::SystemTask* systemTask = nullptr; TickType_t releaseTime = 0; TimerHandle_t buttonTimer; bool buttonPressed = false; diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h index b0bdbf3..b714270 100644 --- a/src/systemtask/Messages.h +++ b/src/systemtask/Messages.h @@ -15,17 +15,13 @@ namespace Pinetime { BleFirmwareUpdateStarted, BleFirmwareUpdateFinished, OnTouchEvent, - OnButtonPushed, - OnButtonLongPressed, - OnButtonLongerPressed, - OnButtonDoubleClicked, HandleButtonEvent, + HandleButtonTimerEvent, OnDisplayTaskSleeping, EnableSleeping, DisableSleeping, OnNewDay, OnChargingEvent, - ReloadIdleTimer, SetOffAlarm, StopRinging, MeasureBatteryTimerExpired, diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 8a4f894..85cefb6 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -335,33 +335,25 @@ void SystemTask::Work() { ReloadIdleTimer(); displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent); break; - case Messages::OnButtonPushed: - if (!isSleeping && !isGoingToSleep) { - displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonPushed); - } - break; - case Messages::OnButtonLongPressed: - if (!isSleeping) { - displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonLongPressed); - } - break; - case Messages::OnButtonLongerPressed: - if (!isSleeping) { - displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonLongerPressed); - } - break; - case Messages::OnButtonDoubleClicked: - if (!isSleeping) { - displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonDoubleClicked); + case Messages::HandleButtonEvent: { + // This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping + if (IsSleeping()) { + GoToRunning(); + break; } - break; - case Messages::HandleButtonEvent: + + Controllers::ButtonActions action; if (nrf_gpio_pin_read(Pinetime::PinMap::Button) == 0) { - buttonHandler.HandleEvent(Pinetime::Controllers::ButtonHandler::Events::Release); + action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Release); } else { - buttonHandler.HandleEvent(Pinetime::Controllers::ButtonHandler::Events::Press); + action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Press); } - break; + HandleButtonAction(action); + } break; + case Messages::HandleButtonTimerEvent: { + auto action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Timer); + HandleButtonAction(action); + } break; case Messages::OnDisplayTaskSleeping: if (BootloaderVersion::IsValid()) { // First versions of the bootloader do not expose their version and cannot initialize the SPI NOR FLASH @@ -398,9 +390,6 @@ void SystemTask::Work() { case Messages::BatteryPercentageUpdated: nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining()); break; - case Messages::ReloadIdleTimer: - ReloadIdleTimer(); - break; default: break; @@ -449,6 +438,35 @@ void SystemTask::UpdateMotion() { } } +void SystemTask::HandleButtonAction(Controllers::ButtonActions action) { + if (IsSleeping()) { + return; + } + + ReloadIdleTimer(); + + using Actions = Controllers::ButtonActions; + + switch (action) { + case Actions::Click: + if (!isGoingToSleep) { + displayApp.PushMessage(Applications::Display::Messages::ButtonPushed); + } + break; + case Actions::DoubleClick: + displayApp.PushMessage(Applications::Display::Messages::ButtonDoubleClicked); + break; + case Actions::LongPress: + displayApp.PushMessage(Applications::Display::Messages::ButtonLongPressed); + break; + case Actions::LongerPress: + displayApp.PushMessage(Applications::Display::Messages::ButtonLongerPressed); + break; + default: + break; + } +} + void SystemTask::GoToRunning() { if (isGoingToSleep or (not isSleeping) or isWakingUp) return; diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index 9967f75..d6045e9 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -21,6 +21,7 @@ #include "components/fs/FS.h" #include "touchhandler/TouchHandler.h" #include "buttonhandler/ButtonHandler.h" +#include "buttonhandler/ButtonActions.h" #ifdef PINETIME_IS_RECOVERY #include "displayapp/DisplayAppRecovery.h" @@ -138,6 +139,7 @@ namespace Pinetime { TimerHandle_t measureBatteryTimer; bool doNotGoToSleep = false; + void HandleButtonAction(Controllers::ButtonActions action); void GoToRunning(); void UpdateMotion(); bool stepCounterMustBeReset = false; -- cgit v0.10.2 From 887c409b135bb2f21f2fb5ae70a4d8831049d14d Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 25 Oct 2021 17:13:02 +0300 Subject: Only wake up on press. Fixes issue with longer press and sleep diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 85cefb6..51dbc3e 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -337,15 +337,14 @@ void SystemTask::Work() { break; case Messages::HandleButtonEvent: { // This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping - if (IsSleeping()) { - GoToRunning(); - break; - } - Controllers::ButtonActions action; if (nrf_gpio_pin_read(Pinetime::PinMap::Button) == 0) { action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Release); } else { + if (IsSleeping()) { + GoToRunning(); + break; + } action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Press); } HandleButtonAction(action); -- cgit v0.10.2 From 60a717b1a2272e61dfc4d297998da1c7672a8316 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 25 Oct 2021 17:45:48 +0300 Subject: Make it so special actions can be input while sleeping, like in #480 diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 51dbc3e..0a3f995 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -336,16 +336,17 @@ void SystemTask::Work() { displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent); break; case Messages::HandleButtonEvent: { - // This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping Controllers::ButtonActions action; if (nrf_gpio_pin_read(Pinetime::PinMap::Button) == 0) { action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Release); } else { + action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Press); + // This is for faster wakeup, sacrificing special longpress and doubleclick handling while sleeping if (IsSleeping()) { + fastWakeUpDone = true; GoToRunning(); break; } - action = buttonHandler.HandleEvent(Controllers::ButtonHandler::Events::Press); } HandleButtonAction(action); } break; @@ -448,7 +449,8 @@ void SystemTask::HandleButtonAction(Controllers::ButtonActions action) { switch (action) { case Actions::Click: - if (!isGoingToSleep) { + // If the first action after fast wakeup is a click, it should be ignored. + if (!fastWakeUpDone && !isGoingToSleep) { displayApp.PushMessage(Applications::Display::Messages::ButtonPushed); } break; @@ -462,8 +464,10 @@ void SystemTask::HandleButtonAction(Controllers::ButtonActions action) { displayApp.PushMessage(Applications::Display::Messages::ButtonLongerPressed); break; default: - break; + return; } + + fastWakeUpDone = false; } void SystemTask::GoToRunning() { diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index d6045e9..412878b 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -140,6 +140,8 @@ namespace Pinetime { bool doNotGoToSleep = false; void HandleButtonAction(Controllers::ButtonActions action); + bool fastWakeUpDone = false; + void GoToRunning(); void UpdateMotion(); bool stepCounterMustBeReset = false; -- cgit v0.10.2 From 30520d262b8bae9868645462e196027389dce246 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Fri, 29 Oct 2021 13:10:34 +0300 Subject: Memory savings by replacing strings diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index 343b72b..dd223b2 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -209,7 +209,7 @@ std::unique_ptr SystemInfo::CreateScreen4() { static constexpr uint8_t maxTaskCount = 9; TaskStatus_t tasksStatus[maxTaskCount]; - lv_obj_t* infoTask = lv_table_create(lv_scr_act(), NULL); + lv_obj_t* infoTask = lv_table_create(lv_scr_act(), nullptr); lv_table_set_col_cnt(infoTask, 4); lv_table_set_row_cnt(infoTask, maxTaskCount + 1); lv_obj_set_style_local_pad_all(infoTask, LV_TABLE_PART_CELL1, LV_STATE_DEFAULT, 0); @@ -227,35 +227,37 @@ 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 < maxTaskCount; i++) { + char buffer[7] = {0}; - lv_table_set_cell_value(infoTask, i + 1, 0, std::to_string(tasksStatus[i].xTaskNumber).c_str()); - char state[2] = {0}; + sprintf(buffer, "%lu", tasksStatus[i].xTaskNumber); + lv_table_set_cell_value(infoTask, i + 1, 0, buffer); switch (tasksStatus[i].eCurrentState) { case eReady: case eRunning: - state[0] = 'R'; + buffer[0] = 'R'; break; case eBlocked: - state[0] = 'B'; + buffer[0] = 'B'; break; case eSuspended: - state[0] = 'S'; + buffer[0] = 'S'; break; case eDeleted: - state[0] = 'D'; + buffer[0] = 'D'; break; default: - state[0] = 'I'; // Invalid + buffer[0] = 'I'; // Invalid break; } - lv_table_set_cell_value(infoTask, i + 1, 1, state); + buffer[1] = '\0'; + lv_table_set_cell_value(infoTask, i + 1, 1, buffer); lv_table_set_cell_value(infoTask, i + 1, 2, tasksStatus[i].pcTaskName); if (tasksStatus[i].usStackHighWaterMark < 20) { - std::string str1 = std::to_string(tasksStatus[i].usStackHighWaterMark) + " low"; - lv_table_set_cell_value(infoTask, i + 1, 3, str1.c_str()); + sprintf(buffer, "%d low", tasksStatus[i].usStackHighWaterMark); } else { - lv_table_set_cell_value(infoTask, i + 1, 3, std::to_string(tasksStatus[i].usStackHighWaterMark).c_str()); + sprintf(buffer, "%d", tasksStatus[i].usStackHighWaterMark); } + lv_table_set_cell_value(infoTask, i + 1, 3, buffer); } return std::make_unique(3, 5, app, infoTask); } diff --git a/src/displayapp/screens/Twos.cpp b/src/displayapp/screens/Twos.cpp index 4201d50..d12ef90 100644 --- a/src/displayapp/screens/Twos.cpp +++ b/src/displayapp/screens/Twos.cpp @@ -1,10 +1,10 @@ #include "Twos.h" -#include -#include -#include #include -#include +#include +#include +#include #include +#include using namespace Pinetime::Applications::Screens; @@ -265,7 +265,9 @@ void Twos::updateGridDisplay(Tile grid[][4]) { for (int row = 0; row < 4; row++) { for (int col = 0; col < 4; col++) { if (grid[row][col].value) { - lv_table_set_cell_value(gridDisplay, row, col, (std::to_string(grid[row][col].value)).c_str()); + char buffer[7]; + sprintf(buffer, "%d", grid[row][col].value); + lv_table_set_cell_value(gridDisplay, row, col, buffer); } else { lv_table_set_cell_value(gridDisplay, row, col, ""); } -- cgit v0.10.2 From f9613d28c06f96fbc93ccbc59a8f749bbc5f7fa5 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Sat, 30 Oct 2021 22:51:49 +0200 Subject: MotionService: fix not needed '/' in include diff --git a/src/components/ble/MotionService.cpp b/src/components/ble/MotionService.cpp index b4786ab..5069305 100644 --- a/src/components/ble/MotionService.cpp +++ b/src/components/ble/MotionService.cpp @@ -1,5 +1,5 @@ #include "MotionService.h" -#include "components/motion//MotionController.h" +#include "components/motion/MotionController.h" #include "systemtask/SystemTask.h" using namespace Pinetime::Controllers; -- cgit v0.10.2 From 5e1f4839daff075d6411f41148eb6d5d0543bcee Mon Sep 17 00:00:00 2001 From: Clemens von Molo Date: Sun, 31 Oct 2021 21:23:43 +0100 Subject: InfiniPaint vibrate on colorchange, fix color rotation diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index abe5851..04aec4c 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -410,7 +410,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) currentScreen = std::make_unique(this); break; case Apps::Paint: - currentScreen = std::make_unique(this, lvgl); + currentScreen = std::make_unique(this, lvgl,motorController); break; case Apps::Paddle: currentScreen = std::make_unique(this, lvgl); diff --git a/src/displayapp/screens/InfiniPaint.cpp b/src/displayapp/screens/InfiniPaint.cpp index 85a5e82..66391b1 100644 --- a/src/displayapp/screens/InfiniPaint.cpp +++ b/src/displayapp/screens/InfiniPaint.cpp @@ -4,7 +4,7 @@ using namespace Pinetime::Applications::Screens; -InfiniPaint::InfiniPaint(Pinetime::Applications::DisplayApp* app, Pinetime::Components::LittleVgl& lvgl) : Screen(app), lvgl {lvgl} { +InfiniPaint::InfiniPaint(Pinetime::Applications::DisplayApp* app, Pinetime::Components::LittleVgl& lvgl, Pinetime::Controllers::MotorController& motor) : Screen(app), lvgl {lvgl}, motor{motor} { std::fill(b, b + bufferSize, selectColor); } @@ -16,9 +16,6 @@ bool InfiniPaint::OnTouchEvent(Pinetime::Applications::TouchEvents event) { switch (event) { case Pinetime::Applications::TouchEvents::LongTap: switch (color) { - case 0: - selectColor = LV_COLOR_MAGENTA; - break; case 1: selectColor = LV_COLOR_GREEN; break; @@ -43,11 +40,13 @@ bool InfiniPaint::OnTouchEvent(Pinetime::Applications::TouchEvents event) { default: color = 0; + selectColor = LV_COLOR_MAGENTA; break; } std::fill(b, b + bufferSize, selectColor); color++; + motor.RunForDuration(50); return true; default: return true; diff --git a/src/displayapp/screens/InfiniPaint.h b/src/displayapp/screens/InfiniPaint.h index 0a70e03..8a96fc6 100644 --- a/src/displayapp/screens/InfiniPaint.h +++ b/src/displayapp/screens/InfiniPaint.h @@ -3,6 +3,7 @@ #include #include #include "Screen.h" +#include "components/motor/MotorController.h" namespace Pinetime { namespace Components { @@ -13,7 +14,7 @@ namespace Pinetime { class InfiniPaint : public Screen { public: - InfiniPaint(DisplayApp* app, Pinetime::Components::LittleVgl& lvgl); + InfiniPaint(DisplayApp* app, Pinetime::Components::LittleVgl& lvgl, Controllers::MotorController& motor); ~InfiniPaint() override; @@ -23,12 +24,13 @@ namespace Pinetime { private: Pinetime::Components::LittleVgl& lvgl; + Controllers::MotorController& motor; static constexpr uint16_t width = 10; static constexpr uint16_t height = 10; static constexpr uint16_t bufferSize = width * height; lv_color_t b[bufferSize]; lv_color_t selectColor = LV_COLOR_WHITE; - uint8_t color = 2; + uint8_t color = 3; }; } } -- cgit v0.10.2 From 2d985309760172db00b0b9cb7bd523579413d634 Mon Sep 17 00:00:00 2001 From: Clemens von Molo Date: Mon, 1 Nov 2021 11:46:27 +0100 Subject: color rotation using modulo, ran clang-format for InfiniPaint diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 04aec4c..a90a1e5 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -410,7 +410,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) currentScreen = std::make_unique(this); break; case Apps::Paint: - currentScreen = std::make_unique(this, lvgl,motorController); + currentScreen = std::make_unique(this, lvgl, motorController); break; case Apps::Paddle: currentScreen = std::make_unique(this, lvgl); diff --git a/src/displayapp/screens/InfiniPaint.cpp b/src/displayapp/screens/InfiniPaint.cpp index 66391b1..c5ff27b 100644 --- a/src/displayapp/screens/InfiniPaint.cpp +++ b/src/displayapp/screens/InfiniPaint.cpp @@ -4,7 +4,10 @@ using namespace Pinetime::Applications::Screens; -InfiniPaint::InfiniPaint(Pinetime::Applications::DisplayApp* app, Pinetime::Components::LittleVgl& lvgl, Pinetime::Controllers::MotorController& motor) : Screen(app), lvgl {lvgl}, motor{motor} { +InfiniPaint::InfiniPaint(Pinetime::Applications::DisplayApp* app, + Pinetime::Components::LittleVgl& lvgl, + Pinetime::Controllers::MotorController& motor) + : Screen(app), lvgl {lvgl}, motor {motor} { std::fill(b, b + bufferSize, selectColor); } @@ -15,7 +18,11 @@ InfiniPaint::~InfiniPaint() { bool InfiniPaint::OnTouchEvent(Pinetime::Applications::TouchEvents event) { switch (event) { case Pinetime::Applications::TouchEvents::LongTap: + color = (color + 1) % 8; switch (color) { + case 0: + selectColor = LV_COLOR_MAGENTA; + break; case 1: selectColor = LV_COLOR_GREEN; break; @@ -40,12 +47,10 @@ bool InfiniPaint::OnTouchEvent(Pinetime::Applications::TouchEvents event) { default: color = 0; - selectColor = LV_COLOR_MAGENTA; break; } std::fill(b, b + bufferSize, selectColor); - color++; motor.RunForDuration(50); return true; default: diff --git a/src/displayapp/screens/InfiniPaint.h b/src/displayapp/screens/InfiniPaint.h index 8a96fc6..fb0bd9b 100644 --- a/src/displayapp/screens/InfiniPaint.h +++ b/src/displayapp/screens/InfiniPaint.h @@ -1,9 +1,9 @@ #pragma once -#include -#include #include "Screen.h" #include "components/motor/MotorController.h" +#include +#include namespace Pinetime { namespace Components { @@ -30,7 +30,7 @@ namespace Pinetime { static constexpr uint16_t bufferSize = width * height; lv_color_t b[bufferSize]; lv_color_t selectColor = LV_COLOR_WHITE; - uint8_t color = 3; + uint8_t color = 2; }; } } -- cgit v0.10.2 From 75f0bbb7ca51fa0aa65c8c3d4081a5e8d8d48c55 Mon Sep 17 00:00:00 2001 From: Clemens von Molo Date: Mon, 1 Nov 2021 12:10:06 +0100 Subject: change paint vibration to 35ms diff --git a/src/displayapp/screens/InfiniPaint.cpp b/src/displayapp/screens/InfiniPaint.cpp index c5ff27b..271a022 100644 --- a/src/displayapp/screens/InfiniPaint.cpp +++ b/src/displayapp/screens/InfiniPaint.cpp @@ -51,7 +51,7 @@ bool InfiniPaint::OnTouchEvent(Pinetime::Applications::TouchEvents event) { } std::fill(b, b + bufferSize, selectColor); - motor.RunForDuration(50); + motor.RunForDuration(35); return true; default: return true; -- cgit v0.10.2 From e9c7ab4cfc82172a07c19a0c4877b4afd11412f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Sat, 6 Nov 2021 19:01:19 +0100 Subject: Add data validity check and retries in CST816S driver. See https://github.com/InfiniTimeOrg/InfiniTime/issues/763#issuecomment-962436976. diff --git a/src/drivers/Cst816s.cpp b/src/drivers/Cst816s.cpp index 7fc8eca..46dd96d 100644 --- a/src/drivers/Cst816s.cpp +++ b/src/drivers/Cst816s.cpp @@ -32,6 +32,18 @@ bool Cst816S::Init() { twiMaster.Read(twiAddress, 0xa7, &dummy, 1); vTaskDelay(5); + static constexpr uint8_t maxRetries = 3; + bool isDeviceOk = false; + uint8_t retries = 0; + do { + isDeviceOk = CheckDeviceIds(); + retries++; + } while(!isDeviceOk && retries < maxRetries); + + if(!isDeviceOk) { + return false; + } + /* [2] EnConLR - Continuous operation can slide around [1] EnConUD - Slide up and down to enable continuous operation @@ -50,21 +62,7 @@ bool Cst816S::Init() { static constexpr uint8_t irqCtl = 0b01110000; twiMaster.Write(twiAddress, 0xFA, &irqCtl, 1); - // 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; + return true; } Cst816S::TouchInfos Cst816S::GetTouchInfo() { @@ -79,18 +77,33 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() { // This can only be 0 or 1 uint8_t nbTouchPoints = touchData[touchPointNumIndex] & 0x0f; - uint8_t xHigh = touchData[touchXHighIndex] & 0x0f; uint8_t xLow = touchData[touchXLowIndex]; - info.x = (xHigh << 8) | xLow; - + uint16_t x = (xHigh << 8) | xLow; uint8_t yHigh = touchData[touchYHighIndex] & 0x0f; uint8_t yLow = touchData[touchYLowIndex]; - info.y = (yHigh << 8) | yLow; + uint16_t y = (yHigh << 8) | yLow; + Gestures gesture = static_cast(touchData[gestureIndex]); + + // Validity check + if(x >= maxX || y >= maxY || + (gesture != Gestures::None && + gesture != Gestures::SlideDown && + gesture != Gestures::SlideUp && + gesture != Gestures::SlideLeft && + gesture != Gestures::SlideRight && + gesture != Gestures::SingleTap && + gesture != Gestures::DoubleTap && + gesture != Gestures::LongPress)) { + info.isValid = false; + return info; + } + info.x = x; + info.y = y; info.touching = (nbTouchPoints > 0); - info.gesture = static_cast(touchData[gestureIndex]); - + info.gesture = gesture; + info.isValid = true; return info; } @@ -108,3 +121,21 @@ void Cst816S::Wakeup() { Init(); NRF_LOG_INFO("[TOUCHPANEL] Wakeup"); } + +bool Cst816S::CheckDeviceIds() { + // 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; +} diff --git a/src/drivers/Cst816s.h b/src/drivers/Cst816s.h index 0fec841..507dd4f 100644 --- a/src/drivers/Cst816s.h +++ b/src/drivers/Cst816s.h @@ -21,7 +21,7 @@ namespace Pinetime { uint16_t y = 0; Gestures gesture = Gestures::None; bool touching = false; - bool isValid = true; + bool isValid = false; }; Cst816S(TwiMaster& twiMaster, uint8_t twiAddress); @@ -45,6 +45,8 @@ namespace Pinetime { return fwVersion; } private: + bool CheckDeviceIds(); + // Unused/Unavailable commented out static constexpr uint8_t gestureIndex = 1; static constexpr uint8_t touchPointNumIndex = 2; @@ -58,6 +60,9 @@ namespace Pinetime { //static constexpr uint8_t touchXYIndex = 7; //static constexpr uint8_t touchMiscIndex = 8; + static constexpr uint8_t maxX = 240; + static constexpr uint8_t maxY = 240; + TwiMaster& twiMaster; uint8_t twiAddress; -- cgit v0.10.2 From 8d61419836bffa7c59cb41c33fe747bafe841af5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Sun, 7 Nov 2021 16:19:06 +0100 Subject: Fix formatting following the code review. diff --git a/src/drivers/Cst816s.cpp b/src/drivers/Cst816s.cpp index 46dd96d..4aac19f 100644 --- a/src/drivers/Cst816s.cpp +++ b/src/drivers/Cst816s.cpp @@ -33,14 +33,14 @@ bool Cst816S::Init() { vTaskDelay(5); static constexpr uint8_t maxRetries = 3; - bool isDeviceOk = false; + bool isDeviceOk; uint8_t retries = 0; do { isDeviceOk = CheckDeviceIds(); retries++; - } while(!isDeviceOk && retries < maxRetries); + } while (!isDeviceOk && retries < maxRetries); - if(!isDeviceOk) { + if (!isDeviceOk) { return false; } -- cgit v0.10.2 From e6edf2155296864114a62cecbd0244c65c020a48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Sun, 7 Nov 2021 18:00:34 +0100 Subject: Disable the warning that is displayed when the initialization of the touch controller fails, as some users reported that it was displayed when a valid touch controller was installed. diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 0a3f995..f2cc1df 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -144,9 +144,14 @@ void SystemTask::Work() { lcd.Init(); twiMaster.Init(); + /* + * TODO We disable this warning message until we ensure it won't be displayed + * on legitimate PineTime equipped with a compatible touch controller. + * (some users reported false positive). See https://github.com/InfiniTimeOrg/InfiniTime/issues/763 if (!touchPanel.Init()) { bootError = BootErrors::TouchController; } + */ dateTimeController.Register(this); batteryController.Register(this); motorController.Init(); -- cgit v0.10.2 From 76c43ebc82eb1d6580a10f292c83b0b18da135e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Sun, 7 Nov 2021 20:13:22 +0100 Subject: Fix previous commit, call touchPanel.Init() even if we disabled the touch controller boot error. diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index f2cc1df..4b03f9a 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -152,6 +152,7 @@ void SystemTask::Work() { bootError = BootErrors::TouchController; } */ + touchPanel.Init(); dateTimeController.Register(this); batteryController.Register(this); motorController.Init(); -- cgit v0.10.2 From 1d6455c28943efc0e51a91e6e7daa9045a372e50 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Tue, 9 Nov 2021 11:38:19 +0200 Subject: Fix Alarm app crashing on buttonpress diff --git a/src/displayapp/screens/Alarm.h b/src/displayapp/screens/Alarm.h index 32a14d2..487ba1d 100644 --- a/src/displayapp/screens/Alarm.h +++ b/src/displayapp/screens/Alarm.h @@ -40,7 +40,9 @@ namespace Pinetime { Controllers::AlarmController& alarmController; lv_obj_t *time, *btnEnable, *txtEnable, *btnMinutesUp, *btnMinutesDown, *btnHoursUp, *btnHoursDown, *txtMinUp, *txtMinDown, - *txtHrUp, *txtHrDown, *btnRecur, *txtRecur, *btnMessage, *txtMessage, *btnInfo, *txtInfo; + *txtHrUp, *txtHrDown, *btnRecur, *txtRecur, *btnInfo, *txtInfo; + lv_obj_t* txtMessage = nullptr; + lv_obj_t* btnMessage = nullptr; enum class EnableButtonState { On, Off, Alerting }; void SetEnableButtonState(); -- cgit v0.10.2 From bdf7e5293f2fe9eb061940dc841d2b6e4dbe13b2 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Wed, 10 Nov 2021 13:45:49 +0200 Subject: Fix animation when long pressing on screens adjacent to watch face diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 13ee004..63afec1 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -262,7 +262,13 @@ void DisplayApp::Refresh() { break; case Messages::ButtonLongPressed: if (currentApp != Apps::Clock) { - LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::Down); + if (currentApp == Apps::Notifications) { + LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::Up); + } else if (currentApp == Apps::QuickSettings) { + LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::LeftAnim); + } else { + LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::Down); + } } break; case Messages::ButtonLongerPressed: -- cgit v0.10.2 From a57fda6ba4a29866083a1254ffdf92939d00e182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Thu, 11 Nov 2021 09:54:30 +0100 Subject: Set version to 1.7.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index a8ecb81..63257ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10) -project(pinetime VERSION 1.6.0 LANGUAGES C CXX ASM) +project(pinetime VERSION 1.7.0 LANGUAGES C CXX ASM) set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 14) -- cgit v0.10.2 From 39157f2f193a6da9e73fbf459373ea054cb3c162 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Sat, 13 Nov 2021 13:02:00 +0200 Subject: Close menu with button diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 342c387..4e508ee 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -249,10 +249,10 @@ void DisplayApp::Refresh() { } } break; case Messages::ButtonPushed: - if (currentApp == Apps::Clock) { - PushMessageToSystemTask(System::Messages::GoToSleep); - } else { - if (!currentScreen->OnButtonPushed()) { + if (!currentScreen->OnButtonPushed()) { + if (currentApp == Apps::Clock) { + PushMessageToSystemTask(System::Messages::GoToSleep); + } else { LoadApp(returnToApp, returnDirection); brightnessController.Set(settingsController.GetBrightness()); brightnessController.Backup(); diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp index 5a5cd18..d112241 100644 --- a/src/displayapp/screens/Clock.cpp +++ b/src/displayapp/screens/Clock.cpp @@ -54,6 +54,10 @@ bool Clock::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return screen->OnTouchEvent(event); } +bool Clock::OnButtonPushed() { + return screen->OnButtonPushed(); +} + std::unique_ptr Clock::WatchFaceDigitalScreen() { return std::make_unique(app, dateTimeController, diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h index 648f72d..dffe2a4 100644 --- a/src/displayapp/screens/Clock.h +++ b/src/displayapp/screens/Clock.h @@ -32,6 +32,7 @@ namespace Pinetime { ~Clock() override; bool OnTouchEvent(TouchEvents event) override; + bool OnButtonPushed() override; private: Controllers::DateTime& dateTimeController; diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index fa9aec1..47798ae 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -316,6 +316,27 @@ bool PineTimeStyle::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return false; } +void PineTimeStyle::CloseMenu() { + settingsController.SaveSettings(); + lv_obj_set_hidden(btnNextTime, true); + lv_obj_set_hidden(btnPrevTime, true); + lv_obj_set_hidden(btnNextBar, true); + lv_obj_set_hidden(btnPrevBar, true); + lv_obj_set_hidden(btnNextBG, true); + lv_obj_set_hidden(btnPrevBG, true); + lv_obj_set_hidden(btnReset, true); + lv_obj_set_hidden(btnRandom, true); + lv_obj_set_hidden(btnClose, true); +} + +bool PineTimeStyle::OnButtonPushed() { + if (!lv_obj_get_hidden(btnClose)) { + CloseMenu(); + return true; + } + return false; +} + void PineTimeStyle::SetBatteryIcon() { auto batteryPercent = batteryPercentRemaining.Get(); lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent)); @@ -532,16 +553,7 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBG)); } if (object == btnClose) { - settingsController.SaveSettings(); - lv_obj_set_hidden(btnNextTime, true); - lv_obj_set_hidden(btnPrevTime, true); - lv_obj_set_hidden(btnNextBar, true); - lv_obj_set_hidden(btnPrevBar, true); - lv_obj_set_hidden(btnNextBG, true); - lv_obj_set_hidden(btnPrevBG, true); - lv_obj_set_hidden(btnReset, true); - lv_obj_set_hidden(btnRandom, true); - lv_obj_set_hidden(btnClose, true); + CloseMenu(); } if (object == btnSet) { lv_obj_set_hidden(btnSet, true); @@ -579,4 +591,4 @@ Pinetime::Controllers::Settings::Colors PineTimeStyle::GetPrevious(Pinetime::Con prevColor = static_cast(16); } return prevColor; -} \ No newline at end of file +} diff --git a/src/displayapp/screens/PineTimeStyle.h b/src/displayapp/screens/PineTimeStyle.h index 5274d0c..63dba58 100644 --- a/src/displayapp/screens/PineTimeStyle.h +++ b/src/displayapp/screens/PineTimeStyle.h @@ -31,6 +31,7 @@ namespace Pinetime { ~PineTimeStyle() override; bool OnTouchEvent(TouchEvents event) override; + bool OnButtonPushed() override; void Refresh() override; @@ -96,9 +97,10 @@ namespace Pinetime { Controllers::MotionController& motionController; void SetBatteryIcon(); + void CloseMenu(); lv_task_t* taskRefresh; }; } } -} \ No newline at end of file +} -- cgit v0.10.2 From 2e7b51c8e1cb32833f1d07a499fd6a848f1bf96e Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Sat, 13 Nov 2021 13:11:32 +0200 Subject: clang-format and clang-tidy PineTimeStyle diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index 47798ae..7c4ed69 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -38,8 +38,8 @@ using namespace Pinetime::Applications::Screens; namespace { - static void event_handler(lv_obj_t* obj, lv_event_t event) { - PineTimeStyle* screen = static_cast(obj->user_data); + void event_handler(lv_obj_t* obj, lv_event_t event) { + auto* screen = static_cast(obj->user_data); screen->UpdateSelected(obj, event); } } @@ -169,8 +169,8 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app, // Step count gauge if (settingsController.GetPTSColorBar() == Pinetime::Controllers::Settings::Colors::White) { - needle_colors[0] = LV_COLOR_BLACK; - } else { + needle_colors[0] = LV_COLOR_BLACK; + } else { needle_colors[0] = LV_COLOR_WHITE; } stepGauge = lv_gauge_create(lv_scr_act(), nullptr); @@ -305,7 +305,7 @@ PineTimeStyle::~PineTimeStyle() { } bool PineTimeStyle::OnTouchEvent(Pinetime::Applications::TouchEvents event) { - if ((event == Pinetime::Applications::TouchEvents::LongTap) && (lv_obj_get_hidden(btnRandom) == true)) { + if ((event == Pinetime::Applications::TouchEvents::LongTap) && lv_obj_get_hidden(btnRandom)) { lv_obj_set_hidden(btnSet, false); savedTick = lv_tick_get(); return true; @@ -392,7 +392,7 @@ void PineTimeStyle::Refresh() { char hoursChar[3]; char ampmChar[5]; if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) { - sprintf(hoursChar, "%02d", hour); + sprintf(hoursChar, "%02d", hour); } else { if (hour == 0 && hour != 12) { hour = 12; @@ -447,7 +447,7 @@ void PineTimeStyle::Refresh() { lv_obj_set_style_local_scale_grad_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE); } } - if (lv_obj_get_hidden(btnSet) == false) { + if (!lv_obj_get_hidden(btnSet)) { if ((savedTick > 0) && (lv_tick_get() - savedTick > 3000)) { lv_obj_set_hidden(btnSet, true); savedTick = 0; @@ -463,8 +463,9 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { if (event == LV_EVENT_CLICKED) { if (object == btnNextTime) { valueTime = GetNext(valueTime); - if(valueTime == valueBG) + if (valueTime == valueBG) { valueTime = GetNext(valueTime); + } settingsController.SetPTSColorTime(valueTime); lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); @@ -472,8 +473,9 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { } if (object == btnPrevTime) { valueTime = GetPrevious(valueTime); - if(valueTime == valueBG) + if (valueTime == valueBG) { valueTime = GetPrevious(valueTime); + } settingsController.SetPTSColorTime(valueTime); lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); @@ -481,11 +483,12 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { } if (object == btnNextBar) { valueBar = GetNext(valueBar); - if(valueBar == Controllers::Settings::Colors::Black) + if (valueBar == Controllers::Settings::Colors::Black) { valueBar = GetNext(valueBar); - if(valueBar == Controllers::Settings::Colors::White) { - needle_colors[0] = LV_COLOR_BLACK; - } else { + } + if (valueBar == Controllers::Settings::Colors::White) { + needle_colors[0] = LV_COLOR_BLACK; + } else { needle_colors[0] = LV_COLOR_WHITE; } settingsController.SetPTSColorBar(valueBar); @@ -493,11 +496,12 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { } if (object == btnPrevBar) { valueBar = GetPrevious(valueBar); - if(valueBar == Controllers::Settings::Colors::Black) + if (valueBar == Controllers::Settings::Colors::Black) { valueBar = GetPrevious(valueBar); - if(valueBar == Controllers::Settings::Colors::White) { - needle_colors[0] = LV_COLOR_BLACK; - } else { + } + if (valueBar == Controllers::Settings::Colors::White) { + needle_colors[0] = LV_COLOR_BLACK; + } else { needle_colors[0] = LV_COLOR_WHITE; } settingsController.SetPTSColorBar(valueBar); @@ -505,15 +509,17 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { } if (object == btnNextBG) { valueBG = GetNext(valueBG); - if(valueBG == valueTime) + if (valueBG == valueTime) { valueBG = GetNext(valueBG); + } settingsController.SetPTSColorBG(valueBG); lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBG)); } if (object == btnPrevBG) { valueBG = GetPrevious(valueBG); - if(valueBG == valueTime) + if (valueBG == valueTime) { valueBG = GetPrevious(valueBG); + } settingsController.SetPTSColorBG(valueBG); lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBG)); } @@ -545,12 +551,12 @@ void PineTimeStyle::UpdateSelected(lv_obj_t* object, lv_event_t event) { } settingsController.SetPTSColorTime(static_cast(valueTime)); lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); - lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); - lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); + lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); + lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(valueTime)); settingsController.SetPTSColorBar(static_cast(valueBar)); - lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBar)); + lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBar)); settingsController.SetPTSColorBG(static_cast(valueBG)); - lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBG)); + lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(valueBG)); } if (object == btnClose) { CloseMenu(); diff --git a/src/displayapp/screens/PineTimeStyle.h b/src/displayapp/screens/PineTimeStyle.h index 63dba58..8d2003c 100644 --- a/src/displayapp/screens/PineTimeStyle.h +++ b/src/displayapp/screens/PineTimeStyle.h @@ -54,8 +54,8 @@ namespace Pinetime { DirtyValue stepCount {}; DirtyValue notificationState {}; - Pinetime::Controllers::Settings::Colors GetNext(Controllers::Settings::Colors color); - Pinetime::Controllers::Settings::Colors GetPrevious(Controllers::Settings::Colors color); + static Pinetime::Controllers::Settings::Colors GetNext(Controllers::Settings::Colors color); + static Pinetime::Controllers::Settings::Colors GetPrevious(Controllers::Settings::Colors color); lv_obj_t* btnNextTime; lv_obj_t* btnPrevTime; -- cgit v0.10.2 From 71a64974c0783b425efefd091ab7127c42c8724a Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Sat, 13 Nov 2021 13:37:52 +0200 Subject: Remove some clang-tidy checks diff --git a/.clang-tidy b/.clang-tidy index df52357..88ca6c5 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -1,6 +1,7 @@ Checks: '*, -altera-unroll-loops, -llvmlibc-callee-namespace, + -llvmlibc-implementation-in-namespace, -llvmlibc-restrict-system-libc-headers, -llvm-header-guard, -llvm-namespace-comment, @@ -8,6 +9,7 @@ Checks: '*, -google-runtime-int, -google-readability-namespace-comments, -fuchsia-statically-constructed-objects, + -cppcoreguidelines-prefer-member-initializer, -cppcoreguidelines-pro-bounds-array-to-pointer-decay, -cppcoreguidelines-pro-bounds-constant-array-index, -cppcoreguidelines-pro-type-static-cast-downcast, -- cgit v0.10.2 From 9671a8451fc0bc49fcd06521906d8be53959a74f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Sun, 14 Nov 2021 20:32:25 +0100 Subject: Fix unresponsive touch panel after update to 1.7 : don't care if device ids are not the ones we expected (until we know more about these communication and IDs issues). diff --git a/CMakeLists.txt b/CMakeLists.txt index 63257ff..b588066 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.10) -project(pinetime VERSION 1.7.0 LANGUAGES C CXX ASM) +project(pinetime VERSION 1.7.1 LANGUAGES C CXX ASM) set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 14) diff --git a/src/drivers/Cst816s.cpp b/src/drivers/Cst816s.cpp index 4aac19f..bf51a8b 100644 --- a/src/drivers/Cst816s.cpp +++ b/src/drivers/Cst816s.cpp @@ -32,17 +32,11 @@ bool Cst816S::Init() { twiMaster.Read(twiAddress, 0xa7, &dummy, 1); vTaskDelay(5); - static constexpr uint8_t maxRetries = 3; - bool isDeviceOk; - uint8_t retries = 0; - do { - isDeviceOk = CheckDeviceIds(); - retries++; - } while (!isDeviceOk && retries < maxRetries); - - if (!isDeviceOk) { - return false; - } + // TODO This function check that the device IDs from the controller are equal to the ones + // we expect. However, it seems to return false positive (probably in case of communication issue). + // Also, it seems that some users have pinetimes that works correctly but that report different device IDs + // Until we know more about this, we'll just read the IDs but not take any action in case they are not 'valid' + CheckDeviceIds(); /* [2] EnConLR - Continuous operation can slide around -- cgit v0.10.2 From a631fa351858f722f8c4ba7992901722acf3f0c9 Mon Sep 17 00:00:00 2001 From: mabuch Date: Mon, 15 Nov 2021 20:41:32 +0100 Subject: fix Motion Service UUID in doc and code comments diff --git a/doc/MotionService.md b/doc/MotionService.md index 0d0a551..7cec3fb 100644 --- a/doc/MotionService.md +++ b/doc/MotionService.md @@ -3,13 +3,13 @@ The motion service exposes step count and raw X/Y/Z motion value as READ and NOTIFY characteristics. ## Service -The service UUID is **00020000-78fc-48fe-8e23-433b3a1942d0** +The service UUID is **00030000-78fc-48fe-8e23-433b3a1942d0** ## Characteristics -### Step count (UUID 00020001-78fc-48fe-8e23-433b3a1942d0) +### Step count (UUID 00030001-78fc-48fe-8e23-433b3a1942d0) The current number of steps represented as a single `uint32_t` (4 bytes) value. -### Raw motion values (UUID 00020002-78fc-48fe-8e23-433b3a1942d0) +### Raw motion values (UUID 00030002-78fc-48fe-8e23-433b3a1942d0) The current raw motion values. This is a 3 `int16_t` array: - [0] : X diff --git a/src/components/ble/MotionService.cpp b/src/components/ble/MotionService.cpp index b4786ab..284c60d 100644 --- a/src/components/ble/MotionService.cpp +++ b/src/components/ble/MotionService.cpp @@ -5,7 +5,7 @@ using namespace Pinetime::Controllers; namespace { - // 0002yyxx-78fc-48fe-8e23-433b3a1942d0 + // 0003yyxx-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}, @@ -13,7 +13,7 @@ namespace { }; } - // 00020000-78fc-48fe-8e23-433b3a1942d0 + // 00030000-78fc-48fe-8e23-433b3a1942d0 constexpr ble_uuid128_t BaseUuid() { return CharUuid(0x00, 0x00); } -- cgit v0.10.2 From c4f2fb2fa478ccd404afc0220e3e8cfe127e58e7 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Mon, 15 Nov 2021 21:09:59 +0100 Subject: BatteryInfo: remove unused FreeRTOS.h and timer.h includes diff --git a/src/displayapp/screens/BatteryInfo.h b/src/displayapp/screens/BatteryInfo.h index 63454a2..aaa741c 100644 --- a/src/displayapp/screens/BatteryInfo.h +++ b/src/displayapp/screens/BatteryInfo.h @@ -1,8 +1,6 @@ #pragma once #include -#include -#include #include "Screen.h" #include -- cgit v0.10.2 From ac7b2da611fa5ef4cc989a9feb027f66c0ebfc6c Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Wed, 13 Oct 2021 22:08:35 +0200 Subject: Update includes to to be relative to src directory Don't use relative imports like `../foo.h` as those depend on the relative position of both files. Rather than that use imports relative to the `src` directory, which explicitly is part of the include directories. diff --git a/src/components/alarm/AlarmController.cpp b/src/components/alarm/AlarmController.cpp index 67ca05a..28b328d 100644 --- a/src/components/alarm/AlarmController.cpp +++ b/src/components/alarm/AlarmController.cpp @@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include "AlarmController.h" +#include "components/alarm/AlarmController.h" #include "systemtask/SystemTask.h" #include "app_timer.h" #include "task.h" diff --git a/src/components/battery/BatteryController.cpp b/src/components/battery/BatteryController.cpp index e807f03..c875cb8 100644 --- a/src/components/battery/BatteryController.cpp +++ b/src/components/battery/BatteryController.cpp @@ -1,4 +1,4 @@ -#include "BatteryController.h" +#include "components/battery/BatteryController.h" #include "drivers/PinMap.h" #include #include diff --git a/src/components/ble/AlertNotificationClient.cpp b/src/components/ble/AlertNotificationClient.cpp index 5e5c25c..0f85087 100644 --- a/src/components/ble/AlertNotificationClient.cpp +++ b/src/components/ble/AlertNotificationClient.cpp @@ -1,6 +1,6 @@ -#include "AlertNotificationClient.h" +#include "components/ble/AlertNotificationClient.h" #include -#include "NotificationManager.h" +#include "components/ble/NotificationManager.h" #include "systemtask/SystemTask.h" using namespace Pinetime::Controllers; diff --git a/src/components/ble/AlertNotificationClient.h b/src/components/ble/AlertNotificationClient.h index dfba814..2d6a387 100644 --- a/src/components/ble/AlertNotificationClient.h +++ b/src/components/ble/AlertNotificationClient.h @@ -7,7 +7,7 @@ #include #undef max #undef min -#include "BleClient.h" +#include "components/ble/BleClient.h" namespace Pinetime { diff --git a/src/components/ble/AlertNotificationService.cpp b/src/components/ble/AlertNotificationService.cpp index 56fc595..f616cce 100644 --- a/src/components/ble/AlertNotificationService.cpp +++ b/src/components/ble/AlertNotificationService.cpp @@ -1,8 +1,8 @@ -#include "AlertNotificationService.h" +#include "components/ble/AlertNotificationService.h" #include #include #include -#include "NotificationManager.h" +#include "components/ble/NotificationManager.h" #include "systemtask/SystemTask.h" using namespace Pinetime::Controllers; diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp index 2917866..b95a88d 100644 --- a/src/components/ble/BatteryInformationService.cpp +++ b/src/components/ble/BatteryInformationService.cpp @@ -1,5 +1,5 @@ #include -#include "BatteryInformationService.h" +#include "components/ble/BatteryInformationService.h" #include "components/battery/BatteryController.h" using namespace Pinetime::Controllers; diff --git a/src/components/ble/BleController.cpp b/src/components/ble/BleController.cpp index 7c14aeb..a80c971 100644 --- a/src/components/ble/BleController.cpp +++ b/src/components/ble/BleController.cpp @@ -1,4 +1,4 @@ -#include "BleController.h" +#include "components/ble/BleController.h" using namespace Pinetime::Controllers; diff --git a/src/components/ble/CurrentTimeClient.cpp b/src/components/ble/CurrentTimeClient.cpp index 90d1f0c..dd8171b 100644 --- a/src/components/ble/CurrentTimeClient.cpp +++ b/src/components/ble/CurrentTimeClient.cpp @@ -1,4 +1,4 @@ -#include "CurrentTimeClient.h" +#include "components/ble/CurrentTimeClient.h" #include #include #include "components/datetime/DateTimeController.h" diff --git a/src/components/ble/CurrentTimeClient.h b/src/components/ble/CurrentTimeClient.h index 6424c03..9e48be7 100644 --- a/src/components/ble/CurrentTimeClient.h +++ b/src/components/ble/CurrentTimeClient.h @@ -5,7 +5,7 @@ #undef max #undef min #include -#include "BleClient.h" +#include "components/ble/BleClient.h" namespace Pinetime { namespace Controllers { diff --git a/src/components/ble/CurrentTimeService.cpp b/src/components/ble/CurrentTimeService.cpp index eefb7ec..e509aea 100644 --- a/src/components/ble/CurrentTimeService.cpp +++ b/src/components/ble/CurrentTimeService.cpp @@ -1,4 +1,4 @@ -#include "CurrentTimeService.h" +#include "components/ble/CurrentTimeService.h" #include #include diff --git a/src/components/ble/DeviceInformationService.cpp b/src/components/ble/DeviceInformationService.cpp index 778d6e3..0f47c90 100644 --- a/src/components/ble/DeviceInformationService.cpp +++ b/src/components/ble/DeviceInformationService.cpp @@ -1,4 +1,4 @@ -#include "DeviceInformationService.h" +#include "components/ble/DeviceInformationService.h" using namespace Pinetime::Controllers; diff --git a/src/components/ble/DfuService.cpp b/src/components/ble/DfuService.cpp index 3d6416f..71dcc7e 100644 --- a/src/components/ble/DfuService.cpp +++ b/src/components/ble/DfuService.cpp @@ -1,4 +1,4 @@ -#include "DfuService.h" +#include "components/ble/DfuService.h" #include #include "components/ble/BleController.h" #include "drivers/SpiNorFlash.h" diff --git a/src/components/ble/HeartRateService.cpp b/src/components/ble/HeartRateService.cpp index 75a038a..f178af7 100644 --- a/src/components/ble/HeartRateService.cpp +++ b/src/components/ble/HeartRateService.cpp @@ -1,4 +1,4 @@ -#include "HeartRateService.h" +#include "components/ble/HeartRateService.h" #include "components/heartrate/HeartRateController.h" #include "systemtask/SystemTask.h" diff --git a/src/components/ble/ImmediateAlertService.cpp b/src/components/ble/ImmediateAlertService.cpp index 17ed1a9..c80b378 100644 --- a/src/components/ble/ImmediateAlertService.cpp +++ b/src/components/ble/ImmediateAlertService.cpp @@ -1,6 +1,6 @@ -#include "ImmediateAlertService.h" +#include "components/ble/ImmediateAlertService.h" #include -#include "NotificationManager.h" +#include "components/ble/NotificationManager.h" #include "systemtask/SystemTask.h" using namespace Pinetime::Controllers; diff --git a/src/components/ble/MotionService.cpp b/src/components/ble/MotionService.cpp index b4786ab..0146ae8 100644 --- a/src/components/ble/MotionService.cpp +++ b/src/components/ble/MotionService.cpp @@ -1,4 +1,4 @@ -#include "MotionService.h" +#include "components/ble/MotionService.h" #include "components/motion//MotionController.h" #include "systemtask/SystemTask.h" diff --git a/src/components/ble/MusicService.cpp b/src/components/ble/MusicService.cpp index 74fe952..3457ce4 100644 --- a/src/components/ble/MusicService.cpp +++ b/src/components/ble/MusicService.cpp @@ -15,7 +15,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include "MusicService.h" +#include "components/ble/MusicService.h" #include "systemtask/SystemTask.h" namespace { diff --git a/src/components/ble/NavigationService.cpp b/src/components/ble/NavigationService.cpp index b49148d..5418b9e 100644 --- a/src/components/ble/NavigationService.cpp +++ b/src/components/ble/NavigationService.cpp @@ -16,7 +16,7 @@ along with this program. If not, see . */ -#include "NavigationService.h" +#include "components/ble/NavigationService.h" #include "systemtask/SystemTask.h" diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 1bcae1b..43a8b0d 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -1,4 +1,4 @@ -#include "NimbleController.h" +#include "components/ble/NimbleController.h" #include #define min // workaround: nimble's min/max macros conflict with libstdc++ #define max diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 76f89ba..895b87f 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -7,19 +7,19 @@ #include #undef max #undef min -#include "AlertNotificationClient.h" -#include "AlertNotificationService.h" -#include "BatteryInformationService.h" -#include "CurrentTimeClient.h" -#include "CurrentTimeService.h" -#include "DeviceInformationService.h" -#include "DfuService.h" -#include "ImmediateAlertService.h" -#include "MusicService.h" -#include "NavigationService.h" -#include "ServiceDiscovery.h" -#include "HeartRateService.h" -#include "MotionService.h" +#include "components/ble/AlertNotificationClient.h" +#include "components/ble/AlertNotificationService.h" +#include "components/ble/BatteryInformationService.h" +#include "components/ble/CurrentTimeClient.h" +#include "components/ble/CurrentTimeService.h" +#include "components/ble/DeviceInformationService.h" +#include "components/ble/DfuService.h" +#include "components/ble/ImmediateAlertService.h" +#include "components/ble/MusicService.h" +#include "components/ble/NavigationService.h" +#include "components/ble/ServiceDiscovery.h" +#include "components/ble/HeartRateService.h" +#include "components/ble/MotionService.h" namespace Pinetime { namespace Drivers { diff --git a/src/components/ble/NotificationManager.cpp b/src/components/ble/NotificationManager.cpp index 7ffed30..ec99c4e 100644 --- a/src/components/ble/NotificationManager.cpp +++ b/src/components/ble/NotificationManager.cpp @@ -1,4 +1,4 @@ -#include "NotificationManager.h" +#include "components/ble/NotificationManager.h" #include #include diff --git a/src/components/ble/ServiceDiscovery.cpp b/src/components/ble/ServiceDiscovery.cpp index b36b241..03bcfeb 100644 --- a/src/components/ble/ServiceDiscovery.cpp +++ b/src/components/ble/ServiceDiscovery.cpp @@ -1,6 +1,6 @@ -#include "ServiceDiscovery.h" +#include "components/ble/ServiceDiscovery.h" #include -#include "BleClient.h" +#include "components/ble/BleClient.h" using namespace Pinetime::Controllers; diff --git a/src/components/brightness/BrightnessController.cpp b/src/components/brightness/BrightnessController.cpp index 6c52467..2d9f980 100644 --- a/src/components/brightness/BrightnessController.cpp +++ b/src/components/brightness/BrightnessController.cpp @@ -1,4 +1,4 @@ -#include "BrightnessController.h" +#include "components/brightness/BrightnessController.h" #include #include "displayapp/screens/Symbols.h" #include "drivers/PinMap.h" diff --git a/src/components/datetime/DateTimeController.cpp b/src/components/datetime/DateTimeController.cpp index e9c5d87..4ac9e1f 100644 --- a/src/components/datetime/DateTimeController.cpp +++ b/src/components/datetime/DateTimeController.cpp @@ -1,4 +1,4 @@ -#include "DateTimeController.h" +#include "components/datetime/DateTimeController.h" #include #include #include diff --git a/src/components/firmwarevalidator/FirmwareValidator.cpp b/src/components/firmwarevalidator/FirmwareValidator.cpp index 68e66d3..5a63b6b 100644 --- a/src/components/firmwarevalidator/FirmwareValidator.cpp +++ b/src/components/firmwarevalidator/FirmwareValidator.cpp @@ -1,4 +1,4 @@ -#include "FirmwareValidator.h" +#include "components/firmwarevalidator/FirmwareValidator.h" #include #include "drivers/InternalFlash.h" diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp index 857e6bf..1cad4f0 100644 --- a/src/components/fs/FS.cpp +++ b/src/components/fs/FS.cpp @@ -1,4 +1,4 @@ -#include "FS.h" +#include "components/fs/FS.h" #include #include #include diff --git a/src/components/gfx/Gfx.cpp b/src/components/gfx/Gfx.cpp index cf27103..3eaaa3f 100644 --- a/src/components/gfx/Gfx.cpp +++ b/src/components/gfx/Gfx.cpp @@ -1,4 +1,4 @@ -#include "Gfx.h" +#include "components/gfx/Gfx.h" #include "drivers/St7789.h" using namespace Pinetime::Components; diff --git a/src/components/heartrate/Biquad.cpp b/src/components/heartrate/Biquad.cpp index 0341eda..b7edd40 100644 --- a/src/components/heartrate/Biquad.cpp +++ b/src/components/heartrate/Biquad.cpp @@ -4,7 +4,7 @@ C++ port Copyright (C) 2021 Jean-François Milants */ -#include "Biquad.h" +#include "components/heartrate/Biquad.h" using namespace Pinetime::Controllers; diff --git a/src/components/heartrate/HeartRateController.cpp b/src/components/heartrate/HeartRateController.cpp index 716813b..e0d6927 100644 --- a/src/components/heartrate/HeartRateController.cpp +++ b/src/components/heartrate/HeartRateController.cpp @@ -1,4 +1,4 @@ -#include "HeartRateController.h" +#include "components/heartrate/HeartRateController.h" #include #include diff --git a/src/components/heartrate/Ppg.cpp b/src/components/heartrate/Ppg.cpp index fcba381..c247d1f 100644 --- a/src/components/heartrate/Ppg.cpp +++ b/src/components/heartrate/Ppg.cpp @@ -6,7 +6,7 @@ #include #include -#include "Ppg.h" +#include "components/heartrate/Ppg.h" using namespace Pinetime::Controllers; /** Original implementation from wasp-os : https://github.com/daniel-thompson/wasp-os/blob/master/wasp/ppg.py */ diff --git a/src/components/heartrate/Ppg.h b/src/components/heartrate/Ppg.h index 0001416..ed79b08 100644 --- a/src/components/heartrate/Ppg.h +++ b/src/components/heartrate/Ppg.h @@ -1,8 +1,8 @@ #pragma once #include -#include "Biquad.h" -#include "Ptagc.h" +#include "components/heartrate/Biquad.h" +#include "components/heartrate/Ptagc.h" namespace Pinetime { namespace Controllers { diff --git a/src/components/heartrate/Ptagc.cpp b/src/components/heartrate/Ptagc.cpp index e358371..db496a1 100644 --- a/src/components/heartrate/Ptagc.cpp +++ b/src/components/heartrate/Ptagc.cpp @@ -5,7 +5,7 @@ */ #include -#include "Ptagc.h" +#include "components/heartrate/Ptagc.h" using namespace Pinetime::Controllers; diff --git a/src/components/motion/MotionController.cpp b/src/components/motion/MotionController.cpp index a2384d7..cae4910 100644 --- a/src/components/motion/MotionController.cpp +++ b/src/components/motion/MotionController.cpp @@ -1,4 +1,4 @@ -#include "MotionController.h" +#include "components/motion/MotionController.h" using namespace Pinetime::Controllers; diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index f596c71..c794a02 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -1,4 +1,4 @@ -#include "MotorController.h" +#include "components/motor/MotorController.h" #include #include "systemtask/SystemTask.h" #include "app_timer.h" diff --git a/src/components/rle/RleDecoder.cpp b/src/components/rle/RleDecoder.cpp index df2bcb6..19ebfec 100644 --- a/src/components/rle/RleDecoder.cpp +++ b/src/components/rle/RleDecoder.cpp @@ -1,4 +1,4 @@ -#include "RleDecoder.h" +#include "components/rle/RleDecoder.h" using namespace Pinetime::Tools; diff --git a/src/components/settings/Settings.cpp b/src/components/settings/Settings.cpp index 37c09f9..ef73ad1 100644 --- a/src/components/settings/Settings.cpp +++ b/src/components/settings/Settings.cpp @@ -1,4 +1,4 @@ -#include "Settings.h" +#include "components/settings/Settings.h" #include #include diff --git a/src/components/timer/TimerController.cpp b/src/components/timer/TimerController.cpp index 8d5f5c3..79e44d6 100644 --- a/src/components/timer/TimerController.cpp +++ b/src/components/timer/TimerController.cpp @@ -2,7 +2,7 @@ // Created by florian on 16.05.21. // -#include "TimerController.h" +#include "components/timer/TimerController.h" #include "systemtask/SystemTask.h" #include "app_timer.h" #include "task.h" diff --git a/src/displayapp/Colors.cpp b/src/displayapp/Colors.cpp index f45f072..93b1aa0 100644 --- a/src/displayapp/Colors.cpp +++ b/src/displayapp/Colors.cpp @@ -1,4 +1,4 @@ -#include "Colors.h" +#include "displayapp/Colors.h" using namespace Pinetime::Applications; using namespace Pinetime::Controllers; diff --git a/src/displayapp/Colors.h b/src/displayapp/Colors.h index 9db7dd2..43e2b80 100644 --- a/src/displayapp/Colors.h +++ b/src/displayapp/Colors.h @@ -1,7 +1,7 @@ #pragma once #include -#include +#include "components/settings/Settings.h" namespace Pinetime { namespace Applications { diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 13ee004..f4d0ce4 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -1,9 +1,9 @@ -#include "DisplayApp.h" +#include "displayapp/DisplayApp.h" #include -#include -#include -#include -#include +#include "displayapp/screens/HeartRate.h" +#include "displayapp/screens/Motion.h" +#include "displayapp/screens/Timer.h" +#include "displayapp/screens/Alarm.h" #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "components/datetime/DateTimeController.h" diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h index a87cab0..39fe631 100644 --- a/src/displayapp/DisplayApp.h +++ b/src/displayapp/DisplayApp.h @@ -5,9 +5,9 @@ #include #include #include -#include "Apps.h" -#include "LittleVgl.h" -#include "TouchEvents.h" +#include "displayapp/Apps.h" +#include "displayapp/LittleVgl.h" +#include "displayapp/TouchEvents.h" #include "components/brightness/BrightnessController.h" #include "components/motor/MotorController.h" #include "components/firmwarevalidator/FirmwareValidator.h" @@ -17,7 +17,7 @@ #include "components/alarm/AlarmController.h" #include "touchhandler/TouchHandler.h" -#include "Messages.h" +#include "displayapp/Messages.h" #include "BootErrors.h" namespace Pinetime { diff --git a/src/displayapp/DisplayAppRecovery.cpp b/src/displayapp/DisplayAppRecovery.cpp index a42d81a..fd7017a 100644 --- a/src/displayapp/DisplayAppRecovery.cpp +++ b/src/displayapp/DisplayAppRecovery.cpp @@ -1,9 +1,9 @@ -#include "DisplayAppRecovery.h" +#include "displayapp/DisplayAppRecovery.h" #include #include #include -#include -#include +#include "components/rle/RleDecoder.h" +#include "touchhandler/TouchHandler.h" #include "displayapp/icons/infinitime/infinitime-nb.c" #include "components/ble/BleController.h" diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h index 7286815..86e956d 100644 --- a/src/displayapp/DisplayAppRecovery.h +++ b/src/displayapp/DisplayAppRecovery.h @@ -11,10 +11,10 @@ #include #include #include "BootErrors.h" -#include "TouchEvents.h" -#include "Apps.h" -#include "Messages.h" -#include "DummyLittleVgl.h" +#include "displayapp/TouchEvents.h" +#include "displayapp/Apps.h" +#include "displayapp/Messages.h" +#include "displayapp/DummyLittleVgl.h" namespace Pinetime { namespace Drivers { diff --git a/src/displayapp/LittleVgl.cpp b/src/displayapp/LittleVgl.cpp index 2bd5e57..e7b58c1 100644 --- a/src/displayapp/LittleVgl.cpp +++ b/src/displayapp/LittleVgl.cpp @@ -1,5 +1,5 @@ -#include "LittleVgl.h" -#include "lv_pinetime_theme.h" +#include "displayapp/LittleVgl.h" +#include "displayapp/lv_pinetime_theme.h" #include #include diff --git a/src/displayapp/lv_pinetime_theme.c b/src/displayapp/lv_pinetime_theme.c index 1b8b198..1780e64 100644 --- a/src/displayapp/lv_pinetime_theme.c +++ b/src/displayapp/lv_pinetime_theme.c @@ -6,7 +6,7 @@ /********************* * INCLUDES *********************/ -#include "lv_pinetime_theme.h" +#include "displayapp/lv_pinetime_theme.h" /********************* * DEFINES diff --git a/src/displayapp/screens/Alarm.cpp b/src/displayapp/screens/Alarm.cpp index 6b45a36..772e5d4 100644 --- a/src/displayapp/screens/Alarm.cpp +++ b/src/displayapp/screens/Alarm.cpp @@ -15,9 +15,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include "Alarm.h" -#include "Screen.h" -#include "Symbols.h" +#include "displayapp/screens/Alarm.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/Symbols.h" using namespace Pinetime::Applications::Screens; using Pinetime::Controllers::AlarmController; diff --git a/src/displayapp/screens/Alarm.h b/src/displayapp/screens/Alarm.h index 487ba1d..4b301ce 100644 --- a/src/displayapp/screens/Alarm.h +++ b/src/displayapp/screens/Alarm.h @@ -17,9 +17,9 @@ */ #pragma once -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include "systemtask/SystemTask.h" -#include "../LittleVgl.h" +#include "displayapp/LittleVgl.h" #include "components/alarm/AlarmController.h" namespace Pinetime { diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp index 5c582f6..29c8aff 100644 --- a/src/displayapp/screens/ApplicationList.cpp +++ b/src/displayapp/screens/ApplicationList.cpp @@ -1,10 +1,10 @@ -#include "ApplicationList.h" +#include "displayapp/screens/ApplicationList.h" #include #include -#include "Symbols.h" -#include "Tile.h" +#include "displayapp/screens/Symbols.h" +#include "displayapp/screens/Tile.h" #include "displayapp/Apps.h" -#include "../DisplayApp.h" +#include "displayapp/DisplayApp.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/ApplicationList.h b/src/displayapp/screens/ApplicationList.h index 103c38a..f430a89 100644 --- a/src/displayapp/screens/ApplicationList.h +++ b/src/displayapp/screens/ApplicationList.h @@ -2,8 +2,8 @@ #include -#include "Screen.h" -#include "ScreenList.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/ScreenList.h" #include "components/datetime/DateTimeController.h" #include "components/settings/Settings.h" #include "components/battery/BatteryController.h" diff --git a/src/displayapp/screens/BatteryIcon.cpp b/src/displayapp/screens/BatteryIcon.cpp index c67bcb2..114b08f 100644 --- a/src/displayapp/screens/BatteryIcon.cpp +++ b/src/displayapp/screens/BatteryIcon.cpp @@ -1,6 +1,6 @@ #include -#include "BatteryIcon.h" -#include "Symbols.h" +#include "displayapp/screens/BatteryIcon.h" +#include "displayapp/screens/Symbols.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/BatteryInfo.cpp b/src/displayapp/screens/BatteryInfo.cpp index 44ea7f5..e17de9a 100644 --- a/src/displayapp/screens/BatteryInfo.cpp +++ b/src/displayapp/screens/BatteryInfo.cpp @@ -1,5 +1,5 @@ -#include "BatteryInfo.h" -#include "../DisplayApp.h" +#include "displayapp/screens/BatteryInfo.h" +#include "displayapp/DisplayApp.h" #include "components/battery/BatteryController.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/BatteryInfo.h b/src/displayapp/screens/BatteryInfo.h index 63454a2..d7600af 100644 --- a/src/displayapp/screens/BatteryInfo.h +++ b/src/displayapp/screens/BatteryInfo.h @@ -3,7 +3,7 @@ #include #include #include -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include namespace Pinetime { diff --git a/src/displayapp/screens/BleIcon.cpp b/src/displayapp/screens/BleIcon.cpp index da3d15e..5058f3e 100644 --- a/src/displayapp/screens/BleIcon.cpp +++ b/src/displayapp/screens/BleIcon.cpp @@ -1,5 +1,5 @@ -#include "BleIcon.h" -#include "Symbols.h" +#include "displayapp/screens/BleIcon.h" +#include "displayapp/screens/Symbols.h" using namespace Pinetime::Applications::Screens; const char* BleIcon::GetIcon(bool isConnected) { diff --git a/src/displayapp/screens/Brightness.cpp b/src/displayapp/screens/Brightness.cpp index 1278cd6..d9901ae 100644 --- a/src/displayapp/screens/Brightness.cpp +++ b/src/displayapp/screens/Brightness.cpp @@ -1,4 +1,4 @@ -#include "Brightness.h" +#include "displayapp/screens/Brightness.h" #include using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/Brightness.h b/src/displayapp/screens/Brightness.h index 14e4859..693570c 100644 --- a/src/displayapp/screens/Brightness.h +++ b/src/displayapp/screens/Brightness.h @@ -2,7 +2,7 @@ #include #include -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include "components/brightness/BrightnessController.h" namespace Pinetime { diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp index 5a5cd18..71f01b9 100644 --- a/src/displayapp/screens/Clock.cpp +++ b/src/displayapp/screens/Clock.cpp @@ -1,4 +1,4 @@ -#include "Clock.h" +#include "displayapp/screens/Clock.h" #include #include @@ -6,10 +6,10 @@ #include "components/motion/MotionController.h" #include "components/ble/BleController.h" #include "components/ble/NotificationManager.h" -#include "../DisplayApp.h" -#include "WatchFaceDigital.h" -#include "WatchFaceAnalog.h" -#include "PineTimeStyle.h" +#include "displayapp/DisplayApp.h" +#include "displayapp/screens/WatchFaceDigital.h" +#include "displayapp/screens/WatchFaceAnalog.h" +#include "displayapp/screens/PineTimeStyle.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h index 648f72d..2fad1e2 100644 --- a/src/displayapp/screens/Clock.h +++ b/src/displayapp/screens/Clock.h @@ -5,7 +5,7 @@ #include #include #include -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include "components/datetime/DateTimeController.h" namespace Pinetime { diff --git a/src/displayapp/screens/DropDownDemo.cpp b/src/displayapp/screens/DropDownDemo.cpp index 9043c20..cf239a2 100644 --- a/src/displayapp/screens/DropDownDemo.cpp +++ b/src/displayapp/screens/DropDownDemo.cpp @@ -1,7 +1,7 @@ -#include "DropDownDemo.h" +#include "displayapp/screens/DropDownDemo.h" #include #include -#include "../DisplayApp.h" +#include "displayapp/DisplayApp.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/DropDownDemo.h b/src/displayapp/screens/DropDownDemo.h index ff388c5..bcf0f45 100644 --- a/src/displayapp/screens/DropDownDemo.h +++ b/src/displayapp/screens/DropDownDemo.h @@ -1,7 +1,7 @@ #pragma once #include -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include namespace Pinetime { diff --git a/src/displayapp/screens/Error.cpp b/src/displayapp/screens/Error.cpp index 75946ab..1dbc344 100644 --- a/src/displayapp/screens/Error.cpp +++ b/src/displayapp/screens/Error.cpp @@ -1,4 +1,4 @@ -#include "Error.h" +#include "displayapp/screens/Error.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/Error.h b/src/displayapp/screens/Error.h index 20dde7e..2316754 100644 --- a/src/displayapp/screens/Error.h +++ b/src/displayapp/screens/Error.h @@ -1,6 +1,6 @@ #pragma once -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include "BootErrors.h" #include diff --git a/src/displayapp/screens/FirmwareUpdate.cpp b/src/displayapp/screens/FirmwareUpdate.cpp index 79bda0b..373fcae 100644 --- a/src/displayapp/screens/FirmwareUpdate.cpp +++ b/src/displayapp/screens/FirmwareUpdate.cpp @@ -1,7 +1,7 @@ -#include "FirmwareUpdate.h" +#include "displayapp/screens/FirmwareUpdate.h" #include #include "components/ble/BleController.h" -#include "../DisplayApp.h" +#include "displayapp/DisplayApp.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/FirmwareUpdate.h b/src/displayapp/screens/FirmwareUpdate.h index 8fc86d8..a61178c 100644 --- a/src/displayapp/screens/FirmwareUpdate.h +++ b/src/displayapp/screens/FirmwareUpdate.h @@ -1,6 +1,6 @@ #pragma once -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include #include "FreeRTOS.h" diff --git a/src/displayapp/screens/FirmwareValidation.cpp b/src/displayapp/screens/FirmwareValidation.cpp index eef8f91..ea41713 100644 --- a/src/displayapp/screens/FirmwareValidation.cpp +++ b/src/displayapp/screens/FirmwareValidation.cpp @@ -1,8 +1,8 @@ -#include "FirmwareValidation.h" +#include "displayapp/screens/FirmwareValidation.h" #include #include "Version.h" #include "components/firmwarevalidator/FirmwareValidator.h" -#include "../DisplayApp.h" +#include "displayapp/DisplayApp.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/FirmwareValidation.h b/src/displayapp/screens/FirmwareValidation.h index bfdb096..278c4ad 100644 --- a/src/displayapp/screens/FirmwareValidation.h +++ b/src/displayapp/screens/FirmwareValidation.h @@ -1,6 +1,6 @@ #pragma once -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include namespace Pinetime { diff --git a/src/displayapp/screens/FlashLight.cpp b/src/displayapp/screens/FlashLight.cpp index dcb31a7..c4d0264 100644 --- a/src/displayapp/screens/FlashLight.cpp +++ b/src/displayapp/screens/FlashLight.cpp @@ -1,6 +1,6 @@ -#include "FlashLight.h" -#include "../DisplayApp.h" -#include "Symbols.h" +#include "displayapp/screens/FlashLight.h" +#include "displayapp/DisplayApp.h" +#include "displayapp/screens/Symbols.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/FlashLight.h b/src/displayapp/screens/FlashLight.h index f2c65bb..e91a103 100644 --- a/src/displayapp/screens/FlashLight.h +++ b/src/displayapp/screens/FlashLight.h @@ -1,6 +1,6 @@ #pragma once -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include "components/brightness/BrightnessController.h" #include "systemtask/SystemTask.h" #include diff --git a/src/displayapp/screens/HeartRate.cpp b/src/displayapp/screens/HeartRate.cpp index b6ece27..65d1aa2 100644 --- a/src/displayapp/screens/HeartRate.cpp +++ b/src/displayapp/screens/HeartRate.cpp @@ -1,8 +1,8 @@ -#include -#include "HeartRate.h" +#include +#include "displayapp/screens/HeartRate.h" #include -#include "../DisplayApp.h" +#include "displayapp/DisplayApp.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/HeartRate.h b/src/displayapp/screens/HeartRate.h index 7f7d3ad..d06415c 100644 --- a/src/displayapp/screens/HeartRate.h +++ b/src/displayapp/screens/HeartRate.h @@ -2,7 +2,7 @@ #include #include -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include #include "systemtask/SystemTask.h" #include diff --git a/src/displayapp/screens/InfiniPaint.cpp b/src/displayapp/screens/InfiniPaint.cpp index 85a5e82..00d224e 100644 --- a/src/displayapp/screens/InfiniPaint.cpp +++ b/src/displayapp/screens/InfiniPaint.cpp @@ -1,6 +1,6 @@ -#include "InfiniPaint.h" -#include "../DisplayApp.h" -#include "../LittleVgl.h" +#include "displayapp/screens/InfiniPaint.h" +#include "displayapp/DisplayApp.h" +#include "displayapp/LittleVgl.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/InfiniPaint.h b/src/displayapp/screens/InfiniPaint.h index 0a70e03..322ce75 100644 --- a/src/displayapp/screens/InfiniPaint.h +++ b/src/displayapp/screens/InfiniPaint.h @@ -2,7 +2,7 @@ #include #include -#include "Screen.h" +#include "displayapp/screens/Screen.h" namespace Pinetime { namespace Components { diff --git a/src/displayapp/screens/Label.cpp b/src/displayapp/screens/Label.cpp index 1761a7b..62ec1f0 100644 --- a/src/displayapp/screens/Label.cpp +++ b/src/displayapp/screens/Label.cpp @@ -1,4 +1,4 @@ -#include "Label.h" +#include "displayapp/screens/Label.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/Label.h b/src/displayapp/screens/Label.h index f1e4907..3fe5111 100644 --- a/src/displayapp/screens/Label.h +++ b/src/displayapp/screens/Label.h @@ -1,6 +1,6 @@ #pragma once -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include namespace Pinetime { diff --git a/src/displayapp/screens/List.cpp b/src/displayapp/screens/List.cpp index 064b47a..af3f30f 100644 --- a/src/displayapp/screens/List.cpp +++ b/src/displayapp/screens/List.cpp @@ -1,6 +1,6 @@ -#include "List.h" -#include "../DisplayApp.h" -#include "Symbols.h" +#include "displayapp/screens/List.h" +#include "displayapp/DisplayApp.h" +#include "displayapp/screens/Symbols.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/List.h b/src/displayapp/screens/List.h index d9f61f2..023de3a 100644 --- a/src/displayapp/screens/List.h +++ b/src/displayapp/screens/List.h @@ -3,8 +3,8 @@ #include #include #include -#include "Screen.h" -#include "../Apps.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/Apps.h" #include "components/settings/Settings.h" #define MAXLISTITEMS 4 diff --git a/src/displayapp/screens/Meter.cpp b/src/displayapp/screens/Meter.cpp index 57cde9c..9c85310 100644 --- a/src/displayapp/screens/Meter.cpp +++ b/src/displayapp/screens/Meter.cpp @@ -1,6 +1,6 @@ -#include "Meter.h" +#include "displayapp/screens/Meter.h" #include -#include "../DisplayApp.h" +#include "displayapp/DisplayApp.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/Meter.h b/src/displayapp/screens/Meter.h index 9b3d1d4..50d9f83 100644 --- a/src/displayapp/screens/Meter.h +++ b/src/displayapp/screens/Meter.h @@ -1,7 +1,7 @@ #pragma once #include -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include #include diff --git a/src/displayapp/screens/Metronome.cpp b/src/displayapp/screens/Metronome.cpp index 52cb851..8347e1b 100644 --- a/src/displayapp/screens/Metronome.cpp +++ b/src/displayapp/screens/Metronome.cpp @@ -1,5 +1,5 @@ -#include "Metronome.h" -#include "Symbols.h" +#include "displayapp/screens/Metronome.h" +#include "displayapp/screens/Symbols.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/Motion.cpp b/src/displayapp/screens/Motion.cpp index 2f1f7c2..3641110 100644 --- a/src/displayapp/screens/Motion.cpp +++ b/src/displayapp/screens/Motion.cpp @@ -1,6 +1,6 @@ #include -#include "Motion.h" -#include "../DisplayApp.h" +#include "displayapp/screens/Motion.h" +#include "displayapp/DisplayApp.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/Motion.h b/src/displayapp/screens/Motion.h index 20a18d0..f6202b5 100644 --- a/src/displayapp/screens/Motion.h +++ b/src/displayapp/screens/Motion.h @@ -2,7 +2,7 @@ #include #include -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include #include #include diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 47ddb65..8a01a6f 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -15,10 +15,10 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include "Music.h" -#include "Symbols.h" +#include "displayapp/screens/Music.h" +#include "displayapp/screens/Symbols.h" #include -#include "../DisplayApp.h" +#include "displayapp/DisplayApp.h" #include "components/ble/MusicService.h" #include "displayapp/icons/music/disc.cpp" #include "displayapp/icons/music/disc_f_1.cpp" diff --git a/src/displayapp/screens/Music.h b/src/displayapp/screens/Music.h index 6f2d80a..f9b4eaa 100644 --- a/src/displayapp/screens/Music.h +++ b/src/displayapp/screens/Music.h @@ -20,7 +20,7 @@ #include #include #include -#include "Screen.h" +#include "displayapp/screens/Screen.h" namespace Pinetime { namespace Controllers { diff --git a/src/displayapp/screens/Navigation.cpp b/src/displayapp/screens/Navigation.cpp index d437cc6..674362a 100644 --- a/src/displayapp/screens/Navigation.cpp +++ b/src/displayapp/screens/Navigation.cpp @@ -15,9 +15,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#include "Navigation.h" +#include "displayapp/screens/Navigation.h" #include -#include "../DisplayApp.h" +#include "displayapp/DisplayApp.h" #include "components/ble/NavigationService.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/Navigation.h b/src/displayapp/screens/Navigation.h index 48f00a7..07674ef 100644 --- a/src/displayapp/screens/Navigation.h +++ b/src/displayapp/screens/Navigation.h @@ -20,7 +20,7 @@ #include #include #include -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include namespace Pinetime { diff --git a/src/displayapp/screens/NotificationIcon.cpp b/src/displayapp/screens/NotificationIcon.cpp index d8792f9..0e913ae 100644 --- a/src/displayapp/screens/NotificationIcon.cpp +++ b/src/displayapp/screens/NotificationIcon.cpp @@ -1,5 +1,5 @@ -#include "NotificationIcon.h" -#include "Symbols.h" +#include "displayapp/screens/NotificationIcon.h" +#include "displayapp/screens/Symbols.h" using namespace Pinetime::Applications::Screens; const char* NotificationIcon::GetIcon(bool newNotificationAvailable) { diff --git a/src/displayapp/screens/Notifications.cpp b/src/displayapp/screens/Notifications.cpp index 4f47581..569c422 100644 --- a/src/displayapp/screens/Notifications.cpp +++ b/src/displayapp/screens/Notifications.cpp @@ -1,8 +1,8 @@ -#include "Notifications.h" -#include +#include "displayapp/screens/Notifications.h" +#include "displayapp/DisplayApp.h" #include "components/ble/MusicService.h" #include "components/ble/AlertNotificationService.h" -#include "Symbols.h" +#include "displayapp/screens/Symbols.h" using namespace Pinetime::Applications::Screens; extern lv_font_t jetbrains_mono_extrabold_compressed; diff --git a/src/displayapp/screens/Notifications.h b/src/displayapp/screens/Notifications.h index 0b5271e..cbb7af6 100644 --- a/src/displayapp/screens/Notifications.h +++ b/src/displayapp/screens/Notifications.h @@ -3,7 +3,7 @@ #include #include #include -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include "components/ble/NotificationManager.h" #include "components/motor/MotorController.h" diff --git a/src/displayapp/screens/Paddle.cpp b/src/displayapp/screens/Paddle.cpp index 26c2368..aa3420d 100644 --- a/src/displayapp/screens/Paddle.cpp +++ b/src/displayapp/screens/Paddle.cpp @@ -1,6 +1,6 @@ -#include "Paddle.h" -#include "../DisplayApp.h" -#include "../LittleVgl.h" +#include "displayapp/screens/Paddle.h" +#include "displayapp/DisplayApp.h" +#include "displayapp/LittleVgl.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/Paddle.h b/src/displayapp/screens/Paddle.h index fc2131a..3a30eee 100644 --- a/src/displayapp/screens/Paddle.h +++ b/src/displayapp/screens/Paddle.h @@ -2,7 +2,7 @@ #include #include -#include "Screen.h" +#include "displayapp/screens/Screen.h" namespace Pinetime { namespace Components { diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index fa88d45..781a359 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -19,21 +19,21 @@ * Style/layout copied from TimeStyle for Pebble by Dan Tilden (github.com/tilden) */ -#include "PineTimeStyle.h" +#include "displayapp/screens/PineTimeStyle.h" #include #include #include #include -#include "BatteryIcon.h" -#include "BleIcon.h" -#include "NotificationIcon.h" -#include "Symbols.h" +#include "displayapp/screens/BatteryIcon.h" +#include "displayapp/screens/BleIcon.h" +#include "displayapp/screens/NotificationIcon.h" +#include "displayapp/screens/Symbols.h" #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "components/ble/NotificationManager.h" #include "components/motion/MotionController.h" #include "components/settings/Settings.h" -#include "../DisplayApp.h" +#include "displayapp/DisplayApp.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/PineTimeStyle.h b/src/displayapp/screens/PineTimeStyle.h index ba47380..f8c7c8b 100644 --- a/src/displayapp/screens/PineTimeStyle.h +++ b/src/displayapp/screens/PineTimeStyle.h @@ -4,8 +4,8 @@ #include #include #include -#include "Screen.h" -#include "ScreenList.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/ScreenList.h" #include "components/datetime/DateTimeController.h" namespace Pinetime { diff --git a/src/displayapp/screens/Screen.cpp b/src/displayapp/screens/Screen.cpp index 6ae5b7b..bc4cc43 100644 --- a/src/displayapp/screens/Screen.cpp +++ b/src/displayapp/screens/Screen.cpp @@ -1,4 +1,4 @@ -#include "Screen.h" +#include "displayapp/screens/Screen.h" using namespace Pinetime::Applications::Screens; void Screen::RefreshTaskCallback(lv_task_t* task) { diff --git a/src/displayapp/screens/Screen.h b/src/displayapp/screens/Screen.h index ce5741b..04bb152 100644 --- a/src/displayapp/screens/Screen.h +++ b/src/displayapp/screens/Screen.h @@ -1,7 +1,7 @@ #pragma once #include -#include "../TouchEvents.h" +#include "displayapp/TouchEvents.h" #include namespace Pinetime { diff --git a/src/displayapp/screens/ScreenList.h b/src/displayapp/screens/ScreenList.h index a9d747a..e316e36 100644 --- a/src/displayapp/screens/ScreenList.h +++ b/src/displayapp/screens/ScreenList.h @@ -3,8 +3,8 @@ #include #include #include -#include "Screen.h" -#include "../DisplayApp.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/DisplayApp.h" namespace Pinetime { namespace Applications { diff --git a/src/displayapp/screens/Steps.cpp b/src/displayapp/screens/Steps.cpp index c41163a..916138e 100644 --- a/src/displayapp/screens/Steps.cpp +++ b/src/displayapp/screens/Steps.cpp @@ -1,7 +1,7 @@ -#include "Steps.h" +#include "displayapp/screens/Steps.h" #include -#include "../DisplayApp.h" -#include "Symbols.h" +#include "displayapp/DisplayApp.h" +#include "displayapp/screens/Symbols.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/Steps.h b/src/displayapp/screens/Steps.h index d7cf31e..68daf16 100644 --- a/src/displayapp/screens/Steps.h +++ b/src/displayapp/screens/Steps.h @@ -2,7 +2,7 @@ #include #include -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include namespace Pinetime { diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp index 9b27a89..a260d29 100644 --- a/src/displayapp/screens/StopWatch.cpp +++ b/src/displayapp/screens/StopWatch.cpp @@ -1,8 +1,8 @@ #include "StopWatch.h" -#include "Screen.h" -#include "Symbols.h" -#include "lvgl/lvgl.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/Symbols.h" +#include #include "projdefs.h" #include "FreeRTOSConfig.h" #include "task.h" diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h index 25634e9..0720a58 100644 --- a/src/displayapp/screens/StopWatch.h +++ b/src/displayapp/screens/StopWatch.h @@ -1,8 +1,8 @@ #pragma once -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include "components/datetime/DateTimeController.h" -#include "../LittleVgl.h" +#include "displayapp/LittleVgl.h" #include "FreeRTOS.h" #include "portmacro_cmsis.h" diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index dd223b2..350c15c 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -1,7 +1,7 @@ -#include "SystemInfo.h" +#include "displayapp/screens/SystemInfo.h" #include -#include "../DisplayApp.h" -#include "Label.h" +#include "displayapp/DisplayApp.h" +#include "displayapp/screens/Label.h" #include "Version.h" #include "BootloaderVersion.h" #include "components/battery/BatteryController.h" diff --git a/src/displayapp/screens/SystemInfo.h b/src/displayapp/screens/SystemInfo.h index bfcc3aa..a382ed8 100644 --- a/src/displayapp/screens/SystemInfo.h +++ b/src/displayapp/screens/SystemInfo.h @@ -1,8 +1,8 @@ #pragma once #include -#include "Screen.h" -#include "ScreenList.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/ScreenList.h" namespace Pinetime { namespace Controllers { diff --git a/src/displayapp/screens/Tile.cpp b/src/displayapp/screens/Tile.cpp index 1d4f0d0..ba764a2 100644 --- a/src/displayapp/screens/Tile.cpp +++ b/src/displayapp/screens/Tile.cpp @@ -1,6 +1,6 @@ -#include "Tile.h" -#include "../DisplayApp.h" -#include "BatteryIcon.h" +#include "displayapp/screens/Tile.h" +#include "displayapp/DisplayApp.h" +#include "displayapp/screens/BatteryIcon.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/Tile.h b/src/displayapp/screens/Tile.h index 83d3fdf..4869fef 100644 --- a/src/displayapp/screens/Tile.h +++ b/src/displayapp/screens/Tile.h @@ -3,8 +3,8 @@ #include #include #include -#include "Screen.h" -#include "../Apps.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/Apps.h" #include "components/datetime/DateTimeController.h" #include "components/settings/Settings.h" #include "components/datetime/DateTimeController.h" diff --git a/src/displayapp/screens/Timer.cpp b/src/displayapp/screens/Timer.cpp index ff3099d..a5e4019 100644 --- a/src/displayapp/screens/Timer.cpp +++ b/src/displayapp/screens/Timer.cpp @@ -1,8 +1,8 @@ -#include "Timer.h" +#include "displayapp/screens/Timer.h" -#include "Screen.h" -#include "Symbols.h" -#include "lvgl/lvgl.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/Symbols.h" +#include using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/Timer.h b/src/displayapp/screens/Timer.h index d0fc8ed..23c8734 100644 --- a/src/displayapp/screens/Timer.h +++ b/src/displayapp/screens/Timer.h @@ -1,9 +1,9 @@ #pragma once -#include "Screen.h" +#include "displayapp/screens/Screen.h" #include "components/datetime/DateTimeController.h" #include "systemtask/SystemTask.h" -#include "../LittleVgl.h" +#include "displayapp/LittleVgl.h" #include "components/timer/TimerController.h" diff --git a/src/displayapp/screens/Twos.cpp b/src/displayapp/screens/Twos.cpp index d12ef90..a1f0ba2 100644 --- a/src/displayapp/screens/Twos.cpp +++ b/src/displayapp/screens/Twos.cpp @@ -1,4 +1,4 @@ -#include "Twos.h" +#include "displayapp/screens/Twos.h" #include #include #include diff --git a/src/displayapp/screens/Twos.h b/src/displayapp/screens/Twos.h index 6d85cff..48ea079 100644 --- a/src/displayapp/screens/Twos.h +++ b/src/displayapp/screens/Twos.h @@ -1,7 +1,7 @@ #pragma once #include -#include "Screen.h" +#include "displayapp/screens/Screen.h" namespace Pinetime { namespace Applications { diff --git a/src/displayapp/screens/WatchFaceAnalog.cpp b/src/displayapp/screens/WatchFaceAnalog.cpp index 53e7faf..510d113 100644 --- a/src/displayapp/screens/WatchFaceAnalog.cpp +++ b/src/displayapp/screens/WatchFaceAnalog.cpp @@ -1,9 +1,9 @@ #include -#include "WatchFaceAnalog.h" -#include "BatteryIcon.h" -#include "BleIcon.h" -#include "Symbols.h" -#include "NotificationIcon.h" +#include "displayapp/screens/WatchFaceAnalog.h" +#include "displayapp/screens/BatteryIcon.h" +#include "displayapp/screens/BleIcon.h" +#include "displayapp/screens/Symbols.h" +#include "displayapp/screens/NotificationIcon.h" LV_IMG_DECLARE(bg_clock); diff --git a/src/displayapp/screens/WatchFaceAnalog.h b/src/displayapp/screens/WatchFaceAnalog.h index 001414a..ca0462a 100644 --- a/src/displayapp/screens/WatchFaceAnalog.h +++ b/src/displayapp/screens/WatchFaceAnalog.h @@ -4,8 +4,8 @@ #include #include #include -#include "Screen.h" -#include "ScreenList.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/ScreenList.h" #include "components/datetime/DateTimeController.h" #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index 2ecab60..2894812 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -1,12 +1,12 @@ -#include "WatchFaceDigital.h" +#include "displayapp/screens/WatchFaceDigital.h" #include #include #include -#include "BatteryIcon.h" -#include "BleIcon.h" -#include "NotificationIcon.h" -#include "Symbols.h" +#include "displayapp/screens/BatteryIcon.h" +#include "displayapp/screens/BleIcon.h" +#include "displayapp/screens/NotificationIcon.h" +#include "displayapp/screens/Symbols.h" #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" #include "components/ble/NotificationManager.h" diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h index e27545f..7134efb 100644 --- a/src/displayapp/screens/WatchFaceDigital.h +++ b/src/displayapp/screens/WatchFaceDigital.h @@ -4,8 +4,8 @@ #include #include #include -#include "Screen.h" -#include "ScreenList.h" +#include "displayapp/screens/Screen.h" +#include "displayapp/screens/ScreenList.h" #include "components/datetime/DateTimeController.h" namespace Pinetime { diff --git a/src/displayapp/screens/settings/QuickSettings.cpp b/src/displayapp/screens/settings/QuickSettings.cpp index dd62607..5d3a983 100644 --- a/src/displayapp/screens/settings/QuickSettings.cpp +++ b/src/displayapp/screens/settings/QuickSettings.cpp @@ -1,4 +1,4 @@ -#include "QuickSettings.h" +#include "displayapp/screens/settings/QuickSettings.h" #include "displayapp/DisplayApp.h" #include "displayapp/screens/Symbols.h" #include "displayapp/screens/BatteryIcon.h" diff --git a/src/displayapp/screens/settings/SettingDisplay.cpp b/src/displayapp/screens/settings/SettingDisplay.cpp index d8d6c76..666dfb8 100644 --- a/src/displayapp/screens/settings/SettingDisplay.cpp +++ b/src/displayapp/screens/settings/SettingDisplay.cpp @@ -1,4 +1,4 @@ -#include "SettingDisplay.h" +#include "displayapp/screens/settings/SettingDisplay.h" #include #include "displayapp/DisplayApp.h" #include "displayapp/Messages.h" diff --git a/src/displayapp/screens/settings/SettingPineTimeStyle.cpp b/src/displayapp/screens/settings/SettingPineTimeStyle.cpp index c9af19b..f38ec3b 100644 --- a/src/displayapp/screens/settings/SettingPineTimeStyle.cpp +++ b/src/displayapp/screens/settings/SettingPineTimeStyle.cpp @@ -1,4 +1,4 @@ -#include "SettingPineTimeStyle.h" +#include "displayapp/screens/settings/SettingPineTimeStyle.h" #include #include #include "displayapp/DisplayApp.h" diff --git a/src/displayapp/screens/settings/SettingSetDate.cpp b/src/displayapp/screens/settings/SettingSetDate.cpp index ba3413e..8bfded3 100644 --- a/src/displayapp/screens/settings/SettingSetDate.cpp +++ b/src/displayapp/screens/settings/SettingSetDate.cpp @@ -1,4 +1,4 @@ -#include "SettingSetDate.h" +#include "displayapp/screens/settings/SettingSetDate.h" #include #include #include diff --git a/src/displayapp/screens/settings/SettingSetTime.cpp b/src/displayapp/screens/settings/SettingSetTime.cpp index 194bf5e..5351ade 100644 --- a/src/displayapp/screens/settings/SettingSetTime.cpp +++ b/src/displayapp/screens/settings/SettingSetTime.cpp @@ -1,4 +1,4 @@ -#include "SettingSetTime.h" +#include "displayapp/screens/settings/SettingSetTime.h" #include #include #include diff --git a/src/displayapp/screens/settings/SettingSteps.cpp b/src/displayapp/screens/settings/SettingSteps.cpp index bec7972..149840d 100644 --- a/src/displayapp/screens/settings/SettingSteps.cpp +++ b/src/displayapp/screens/settings/SettingSteps.cpp @@ -1,4 +1,4 @@ -#include "SettingSteps.h" +#include "displayapp/screens/settings/SettingSteps.h" #include #include "displayapp/DisplayApp.h" #include "displayapp/screens/Symbols.h" diff --git a/src/displayapp/screens/settings/SettingTimeFormat.cpp b/src/displayapp/screens/settings/SettingTimeFormat.cpp index c99e3a0..c6bdf40 100644 --- a/src/displayapp/screens/settings/SettingTimeFormat.cpp +++ b/src/displayapp/screens/settings/SettingTimeFormat.cpp @@ -1,4 +1,4 @@ -#include "SettingTimeFormat.h" +#include "displayapp/screens/settings/SettingTimeFormat.h" #include #include "displayapp/DisplayApp.h" #include "displayapp/screens/Screen.h" diff --git a/src/displayapp/screens/settings/SettingWakeUp.cpp b/src/displayapp/screens/settings/SettingWakeUp.cpp index d999004..8339d9a 100644 --- a/src/displayapp/screens/settings/SettingWakeUp.cpp +++ b/src/displayapp/screens/settings/SettingWakeUp.cpp @@ -1,4 +1,4 @@ -#include "SettingWakeUp.h" +#include "displayapp/screens/settings/SettingWakeUp.h" #include #include "displayapp/DisplayApp.h" #include "displayapp/screens/Screen.h" diff --git a/src/displayapp/screens/settings/SettingWatchFace.cpp b/src/displayapp/screens/settings/SettingWatchFace.cpp index cdec704..8e6e7cf 100644 --- a/src/displayapp/screens/settings/SettingWatchFace.cpp +++ b/src/displayapp/screens/settings/SettingWatchFace.cpp @@ -1,4 +1,4 @@ -#include "SettingWatchFace.h" +#include "displayapp/screens/settings/SettingWatchFace.h" #include #include "displayapp/DisplayApp.h" #include "displayapp/screens/Screen.h" diff --git a/src/displayapp/screens/settings/Settings.cpp b/src/displayapp/screens/settings/Settings.cpp index 1daf311..392c12e 100644 --- a/src/displayapp/screens/settings/Settings.cpp +++ b/src/displayapp/screens/settings/Settings.cpp @@ -1,4 +1,4 @@ -#include "Settings.h" +#include "displayapp/screens/settings/Settings.h" #include #include #include "displayapp/screens/List.h" diff --git a/src/drivers/Bma421.cpp b/src/drivers/Bma421.cpp index dd28400..8db64ad 100644 --- a/src/drivers/Bma421.cpp +++ b/src/drivers/Bma421.cpp @@ -1,7 +1,7 @@ #include #include -#include "Bma421.h" -#include "TwiMaster.h" +#include "drivers/Bma421.h" +#include "drivers/TwiMaster.h" #include using namespace Pinetime::Drivers; diff --git a/src/drivers/Cst816s.cpp b/src/drivers/Cst816s.cpp index bf51a8b..e9573df 100644 --- a/src/drivers/Cst816s.cpp +++ b/src/drivers/Cst816s.cpp @@ -1,4 +1,4 @@ -#include "Cst816s.h" +#include "drivers/Cst816s.h" #include #include #include diff --git a/src/drivers/Cst816s.h b/src/drivers/Cst816s.h index 507dd4f..4a548d4 100644 --- a/src/drivers/Cst816s.h +++ b/src/drivers/Cst816s.h @@ -1,6 +1,6 @@ #pragma once -#include "TwiMaster.h" +#include "drivers/TwiMaster.h" namespace Pinetime { namespace Drivers { diff --git a/src/drivers/DebugPins.cpp b/src/drivers/DebugPins.cpp index 56fd145..9209128 100644 --- a/src/drivers/DebugPins.cpp +++ b/src/drivers/DebugPins.cpp @@ -1,4 +1,4 @@ -#include "DebugPins.h" +#include "drivers/DebugPins.h" #include #ifdef USE_DEBUG_PINS diff --git a/src/drivers/Hrs3300.cpp b/src/drivers/Hrs3300.cpp index edb9e81..cecef14 100644 --- a/src/drivers/Hrs3300.cpp +++ b/src/drivers/Hrs3300.cpp @@ -6,7 +6,7 @@ #include #include -#include "Hrs3300.h" +#include "drivers/Hrs3300.h" #include #include diff --git a/src/drivers/Hrs3300.h b/src/drivers/Hrs3300.h index c4f2890..01310c6 100644 --- a/src/drivers/Hrs3300.h +++ b/src/drivers/Hrs3300.h @@ -1,6 +1,6 @@ #pragma once -#include "TwiMaster.h" +#include "drivers/TwiMaster.h" namespace Pinetime { namespace Drivers { diff --git a/src/drivers/InternalFlash.cpp b/src/drivers/InternalFlash.cpp index 0840c6e..ec5885d 100644 --- a/src/drivers/InternalFlash.cpp +++ b/src/drivers/InternalFlash.cpp @@ -1,4 +1,4 @@ -#include "InternalFlash.h" +#include "drivers/InternalFlash.h" #include using namespace Pinetime::Drivers; diff --git a/src/drivers/Spi.cpp b/src/drivers/Spi.cpp index a55d288..e477622 100644 --- a/src/drivers/Spi.cpp +++ b/src/drivers/Spi.cpp @@ -1,4 +1,4 @@ -#include "Spi.h" +#include "drivers/Spi.h" #include #include diff --git a/src/drivers/Spi.h b/src/drivers/Spi.h index 6875710..9b6a30f 100644 --- a/src/drivers/Spi.h +++ b/src/drivers/Spi.h @@ -1,7 +1,7 @@ #pragma once #include #include -#include "SpiMaster.h" +#include "drivers/SpiMaster.h" namespace Pinetime { namespace Drivers { diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp index c45e129..747dbc8 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/SpiMaster.cpp @@ -1,4 +1,4 @@ -#include "SpiMaster.h" +#include "drivers/SpiMaster.h" #include #include #include diff --git a/src/drivers/SpiNorFlash.cpp b/src/drivers/SpiNorFlash.cpp index 068d1d0..ebe3174 100644 --- a/src/drivers/SpiNorFlash.cpp +++ b/src/drivers/SpiNorFlash.cpp @@ -1,8 +1,8 @@ -#include "SpiNorFlash.h" +#include "drivers/SpiNorFlash.h" #include #include #include -#include "Spi.h" +#include "drivers/Spi.h" using namespace Pinetime::Drivers; diff --git a/src/drivers/St7789.cpp b/src/drivers/St7789.cpp index 4d81cf2..fd1366f 100644 --- a/src/drivers/St7789.cpp +++ b/src/drivers/St7789.cpp @@ -1,8 +1,8 @@ -#include "St7789.h" +#include "drivers/St7789.h" #include #include #include -#include "Spi.h" +#include "drivers/Spi.h" using namespace Pinetime::Drivers; diff --git a/src/drivers/TwiMaster.cpp b/src/drivers/TwiMaster.cpp index 7600927..9b456d5 100644 --- a/src/drivers/TwiMaster.cpp +++ b/src/drivers/TwiMaster.cpp @@ -1,4 +1,4 @@ -#include "TwiMaster.h" +#include "drivers/TwiMaster.h" #include #include #include diff --git a/src/drivers/Watchdog.cpp b/src/drivers/Watchdog.cpp index a6ad263..d0907a6 100644 --- a/src/drivers/Watchdog.cpp +++ b/src/drivers/Watchdog.cpp @@ -1,4 +1,4 @@ -#include "Watchdog.h" +#include "drivers/Watchdog.h" #include using namespace Pinetime::Drivers; diff --git a/src/heartratetask/HeartRateTask.cpp b/src/heartratetask/HeartRateTask.cpp index fddc05d..213ab4a 100644 --- a/src/heartratetask/HeartRateTask.cpp +++ b/src/heartratetask/HeartRateTask.cpp @@ -1,4 +1,4 @@ -#include "HeartRateTask.h" +#include "heartratetask/HeartRateTask.h" #include #include #include diff --git a/src/logging/DummyLogger.h b/src/logging/DummyLogger.h index 8732dff..1b050b3 100644 --- a/src/logging/DummyLogger.h +++ b/src/logging/DummyLogger.h @@ -1,5 +1,5 @@ #pragma once -#include "Logger.h" +#include "logging/Logger.h" namespace Pinetime { namespace Logging { diff --git a/src/logging/NrfLogger.cpp b/src/logging/NrfLogger.cpp index 1c048f2..ab54afe 100644 --- a/src/logging/NrfLogger.cpp +++ b/src/logging/NrfLogger.cpp @@ -1,4 +1,4 @@ -#include "NrfLogger.h" +#include "logging/NrfLogger.h" #include #include diff --git a/src/logging/NrfLogger.h b/src/logging/NrfLogger.h index 060c4e7..21183a3 100644 --- a/src/logging/NrfLogger.h +++ b/src/logging/NrfLogger.h @@ -1,5 +1,5 @@ #pragma once -#include "Logger.h" +#include "logging/Logger.h" #include #include diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 4b03f9a..1120b80 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -1,4 +1,4 @@ -#include "SystemTask.h" +#include "systemtask/SystemTask.h" #define min // workaround: nimble's min/max macros conflict with libstdc++ #define max #include diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h index 412878b..e2e6de7 100644 --- a/src/systemtask/SystemTask.h +++ b/src/systemtask/SystemTask.h @@ -11,7 +11,7 @@ #include #include -#include "SystemMonitor.h" +#include "systemtask/SystemMonitor.h" #include "components/battery/BatteryController.h" #include "components/ble/NimbleController.h" #include "components/ble/NotificationManager.h" @@ -33,7 +33,7 @@ #endif #include "drivers/Watchdog.h" -#include "Messages.h" +#include "systemtask/Messages.h" extern std::chrono::time_point NoInit_BackUpTime; namespace Pinetime { diff --git a/src/touchhandler/TouchHandler.cpp b/src/touchhandler/TouchHandler.cpp index 735b311..0be3347 100644 --- a/src/touchhandler/TouchHandler.cpp +++ b/src/touchhandler/TouchHandler.cpp @@ -1,4 +1,4 @@ -#include "TouchHandler.h" +#include "touchhandler/TouchHandler.h" using namespace Pinetime::Controllers; -- cgit v0.10.2 From f2918709d92dd49e7e1fffe22be04fc2b47f928b Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Wed, 3 Nov 2021 23:02:30 +0100 Subject: Add missing standard includes diff --git a/src/BootloaderVersion.h b/src/BootloaderVersion.h index f812741..309c23c 100644 --- a/src/BootloaderVersion.h +++ b/src/BootloaderVersion.h @@ -1,5 +1,8 @@ #pragma once +#include +#include + namespace Pinetime { class BootloaderVersion { public: diff --git a/src/Version.h.in b/src/Version.h.in index 8cd39c9..0d6219c 100644 --- a/src/Version.h.in +++ b/src/Version.h.in @@ -2,6 +2,8 @@ @VERSION_EDIT_WARNING@ +#include + namespace Pinetime { class Version { public: diff --git a/src/components/ble/DeviceInformationService.h b/src/components/ble/DeviceInformationService.h index 54b3e96..a269afb 100644 --- a/src/components/ble/DeviceInformationService.h +++ b/src/components/ble/DeviceInformationService.h @@ -1,4 +1,5 @@ #pragma once +#include #define min // workaround: nimble's min/max macros conflict with libstdc++ #define max #include diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index ab0a060..29e09eb 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -1,4 +1,5 @@ #pragma once +#include namespace Pinetime { namespace Applications { namespace Display { diff --git a/src/displayapp/screens/BatteryIcon.h b/src/displayapp/screens/BatteryIcon.h index b370b33..bec2e4e 100644 --- a/src/displayapp/screens/BatteryIcon.h +++ b/src/displayapp/screens/BatteryIcon.h @@ -1,4 +1,5 @@ #pragma once +#include namespace Pinetime { namespace Applications { diff --git a/src/displayapp/screens/InfiniPaint.h b/src/displayapp/screens/InfiniPaint.h index 322ce75..bc0bca2 100644 --- a/src/displayapp/screens/InfiniPaint.h +++ b/src/displayapp/screens/InfiniPaint.h @@ -2,6 +2,7 @@ #include #include +#include // std::fill #include "displayapp/screens/Screen.h" namespace Pinetime { diff --git a/src/drivers/PinMap.h b/src/drivers/PinMap.h index 5796402..579bf38 100644 --- a/src/drivers/PinMap.h +++ b/src/drivers/PinMap.h @@ -1,4 +1,5 @@ #pragma once +#include namespace Pinetime { namespace PinMap { -- cgit v0.10.2 From 1b937a77b981557015a614c7b806f8ddf62c614e Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Wed, 3 Nov 2021 23:08:57 +0100 Subject: remove unused libs/ prefix from lvgl includes as not needed diff --git a/src/displayapp/DummyLittleVgl.h b/src/displayapp/DummyLittleVgl.h index 1db5134..47c9e02 100644 --- a/src/displayapp/DummyLittleVgl.h +++ b/src/displayapp/DummyLittleVgl.h @@ -1,8 +1,8 @@ #pragma once -#include -#include -#include +#include +#include +#include #include #include diff --git a/src/displayapp/screens/HeartRate.h b/src/displayapp/screens/HeartRate.h index d06415c..baa0ccd 100644 --- a/src/displayapp/screens/HeartRate.h +++ b/src/displayapp/screens/HeartRate.h @@ -5,8 +5,8 @@ #include "displayapp/screens/Screen.h" #include #include "systemtask/SystemTask.h" -#include -#include +#include +#include namespace Pinetime { namespace Controllers { diff --git a/src/displayapp/screens/Motion.cpp b/src/displayapp/screens/Motion.cpp index 3641110..8162e02 100644 --- a/src/displayapp/screens/Motion.cpp +++ b/src/displayapp/screens/Motion.cpp @@ -1,4 +1,4 @@ -#include +#include #include "displayapp/screens/Motion.h" #include "displayapp/DisplayApp.h" diff --git a/src/displayapp/screens/Motion.h b/src/displayapp/screens/Motion.h index f6202b5..d699740 100644 --- a/src/displayapp/screens/Motion.h +++ b/src/displayapp/screens/Motion.h @@ -4,8 +4,8 @@ #include #include "displayapp/screens/Screen.h" #include -#include -#include +#include +#include #include namespace Pinetime { diff --git a/src/displayapp/screens/WatchFaceAnalog.cpp b/src/displayapp/screens/WatchFaceAnalog.cpp index 510d113..470fc8e 100644 --- a/src/displayapp/screens/WatchFaceAnalog.cpp +++ b/src/displayapp/screens/WatchFaceAnalog.cpp @@ -1,4 +1,4 @@ -#include +#include #include "displayapp/screens/WatchFaceAnalog.h" #include "displayapp/screens/BatteryIcon.h" #include "displayapp/screens/BleIcon.h" -- cgit v0.10.2 From 241d36471daaea03215c289f3dc2bdc2860b5053 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Fri, 5 Nov 2021 23:55:34 +0100 Subject: Move up file header include to top diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp index b95a88d..9a3f86f 100644 --- a/src/components/ble/BatteryInformationService.cpp +++ b/src/components/ble/BatteryInformationService.cpp @@ -1,5 +1,5 @@ -#include #include "components/ble/BatteryInformationService.h" +#include #include "components/battery/BatteryController.h" using namespace Pinetime::Controllers; diff --git a/src/components/heartrate/Ppg.cpp b/src/components/heartrate/Ppg.cpp index c247d1f..a5d8369 100644 --- a/src/components/heartrate/Ppg.cpp +++ b/src/components/heartrate/Ppg.cpp @@ -4,9 +4,9 @@ C++ port Copyright (C) 2021 Jean-François Milants */ +#include "components/heartrate/Ppg.h" #include #include -#include "components/heartrate/Ppg.h" using namespace Pinetime::Controllers; /** Original implementation from wasp-os : https://github.com/daniel-thompson/wasp-os/blob/master/wasp/ppg.py */ diff --git a/src/components/heartrate/Ptagc.cpp b/src/components/heartrate/Ptagc.cpp index db496a1..1c60bc2 100644 --- a/src/components/heartrate/Ptagc.cpp +++ b/src/components/heartrate/Ptagc.cpp @@ -4,8 +4,8 @@ C++ port Copyright (C) 2021 Jean-François Milants */ -#include #include "components/heartrate/Ptagc.h" +#include using namespace Pinetime::Controllers; diff --git a/src/displayapp/screens/BatteryIcon.cpp b/src/displayapp/screens/BatteryIcon.cpp index 114b08f..08aaab7 100644 --- a/src/displayapp/screens/BatteryIcon.cpp +++ b/src/displayapp/screens/BatteryIcon.cpp @@ -1,5 +1,5 @@ -#include #include "displayapp/screens/BatteryIcon.h" +#include #include "displayapp/screens/Symbols.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/HeartRate.cpp b/src/displayapp/screens/HeartRate.cpp index 65d1aa2..513c40b 100644 --- a/src/displayapp/screens/HeartRate.cpp +++ b/src/displayapp/screens/HeartRate.cpp @@ -1,5 +1,5 @@ -#include #include "displayapp/screens/HeartRate.h" +#include #include #include "displayapp/DisplayApp.h" diff --git a/src/displayapp/screens/Motion.cpp b/src/displayapp/screens/Motion.cpp index 8162e02..23eb276 100644 --- a/src/displayapp/screens/Motion.cpp +++ b/src/displayapp/screens/Motion.cpp @@ -1,5 +1,5 @@ -#include #include "displayapp/screens/Motion.h" +#include #include "displayapp/DisplayApp.h" using namespace Pinetime::Applications::Screens; diff --git a/src/displayapp/screens/WatchFaceAnalog.cpp b/src/displayapp/screens/WatchFaceAnalog.cpp index 470fc8e..4540c1a 100644 --- a/src/displayapp/screens/WatchFaceAnalog.cpp +++ b/src/displayapp/screens/WatchFaceAnalog.cpp @@ -1,5 +1,5 @@ -#include #include "displayapp/screens/WatchFaceAnalog.h" +#include #include "displayapp/screens/BatteryIcon.h" #include "displayapp/screens/BleIcon.h" #include "displayapp/screens/Symbols.h" diff --git a/src/drivers/Bma421.cpp b/src/drivers/Bma421.cpp index 8db64ad..2f60f42 100644 --- a/src/drivers/Bma421.cpp +++ b/src/drivers/Bma421.cpp @@ -1,6 +1,6 @@ +#include "drivers/Bma421.h" #include #include -#include "drivers/Bma421.h" #include "drivers/TwiMaster.h" #include diff --git a/src/drivers/Hrs3300.cpp b/src/drivers/Hrs3300.cpp index cecef14..c14fe7a 100644 --- a/src/drivers/Hrs3300.cpp +++ b/src/drivers/Hrs3300.cpp @@ -4,9 +4,9 @@ C++ port Copyright (C) 2021 Jean-François Milants */ +#include "drivers/Hrs3300.h" #include #include -#include "drivers/Hrs3300.h" #include #include -- cgit v0.10.2 From 3a41bff9eaf9cbae6d3864664ad08859ec2d2c44 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Sat, 6 Nov 2021 00:02:17 +0100 Subject: docs: add non-relative includes to coding standard diff --git a/doc/contribute.md b/doc/contribute.md index 595a599..f7b8ea3 100644 --- a/doc/contribute.md +++ b/doc/contribute.md @@ -94,6 +94,7 @@ If there are no preconfigured rules for your IDE, you can use one of the existin - **Includes** : - files from the project : `#include "relative/path/to/the/file.h"` - external files and std : `#include ` + - use includes relative to included directories like `src`, not relative to the current file. Don't do: `#include "../file.h"` - Only use [primary spellings for operators and tokens](https://en.cppreference.com/w/cpp/language/operator_alternative) - Use auto sparingly. Don't use auto for [fundamental/built-in types](https://en.cppreference.com/w/cpp/language/types) and [fixed width integer types](https://en.cppreference.com/w/cpp/types/integer), except when initializing with a cast to avoid duplicating the type name. - Examples: -- cgit v0.10.2 From 29bb359e90bff68bdfca67bbd42baeac73dae6ae Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Tue, 16 Nov 2021 00:06:13 +0100 Subject: Fix notification icon alignment diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index 7c4ed69..a65d259 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -108,11 +108,11 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app, bleIcon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); - lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); + lv_label_set_text(bleIcon, ""); notificationIcon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); - lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 40); + lv_label_set_text(notificationIcon, ""); // Calendar icon calendarOuter = lv_obj_create(lv_scr_act(), nullptr); @@ -305,12 +305,12 @@ PineTimeStyle::~PineTimeStyle() { } bool PineTimeStyle::OnTouchEvent(Pinetime::Applications::TouchEvents event) { - if ((event == Pinetime::Applications::TouchEvents::LongTap) && lv_obj_get_hidden(btnRandom)) { + if ((event == Pinetime::Applications::TouchEvents::LongTap) && lv_obj_get_hidden(btnClose)) { lv_obj_set_hidden(btnSet, false); savedTick = lv_tick_get(); return true; } - if ((event == Pinetime::Applications::TouchEvents::DoubleTap) && (lv_obj_get_hidden(btnRandom) == false)) { + if ((event == Pinetime::Applications::TouchEvents::DoubleTap) && !lv_obj_get_hidden(btnClose)) { return true; } return false; @@ -359,15 +359,20 @@ void PineTimeStyle::Refresh() { } bleState = bleController.IsConnected(); - if (bleState.IsUpdated()) { + if (bleState.Get()) { lv_label_set_text(bleIcon, BleIcon::GetIcon(bleState.Get())); - lv_obj_realign(bleIcon); + } else { + lv_label_set_text(bleIcon, ""); } notificationState = notificatioManager.AreNewNotificationsAvailable(); - if (notificationState.IsUpdated()) { + if (notificationState.Get()) { lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(notificationState.Get())); - lv_obj_realign(notificationIcon); + lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 8, 25); + lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, -8, 25); + } else { + lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); + lv_label_set_text(notificationIcon, ""); } currentDateTime = dateTimeController.CurrentDateTime(); -- cgit v0.10.2 From bea5c60a11a9c5b97045093a356988de90bb46da Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Tue, 16 Nov 2021 18:10:34 +0100 Subject: Revert "Fix notification icon alignment" This reverts commit 29bb359e90bff68bdfca67bbd42baeac73dae6ae. diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index a65d259..7c4ed69 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -108,11 +108,11 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app, bleIcon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); - lv_label_set_text(bleIcon, ""); + lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); notificationIcon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); - lv_label_set_text(notificationIcon, ""); + lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 40); // Calendar icon calendarOuter = lv_obj_create(lv_scr_act(), nullptr); @@ -305,12 +305,12 @@ PineTimeStyle::~PineTimeStyle() { } bool PineTimeStyle::OnTouchEvent(Pinetime::Applications::TouchEvents event) { - if ((event == Pinetime::Applications::TouchEvents::LongTap) && lv_obj_get_hidden(btnClose)) { + if ((event == Pinetime::Applications::TouchEvents::LongTap) && lv_obj_get_hidden(btnRandom)) { lv_obj_set_hidden(btnSet, false); savedTick = lv_tick_get(); return true; } - if ((event == Pinetime::Applications::TouchEvents::DoubleTap) && !lv_obj_get_hidden(btnClose)) { + if ((event == Pinetime::Applications::TouchEvents::DoubleTap) && (lv_obj_get_hidden(btnRandom) == false)) { return true; } return false; @@ -359,20 +359,15 @@ void PineTimeStyle::Refresh() { } bleState = bleController.IsConnected(); - if (bleState.Get()) { + if (bleState.IsUpdated()) { lv_label_set_text(bleIcon, BleIcon::GetIcon(bleState.Get())); - } else { - lv_label_set_text(bleIcon, ""); + lv_obj_realign(bleIcon); } notificationState = notificatioManager.AreNewNotificationsAvailable(); - if (notificationState.Get()) { + if (notificationState.IsUpdated()) { lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(notificationState.Get())); - lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 8, 25); - lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, -8, 25); - } else { - lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); - lv_label_set_text(notificationIcon, ""); + lv_obj_realign(notificationIcon); } currentDateTime = dateTimeController.CurrentDateTime(); -- cgit v0.10.2 From 1b2a8a5a044d01978854b54fd30ed3737a041e9b Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Tue, 16 Nov 2021 18:18:56 +0100 Subject: Improve notification icon alignment diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index 7c4ed69..0c29503 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -112,7 +112,7 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app, notificationIcon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK); - lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 40); + lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 50); // Calendar icon calendarOuter = lv_obj_create(lv_scr_act(), nullptr); -- cgit v0.10.2 From 7322f3286bd4aa15f671e780fa09d36b12ef0f20 Mon Sep 17 00:00:00 2001 From: Arsen6331 Date: Mon, 22 Nov 2021 00:35:50 +0000 Subject: Add documentation for BLE FS diff --git a/doc/BLEFS.md b/doc/BLEFS.md new file mode 100644 index 0000000..519d84a --- /dev/null +++ b/doc/BLEFS.md @@ -0,0 +1,167 @@ +# BLE FS +--- + +The BLE FS protocol in InfiniTime is mostly Adafruit's BLE file transfer protocol, as described in [adafruit/Adafruit_CircuitPython_BLE_File_Transfer](https://github.com/adafruit/Adafruit_CircuitPython_BLE_File_Transfer). There are some deviations, such as the status codes. These will be described later in the document. + +--- + +## UUIDs + +There are two relevant UUIDs in this protocol: the version characteristic, and the raw transfer characteristic. + +### Version + +UUID: `adaf0100-4669-6c65-5472-616e73666572` + +The version characteristic returns the version of the protocol to which the sender adheres. It returns a single unsigned 32-bit integer. The latest version at the time of writing this is 4. + +### Transfer + +UUID: `adaf0200-4669-6c65-5472-616e73666572` + +The transfer characteristic is responsible for all the data transfer between the client and the watch. It supports write and notify. Writing a packet on the characteristic results in a response via notify. + +--- + +## Usage + +The separator for paths is `/`, and absolute paths must start with `/`. + +All of the following commands and responses are transferred via the transfer characteristic + +### Read file + +To begin reading a file, a header must first be sent. The header packet should be formatted like so: + +- Command (single byte): `0x10` +- 1 byte of padding +- Unsigned 16-bit integer encoding the length of the file path. +- Unsigned 32-bit integer encoding the location at which to start reading the first chunk. +- Unsigned 32-bit integer encoding the amount of bytes to be read. +- File path: UTF-8 encoded string that is _not_ null terminated. + +To continue reading the file after this initial packet, the following packet should be sent until all the data has been received. No close command is required after the data has been received. + +- Command (single byte): `0x12` +- Status: `0x01` +- 2 bytes of padding +- Unsigned 32-bit integer encoding the location at which to start reading the next chunk. +- Unsigned 32-bit integer encoding the amount of bytes to be read. This may be different from the size in the header. + +Both of these commands receive the following response: + +- Command (single byte): `0x11` +- Status (signed 8-bit integer) +- 2 bytes of padding +- Unsigned 32-bit integer encoding the offset of this chunk +- Unsigned 32-bit integer encoding the total size of the file +- Unsigned 32-bit integer encoding the amount of data in the current chunk +- Contents of the current chunk + +### Write file + +To begin writing to a file, a header must first be sent. The header packet should be formatted like so: + +- Command (single byte): `0x20` +- 1 byte of padding +- Unsigned 16-bit integer encoding the length of the file path. +- Unsigned 32-bit integer encoding the location at which to start writing to the file. +- Unsigned 64-bit integer encoding the unix timestamp with nanosecond resolution. This will be used as the modification time. At the time of writing, this is not implemented in InfiniTime, but may be in the future. +- Unsigned 32-bit integer encoding the size of the file that will be sent +- File path: UTF-8 encoded string that is _not_ null terminated. + +To continue reading the file after this initial packet, the following packet should be sent until all the data has been sent and a response had been received with 0 free space. No close command is required after the data has been received. + +- Command (single byte): `0x22` +- Status: `0x01` +- 2 bytes of padding. +- Unsigned 32-bit integer encoding the location at which to write the next chunk. +- Unsigned 32-bit integer encoding the amount of bytes to be written. +- Data + +Both of these commands receive the following response: + +- Command (single byte): `0x21` +- Status (signed 8-bit integer) +- 2 bytes of padding +- Unsigned 32-bit integer encoding the current offset in the file +- Unsigned 64-bit integer encoding the unix timestamp with nanosecond resolution. This will be used as the modification time. At the time of writing, this is not implemented in InfiniTime, but may be in the future. +- Unsigned 32-bit integer encoding the amount of data the client can send until the file is full. + +### Delete file + +- Command (single byte): `0x30` +- 1 byte of padding +- Unsigned 16-bit integer encoding the length of the file path. +- File path: UTF-8 encoded string that is _not_ null terminated. + +The response to this packet will be as follows: + +- Command (single byte): `0x31` +- Status (signed 8-bit integer) + +### Make directory + +- Command (single byte): `0x40` +- 1 byte of padding +- Unsigned 16-bit integer encoding the length of the file path. +- 4 bytes of padding +- Unsigned 64-bit integer encoding the unix timestamp with nanosecond resolution. +- File path: UTF-8 encoded string that is _not_ null terminated. + +The response to this packet will be as follows: + +- Command (single byte): `0x41` +- Status (signed 8-bit integer) +- 6 bytes of padding +- Unsigned 64-bit integer encoding the unix timestamp with nanosecond resolution. + +### List directory + +Paths returned by this command are relative to the path given in the request + +- Command (single byte): `0x50` +- 1 byte of padding +- Unsigned 16-bit integer encoding the length of the file path. +- File path: UTF-8 encoded string that is _not_ null terminated. + +The response to this packet will be as follows. Responses will be sent until the final entry, which will have entry number == total entries + +- Command (single byte): `0x51` +- Status (signed 8-bit integer) +- Unsigned 16-bit integer encoding the length of the file path. +- Unsigned 32-bit integer encoding the entry number +- Unsigned 32-bit integer encoding the total amount of entries +- Flags: unsigned 32-bit integer + + Bit 0: Set when entry is a directory + + Bits 1-7: Reserved +- Unsigned 64-bit integer encoding the unix timestamp of the modification time with nanosecond resolution +- Unsigned 32-bit integer encoding the size of the file +- Path: UTF-8 encoded string that is _not_ null terminated. + +### Move file or directory + +- Command (single byte): `0x60` +- 1 byte of padding +- Unsigned 16-bit integer encoding the length of the old path +- Unsigned 16-bit integer encoding the length of the new path +- Old path: UTF-8 encoded string that is _not_ null terminated. +- 1 byte of padding +- Newpath: UTF-8 encoded string that is _not_ null terminated. + +The response to this packet will be as follows: + +- Command (single byte): `0x61` +- Status (signed 8-bit integer) + +--- + +## Deviations + +This section describes the differences between Adafruit's spec and InfiniTime's implementation. + +### Status codes + +The status codes returned by InfiniTime are a signed 8-bit integer, rather than an unsigned one as described in the spec. + +InfiniTime uses LittleFS error codes rather than the ones described in the spec. Those codes can be found in [lfs.h](https://github.com/littlefs-project/littlefs/blob/master/lfs.h#L70). \ No newline at end of file -- cgit v0.10.2 From 47f73269bbf24aeabeacd5190d64133f46372525 Mon Sep 17 00:00:00 2001 From: Arsen6331 Date: Wed, 24 Nov 2021 22:22:04 +0000 Subject: Add BLE FS docs link to BLE docs diff --git a/doc/ble.md b/doc/ble.md index 8573166..c36fa62 100644 --- a/doc/ble.md +++ b/doc/ble.md @@ -9,6 +9,7 @@ This page describes the BLE implementation and API built in this firmware. ### Table of Contents - [BLE Connection](#ble-connection) +- [BLE FS](#ble-fs) - [BLE UUIDs](#ble-uuids) - [BLE Services](#ble-services) - [CTS](#cts) @@ -51,6 +52,13 @@ If **CTS** is detected, it'll request the current time to the companion applicat --- +## BLE FS + +The documentation for BLE FS can be found here: +[BLEFS.md](./BLEFS.md) + +--- + ## BLE UUIDs When possible, InfiniTime tries to implement BLE services defined by the BLE specification. @@ -285,4 +293,4 @@ This characteristic expects a particular format: - Microsecond divided by `1e6*256` (`uint8`) - Binary 0001 (`uint8`) -Write all of these together, encoded as little-endian, to the current time characteristic. \ No newline at end of file +Write all of these together, encoded as little-endian, to the current time characteristic. -- cgit v0.10.2 From 4aaf3d06bceadb05de0d3a9b0de94e4aba215131 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Sat, 6 Nov 2021 14:38:11 +0200 Subject: Documentation cleanup and reorganization diff --git a/README.md b/README.md index 765aa86..22c91b5 100644 --- a/README.md +++ b/README.md @@ -1,73 +1,18 @@ -# InfiniTime +# [InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime) [![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") +![InfiniTime logo](images/infinitime-logo-small.jpg "InfiniTime Logo") -The goal of this project is to design an open-source firmware for the [Pinetime smartwatch](https://www.pine64.org/pinetime/) : - - - Code written in **modern C++**; - - Build system based on **CMake**; - - Based on **[FreeRTOS 10.0.0](https://freertos.org)** real-time OS. - - Using **[LittleVGL/LVGL 7](https://lvgl.io/)** as UI library... - - ... and **[NimBLE 1.3.0](https://github.com/apache/mynewt-nimble)** as BLE stack. +InfiniTime is an open-source firmware for the [Pinetime smartwatch](https://www.pine64.org/pinetime/) ## New to InfiniTime? - - [Getting started with InfiniTime 1.0 (quick user guide, update bootloader and InfiniTime,...)](doc/gettingStarted/gettingStarted-1.0.md) - - [Flash, upgrade (OTA), time synchronization,...](doc/gettingStarted/ota-gadgetbridge-nrfconnect.md) - -## Overview - -![Pinetime screens](images/1.0.0/collage.png "PinetimeScreens") - -As of now, here is the list of achievements of this project: - - - Fast and optimized LCD driver - - BLE communication - - Rich user interface via display, touchscreen and pushbutton - - Time synchronization via BLE - - Notification via BLE - - Heart rate measurements - - Step counting - - Wake-up on wrist rotation - - Quick actions - * Disable vibration on notification - * Brightness settings - * Flashlight - * Settings - - 3 watch faces: - * Digital - * Analog - * [PineTimeStyle](https://wiki.pine64.org/wiki/PineTimeStyle) - - Multiple 'apps' : - * Music (control the playback of music on your phone) - * Heart rate (measure your heart rate) - * Navigation (displays navigation instructions coming from the companion app) - * Notification (displays the last notification received) - * Paddle (single player pong-like game) - * Twos (2048 clone game) - * Stopwatch - * Steps (displays the number of steps taken) - * Timer (set a countdown timer that will notify you when it expires) - * Metronome (vibrates to a given bpm with a customizable beats per bar) - - User settings: - * Display timeout - * Wake-up condition - * Time format (12/24h) - * Default watch face - * Daily step goal - * Battery status - * Firmware validation - * System information - - Supported by 3 companion apps (development is in progress): - * [Gadgetbridge](https://codeberg.org/Freeyourgadget/Gadgetbridge/) (on Android via F-Droid) - * [Amazfish](https://openrepos.net/content/piggz/amazfish) (on SailfishOS and Linux) - * [Siglo](https://github.com/alexr4535/siglo) (on Linux) - * **[Experimental]** [WebBLEWatch](https://hubmartin.github.io/WebBLEWatch/) Synchronize time directly from your web browser. [video](https://youtu.be/IakiuhVDdrY) - * **[Experimental]** [InfiniLink](https://github.com/xan-m/InfiniLink) (on iOS) - - OTA (Over-the-air) update via BLE - - [Bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader) based on [MCUBoot](https://www.mcuboot.com) + - [Getting started with InfiniTime](doc/gettingStarted/gettingStarted-1.0.md) + - [About the software and updating](doc/gettingStarted/updating-software.md) + - Companion apps: + - [Gadgetbridge](doc/companionapps/Gadgetbridge.md) + - [AmazFish](doc/companionapps/Amazfish.md) ## Documentation @@ -84,16 +29,11 @@ As of now, here is the list of achievements of this project: - [Files included in the release notes](doc/filesInReleaseNotes.md) - [Build the project](doc/buildAndProgram.md) - [Flash the firmware using OpenOCD and STLinkV2](doc/openOCD.md) + - [Flash the firmware using SWD interface](doc/SWD.md) - [Build the project with Docker](doc/buildWithDocker.md) - [Build the project with VSCode](doc/buildWithVScode.md) - [Bootloader, OTA and DFU](./bootloader/README.md) - [Stub using NRF52-DK](./doc/PinetimeStubWithNrf52DK.md) - - Logging with JLink RTT. - - Using files from the releases - -### Contribute - - - [How to contribute ?](doc/contribute.md) ### API @@ -103,29 +43,13 @@ As of now, here is the list of achievements of this project: - [Memory analysis](./doc/MemoryAnalysis.md) -### Using the firmware - - - [Integration with Gadgetbridge](doc/companionapps/Gadgetbridge.md) - - [Integration with AmazFish](doc/companionapps/Amazfish.md) - - [Firmware update, OTA](doc/companionapps/NrfconnectOTA.md) - -## TODO - contribute +## Contributing This project is far from being finished, and there are still a lot of things to do for this project to become a firmware usable by the general public. -Here a quick list out of my head of things to do for this project: - - - Improve BLE communication stability and reliability - - Improve OTA and MCUBoot bootloader - - Add more functionalities : Alarm, chronometer, configuration, activities, heart rate logging, games,... - - Add more BLE functionalities : call notifications, agenda, configuration, data logging,... - - Measure power consumption and improve battery life - - Improve documentation, take better pictures and video than mine - - Improve the UI - - Create companion app for multiple OSes (Linux, Android, iOS) and platforms (desktop, ARM, mobile). Do not forget the other devices from Pine64 like [the Pinephone](https://www.pine64.org/pinephone/) and the [Pinebook Pro](https://www.pine64.org/pinebook-pro/). - - Design a simple CI (preferably self-hosted and easy to reproduce). +Do not hesitate to fork the code, hack it and create pull-requests! -Do not hesitate to clone/fork the code, hack it and create pull-requests. I'll do my best to review and merge them :) +Read this page for more information on how you can help: [How to contribute?](doc/contribute.md) ## Licenses diff --git a/doc/SWD.md b/doc/SWD.md new file mode 100644 index 0000000..4146e6a --- /dev/null +++ b/doc/SWD.md @@ -0,0 +1,14 @@ +# How to flash InfiniTime using the SWD interface +Download the files **bootloader.bin**, **image-x.y.z.bin** and **pinetime-graphics-x.y.z.bin** from the release page: + +![Image file](imageFile.png) + +The bootloader reads a boot logo from the external SPI flash memory. The first step consists of flashing a tool in the MCU that will flash the boot logo into this SPI flash memory. This first step is optional but recommended (the bootloader will display garbage on screen for a few second if you don't do it). +Using your SWD tool, flash **pinetime-graphics-x.y.z.bin** at offset **0x0000**. Reset the MCU and wait for a few second, until the logo is completely drawn on the display. + +Then, using your SWD tool, flash those file at specific offset: + + - bootloader.bin : **0x0000** + - image-x.y.z.bin : **0x8000** + +Reset and voilà, you're running InfiniTime on your PineTime! diff --git a/doc/companionapps/Gadgetbridge.md b/doc/companionapps/Gadgetbridge.md index 974e282..678fe7a 100644 --- a/doc/companionapps/Gadgetbridge.md +++ b/doc/companionapps/Gadgetbridge.md @@ -1,13 +1,7 @@ # Integration with Gadgetbridge [Gadgetbridge](https://gadgetbridge.org/) is an Android application that supports many smartwatches and fitness trackers. -The integration of InfiniTime (previously Pinetime-JF) is now merged into the master branch (https://codeberg.org/Freeyourgadget/Gadgetbridge/) and initial support is available [starting with version 0.47](https://codeberg.org/Freeyourgadget/Gadgetbridge/src/branch/master/CHANGELOG.md). Note that the official version is only available on F-Droid (as of May 2021), and the unofficial fork available on the Play Store is outdated and does not support Infinitime. +Gadgetbridge supports InfiniTime [starting with version 0.47](https://codeberg.org/Freeyourgadget/Gadgetbridge/src/branch/master/CHANGELOG.md). Note that the official version is only available on F-Droid (as of May 2021), and the unofficial fork available on the Play Store is outdated and does not support InfiniTime. -## Features -The following features are implemented: - - Scanning & detection of Pinetime-JF / InfiniTime - - Connection / disconnection - - Notifications - ## Demo -[This video](https://seafile.codingfield.com/f/0a2920b9d765462385e4/) shows how to scan, connect, send notification (using the debug screen) and disconnect from the Pinetime. +[This video](https://seafile.codingfield.com/f/0a2920b9d765462385e4/) shows how to scan, connect, send notification (using the debug screen) and disconnect from the PineTime. diff --git a/doc/companionapps/NrfconnectOTA.md b/doc/companionapps/NrfconnectOTA.md deleted file mode 100644 index 0fa3cd0..0000000 --- a/doc/companionapps/NrfconnectOTA.md +++ /dev/null @@ -1,12 +0,0 @@ -# OTA using NRFConnect -[NRFConnect](https://www.nordicsemi.com/Software-and-tools/Development-Tools/nRF-Connect-for-mobile) is a powerful application (running on Android and iOS) which allows to scan and connect to BLE devices. - -## Features - - Scanning, connect, disconnect - - Time synchronization - - OTA - -InfiniTime implements the Nordic DFU protocol for the OTA functionality. NRFConnect also supports this protocol. - -# Demo -[This video](https://seafile.codingfield.com/f/a52b69683a05472a90c7/) shows how to use NRFConnect to update the firmware running on the Pinetime. \ No newline at end of file diff --git a/doc/gettingStarted/gettingStarted-1.0.md b/doc/gettingStarted/gettingStarted-1.0.md index 409b7c7..a688193 100644 --- a/doc/gettingStarted/gettingStarted-1.0.md +++ b/doc/gettingStarted/gettingStarted-1.0.md @@ -1,91 +1,23 @@ -# Getting started with InfiniTime 1.0 +# Getting started with InfiniTime 1.0.0 -On April 22 2021, InfiniTime and Pine64 [announced the release of InfiniTime 1.0](https://www.pine64.org/2021/04/22/its-time-infinitime-1-0/) and the availability of PineTime smartwatches as *enthusiast grade end-user product*. This page aims to guide you with your first step with your new PineTime. +On April 22 2021, InfiniTime and Pine64 [announced the release of InfiniTime 1.0.0](https://www.pine64.org/2021/04/22/its-time-infinitime-1-0/) and the availability of PineTime smartwatches as *enthusiast grade end-user product*. This page aims to guide you with your first step with your new PineTime. -## Firmware, InfiniTime, Bootloader, Recovery firmware, OTA, DFU... What is it? +It is highly recommended to update the firmware to the latest version when you receive your watch and when a new InfiniTime version is released. More information on updating the firmware [here](/doc/gettingStarted/updating-software.md). -You might have already seen these words by reading the announcement, release notes, or [the wiki guide](https://wiki.pine64.org/wiki/Upgrade_PineTime_to_InfiniTime_1.0.0) and, you may find them misleading if you're not familiar with the project. +## InfiniTime 1.0.0 quick user guide -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/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/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**evice **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/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). - -You can recognize this first iteration of the bootloader with it greenish **PINETIME** logo. - -![Old bootloader logo](oldbootloaderlogo.jpg) - -You can check the version of InfiniTime by opening the app *SystemInfo*. For version < 1.0: - -![InfiniTime 0.7.1 Application menu](appmenu-071.jpg) -![InfiniTime 0.7.1 version](version-071.jpg) - -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/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). - -![Bootloader 1.0](bootloader-1.0.jpg) - -## How to update your PineTime? - -To update your PineTime, you can use one of the compatible companion applications. Here are the main ones: - - - **[Amazfish](https://github.com/piggz/harbour-amazfish)** (Desktop Linux, mobile Linux, SailfishOS, runs on the PinebookPro and the Pinephone) - - **[Gadgetbridge](https://www.gadgetbridge.org/)** (Android) - - **[Siglo](https://github.com/alexr4535/siglo)** (Linux, GTK based) - - **NRFConnect** (closed source, Android & iOS). - -See [this page](ota-gadgetbridge-nrfconnect.md) for more info about the OTA procedure using Gadgetbridge and NRFConnect. - -### From InfiniTime 0.7.1 / old bootloader - -If your PineTime is currently running InfiniTime 0.7.1 and the old bootloader, we strongly recommend you update them to more recent version (Bootloader 1.0.0 and InfiniTime 1.0.0 as of now). We also recommend you install the recovery firmware once the bootloader is up-do-date. - -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/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/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) - -### From version > 1.0 - -If you are already running the new "1.0.0" bootloader, all you have to do is update your version of InfiniTime when it'll be available. We'll write specific instructions when (if) we release a new version of the bootloader. - -### Firmware validation - -The bootloader requires a (manual) validation of the firmware. If the watch reset with an updated firmware that was not validated, the bootloader will consider it as non-functioning and will revert to the previous version of the firmware. This is a safety feature to prevent bricking your device with a faulty firmware. - -You can validate your updated firmware on InfiniTime >= 1.0 by following this simple procedure: - - - From the watchface, swipe **right** to display the *Quick Actions menu* - - Open the **Settings** app by tapping the *gear* icon on the bottom right - - Swipe down and tap on the entry named **Firmware** - - This app shows the version that is currently running. If it's not validated yet, it displays 2 buttons: - - **Validate** to validate your firmware - - **Reset** to reset the watch and revert to the previously running version of the firmware +### Setting the time -## InfiniTime 1.0 quick user guide +By default, InfiniTime starts on the digital watchface. It'll probably display the epoch time (1 Jan 1970, 00:00). -### Setting the time +You can sync the time using companion apps. -By default, InfiniTime starts on the digital watchface. It'll probably display the epoch time (1 Jan 1970, 00:00). The time will be automatically synchronized once you connect on of the companion app to your PineTime using BLE connectivity. InfiniTime does not provide any way to manually set the time for now. + - Gadgetbridge automatically synchronizes the time when you connect it to your watch. More information on Gadgetbridge [here](/doc/gettingStarted/ota-gadgetbridge.md) + - You can use NRFConnect to [sync the time](/doc/gettingStarted/time-nrfconnect.md) + - Sync the time with your browser https://hubmartin.github.io/WebBLEWatch/ + - Since InfiniTime 1.7.0, you can set the time in the settings without needing to use a companion app -### Navigation in the menu +## Navigation in the menu ![Quick actions](quickactions.jpg) ![Settings](settings.jpg) @@ -98,14 +30,7 @@ By default, InfiniTime starts on the digital watchface. It'll probably display t - Start the **flashlight** app - Enable/disable vibrations on notifications (Do Not Disturb mode) - Enter the **settings** menu - - Settings - - Display timeout - - Wake up event (Tap, wrist rotation) - - Time format (12/24H) - - Default watchface (digital / analog) - - Battery info - - Firmware validation - - About (system info, firmware version,...) + - Swipe up and down to see all options ### Bootloader diff --git a/doc/gettingStarted/ota-gadgetbridge-nrfconnect.md b/doc/gettingStarted/ota-gadgetbridge-nrfconnect.md deleted file mode 100644 index 57d1621..0000000 --- a/doc/gettingStarted/ota-gadgetbridge-nrfconnect.md +++ /dev/null @@ -1,109 +0,0 @@ -# Flash and upgrade InfiniTime -If you just want to flash or upgrade InfiniTime on your PineTime, this page is for you! - -- [InfiniTime releases and versions](#infinitime-releases-and-versions) -- [How to upgrade Over-The-Air (OTA)](#how-to-upgrade-over-the-air-ota) - - [Using Gadgetbridge](#using-gadgetbridge) - - [Using NRFConnect](#Using-nrfconnect) -- [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/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. - -Release files are available under the *Assets* button. - -## How to upgrade Over-The-Air (OTA) -OTA is the easiest method to upgrade InfiniTime. Note that it's only possible is your PineTime is already running InfiniTime (>= 0.7.1). - -2 companion apps provide support for OTA : - - [Gadgetbridge](https://gadgetbridge.org/) (open source, runs on Android, [available on F-Droid](https://f-droid.org/packages/nodomain.freeyourgadget.gadgetbridge/)). - - [NRFConnect](https://www.nordicsemi.com/Software-and-tools/Development-Tools/nRF-Connect-for-mobile) (close source, runs on Android and iOS). - -Both applications need you to download the **DFU file** of InfiniTime. This file contains the new version of InfiniTime that will be flashed into your device. It's called **dfu-x.y.z.zip** (ex: dfu-0.9.0.zip) in the release note. -![Dfu file](dfuFile.png ) - -### Using Gadgetbridge -Launch Gadgetbridge and tap on the **"+"** button on the bottom right to add a new device: - -![Gadgetbridge 0](gadgetbridge0.jpg) - -Wait for the scan to complete, your PineTime should be detected: - -![Gadgetbridge 1](gadgetbridge1.jpg) - -Tap on it. Gadgdetbridge will pair and connect to your device: - -![Gadgetbridge 2](gadgetbridge2.jpg) - -Now that Gadgetbridge is connected to your PineTime, use a file browser application (I'm using Seafile to browse my NAS) and browse to the DFU file (image-xxx.zip) you downloaded previously. Tap on it and open it using the Gadgetbridge application/firmware installer: - -![Gadgetbridge 3](gadgetbridge3.jpg) - -Read carefully the warning and tap **Install**: - -![Gadgetbridge 4](gadgetbridge4.jpg) - -Wait for the transfer to finish. Your PineTime should reset and reboot with the new version of InfiniTime! - -Don't forget to **validate** your firmware. In the InfiniTime go to the settings (swipe right, select gear icon) and Firmware option and click **validate**. Otherwise after reboot the previous firmware will be used. - -![Gadgetbridge 5](gadgetbridge5.jpg) - -### Using NRFConnect -Open NRFConnect. Swipe down in the *Scanner* tab and wait for your device to appear: - -![NRFConnect 0](nrfconnect0.jpg) - -Tap on the *Connect* button on the right of your device. NRFConnect will connect to your PineTime and discover its characteristics. Tap on the **DFU** button on the top right: - -![NRFConnect 1](nrfconnect1.jpg) - -Select **Distribution packet (ZIP)**: - -![NRFConnect 2](nrfconnect2.jpg) - -Browse to the DFU file you downloaded previously, the DFU transfer will start automatically. When the transfer is finished, your PineTime will reset and restart on the new version of InfiniTime! - -Don't forget to **validate** your firmware. In the InfiniTime go to the settings (swipe right, select gear icon) and Firmware option and click **validate**. Otherwise after reboot the previous firmware will be used. - -![NRFConnect 3](nrfconnect3.jpg) - -## How to flash InfiniTime using the SWD interface -Download the files **bootloader.bin**, **image-x.y.z.bin** and **pinetime-graphics-x.y.z.bin** from the release page: - -![Image file](imageFile.png ) - -The bootloader reads a boot logo from the external SPI flash memory. The first step consists in flashing a tool in the MCU that will flash the boot logo into this SPI flash memory. This first step is optional but recommanded (the bootloader will display garbage on screen for a few second if you don't do it). -Using your SWD tool, flash **pinetime-graphics-x.y.z.bin** at offset **0x0000**. Reset the MCU and wait for a few second, until the logo is completely drawn on the display. - -Then, using your SWD tool, flash those file at specific offset: - - - bootloader.bin : **0x0000** - - image-x.y.z.bin : **0x8000** - -Reset and voilà, you're running InfiniTime on your PineTime! - -If you are using OpenOCD with a STLinkV2, you can find more info [on this page](../openOCD.md). - -## How to synchronize the time - -### Using Gadgetbridge -Good news! Gadgetbridge **automatically** synchronizes the time when connecting to your PineTime! - -### Using any Chromium-based web browser -You can use it from your PC, Mac, Android. Browsers now have BLE support. -https://hubmartin.github.io/WebBLEWatch/ - -### Using NRFConnect -You must enable the **CTS** *GATT server* into NRFConnect so that InfiniTime can synchronize the time with your smartphone. - -Launch NRFConnect, tap the sandwich button on the top left and select *Configure GATT server*: - -![NRFConnect CTS 0](nrfconnectcts0.jpg) - - -Tap *Add service* and select the server configuration *Current Time service*. Tap OK and connect to your PineTime, it should automcatically sync the time once the connection is established! - -![NRFConnect CTS 1](nrfconnectcts1.jpg) diff --git a/doc/gettingStarted/ota-gadgetbridge.md b/doc/gettingStarted/ota-gadgetbridge.md new file mode 100644 index 0000000..971eaad --- /dev/null +++ b/doc/gettingStarted/ota-gadgetbridge.md @@ -0,0 +1,39 @@ +# Connecting to Gadgetbridge + +Launch Gadgetbridge and tap on the **"+"** button on the bottom right to add a new device: + +![Gadgetbridge 0](gadgetbridge0.jpg) + +Wait for the scan to complete, your PineTime should be detected: + +![Gadgetbridge 1](gadgetbridge1.jpg) + +Tap on it. Gadgdetbridge will pair and connect to your device: + +![Gadgetbridge 2](gadgetbridge2.jpg) + +# Updating with Gadgetbridge + +## Preparation + +All releases of InfiniTime are available on the [release page of the GitHub repo](https://github.com/InfiniTimeOrg/InfiniTime/releases). + +Release files are available under the *Assets* button. + +You need to download the DFU of the firmware version that you'd like to install, for example `pinetime-mcuboot-app-dfu-1.6.0.zip` + +## Gadgetbridge + +Now that Gadgetbridge is connected to your PineTime, use a file browser application (I'm using Seafile to browse my NAS) and browse to the DFU file (image-xxx.zip) you downloaded previously. Tap on it and open it using the Gadgetbridge application/firmware installer: + +![Gadgetbridge 3](gadgetbridge3.jpg) + +Read carefully the warning and tap **Install**: + +![Gadgetbridge 4](gadgetbridge4.jpg) + +Wait for the transfer to finish. Your PineTime should reset and reboot with the new version of InfiniTime! + +Don't forget to **validate** your firmware. In the InfiniTime go to the settings (swipe right, select gear icon) and Firmware option and click **validate**. Otherwise after reboot the previous firmware will be used. + +![Gadgetbridge 5](gadgetbridge5.jpg) diff --git a/doc/gettingStarted/ota-nrfconnect.md b/doc/gettingStarted/ota-nrfconnect.md new file mode 100644 index 0000000..dbc7829 --- /dev/null +++ b/doc/gettingStarted/ota-nrfconnect.md @@ -0,0 +1,32 @@ +# Updating with NRFConnect + +## Preparation + +All releases of InfiniTime are available on the [release page of the GitHub repo](https://github.com/InfiniTimeOrg/InfiniTime/releases). + +Release files are available under the *Assets* button. + +You need to download the DFU of the firmware version that you'd like to install, for example `pinetime-mcuboot-app-dfu-1.6.0.zip` + +## NRFConnect + +Open NRFConnect. Swipe down in the *Scanner* tab and wait for your device to appear: + +![NRFConnect 0](nrfconnect0.jpg) + +Tap on the *Connect* button on the right of your device. NRFConnect will connect to your PineTime and discover its characteristics. Tap on the **DFU** button on the top right: + +![NRFConnect 1](nrfconnect1.jpg) + +Select **Distribution packet (ZIP)**: + +![NRFConnect 2](nrfconnect2.jpg) + +Browse to the DFU file you downloaded previously, the DFU transfer will start automatically. When the transfer is finished, your PineTime will reset and restart on the new version of InfiniTime! + +Don't forget to **validate** your firmware. In the InfiniTime go to the settings (swipe right, select gear icon) and Firmware option and click **validate**. Otherwise after reboot the previous firmware will be used. + +![NRFConnect 3](nrfconnect3.jpg) + +# Demo +[This video](https://seafile.codingfield.com/f/a52b69683a05472a90c7/) shows how to use NRFConnect to update the firmware running on the Pinetime. diff --git a/doc/gettingStarted/time-nrfconnect.md b/doc/gettingStarted/time-nrfconnect.md new file mode 100644 index 0000000..a30d98f --- /dev/null +++ b/doc/gettingStarted/time-nrfconnect.md @@ -0,0 +1,11 @@ +### Syncing time + +You must enable the **CTS** *GATT server* in NRFConnect so that InfiniTime can synchronize the time with your smartphone. + +Launch NRFConnect, tap the sandwich button on the top left and select *Configure GATT server*: + +![NRFConnect CTS 0](nrfconnectcts0.jpg) + +Tap *Add service* and select the server configuration *Current Time service*. Tap OK and connect to your PineTime, it should automcatically sync the time once the connection is established! + +![NRFConnect CTS 1](nrfconnectcts1.jpg) diff --git a/doc/gettingStarted/updating-software.md b/doc/gettingStarted/updating-software.md new file mode 100644 index 0000000..1ad0040 --- /dev/null +++ b/doc/gettingStarted/updating-software.md @@ -0,0 +1,50 @@ +## Firmware, InfiniTime, Bootloader, Recovery firmware, OTA, DFU... What is it? + +You might have already seen these words by reading the announcement, release notes, or [the wiki guide](https://wiki.pine64.org/wiki/Upgrade_PineTime_to_InfiniTime_1.0.0) and, you may find them confusing if you're not familiar with the project. + +Basically, a **firmware** is just a software running on the embedded hardware of a device, the PineTime in this case. +**InfiniTime OS** is based on 3 distinct **firmwares**: + - **[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/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**evice **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? + +You can check the InfiniTime version by first swiping right on the watchface to open quick settings, tapping the cogwheel to open settings, swipe up until you find an entry named "About" and tap on it. + +![InfiniTime 1.0 version](version-1.0.jpg) + +PineTimes shipped after June 2021 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 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). + +The bootloader is easily recognizable with its white pine cone that is progressively drawn in green. It also displays its own version on the bottom (1.0.0 as of now). + +![Bootloader 1.0](bootloader-1.0.jpg) + +## How to update your PineTime? + +To update your PineTime, you can use one of the compatible companion applications. Here are the main ones: + + - **[Amazfish](https://github.com/piggz/harbour-amazfish)** (Desktop Linux, mobile Linux, SailfishOS, runs on the PinebookPro and the Pinephone) + - **[Gadgetbridge](https://www.gadgetbridge.org/)** (Android) + - **[Siglo](https://github.com/alexr4535/siglo)** (Linux, GTK based) + - **NRFConnect** (closed source, Android & iOS) + +We have instructions for updating the software with Gadgetbridge and NRFConnect. + + - [Updating with Gadgetbridge](/doc/gettingStarted/ota-gadgetbridge.md) + - [Updating with NRFConnect](/doc/gettingStarted/ota-nrfconnect.md) + +### Firmware validation + +The bootloader requires a manual validation of the firmware. If the watch reset with an updated firmware that was not validated, the bootloader will consider it as non-functioning and will revert to the previous version of the firmware. This is a safety feature to prevent bricking your device with a faulty firmware. + +You can validate your updated firmware on InfiniTime >= 1.0 by following this simple procedure: + + - From the watchface, swipe **right** to display the *quick settings menu* + - Open settings by tapping the cogwheel on the bottom right + - Swipe up until you find an entry named **Firmware** and tap on it + - This app shows the version that is currently running. If the firmware is not validated yet, you can either validate the running firmware, or reset and revert to the previous firmware version diff --git a/images/infinitime-logo-github.jpg b/images/infinitime-logo-github.jpg deleted file mode 100644 index cf19e35..0000000 Binary files a/images/infinitime-logo-github.jpg and /dev/null differ diff --git a/images/infinitime-logo-small.jpg b/images/infinitime-logo-small.jpg new file mode 100644 index 0000000..9949f5b Binary files /dev/null and b/images/infinitime-logo-small.jpg differ -- cgit v0.10.2 From cf9332f0e502007fa04e0a4cdf9f0b1a2d97508f Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Sat, 6 Nov 2021 14:48:51 +0200 Subject: Crop and shrink photos diff --git a/doc/gettingStarted/appmenu.jpg b/doc/gettingStarted/appmenu.jpg index 1e52fe7..5e3d6a8 100644 Binary files a/doc/gettingStarted/appmenu.jpg and b/doc/gettingStarted/appmenu.jpg differ diff --git a/doc/gettingStarted/bootloader-1.0.jpg b/doc/gettingStarted/bootloader-1.0.jpg index 7b63918..a21f88f 100644 Binary files a/doc/gettingStarted/bootloader-1.0.jpg and b/doc/gettingStarted/bootloader-1.0.jpg differ diff --git a/doc/gettingStarted/quickactions.jpg b/doc/gettingStarted/quickactions.jpg index 0d92b13..3bbe162 100644 Binary files a/doc/gettingStarted/quickactions.jpg and b/doc/gettingStarted/quickactions.jpg differ diff --git a/doc/gettingStarted/settings.jpg b/doc/gettingStarted/settings.jpg index 510b29e..075708a 100644 Binary files a/doc/gettingStarted/settings.jpg and b/doc/gettingStarted/settings.jpg differ diff --git a/doc/gettingStarted/version-1.0.jpg b/doc/gettingStarted/version-1.0.jpg index bcfc8c6..59655b1 100644 Binary files a/doc/gettingStarted/version-1.0.jpg and b/doc/gettingStarted/version-1.0.jpg differ -- cgit v0.10.2 From c3c5ab347308d820843d2076db5543ffa93934d1 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Sat, 6 Nov 2021 14:58:10 +0200 Subject: Reorganization diff --git a/doc/gettingStarted/gettingStarted-1.0.md b/doc/gettingStarted/gettingStarted-1.0.md index a688193..074c34a 100644 --- a/doc/gettingStarted/gettingStarted-1.0.md +++ b/doc/gettingStarted/gettingStarted-1.0.md @@ -13,11 +13,12 @@ By default, InfiniTime starts on the digital watchface. It'll probably display t You can sync the time using companion apps. - Gadgetbridge automatically synchronizes the time when you connect it to your watch. More information on Gadgetbridge [here](/doc/gettingStarted/ota-gadgetbridge.md) - - You can use NRFConnect to [sync the time](/doc/gettingStarted/time-nrfconnect.md) + - [Sync the time with NRFConnect](/doc/gettingStarted/time-nrfconnect.md) - Sync the time with your browser https://hubmartin.github.io/WebBLEWatch/ - - Since InfiniTime 1.7.0, you can set the time in the settings without needing to use a companion app -## Navigation in the menu +Since InfiniTime 1.7.0, you can set the time in the settings without needing to use a companion app + +### Navigation in the menu ![Quick actions](quickactions.jpg) ![Settings](settings.jpg) @@ -31,14 +32,3 @@ You can sync the time using companion apps. - Enable/disable vibrations on notifications (Do Not Disturb mode) - Enter the **settings** menu - Swipe up and down to see all options - -### Bootloader - -Most of the time, the bootloader just runs without your intervention (update and load the firmware). - -However, you can enable 2 functionalities using the push button: - - - Push the button until the pine cone is drawn in **blue** to force the rollback of the previous version of the firmware, even if you've already validated the updated one - - Push the button until the pine cone is drawn in **red** to load the recovery firmware. This recovery firmware only provides BLE connectivity and OTA functionality. - -More info about the bootloader in [its project page](https://github.com/JF002/pinetime-mcuboot-bootloader/blob/master/README.md). diff --git a/doc/gettingStarted/updating-software.md b/doc/gettingStarted/updating-software.md index 1ad0040..52d3516 100644 --- a/doc/gettingStarted/updating-software.md +++ b/doc/gettingStarted/updating-software.md @@ -48,3 +48,14 @@ You can validate your updated firmware on InfiniTime >= 1.0 by following this si - Open settings by tapping the cogwheel on the bottom right - Swipe up until you find an entry named **Firmware** and tap on it - This app shows the version that is currently running. If the firmware is not validated yet, you can either validate the running firmware, or reset and revert to the previous firmware version + +## Bootloader + +Most of the time, the bootloader just runs without your intervention (update and load the firmware). + +However, you can enable 2 functionalities using the push button: + + - Push the button until the pine cone is drawn in **blue** to force the rollback of the previous version of the firmware, even if you've already validated the updated one + - Push the button until the pine cone is drawn in **red** to load the recovery firmware. This recovery firmware only provides BLE connectivity and OTA functionality. + +More info about the bootloader in [its project page](https://github.com/JF002/pinetime-mcuboot-bootloader/blob/master/README.md). -- cgit v0.10.2 From 1d3098baa772176476febb05531a074c0d133b56 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Sat, 6 Nov 2021 15:04:37 +0200 Subject: Update ui_guidelines diff --git a/README.md b/README.md index 22c91b5..ecda014 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ InfiniTime is an open-source firmware for the [Pinetime smartwatch](https://www. - [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) + - [Tips on designing an app UI](doc/ui_guidelines.md) ### Build, flash and debug diff --git a/doc/ui_guidelines.md b/doc/ui_guidelines.md index c267b79..0cbd39f 100644 --- a/doc/ui_guidelines.md +++ b/doc/ui_guidelines.md @@ -4,13 +4,10 @@ - Buttons should generally be at least 50px high - Buttons should generally be on the bottom edge - Make interactable objects **big** -- Recommendations for inner padding, aka distance between buttons: - - When aligning 4 objects: 4px, e.g. Settings - - When aligning 3 objects: 6px, e.g. App list - - When aligning 2 objects: 10px, e.g. Quick settings - When using a page indicator, leave 8px for it on the right side - It is acceptable to leave 8px on the left side as well to center the content - Top bar takes at least 20px + padding - Top bar right icons move 8px to the left when using a page indicator +- A black background helps to hide the screen border, allowing the UI to look less cramped when utilizing the entire display area. ![example layouts](./ui/example.png) -- cgit v0.10.2 From 52d19065893f6af66fa0e1c426852b820358f3b5 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Sun, 7 Nov 2021 18:30:29 +0200 Subject: Separate and update coding conventions and contributing pages diff --git a/README.md b/README.md index ecda014..4b80ef3 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,7 @@ InfiniTime is an open-source firmware for the [Pinetime smartwatch](https://www. ## Documentation ### Develop + - [Coding conventions](/doc/coding-convention.md) - [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) @@ -48,9 +49,9 @@ InfiniTime is an open-source firmware for the [Pinetime smartwatch](https://www. This project is far from being finished, and there are still a lot of things to do for this project to become a firmware usable by the general public. -Do not hesitate to fork the code, hack it and create pull-requests! +Do not hesitate to fork the code, hack it and create pull-requests! Make sure to read the [coding conventions](/doc/coding-convention.md) -Read this page for more information on how you can help: [How to contribute?](doc/contribute.md) +You don't need to be a programmer to contribute. Read this page for more information on how you can help: [How to contribute?](doc/contribute.md) ## Licenses diff --git a/doc/coding-convention.md b/doc/coding-convention.md new file mode 100644 index 0000000..6672d54 --- /dev/null +++ b/doc/coding-convention.md @@ -0,0 +1,40 @@ +# Coding convention + +## Language + +The language of this project is **C++**, and all new code must be written in C++. (Modern) C++ provides a lot of useful tools and functionalities that are beneficial for embedded software development like `constexpr`, `template` and anything that provides zero-cost abstraction. + +C code is accepted if it comes from another library like FreeRTOS, NimBLE, LVGL or the NRF-SDK. + +## Coding style + +The most important rule to follow is to try to keep the code as easy to read and maintain as possible. + +Using an autoformatter is highly recommended, but make sure it's configured properly. + +There are preconfigured autoformatter rules for: + + * CLion (IntelliJ) in [.idea/codeStyles/Project.xml](/.idea/codeStyles/Project.xml) + * `clang-format` + +Also use `clang-tidy` to check the code for other issues. + +If there are no preconfigured rules for your IDE, you can use one of the existing ones to configure your IDE. + + - **Indentation** : 2 spaces, no tabulation + - **Opening brace** at the end of the line + - **Naming** : Choose self-describing variable name + - **class** : PascalCase + - **namespace** : PascalCase + - **variable** : camelCase, **no** prefix/suffix ('_', 'm_',...) for class members + - **Include guard** : `#pragma once` (no `#ifdef __MODULE__ / #define __MODULE__ / #endif`) + - **Includes** : + - files from the project : `#include "relative/path/to/the/file.h"` + - external files and std : `#include ` + - Only use [primary spellings for operators and tokens](https://en.cppreference.com/w/cpp/language/operator_alternative) + - Use auto sparingly. Don't use auto for [fundamental/built-in types](https://en.cppreference.com/w/cpp/language/types) and [fixed width integer types](https://en.cppreference.com/w/cpp/types/integer), except when initializing with a cast to avoid duplicating the type name. + - Examples: + - `auto* app = static_cast(instance);` + - `auto number = static_cast(variable);` + - `uint8_t returnValue = MyFunction();` + - Use nullptr instead of NULL diff --git a/doc/contribute.md b/doc/contribute.md index 595a599..70fc567 100644 --- a/doc/contribute.md +++ b/doc/contribute.md @@ -14,10 +14,6 @@ As the documentation is part of the source code, you can submit your improvement You want to fix a bug, add a cool new functionality or improve the code? See *How to submit a pull request below*. -## Spread the word - -The Pinetime is a cool open source project that deserves to be known. Talk about it around you, on social networks, on your blog,... and let people know that we are working on an open source firmware for a smartwatch! - # How to submit a pull request? ## TL;DR @@ -25,7 +21,7 @@ The Pinetime is a cool open source project that deserves to be known. Talk about - Create a branch from develop - Work on a single subject in this branch. Create multiple branches/pulls-requests if you want to work on multiple subjects (bugs, features,...) - Test your modifications on the actual hardware - - Check the code formatting against our coding conventions and [clang-format](../.clang-format) and [clang-tidy](../.clang-tidy) + - Check your code against the [coding conventions](/doc/coding-convention.md) and [clang-format](../.clang-format) and [clang-tidy](../.clang-tidy) - Clean your code and remove files that are not needed - Write documentation related to your new feature if applicable - Create a pull request and write a great description about it: what does your PR do, why, how,... Add pictures and video if possible @@ -38,9 +34,9 @@ If you want to fix a bug, add functionality or improve the code, you'll first ne When your feature branch is ready, **make sure it actually works** and **do not forget to write documentation** about it if it's relevant. -**Creating a pull request containing modifications that haven't been tested is strongly discouraged.** If, for any reason, you cannot test your modifications but want to publish them anyway, **please mention it in the description**. This way, other contributors might be willing to test it and provide feedback about your code. +**Creating a pull request containing modifications that haven't been tested is strongly discouraged.** If for any reason you cannot test your modifications, but want to publish them anyway, **please mention it in the description**. This way, other contributors might be willing to test it and provide feedback about your code. -Also, before submitting your PR, check the coding style of your code against the **coding conventions** detailed below. This project also provides [clang-format](../.clang-format) and [clang-tidy](../.clang-tidy) configuration files. You can use them to ensure correct formatting of your code. +Before submitting a PR, check your code against our [coding conventions](/doc/coding-convention.md). This project also provides [clang-format](../.clang-format) and [clang-tidy](../.clang-tidy) configuration files. You should use them to ensure correct formatting of your code. Don't forget to check the files you are going to commit and remove those which aren't necessary (config files from your IDE, for example). Remove old comments, commented code,... @@ -52,52 +48,14 @@ Once the pull request is reviewed and accepted, it'll be merged into **develop** ## Why all these rules? -Reviewing pull requests is a **very time consuming task** for the creator of this project ([JF002](https://github.com/JF002)) and for other contributors who take the time to review them. Everything you do to make reviewing easier will **get your PR merged faster**. +Reviewing pull requests is a **very time consuming task**. Everything you do to make reviewing easier will **get your PR merged faster**. -When reviewing PRs, the author and contributors will first look at the **description**. If it's easy to understand what the PR does, why the modification is needed or interesting and how it's done, a good part of the work is already done : we understand the PR and its context. +Reviewers will first look at the **description**. If it's easy to understand what the PR does, why the modification is needed or interesting and how it's done, a good part of the work is already done : we understand the PR and its context. -Then, reviewing **a few files that were modified for a single purpose** is a lot more easier than to review 30 files modified for many reasons (bug fix, UI improvements, typos in doc,...), even if all these changes make sense. Also, it's possible that we agree on some modification but not on some other, so we won't be able to merge the PR because of the changes that are not accepted. +Reviewing **a few files that were modified for a single purpose** is a lot easier than reviewing 30 files modified for many reasons (bug fix, UI improvements, typos in doc,...), even if all the changes make sense. Also, it's possible that we agree on some modification but not on another, so we won't be able to merge the PR because of the changes that are not accepted. -We do our best to keep the code as consistent as possible. If the formatting of the code in your PR is not consistent with our code base, we'll ask you to review it, which will take more time. +We do our best to keep the code as consistent as possible. If the formatting of your code is not consistent with our code base, we'll ask you to review it. -The last step of the review consists of **testing** the modification. If it doesn't work out of the box, we'll ask your to review your code and to ensure that it works as expected. +Lastly the changes are tested. If it doesn't work out of the box, we'll ask your to review your code and to ensure that it works as expected. It's totally normal for a PR to need some more work even after it was created, that's why we review them. But every round trip takes time, so it's good practice to try to reduce them as much as possible by following those simple rules. - -# Coding convention - -## Language - -The language of this project is **C++**, and all new code must be written in C++. (Modern) C++ provides a lot of useful tools and functionalities that are beneficial for embedded software development like `constexpr`, `template` and anything that provides zero-cost abstraction. - -C code is accepted if it comes from another library like FreeRTOS, NimBLE, LVGL or the NRF-SDK. - -## Coding style - -The most important rule to follow is to try to keep the code as easy to read and maintain as possible. - -Using an autoformatter is highly recommended, but make sure it's configured properly. - -There are preconfigured autoformatter rules for: - - * CLion (IntelliJ) in .idea/codeStyles/Project.xml - -If there are no preconfigured rules for your IDE, you can use one of the existing ones to configure your IDE. - - - **Indentation** : 2 spaces, no tabulation - - **Opening brace** at the end of the line - - **Naming** : Choose self-describing variable name - - **class** : PascalCase - - **namespace** : PascalCase - - **variable** : camelCase, **no** prefix/suffix ('_', 'm_',...) for class members - - **Include guard** : `#pragma once` (no `#ifdef __MODULE__ / #define __MODULE__ / #endif`) - - **Includes** : - - files from the project : `#include "relative/path/to/the/file.h"` - - external files and std : `#include ` - - Only use [primary spellings for operators and tokens](https://en.cppreference.com/w/cpp/language/operator_alternative) - - Use auto sparingly. Don't use auto for [fundamental/built-in types](https://en.cppreference.com/w/cpp/language/types) and [fixed width integer types](https://en.cppreference.com/w/cpp/types/integer), except when initializing with a cast to avoid duplicating the type name. - - Examples: - - `auto* app = static_cast(instance);` - - `auto number = static_cast(variable);` - - `uint8_t returnValue = MyFunction();` - - Use nullptr instead of NULL -- cgit v0.10.2 From 2314c41ad66836fe4142d73895ad0ae2ad18651c Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Sun, 7 Nov 2021 18:45:24 +0200 Subject: Reorganize bootloader readme diff --git a/bootloader/README.md b/bootloader/README.md index 9f99602..1a02ebd 100644 --- a/bootloader/README.md +++ b/bootloader/README.md @@ -115,8 +115,6 @@ sudo dfu.py -z /home/jf/nrf52/bootloader/dfu.zip -a --leg **Note** : dfu.py is a slightly modified version of [this repo](https://github.com/daniel-thompson/ota-dfu-python). -See [this page](../doc/CompanionApps/NrfconnectOTA.md) for more info about OTA with NRFConect - ### Firmware validation Once the OTA is done, InfiniTime will reset the watch to apply the update. When the watch reboots, the new firmware is running. @@ -126,12 +124,12 @@ If the new firmware is working correctly, open the application menu and tap on t Firmware validation application in the menu: -![Firmware Validation App](../doc/CompanionApps/firmwareValidationApp.jpg "Firmware Validation App") +![Firmware Validation App](../doc/bootloader/firmwareValidationApp.jpg "Firmware Validation App") The firmware is not validated yet. Tap 'Validate' to validate it, or 'Reset' to rollback to the previous version. -![Firmware Not Validated](../doc/CompanionApps/firmwareNoValidated.jpg "Firmware Not Validated") +![Firmware Not Validated](../doc/bootloader/firmwareNoValidated.jpg "Firmware Not Validated") The firmware is validated! -![Firmware Validated](../doc/CompanionApps/firmwareValidated.jpg "Firmware Validated") +![Firmware Validated](../doc/bootloader/firmwareValidated.jpg "Firmware Validated") diff --git a/doc/bootloader/firmwareNoValidated.jpg b/doc/bootloader/firmwareNoValidated.jpg new file mode 100644 index 0000000..28df7ea Binary files /dev/null and b/doc/bootloader/firmwareNoValidated.jpg differ diff --git a/doc/bootloader/firmwareValidated.jpg b/doc/bootloader/firmwareValidated.jpg new file mode 100644 index 0000000..0d6f99b Binary files /dev/null and b/doc/bootloader/firmwareValidated.jpg differ diff --git a/doc/bootloader/firmwareValidationApp.jpg b/doc/bootloader/firmwareValidationApp.jpg new file mode 100644 index 0000000..d78ad0c Binary files /dev/null and b/doc/bootloader/firmwareValidationApp.jpg differ diff --git a/doc/companionapps/firmwareNoValidated.jpg b/doc/companionapps/firmwareNoValidated.jpg deleted file mode 100644 index 28df7ea..0000000 Binary files a/doc/companionapps/firmwareNoValidated.jpg and /dev/null differ diff --git a/doc/companionapps/firmwareValidated.jpg b/doc/companionapps/firmwareValidated.jpg deleted file mode 100644 index 0d6f99b..0000000 Binary files a/doc/companionapps/firmwareValidated.jpg and /dev/null differ diff --git a/doc/companionapps/firmwareValidationApp.jpg b/doc/companionapps/firmwareValidationApp.jpg deleted file mode 100644 index d78ad0c..0000000 Binary files a/doc/companionapps/firmwareValidationApp.jpg and /dev/null differ -- cgit v0.10.2 From a0c7b48b8eb6f2b59dcaec846c5ed46aeabf1e6a Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Sun, 7 Nov 2021 18:55:51 +0200 Subject: Replace companionapp pages with links. Add companion apps diff --git a/README.md b/README.md index 4b80ef3..2214a35 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,10 @@ InfiniTime is an open-source firmware for the [Pinetime smartwatch](https://www. - [Getting started with InfiniTime](doc/gettingStarted/gettingStarted-1.0.md) - [About the software and updating](doc/gettingStarted/updating-software.md) - Companion apps: - - [Gadgetbridge](doc/companionapps/Gadgetbridge.md) - - [AmazFish](doc/companionapps/Amazfish.md) + - [Gadgetbridge](https://gadgetbridge.org/) (Android) + - [AmazFish](https://openrepos.net/content/piggz/amazfish/) (SailfishOS) + - [Siglo](https://github.com/alexr4535/siglo) (Linux) + - [InfiniLink](https://github.com/xan-m/InfiniLink) **[Experimental]** (iOS) ## Documentation diff --git a/doc/companionapps/Amazfish.md b/doc/companionapps/Amazfish.md deleted file mode 100644 index 90ad20c..0000000 --- a/doc/companionapps/Amazfish.md +++ /dev/null @@ -1,16 +0,0 @@ -# Amazfish -[Amazfish](https://openrepos.net/content/piggz/amazfish) is a companion app that supports many smartwatches and activity trackers running on [SailfishOS](https://sailfishos.org/). - -## Features -The following features are implemented: - - Scanning & detection of Pinetime-JF / InfiniTime - - Connection / disconnection - - Time synchronization - - Notifications - - Music control - - Navigation with Puremaps - -## Demo -[This video](https://seafile.codingfield.com/f/21c5d023452740279e36/) shows how to connect to the Pinetime and control the playback of the music on the phone. -Amazfish and Sailfish OS are running on the [Pinephone](https://www.pine64.org/pinephone/), another awesome device from Pine64. - diff --git a/doc/companionapps/Gadgetbridge.md b/doc/companionapps/Gadgetbridge.md deleted file mode 100644 index 678fe7a..0000000 --- a/doc/companionapps/Gadgetbridge.md +++ /dev/null @@ -1,7 +0,0 @@ -# Integration with Gadgetbridge -[Gadgetbridge](https://gadgetbridge.org/) is an Android application that supports many smartwatches and fitness trackers. - -Gadgetbridge supports InfiniTime [starting with version 0.47](https://codeberg.org/Freeyourgadget/Gadgetbridge/src/branch/master/CHANGELOG.md). Note that the official version is only available on F-Droid (as of May 2021), and the unofficial fork available on the Play Store is outdated and does not support InfiniTime. - -## Demo -[This video](https://seafile.codingfield.com/f/0a2920b9d765462385e4/) shows how to scan, connect, send notification (using the debug screen) and disconnect from the PineTime. -- cgit v0.10.2 From 88e55b2504f52c7d89f733bf5141bc67e525d908 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Sun, 7 Nov 2021 19:38:54 +0200 Subject: Update updating instructions diff --git a/doc/gettingStarted/ota-gadgetbridge.md b/doc/gettingStarted/ota-gadgetbridge.md index 971eaad..022b5e4 100644 --- a/doc/gettingStarted/ota-gadgetbridge.md +++ b/doc/gettingStarted/ota-gadgetbridge.md @@ -14,17 +14,7 @@ Tap on it. Gadgdetbridge will pair and connect to your device: # Updating with Gadgetbridge -## Preparation - -All releases of InfiniTime are available on the [release page of the GitHub repo](https://github.com/InfiniTimeOrg/InfiniTime/releases). - -Release files are available under the *Assets* button. - -You need to download the DFU of the firmware version that you'd like to install, for example `pinetime-mcuboot-app-dfu-1.6.0.zip` - -## Gadgetbridge - -Now that Gadgetbridge is connected to your PineTime, use a file browser application (I'm using Seafile to browse my NAS) and browse to the DFU file (image-xxx.zip) you downloaded previously. Tap on it and open it using the Gadgetbridge application/firmware installer: +Now that Gadgetbridge is connected to your PineTime, use a file browser application and find the DFU file (`pinetime-mcuboot-app-dfu-x.x.x.zip`) you downloaded previously. Tap on it and open it using the Gadgetbridge application/firmware installer: ![Gadgetbridge 3](gadgetbridge3.jpg) diff --git a/doc/gettingStarted/ota-nrfconnect.md b/doc/gettingStarted/ota-nrfconnect.md index dbc7829..800bd6b 100644 --- a/doc/gettingStarted/ota-nrfconnect.md +++ b/doc/gettingStarted/ota-nrfconnect.md @@ -1,15 +1,5 @@ # Updating with NRFConnect -## Preparation - -All releases of InfiniTime are available on the [release page of the GitHub repo](https://github.com/InfiniTimeOrg/InfiniTime/releases). - -Release files are available under the *Assets* button. - -You need to download the DFU of the firmware version that you'd like to install, for example `pinetime-mcuboot-app-dfu-1.6.0.zip` - -## NRFConnect - Open NRFConnect. Swipe down in the *Scanner* tab and wait for your device to appear: ![NRFConnect 0](nrfconnect0.jpg) @@ -22,7 +12,7 @@ Select **Distribution packet (ZIP)**: ![NRFConnect 2](nrfconnect2.jpg) -Browse to the DFU file you downloaded previously, the DFU transfer will start automatically. When the transfer is finished, your PineTime will reset and restart on the new version of InfiniTime! +Find the DFU file (`pinetime-mcuboot-app-dfu-x.x.x.zip`) you downloaded previously, the DFU transfer will start automatically. When the transfer is finished, your PineTime will reset and restart on the new version of InfiniTime! Don't forget to **validate** your firmware. In the InfiniTime go to the settings (swipe right, select gear icon) and Firmware option and click **validate**. Otherwise after reboot the previous firmware will be used. diff --git a/doc/gettingStarted/updating-software.md b/doc/gettingStarted/updating-software.md index 52d3516..214200a 100644 --- a/doc/gettingStarted/updating-software.md +++ b/doc/gettingStarted/updating-software.md @@ -26,14 +26,17 @@ The bootloader is easily recognizable with its white pine cone that is progressi ## How to update your PineTime? -To update your PineTime, you can use one of the compatible companion applications. Here are the main ones: +To update your PineTime, you can use one of the compatible companion applications. - - **[Amazfish](https://github.com/piggz/harbour-amazfish)** (Desktop Linux, mobile Linux, SailfishOS, runs on the PinebookPro and the Pinephone) - - **[Gadgetbridge](https://www.gadgetbridge.org/)** (Android) - - **[Siglo](https://github.com/alexr4535/siglo)** (Linux, GTK based) - - **NRFConnect** (closed source, Android & iOS) +The updating process differs slightly on every companion app, so you'll need to familiarize yourself with the companion app of your choice. -We have instructions for updating the software with Gadgetbridge and NRFConnect. +All releases of InfiniTime are available on the [release page of the GitHub repo](https://github.com/InfiniTimeOrg/InfiniTime/releases). + +Release files are available under the *Assets* button. + +To update the firmware, you need to download the DFU of the firmware version that you'd like to install, for example `pinetime-mcuboot-app-dfu-1.6.0.zip`, and flash it with your companion app. + +We have prepared instructions for flashing InfiniTime with Gadgetbridge and NRFConnect. - [Updating with Gadgetbridge](/doc/gettingStarted/ota-gadgetbridge.md) - [Updating with NRFConnect](/doc/gettingStarted/ota-nrfconnect.md) -- cgit v0.10.2 From e53f1bfd668a5c130352616aceb6c660821dc14c Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 8 Nov 2021 17:37:25 +0200 Subject: Summarize updating-softare diff --git a/doc/gettingStarted/updating-software.md b/doc/gettingStarted/updating-software.md index 214200a..4058672 100644 --- a/doc/gettingStarted/updating-software.md +++ b/doc/gettingStarted/updating-software.md @@ -1,14 +1,18 @@ ## Firmware, InfiniTime, Bootloader, Recovery firmware, OTA, DFU... What is it? -You might have already seen these words by reading the announcement, release notes, or [the wiki guide](https://wiki.pine64.org/wiki/Upgrade_PineTime_to_InfiniTime_1.0.0) and, you may find them confusing if you're not familiar with the project. +You may have already encountered these words by reading the announcement, release notes, or [the wiki guide](https://wiki.pine64.org/wiki/Upgrade_PineTime_to_InfiniTime_1.0.0) and you may find them confusing if you're not familiar with the project. -Basically, a **firmware** is just a software running on the embedded hardware of a device, the PineTime in this case. -**InfiniTime OS** is based on 3 distinct **firmwares**: - - **[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/InfiniTimeOrg/InfiniTime/releases/tag/0.14.1). +A **firmware** is software running on the embedded hardware of a device. -**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**evice **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). +InfiniTime has three distinct firmwares: + + - **[InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime)** is the operating system. + - **[The bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader)** is responsible for safely applying firmware updates and runs before booting into InfiniTime. + - **The recovery firmware** is a special *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. + +**OTA** (**O**ver **T**he **A**ir) refers to updating of the firmware over BLE (**B**luetooth **L**ow **E**nergy). This is a functionality that allows the user to update the firmware on their device wirelessly. + +**DFU** (**D**evice **F**irmware **U**pdate) is 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? @@ -18,7 +22,7 @@ You can check the InfiniTime version by first swiping right on the watchface to PineTimes shipped after June 2021 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 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). +The bootloader is run right before booting to InfiniTime. The bootloader is easily recognizable with its white pine cone that is progressively drawn in green. It also displays its own version on the bottom (1.0.0 as of now). @@ -30,9 +34,7 @@ To update your PineTime, you can use one of the compatible companion application The updating process differs slightly on every companion app, so you'll need to familiarize yourself with the companion app of your choice. -All releases of InfiniTime are available on the [release page of the GitHub repo](https://github.com/InfiniTimeOrg/InfiniTime/releases). - -Release files are available under the *Assets* button. +All releases of InfiniTime are available on the [release page of the GitHub repo](https://github.com/InfiniTimeOrg/InfiniTime/releases) under assets. To update the firmware, you need to download the DFU of the firmware version that you'd like to install, for example `pinetime-mcuboot-app-dfu-1.6.0.zip`, and flash it with your companion app. @@ -43,14 +45,14 @@ We have prepared instructions for flashing InfiniTime with Gadgetbridge and NRFC ### Firmware validation -The bootloader requires a manual validation of the firmware. If the watch reset with an updated firmware that was not validated, the bootloader will consider it as non-functioning and will revert to the previous version of the firmware. This is a safety feature to prevent bricking your device with a faulty firmware. +Firmware updates must be manually validated. If the firmware isn't validated and the watch resets, the watch will revert to the previous firmware. This is a safety feature to prevent bricking your device with faulty firmware. You can validate your updated firmware on InfiniTime >= 1.0 by following this simple procedure: - From the watchface, swipe **right** to display the *quick settings menu* - Open settings by tapping the cogwheel on the bottom right - Swipe up until you find an entry named **Firmware** and tap on it - - This app shows the version that is currently running. If the firmware is not validated yet, you can either validate the running firmware, or reset and revert to the previous firmware version + - If the firmware is not validated yet, you can either validate the running firmware, or reset and revert to the previous firmware version ## Bootloader -- cgit v0.10.2 From 5eaae4175c19f0e2752d3e27372f5aa578dec980 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 8 Nov 2021 17:38:21 +0200 Subject: Fix versioning diff --git a/doc/versioning.md b/doc/versioning.md index 48e0504..8b87d47 100644 --- a/doc/versioning.md +++ b/doc/versioning.md @@ -1,6 +1,6 @@ # Versioning -The versioning of this project is based on [Semantic versionning](https://semver.org/) : +The versioning of this project is based on [Semantic versioning](https://semver.org/): - The **patch** is incremented when we fix a bug on a **released** version (most of the time using a **hotfix** branch). - The **minor** is incremented when we release a new version with new features. It corresponds to a merge of **develop** into **master**. - - The **major** should be incremented when a breaking change is made to the application. We still have to define what is a breaking change in the context of this project. For now, I suggest that it stays **0** until we have a fully functioning firmware suited for the final user. \ No newline at end of file + - The **major** should be incremented when a breaking change is made to the application. We still have to define what is a breaking change in the context of this project. -- cgit v0.10.2 From d1583035d9564ca49d00711cf53ad07a35038b7c Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 8 Nov 2021 17:42:42 +0200 Subject: Link to companion apps diff --git a/README.md b/README.md index 2214a35..b85dba3 100644 --- a/README.md +++ b/README.md @@ -10,11 +10,11 @@ InfiniTime is an open-source firmware for the [Pinetime smartwatch](https://www. - [Getting started with InfiniTime](doc/gettingStarted/gettingStarted-1.0.md) - [About the software and updating](doc/gettingStarted/updating-software.md) - - Companion apps: - - [Gadgetbridge](https://gadgetbridge.org/) (Android) - - [AmazFish](https://openrepos.net/content/piggz/amazfish/) (SailfishOS) - - [Siglo](https://github.com/alexr4535/siglo) (Linux) - - [InfiniLink](https://github.com/xan-m/InfiniLink) **[Experimental]** (iOS) +### Companion apps + - [Gadgetbridge](https://gadgetbridge.org/) (Android) + - [AmazFish](https://openrepos.net/content/piggz/amazfish/) (SailfishOS) + - [Siglo](https://github.com/alexr4535/siglo) (Linux) + - [InfiniLink](https://github.com/xan-m/InfiniLink) **[Experimental]** (iOS) ## Documentation diff --git a/doc/gettingStarted/updating-software.md b/doc/gettingStarted/updating-software.md index 4058672..316d77f 100644 --- a/doc/gettingStarted/updating-software.md +++ b/doc/gettingStarted/updating-software.md @@ -30,7 +30,7 @@ The bootloader is easily recognizable with its white pine cone that is progressi ## How to update your PineTime? -To update your PineTime, you can use one of the compatible companion applications. +To update your PineTime, you can use one of the [compatible companion applications](/README.md#companion-apps). The updating process differs slightly on every companion app, so you'll need to familiarize yourself with the companion app of your choice. -- cgit v0.10.2 From c12fc5e3132f88e2b134f9feed70a8bc1cae5e7f Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 8 Nov 2021 18:11:29 +0200 Subject: Improvements to Apps.md and Intro.md diff --git a/doc/code/Apps.md b/doc/code/Apps.md index 7c2d7a0..b8e4a3f 100644 --- a/doc/code/Apps.md +++ b/doc/code/Apps.md @@ -1,11 +1,12 @@ # Apps This page will teach you: -- what apps in InfiniTime are +- what screens and apps are in InfiniTime - how to implement your own app ## 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. + +The user interface of InfiniTime is made up of **screens** +Screens that are opened from the app launcher are considered **apps** 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)). @@ -23,27 +24,21 @@ it does not need to override any of these functions, as LVGL can also handle tou 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 +If your app needs to be updated continuously, you 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. -### 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. +An example call could look like this: +```cpp +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. ## Creating your own app -A minimal app could look like this:
+A minimal app could look like this: + MyApp.h: ```cpp #pragma once @@ -66,13 +61,13 @@ namespace Pinetime { MyApp.cpp: ```cpp -#include "MyApp.h" +#include "displayapp/screens/MyApp.h" #include "displayapp/DisplayApp.h" using namespace Pinetime::Applications::Screens; MyApp::MyApp(DisplayApp* app) : Screen(app) { - lv_obj_t* title = lv_label_create(lv_scr_act(), NULL); + lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr); 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); @@ -95,12 +90,10 @@ Now, go to the function `DisplayApp::LoadApp` and add another case to the switch 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 your app is a setting, do the same procedure in [displayapp/screens/settings/Settings.cpp](/src/displayapp/screens/settings/Settings.cpp). +If you want to add your app in the app launcher, add your app in [displayapp/screens/ApplicationList.cpp](/src/displayapp/screens/ApplicationList.cpp) 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! Please remember to pay attention to the [UI guidelines](../ui_guidelines.md) -when designing an app that you want to include in mainstream InfiniTime. +when designing an app that you want to be included in InfiniTime. diff --git a/doc/code/Intro.md b/doc/code/Intro.md index 762102f..6764e58 100644 --- a/doc/code/Intro.md +++ b/doc/code/Intro.md @@ -21,7 +21,7 @@ Both functions are located inside [systemtask/SystemTask.cpp](/src/systemtask/Sy 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)).
+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. -- cgit v0.10.2 From 3375c4e18764cd0ed1be8898a21695ff60540b22 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 8 Nov 2021 18:13:27 +0200 Subject: Add missing periods diff --git a/doc/code/Apps.md b/doc/code/Apps.md index b8e4a3f..b1c7d20 100644 --- a/doc/code/Apps.md +++ b/doc/code/Apps.md @@ -5,8 +5,8 @@ This page will teach you: ## Theory -The user interface of InfiniTime is made up of **screens** -Screens that are opened from the app launcher are considered **apps** +The user interface of InfiniTime is made up of **screens**. +Screens that are opened from the app launcher are considered **apps**. 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)). -- cgit v0.10.2 From a326e22986f69e40572e8ef0c0efde854ea7d386 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 8 Nov 2021 18:16:28 +0200 Subject: Add line break diff --git a/doc/code/Intro.md b/doc/code/Intro.md index 6764e58..bf68c7a 100644 --- a/doc/code/Intro.md +++ b/doc/code/Intro.md @@ -22,6 +22,7 @@ It also starts the **task "displayapp"**, which is responsible for launching and 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. -- cgit v0.10.2 From caec4a560b46f30f08f03ea5cff4c902034956e4 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 8 Nov 2021 19:14:23 +0200 Subject: Replace some "we" diff --git a/doc/contribute.md b/doc/contribute.md index 70fc567..b1be84a 100644 --- a/doc/contribute.md +++ b/doc/contribute.md @@ -36,7 +36,7 @@ When your feature branch is ready, **make sure it actually works** and **do not **Creating a pull request containing modifications that haven't been tested is strongly discouraged.** If for any reason you cannot test your modifications, but want to publish them anyway, **please mention it in the description**. This way, other contributors might be willing to test it and provide feedback about your code. -Before submitting a PR, check your code against our [coding conventions](/doc/coding-convention.md). This project also provides [clang-format](../.clang-format) and [clang-tidy](../.clang-tidy) configuration files. You should use them to ensure correct formatting of your code. +Before submitting a PR, check your code against the [coding conventions](/doc/coding-convention.md). This project also provides [clang-format](../.clang-format) and [clang-tidy](../.clang-tidy) configuration files. You should use them to ensure correct formatting of your code. Don't forget to check the files you are going to commit and remove those which aren't necessary (config files from your IDE, for example). Remove old comments, commented code,... @@ -54,8 +54,8 @@ Reviewers will first look at the **description**. If it's easy to understand wha Reviewing **a few files that were modified for a single purpose** is a lot easier than reviewing 30 files modified for many reasons (bug fix, UI improvements, typos in doc,...), even if all the changes make sense. Also, it's possible that we agree on some modification but not on another, so we won't be able to merge the PR because of the changes that are not accepted. -We do our best to keep the code as consistent as possible. If the formatting of your code is not consistent with our code base, we'll ask you to review it. +The code base should be kept as consistent as possible. If the formatting of your code is not consistent with the rest of the code base, we'll ask you to review it. -Lastly the changes are tested. If it doesn't work out of the box, we'll ask your to review your code and to ensure that it works as expected. +Lastly the changes are tested. If it doesn't work out of the box, we'll ask you to review your code and to ensure that it works as expected. It's totally normal for a PR to need some more work even after it was created, that's why we review them. But every round trip takes time, so it's good practice to try to reduce them as much as possible by following those simple rules. diff --git a/doc/versioning.md b/doc/versioning.md index 8b87d47..2fa36ab 100644 --- a/doc/versioning.md +++ b/doc/versioning.md @@ -1,6 +1,6 @@ # Versioning The versioning of this project is based on [Semantic versioning](https://semver.org/): - - The **patch** is incremented when we fix a bug on a **released** version (most of the time using a **hotfix** branch). - - The **minor** is incremented when we release a new version with new features. It corresponds to a merge of **develop** into **master**. + - The **patch** is incremented when a bug is fixed on a **released** version (most of the time using a **hotfix** branch). + - The **minor** is incremented when a new version with new features is released. It corresponds to a merge of **develop** into **master**. - The **major** should be incremented when a breaking change is made to the application. We still have to define what is a breaking change in the context of this project. -- cgit v0.10.2 From 45a90e4967e10b31d148ae9c68123751d0e6bf6b Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Thu, 11 Nov 2021 14:26:08 +0200 Subject: Update getting started. New pics. More information. diff --git a/doc/gettingStarted/appmenu-071.jpg b/doc/gettingStarted/appmenu-071.jpg deleted file mode 100644 index dee7c8f..0000000 Binary files a/doc/gettingStarted/appmenu-071.jpg and /dev/null differ diff --git a/doc/gettingStarted/appmenu.jpg b/doc/gettingStarted/appmenu.jpg deleted file mode 100644 index 5e3d6a8..0000000 Binary files a/doc/gettingStarted/appmenu.jpg and /dev/null differ diff --git a/doc/gettingStarted/gettingStarted-1.0.md b/doc/gettingStarted/gettingStarted-1.0.md index 074c34a..939dfe5 100644 --- a/doc/gettingStarted/gettingStarted-1.0.md +++ b/doc/gettingStarted/gettingStarted-1.0.md @@ -16,19 +16,42 @@ You can sync the time using companion apps. - [Sync the time with NRFConnect](/doc/gettingStarted/time-nrfconnect.md) - Sync the time with your browser https://hubmartin.github.io/WebBLEWatch/ -Since InfiniTime 1.7.0, you can set the time in the settings without needing to use a companion app +You can also set the time in the settings without a companion app. (version >1.7.0) + +InfiniTime doesn't handle daylight savings automatically, so make sure to set the correct the time or sync it with a companion app + +### Digital watch face + +![Digital watch face](ui/watchface.jpg) + +This is what the default digital watch face looks like. You can change watch faces in the settings. + +The indicator on the top left is visible if you have unread notifications + +On the top right there are status icons + + - The battery icon shows roughly how much charge is remaining + - The Bluetooth icon is visible when the watch is connected to a companion app + - A plug icon is shown when the watch is plugged into a charger. + +On the bottom left you can see your heart rate if you have the measurement enabled in the heart rate app. + +On the bottom right you can see how many steps you have taken today. ### Navigation in the menu -![Quick actions](quickactions.jpg) -![Settings](settings.jpg) -![Application menu](appmenu.jpg) +![Application menu](ui/applist.jpg) +![Notifications](ui/notifications.jpg) +![Quick actions](ui/quicksettings.jpg) +![Settings](ui/settings.jpg) - - Swipe **down** to display the notification panel. Notification sent by your companion app will be displayed in this panel. - Swipe **up** to display the application menus. Apps (stopwatch, music, step, games,...) can be started from this menu. + - Swipe **down** to display the notification panel. Notification sent by your companion app will be displayed here. - Swipe **right** to display the Quick Actions menu. This menu allows you to - Set the brightness of the display - Start the **flashlight** app - - Enable/disable vibrations on notifications (Do Not Disturb mode) + - Enable/disable notifications (Do Not Disturb mode) - Enter the **settings** menu - Swipe up and down to see all options + - Click the button to go back a screen. + - You can hold the button for a short time to return to the watch face. (version >1.7.0) diff --git a/doc/gettingStarted/oldbootloaderlogo.jpg b/doc/gettingStarted/oldbootloaderlogo.jpg deleted file mode 100644 index b4d0cdf..0000000 Binary files a/doc/gettingStarted/oldbootloaderlogo.jpg and /dev/null differ diff --git a/doc/gettingStarted/quickactions.jpg b/doc/gettingStarted/quickactions.jpg deleted file mode 100644 index 3bbe162..0000000 Binary files a/doc/gettingStarted/quickactions.jpg and /dev/null differ diff --git a/doc/gettingStarted/settings.jpg b/doc/gettingStarted/settings.jpg deleted file mode 100644 index 075708a..0000000 Binary files a/doc/gettingStarted/settings.jpg and /dev/null differ diff --git a/doc/gettingStarted/ui/applist.jpg b/doc/gettingStarted/ui/applist.jpg new file mode 100644 index 0000000..927780e Binary files /dev/null and b/doc/gettingStarted/ui/applist.jpg differ diff --git a/doc/gettingStarted/ui/notifications.jpg b/doc/gettingStarted/ui/notifications.jpg new file mode 100644 index 0000000..00b2726 Binary files /dev/null and b/doc/gettingStarted/ui/notifications.jpg differ diff --git a/doc/gettingStarted/ui/quicksettings.jpg b/doc/gettingStarted/ui/quicksettings.jpg new file mode 100644 index 0000000..250c915 Binary files /dev/null and b/doc/gettingStarted/ui/quicksettings.jpg differ diff --git a/doc/gettingStarted/ui/settings.jpg b/doc/gettingStarted/ui/settings.jpg new file mode 100644 index 0000000..a61279b Binary files /dev/null and b/doc/gettingStarted/ui/settings.jpg differ diff --git a/doc/gettingStarted/ui/watchface.jpg b/doc/gettingStarted/ui/watchface.jpg new file mode 100644 index 0000000..e7a9439 Binary files /dev/null and b/doc/gettingStarted/ui/watchface.jpg differ diff --git a/doc/gettingStarted/version-071.jpg b/doc/gettingStarted/version-071.jpg deleted file mode 100644 index bc9bc5b..0000000 Binary files a/doc/gettingStarted/version-071.jpg and /dev/null differ -- cgit v0.10.2 From d5e8e3ca44e998511907d1ec74c98c06c2e542b8 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Sun, 14 Nov 2021 15:23:12 +0200 Subject: Split updating and about software. Remove big Contributing section from README diff --git a/README.md b/README.md index b85dba3..ae315f2 100644 --- a/README.md +++ b/README.md @@ -4,28 +4,31 @@ ![InfiniTime logo](images/infinitime-logo-small.jpg "InfiniTime Logo") -InfiniTime is an open-source firmware for the [Pinetime smartwatch](https://www.pine64.org/pinetime/) +Fast open-source firmware for the [PineTime smartwatch](https://www.pine64.org/pinetime/) with many features, written in modern C++. ## New to InfiniTime? - [Getting started with InfiniTime](doc/gettingStarted/gettingStarted-1.0.md) - - [About the software and updating](doc/gettingStarted/updating-software.md) + - [Updating the software](doc/gettingStarted/updating-software.md) + - [About the firmware and bootloader](doc/gettingStarted/about-software.md) ### Companion apps - [Gadgetbridge](https://gadgetbridge.org/) (Android) - [AmazFish](https://openrepos.net/content/piggz/amazfish/) (SailfishOS) - [Siglo](https://github.com/alexr4535/siglo) (Linux) - [InfiniLink](https://github.com/xan-m/InfiniLink) **[Experimental]** (iOS) -## Documentation +## Development -### Develop - - [Coding conventions](/doc/coding-convention.md) - [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) - [Tips on designing an app UI](doc/ui_guidelines.md) +### Contributing + - [How to contribute?](/doc/contribute.md) + - [Coding conventions](/doc/coding-convention.md) + ### Build, flash and debug - [Project branches](doc/branches.md) @@ -47,14 +50,6 @@ InfiniTime is an open-source firmware for the [Pinetime smartwatch](https://www. - [Memory analysis](./doc/MemoryAnalysis.md) -## Contributing - -This project is far from being finished, and there are still a lot of things to do for this project to become a firmware usable by the general public. - -Do not hesitate to fork the code, hack it and create pull-requests! Make sure to read the [coding conventions](/doc/coding-convention.md) - -You don't need to be a programmer to contribute. Read this page for more information on how you can help: [How to contribute?](doc/contribute.md) - ## Licenses This project is released under the GNU General Public License version 3 or, at your option, any later version. diff --git a/doc/gettingStarted/about-software.md b/doc/gettingStarted/about-software.md new file mode 100644 index 0000000..b19a610 --- /dev/null +++ b/doc/gettingStarted/about-software.md @@ -0,0 +1,26 @@ +# Firmware, InfiniTime, Bootloader, Recovery firmware, OTA, DFU... What is it? + +You may have already encountered these words by reading the announcement, release notes, or [the wiki guide](https://wiki.pine64.org/wiki/Upgrade_PineTime_to_InfiniTime_1.0.0) and you may find them confusing if you're not familiar with the project. + +A **firmware** is software running on the embedded hardware of a device. + +InfiniTime has three distinct firmwares: + + - **[InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime)** is the operating system. + - **[The bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader)** is responsible for safely applying firmware updates and runs before booting into InfiniTime. + - **The recovery firmware** is a special *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. + +**OTA** (**O**ver **T**he **A**ir) refers to updating of the firmware over BLE (**B**luetooth **L**ow **E**nergy). This is a functionality that allows the user to update the firmware on their device wirelessly. + +**DFU** (**D**evice **F**irmware **U**pdate) is 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). + +## Bootloader + +Most of the time, the bootloader just runs without your intervention (update and load the firmware). + +However, you can enable 2 functionalities using the push button: + + - Push the button until the pine cone is drawn in **blue** to force the rollback of the previous version of the firmware, even if you've already validated the updated one + - Push the button until the pine cone is drawn in **red** to load the recovery firmware. This recovery firmware only provides BLE connectivity and OTA functionality. + +More info about the bootloader in [its project page](https://github.com/JF002/pinetime-mcuboot-bootloader/blob/master/README.md). diff --git a/doc/gettingStarted/gettingStarted-1.0.md b/doc/gettingStarted/gettingStarted-1.0.md index 939dfe5..30b8bdb 100644 --- a/doc/gettingStarted/gettingStarted-1.0.md +++ b/doc/gettingStarted/gettingStarted-1.0.md @@ -1,10 +1,10 @@ -# Getting started with InfiniTime 1.0.0 +# Getting started with InfiniTime -On April 22 2021, InfiniTime and Pine64 [announced the release of InfiniTime 1.0.0](https://www.pine64.org/2021/04/22/its-time-infinitime-1-0/) and the availability of PineTime smartwatches as *enthusiast grade end-user product*. This page aims to guide you with your first step with your new PineTime. +On April 22 2021, InfiniTime and Pine64 [announced the release of InfiniTime 1.0.0](https://www.pine64.org/2021/04/22/its-time-infinitime-1-0/) and the availability of PineTime smartwatches as an *enthusiast grade end-user product*. This page aims to guide you with your first step with your new PineTime. It is highly recommended to update the firmware to the latest version when you receive your watch and when a new InfiniTime version is released. More information on updating the firmware [here](/doc/gettingStarted/updating-software.md). -## InfiniTime 1.0.0 quick user guide +## InfiniTime quick user guide ### Setting the time diff --git a/doc/gettingStarted/updating-software.md b/doc/gettingStarted/updating-software.md index 316d77f..7a05073 100644 --- a/doc/gettingStarted/updating-software.md +++ b/doc/gettingStarted/updating-software.md @@ -1,34 +1,20 @@ -## Firmware, InfiniTime, Bootloader, Recovery firmware, OTA, DFU... What is it? +# Updating InfiniTime -You may have already encountered these words by reading the announcement, release notes, or [the wiki guide](https://wiki.pine64.org/wiki/Upgrade_PineTime_to_InfiniTime_1.0.0) and you may find them confusing if you're not familiar with the project. +If you just want to flash or upgrade InfiniTime on your PineTime, this page is for you! If you want more information about the software and the update procedure, check out [this](/doc/gettingStarted/about-software.md) page. -A **firmware** is software running on the embedded hardware of a device. - -InfiniTime has three distinct firmwares: - - - **[InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime)** is the operating system. - - **[The bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader)** is responsible for safely applying firmware updates and runs before booting into InfiniTime. - - **The recovery firmware** is a special *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. - -**OTA** (**O**ver **T**he **A**ir) refers to updating of the firmware over BLE (**B**luetooth **L**ow **E**nergy). This is a functionality that allows the user to update the firmware on their device wirelessly. - -**DFU** (**D**evice **F**irmware **U**pdate) is 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? +## Checking the version of InfiniTime You can check the InfiniTime version by first swiping right on the watchface to open quick settings, tapping the cogwheel to open settings, swipe up until you find an entry named "About" and tap on it. ![InfiniTime 1.0 version](version-1.0.jpg) -PineTimes shipped after June 2021 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 run right before booting to InfiniTime. +PineTimes shipped after June 2021 will ship with the latest version of [the bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader/releases/tag/1.0.0) and [recovery firmware](https://github.com/InfiniTimeOrg/InfiniTime/releases/tag/0.14.1) -The bootloader is easily recognizable with its white pine cone that is progressively drawn in green. It also displays its own version on the bottom (1.0.0 as of now). +The bootloader is run right before booting into InfiniTime. It is easily recognizable with its white pine cone that is progressively drawn in green. It also displays its own version on the bottom (1.0.0 as of now). ![Bootloader 1.0](bootloader-1.0.jpg) -## How to update your PineTime? +## Updating with companion apps To update your PineTime, you can use one of the [compatible companion applications](/README.md#companion-apps). @@ -43,7 +29,7 @@ We have prepared instructions for flashing InfiniTime with Gadgetbridge and NRFC - [Updating with Gadgetbridge](/doc/gettingStarted/ota-gadgetbridge.md) - [Updating with NRFConnect](/doc/gettingStarted/ota-nrfconnect.md) -### Firmware validation +## Firmware validation Firmware updates must be manually validated. If the firmware isn't validated and the watch resets, the watch will revert to the previous firmware. This is a safety feature to prevent bricking your device with faulty firmware. @@ -53,14 +39,3 @@ You can validate your updated firmware on InfiniTime >= 1.0 by following this si - Open settings by tapping the cogwheel on the bottom right - Swipe up until you find an entry named **Firmware** and tap on it - If the firmware is not validated yet, you can either validate the running firmware, or reset and revert to the previous firmware version - -## Bootloader - -Most of the time, the bootloader just runs without your intervention (update and load the firmware). - -However, you can enable 2 functionalities using the push button: - - - Push the button until the pine cone is drawn in **blue** to force the rollback of the previous version of the firmware, even if you've already validated the updated one - - Push the button until the pine cone is drawn in **red** to load the recovery firmware. This recovery firmware only provides BLE connectivity and OTA functionality. - -More info about the bootloader in [its project page](https://github.com/JF002/pinetime-mcuboot-bootloader/blob/master/README.md). -- cgit v0.10.2 From 4257073a02215e3f182d993765e4c5edef2d9845 Mon Sep 17 00:00:00 2001 From: Stephanie Date: Sun, 31 Oct 2021 12:24:13 -0400 Subject: Fixed container to use clang-format-12 and format on save diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 778fe9c..1bb315f 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -12,7 +12,9 @@ // Set *default* container specific settings.json values on container create. "settings": { - "terminal.integrated.shell.linux": "/bin/bash" + "terminal.integrated.shell.linux": "/bin/bash", + "editor.formatOnSave": true, + "clang-format.executable": "clang-format-12" }, // Add the IDs of extensions you want installed when the container is created. @@ -33,4 +35,4 @@ // Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root. // "remoteUser": "vscode" "remoteUser": "infinitime" -} \ No newline at end of file +} -- cgit v0.10.2 From 34511a66ee419086eafe4b5c0f932d7c5b1ab0a7 Mon Sep 17 00:00:00 2001 From: Steveis Date: Tue, 26 Oct 2021 17:16:42 +0100 Subject: About : Remove misleading info Removed Steps which is hard coded to display 0. Could be misleading and is using up memory. diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index 350c15c..c363e2d 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -182,9 +182,7 @@ std::unique_ptr SystemInfo::CreateScreen3() { " #444444 used# %d (%d%%)\n" " #444444 max used# %lu\n" " #444444 frag# %d%%\n" - " #444444 free# %d" - "\n" - "#444444 Steps# %i", + " #444444 free# %d", bleAddr[5], bleAddr[4], bleAddr[3], @@ -195,8 +193,7 @@ std::unique_ptr SystemInfo::CreateScreen3() { mon.used_pct, mon.max_used, mon.frag_pct, - static_cast(mon.free_biggest_size), - 0); + static_cast(mon.free_biggest_size)); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); return std::make_unique(2, 5, app, label); } -- cgit v0.10.2 From 871a673a4656c438fc12d4c0ad61d2eacc3ca340 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Milants?= Date: Thu, 2 Dec 2021 21:02:21 +0100 Subject: Tentative : fix issue template that redirect to a blank page. diff --git a/.github/ISSUE_TEMPLATE/bug-report.yaml b/.github/ISSUE_TEMPLATE/bug-report.yaml index f0fb076..6e9f660 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.yaml +++ b/.github/ISSUE_TEMPLATE/bug-report.yaml @@ -9,6 +9,7 @@ body: *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: + label: Verification options: - label: I searched for similar bug reports and found none was relevant. required: true diff --git a/.github/ISSUE_TEMPLATE/feature-request.yaml b/.github/ISSUE_TEMPLATE/feature-request.yaml index 26e4fa0..a35bbfe 100644 --- a/.github/ISSUE_TEMPLATE/feature-request.yaml +++ b/.github/ISSUE_TEMPLATE/feature-request.yaml @@ -9,6 +9,7 @@ body: *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: + label: Verification options: - label: I searched for similar feature request and found none was relevant. required: true -- cgit v0.10.2 From ec437b1c661b76e5c82681777c8900bd1ffa42a9 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Wed, 1 Dec 2021 23:30:25 +0100 Subject: QuickSettings: remove unused imports diff --git a/src/displayapp/screens/settings/QuickSettings.h b/src/displayapp/screens/settings/QuickSettings.h index c036fa5..7913898 100644 --- a/src/displayapp/screens/settings/QuickSettings.h +++ b/src/displayapp/screens/settings/QuickSettings.h @@ -1,8 +1,6 @@ #pragma once #include -#include -#include #include "displayapp/screens/Screen.h" #include #include "components/datetime/DateTimeController.h" -- cgit v0.10.2 From 4b7f2546bd26d9ad53eea6f7bb4e27f41d5842f3 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Mon, 29 Nov 2021 23:36:56 +0100 Subject: PineTimeStyle: remove include and add forward declare Remove unused `ScreenList.h` include and add a forward declaration for the `MotionController` class. diff --git a/src/displayapp/screens/PineTimeStyle.h b/src/displayapp/screens/PineTimeStyle.h index f8c7c8b..f86f4c5 100644 --- a/src/displayapp/screens/PineTimeStyle.h +++ b/src/displayapp/screens/PineTimeStyle.h @@ -5,7 +5,6 @@ #include #include #include "displayapp/screens/Screen.h" -#include "displayapp/screens/ScreenList.h" #include "components/datetime/DateTimeController.h" namespace Pinetime { @@ -15,6 +14,7 @@ namespace Pinetime { class Ble; class NotificationManager; class HeartRateController; + class MotionController; } namespace Applications { -- cgit v0.10.2 From e8db73e0e71c3a0b48beb185949e64fcdc79c066 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Mon, 29 Nov 2021 22:39:33 +0100 Subject: WatchFaceAnalog: remove unused ScreenList, add needed includes Remove unused `ScreenList.h` include. For `std::abs()` add needed include ``. For the forward declared Settings-Controller add the `Settings.h` include to the cpp file. diff --git a/src/displayapp/screens/WatchFaceAnalog.cpp b/src/displayapp/screens/WatchFaceAnalog.cpp index 4540c1a..bc720ec 100644 --- a/src/displayapp/screens/WatchFaceAnalog.cpp +++ b/src/displayapp/screens/WatchFaceAnalog.cpp @@ -1,9 +1,11 @@ #include "displayapp/screens/WatchFaceAnalog.h" +#include #include #include "displayapp/screens/BatteryIcon.h" #include "displayapp/screens/BleIcon.h" #include "displayapp/screens/Symbols.h" #include "displayapp/screens/NotificationIcon.h" +#include "components/settings/Settings.h" LV_IMG_DECLARE(bg_clock); diff --git a/src/displayapp/screens/WatchFaceAnalog.h b/src/displayapp/screens/WatchFaceAnalog.h index ca0462a..a18eb29 100644 --- a/src/displayapp/screens/WatchFaceAnalog.h +++ b/src/displayapp/screens/WatchFaceAnalog.h @@ -5,7 +5,6 @@ #include #include #include "displayapp/screens/Screen.h" -#include "displayapp/screens/ScreenList.h" #include "components/datetime/DateTimeController.h" #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" -- cgit v0.10.2 From 0705b746569cc49f01cceb4832a0cd0bc0afe36c Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Sun, 21 Nov 2021 22:48:28 +0100 Subject: WatchFaceDigital: add missing include to Settings.h diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index 2894812..8769579 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -12,6 +12,7 @@ #include "components/ble/NotificationManager.h" #include "components/heartrate/HeartRateController.h" #include "components/motion/MotionController.h" +#include "components/settings/Settings.h" using namespace Pinetime::Applications::Screens; WatchFaceDigital::WatchFaceDigital(DisplayApp* app, -- cgit v0.10.2 From fe6e4bea8cff2d811c24cfc16aa5580bb9a13efb Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Sun, 21 Nov 2021 22:50:23 +0100 Subject: WatchFaceDigital: remove unused include for ScreenList.h diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h index 7134efb..627154c 100644 --- a/src/displayapp/screens/WatchFaceDigital.h +++ b/src/displayapp/screens/WatchFaceDigital.h @@ -5,7 +5,6 @@ #include #include #include "displayapp/screens/Screen.h" -#include "displayapp/screens/ScreenList.h" #include "components/datetime/DateTimeController.h" namespace Pinetime { -- cgit v0.10.2 From 88b017d9b193fac301e8fd831e09736774e5061d Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Fri, 19 Nov 2021 21:15:35 +0100 Subject: Settings: remove unused driver include diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h index 871ff3b..2d7973d 100644 --- a/src/components/settings/Settings.h +++ b/src/components/settings/Settings.h @@ -4,7 +4,6 @@ #include "components/datetime/DateTimeController.h" #include "components/brightness/BrightnessController.h" #include "components/fs/FS.h" -#include "drivers/Cst816s.h" namespace Pinetime { namespace Controllers { -- cgit v0.10.2 From a17d8bd566ae7686b9373dc3f2ab218d3a191630 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Sun, 28 Nov 2021 21:47:19 +0100 Subject: Metronome: add missing include for Screen.h diff --git a/src/displayapp/screens/Metronome.h b/src/displayapp/screens/Metronome.h index f3a84dc..373c884 100644 --- a/src/displayapp/screens/Metronome.h +++ b/src/displayapp/screens/Metronome.h @@ -2,6 +2,7 @@ #include "systemtask/SystemTask.h" #include "components/motor/MotorController.h" +#include "displayapp/screens/Screen.h" namespace Pinetime { namespace Applications { -- cgit v0.10.2 From 054a99cf6c6a8eff181724ceebd5cd3539c62743 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Sat, 30 Oct 2021 22:25:42 +0200 Subject: Paddle: add a little randomization in the dy speed To make the game a bit more challenging an less predictable add a little bit of randomness to the `dy` value. When hitting the right wall add a random number (one of [-1, 0, 1]) to the `dy` value. To keep the difficulty level managable limit the dy value to be in the range from -5 to 5. diff --git a/src/displayapp/screens/Paddle.cpp b/src/displayapp/screens/Paddle.cpp index aa3420d..608eb64 100644 --- a/src/displayapp/screens/Paddle.cpp +++ b/src/displayapp/screens/Paddle.cpp @@ -2,6 +2,8 @@ #include "displayapp/DisplayApp.h" #include "displayapp/LittleVgl.h" +#include // for rand() + using namespace Pinetime::Applications::Screens; Paddle::Paddle(Pinetime::Applications::DisplayApp* app, Pinetime::Components::LittleVgl& lvgl) : Screen(app), lvgl {lvgl} { @@ -50,6 +52,13 @@ void Paddle::Refresh() { // checks if it has touched the side (right side) if (ballX >= LV_HOR_RES - ballSize - 1) { dx *= -1; + dy += rand() % 3 - 1; // add a little randomization in wall bounce direction, one of [-1, 0, 1] + if (dy > 5) { // limit dy to be in range [-5 to 5] + dy = 5; + } + if (dy < -5) { + dy = -5; + } } // checks if it is in the position of the paddle -- cgit v0.10.2 From b8dfad40bbdebea1bfde1fc267b245cfaf68be8a Mon Sep 17 00:00:00 2001 From: Steveis Date: Sat, 23 Oct 2021 08:21:55 +0100 Subject: WatchFaceAnalog : move notification icon Standardise notification icon to display in top left. diff --git a/src/displayapp/screens/WatchFaceAnalog.cpp b/src/displayapp/screens/WatchFaceAnalog.cpp index bc720ec..f027a74 100644 --- a/src/displayapp/screens/WatchFaceAnalog.cpp +++ b/src/displayapp/screens/WatchFaceAnalog.cpp @@ -75,7 +75,7 @@ WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app, notificationIcon = lv_label_create(lv_scr_act(), NULL); lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00)); lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false)); - lv_obj_align(notificationIcon, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); + lv_obj_align(notificationIcon, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0); // Date - Day / Week day -- cgit v0.10.2 From 85a25302bfac215f9ec7b993f6a2c21a20ee223b Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Tue, 30 Nov 2021 22:29:00 +0100 Subject: Clock: add missing Settings include Add missing include in `Clock.cpp` for `Settings.h`. The Settings class is forward declared in the header file, but it needs to be included in the cpp file. diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp index 71f01b9..96d8e5b 100644 --- a/src/displayapp/screens/Clock.cpp +++ b/src/displayapp/screens/Clock.cpp @@ -6,6 +6,7 @@ #include "components/motion/MotionController.h" #include "components/ble/BleController.h" #include "components/ble/NotificationManager.h" +#include "components/settings/Settings.h" #include "displayapp/DisplayApp.h" #include "displayapp/screens/WatchFaceDigital.h" #include "displayapp/screens/WatchFaceAnalog.h" -- cgit v0.10.2 From 6ba28786055e0538cf0b7631cd33b36f02d46deb Mon Sep 17 00:00:00 2001 From: Avamander Date: Mon, 17 May 2021 13:57:21 +0300 Subject: Added QCBOR dependency diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e727b2b..4ab303d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -357,6 +357,14 @@ set(LVGL_SRC libs/lvgl/src/lv_widgets/lv_win.c ) +set(QCBOR_SRC + libs/QCBOR/src/ieee754.c + libs/QCBOR/src/qcbor_decode.c + libs/QCBOR/src/qcbor_encode.c + libs/QCBOR/src/qcbor_err_to_str.c + libs/QCBOR/src/UsefulBuf.c + ) + list(APPEND IMAGE_FILES displayapp/icons/battery/os_battery_error.c displayapp/icons/battery/os_battery_100.c @@ -835,6 +843,24 @@ target_compile_options(lvgl PRIVATE $<$: -MP -MD -x assembler-with-cpp> ) +# QCBOR +add_library(QCBOR STATIC ${QCBOR_SRC}) +target_include_directories(QCBOR SYSTEM PUBLIC libs/QCBOR/inc) +# This is required with the current configuration +target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_FLOAT_HW_USE) +# These are for space-saving +target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_PREFERRED_FLOAT) +target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_EXP_AND_MANTISSA) +target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS) +target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS) +target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_UNCOMMON_TAGS) +set_target_properties(QCBOR PROPERTIES LINKER_LANGUAGE C) +target_compile_options(QCBOR PRIVATE + $<$,$>: ${COMMON_FLAGS} -O0 -g3> + $<$,$>: ${COMMON_FLAGS} -O3> + $<$: -MP -MD -x assembler-with-cpp> + ) + # LITTLEFS_SRC add_library(littlefs STATIC ${LITTLEFS_SRC}) target_include_directories(littlefs SYSTEM PUBLIC . ../) @@ -853,7 +879,7 @@ set(EXECUTABLE_FILE_NAME ${EXECUTABLE_NAME}-${pinetime_VERSION_MAJOR}.${pinetime set(NRF5_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/gcc_nrf52.ld") add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES}) set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_FILE_NAME}) -target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl littlefs) +target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl littlefs QCBOR) target_compile_options(${EXECUTABLE_NAME} PUBLIC $<$,$>: ${COMMON_FLAGS} -Og -g3> $<$,$>: ${COMMON_FLAGS} -Os> @@ -882,7 +908,7 @@ set(IMAGE_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-image-${pinetime_VERSION_ set(DFU_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip) set(NRF5_LINKER_SCRIPT_MCUBOOT "${CMAKE_SOURCE_DIR}/gcc_nrf52-mcuboot.ld") add_executable(${EXECUTABLE_MCUBOOT_NAME} ${SOURCE_FILES}) -target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl littlefs) +target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl littlefs QCBOR) set_target_properties(${EXECUTABLE_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_MCUBOOT_FILE_NAME}) target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC $<$,$>: ${COMMON_FLAGS} -Og -g3> diff --git a/src/libs/QCBOR b/src/libs/QCBOR new file mode 160000 index 0000000..9e2f708 --- /dev/null +++ b/src/libs/QCBOR @@ -0,0 +1 @@ +Subproject commit 9e2f70804393823cc6d16f9f1035ef7223faca04 -- cgit v0.10.2 From bda96dc595aecb56739cc02de7e7d2d825927b7f Mon Sep 17 00:00:00 2001 From: Avamander Date: Thu, 10 Jun 2021 00:44:49 +0300 Subject: Initial Weather service skeleton diff --git a/.gitmodules b/.gitmodules index 815fc02..8d302ae 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "src/libs/littlefs"] path = src/libs/littlefs url = https://github.com/littlefs-project/littlefs.git +[submodule "src/libs/QCBOR"] + path = src/libs/QCBOR + url = https://github.com/laurencelundblade/QCBOR.git diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 43a8b0d..9ef2d05 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -36,6 +36,7 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, alertNotificationClient {systemTask, notificationManager}, currentTimeService {dateTimeController}, musicService {systemTask}, + weatherService {systemTask, dateTimeController}, navService {systemTask}, batteryInformationService {batteryController}, immediateAlertService {systemTask, notificationManager}, @@ -77,6 +78,7 @@ void NimbleController::Init() { currentTimeClient.Init(); currentTimeService.Init(); musicService.Init(); + weatherService.Init(); navService.Init(); anService.Init(); dfuService.Init(); diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 895b87f..a21cbe8 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -20,6 +20,7 @@ #include "components/ble/ServiceDiscovery.h" #include "components/ble/HeartRateService.h" #include "components/ble/MotionService.h" +#include "components/ble/weather/WeatherService.h" namespace Pinetime { namespace Drivers { @@ -93,6 +94,7 @@ namespace Pinetime { AlertNotificationClient alertNotificationClient; CurrentTimeService currentTimeService; MusicService musicService; + WeatherService weatherService; NavigationService navService; BatteryInformationService batteryInformationService; ImmediateAlertService immediateAlertService; diff --git a/src/components/ble/weather/WeatherData.h b/src/components/ble/weather/WeatherData.h new file mode 100644 index 0000000..c1d53f4 --- /dev/null +++ b/src/components/ble/weather/WeatherData.h @@ -0,0 +1,338 @@ +/* Copyright (C) 2021 Avamander + + This file is part of InfiniTime. + + InfiniTime is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + InfiniTime is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#pragma once + +/** + * Different weather events, weather data structures used by {@link WeatherService.h} + * + * + * Implemented based on and other material: + * https://en.wikipedia.org/wiki/METAR + * https://www.weather.gov/jetstream/obscurationtypes + * http://www.faraim.org/aim/aim-4-03-14-493.html + */ + +namespace Pinetime { + namespace Controllers { + class WeatherData { + public: + /** + * Visibility obscuration types + */ + enum class obscurationtype { + /** No obscuration */ + None = 0, + /** Water particles suspended in the air; low visibility; does not fall */ + Fog = 1, + /** Extremely small, dry particles in the air; invisible to the eye; opalescent */ + Haze = 2, + /** Small fire-created particles suspended in the air */ + Smoke = 3, + /** Fine rock powder, from for example volcanoes */ + Ash = 4, + /** Fine particles of earth suspended in the air by the wind */ + Dust = 5, + /** Fine particles of sand suspended in the air by the wind */ + Sand = 6, + /** Water particles suspended in the air; low-ish visibility; temperature is near dewpoint */ + Mist = 7, + }; + + /** + * Types of precipitation + */ + enum class precipitationtype { + /** + * No precipitation + * + * Theoretically we could just _not_ send the event, but then + * how do we differentiate between no precipitation and + * no information about precipitation + */ + None = 0, + /** Drops larger than a drizzle; also widely separated drizzle */ + Rain = 1, + /** Fairly uniform rain consisting of fine drops */ + Drizzle = 2, + /** Rain that freezes upon contact with objects and ground */ + FreezingRain = 3, + /** Rain + hail; ice pellets; small translucent frozen raindrops */ + Sleet = 4, + /** Larger ice pellets; falling separately or in irregular clumps */ + Hail = 5, + /** Hail with smaller grains of ice; mini-snowballs */ + SmallHail = 6, + /** Snow... */ + Snow = 7, + /** Frozen drizzle; very small snow crystals */ + SnowGrains = 8, + /** Needles; columns or plates of ice. Sometimes described as "diamond dust". In very cold regions */ + IceCrystals = 9 + }; + + /** + * These are special events that can "enhance" the "experience" of existing weather events + */ + enum class specialtype { + /** Strong wind with a sudden onset that lasts at least a minute */ + Squall = 0, + /** Series of waves in a water body caused by the displacement of a large volume of water */ + Tsunami = 1, + /** Violent; rotating column of air */ + Tornado = 2, + /** Unplanned; unwanted; uncontrolled fire in an area */ + Fire = 3, + /** Thunder and/or lightning */ + Thunder = 4, + }; + + /** + * These are used for weather timeline manipulation + * that isn't just adding to the stack of weather events + */ + enum class controlcodes { + /** How much is stored already */ + GetLength = 0, + /** This wipes the entire timeline */ + DelTimeline = 1, + /** There's a currently valid timeline event with the given type */ + HasValidEvent = 3 + }; + + /** + * Events have types + * then they're easier to parse after sending them over the air + */ + enum class eventtype { + /** @see obscuration */ + Obscuration = 0, + /** @see precipitation */ + Precipitation = 1, + /** @see wind */ + Wind = 2, + /** @see temperature */ + Temperature = 3, + /** @see airquality */ + AirQuality = 4, + /** @see special */ + Special = 5, + /** @see pressure */ + Pressure = 6, + /** @see location */ + Location = 7, + /** @see cloud */ + Clouds = 8, + }; + + /** + * Valid event query + */ + class valideventquery { + public: + static constexpr controlcodes code = controlcodes::HasValidEvent; + eventtype eventType; + }; + + /** The header used for further parsing */ + class timelineheader { + public: + /** UNIX timestamp */ + uint64_t timestamp; + /** + * Time in seconds until the event expires + * + * 32 bits ought to be enough for everyone + * + * If there's a newer event of the same type then it overrides this one, even if it hasn't expired + */ + uint32_t expires; + /** + * What type of weather-related event + */ + eventtype eventType; + }; + + /** Specifies how cloudiness is stored */ + class clouds : public timelineheader { + public: + /** Cloud coverage in percentage, 0-100% */ + uint8_t amount; + }; + + /** Specifies how obscuration is stored */ + class obscuration : public timelineheader { + public: + /** Type */ + obscurationtype type; + /** Visibility distance in meters */ + uint8_t amount; + }; + + /** Specifies how precipitation is stored */ + class precipitation : public timelineheader { + public: + /** Type */ + precipitationtype type; + /** How much is it going to rain? In millimeters */ + uint8_t amount; + }; + + /** + * How wind speed is stored + * + * In order to represent bursts of wind instead of constant wind, + * you have minimum and maximum speeds. + * + * As direction can fluctuate wildly and some watchfaces might wish to display it nicely, + * we're following the aerospace industry weather report option of specifying a range. + */ + class wind : public timelineheader { + public: + /** Meters per second */ + uint8_t speedMin; + /** Meters per second */ + uint8_t speedMax; + /** Unitless direction between 0-255; approximately 1 unit per 0.71 degrees */ + uint8_t directionMin; + /** Unitless direction between 0-255; approximately 1 unit per 0.71 degrees */ + uint8_t directionMax; + }; + + /** + * How temperature is stored + * + * As it's annoying to figure out the dewpoint on the watch, + * please send it from the companion + * + * We don't do floats, microdegrees are not useful. Make sure to multiply. + */ + class temperature : public timelineheader { + public: + /** Temperature °C but multiplied by 100 (e.g. -12.50°C becomes -1250) */ + int16_t temperature; + /** Dewpoint °C but multiplied by 100 (e.g. -12.50°C becomes -1250) */ + int16_t dewPoint; + }; + + /** + * How location info is stored + * + * This can be mostly static with long expiration, + * as it usually is, but it could change during a trip for ex. + * so we allow changing it dynamically. + * + * Location info can be for some kind of map watchface + * or daylight calculations, should those be required. + * + */ + class location : public timelineheader { + public: + /** Location name */ + std::string location; + /** Altitude relative to sea level in meters */ + int16_t altitude; + /** Latitude, EPSG:3857 (Google Maps, Openstreetmaps datum) */ + int32_t latitude; + /** Longitude, EPSG:3857 (Google Maps, Openstreetmaps datum) */ + int32_t longitude; + }; + + /** + * How humidity is stored + */ + class humidity : public timelineheader { + public: + /** Relative humidity, 0-100% */ + uint8_t humidity; + }; + + /** + * How air pressure is stored + */ + class pressure : public timelineheader { + public: + /** Air pressure in hectopascals (hPa) */ + int16_t pressure; + }; + + /** + * How special events are stored + */ + class special : public timelineheader { + public: + /** Special event's type */ + specialtype type; + }; + + /** + * How air quality is stored + * + * These events are a bit more complex because the topic is not simple, + * the intention is to heavy-lift the annoying preprocessing from the watch + * this allows watchface or watchapp makers to generate accurate alerts and graphics + * + * If this needs further enforced standardization, pull requests are welcome + */ + class airquality : public timelineheader { + public: + /** + * The name of the pollution + * + * for the sake of better compatibility with watchapps + * that might want to use this data for say visuals + * don't localize the name. + * + * Ideally watchapp itself localizes the name, if it's at all needed. + * + * E.g. + * For generic ones use "PM0.1", "PM5", "PM10" + * For chemical compounds use the molecular formula e.g. "NO2", "CO2", "O3" + * For pollen use the genus, e.g. "Betula" for birch or "Alternaria" for that mold's spores + */ + std::string polluter; + /** + * Amount of the pollution in SI units, + * otherwise it's going to be difficult to create UI, alerts + * and so on and for. + * + * See more: + * https://ec.europa.eu/environment/air/quality/standards.htm + * http://www.ourair.org/wp-content/uploads/2012-aaqs2.pdf + * + * Example units: + * count/m³ for pollen + * µgC/m³ for micrograms of organic carbon + * µg/m³ sulfates, PM0.1, PM1, PM2, PM10 and so on, dust + * mg/m³ CO2, CO + * ng/m³ for heavy metals + * + * List is not comprehensive, should be improved. + * The current ones are what watchapps assume. + * + * Note: ppb and ppm to concentration should be calculated on the companion, using + * the correct formula (taking into account temperature and air pressure) + * + * Note2: The amount is off by times 100, for two decimal places of precision. + * E.g. 54.32µg/m³ is 5432 + * + */ + uint32_t amount; + }; + }; + } +} \ No newline at end of file diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp new file mode 100644 index 0000000..006fc6c --- /dev/null +++ b/src/components/ble/weather/WeatherService.cpp @@ -0,0 +1,208 @@ +/* Copyright (C) 2021 Avamander + + This file is part of InfiniTime. + + InfiniTime is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + InfiniTime is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#include +#include "WeatherService.h" +#include "libs/QCBOR/inc/qcbor/qcbor.h" +#include "systemtask/SystemTask.h" + +int WeatherCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) { + return static_cast(arg)->OnCommand(conn_handle, attr_handle, ctxt); +} + +namespace Pinetime { + namespace Controllers { + WeatherService::WeatherService(System::SystemTask& system, DateTime& dateTimeController) + : system(system), dateTimeController(dateTimeController) { + } + + void WeatherService::Init() { + uint8_t res = 0; + res = ble_gatts_count_cfg(serviceDefinition); + ASSERT(res == 0) + + res = ble_gatts_add_svcs(serviceDefinition); + ASSERT(res == 0); + } + + int WeatherService::OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) { + if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { + getCurrentPressure(); + tidyTimeline(); + getTimelineLength(); + const auto packetLen = OS_MBUF_PKTLEN(ctxt->om); + if (packetLen <= 0) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + // Decode + QCBORDecodeContext decodeContext; + UsefulBufC EncodedCBOR; + // TODO: Check uninit fine + QCBORDecode_Init(&decodeContext, EncodedCBOR, QCBOR_DECODE_MODE_NORMAL); + QCBORDecode_EnterMap(&decodeContext, nullptr); + WeatherData::timelineheader timelineHeader {}; + // Always encodes to the smallest number of bytes based on the value + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", reinterpret_cast(&(timelineHeader.timestamp))); + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", reinterpret_cast(&(timelineHeader.expires))); + QCBORDecode_GetInt64InMapSZ(&decodeContext, "EventType", reinterpret_cast(&(timelineHeader.eventType))); + switch (timelineHeader.eventType) { + // TODO: Populate + case WeatherData::eventtype::AirQuality: { + break; + } + case WeatherData::eventtype::Obscuration: { + break; + } + case WeatherData::eventtype::Precipitation: { + break; + } + case WeatherData::eventtype::Wind: { + break; + } + case WeatherData::eventtype::Temperature: { + break; + } + case WeatherData::eventtype::Special: { + break; + } + case WeatherData::eventtype::Pressure: { + break; + } + case WeatherData::eventtype::Location: { + break; + } + case WeatherData::eventtype::Clouds: { + break; + } + default: { + break; + } + } + QCBORDecode_ExitMap(&decodeContext); + + auto uErr = QCBORDecode_Finish(&decodeContext); + if (uErr != 0) { + return BLE_ATT_ERR_INSUFFICIENT_RES; + } + } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) { + // TODO: Detect control messages + + // Encode + uint8_t buffer[64]; + QCBOREncodeContext encodeContext; + QCBOREncode_Init(&encodeContext, UsefulBuf_FROM_BYTE_ARRAY(buffer)); + QCBOREncode_OpenMap(&encodeContext); + QCBOREncode_AddTextToMap(&encodeContext, "test", UsefulBuf_FROM_SZ_LITERAL("test")); + QCBOREncode_AddInt64ToMap(&encodeContext, "test", 1ul); + QCBOREncode_CloseMap(&encodeContext); + + UsefulBufC encodedEvent; + auto uErr = QCBOREncode_Finish(&encodeContext, &encodedEvent); + if (uErr != 0) { + return BLE_ATT_ERR_INSUFFICIENT_RES; + } + auto res = os_mbuf_append(ctxt->om, &buffer, sizeof(buffer)); + if (res == 0) { + return BLE_ATT_ERR_INSUFFICIENT_RES; + } + + return 0; + } + return 0; + } + + WeatherData::location WeatherService::getCurrentLocation() const { + return WeatherData::location(); + } + WeatherData::clouds WeatherService::getCurrentClouds() const { + return WeatherData::clouds(); + } + WeatherData::obscuration WeatherService::getCurrentObscuration() const { + return WeatherData::obscuration(); + } + WeatherData::precipitation WeatherService::getCurrentPrecipitation() const { + return WeatherData::precipitation(); + } + WeatherData::wind WeatherService::getCurrentWind() const { + return WeatherData::wind(); + } + WeatherData::temperature WeatherService::getCurrentTemperature() const { + return WeatherData::temperature(); + } + WeatherData::humidity WeatherService::getCurrentHumidity() const { + return WeatherData::humidity(); + } + WeatherData::pressure WeatherService::getCurrentPressure() const { + uint64_t currentTimestamp = getCurrentUNIXTimestamp(); + for (auto&& header : timeline) { + if (header->eventType == WeatherData::eventtype::Pressure && header->timestamp + header->expires <= currentTimestamp) { + return WeatherData::pressure(); + } + } + return WeatherData::pressure(); + } + + WeatherData::airquality WeatherService::getCurrentQuality() const { + return WeatherData::airquality(); + } + + size_t WeatherService::getTimelineLength() const { + return timeline.size(); + } + + bool WeatherService::addEventToTimeline(std::unique_ptr event) { + if (timeline.size() == timeline.max_size()) { + return false; + } + + timeline.push_back(std::move(event)); + return true; + } + + bool WeatherService::hasTimelineEventOfType(const WeatherData::eventtype type) const { + uint64_t currentTimestamp = getCurrentUNIXTimestamp(); + for (auto&& header : timeline) { + if (header->eventType == type && header->timestamp + header->expires <= currentTimestamp) { + // TODO: Check if its currently valid + return true; + } + } + return false; + } + + void WeatherService::tidyTimeline() { + uint64_t timeCurrent = 0; + timeline.erase(std::remove_if(std::begin(timeline), + std::end(timeline), + [&](std::unique_ptr const& header) { + return header->timestamp + header->expires > timeCurrent; + }), + std::end(timeline)); + + std::sort(std::begin(timeline), std::end(timeline), compareTimelineEvents); + } + + bool WeatherService::compareTimelineEvents(const std::unique_ptr& first, + const std::unique_ptr& second) { + return first->timestamp > second->timestamp; + } + + uint64_t WeatherService::getCurrentUNIXTimestamp() const { + return std::chrono::duration_cast(dateTimeController.CurrentDateTime().time_since_epoch()).count(); + } + } +} diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h new file mode 100644 index 0000000..ef99db8 --- /dev/null +++ b/src/components/ble/weather/WeatherService.h @@ -0,0 +1,139 @@ +/* Copyright (C) 2021 Avamander + + This file is part of InfiniTime. + + InfiniTime is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + InfiniTime is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#pragma once + +#include +#include +#include +#include + +#define min // workaround: nimble's min/max macros conflict with libstdc++ +#define max +#include +#include +#undef max +#undef min + +#include "WeatherData.h" +#include + +// 00030000-78fc-48fe-8e23-433b3a1942d0 +#define WEATHER_SERVICE_UUID_BASE \ + { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x03, 0x00 } +#define WEATHER_SERVICE_CHAR_UUID(y, x) \ + { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, (x), (y), 0x03, 0x00 } + +int WeatherCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg); + +namespace Pinetime { + namespace System { + class SystemTask; + } + namespace Controllers { + + class WeatherService { + public: + explicit WeatherService(System::SystemTask& system, DateTime& dateTimeController); + + void Init(); + + int OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt); + + /* + * Helper functions for quick access to currently valid data + */ + WeatherData::location getCurrentLocation() const; + WeatherData::clouds getCurrentClouds() const; + WeatherData::obscuration getCurrentObscuration() const; + WeatherData::precipitation getCurrentPrecipitation() const; + WeatherData::wind getCurrentWind() const; + WeatherData::temperature getCurrentTemperature() const; + WeatherData::humidity getCurrentHumidity() const; + WeatherData::pressure getCurrentPressure() const; + WeatherData::airquality getCurrentQuality() const; + + /* + * Management functions + */ + /** + * Adds an event to the timeline + * @return + */ + bool addEventToTimeline(std::unique_ptr event); + /** + * Gets the current timeline length + */ + size_t getTimelineLength() const; + /** + * Checks if an event of a certain type exists in the timeline + * @return + */ + bool hasTimelineEventOfType(WeatherData::eventtype type) const; + + private: + ble_uuid128_t msUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_UUID_BASE}; + + /** + * Just write timeline data here + */ + ble_uuid128_t wDataCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_CHAR_UUID(0x00, 0x01)}; + /** + * This doesn't take timeline data + * but provides some control over it + */ + ble_uuid128_t wControlCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_CHAR_UUID(0x00, 0x02)}; + + const struct ble_gatt_chr_def characteristicDefinition[2] = {{.uuid = reinterpret_cast(&wDataCharUuid), + .access_cb = WeatherCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_NOTIFY, + .val_handle = &eventHandle}, + {.uuid = reinterpret_cast(&wControlCharUuid), + .access_cb = WeatherCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}}; + const struct ble_gatt_svc_def serviceDefinition[2] = { + {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = reinterpret_cast(&msUuid), .characteristics = characteristicDefinition}, + {0}}; + + uint16_t eventHandle {}; + + Pinetime::System::SystemTask& system; + Pinetime::Controllers::DateTime& dateTimeController; + + std::vector> timeline; + + /** + * Cleans up the timeline of expired events + * @return result code + */ + void tidyTimeline(); + + /** + * Compares two timeline events + */ + static bool compareTimelineEvents(const std::unique_ptr& first, + const std::unique_ptr& second); + + /** + * + */ + uint64_t getCurrentUNIXTimestamp() const; + }; + } +} diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp new file mode 100644 index 0000000..014761b --- /dev/null +++ b/src/displayapp/screens/Weather.cpp @@ -0,0 +1,246 @@ +#include "Weather.h" +#include +#include "../DisplayApp.h" +#include "Label.h" +#include "Version.h" +#include "components/battery/BatteryController.h" +#include "components/ble/BleController.h" +#include "components/brightness/BrightnessController.h" +#include "components/datetime/DateTimeController.h" +#include "drivers/Watchdog.h" +#include "components/ble/weather/WeatherData.h" + +using namespace Pinetime::Applications::Screens; + +Weather::Weather(Pinetime::Applications::DisplayApp* app, + Pinetime::Controllers::DateTime& dateTimeController, + Pinetime::Controllers::Battery& batteryController, + Pinetime::Controllers::BrightnessController& brightnessController, + Pinetime::Controllers::Ble& bleController, + Pinetime::Drivers::WatchdogView& watchdog) + : Screen(app), + dateTimeController {dateTimeController}, + batteryController {batteryController}, + brightnessController {brightnessController}, + bleController {bleController}, + watchdog {watchdog}, + screens {app, + 0, + {[this]() -> std::unique_ptr { + return CreateScreen1(); + }, + [this]() -> std::unique_ptr { + return CreateScreen2(); + }, + [this]() -> std::unique_ptr { + return CreateScreen3(); + }, + [this]() -> std::unique_ptr { + return CreateScreen4(); + }, + [this]() -> std::unique_ptr { + return CreateScreen5(); + }}, + Screens::ScreenListModes::UpDown} { +} + +Weather::~Weather() { + lv_obj_clean(lv_scr_act()); +} + +bool Weather::Refresh() { + if (running) { + screens.Refresh(); + } + return running; +} + +bool Weather::OnButtonPushed() { + running = false; + return true; +} + +bool Weather::OnTouchEvent(Pinetime::Applications::TouchEvents event) { + return screens.OnTouchEvent(event); +} + +std::unique_ptr Weather::CreateScreen1() { + lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(label, true); + lv_label_set_text_fmt(label, + "#FFFF00 InfiniTime#\n\n" + "#444444 Version# %ld.%ld.%ld\n\n" + "#444444 Build date#\n" + "%s\n" + "%s\n", + Version::Major(), + Version::Minor(), + Version::Patch(), + __DATE__, + __TIME__); + lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); + lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + return std::unique_ptr(new Screens::Label(0, 5, app, label)); +} + +std::unique_ptr Weather::CreateScreen2() { + auto batteryPercent = static_cast(batteryController.PercentRemaining()); + float batteryVoltage = batteryController.Voltage(); + + auto resetReason = [this]() { + switch (watchdog.ResetReason()) { + case Drivers::Watchdog::ResetReasons::Watchdog: + return "wtdg"; + case Drivers::Watchdog::ResetReasons::HardReset: + return "hardr"; + case Drivers::Watchdog::ResetReasons::NFC: + return "nfc"; + case Drivers::Watchdog::ResetReasons::SoftReset: + return "softr"; + case Drivers::Watchdog::ResetReasons::CpuLockup: + return "cpulock"; + case Drivers::Watchdog::ResetReasons::SystemOff: + return "off"; + case Drivers::Watchdog::ResetReasons::LpComp: + return "lpcomp"; + case Drivers::Watchdog::ResetReasons::DebugInterface: + return "dbg"; + case Drivers::Watchdog::ResetReasons::ResetPin: + return "rst"; + default: + return "?"; + } + }(); + + // uptime + static constexpr uint32_t secondsInADay = 60 * 60 * 24; + static constexpr uint32_t secondsInAnHour = 60 * 60; + static constexpr uint32_t secondsInAMinute = 60; + uint32_t uptimeSeconds = dateTimeController.Uptime().count(); + uint32_t uptimeDays = (uptimeSeconds / secondsInADay); + uptimeSeconds = uptimeSeconds % secondsInADay; + uint32_t uptimeHours = uptimeSeconds / secondsInAnHour; + uptimeSeconds = uptimeSeconds % secondsInAnHour; + uint32_t uptimeMinutes = uptimeSeconds / secondsInAMinute; + uptimeSeconds = uptimeSeconds % secondsInAMinute; + // TODO handle more than 100 days of uptime + + if (batteryPercent == -1) + batteryPercent = 0; + + // hack to not use the flot functions from printf + uint8_t batteryVoltageBytes[2]; + batteryVoltageBytes[1] = static_cast(batteryVoltage); // truncate whole numbers + batteryVoltageBytes[0] = + static_cast((batteryVoltage - batteryVoltageBytes[1]) * 100); // remove whole part of flt and shift 2 places over + // + + lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(label, true); + lv_label_set_text_fmt(label, + "#444444 Date# %02d/%02d/%04d\n" + "#444444 Time# %02d:%02d:%02d\n" + "#444444 Uptime#\n %02lud %02lu:%02lu:%02lu\n" + "#444444 Battery# %d%%/%1i.%02iv\n" + "#444444 Backlight# %s\n" + "#444444 Last reset# %s\n", + dateTimeController.Day(), + static_cast(dateTimeController.Month()), + dateTimeController.Year(), + dateTimeController.Hours(), + dateTimeController.Minutes(), + dateTimeController.Seconds(), + uptimeDays, + uptimeHours, + uptimeMinutes, + uptimeSeconds, + batteryPercent, + batteryVoltageBytes[1], + batteryVoltageBytes[0], + brightnessController.ToString(), + resetReason); + lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + return std::unique_ptr(new Screens::Label(1, 4, app, label)); +} + +std::unique_ptr Weather::CreateScreen3() { + lv_mem_monitor_t mon; + lv_mem_monitor(&mon); + + lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(label, true); + auto& bleAddr = bleController.Address(); + lv_label_set_text_fmt(label, + "#444444 BLE MAC#\n" + " %02x:%02x:%02x:%02x:%02x:%02x" + "\n" + "#444444 Memory#\n" + " #444444 used# %d (%d%%)\n" + " #444444 frag# %d%%\n" + " #444444 free# %d" + "\n" + "#444444 Steps# %li", + bleAddr[5], + bleAddr[4], + bleAddr[3], + bleAddr[2], + bleAddr[1], + bleAddr[0], + (int) mon.total_size - mon.free_size, + mon.used_pct, + mon.frag_pct, + (int) mon.free_biggest_size, + 0); + lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + return std::unique_ptr(new Screens::Label(2, 5, app, label)); +} + +bool sortById(const TaskStatus_t& lhs, const TaskStatus_t& rhs) { + return lhs.xTaskNumber < rhs.xTaskNumber; +} + +std::unique_ptr Weather::CreateScreen4() { + TaskStatus_t tasksStatus[7]; + 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_cell_value(infoTask, 0, 0, "#"); + lv_table_set_col_width(infoTask, 0, 50); + lv_table_set_cell_value(infoTask, 0, 1, "Task"); + lv_table_set_col_width(infoTask, 1, 80); + lv_table_set_cell_value(infoTask, 0, 2, "Free"); + lv_table_set_col_width(infoTask, 2, 90); + + auto nb = uxTaskGetSystemState(tasksStatus, 7, 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()); + lv_table_set_cell_value(infoTask, i + 1, 1, tasksStatus[i].pcTaskName); + if (tasksStatus[i].usStackHighWaterMark < 20) { + std::string str1 = std::to_string(tasksStatus[i].usStackHighWaterMark) + " low"; + lv_table_set_cell_value(infoTask, i + 1, 2, str1.c_str()); + } else { + lv_table_set_cell_value(infoTask, i + 1, 2, std::to_string(tasksStatus[i].usStackHighWaterMark).c_str()); + } + } + return std::unique_ptr(new Screens::Label(3, 5, app, infoTask)); +} + +std::unique_ptr Weather::CreateScreen5() { + lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(label, true); + lv_label_set_text_static(label, + "Software Licensed\n" + "under the terms of\n" + "the GNU General\n" + "Public License v3\n" + "#444444 Source code#\n" + "#FFFF00 https://github.com/#\n" + "#FFFF00 JF002/InfiniTime#"); + lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); + lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + return std::unique_ptr(new Screens::Label(4, 5, app, label)); +} diff --git a/src/displayapp/screens/Weather.h b/src/displayapp/screens/Weather.h new file mode 100644 index 0000000..8b393ca --- /dev/null +++ b/src/displayapp/screens/Weather.h @@ -0,0 +1,54 @@ +#pragma once + +#include +#include "Screen.h" +#include "ScreenList.h" + +namespace Pinetime { + namespace Controllers { + class DateTime; + class Battery; + class BrightnessController; + class Ble; + } + + namespace Drivers { + class WatchdogView; + } + + namespace Applications { + class DisplayApp; + + namespace Screens { + class Weather : public Screen { + public: + explicit Weather(DisplayApp* app, + Pinetime::Controllers::DateTime& dateTimeController, + Pinetime::Controllers::Battery& batteryController, + Pinetime::Controllers::BrightnessController& brightnessController, + Pinetime::Controllers::Ble& bleController, + Pinetime::Drivers::WatchdogView& watchdog); + ~Weather() override; + bool Refresh() override; + bool OnButtonPushed() override; + bool OnTouchEvent(TouchEvents event) override; + + private: + bool running = true; + + Pinetime::Controllers::DateTime& dateTimeController; + Pinetime::Controllers::Battery& batteryController; + Pinetime::Controllers::BrightnessController& brightnessController; + Pinetime::Controllers::Ble& bleController; + Pinetime::Drivers::WatchdogView& watchdog; + + ScreenList<5> screens; + std::unique_ptr CreateScreen1(); + std::unique_ptr CreateScreen2(); + std::unique_ptr CreateScreen3(); + std::unique_ptr CreateScreen4(); + std::unique_ptr CreateScreen5(); + }; + } + } +} \ No newline at end of file -- cgit v0.10.2 From 1d3f0dfa9eadf490b6804052ea76e79d29ecda43 Mon Sep 17 00:00:00 2001 From: Avamander Date: Thu, 10 Jun 2021 00:45:39 +0300 Subject: Tidied up and added Weather to CMakeLists.txt diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4ab303d..fb5e1d1 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -415,6 +415,7 @@ list(APPEND SOURCE_FILES displayapp/screens/Label.cpp displayapp/screens/FirmwareUpdate.cpp displayapp/screens/Music.cpp + displayapp/screens/Weather.cpp displayapp/screens/Navigation.cpp displayapp/screens/Metronome.cpp displayapp/screens/Motion.cpp @@ -479,6 +480,7 @@ list(APPEND SOURCE_FILES components/ble/CurrentTimeService.cpp components/ble/AlertNotificationService.cpp components/ble/MusicService.cpp + components/ble/weather/WeatherService.cpp components/ble/NavigationService.cpp displayapp/fonts/lv_font_navi_80.c components/ble/BatteryInformationService.cpp @@ -653,6 +655,9 @@ set(INCLUDE_FILES components/datetime/DateTimeController.h components/brightness/BrightnessController.h components/motion/MotionController.h + components/firmwarevalidator/FirmwareValidator.h + components/ble/BleController.h + components/ble/NotificationManager.h components/ble/NimbleController.h components/ble/DeviceInformationService.h components/ble/CurrentTimeClient.h @@ -665,6 +670,7 @@ set(INCLUDE_FILES components/ble/BleClient.h components/ble/HeartRateService.h components/ble/MotionService.h + components/ble/weather/WeatherService.h components/settings/Settings.h components/timer/TimerController.h components/alarm/AlarmController.h -- cgit v0.10.2 From eb27813c1839ff2edcce3176e11b1258167af229 Mon Sep 17 00:00:00 2001 From: Avamander Date: Thu, 10 Jun 2021 00:47:11 +0300 Subject: Removed redundant comments from NrfLogger diff --git a/src/logging/NrfLogger.cpp b/src/logging/NrfLogger.cpp index ab54afe..f8d95a6 100644 --- a/src/logging/NrfLogger.cpp +++ b/src/logging/NrfLogger.cpp @@ -19,14 +19,13 @@ void NrfLogger::Init() { void NrfLogger::Process(void*) { NRF_LOG_INFO("Logger task started!"); -// Suppress endless loop diagnostic + #pragma clang diagnostic push #pragma ide diagnostic ignored "EndlessLoop" while (true) { NRF_LOG_FLUSH(); vTaskDelay(100); // Not good for power consumption, it will wake up every 100ms... } -// Clear diagnostic suppression #pragma clang diagnostic pop } -- cgit v0.10.2 From 6e165848161b72d1afa43af6807c654d3fc23d03 Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 16 Jun 2021 23:31:17 +0300 Subject: Skeleton of the receiving logic diff --git a/src/components/ble/weather/WeatherData.h b/src/components/ble/weather/WeatherData.h index c1d53f4..7cf6841 100644 --- a/src/components/ble/weather/WeatherData.h +++ b/src/components/ble/weather/WeatherData.h @@ -39,7 +39,7 @@ namespace Pinetime { None = 0, /** Water particles suspended in the air; low visibility; does not fall */ Fog = 1, - /** Extremely small, dry particles in the air; invisible to the eye; opalescent */ + /** Tiny, dry particles in the air; invisible to the eye; opalescent */ Haze = 2, /** Small fire-created particles suspended in the air */ Smoke = 3, @@ -51,6 +51,7 @@ namespace Pinetime { Sand = 6, /** Water particles suspended in the air; low-ish visibility; temperature is near dewpoint */ Mist = 7, + Length }; /** @@ -82,7 +83,8 @@ namespace Pinetime { /** Frozen drizzle; very small snow crystals */ SnowGrains = 8, /** Needles; columns or plates of ice. Sometimes described as "diamond dust". In very cold regions */ - IceCrystals = 9 + IceCrystals = 9, + Length }; /** @@ -99,6 +101,7 @@ namespace Pinetime { Fire = 3, /** Thunder and/or lightning */ Thunder = 4, + Length }; /** @@ -111,7 +114,8 @@ namespace Pinetime { /** This wipes the entire timeline */ DelTimeline = 1, /** There's a currently valid timeline event with the given type */ - HasValidEvent = 3 + HasValidEvent = 3, + Length }; /** @@ -137,19 +141,20 @@ namespace Pinetime { Location = 7, /** @see cloud */ Clouds = 8, + Length }; /** * Valid event query */ - class valideventquery { + class ValidEventQuery { public: static constexpr controlcodes code = controlcodes::HasValidEvent; eventtype eventType; }; /** The header used for further parsing */ - class timelineheader { + class TimelineHeader { public: /** UNIX timestamp */ uint64_t timestamp; @@ -168,23 +173,23 @@ namespace Pinetime { }; /** Specifies how cloudiness is stored */ - class clouds : public timelineheader { + class Clouds : public TimelineHeader { public: /** Cloud coverage in percentage, 0-100% */ uint8_t amount; }; /** Specifies how obscuration is stored */ - class obscuration : public timelineheader { + class Obscuration : public TimelineHeader { public: /** Type */ obscurationtype type; /** Visibility distance in meters */ - uint8_t amount; + uint16_t amount; }; /** Specifies how precipitation is stored */ - class precipitation : public timelineheader { + class Precipitation : public TimelineHeader { public: /** Type */ precipitationtype type; @@ -201,7 +206,7 @@ namespace Pinetime { * As direction can fluctuate wildly and some watchfaces might wish to display it nicely, * we're following the aerospace industry weather report option of specifying a range. */ - class wind : public timelineheader { + class Wind : public TimelineHeader { public: /** Meters per second */ uint8_t speedMin; @@ -221,7 +226,7 @@ namespace Pinetime { * * We don't do floats, microdegrees are not useful. Make sure to multiply. */ - class temperature : public timelineheader { + class Temperature : public TimelineHeader { public: /** Temperature °C but multiplied by 100 (e.g. -12.50°C becomes -1250) */ int16_t temperature; @@ -240,7 +245,7 @@ namespace Pinetime { * or daylight calculations, should those be required. * */ - class location : public timelineheader { + class Location : public TimelineHeader { public: /** Location name */ std::string location; @@ -255,7 +260,7 @@ namespace Pinetime { /** * How humidity is stored */ - class humidity : public timelineheader { + class Humidity : public TimelineHeader { public: /** Relative humidity, 0-100% */ uint8_t humidity; @@ -264,7 +269,7 @@ namespace Pinetime { /** * How air pressure is stored */ - class pressure : public timelineheader { + class Pressure : public TimelineHeader { public: /** Air pressure in hectopascals (hPa) */ int16_t pressure; @@ -273,7 +278,7 @@ namespace Pinetime { /** * How special events are stored */ - class special : public timelineheader { + class Special : public TimelineHeader { public: /** Special event's type */ specialtype type; @@ -288,7 +293,7 @@ namespace Pinetime { * * If this needs further enforced standardization, pull requests are welcome */ - class airquality : public timelineheader { + class AirQuality : public TimelineHeader { public: /** * The name of the pollution diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index 006fc6c..60e608e 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -40,58 +40,125 @@ namespace Pinetime { } int WeatherService::OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) { + // TODO: Detect control messages if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { - getCurrentPressure(); - tidyTimeline(); - getTimelineLength(); const auto packetLen = OS_MBUF_PKTLEN(ctxt->om); if (packetLen <= 0) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } // Decode QCBORDecodeContext decodeContext; - UsefulBufC EncodedCBOR; - // TODO: Check uninit fine - QCBORDecode_Init(&decodeContext, EncodedCBOR, QCBOR_DECODE_MODE_NORMAL); + UsefulBufC encodedCbor; + // TODO: Check, uninit fine? + + QCBORDecode_Init(&decodeContext, encodedCbor, QCBOR_DECODE_MODE_NORMAL); QCBORDecode_EnterMap(&decodeContext, nullptr); - WeatherData::timelineheader timelineHeader {}; // Always encodes to the smallest number of bytes based on the value - QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", reinterpret_cast(&(timelineHeader.timestamp))); - QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", reinterpret_cast(&(timelineHeader.expires))); - QCBORDecode_GetInt64InMapSZ(&decodeContext, "EventType", reinterpret_cast(&(timelineHeader.eventType))); - switch (timelineHeader.eventType) { - // TODO: Populate + int64_t tmpVersion = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Version", &tmpVersion); + if (tmpVersion != 1) { + // TODO: Return better error? + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + int64_t tmpTimestamp = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", &tmpTimestamp); + int64_t tmpExpires = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", &tmpExpires); + if (tmpExpires > 4294967295) { + // TODO: Return better error? + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + int64_t tmpEventType = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "EventType", &tmpEventType); + if (tmpEventType > static_cast(WeatherData::eventtype::Length)) { + // TODO: Return better error? + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + + switch (static_cast(tmpEventType)) { + // TODO: Populate case WeatherData::eventtype::AirQuality: { + std::unique_ptr airquality = std::make_unique(); + airquality->timestamp = tmpTimestamp; + airquality->eventType = static_cast(tmpEventType); + airquality->expires = tmpExpires; + + timeline.push_back(std::move(airquality)); break; } case WeatherData::eventtype::Obscuration: { + std::unique_ptr obscuration = std::make_unique(); + obscuration->timestamp = tmpTimestamp; + obscuration->eventType = static_cast(tmpEventType); + obscuration->expires = tmpExpires; + + timeline.push_back(std::move(obscuration)); break; } case WeatherData::eventtype::Precipitation: { + std::unique_ptr precipitation = std::make_unique(); + precipitation->timestamp = tmpTimestamp; + precipitation->eventType = static_cast(tmpEventType); + precipitation->expires = tmpExpires; + timeline.push_back(std::move(precipitation)); break; } case WeatherData::eventtype::Wind: { + std::unique_ptr wind = std::make_unique(); + wind->timestamp = tmpTimestamp; + wind->eventType = static_cast(tmpEventType); + wind->expires = tmpExpires; + timeline.push_back(std::move(wind)); break; } case WeatherData::eventtype::Temperature: { + std::unique_ptr temperature = std::make_unique(); + temperature->timestamp = tmpTimestamp; + temperature->eventType = static_cast(tmpEventType); + temperature->expires = tmpExpires; + timeline.push_back(std::move(temperature)); break; } case WeatherData::eventtype::Special: { + std::unique_ptr special = std::make_unique(); + special->timestamp = tmpTimestamp; + special->eventType = static_cast(tmpEventType); + special->expires = tmpExpires; + timeline.push_back(std::move(special)); break; } case WeatherData::eventtype::Pressure: { + std::unique_ptr pressure = std::make_unique(); + pressure->timestamp = tmpTimestamp; + pressure->eventType = static_cast(tmpEventType); + pressure->expires = tmpExpires; + timeline.push_back(std::move(pressure)); break; } case WeatherData::eventtype::Location: { + std::unique_ptr location = std::make_unique(); + location->timestamp = tmpTimestamp; + location->eventType = static_cast(tmpEventType); + location->expires = tmpExpires; + timeline.push_back(std::move(location)); break; } case WeatherData::eventtype::Clouds: { + std::unique_ptr clouds = std::make_unique(); + clouds->timestamp = tmpTimestamp; + clouds->eventType = static_cast(tmpEventType); + clouds->expires = tmpExpires; + timeline.push_back(std::move(clouds)); break; } default: { break; } } + + getCurrentPressure(); + tidyTimeline(); + getTimelineLength(); QCBORDecode_ExitMap(&decodeContext); auto uErr = QCBORDecode_Finish(&decodeContext); @@ -99,8 +166,6 @@ namespace Pinetime { return BLE_ATT_ERR_INSUFFICIENT_RES; } } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) { - // TODO: Detect control messages - // Encode uint8_t buffer[64]; QCBOREncodeContext encodeContext; @@ -125,46 +190,46 @@ namespace Pinetime { return 0; } - WeatherData::location WeatherService::getCurrentLocation() const { - return WeatherData::location(); + WeatherData::Location WeatherService::getCurrentLocation() const { + return WeatherData::Location(); } - WeatherData::clouds WeatherService::getCurrentClouds() const { - return WeatherData::clouds(); + WeatherData::Clouds WeatherService::getCurrentClouds() const { + return WeatherData::Clouds(); } - WeatherData::obscuration WeatherService::getCurrentObscuration() const { - return WeatherData::obscuration(); + WeatherData::Obscuration WeatherService::getCurrentObscuration() const { + return WeatherData::Obscuration(); } - WeatherData::precipitation WeatherService::getCurrentPrecipitation() const { - return WeatherData::precipitation(); + WeatherData::Precipitation WeatherService::getCurrentPrecipitation() const { + return WeatherData::Precipitation(); } - WeatherData::wind WeatherService::getCurrentWind() const { - return WeatherData::wind(); + WeatherData::Wind WeatherService::getCurrentWind() const { + return WeatherData::Wind(); } - WeatherData::temperature WeatherService::getCurrentTemperature() const { - return WeatherData::temperature(); + WeatherData::Temperature WeatherService::getCurrentTemperature() const { + return WeatherData::Temperature(); } - WeatherData::humidity WeatherService::getCurrentHumidity() const { - return WeatherData::humidity(); + WeatherData::Humidity WeatherService::getCurrentHumidity() const { + return WeatherData::Humidity(); } - WeatherData::pressure WeatherService::getCurrentPressure() const { + WeatherData::Pressure WeatherService::getCurrentPressure() const { uint64_t currentTimestamp = getCurrentUNIXTimestamp(); for (auto&& header : timeline) { if (header->eventType == WeatherData::eventtype::Pressure && header->timestamp + header->expires <= currentTimestamp) { - return WeatherData::pressure(); + return WeatherData::Pressure(); } } - return WeatherData::pressure(); + return WeatherData::Pressure(); } - WeatherData::airquality WeatherService::getCurrentQuality() const { - return WeatherData::airquality(); + WeatherData::AirQuality WeatherService::getCurrentQuality() const { + return WeatherData::AirQuality(); } size_t WeatherService::getTimelineLength() const { return timeline.size(); } - bool WeatherService::addEventToTimeline(std::unique_ptr event) { + bool WeatherService::addEventToTimeline(std::unique_ptr event) { if (timeline.size() == timeline.max_size()) { return false; } @@ -188,7 +253,7 @@ namespace Pinetime { uint64_t timeCurrent = 0; timeline.erase(std::remove_if(std::begin(timeline), std::end(timeline), - [&](std::unique_ptr const& header) { + [&](std::unique_ptr const& header) { return header->timestamp + header->expires > timeCurrent; }), std::end(timeline)); @@ -196,8 +261,8 @@ namespace Pinetime { std::sort(std::begin(timeline), std::end(timeline), compareTimelineEvents); } - bool WeatherService::compareTimelineEvents(const std::unique_ptr& first, - const std::unique_ptr& second) { + bool WeatherService::compareTimelineEvents(const std::unique_ptr& first, + const std::unique_ptr& second) { return first->timestamp > second->timestamp; } diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index ef99db8..64a8213 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -57,15 +57,15 @@ namespace Pinetime { /* * Helper functions for quick access to currently valid data */ - WeatherData::location getCurrentLocation() const; - WeatherData::clouds getCurrentClouds() const; - WeatherData::obscuration getCurrentObscuration() const; - WeatherData::precipitation getCurrentPrecipitation() const; - WeatherData::wind getCurrentWind() const; - WeatherData::temperature getCurrentTemperature() const; - WeatherData::humidity getCurrentHumidity() const; - WeatherData::pressure getCurrentPressure() const; - WeatherData::airquality getCurrentQuality() const; + WeatherData::Location getCurrentLocation() const; + WeatherData::Clouds getCurrentClouds() const; + WeatherData::Obscuration getCurrentObscuration() const; + WeatherData::Precipitation getCurrentPrecipitation() const; + WeatherData::Wind getCurrentWind() const; + WeatherData::Temperature getCurrentTemperature() const; + WeatherData::Humidity getCurrentHumidity() const; + WeatherData::Pressure getCurrentPressure() const; + WeatherData::AirQuality getCurrentQuality() const; /* * Management functions @@ -74,7 +74,7 @@ namespace Pinetime { * Adds an event to the timeline * @return */ - bool addEventToTimeline(std::unique_ptr event); + bool addEventToTimeline(std::unique_ptr event); /** * Gets the current timeline length */ @@ -86,37 +86,36 @@ namespace Pinetime { bool hasTimelineEventOfType(WeatherData::eventtype type) const; private: - ble_uuid128_t msUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_UUID_BASE}; + ble_uuid128_t weatherUUID {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_UUID_BASE}; /** * Just write timeline data here */ - ble_uuid128_t wDataCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_CHAR_UUID(0x00, 0x01)}; + ble_uuid128_t weatherDataCharUUID {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_CHAR_UUID(0x00, 0x01)}; /** - * This doesn't take timeline data - * but provides some control over it + * This doesn't take timeline data, + * provides some control over it */ - ble_uuid128_t wControlCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_CHAR_UUID(0x00, 0x02)}; + ble_uuid128_t weatherControlCharUUID {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_CHAR_UUID(0x00, 0x02)}; - const struct ble_gatt_chr_def characteristicDefinition[2] = {{.uuid = reinterpret_cast(&wDataCharUuid), + const struct ble_gatt_chr_def characteristicDefinition[2] = {{.uuid = &weatherDataCharUUID.u, .access_cb = WeatherCallback, .arg = this, .flags = BLE_GATT_CHR_F_NOTIFY, .val_handle = &eventHandle}, - {.uuid = reinterpret_cast(&wControlCharUuid), + {.uuid = &weatherControlCharUUID.u, .access_cb = WeatherCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}}; const struct ble_gatt_svc_def serviceDefinition[2] = { - {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = reinterpret_cast(&msUuid), .characteristics = characteristicDefinition}, - {0}}; + {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &weatherUUID.u, .characteristics = characteristicDefinition}, {0}}; uint16_t eventHandle {}; Pinetime::System::SystemTask& system; Pinetime::Controllers::DateTime& dateTimeController; - std::vector> timeline; + std::vector> timeline; /** * Cleans up the timeline of expired events @@ -127,11 +126,11 @@ namespace Pinetime { /** * Compares two timeline events */ - static bool compareTimelineEvents(const std::unique_ptr& first, - const std::unique_ptr& second); + static bool compareTimelineEvents(const std::unique_ptr& first, + const std::unique_ptr& second); /** - * + * Returns current UNIX timestamp */ uint64_t getCurrentUNIXTimestamp() const; }; -- cgit v0.10.2 From 4349657f799bed04538d95c8d54653586100e82e Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 16 Jun 2021 23:31:40 +0300 Subject: Minor style improvement diff --git a/src/components/ble/AlertNotificationService.cpp b/src/components/ble/AlertNotificationService.cpp index f616cce..0481912 100644 --- a/src/components/ble/AlertNotificationService.cpp +++ b/src/components/ble/AlertNotificationService.cpp @@ -53,8 +53,9 @@ int AlertNotificationService::OnAlert(uint16_t conn_handle, uint16_t attr_handle // Ignore notifications with empty message const auto packetLen = OS_MBUF_PKTLEN(ctxt->om); - if (packetLen <= headerSize) + if (packetLen <= headerSize) { return 0; + } size_t bufferSize = std::min(packetLen + stringTerminatorSize, maxBufferSize); auto messageSize = std::min(maxMessageSize, (bufferSize - headerSize)); -- cgit v0.10.2 From 4b2dcbb4f053a89faab50c03083c71fabf9f288a Mon Sep 17 00:00:00 2001 From: Avamander Date: Sun, 20 Jun 2021 21:37:53 +0300 Subject: Fixed a few bugs, enabled UsefulBuf library optimizations diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fb5e1d1..4273bec 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -860,6 +860,7 @@ target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_EXP_AND_MANTISSA) target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS) target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS) target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_UNCOMMON_TAGS) +target_compile_definitions(QCBOR PUBLIC USEFULBUF_CONFIG_LITTLE_ENDIAN) set_target_properties(QCBOR PROPERTIES LINKER_LANGUAGE C) target_compile_options(QCBOR PRIVATE $<$,$>: ${COMMON_FLAGS} -O0 -g3> diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index a21cbe8..34f00e4 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -71,6 +71,9 @@ namespace Pinetime { Pinetime::Controllers::AlertNotificationService& alertService() { return anService; }; + Pinetime::Controllers::WeatherService& weather() { + return weatherService; + }; uint16_t connHandle(); void NotifyBatteryLevel(uint8_t level); diff --git a/src/components/ble/weather/WeatherData.h b/src/components/ble/weather/WeatherData.h index 7cf6841..ee2a364 100644 --- a/src/components/ble/weather/WeatherData.h +++ b/src/components/ble/weather/WeatherData.h @@ -248,7 +248,7 @@ namespace Pinetime { class Location : public TimelineHeader { public: /** Location name */ - std::string location; + std::unique_ptr location; /** Altitude relative to sea level in meters */ int16_t altitude; /** Latitude, EPSG:3857 (Google Maps, Openstreetmaps datum) */ @@ -309,7 +309,7 @@ namespace Pinetime { * For chemical compounds use the molecular formula e.g. "NO2", "CO2", "O3" * For pollen use the genus, e.g. "Betula" for birch or "Alternaria" for that mold's spores */ - std::string polluter; + std::unique_ptr polluter; /** * Amount of the pollution in SI units, * otherwise it's going to be difficult to create UI, alerts diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index 60e608e..30d274b 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -33,7 +33,7 @@ namespace Pinetime { void WeatherService::Init() { uint8_t res = 0; res = ble_gatts_count_cfg(serviceDefinition); - ASSERT(res == 0) + ASSERT(res == 0); res = ble_gatts_add_svcs(serviceDefinition); ASSERT(res == 0); @@ -64,13 +64,13 @@ namespace Pinetime { QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", &tmpTimestamp); int64_t tmpExpires = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", &tmpExpires); - if (tmpExpires > 4294967295) { + if (tmpExpires < 0 || tmpExpires > 4294967295) { // TODO: Return better error? return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } int64_t tmpEventType = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "EventType", &tmpEventType); - if (tmpEventType > static_cast(WeatherData::eventtype::Length)) { + if (tmpEventType < 0 || tmpEventType > static_cast(WeatherData::eventtype::Length)) { // TODO: Return better error? return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } @@ -82,7 +82,18 @@ namespace Pinetime { airquality->timestamp = tmpTimestamp; airquality->eventType = static_cast(tmpEventType); airquality->expires = tmpExpires; - + UsefulBufC String; + QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Polluter", &String); + if (UsefulBuf_IsNULLOrEmptyC(String) != 0) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + airquality->polluter = std::make_unique(static_cast(String.ptr), String.len); + int64_t tmpAmount = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount); + if (tmpAmount < 0 || tmpAmount > 4294967295) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + airquality->amount = tmpAmount; timeline.push_back(std::move(airquality)); break; } diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index 64a8213..43002dc 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -32,12 +32,6 @@ #include "WeatherData.h" #include -// 00030000-78fc-48fe-8e23-433b3a1942d0 -#define WEATHER_SERVICE_UUID_BASE \ - { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x03, 0x00 } -#define WEATHER_SERVICE_CHAR_UUID(y, x) \ - { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, (x), (y), 0x03, 0x00 } - int WeatherCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg); namespace Pinetime { @@ -86,27 +80,37 @@ namespace Pinetime { bool hasTimelineEventOfType(WeatherData::eventtype type) const; private: - ble_uuid128_t weatherUUID {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_UUID_BASE}; + // 00030000-78fc-48fe-8e23-433b3a1942d0 + static constexpr ble_uuid128_t BaseUUID() { + return CharUUID(0x00, 0x00); + } + + // 0003yyxx-78fc-48fe-8e23-433b3a1942d0 + static 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, 0x03, 0x00}}; + } + + ble_uuid128_t weatherUUID {BaseUUID()}; /** * Just write timeline data here */ - ble_uuid128_t weatherDataCharUUID {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_CHAR_UUID(0x00, 0x01)}; + ble_uuid128_t weatherDataCharUUID {CharUUID(0x00, 0x01)}; /** * This doesn't take timeline data, * provides some control over it */ - ble_uuid128_t weatherControlCharUUID {.u = {.type = BLE_UUID_TYPE_128}, .value = WEATHER_SERVICE_CHAR_UUID(0x00, 0x02)}; - - const struct ble_gatt_chr_def characteristicDefinition[2] = {{.uuid = &weatherDataCharUUID.u, - .access_cb = WeatherCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_NOTIFY, - .val_handle = &eventHandle}, - {.uuid = &weatherControlCharUUID.u, - .access_cb = WeatherCallback, - .arg = this, - .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}}; + ble_uuid128_t weatherControlCharUUID {CharUUID(0x00, 0x02)}; + + const struct ble_gatt_chr_def characteristicDefinition[3] = { + {.uuid = &weatherDataCharUUID.u, + .access_cb = WeatherCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE, + .val_handle = &eventHandle}, + {.uuid = &weatherControlCharUUID.u, .access_cb = WeatherCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}, + {nullptr}}; const struct ble_gatt_svc_def serviceDefinition[2] = { {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &weatherUUID.u, .characteristics = characteristicDefinition}, {0}}; -- cgit v0.10.2 From b6e9e4171d3ecb417b7fbae61285474036542508 Mon Sep 17 00:00:00 2001 From: Avamander Date: Fri, 25 Jun 2021 00:39:50 +0300 Subject: Switched to non-deprecated math header diff --git a/src/components/battery/BatteryController.cpp b/src/components/battery/BatteryController.cpp index c875cb8..300d097 100644 --- a/src/components/battery/BatteryController.cpp +++ b/src/components/battery/BatteryController.cpp @@ -3,6 +3,7 @@ #include #include #include +#include using namespace Pinetime::Controllers; -- cgit v0.10.2 From 3a09b3614c19fda8f90af28b596a6359064ad0fb Mon Sep 17 00:00:00 2001 From: Avamander Date: Fri, 25 Jun 2021 00:43:30 +0300 Subject: Brace style and whitespace fixes diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4273bec..d83c467 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1153,4 +1153,4 @@ elseif (USE_OPENOCD) COMMENT "flashing ${EXECUTABLE_FILE_NAME}.hex" ) endif () -endif () +endif () \ No newline at end of file diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index 30d274b..ae7370b 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -281,4 +281,4 @@ namespace Pinetime { return std::chrono::duration_cast(dateTimeController.CurrentDateTime().time_since_epoch()).count(); } } -} +} \ No newline at end of file diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index 43002dc..53dbebf 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -139,4 +139,4 @@ namespace Pinetime { uint64_t getCurrentUNIXTimestamp() const; }; } -} +} \ No newline at end of file diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index c363e2d..0762626 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -274,4 +274,4 @@ std::unique_ptr SystemInfo::CreateScreen5() { 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); -} +} \ No newline at end of file diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp index 014761b..0ba53be 100644 --- a/src/displayapp/screens/Weather.cpp +++ b/src/displayapp/screens/Weather.cpp @@ -243,4 +243,4 @@ std::unique_ptr Weather::CreateScreen5() { lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); return std::unique_ptr(new Screens::Label(4, 5, app, label)); -} +} \ No newline at end of file -- cgit v0.10.2 From 2736fa57bb0fd802222f5989584eac64c371b118 Mon Sep 17 00:00:00 2001 From: Avamander Date: Fri, 25 Jun 2021 01:10:35 +0300 Subject: Added autodetection for clang-format version diff --git a/src/displayapp/screens/settings/SettingSteps.cpp b/src/displayapp/screens/settings/SettingSteps.cpp index 149840d..5ca3eec 100644 --- a/src/displayapp/screens/settings/SettingSteps.cpp +++ b/src/displayapp/screens/settings/SettingSteps.cpp @@ -6,8 +6,8 @@ using namespace Pinetime::Applications::Screens; namespace { - static void event_handler(lv_obj_t * obj, lv_event_t event) { - SettingSteps* screen = static_cast(obj->user_data); + void event_handler(lv_obj_t* obj, lv_event_t event) { + SettingSteps* screen = static_cast(obj->user_data); screen->UpdateSelected(obj, event); } } @@ -30,33 +30,32 @@ SettingSteps::SettingSteps( 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_obj_t* title = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_static(title,"Daily steps goal"); 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::shoe); lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); - - stepValue = lv_label_create(lv_scr_act(), NULL); + stepValue = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); lv_label_set_text_fmt(stepValue, "%lu", settingsController.GetStepsGoal()); lv_label_set_align(stepValue, LV_LABEL_ALIGN_CENTER); lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_CENTER, 0, -10); - btnPlus = lv_btn_create(lv_scr_act(), NULL); + btnPlus = lv_btn_create(lv_scr_act(), nullptr); btnPlus->user_data = this; lv_obj_set_size(btnPlus, 80, 50); lv_obj_align(btnPlus, lv_scr_act(), LV_ALIGN_CENTER, 55, 80); lv_obj_set_style_local_value_str(btnPlus, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, "+"); lv_obj_set_event_cb(btnPlus, event_handler); - btnMinus = lv_btn_create(lv_scr_act(), NULL); + btnMinus = lv_btn_create(lv_scr_act(), nullptr); btnMinus->user_data = this; lv_obj_set_size(btnMinus, 80, 50); lv_obj_set_event_cb(btnMinus, event_handler); -- cgit v0.10.2 From 19c9667a3d597167241ebcb4dfefb4e0cac068df Mon Sep 17 00:00:00 2001 From: Avamander Date: Fri, 25 Jun 2021 01:18:56 +0300 Subject: Started initial work on the UI diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index ae7370b..7d20867 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -20,8 +20,8 @@ #include "libs/QCBOR/inc/qcbor/qcbor.h" #include "systemtask/SystemTask.h" -int WeatherCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) { - return static_cast(arg)->OnCommand(conn_handle, attr_handle, ctxt); +int WeatherCallback(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt, void* arg) { + return static_cast(arg)->OnCommand(connHandle, attrHandle, ctxt); } namespace Pinetime { @@ -39,7 +39,7 @@ namespace Pinetime { ASSERT(res == 0); } - int WeatherService::OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) { + int WeatherService::OnCommand(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt) { // TODO: Detect control messages if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { const auto packetLen = OS_MBUF_PKTLEN(ctxt->om); @@ -167,9 +167,9 @@ namespace Pinetime { } } - getCurrentPressure(); - tidyTimeline(); - getTimelineLength(); + GetCurrentPressure(); + TidyTimeline(); + GetTimelineLength(); QCBORDecode_ExitMap(&decodeContext); auto uErr = QCBORDecode_Finish(&decodeContext); @@ -201,29 +201,36 @@ namespace Pinetime { return 0; } - WeatherData::Location WeatherService::getCurrentLocation() const { + WeatherData::Location WeatherService::GetCurrentLocation() const { return WeatherData::Location(); } - WeatherData::Clouds WeatherService::getCurrentClouds() const { + + WeatherData::Clouds WeatherService::GetCurrentClouds() const { return WeatherData::Clouds(); } - WeatherData::Obscuration WeatherService::getCurrentObscuration() const { + + WeatherData::Obscuration WeatherService::GetCurrentObscuration() const { return WeatherData::Obscuration(); } - WeatherData::Precipitation WeatherService::getCurrentPrecipitation() const { + + WeatherData::Precipitation WeatherService::GetCurrentPrecipitation() const { return WeatherData::Precipitation(); } - WeatherData::Wind WeatherService::getCurrentWind() const { + + WeatherData::Wind WeatherService::GetCurrentWind() const { return WeatherData::Wind(); } - WeatherData::Temperature WeatherService::getCurrentTemperature() const { + + WeatherData::Temperature WeatherService::GetCurrentTemperature() const { return WeatherData::Temperature(); } - WeatherData::Humidity WeatherService::getCurrentHumidity() const { + + WeatherData::Humidity WeatherService::GetCurrentHumidity() const { return WeatherData::Humidity(); } - WeatherData::Pressure WeatherService::getCurrentPressure() const { - uint64_t currentTimestamp = getCurrentUNIXTimestamp(); + + WeatherData::Pressure WeatherService::GetCurrentPressure() const { + uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : timeline) { if (header->eventType == WeatherData::eventtype::Pressure && header->timestamp + header->expires <= currentTimestamp) { return WeatherData::Pressure(); @@ -232,15 +239,15 @@ namespace Pinetime { return WeatherData::Pressure(); } - WeatherData::AirQuality WeatherService::getCurrentQuality() const { + WeatherData::AirQuality WeatherService::GetCurrentQuality() const { return WeatherData::AirQuality(); } - size_t WeatherService::getTimelineLength() const { + size_t WeatherService::GetTimelineLength() const { return timeline.size(); } - bool WeatherService::addEventToTimeline(std::unique_ptr event) { + bool WeatherService::AddEventToTimeline(std::unique_ptr event) { if (timeline.size() == timeline.max_size()) { return false; } @@ -249,8 +256,8 @@ namespace Pinetime { return true; } - bool WeatherService::hasTimelineEventOfType(const WeatherData::eventtype type) const { - uint64_t currentTimestamp = getCurrentUNIXTimestamp(); + bool WeatherService::HasTimelineEventOfType(const WeatherData::eventtype type) const { + uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : timeline) { if (header->eventType == type && header->timestamp + header->expires <= currentTimestamp) { // TODO: Check if its currently valid @@ -260,7 +267,7 @@ namespace Pinetime { return false; } - void WeatherService::tidyTimeline() { + void WeatherService::TidyTimeline() { uint64_t timeCurrent = 0; timeline.erase(std::remove_if(std::begin(timeline), std::end(timeline), @@ -269,15 +276,15 @@ namespace Pinetime { }), std::end(timeline)); - std::sort(std::begin(timeline), std::end(timeline), compareTimelineEvents); + std::sort(std::begin(timeline), std::end(timeline), CompareTimelineEvents); } - bool WeatherService::compareTimelineEvents(const std::unique_ptr& first, + bool WeatherService::CompareTimelineEvents(const std::unique_ptr& first, const std::unique_ptr& second) { return first->timestamp > second->timestamp; } - uint64_t WeatherService::getCurrentUNIXTimestamp() const { + uint64_t WeatherService::GetCurrentUnixTimestamp() const { return std::chrono::duration_cast(dateTimeController.CurrentDateTime().time_since_epoch()).count(); } } diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index 53dbebf..786d471 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -32,7 +32,7 @@ #include "WeatherData.h" #include -int WeatherCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg); +int WeatherCallback(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt, void* arg); namespace Pinetime { namespace System { @@ -46,20 +46,20 @@ namespace Pinetime { void Init(); - int OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt); + int OnCommand(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt); /* * Helper functions for quick access to currently valid data */ - WeatherData::Location getCurrentLocation() const; - WeatherData::Clouds getCurrentClouds() const; - WeatherData::Obscuration getCurrentObscuration() const; - WeatherData::Precipitation getCurrentPrecipitation() const; - WeatherData::Wind getCurrentWind() const; - WeatherData::Temperature getCurrentTemperature() const; - WeatherData::Humidity getCurrentHumidity() const; - WeatherData::Pressure getCurrentPressure() const; - WeatherData::AirQuality getCurrentQuality() const; + WeatherData::Location GetCurrentLocation() const; + WeatherData::Clouds GetCurrentClouds() const; + WeatherData::Obscuration GetCurrentObscuration() const; + WeatherData::Precipitation GetCurrentPrecipitation() const; + WeatherData::Wind GetCurrentWind() const; + WeatherData::Temperature GetCurrentTemperature() const; + WeatherData::Humidity GetCurrentHumidity() const; + WeatherData::Pressure GetCurrentPressure() const; + WeatherData::AirQuality GetCurrentQuality() const; /* * Management functions @@ -68,16 +68,16 @@ namespace Pinetime { * Adds an event to the timeline * @return */ - bool addEventToTimeline(std::unique_ptr event); + bool AddEventToTimeline(std::unique_ptr event); /** * Gets the current timeline length */ - size_t getTimelineLength() const; + size_t GetTimelineLength() const; /** * Checks if an event of a certain type exists in the timeline * @return */ - bool hasTimelineEventOfType(WeatherData::eventtype type) const; + bool HasTimelineEventOfType(const WeatherData::eventtype type) const; private: // 00030000-78fc-48fe-8e23-433b3a1942d0 @@ -125,18 +125,18 @@ namespace Pinetime { * Cleans up the timeline of expired events * @return result code */ - void tidyTimeline(); + void TidyTimeline(); /** * Compares two timeline events */ - static bool compareTimelineEvents(const std::unique_ptr& first, + static bool CompareTimelineEvents(const std::unique_ptr& first, const std::unique_ptr& second); /** * Returns current UNIX timestamp */ - uint64_t getCurrentUNIXTimestamp() const; + uint64_t GetCurrentUnixTimestamp() const; }; } } \ No newline at end of file diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp index 0ba53be..a127864 100644 --- a/src/displayapp/screens/Weather.cpp +++ b/src/displayapp/screens/Weather.cpp @@ -1,5 +1,6 @@ #include "Weather.h" #include +#include #include "../DisplayApp.h" #include "Label.h" #include "Version.h" @@ -12,22 +13,14 @@ using namespace Pinetime::Applications::Screens; -Weather::Weather(Pinetime::Applications::DisplayApp* app, - Pinetime::Controllers::DateTime& dateTimeController, - Pinetime::Controllers::Battery& batteryController, - Pinetime::Controllers::BrightnessController& brightnessController, - Pinetime::Controllers::Ble& bleController, - Pinetime::Drivers::WatchdogView& watchdog) +Weather::Weather(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::WeatherService& weather) : Screen(app), dateTimeController {dateTimeController}, - batteryController {batteryController}, - brightnessController {brightnessController}, - bleController {bleController}, - watchdog {watchdog}, + weatherService(weather), screens {app, 0, {[this]() -> std::unique_ptr { - return CreateScreen1(); + return CreateScreenTemperature(); }, [this]() -> std::unique_ptr { return CreateScreen2(); @@ -64,101 +57,30 @@ bool Weather::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return screens.OnTouchEvent(event); } -std::unique_ptr Weather::CreateScreen1() { +std::unique_ptr Weather::CreateScreenTemperature() { lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); lv_label_set_recolor(label, true); + Controllers::WeatherData::Temperature current = weatherService.GetCurrentTemperature(); lv_label_set_text_fmt(label, - "#FFFF00 InfiniTime#\n\n" - "#444444 Version# %ld.%ld.%ld\n\n" - "#444444 Build date#\n" - "%s\n" - "%s\n", - Version::Major(), - Version::Minor(), - Version::Patch(), - __DATE__, - __TIME__); + "#FFFF00 Temperature#\n\n" + "#444444 %hd%%#°C \n\n" + "#444444 %hd#\n" + "%llu\n" + "%lu\n", + current.temperature, + current.dewPoint, + current.timestamp, + current.expires); lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); return std::unique_ptr(new Screens::Label(0, 5, app, label)); } std::unique_ptr Weather::CreateScreen2() { - auto batteryPercent = static_cast(batteryController.PercentRemaining()); - float batteryVoltage = batteryController.Voltage(); - - auto resetReason = [this]() { - switch (watchdog.ResetReason()) { - case Drivers::Watchdog::ResetReasons::Watchdog: - return "wtdg"; - case Drivers::Watchdog::ResetReasons::HardReset: - return "hardr"; - case Drivers::Watchdog::ResetReasons::NFC: - return "nfc"; - case Drivers::Watchdog::ResetReasons::SoftReset: - return "softr"; - case Drivers::Watchdog::ResetReasons::CpuLockup: - return "cpulock"; - case Drivers::Watchdog::ResetReasons::SystemOff: - return "off"; - case Drivers::Watchdog::ResetReasons::LpComp: - return "lpcomp"; - case Drivers::Watchdog::ResetReasons::DebugInterface: - return "dbg"; - case Drivers::Watchdog::ResetReasons::ResetPin: - return "rst"; - default: - return "?"; - } - }(); - // uptime - static constexpr uint32_t secondsInADay = 60 * 60 * 24; - static constexpr uint32_t secondsInAnHour = 60 * 60; - static constexpr uint32_t secondsInAMinute = 60; - uint32_t uptimeSeconds = dateTimeController.Uptime().count(); - uint32_t uptimeDays = (uptimeSeconds / secondsInADay); - uptimeSeconds = uptimeSeconds % secondsInADay; - uint32_t uptimeHours = uptimeSeconds / secondsInAnHour; - uptimeSeconds = uptimeSeconds % secondsInAnHour; - uint32_t uptimeMinutes = uptimeSeconds / secondsInAMinute; - uptimeSeconds = uptimeSeconds % secondsInAMinute; - // TODO handle more than 100 days of uptime - - if (batteryPercent == -1) - batteryPercent = 0; - - // hack to not use the flot functions from printf - uint8_t batteryVoltageBytes[2]; - batteryVoltageBytes[1] = static_cast(batteryVoltage); // truncate whole numbers - batteryVoltageBytes[0] = - static_cast((batteryVoltage - batteryVoltageBytes[1]) * 100); // remove whole part of flt and shift 2 places over - // - lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); lv_label_set_recolor(label, true); - lv_label_set_text_fmt(label, - "#444444 Date# %02d/%02d/%04d\n" - "#444444 Time# %02d:%02d:%02d\n" - "#444444 Uptime#\n %02lud %02lu:%02lu:%02lu\n" - "#444444 Battery# %d%%/%1i.%02iv\n" - "#444444 Backlight# %s\n" - "#444444 Last reset# %s\n", - dateTimeController.Day(), - static_cast(dateTimeController.Month()), - dateTimeController.Year(), - dateTimeController.Hours(), - dateTimeController.Minutes(), - dateTimeController.Seconds(), - uptimeDays, - uptimeHours, - uptimeMinutes, - uptimeSeconds, - batteryPercent, - batteryVoltageBytes[1], - batteryVoltageBytes[0], - brightnessController.ToString(), - resetReason); + lv_label_set_text_fmt(label, "#444444 Date# %02d\n", dateTimeController.Day()); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); return std::unique_ptr(new Screens::Label(1, 4, app, label)); } @@ -169,28 +91,11 @@ std::unique_ptr Weather::CreateScreen3() { lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); lv_label_set_recolor(label, true); - auto& bleAddr = bleController.Address(); lv_label_set_text_fmt(label, - "#444444 BLE MAC#\n" - " %02x:%02x:%02x:%02x:%02x:%02x" - "\n" - "#444444 Memory#\n" - " #444444 used# %d (%d%%)\n" " #444444 frag# %d%%\n" - " #444444 free# %d" - "\n" - "#444444 Steps# %li", - bleAddr[5], - bleAddr[4], - bleAddr[3], - bleAddr[2], - bleAddr[1], - bleAddr[0], - (int) mon.total_size - mon.free_size, + " #444444 free# %d", mon.used_pct, - mon.frag_pct, - (int) mon.free_biggest_size, - 0); + mon.frag_pct); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); return std::unique_ptr(new Screens::Label(2, 5, app, label)); } @@ -201,7 +106,7 @@ bool sortById(const TaskStatus_t& lhs, const TaskStatus_t& rhs) { std::unique_ptr Weather::CreateScreen4() { TaskStatus_t tasksStatus[7]; - lv_obj_t* infoTask = lv_table_create(lv_scr_act(), NULL); + lv_obj_t* infoTask = lv_table_create(lv_scr_act(), nullptr); lv_table_set_col_cnt(infoTask, 3); lv_table_set_row_cnt(infoTask, 8); lv_obj_set_pos(infoTask, 10, 10); diff --git a/src/displayapp/screens/Weather.h b/src/displayapp/screens/Weather.h index 8b393ca..469bf59 100644 --- a/src/displayapp/screens/Weather.h +++ b/src/displayapp/screens/Weather.h @@ -1,52 +1,43 @@ #pragma once #include +#include #include "Screen.h" #include "ScreenList.h" namespace Pinetime { - namespace Controllers { - class DateTime; - class Battery; - class BrightnessController; - class Ble; - } - - namespace Drivers { - class WatchdogView; - } - namespace Applications { class DisplayApp; namespace Screens { class Weather : public Screen { public: - explicit Weather(DisplayApp* app, - Pinetime::Controllers::DateTime& dateTimeController, - Pinetime::Controllers::Battery& batteryController, - Pinetime::Controllers::BrightnessController& brightnessController, - Pinetime::Controllers::Ble& bleController, - Pinetime::Drivers::WatchdogView& watchdog); + explicit Weather(DisplayApp* app, Pinetime::Controllers::WeatherService& weather); + ~Weather() override; + bool Refresh() override; + bool OnButtonPushed() override; + bool OnTouchEvent(TouchEvents event) override; private: bool running = true; Pinetime::Controllers::DateTime& dateTimeController; - Pinetime::Controllers::Battery& batteryController; - Pinetime::Controllers::BrightnessController& brightnessController; - Pinetime::Controllers::Ble& bleController; - Pinetime::Drivers::WatchdogView& watchdog; + Controllers::WeatherService& weatherService; ScreenList<5> screens; - std::unique_ptr CreateScreen1(); + + std::unique_ptr CreateScreenTemperature(); + std::unique_ptr CreateScreen2(); + std::unique_ptr CreateScreen3(); + std::unique_ptr CreateScreen4(); + std::unique_ptr CreateScreen5(); }; } -- cgit v0.10.2 From 0ed256ba15ceace2949f21ecbc1407b8553dd75d Mon Sep 17 00:00:00 2001 From: Avamander Date: Fri, 25 Jun 2021 02:52:59 +0300 Subject: Few formatting fixes diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d83c467..f1149ce 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -796,7 +796,7 @@ link_directories( ) -set(COMMON_FLAGS -MP -MD -mthumb -mabi=aapcs -Wall -Wno-unknown-pragmas -g3 -ffunction-sections -fdata-sections -fno-strict-aliasing -fno-builtin --short-enums -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wreturn-type -Werror=return-type -fstack-usage -fno-exceptions -fno-non-call-exceptions) +set(COMMON_FLAGS -MP -MD -mthumb -mabi=aapcs -Wall -Wextra -Warray-bounds=2 -Wformat=2 -Wformat-overflow=2 -Wformat-truncation=2 -Wformat-nonliteral -ftree-vrp -Wno-unused-parameter -Wno-missing-field-initializers -Wno-unknown-pragmas -Wno-expansion-to-defined -g3 -ffunction-sections -fdata-sections -fno-strict-aliasing -fno-builtin --short-enums -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wreturn-type -Werror=return-type -fstack-usage -fno-exceptions -fno-non-call-exceptions) add_definitions(-DCONFIG_GPIO_AS_PINRESET) add_definitions(-DNIMBLE_CFG_CONTROLLER) add_definitions(-DOS_CPUTIME_FREQ) @@ -818,10 +818,10 @@ add_library(nrf-sdk STATIC ${SDK_SOURCE_FILES}) target_include_directories(nrf-sdk SYSTEM PUBLIC . ../) target_include_directories(nrf-sdk SYSTEM PUBLIC ${INCLUDES_FROM_LIBS}) target_compile_options(nrf-sdk PRIVATE - $<$,$>: ${COMMON_FLAGS} -Og -g3> - $<$,$>: ${COMMON_FLAGS} -Os> - $<$,$>: ${COMMON_FLAGS} -Og -fno-rtti> - $<$,$>: ${COMMON_FLAGS} -Os -fno-rtti> + $<$,$>: ${COMMON_FLAGS} -Wno-expansion-to-defined -Og -g3> + $<$,$>: ${COMMON_FLAGS} -Wno-expansion-to-defined -O3> + $<$,$>: ${COMMON_FLAGS} -Wno-expansion-to-defined -Og -fno-rtti> + $<$,$>: ${COMMON_FLAGS} -Wno-expansion-to-defined -O3 -fno-rtti> $<$: -MP -MD -x assembler-with-cpp> ) @@ -1153,4 +1153,4 @@ elseif (USE_OPENOCD) COMMENT "flashing ${EXECUTABLE_FILE_NAME}.hex" ) endif () -endif () \ No newline at end of file +endif () diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index 7d20867..a9c9f11 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -288,4 +288,4 @@ namespace Pinetime { return std::chrono::duration_cast(dateTimeController.CurrentDateTime().time_since_epoch()).count(); } } -} \ No newline at end of file +} diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index 786d471..995f856 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -139,4 +139,4 @@ namespace Pinetime { uint64_t GetCurrentUnixTimestamp() const; }; } -} \ No newline at end of file +} -- cgit v0.10.2 From ed6f0aade4db811b5013441c57944baff4528938 Mon Sep 17 00:00:00 2001 From: Avamander Date: Sat, 21 Aug 2021 21:58:03 +0300 Subject: Implemented a few functions. diff --git a/src/components/ble/weather/WeatherData.h b/src/components/ble/weather/WeatherData.h index ee2a364..9b42400 100644 --- a/src/components/ble/weather/WeatherData.h +++ b/src/components/ble/weather/WeatherData.h @@ -122,7 +122,7 @@ namespace Pinetime { * Events have types * then they're easier to parse after sending them over the air */ - enum class eventtype { + enum class eventtype : uint8_t { /** @see obscuration */ Obscuration = 0, /** @see precipitation */ @@ -141,6 +141,8 @@ namespace Pinetime { Location = 7, /** @see cloud */ Clouds = 8, + /** @see humidity */ + Humidity = 9, Length }; @@ -340,4 +342,4 @@ namespace Pinetime { }; }; } -} \ No newline at end of file +} diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index a9c9f11..22c8083 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -90,7 +90,7 @@ namespace Pinetime { airquality->polluter = std::make_unique(static_cast(String.ptr), String.len); int64_t tmpAmount = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount); - if (tmpAmount < 0 || tmpAmount > 4294967295) { + if (tmpAmount < 0) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } airquality->amount = tmpAmount; @@ -162,6 +162,14 @@ namespace Pinetime { timeline.push_back(std::move(clouds)); break; } + case WeatherData::eventtype::Humidity: { + std::unique_ptr humidity = std::make_unique(); + humidity->timestamp = tmpTimestamp; + humidity->eventType = static_cast(tmpEventType); + humidity->expires = tmpExpires; + timeline.push_back(std::move(humidity)); + break; + } default: { break; } @@ -201,46 +209,94 @@ namespace Pinetime { return 0; } - WeatherData::Location WeatherService::GetCurrentLocation() const { - return WeatherData::Location(); - } - WeatherData::Clouds WeatherService::GetCurrentClouds() const { - return WeatherData::Clouds(); + uint64_t currentTimestamp = GetCurrentUnixTimestamp(); + for (auto&& header : timeline) { + if (header->eventType == WeatherData::eventtype::Clouds && header->timestamp + header->expires <= currentTimestamp) { + return reinterpret_cast(header); + } + } + return {}; } WeatherData::Obscuration WeatherService::GetCurrentObscuration() const { - return WeatherData::Obscuration(); + uint64_t currentTimestamp = GetCurrentUnixTimestamp(); + for (auto&& header : timeline) { + if (header->eventType == WeatherData::eventtype::Obscuration && header->timestamp + header->expires <= currentTimestamp) { + return reinterpret_cast(header); + } + } + return {}; } WeatherData::Precipitation WeatherService::GetCurrentPrecipitation() const { - return WeatherData::Precipitation(); + uint64_t currentTimestamp = GetCurrentUnixTimestamp(); + for (auto&& header : timeline) { + if (header->eventType == WeatherData::eventtype::Precipitation && header->timestamp + header->expires <= currentTimestamp) { + return reinterpret_cast(header); + } + } + return {}; } WeatherData::Wind WeatherService::GetCurrentWind() const { - return WeatherData::Wind(); + uint64_t currentTimestamp = GetCurrentUnixTimestamp(); + for (auto&& header : timeline) { + if (header->eventType == WeatherData::eventtype::Wind && header->timestamp + header->expires <= currentTimestamp) { + return reinterpret_cast(header); + } + } + return {}; } WeatherData::Temperature WeatherService::GetCurrentTemperature() const { - return WeatherData::Temperature(); + uint64_t currentTimestamp = GetCurrentUnixTimestamp(); + for (auto&& header : timeline) { + if (header->eventType == WeatherData::eventtype::Temperature && header->timestamp + header->expires <= currentTimestamp) { + return reinterpret_cast(header); + } + } + return {}; } WeatherData::Humidity WeatherService::GetCurrentHumidity() const { - return WeatherData::Humidity(); + uint64_t currentTimestamp = GetCurrentUnixTimestamp(); + for (auto&& header : timeline) { + if (header->eventType == WeatherData::eventtype::Humidity && header->timestamp + header->expires <= currentTimestamp) { + return reinterpret_cast(header); + } + } + return {}; } WeatherData::Pressure WeatherService::GetCurrentPressure() const { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : timeline) { if (header->eventType == WeatherData::eventtype::Pressure && header->timestamp + header->expires <= currentTimestamp) { - return WeatherData::Pressure(); + return reinterpret_cast(header); + } + } + return {}; + } + + WeatherData::Location WeatherService::GetCurrentLocation() const { + uint64_t currentTimestamp = GetCurrentUnixTimestamp(); + for (auto&& header : timeline) { + if (header->eventType == WeatherData::eventtype::Location && header->timestamp + header->expires <= currentTimestamp) { + return reinterpret_cast(header); } } - return WeatherData::Pressure(); + return {}; } WeatherData::AirQuality WeatherService::GetCurrentQuality() const { - return WeatherData::AirQuality(); + uint64_t currentTimestamp = GetCurrentUnixTimestamp(); + for (auto&& header : timeline) { + if (header->eventType == WeatherData::eventtype::AirQuality && header->timestamp + header->expires <= currentTimestamp) { + return reinterpret_cast(header); + } + } + return {}; } size_t WeatherService::GetTimelineLength() const { diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index 995f856..5504ea4 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -77,42 +77,42 @@ namespace Pinetime { * Checks if an event of a certain type exists in the timeline * @return */ - bool HasTimelineEventOfType(const WeatherData::eventtype type) const; + bool HasTimelineEventOfType(WeatherData::eventtype type) const; private: // 00030000-78fc-48fe-8e23-433b3a1942d0 - static constexpr ble_uuid128_t BaseUUID() { - return CharUUID(0x00, 0x00); + static constexpr ble_uuid128_t BaseUuid() { + return CharUuid(0x00, 0x00); } // 0003yyxx-78fc-48fe-8e23-433b3a1942d0 - static constexpr ble_uuid128_t CharUUID(uint8_t x, uint8_t y) { + static 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, 0x03, 0x00}}; } - ble_uuid128_t weatherUUID {BaseUUID()}; + ble_uuid128_t weatherUuid {BaseUuid()}; /** * Just write timeline data here */ - ble_uuid128_t weatherDataCharUUID {CharUUID(0x00, 0x01)}; + ble_uuid128_t weatherDataCharUuid {CharUuid(0x00, 0x01)}; /** * This doesn't take timeline data, * provides some control over it */ - ble_uuid128_t weatherControlCharUUID {CharUUID(0x00, 0x02)}; + ble_uuid128_t weatherControlCharUuid {CharUuid(0x00, 0x02)}; const struct ble_gatt_chr_def characteristicDefinition[3] = { - {.uuid = &weatherDataCharUUID.u, + {.uuid = &weatherDataCharUuid.u, .access_cb = WeatherCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE, .val_handle = &eventHandle}, - {.uuid = &weatherControlCharUUID.u, .access_cb = WeatherCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}, + {.uuid = &weatherControlCharUuid.u, .access_cb = WeatherCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ}, {nullptr}}; const struct ble_gatt_svc_def serviceDefinition[2] = { - {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &weatherUUID.u, .characteristics = characteristicDefinition}, {0}}; + {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &weatherUuid.u, .characteristics = characteristicDefinition}, {0}}; uint16_t eventHandle {}; diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp index a127864..ea96c9f 100644 --- a/src/displayapp/screens/Weather.cpp +++ b/src/displayapp/screens/Weather.cpp @@ -105,7 +105,6 @@ bool sortById(const TaskStatus_t& lhs, const TaskStatus_t& rhs) { } std::unique_ptr Weather::CreateScreen4() { - TaskStatus_t tasksStatus[7]; lv_obj_t* infoTask = lv_table_create(lv_scr_act(), nullptr); lv_table_set_col_cnt(infoTask, 3); lv_table_set_row_cnt(infoTask, 8); @@ -118,19 +117,6 @@ std::unique_ptr Weather::CreateScreen4() { lv_table_set_cell_value(infoTask, 0, 2, "Free"); lv_table_set_col_width(infoTask, 2, 90); - auto nb = uxTaskGetSystemState(tasksStatus, 7, 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()); - lv_table_set_cell_value(infoTask, i + 1, 1, tasksStatus[i].pcTaskName); - if (tasksStatus[i].usStackHighWaterMark < 20) { - std::string str1 = std::to_string(tasksStatus[i].usStackHighWaterMark) + " low"; - lv_table_set_cell_value(infoTask, i + 1, 2, str1.c_str()); - } else { - lv_table_set_cell_value(infoTask, i + 1, 2, std::to_string(tasksStatus[i].usStackHighWaterMark).c_str()); - } - } return std::unique_ptr(new Screens::Label(3, 5, app, infoTask)); } @@ -148,4 +134,4 @@ std::unique_ptr Weather::CreateScreen5() { lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); return std::unique_ptr(new Screens::Label(4, 5, app, label)); -} \ No newline at end of file +} -- cgit v0.10.2 From ffb17357e74fd80a0381361a5cbc6bc481d28000 Mon Sep 17 00:00:00 2001 From: Avamander Date: Sun, 28 Nov 2021 15:33:06 +0200 Subject: Fixed a few compilation errors, fixed UUID. diff --git a/src/components/ble/weather/WeatherData.h b/src/components/ble/weather/WeatherData.h index 9b42400..19b9709 100644 --- a/src/components/ble/weather/WeatherData.h +++ b/src/components/ble/weather/WeatherData.h @@ -250,7 +250,7 @@ namespace Pinetime { class Location : public TimelineHeader { public: /** Location name */ - std::unique_ptr location; + std::string location; /** Altitude relative to sea level in meters */ int16_t altitude; /** Latitude, EPSG:3857 (Google Maps, Openstreetmaps datum) */ @@ -311,7 +311,7 @@ namespace Pinetime { * For chemical compounds use the molecular formula e.g. "NO2", "CO2", "O3" * For pollen use the genus, e.g. "Betula" for birch or "Alternaria" for that mold's spores */ - std::unique_ptr polluter; + std::string polluter; /** * Amount of the pollution in SI units, * otherwise it's going to be difficult to create UI, alerts diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index 22c8083..bbaa21f 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -87,7 +87,7 @@ namespace Pinetime { if (UsefulBuf_IsNULLOrEmptyC(String) != 0) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } - airquality->polluter = std::make_unique(static_cast(String.ptr), String.len); + airquality->polluter = std::string(static_cast(String.ptr), String.len); int64_t tmpAmount = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount); if (tmpAmount < 0) { diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index 5504ea4..7bf60ee 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -88,7 +88,7 @@ namespace Pinetime { // 0003yyxx-78fc-48fe-8e23-433b3a1942d0 static 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, 0x03, 0x00}}; + .value = {0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, y, x, 0x03, 0x00}}; } ble_uuid128_t weatherUuid {BaseUuid()}; diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp index ea96c9f..025a3bd 100644 --- a/src/displayapp/screens/Weather.cpp +++ b/src/displayapp/screens/Weather.cpp @@ -1,14 +1,26 @@ +/* Copyright (C) 2021 Avamander + + This file is part of InfiniTime. + + InfiniTime is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + InfiniTime is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ #include "Weather.h" #include #include -#include "../DisplayApp.h" #include "Label.h" -#include "Version.h" #include "components/battery/BatteryController.h" #include "components/ble/BleController.h" -#include "components/brightness/BrightnessController.h" -#include "components/datetime/DateTimeController.h" -#include "drivers/Watchdog.h" #include "components/ble/weather/WeatherData.h" using namespace Pinetime::Applications::Screens; @@ -41,11 +53,10 @@ Weather::~Weather() { lv_obj_clean(lv_scr_act()); } -bool Weather::Refresh() { +void Weather::Refresh() { if (running) { - screens.Refresh(); + // screens.Refresh(); } - return running; } bool Weather::OnButtonPushed() { diff --git a/src/displayapp/screens/Weather.h b/src/displayapp/screens/Weather.h index 469bf59..99cf15b 100644 --- a/src/displayapp/screens/Weather.h +++ b/src/displayapp/screens/Weather.h @@ -16,7 +16,7 @@ namespace Pinetime { ~Weather() override; - bool Refresh() override; + void Refresh() override; bool OnButtonPushed() override; @@ -42,4 +42,4 @@ namespace Pinetime { }; } } -} \ No newline at end of file +} -- cgit v0.10.2 From 657dc3a9ba21039cc9abd3c40c68aa3e810bd074 Mon Sep 17 00:00:00 2001 From: Avamander Date: Sun, 28 Nov 2021 19:12:16 +0200 Subject: Changed UUID so it wouldn't conflict with Motion diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index 7bf60ee..43b2ee2 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -80,15 +80,15 @@ namespace Pinetime { bool HasTimelineEventOfType(WeatherData::eventtype type) const; private: - // 00030000-78fc-48fe-8e23-433b3a1942d0 + // 00040000-78fc-48fe-8e23-433b3a1942d0 static constexpr ble_uuid128_t BaseUuid() { return CharUuid(0x00, 0x00); } - // 0003yyxx-78fc-48fe-8e23-433b3a1942d0 + // 0004yyxx-78fc-48fe-8e23-433b3a1942d0 static 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, y, x, 0x03, 0x00}}; + .value = {0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, y, x, 0x04, 0x00}}; } ble_uuid128_t weatherUuid {BaseUuid()}; -- cgit v0.10.2 From 900598a7eeff1a84ccf7d0d7c94ac28a780299d4 Mon Sep 17 00:00:00 2001 From: Avamander Date: Sun, 28 Nov 2021 19:13:03 +0200 Subject: Removed versioning because it's not necessary diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index bbaa21f..135f64d 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -48,18 +48,11 @@ namespace Pinetime { } // Decode QCBORDecodeContext decodeContext; - UsefulBufC encodedCbor; - // TODO: Check, uninit fine? + UsefulBufC encodedCbor = {ctxt->om, OS_MBUF_PKTLEN(ctxt->om)}; QCBORDecode_Init(&decodeContext, encodedCbor, QCBOR_DECODE_MODE_NORMAL); QCBORDecode_EnterMap(&decodeContext, nullptr); // Always encodes to the smallest number of bytes based on the value - int64_t tmpVersion = 0; - QCBORDecode_GetInt64InMapSZ(&decodeContext, "Version", &tmpVersion); - if (tmpVersion != 1) { - // TODO: Return better error? - return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; - } int64_t tmpTimestamp = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", &tmpTimestamp); int64_t tmpExpires = 0; -- cgit v0.10.2 From df04763ab41aad6be8697c377e4b570c3f2fd238 Mon Sep 17 00:00:00 2001 From: Avamander Date: Sun, 28 Nov 2021 19:13:28 +0200 Subject: Fixed recovery build diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f1149ce..cbccb71 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -552,6 +552,7 @@ list(APPEND RECOVERY_SOURCE_FILES components/ble/CurrentTimeService.cpp components/ble/AlertNotificationService.cpp components/ble/MusicService.cpp + components/ble/weather/WeatherService.cpp components/ble/BatteryInformationService.cpp components/ble/ImmediateAlertService.cpp components/ble/ServiceDiscovery.cpp @@ -951,7 +952,7 @@ endif() set(EXECUTABLE_RECOVERY_NAME "pinetime-recovery") set(EXECUTABLE_RECOVERY_FILE_NAME ${EXECUTABLE_RECOVERY_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}) add_executable(${EXECUTABLE_RECOVERY_NAME} ${RECOVERY_SOURCE_FILES}) -target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk littlefs) +target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk littlefs QCBOR) set_target_properties(${EXECUTABLE_RECOVERY_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_FILE_NAME}) target_compile_definitions(${EXECUTABLE_RECOVERY_NAME} PUBLIC "PINETIME_IS_RECOVERY") target_compile_options(${EXECUTABLE_RECOVERY_NAME} PUBLIC -- cgit v0.10.2 From 48beb7c3b18bcfdc369a63be5923a35a2113aa36 Mon Sep 17 00:00:00 2001 From: Avamander Date: Sun, 28 Nov 2021 20:58:28 +0200 Subject: Improved error handling and fixed incompatibility with co.nstant.in:cbor library diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cbccb71..9f3b6d4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -859,7 +859,7 @@ target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_FLOAT_HW_USE) target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_PREFERRED_FLOAT) target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_EXP_AND_MANTISSA) target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_INDEFINITE_LENGTH_STRINGS) -target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS) +#target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_INDEFINITE_LENGTH_ARRAYS) target_compile_definitions(QCBOR PUBLIC QCBOR_DISABLE_UNCOMMON_TAGS) target_compile_definitions(QCBOR PUBLIC USEFULBUF_CONFIG_LITTLE_ENDIAN) set_target_properties(QCBOR PROPERTIES LINKER_LANGUAGE C) @@ -889,10 +889,10 @@ add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES}) set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_FILE_NAME}) target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl littlefs QCBOR) target_compile_options(${EXECUTABLE_NAME} PUBLIC - $<$,$>: ${COMMON_FLAGS} -Og -g3> - $<$,$>: ${COMMON_FLAGS} -Os> - $<$,$>: ${COMMON_FLAGS} -Og -g3 -fno-rtti> - $<$,$>: ${COMMON_FLAGS} -Os -fno-rtti> + $<$,$>: ${COMMON_FLAGS} -Wextra -Wformat -Wno-missing-field-initializers -Wno-unused-parameter -Og -g3> + $<$,$>: ${COMMON_FLAGS} -Wextra -Wformat -Wno-missing-field-initializers -Wno-unused-parameter -Os> + $<$,$>: ${COMMON_FLAGS} -Wextra -Wformat -Wno-missing-field-initializers -Wno-unused-parameter -Og -g3 -fno-rtti> + $<$,$>: ${COMMON_FLAGS} -Wextra -Wformat -Wno-missing-field-initializers -Wno-unused-parameter -Os -fno-rtti> $<$: -MP -MD -x assembler-with-cpp> ) diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index 135f64d..4230261 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -48,13 +48,17 @@ namespace Pinetime { } // Decode QCBORDecodeContext decodeContext; - UsefulBufC encodedCbor = {ctxt->om, OS_MBUF_PKTLEN(ctxt->om)}; + UsefulBufC encodedCbor = {ctxt->om->om_data, OS_MBUF_PKTLEN(ctxt->om)}; QCBORDecode_Init(&decodeContext, encodedCbor, QCBOR_DECODE_MODE_NORMAL); + // KINDLY provide us a fixed-length map QCBORDecode_EnterMap(&decodeContext, nullptr); // Always encodes to the smallest number of bytes based on the value int64_t tmpTimestamp = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", &tmpTimestamp); + if (QCBORDecode_GetError(&decodeContext) != QCBOR_SUCCESS) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } int64_t tmpExpires = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", &tmpExpires); if (tmpExpires < 0 || tmpExpires > 4294967295) { @@ -173,8 +177,7 @@ namespace Pinetime { GetTimelineLength(); QCBORDecode_ExitMap(&decodeContext); - auto uErr = QCBORDecode_Finish(&decodeContext); - if (uErr != 0) { + if (QCBORDecode_Finish(&decodeContext) != QCBOR_SUCCESS) { return BLE_ATT_ERR_INSUFFICIENT_RES; } } else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) { -- cgit v0.10.2 From c870f8ed302823e12018aa196d87937c92966d06 Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 1 Dec 2021 00:45:28 +0200 Subject: Bunch of bugs fixed, improved error handling, debug UI addition diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index 4230261..4ec57d0 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -28,6 +28,7 @@ namespace Pinetime { namespace Controllers { WeatherService::WeatherService(System::SystemTask& system, DateTime& dateTimeController) : system(system), dateTimeController(dateTimeController) { + nullHeader = &nullTimelineheader; } void WeatherService::Init() { @@ -42,7 +43,7 @@ namespace Pinetime { int WeatherService::OnCommand(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt) { // TODO: Detect control messages if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { - const auto packetLen = OS_MBUF_PKTLEN(ctxt->om); + const uint8_t packetLen = OS_MBUF_PKTLEN(ctxt->om); if (packetLen <= 0) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } @@ -56,30 +57,28 @@ namespace Pinetime { // Always encodes to the smallest number of bytes based on the value int64_t tmpTimestamp = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", &tmpTimestamp); - if (QCBORDecode_GetError(&decodeContext) != QCBOR_SUCCESS) { + uint8_t err = QCBORDecode_GetError(&decodeContext); + if (err != QCBOR_SUCCESS) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } int64_t tmpExpires = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", &tmpExpires); if (tmpExpires < 0 || tmpExpires > 4294967295) { - // TODO: Return better error? return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } int64_t tmpEventType = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "EventType", &tmpEventType); if (tmpEventType < 0 || tmpEventType > static_cast(WeatherData::eventtype::Length)) { - // TODO: Return better error? return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } switch (static_cast(tmpEventType)) { - // TODO: Populate case WeatherData::eventtype::AirQuality: { std::unique_ptr airquality = std::make_unique(); airquality->timestamp = tmpTimestamp; airquality->eventType = static_cast(tmpEventType); airquality->expires = tmpExpires; - UsefulBufC String; + UsefulBufC String; // TODO: Everything ok with lifecycle here? QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Polluter", &String); if (UsefulBuf_IsNULLOrEmptyC(String) != 0) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; @@ -172,10 +171,9 @@ namespace Pinetime { } } - GetCurrentPressure(); - TidyTimeline(); - GetTimelineLength(); QCBORDecode_ExitMap(&decodeContext); + GetTimelineLength(); + TidyTimeline(); if (QCBORDecode_Finish(&decodeContext) != QCBOR_SUCCESS) { return BLE_ATT_ERR_INSUFFICIENT_RES; @@ -205,94 +203,103 @@ namespace Pinetime { return 0; } - WeatherData::Clouds WeatherService::GetCurrentClouds() const { + std::unique_ptr& WeatherService::GetCurrentClouds() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); - for (auto&& header : timeline) { - if (header->eventType == WeatherData::eventtype::Clouds && header->timestamp + header->expires <= currentTimestamp) { - return reinterpret_cast(header); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Clouds && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast&>(header); } } - return {}; + + return reinterpret_cast&>(this->nullHeader); } - WeatherData::Obscuration WeatherService::GetCurrentObscuration() const { + std::unique_ptr& WeatherService::GetCurrentObscuration() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); - for (auto&& header : timeline) { - if (header->eventType == WeatherData::eventtype::Obscuration && header->timestamp + header->expires <= currentTimestamp) { - return reinterpret_cast(header); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Obscuration && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast&>(header); } } - return {}; + + return reinterpret_cast&>(this->nullHeader); } - WeatherData::Precipitation WeatherService::GetCurrentPrecipitation() const { + std::unique_ptr& WeatherService::GetCurrentPrecipitation() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); - for (auto&& header : timeline) { - if (header->eventType == WeatherData::eventtype::Precipitation && header->timestamp + header->expires <= currentTimestamp) { - return reinterpret_cast(header); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Precipitation && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast&>(header); } } - return {}; + + return reinterpret_cast&>(this->nullHeader); } - WeatherData::Wind WeatherService::GetCurrentWind() const { + std::unique_ptr& WeatherService::GetCurrentWind() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); - for (auto&& header : timeline) { - if (header->eventType == WeatherData::eventtype::Wind && header->timestamp + header->expires <= currentTimestamp) { - return reinterpret_cast(header); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Wind && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast&>(header); } } - return {}; + + return reinterpret_cast&>(this->nullHeader); } - WeatherData::Temperature WeatherService::GetCurrentTemperature() const { + std::unique_ptr& WeatherService::GetCurrentTemperature() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); - for (auto&& header : timeline) { - if (header->eventType == WeatherData::eventtype::Temperature && header->timestamp + header->expires <= currentTimestamp) { - return reinterpret_cast(header); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Temperature && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast&>(header); } } - return {}; + + return reinterpret_cast&>(this->nullHeader); } - WeatherData::Humidity WeatherService::GetCurrentHumidity() const { + std::unique_ptr& WeatherService::GetCurrentHumidity() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); - for (auto&& header : timeline) { - if (header->eventType == WeatherData::eventtype::Humidity && header->timestamp + header->expires <= currentTimestamp) { - return reinterpret_cast(header); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Humidity && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast&>(header); } } - return {}; + + return reinterpret_cast&>(this->nullHeader); } - WeatherData::Pressure WeatherService::GetCurrentPressure() const { + std::unique_ptr& WeatherService::GetCurrentPressure() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); - for (auto&& header : timeline) { - if (header->eventType == WeatherData::eventtype::Pressure && header->timestamp + header->expires <= currentTimestamp) { - return reinterpret_cast(header); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Pressure && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast&>(header); } } - return {}; + + return reinterpret_cast&>(this->nullHeader); } - WeatherData::Location WeatherService::GetCurrentLocation() const { + std::unique_ptr& WeatherService::GetCurrentLocation() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); - for (auto&& header : timeline) { - if (header->eventType == WeatherData::eventtype::Location && header->timestamp + header->expires <= currentTimestamp) { - return reinterpret_cast(header); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::Location && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast&>(header); } } - return {}; + + return reinterpret_cast&>(this->nullHeader); } - WeatherData::AirQuality WeatherService::GetCurrentQuality() const { + std::unique_ptr& WeatherService::GetCurrentQuality() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); - for (auto&& header : timeline) { - if (header->eventType == WeatherData::eventtype::AirQuality && header->timestamp + header->expires <= currentTimestamp) { - return reinterpret_cast(header); + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::AirQuality && isEventStillValid(header, currentTimestamp)) { + return reinterpret_cast&>(header); } } - return {}; + + return reinterpret_cast&>(this->nullHeader); } size_t WeatherService::GetTimelineLength() const { @@ -311,8 +318,7 @@ namespace Pinetime { bool WeatherService::HasTimelineEventOfType(const WeatherData::eventtype type) const { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : timeline) { - if (header->eventType == type && header->timestamp + header->expires <= currentTimestamp) { - // TODO: Check if its currently valid + if (header->eventType == type && isEventStillValid(header, currentTimestamp)) { return true; } } @@ -320,11 +326,11 @@ namespace Pinetime { } void WeatherService::TidyTimeline() { - uint64_t timeCurrent = 0; + uint64_t timeCurrent = GetCurrentUnixTimestamp(); timeline.erase(std::remove_if(std::begin(timeline), std::end(timeline), [&](std::unique_ptr const& header) { - return header->timestamp + header->expires > timeCurrent; + return isEventStillValid(header, timeCurrent); }), std::end(timeline)); @@ -336,6 +342,11 @@ namespace Pinetime { return first->timestamp > second->timestamp; } + bool WeatherService::isEventStillValid(const std::unique_ptr& header, const uint64_t currentTimestamp) { + // Not getting timestamp in isEventStillValid for more speed + return header->timestamp + header->expires <= currentTimestamp; + } + uint64_t WeatherService::GetCurrentUnixTimestamp() const { return std::chrono::duration_cast(dateTimeController.CurrentDateTime().time_since_epoch()).count(); } diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index 43b2ee2..7accc49 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -51,15 +51,15 @@ namespace Pinetime { /* * Helper functions for quick access to currently valid data */ - WeatherData::Location GetCurrentLocation() const; - WeatherData::Clouds GetCurrentClouds() const; - WeatherData::Obscuration GetCurrentObscuration() const; - WeatherData::Precipitation GetCurrentPrecipitation() const; - WeatherData::Wind GetCurrentWind() const; - WeatherData::Temperature GetCurrentTemperature() const; - WeatherData::Humidity GetCurrentHumidity() const; - WeatherData::Pressure GetCurrentPressure() const; - WeatherData::AirQuality GetCurrentQuality() const; + std::unique_ptr& GetCurrentLocation(); + std::unique_ptr& GetCurrentClouds(); + std::unique_ptr& GetCurrentObscuration(); + std::unique_ptr& GetCurrentPrecipitation(); + std::unique_ptr& GetCurrentWind(); + std::unique_ptr& GetCurrentTemperature(); + std::unique_ptr& GetCurrentHumidity(); + std::unique_ptr& GetCurrentPressure(); + std::unique_ptr& GetCurrentQuality(); /* * Management functions @@ -123,7 +123,6 @@ namespace Pinetime { /** * Cleans up the timeline of expired events - * @return result code */ void TidyTimeline(); @@ -137,6 +136,18 @@ namespace Pinetime { * Returns current UNIX timestamp */ uint64_t GetCurrentUnixTimestamp() const; + + /** + * Checks if the event hasn't gone past and expired + * + * @param header timeline event to check + * @param currentTimestamp what's the time right now + * @return if the event is valid + */ + static bool isEventStillValid(const std::unique_ptr& uniquePtr, const uint64_t timestamp); + + std::unique_ptr nullTimelineheader = std::make_unique(); + std::unique_ptr* nullHeader; }; } } diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index d340efe..1cf7e2a 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -25,6 +25,7 @@ namespace Pinetime { Metronome, Motion, Steps, + Weather, QuickSettings, Settings, SettingWatchFace, diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp index 025a3bd..132bee7 100644 --- a/src/displayapp/screens/Weather.cpp +++ b/src/displayapp/screens/Weather.cpp @@ -35,16 +35,16 @@ Weather::Weather(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers: return CreateScreenTemperature(); }, [this]() -> std::unique_ptr { - return CreateScreen2(); + return CreateScreenAir(); }, [this]() -> std::unique_ptr { - return CreateScreen3(); + return CreateScreenClouds(); }, [this]() -> std::unique_ptr { - return CreateScreen4(); + return CreateScreenPrecipitation(); }, [this]() -> std::unique_ptr { - return CreateScreen5(); + return CreateScreenHumidity(); }}, Screens::ScreenListModes::UpDown} { } @@ -71,78 +71,108 @@ bool Weather::OnTouchEvent(Pinetime::Applications::TouchEvents event) { std::unique_ptr Weather::CreateScreenTemperature() { lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); lv_label_set_recolor(label, true); - Controllers::WeatherData::Temperature current = weatherService.GetCurrentTemperature(); - lv_label_set_text_fmt(label, - "#FFFF00 Temperature#\n\n" - "#444444 %hd%%#°C \n\n" - "#444444 %hd#\n" - "%llu\n" - "%lu\n", - current.temperature, - current.dewPoint, - current.timestamp, - current.expires); + std::unique_ptr& current = weatherService.GetCurrentTemperature(); + if (current->timestamp == 0) { + // Do not use the data, it's invalid + } else { + lv_label_set_text_fmt(label, + "#FFFF00 Temperature#\n\n" + "#444444 %hd%%#°C \n\n" + "#444444 %hd#\n\n" + "%llu\n" + "%lu\n", + current->temperature, + current->dewPoint, + current->timestamp, + current->expires); + } lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); return std::unique_ptr(new Screens::Label(0, 5, app, label)); } -std::unique_ptr Weather::CreateScreen2() { - // uptime +std::unique_ptr Weather::CreateScreenAir() { lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); lv_label_set_recolor(label, true); - lv_label_set_text_fmt(label, "#444444 Date# %02d\n", dateTimeController.Day()); + std::unique_ptr& current = weatherService.GetCurrentQuality(); + if (current->timestamp == 0) { + // Do not use the data, it's invalid + } else { + lv_label_set_text_fmt(label, + "#FFFF00 Air quality#\n\n" + "#444444 %s#\n" + "#444444 %lu#\n\n" + "%llu\n" + "%lu\n", + current->polluter.c_str(), + current->amount, + current->timestamp, + current->expires); + } + lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); - return std::unique_ptr(new Screens::Label(1, 4, app, label)); + return std::unique_ptr(new Screens::Label(0, 5, app, label)); } -std::unique_ptr Weather::CreateScreen3() { - lv_mem_monitor_t mon; - lv_mem_monitor(&mon); - +std::unique_ptr Weather::CreateScreenClouds() { lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); lv_label_set_recolor(label, true); - lv_label_set_text_fmt(label, - " #444444 frag# %d%%\n" - " #444444 free# %d", - mon.used_pct, - mon.frag_pct); + std::unique_ptr& current = weatherService.GetCurrentClouds(); + if (current->timestamp == 0) { + // Do not use the data, it's invalid + } else { + lv_label_set_text_fmt(label, + "#FFFF00 Clouds#\n\n" + "#444444 %hhu%%#\n\n" + "%llu\n" + "%lu\n", + current->amount, + current->timestamp, + current->expires); + } + lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); - return std::unique_ptr(new Screens::Label(2, 5, app, label)); -} - -bool sortById(const TaskStatus_t& lhs, const TaskStatus_t& rhs) { - return lhs.xTaskNumber < rhs.xTaskNumber; + return std::unique_ptr(new Screens::Label(0, 5, app, label)); } -std::unique_ptr Weather::CreateScreen4() { - lv_obj_t* infoTask = lv_table_create(lv_scr_act(), nullptr); - lv_table_set_col_cnt(infoTask, 3); - lv_table_set_row_cnt(infoTask, 8); - lv_obj_set_pos(infoTask, 10, 10); - - lv_table_set_cell_value(infoTask, 0, 0, "#"); - lv_table_set_col_width(infoTask, 0, 50); - lv_table_set_cell_value(infoTask, 0, 1, "Task"); - lv_table_set_col_width(infoTask, 1, 80); - lv_table_set_cell_value(infoTask, 0, 2, "Free"); - lv_table_set_col_width(infoTask, 2, 90); - - return std::unique_ptr(new Screens::Label(3, 5, app, infoTask)); +std::unique_ptr Weather::CreateScreenPrecipitation() { + lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); + lv_label_set_recolor(label, true); + std::unique_ptr& current = weatherService.GetCurrentPrecipitation(); + if (current->timestamp == 0) { + // Do not use the data, it's invalid + } else { + lv_label_set_text_fmt(label, + "#FFFF00 Precipitation#\n\n" + "#444444 %hhu%%#\n\n" + "%llu\n" + "%lu\n", + current->amount, + current->timestamp, + current->expires); + } + lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); + lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); + return std::unique_ptr(new Screens::Label(0, 5, app, label)); } -std::unique_ptr Weather::CreateScreen5() { +std::unique_ptr Weather::CreateScreenHumidity() { lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr); lv_label_set_recolor(label, true); - lv_label_set_text_static(label, - "Software Licensed\n" - "under the terms of\n" - "the GNU General\n" - "Public License v3\n" - "#444444 Source code#\n" - "#FFFF00 https://github.com/#\n" - "#FFFF00 JF002/InfiniTime#"); + std::unique_ptr& current = weatherService.GetCurrentHumidity(); + if (current->timestamp == 0) { + // Do not use the data, it's invalid + } else { + lv_label_set_text_fmt(label, + "#FFFF00 Humidity#\n\n" + "#444444 %hhu%%#\n\n" + "%llu\n" + "%lu\n", + current->humidity, + current->timestamp, + current->expires); + } lv_label_set_align(label, LV_LABEL_ALIGN_CENTER); lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0); - return std::unique_ptr(new Screens::Label(4, 5, app, label)); + return std::unique_ptr(new Screens::Label(0, 5, app, label)); } diff --git a/src/displayapp/screens/Weather.h b/src/displayapp/screens/Weather.h index 99cf15b..34f95fc 100644 --- a/src/displayapp/screens/Weather.h +++ b/src/displayapp/screens/Weather.h @@ -32,13 +32,13 @@ namespace Pinetime { std::unique_ptr CreateScreenTemperature(); - std::unique_ptr CreateScreen2(); + std::unique_ptr CreateScreenAir(); - std::unique_ptr CreateScreen3(); + std::unique_ptr CreateScreenClouds(); - std::unique_ptr CreateScreen4(); + std::unique_ptr CreateScreenPrecipitation(); - std::unique_ptr CreateScreen5(); + std::unique_ptr CreateScreenHumidity(); }; } } -- cgit v0.10.2 From 06b022fc4dd6c2b1e5145e111f5c1f32e4729eab Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 1 Dec 2021 01:15:11 +0200 Subject: Improved UI and fixed a bug diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index 4ec57d0..250b36a 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -29,6 +29,7 @@ namespace Pinetime { WeatherService::WeatherService(System::SystemTask& system, DateTime& dateTimeController) : system(system), dateTimeController(dateTimeController) { nullHeader = &nullTimelineheader; + nullTimelineheader->timestamp = 0; } void WeatherService::Init() { @@ -211,7 +212,7 @@ namespace Pinetime { } } - return reinterpret_cast&>(this->nullHeader); + return reinterpret_cast&>(*this->nullHeader); } std::unique_ptr& WeatherService::GetCurrentObscuration() { @@ -222,7 +223,7 @@ namespace Pinetime { } } - return reinterpret_cast&>(this->nullHeader); + return reinterpret_cast&>(*this->nullHeader); } std::unique_ptr& WeatherService::GetCurrentPrecipitation() { @@ -233,7 +234,7 @@ namespace Pinetime { } } - return reinterpret_cast&>(this->nullHeader); + return reinterpret_cast&>(*this->nullHeader); } std::unique_ptr& WeatherService::GetCurrentWind() { @@ -244,7 +245,7 @@ namespace Pinetime { } } - return reinterpret_cast&>(this->nullHeader); + return reinterpret_cast&>(*this->nullHeader); } std::unique_ptr& WeatherService::GetCurrentTemperature() { @@ -255,7 +256,7 @@ namespace Pinetime { } } - return reinterpret_cast&>(this->nullHeader); + return reinterpret_cast&>(*this->nullHeader); } std::unique_ptr& WeatherService::GetCurrentHumidity() { @@ -266,7 +267,7 @@ namespace Pinetime { } } - return reinterpret_cast&>(this->nullHeader); + return reinterpret_cast&>(*this->nullHeader); } std::unique_ptr& WeatherService::GetCurrentPressure() { @@ -277,7 +278,7 @@ namespace Pinetime { } } - return reinterpret_cast&>(this->nullHeader); + return reinterpret_cast&>(*this->nullHeader); } std::unique_ptr& WeatherService::GetCurrentLocation() { @@ -288,7 +289,7 @@ namespace Pinetime { } } - return reinterpret_cast&>(this->nullHeader); + return reinterpret_cast&>(*this->nullHeader); } std::unique_ptr& WeatherService::GetCurrentQuality() { @@ -299,7 +300,7 @@ namespace Pinetime { } } - return reinterpret_cast&>(this->nullHeader); + return reinterpret_cast&>(*this->nullHeader); } size_t WeatherService::GetTimelineLength() const { @@ -330,7 +331,7 @@ namespace Pinetime { timeline.erase(std::remove_if(std::begin(timeline), std::end(timeline), [&](std::unique_ptr const& header) { - return isEventStillValid(header, timeCurrent); + return !isEventStillValid(header, timeCurrent); }), std::end(timeline)); diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp index 132bee7..0854c74 100644 --- a/src/displayapp/screens/Weather.cpp +++ b/src/displayapp/screens/Weather.cpp @@ -74,6 +74,16 @@ std::unique_ptr Weather::CreateScreenTemperature() { std::unique_ptr& current = weatherService.GetCurrentTemperature(); if (current->timestamp == 0) { // Do not use the data, it's invalid + lv_label_set_text_fmt(label, + "#FFFF00 Temperature#\n\n" + "#444444 %d#\n\n" + "#444444 %d#\n\n" + "%d\n" + "%d\n", + 0, + 0, + 0, + 0); } else { lv_label_set_text_fmt(label, "#FFFF00 Temperature#\n\n" @@ -97,6 +107,16 @@ std::unique_ptr Weather::CreateScreenAir() { std::unique_ptr& current = weatherService.GetCurrentQuality(); if (current->timestamp == 0) { // Do not use the data, it's invalid + lv_label_set_text_fmt(label, + "#FFFF00 Air quality#\n\n" + "#444444 %s#\n" + "#444444 %d#\n\n" + "%d\n" + "%d\n", + "", + 0, + 0, + 0); } else { lv_label_set_text_fmt(label, "#FFFF00 Air quality#\n\n" -- cgit v0.10.2 From 9108952e6ba96f94bbd1530036318c9b21ec0cf9 Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 1 Dec 2021 15:18:34 +0200 Subject: Implemented parsing of all defined weather data types diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index 250b36a..c60e0f0 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -42,15 +42,14 @@ namespace Pinetime { } int WeatherService::OnCommand(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt) { - // TODO: Detect control messages if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) { - const uint8_t packetLen = OS_MBUF_PKTLEN(ctxt->om); + const uint8_t packetLen = OS_MBUF_PKTLEN(ctxt->om); // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) if (packetLen <= 0) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } // Decode QCBORDecodeContext decodeContext; - UsefulBufC encodedCbor = {ctxt->om->om_data, OS_MBUF_PKTLEN(ctxt->om)}; + UsefulBufC encodedCbor = {ctxt->om->om_data, OS_MBUF_PKTLEN(ctxt->om)}; // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) QCBORDecode_Init(&decodeContext, encodedCbor, QCBOR_DECODE_MODE_NORMAL); // KINDLY provide us a fixed-length map @@ -58,18 +57,18 @@ namespace Pinetime { // Always encodes to the smallest number of bytes based on the value int64_t tmpTimestamp = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", &tmpTimestamp); - uint8_t err = QCBORDecode_GetError(&decodeContext); - if (err != QCBOR_SUCCESS) { + if (QCBORDecode_GetError(&decodeContext) != QCBOR_SUCCESS) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } int64_t tmpExpires = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", &tmpExpires); - if (tmpExpires < 0 || tmpExpires > 4294967295) { + if (QCBORDecode_GetError(&decodeContext) != QCBOR_SUCCESS || tmpExpires < 0 || tmpExpires > 4294967295) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } int64_t tmpEventType = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "EventType", &tmpEventType); - if (tmpEventType < 0 || tmpEventType > static_cast(WeatherData::eventtype::Length)) { + if (QCBORDecode_GetError(&decodeContext) != QCBOR_SUCCESS || tmpEventType < 0 || + tmpEventType >= static_cast(WeatherData::eventtype::Length)) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } @@ -79,19 +78,24 @@ namespace Pinetime { airquality->timestamp = tmpTimestamp; airquality->eventType = static_cast(tmpEventType); airquality->expires = tmpExpires; + UsefulBufC String; // TODO: Everything ok with lifecycle here? QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Polluter", &String); if (UsefulBuf_IsNULLOrEmptyC(String) != 0) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } airquality->polluter = std::string(static_cast(String.ptr), String.len); + int64_t tmpAmount = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount); - if (tmpAmount < 0) { + if (tmpAmount < 0 || tmpAmount > 4294967295) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + airquality->amount = tmpAmount; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + + if (AddEventToTimeline(std::move(airquality))) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } - airquality->amount = tmpAmount; - timeline.push_back(std::move(airquality)); break; } case WeatherData::eventtype::Obscuration: { @@ -100,7 +104,23 @@ namespace Pinetime { obscuration->eventType = static_cast(tmpEventType); obscuration->expires = tmpExpires; - timeline.push_back(std::move(obscuration)); + int64_t tmpType = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Type", &tmpType); + if (tmpType < 0 || tmpType >= static_cast(WeatherData::obscurationtype::Length)) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + obscuration->type = static_cast(tmpType); + + int64_t tmpAmount = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount); + if (tmpAmount < 0 || tmpAmount > 65535) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + obscuration->amount = tmpAmount; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + + if (AddEventToTimeline(std::move(obscuration))) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } break; } case WeatherData::eventtype::Precipitation: { @@ -108,7 +128,24 @@ namespace Pinetime { precipitation->timestamp = tmpTimestamp; precipitation->eventType = static_cast(tmpEventType); precipitation->expires = tmpExpires; - timeline.push_back(std::move(precipitation)); + + int64_t tmpType = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Type", &tmpType); + if (tmpType < 0 || tmpType >= static_cast(WeatherData::precipitationtype::Length)) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + precipitation->type = static_cast(tmpType); + + int64_t tmpAmount = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount); + if (tmpAmount < 0 || tmpAmount > 255) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + precipitation->amount = tmpAmount; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + + if (AddEventToTimeline(std::move(precipitation))) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } break; } case WeatherData::eventtype::Wind: { @@ -116,7 +153,38 @@ namespace Pinetime { wind->timestamp = tmpTimestamp; wind->eventType = static_cast(tmpEventType); wind->expires = tmpExpires; - timeline.push_back(std::move(wind)); + + int64_t tmpMin = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "SpeedMin", &tmpMin); + if (tmpMin < 0 || tmpMin > 255) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + wind->speedMin = tmpMin; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + + int64_t tmpMax = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "SpeedMin", &tmpMax); + if (tmpMax < 0 || tmpMax > 255) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + wind->speedMax = tmpMax; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + + int64_t tmpDMin = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "DirectionMin", &tmpDMin); + if (tmpDMin < 0 || tmpDMin > 255) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + wind->directionMin = tmpDMin; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + + int64_t tmpDMax = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "DirectionMax", &tmpDMax); + if (tmpDMax < 0 || tmpDMax > 255) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + wind->directionMax = tmpDMax; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + + if (AddEventToTimeline(std::move(wind))) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } break; } case WeatherData::eventtype::Temperature: { @@ -124,7 +192,24 @@ namespace Pinetime { temperature->timestamp = tmpTimestamp; temperature->eventType = static_cast(tmpEventType); temperature->expires = tmpExpires; - timeline.push_back(std::move(temperature)); + + int64_t tmpTemperature = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Temperature", &tmpTemperature); + if (tmpTemperature < 0 || tmpTemperature > 65535) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + temperature->temperature = tmpTemperature; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + + int64_t tmpDewPoint = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "DewPoint", &tmpDewPoint); + if (tmpDewPoint < 0 || tmpDewPoint > 65535) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + temperature->dewPoint = tmpDewPoint; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + + if (AddEventToTimeline(std::move(temperature))) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } break; } case WeatherData::eventtype::Special: { @@ -132,7 +217,17 @@ namespace Pinetime { special->timestamp = tmpTimestamp; special->eventType = static_cast(tmpEventType); special->expires = tmpExpires; - timeline.push_back(std::move(special)); + + int64_t tmpType = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "DewPoint", &tmpType); + if (tmpType < 0 || tmpType >= static_cast(WeatherData::specialtype::Length)) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + special->type = static_cast(tmpType); + + if (AddEventToTimeline(std::move(special))) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } break; } case WeatherData::eventtype::Pressure: { @@ -140,7 +235,17 @@ namespace Pinetime { pressure->timestamp = tmpTimestamp; pressure->eventType = static_cast(tmpEventType); pressure->expires = tmpExpires; - timeline.push_back(std::move(pressure)); + + int64_t tmpDewPoint = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "DewPoint", &tmpDewPoint); + if (tmpDewPoint < 0 || tmpDewPoint >= 65535) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + pressure->pressure = tmpDewPoint; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + + if (AddEventToTimeline(std::move(pressure))) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } break; } case WeatherData::eventtype::Location: { @@ -148,7 +253,38 @@ namespace Pinetime { location->timestamp = tmpTimestamp; location->eventType = static_cast(tmpEventType); location->expires = tmpExpires; - timeline.push_back(std::move(location)); + + UsefulBufC stringBuf; // TODO: Everything ok with lifecycle here? + QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Location", &stringBuf); + if (UsefulBuf_IsNULLOrEmptyC(stringBuf) != 0) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + location->location = std::string(static_cast(stringBuf.ptr), stringBuf.len); + + int64_t tmpAltitude = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Altitude", &tmpAltitude); + if (tmpAltitude < -32768 || tmpAltitude >= 32767) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + location->altitude = static_cast(tmpAltitude); + + int64_t tmpLatitude = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Latitude", &tmpLatitude); + if (tmpLatitude < -2147483648 || tmpLatitude >= 2147483647) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + location->latitude = static_cast(tmpLatitude); + + int64_t tmpLongitude = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Longitude", &tmpLongitude); + if (tmpLongitude < -2147483648 || tmpLongitude >= 2147483647) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + location->latitude = static_cast(tmpLongitude); + + if (AddEventToTimeline(std::move(location))) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } break; } case WeatherData::eventtype::Clouds: { @@ -156,7 +292,17 @@ namespace Pinetime { clouds->timestamp = tmpTimestamp; clouds->eventType = static_cast(tmpEventType); clouds->expires = tmpExpires; - timeline.push_back(std::move(clouds)); + + int64_t tmpAmount = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount); + if (tmpAmount < 0 || tmpAmount > 255) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + clouds->amount = static_cast(tmpAmount); + + if (AddEventToTimeline(std::move(clouds))) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } break; } case WeatherData::eventtype::Humidity: { @@ -164,7 +310,17 @@ namespace Pinetime { humidity->timestamp = tmpTimestamp; humidity->eventType = static_cast(tmpEventType); humidity->expires = tmpExpires; - timeline.push_back(std::move(humidity)); + + int64_t tmpType = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "DewPoint", &tmpType); + if (tmpType < 0 || tmpType >= 255) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } + humidity->humidity = static_cast(tmpType); + + if (AddEventToTimeline(std::move(humidity))) { + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; + } break; } default: { @@ -183,6 +339,12 @@ namespace Pinetime { // Encode uint8_t buffer[64]; QCBOREncodeContext encodeContext; + /* TODO: This is very much still a test endpoint + * it needs a characteristic UUID check + * and actual implementations that show + * what actually has to be read. + * WARN: Consider commands not part of the API for now! + */ QCBOREncode_Init(&encodeContext, UsefulBuf_FROM_BYTE_ARRAY(buffer)); QCBOREncode_OpenMap(&encodeContext); QCBOREncode_AddTextToMap(&encodeContext, "test", UsefulBuf_FROM_SZ_LITERAL("test")); -- cgit v0.10.2 From cccec6e1abc8b7180d9e69c22c50fe9244b48ebc Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 1 Dec 2021 15:50:36 +0200 Subject: Improved debug UI. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9f3b6d4..ac91c0c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -892,7 +892,7 @@ target_compile_options(${EXECUTABLE_NAME} PUBLIC $<$,$>: ${COMMON_FLAGS} -Wextra -Wformat -Wno-missing-field-initializers -Wno-unused-parameter -Og -g3> $<$,$>: ${COMMON_FLAGS} -Wextra -Wformat -Wno-missing-field-initializers -Wno-unused-parameter -Os> $<$,$>: ${COMMON_FLAGS} -Wextra -Wformat -Wno-missing-field-initializers -Wno-unused-parameter -Og -g3 -fno-rtti> - $<$,$>: ${COMMON_FLAGS} -Wextra -Wformat -Wno-missing-field-initializers -Wno-unused-parameter -Os -fno-rtti> + $<$,$>: ${COMMON_FLAGS} -Wextra -Wformat -Wno-missing-field-initializers -Wno-unused-parameter -O1 -g3 -fno-rtti> $<$: -MP -MD -x assembler-with-cpp> ) diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp index 0854c74..c9852ee 100644 --- a/src/displayapp/screens/Weather.cpp +++ b/src/displayapp/screens/Weather.cpp @@ -140,6 +140,14 @@ std::unique_ptr Weather::CreateScreenClouds() { std::unique_ptr& current = weatherService.GetCurrentClouds(); if (current->timestamp == 0) { // Do not use the data, it's invalid + lv_label_set_text_fmt(label, + "#FFFF00 Clouds#\n\n" + "#444444 %d%%#\n\n" + "%d\n" + "%d\n", + 0, + 0, + 0); } else { lv_label_set_text_fmt(label, "#FFFF00 Clouds#\n\n" @@ -161,6 +169,14 @@ std::unique_ptr Weather::CreateScreenPrecipitation() { std::unique_ptr& current = weatherService.GetCurrentPrecipitation(); if (current->timestamp == 0) { // Do not use the data, it's invalid + lv_label_set_text_fmt(label, + "#FFFF00 Precipitation#\n\n" + "#444444 %d%%#\n\n" + "%d\n" + "%d\n", + 0, + 0, + 0); } else { lv_label_set_text_fmt(label, "#FFFF00 Precipitation#\n\n" @@ -182,6 +198,14 @@ std::unique_ptr Weather::CreateScreenHumidity() { std::unique_ptr& current = weatherService.GetCurrentHumidity(); if (current->timestamp == 0) { // Do not use the data, it's invalid + lv_label_set_text_fmt(label, + "#FFFF00 Humidity#\n\n" + "#444444 %d%%#\n\n" + "%d\n" + "%d\n", + 0, + 0, + 0); } else { lv_label_set_text_fmt(label, "#FFFF00 Humidity#\n\n" -- cgit v0.10.2 From 75cf5324baf760b3f463ba84126c317471266b32 Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 1 Dec 2021 18:41:01 +0200 Subject: Fixed an incorrect decode in Humidity diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index c60e0f0..c2a1cec 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -312,7 +312,7 @@ namespace Pinetime { humidity->expires = tmpExpires; int64_t tmpType = 0; - QCBORDecode_GetInt64InMapSZ(&decodeContext, "DewPoint", &tmpType); + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Humidity", &tmpType); if (tmpType < 0 || tmpType >= 255) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } -- cgit v0.10.2 From abbfb92fa2039754c45ae10e222ffd6d5bcbd778 Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 1 Dec 2021 18:41:26 +0200 Subject: Added new precipitation and obscuration types diff --git a/src/components/ble/weather/WeatherData.h b/src/components/ble/weather/WeatherData.h index 19b9709..8f5ef8e 100644 --- a/src/components/ble/weather/WeatherData.h +++ b/src/components/ble/weather/WeatherData.h @@ -51,6 +51,8 @@ namespace Pinetime { Sand = 6, /** Water particles suspended in the air; low-ish visibility; temperature is near dewpoint */ Mist = 7, + /** This is SPECIAL in the sense that the thing raining down is doing the obscuration */ + Precipitation = 8, Length }; @@ -84,6 +86,8 @@ namespace Pinetime { SnowGrains = 8, /** Needles; columns or plates of ice. Sometimes described as "diamond dust". In very cold regions */ IceCrystals = 9, + /** It's raining down ash, e.g. from a volcano */ + Ash = 10, Length }; @@ -230,9 +234,15 @@ namespace Pinetime { */ class Temperature : public TimelineHeader { public: - /** Temperature °C but multiplied by 100 (e.g. -12.50°C becomes -1250) */ + /** + * Temperature °C but multiplied by 100 (e.g. -12.50°C becomes -1250) + * -32768 is reserved for "no data" + */ int16_t temperature; - /** Dewpoint °C but multiplied by 100 (e.g. -12.50°C becomes -1250) */ + /** + * Dewpoint °C but multiplied by 100 (e.g. -12.50°C becomes -1250) + * -32768 is reserved for "no data" + */ int16_t dewPoint; }; -- cgit v0.10.2 From b998d5e2a85415e86ac47fd60198bf46ae54e424 Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 1 Dec 2021 18:43:23 +0200 Subject: Removed unnecessary change in CMakeLists diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ac91c0c..9f3b6d4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -892,7 +892,7 @@ target_compile_options(${EXECUTABLE_NAME} PUBLIC $<$,$>: ${COMMON_FLAGS} -Wextra -Wformat -Wno-missing-field-initializers -Wno-unused-parameter -Og -g3> $<$,$>: ${COMMON_FLAGS} -Wextra -Wformat -Wno-missing-field-initializers -Wno-unused-parameter -Os> $<$,$>: ${COMMON_FLAGS} -Wextra -Wformat -Wno-missing-field-initializers -Wno-unused-parameter -Og -g3 -fno-rtti> - $<$,$>: ${COMMON_FLAGS} -Wextra -Wformat -Wno-missing-field-initializers -Wno-unused-parameter -O1 -g3 -fno-rtti> + $<$,$>: ${COMMON_FLAGS} -Wextra -Wformat -Wno-missing-field-initializers -Wno-unused-parameter -Os -fno-rtti> $<$: -MP -MD -x assembler-with-cpp> ) -- cgit v0.10.2 From 9525fc427321ad209de657e837c47db5237912b9 Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 1 Dec 2021 20:54:13 +0200 Subject: Specified how values should be interpreted better diff --git a/src/components/ble/weather/WeatherData.h b/src/components/ble/weather/WeatherData.h index 8f5ef8e..195e502 100644 --- a/src/components/ble/weather/WeatherData.h +++ b/src/components/ble/weather/WeatherData.h @@ -190,7 +190,10 @@ namespace Pinetime { public: /** Type */ obscurationtype type; - /** Visibility distance in meters */ + /** + * Visibility distance in meters + * 65535 is reserved for unspecified + */ uint16_t amount; }; @@ -199,7 +202,9 @@ namespace Pinetime { public: /** Type */ precipitationtype type; - /** How much is it going to rain? In millimeters */ + /** How much is it going to rain? In millimeters + * 255 is reserved for unspecified + **/ uint8_t amount; }; -- cgit v0.10.2 From b72c6a5bc97c786a295136742d89e6c14e1ccd72 Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 1 Dec 2021 21:08:57 +0200 Subject: Clarified a few comments diff --git a/src/components/ble/weather/WeatherData.h b/src/components/ble/weather/WeatherData.h index 195e502..73b15ca 100644 --- a/src/components/ble/weather/WeatherData.h +++ b/src/components/ble/weather/WeatherData.h @@ -188,7 +188,7 @@ namespace Pinetime { /** Specifies how obscuration is stored */ class Obscuration : public TimelineHeader { public: - /** Type */ + /** Type of precipitation */ obscurationtype type; /** * Visibility distance in meters @@ -200,9 +200,10 @@ namespace Pinetime { /** Specifies how precipitation is stored */ class Precipitation : public TimelineHeader { public: - /** Type */ + /** Type of precipitation */ precipitationtype type; - /** How much is it going to rain? In millimeters + /** + * How much is it going to rain? In millimeters * 255 is reserved for unspecified **/ uint8_t amount; @@ -235,7 +236,7 @@ namespace Pinetime { * As it's annoying to figure out the dewpoint on the watch, * please send it from the companion * - * We don't do floats, microdegrees are not useful. Make sure to multiply. + * We don't do floats, picodegrees are not useful. Make sure to multiply. */ class Temperature : public TimelineHeader { public: @@ -344,7 +345,7 @@ namespace Pinetime { * ng/m³ for heavy metals * * List is not comprehensive, should be improved. - * The current ones are what watchapps assume. + * The current ones are what watchapps assume! * * Note: ppb and ppm to concentration should be calculated on the companion, using * the correct formula (taking into account temperature and air pressure) -- cgit v0.10.2 From ffd6c3f0953c753b0caf151be1eb824bdd777264 Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 1 Dec 2021 21:11:31 +0200 Subject: Removed an instance of shadowing diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index c2a1cec..e6d22d7 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -79,12 +79,12 @@ namespace Pinetime { airquality->eventType = static_cast(tmpEventType); airquality->expires = tmpExpires; - UsefulBufC String; // TODO: Everything ok with lifecycle here? - QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Polluter", &String); - if (UsefulBuf_IsNULLOrEmptyC(String) != 0) { + UsefulBufC stringBuf; // TODO: Everything ok with lifecycle here? + QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Polluter", &stringBuf); + if (UsefulBuf_IsNULLOrEmptyC(stringBuf) != 0) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } - airquality->polluter = std::string(static_cast(String.ptr), String.len); + airquality->polluter = std::string(static_cast(stringBuf.ptr), stringBuf.len); int64_t tmpAmount = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount); -- cgit v0.10.2 From e0133cec36db56f71a2d9078c927e450ae361817 Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 1 Dec 2021 21:20:51 +0200 Subject: Improved documentation diff --git a/src/components/ble/weather/WeatherData.h b/src/components/ble/weather/WeatherData.h index 73b15ca..d56f481 100644 --- a/src/components/ble/weather/WeatherData.h +++ b/src/components/ble/weather/WeatherData.h @@ -20,6 +20,24 @@ /** * Different weather events, weather data structures used by {@link WeatherService.h} * + * How to upload events to the timeline? + * + * All timeline write payloads are simply CBOR-encoded payloads of the structs described below. + * + * All payloads have a mandatory header part and the dynamic part that + * depends on the event type specified in the header. If you don't, + * you'll get an error returned. Data is relatively well-validated, + * so keep in the bounds of the data types given. + * + * Write all struct members into a single finite-sized map, and write it to the characteristic. + * Mind the MTU. + * + * How to debug? + * + * There's a Screen that you can compile into your firmware that shows currently valid events. + * You can adapt that to display something else. That part right now is very much work in progress + * because the exact requirements are not yet known. + * * * Implemented based on and other material: * https://en.wikipedia.org/wiki/METAR @@ -152,6 +170,8 @@ namespace Pinetime { /** * Valid event query + * + * NOTE: Not currently available, until needs are better known */ class ValidEventQuery { public: -- cgit v0.10.2 From 797b60397c630ac93dcff1bf7cef268c20747fb3 Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 1 Dec 2021 21:24:53 +0200 Subject: Improved documentation diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index 7accc49..cc1a4b0 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -94,12 +94,16 @@ namespace Pinetime { ble_uuid128_t weatherUuid {BaseUuid()}; /** - * Just write timeline data here + * Just write timeline data here. + * + * See {@link WeatherData.h} for more information. */ ble_uuid128_t weatherDataCharUuid {CharUuid(0x00, 0x01)}; /** - * This doesn't take timeline data, - * provides some control over it + * This doesn't take timeline data, provides some control over it. + * + * NOTE: Currently not supported. Companion app implementer feedback required. + * There's very little point in solidifying an API before we know the needs. */ ble_uuid128_t weatherControlCharUuid {CharUuid(0x00, 0x02)}; -- cgit v0.10.2 From 154e3d27ad0053edf09db6437264028cbca8afd1 Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 1 Dec 2021 23:45:01 +0200 Subject: Added a few helper functions diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index e6d22d7..c8eb3c2 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -513,5 +513,51 @@ namespace Pinetime { uint64_t WeatherService::GetCurrentUnixTimestamp() const { return std::chrono::duration_cast(dateTimeController.CurrentDateTime().time_since_epoch()).count(); } + + int16_t WeatherService::getTodayMinTemp() const { + uint64_t currentTimestamp = GetCurrentUnixTimestamp(); + uint64_t currentDayEnd = currentTimestamp - ((24 - dateTimeController.Hours()) * 60 * 60) - + ((60 - dateTimeController.Minutes()) * 60) - (60 - dateTimeController.Seconds()); + int16_t result = -32768; + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::AirQuality && isEventStillValid(header, currentTimestamp) && + header->timestamp < currentDayEnd && + reinterpret_cast&>(header)->temperature != -32768) { + int16_t temperature = reinterpret_cast&>(header)->temperature; + if (result == -32768) { + result = temperature; + } else if (result > temperature) { + result = temperature; + } else { + // The temperature in this item is higher than the lowest we've found + } + } + } + + return result; + } + + int16_t WeatherService::getTodayMaxTemp() const { + uint64_t currentTimestamp = GetCurrentUnixTimestamp(); + uint64_t currentDayEnd = currentTimestamp - ((24 - dateTimeController.Hours()) * 60 * 60) - + ((60 - dateTimeController.Minutes()) * 60) - (60 - dateTimeController.Seconds()); + int16_t result = -32768; + for (auto&& header : this->timeline) { + if (header->eventType == WeatherData::eventtype::AirQuality && isEventStillValid(header, currentTimestamp) && + header->timestamp < currentDayEnd && + reinterpret_cast&>(header)->temperature != -32768) { + int16_t temperature = reinterpret_cast&>(header)->temperature; + if (result == -32768) { + result = temperature; + } else if (result < temperature) { + result = temperature; + } else { + // The temperature in this item is lower than the highest we've found + } + } + } + + return result; + } } } diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index cc1a4b0..52b0356 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -61,6 +61,17 @@ namespace Pinetime { std::unique_ptr& GetCurrentPressure(); std::unique_ptr& GetCurrentQuality(); + /** + * Searches for the current day's maximum temperature + * @return -32768 if there's no data, degrees celcius times 100 otherwise + */ + int16_t getTodayMaxTemp() const; + /** + * Searches for the current day's minimum temperature + * @return -32768 if there's no data, degrees celcius times 100 otherwise + */ + int16_t getTodayMinTemp() const; + /* * Management functions */ @@ -75,7 +86,6 @@ namespace Pinetime { size_t GetTimelineLength() const; /** * Checks if an event of a certain type exists in the timeline - * @return */ bool HasTimelineEventOfType(WeatherData::eventtype type) const; @@ -124,6 +134,8 @@ namespace Pinetime { Pinetime::Controllers::DateTime& dateTimeController; std::vector> timeline; + std::unique_ptr nullTimelineheader = std::make_unique(); + std::unique_ptr* nullHeader; /** * Cleans up the timeline of expired events @@ -149,9 +161,6 @@ namespace Pinetime { * @return if the event is valid */ static bool isEventStillValid(const std::unique_ptr& uniquePtr, const uint64_t timestamp); - - std::unique_ptr nullTimelineheader = std::make_unique(); - std::unique_ptr* nullHeader; }; } } -- cgit v0.10.2 From be7931c4fb304df077f8a795d1e6e94c522556f7 Mon Sep 17 00:00:00 2001 From: Avamander Date: Wed, 1 Dec 2021 23:47:54 +0200 Subject: Whoops, fixed a wrong type diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index c8eb3c2..c342602 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -520,7 +520,7 @@ namespace Pinetime { ((60 - dateTimeController.Minutes()) * 60) - (60 - dateTimeController.Seconds()); int16_t result = -32768; for (auto&& header : this->timeline) { - if (header->eventType == WeatherData::eventtype::AirQuality && isEventStillValid(header, currentTimestamp) && + if (header->eventType == WeatherData::eventtype::Temperature && isEventStillValid(header, currentTimestamp) && header->timestamp < currentDayEnd && reinterpret_cast&>(header)->temperature != -32768) { int16_t temperature = reinterpret_cast&>(header)->temperature; @@ -543,7 +543,7 @@ namespace Pinetime { ((60 - dateTimeController.Minutes()) * 60) - (60 - dateTimeController.Seconds()); int16_t result = -32768; for (auto&& header : this->timeline) { - if (header->eventType == WeatherData::eventtype::AirQuality && isEventStillValid(header, currentTimestamp) && + if (header->eventType == WeatherData::eventtype::Temperature && isEventStillValid(header, currentTimestamp) && header->timestamp < currentDayEnd && reinterpret_cast&>(header)->temperature != -32768) { int16_t temperature = reinterpret_cast&>(header)->temperature; -- cgit v0.10.2 From 4a8f72bd1e77a387b1fe97d316c0f75d8c94c936 Mon Sep 17 00:00:00 2001 From: Avamander Date: Thu, 2 Dec 2021 21:12:33 +0200 Subject: Fixed a bug in DewPoint decoding diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index c342602..e5d8053 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -202,7 +202,7 @@ namespace Pinetime { int64_t tmpDewPoint = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "DewPoint", &tmpDewPoint); - if (tmpDewPoint < 0 || tmpDewPoint > 65535) { + if (tmpDewPoint < -32768 || tmpDewPoint > 32767) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } temperature->dewPoint = tmpDewPoint; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) -- cgit v0.10.2 From 58d454b11fe3c143b37aea90772c122321a5b902 Mon Sep 17 00:00:00 2001 From: Avamander Date: Thu, 2 Dec 2021 23:49:51 +0200 Subject: Improved Temperature parsing diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index e5d8053..a30b227 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -195,7 +195,7 @@ namespace Pinetime { int64_t tmpTemperature = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Temperature", &tmpTemperature); - if (tmpTemperature < 0 || tmpTemperature > 65535) { + if (tmpTemperature < -32768 || tmpTemperature > 32767) { return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } temperature->temperature = tmpTemperature; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) -- cgit v0.10.2 From 62bb6b51634b22410a96f1ca9cbe183d1e9c504c Mon Sep 17 00:00:00 2001 From: Avamander Date: Fri, 3 Dec 2021 16:28:17 +0200 Subject: Better cleanup, bugfixes and improvements in weather parsing. UI improvements diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index a30b227..f3be35f 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -58,17 +58,20 @@ namespace Pinetime { int64_t tmpTimestamp = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Timestamp", &tmpTimestamp); if (QCBORDecode_GetError(&decodeContext) != QCBOR_SUCCESS) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } int64_t tmpExpires = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Expires", &tmpExpires); if (QCBORDecode_GetError(&decodeContext) != QCBOR_SUCCESS || tmpExpires < 0 || tmpExpires > 4294967295) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } int64_t tmpEventType = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "EventType", &tmpEventType); if (QCBORDecode_GetError(&decodeContext) != QCBOR_SUCCESS || tmpEventType < 0 || tmpEventType >= static_cast(WeatherData::eventtype::Length)) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } @@ -82,6 +85,7 @@ namespace Pinetime { UsefulBufC stringBuf; // TODO: Everything ok with lifecycle here? QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Polluter", &stringBuf); if (UsefulBuf_IsNULLOrEmptyC(stringBuf) != 0) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } airquality->polluter = std::string(static_cast(stringBuf.ptr), stringBuf.len); @@ -89,11 +93,13 @@ namespace Pinetime { int64_t tmpAmount = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount); if (tmpAmount < 0 || tmpAmount > 4294967295) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } airquality->amount = tmpAmount; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) - if (AddEventToTimeline(std::move(airquality))) { + if (!AddEventToTimeline(std::move(airquality))) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } break; @@ -107,6 +113,7 @@ namespace Pinetime { int64_t tmpType = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Type", &tmpType); if (tmpType < 0 || tmpType >= static_cast(WeatherData::obscurationtype::Length)) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } obscuration->type = static_cast(tmpType); @@ -114,11 +121,13 @@ namespace Pinetime { int64_t tmpAmount = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount); if (tmpAmount < 0 || tmpAmount > 65535) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } obscuration->amount = tmpAmount; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) - if (AddEventToTimeline(std::move(obscuration))) { + if (!AddEventToTimeline(std::move(obscuration))) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } break; @@ -132,6 +141,7 @@ namespace Pinetime { int64_t tmpType = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Type", &tmpType); if (tmpType < 0 || tmpType >= static_cast(WeatherData::precipitationtype::Length)) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } precipitation->type = static_cast(tmpType); @@ -139,11 +149,13 @@ namespace Pinetime { int64_t tmpAmount = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount); if (tmpAmount < 0 || tmpAmount > 255) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } precipitation->amount = tmpAmount; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) - if (AddEventToTimeline(std::move(precipitation))) { + if (!AddEventToTimeline(std::move(precipitation))) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } break; @@ -157,6 +169,7 @@ namespace Pinetime { int64_t tmpMin = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "SpeedMin", &tmpMin); if (tmpMin < 0 || tmpMin > 255) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } wind->speedMin = tmpMin; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) @@ -164,6 +177,7 @@ namespace Pinetime { int64_t tmpMax = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "SpeedMin", &tmpMax); if (tmpMax < 0 || tmpMax > 255) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } wind->speedMax = tmpMax; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) @@ -171,6 +185,7 @@ namespace Pinetime { int64_t tmpDMin = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "DirectionMin", &tmpDMin); if (tmpDMin < 0 || tmpDMin > 255) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } wind->directionMin = tmpDMin; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) @@ -178,11 +193,13 @@ namespace Pinetime { int64_t tmpDMax = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "DirectionMax", &tmpDMax); if (tmpDMax < 0 || tmpDMax > 255) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } wind->directionMax = tmpDMax; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) - if (AddEventToTimeline(std::move(wind))) { + if (!AddEventToTimeline(std::move(wind))) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } break; @@ -196,18 +213,23 @@ namespace Pinetime { int64_t tmpTemperature = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Temperature", &tmpTemperature); if (tmpTemperature < -32768 || tmpTemperature > 32767) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } - temperature->temperature = tmpTemperature; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + temperature->temperature = + static_cast(tmpTemperature); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) int64_t tmpDewPoint = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "DewPoint", &tmpDewPoint); if (tmpDewPoint < -32768 || tmpDewPoint > 32767) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } - temperature->dewPoint = tmpDewPoint; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + temperature->dewPoint = + static_cast(tmpDewPoint); // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) - if (AddEventToTimeline(std::move(temperature))) { + if (!AddEventToTimeline(std::move(temperature))) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } break; @@ -219,13 +241,15 @@ namespace Pinetime { special->expires = tmpExpires; int64_t tmpType = 0; - QCBORDecode_GetInt64InMapSZ(&decodeContext, "DewPoint", &tmpType); + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Type", &tmpType); if (tmpType < 0 || tmpType >= static_cast(WeatherData::specialtype::Length)) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } special->type = static_cast(tmpType); - if (AddEventToTimeline(std::move(special))) { + if (!AddEventToTimeline(std::move(special))) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } break; @@ -236,14 +260,16 @@ namespace Pinetime { pressure->eventType = static_cast(tmpEventType); pressure->expires = tmpExpires; - int64_t tmpDewPoint = 0; - QCBORDecode_GetInt64InMapSZ(&decodeContext, "DewPoint", &tmpDewPoint); - if (tmpDewPoint < 0 || tmpDewPoint >= 65535) { + int64_t tmpPressure = 0; + QCBORDecode_GetInt64InMapSZ(&decodeContext, "Pressure", &tmpPressure); + if (tmpPressure < 0 || tmpPressure >= 65535) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } - pressure->pressure = tmpDewPoint; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) + pressure->pressure = tmpPressure; // NOLINT(bugprone-narrowing-conversions,cppcoreguidelines-narrowing-conversions) - if (AddEventToTimeline(std::move(pressure))) { + if (!AddEventToTimeline(std::move(pressure))) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } break; @@ -257,6 +283,7 @@ namespace Pinetime { UsefulBufC stringBuf; // TODO: Everything ok with lifecycle here? QCBORDecode_GetTextStringInMapSZ(&decodeContext, "Location", &stringBuf); if (UsefulBuf_IsNULLOrEmptyC(stringBuf) != 0) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } location->location = std::string(static_cast(stringBuf.ptr), stringBuf.len); @@ -264,6 +291,7 @@ namespace Pinetime { int64_t tmpAltitude = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Altitude", &tmpAltitude); if (tmpAltitude < -32768 || tmpAltitude >= 32767) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } location->altitude = static_cast(tmpAltitude); @@ -271,6 +299,7 @@ namespace Pinetime { int64_t tmpLatitude = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Latitude", &tmpLatitude); if (tmpLatitude < -2147483648 || tmpLatitude >= 2147483647) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } location->latitude = static_cast(tmpLatitude); @@ -278,11 +307,13 @@ namespace Pinetime { int64_t tmpLongitude = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Longitude", &tmpLongitude); if (tmpLongitude < -2147483648 || tmpLongitude >= 2147483647) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } location->latitude = static_cast(tmpLongitude); - if (AddEventToTimeline(std::move(location))) { + if (!AddEventToTimeline(std::move(location))) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } break; @@ -296,11 +327,13 @@ namespace Pinetime { int64_t tmpAmount = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Amount", &tmpAmount); if (tmpAmount < 0 || tmpAmount > 255) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } clouds->amount = static_cast(tmpAmount); - if (AddEventToTimeline(std::move(clouds))) { + if (!AddEventToTimeline(std::move(clouds))) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } break; @@ -314,17 +347,20 @@ namespace Pinetime { int64_t tmpType = 0; QCBORDecode_GetInt64InMapSZ(&decodeContext, "Humidity", &tmpType); if (tmpType < 0 || tmpType >= 255) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } humidity->humidity = static_cast(tmpType); - if (AddEventToTimeline(std::move(humidity))) { + if (!AddEventToTimeline(std::move(humidity))) { + CleanUpQcbor(&decodeContext); return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } break; } default: { - break; + CleanUpQcbor(&decodeContext); + return BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN; } } @@ -369,7 +405,7 @@ namespace Pinetime { std::unique_ptr& WeatherService::GetCurrentClouds() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : this->timeline) { - if (header->eventType == WeatherData::eventtype::Clouds && isEventStillValid(header, currentTimestamp)) { + if (header->eventType == WeatherData::eventtype::Clouds && IsEventStillValid(header, currentTimestamp)) { return reinterpret_cast&>(header); } } @@ -380,7 +416,7 @@ namespace Pinetime { std::unique_ptr& WeatherService::GetCurrentObscuration() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : this->timeline) { - if (header->eventType == WeatherData::eventtype::Obscuration && isEventStillValid(header, currentTimestamp)) { + if (header->eventType == WeatherData::eventtype::Obscuration && IsEventStillValid(header, currentTimestamp)) { return reinterpret_cast&>(header); } } @@ -391,7 +427,7 @@ namespace Pinetime { std::unique_ptr& WeatherService::GetCurrentPrecipitation() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : this->timeline) { - if (header->eventType == WeatherData::eventtype::Precipitation && isEventStillValid(header, currentTimestamp)) { + if (header->eventType == WeatherData::eventtype::Precipitation && IsEventStillValid(header, currentTimestamp)) { return reinterpret_cast&>(header); } } @@ -402,7 +438,7 @@ namespace Pinetime { std::unique_ptr& WeatherService::GetCurrentWind() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : this->timeline) { - if (header->eventType == WeatherData::eventtype::Wind && isEventStillValid(header, currentTimestamp)) { + if (header->eventType == WeatherData::eventtype::Wind && IsEventStillValid(header, currentTimestamp)) { return reinterpret_cast&>(header); } } @@ -413,7 +449,7 @@ namespace Pinetime { std::unique_ptr& WeatherService::GetCurrentTemperature() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : this->timeline) { - if (header->eventType == WeatherData::eventtype::Temperature && isEventStillValid(header, currentTimestamp)) { + if (header->eventType == WeatherData::eventtype::Temperature && IsEventStillValid(header, currentTimestamp)) { return reinterpret_cast&>(header); } } @@ -424,7 +460,7 @@ namespace Pinetime { std::unique_ptr& WeatherService::GetCurrentHumidity() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : this->timeline) { - if (header->eventType == WeatherData::eventtype::Humidity && isEventStillValid(header, currentTimestamp)) { + if (header->eventType == WeatherData::eventtype::Humidity && IsEventStillValid(header, currentTimestamp)) { return reinterpret_cast&>(header); } } @@ -435,7 +471,7 @@ namespace Pinetime { std::unique_ptr& WeatherService::GetCurrentPressure() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : this->timeline) { - if (header->eventType == WeatherData::eventtype::Pressure && isEventStillValid(header, currentTimestamp)) { + if (header->eventType == WeatherData::eventtype::Pressure && IsEventStillValid(header, currentTimestamp)) { return reinterpret_cast&>(header); } } @@ -446,7 +482,7 @@ namespace Pinetime { std::unique_ptr& WeatherService::GetCurrentLocation() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : this->timeline) { - if (header->eventType == WeatherData::eventtype::Location && isEventStillValid(header, currentTimestamp)) { + if (header->eventType == WeatherData::eventtype::Location && IsEventStillValid(header, currentTimestamp)) { return reinterpret_cast&>(header); } } @@ -457,7 +493,7 @@ namespace Pinetime { std::unique_ptr& WeatherService::GetCurrentQuality() { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : this->timeline) { - if (header->eventType == WeatherData::eventtype::AirQuality && isEventStillValid(header, currentTimestamp)) { + if (header->eventType == WeatherData::eventtype::AirQuality && IsEventStillValid(header, currentTimestamp)) { return reinterpret_cast&>(header); } } @@ -481,7 +517,7 @@ namespace Pinetime { bool WeatherService::HasTimelineEventOfType(const WeatherData::eventtype type) const { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); for (auto&& header : timeline) { - if (header->eventType == type && isEventStillValid(header, currentTimestamp)) { + if (header->eventType == type && IsEventStillValid(header, currentTimestamp)) { return true; } } @@ -493,7 +529,7 @@ namespace Pinetime { timeline.erase(std::remove_if(std::begin(timeline), std::end(timeline), [&](std::unique_ptr const& header) { - return !isEventStillValid(header, timeCurrent); + return !IsEventStillValid(header, timeCurrent); }), std::end(timeline)); @@ -505,9 +541,9 @@ namespace Pinetime { return first->timestamp > second->timestamp; } - bool WeatherService::isEventStillValid(const std::unique_ptr& header, const uint64_t currentTimestamp) { + bool WeatherService::IsEventStillValid(const std::unique_ptr& uniquePtr, const uint64_t timestamp) { // Not getting timestamp in isEventStillValid for more speed - return header->timestamp + header->expires <= currentTimestamp; + return uniquePtr->timestamp + uniquePtr->expires >= timestamp; } uint64_t WeatherService::GetCurrentUnixTimestamp() const { @@ -520,7 +556,7 @@ namespace Pinetime { ((60 - dateTimeController.Minutes()) * 60) - (60 - dateTimeController.Seconds()); int16_t result = -32768; for (auto&& header : this->timeline) { - if (header->eventType == WeatherData::eventtype::Temperature && isEventStillValid(header, currentTimestamp) && + if (header->eventType == WeatherData::eventtype::Temperature && IsEventStillValid(header, currentTimestamp) && header->timestamp < currentDayEnd && reinterpret_cast&>(header)->temperature != -32768) { int16_t temperature = reinterpret_cast&>(header)->temperature; @@ -543,7 +579,7 @@ namespace Pinetime { ((60 - dateTimeController.Minutes()) * 60) - (60 - dateTimeController.Seconds()); int16_t result = -32768; for (auto&& header : this->timeline) { - if (header->eventType == WeatherData::eventtype::Temperature && isEventStillValid(header, currentTimestamp) && + if (header->eventType == WeatherData::eventtype::Temperature && IsEventStillValid(header, currentTimestamp) && header->timestamp < currentDayEnd && reinterpret_cast&>(header)->temperature != -32768) { int16_t temperature = reinterpret_cast&>(header)->temperature; @@ -559,5 +595,10 @@ namespace Pinetime { return result; } + + void WeatherService::CleanUpQcbor(QCBORDecodeContext* decodeContext) { + QCBORDecode_ExitMap(decodeContext); + QCBORDecode_Finish(decodeContext); + } } } diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index 52b0356..a9f02b1 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -30,7 +30,8 @@ #undef min #include "WeatherData.h" -#include +#include "libs/QCBOR/inc/qcbor/qcbor.h" +#include "components/datetime/DateTimeController.h" int WeatherCallback(uint16_t connHandle, uint16_t attrHandle, struct ble_gatt_access_ctxt* ctxt, void* arg); @@ -160,7 +161,9 @@ namespace Pinetime { * @param currentTimestamp what's the time right now * @return if the event is valid */ - static bool isEventStillValid(const std::unique_ptr& uniquePtr, const uint64_t timestamp); + static bool IsEventStillValid(const std::unique_ptr& uniquePtr, const uint64_t timestamp); + + void CleanUpQcbor(QCBORDecodeContext* decodeContext); }; } } diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 8015518..d45251b 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -1,5 +1,6 @@ #include "displayapp/DisplayApp.h" #include +#include #include "displayapp/screens/HeartRate.h" #include "displayapp/screens/Motion.h" #include "displayapp/screens/Timer.h" @@ -439,7 +440,8 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) currentScreen = std::make_unique(this, systemTask->nimble().music()); break; case Apps::Navigation: - currentScreen = std::make_unique(this, systemTask->nimble().navigation()); + currentScreen = std::make_unique(this, systemTask->nimble().weather()); + // currentScreen = std::make_unique(this, systemTask->nimble().navigation()); break; case Apps::HeartRate: currentScreen = std::make_unique(this, heartRateController, *systemTask); @@ -451,6 +453,9 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) case Apps::Motion: currentScreen = std::make_unique(this, motionController); break; + case Apps::Weather: + currentScreen = std::make_unique(this, systemTask->nimble().weather()); + break; case Apps::Steps: currentScreen = std::make_unique(this, motionController, settingsController); break; diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp index c9852ee..d424119 100644 --- a/src/displayapp/screens/Weather.cpp +++ b/src/displayapp/screens/Weather.cpp @@ -76,22 +76,22 @@ std::unique_ptr Weather::CreateScreenTemperature() { // Do not use the data, it's invalid lv_label_set_text_fmt(label, "#FFFF00 Temperature#\n\n" - "#444444 %d#\n\n" + "#444444 %.2f#°C \n\n" "#444444 %d#\n\n" "%d\n" "%d\n", - 0, + 0.0f, 0, 0, 0); } else { lv_label_set_text_fmt(label, "#FFFF00 Temperature#\n\n" - "#444444 %hd%%#°C \n\n" + "#444444 %.2f#°C \n\n" "#444444 %hd#\n\n" "%llu\n" "%lu\n", - current->temperature, + current->temperature / 100.0f, current->dewPoint, current->timestamp, current->expires); -- cgit v0.10.2 From 0df49bd43d6d02d8d50918543ae3eda77f31c651 Mon Sep 17 00:00:00 2001 From: Avamander Date: Fri, 3 Dec 2021 17:06:30 +0200 Subject: Removed float usage from display diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp index d424119..fcc15d6 100644 --- a/src/displayapp/screens/Weather.cpp +++ b/src/displayapp/screens/Weather.cpp @@ -76,22 +76,22 @@ std::unique_ptr Weather::CreateScreenTemperature() { // Do not use the data, it's invalid lv_label_set_text_fmt(label, "#FFFF00 Temperature#\n\n" - "#444444 %.2f#°C \n\n" + "#444444 %d#°C \n\n" "#444444 %d#\n\n" "%d\n" "%d\n", - 0.0f, + 0, 0, 0, 0); } else { lv_label_set_text_fmt(label, "#FFFF00 Temperature#\n\n" - "#444444 %.2f#°C \n\n" + "#444444 %d#°C \n\n" "#444444 %hd#\n\n" "%llu\n" "%lu\n", - current->temperature / 100.0f, + current->temperature / 100, current->dewPoint, current->timestamp, current->expires); -- cgit v0.10.2 From 7b04ce5ebaf1d73feac529bd16828415e5a046c7 Mon Sep 17 00:00:00 2001 From: Avamander Date: Fri, 3 Dec 2021 17:38:23 +0200 Subject: Added a note about the timestamp having a timezone offset diff --git a/src/components/ble/weather/WeatherData.h b/src/components/ble/weather/WeatherData.h index d56f481..42572ec 100644 --- a/src/components/ble/weather/WeatherData.h +++ b/src/components/ble/weather/WeatherData.h @@ -182,7 +182,11 @@ namespace Pinetime { /** The header used for further parsing */ class TimelineHeader { public: - /** UNIX timestamp */ + /** + * UNIX timestamp + * TODO: This is currently WITH A TIMEZONE OFFSET! + * Please send events with the timestamp offset by the timezone. + **/ uint64_t timestamp; /** * Time in seconds until the event expires -- cgit v0.10.2 From 6879147648370dea405c169d0e1caea5c2009cbd Mon Sep 17 00:00:00 2001 From: Avamander Date: Sat, 4 Dec 2021 11:46:14 +0200 Subject: Revert wrong change to DisplayApp diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index d45251b..8015518 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -1,6 +1,5 @@ #include "displayapp/DisplayApp.h" #include -#include #include "displayapp/screens/HeartRate.h" #include "displayapp/screens/Motion.h" #include "displayapp/screens/Timer.h" @@ -440,8 +439,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) currentScreen = std::make_unique(this, systemTask->nimble().music()); break; case Apps::Navigation: - currentScreen = std::make_unique(this, systemTask->nimble().weather()); - // currentScreen = std::make_unique(this, systemTask->nimble().navigation()); + currentScreen = std::make_unique(this, systemTask->nimble().navigation()); break; case Apps::HeartRate: currentScreen = std::make_unique(this, heartRateController, *systemTask); @@ -453,9 +451,6 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) case Apps::Motion: currentScreen = std::make_unique(this, motionController); break; - case Apps::Weather: - currentScreen = std::make_unique(this, systemTask->nimble().weather()); - break; case Apps::Steps: currentScreen = std::make_unique(this, motionController, settingsController); break; -- cgit v0.10.2 From f1f2bc119a7c855613616ecaf5c8aa72390cde14 Mon Sep 17 00:00:00 2001 From: Avamander Date: Sat, 4 Dec 2021 13:58:40 +0200 Subject: Added a note about map key capitalization diff --git a/src/components/ble/weather/WeatherData.h b/src/components/ble/weather/WeatherData.h index 42572ec..613d5ac 100644 --- a/src/components/ble/weather/WeatherData.h +++ b/src/components/ble/weather/WeatherData.h @@ -29,7 +29,7 @@ * you'll get an error returned. Data is relatively well-validated, * so keep in the bounds of the data types given. * - * Write all struct members into a single finite-sized map, and write it to the characteristic. + * Write all struct members (CamelCase keys) into a single finite-sized map, and write it to the characteristic. * Mind the MTU. * * How to debug? -- cgit v0.10.2 From 3eebe66d659c9c8e72a7c355973c74c2b8899174 Mon Sep 17 00:00:00 2001 From: Avamander Date: Sat, 4 Dec 2021 17:12:34 +0200 Subject: Updated docs and renamed functions for consistency diff --git a/doc/ble.md b/doc/ble.md index 8573166..2b86243 100644 --- a/doc/ble.md +++ b/doc/ble.md @@ -2,7 +2,7 @@ ## Introduction This page describes the BLE implementation and API built in this firmware. -**Note** : I'm a beginner in BLE related technologies and the information in this document reflects my current knowledge and understanding of the BLE stack. This information might be erroneous or incomplete. Feel free to submit a PR if you think you can improve it. +**Note**: I'm a beginner in BLE related technologies and the information in this document reflects my current knowledge and understanding of the BLE stack. This information might be erroneous or incomplete. Feel free to submit a PR if you think you can improve it. --- @@ -72,12 +72,16 @@ The following custom services are implemented in InfiniTime: * [Navigation Service](NavigationService.md) : 00010000-78fc-48fe-8e23-433b3a1942d0 - - Since InfiniTime 0.13 - * Call characteristic (extension to the Alert Notification Service): 00020001-78fc-48fe-8e23-433b3a1942d0 - - - - Since InfiniTime 1.7: - * [Motion Service](MotionService.md) : 00030000-78fc-48fe-8e23-433b3a1942d0 +- Since InfiniTime 0.13 + * Call characteristic (extension to the Alert Notification Service): 00020001-78fc-48fe-8e23-433b3a1942d0 + + +- Since InfiniTime 1.7: + * [Motion Service](MotionService.md): 00030000-78fc-48fe-8e23-433b3a1942d0 + + +- Since InfiniTime 1.8: + * [Weather Service](/src/components/ble/weather/WeatherService.h): 00040000-78fc-48fe-8e23-433b3a1942d0 --- diff --git a/src/components/ble/weather/WeatherService.cpp b/src/components/ble/weather/WeatherService.cpp index f3be35f..23f53b7 100644 --- a/src/components/ble/weather/WeatherService.cpp +++ b/src/components/ble/weather/WeatherService.cpp @@ -550,7 +550,7 @@ namespace Pinetime { return std::chrono::duration_cast(dateTimeController.CurrentDateTime().time_since_epoch()).count(); } - int16_t WeatherService::getTodayMinTemp() const { + int16_t WeatherService::GetTodayMinTemp() const { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); uint64_t currentDayEnd = currentTimestamp - ((24 - dateTimeController.Hours()) * 60 * 60) - ((60 - dateTimeController.Minutes()) * 60) - (60 - dateTimeController.Seconds()); @@ -573,7 +573,7 @@ namespace Pinetime { return result; } - int16_t WeatherService::getTodayMaxTemp() const { + int16_t WeatherService::GetTodayMaxTemp() const { uint64_t currentTimestamp = GetCurrentUnixTimestamp(); uint64_t currentDayEnd = currentTimestamp - ((24 - dateTimeController.Hours()) * 60 * 60) - ((60 - dateTimeController.Minutes()) * 60) - (60 - dateTimeController.Seconds()); diff --git a/src/components/ble/weather/WeatherService.h b/src/components/ble/weather/WeatherService.h index a9f02b1..eca70cb 100644 --- a/src/components/ble/weather/WeatherService.h +++ b/src/components/ble/weather/WeatherService.h @@ -64,14 +64,14 @@ namespace Pinetime { /** * Searches for the current day's maximum temperature - * @return -32768 if there's no data, degrees celcius times 100 otherwise + * @return -32768 if there's no data, degrees Celsius times 100 otherwise */ - int16_t getTodayMaxTemp() const; + int16_t GetTodayMaxTemp() const; /** * Searches for the current day's minimum temperature - * @return -32768 if there's no data, degrees celcius times 100 otherwise + * @return -32768 if there's no data, degrees Celsius times 100 otherwise */ - int16_t getTodayMinTemp() const; + int16_t GetTodayMinTemp() const; /* * Management functions @@ -163,6 +163,9 @@ namespace Pinetime { */ static bool IsEventStillValid(const std::unique_ptr& uniquePtr, const uint64_t timestamp); + /** + * This is a helper function that closes a QCBOR map and decoding context cleanly + */ void CleanUpQcbor(QCBORDecodeContext* decodeContext); }; } -- cgit v0.10.2 From 5f50f0e538e20ede353b388148b706319da161ce Mon Sep 17 00:00:00 2001 From: Avamander Date: Sat, 4 Dec 2021 20:09:37 +0200 Subject: Fixed air quality amounts being off by a few orders of magnitude diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp index fcc15d6..1d0a83b 100644 --- a/src/displayapp/screens/Weather.cpp +++ b/src/displayapp/screens/Weather.cpp @@ -125,7 +125,7 @@ std::unique_ptr Weather::CreateScreenAir() { "%llu\n" "%lu\n", current->polluter.c_str(), - current->amount, + (current->amount / 100), current->timestamp, current->expires); } -- cgit v0.10.2 From ae4b9e0f2e877d200bd780f99e2a8952f9f8bf5b Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Mon, 6 Dec 2021 10:29:14 +0100 Subject: Include Colors.h diff --git a/src/displayapp/screens/PineTimeStyle.h b/src/displayapp/screens/PineTimeStyle.h index 3632e57..c643688 100644 --- a/src/displayapp/screens/PineTimeStyle.h +++ b/src/displayapp/screens/PineTimeStyle.h @@ -5,6 +5,7 @@ #include #include #include "displayapp/screens/Screen.h" +#include "displayapp/Colors.h" #include "components/datetime/DateTimeController.h" namespace Pinetime { -- cgit v0.10.2 From 62dbcbfc953a36202d96466563a8e71b8bd4ff65 Mon Sep 17 00:00:00 2001 From: "James A. Jerkins" Date: Sat, 30 Oct 2021 13:02:39 -0500 Subject: Connect and bond with a passkey This commit adds the following: Passkey pairing - passkey is displayed on watch Swipe down to clear passkey screen Connection encryption Connection bonding Automatic reconnects to a bonded peripheral Trusted device on Android Note that persisting the bond between reboots is NOT included in this commit. Therefore, rebooting the watch will cause reconnect failures. You must delete the bond from the phone to reconnect/pair. diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e727b2b..fecd09d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -154,6 +154,7 @@ set(NIMBLE_SRC libs/mynewt-nimble/nimble/controller/src/ble_ll_supp_cmd.c libs/mynewt-nimble/nimble/controller/src/ble_ll_hci_ev.c libs/mynewt-nimble/nimble/controller/src/ble_ll_rfmgmt.c + libs/mynewt-nimble/nimble/controller/src/ble_ll_resolv.c libs/mynewt-nimble/porting/nimble/src/os_cputime.c libs/mynewt-nimble/porting/nimble/src/os_cputime_pwr2.c libs/mynewt-nimble/porting/nimble/src/os_mbuf.c @@ -421,6 +422,7 @@ list(APPEND SOURCE_FILES displayapp/screens/BatteryInfo.cpp displayapp/screens/Steps.cpp displayapp/screens/Timer.cpp + displayapp/screens/PassKey.cpp displayapp/screens/Error.cpp displayapp/screens/Alarm.cpp displayapp/Colors.cpp diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp index 9a3f86f..82df7b1 100644 --- a/src/components/ble/BatteryInformationService.cpp +++ b/src/components/ble/BatteryInformationService.cpp @@ -17,7 +17,7 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte characteristicDefinition {{.uuid = &batteryLevelUuid.u, .access_cb = BatteryInformationServiceCallback, .arg = this, - .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_NOTIFY, .val_handle = &batteryLevelHandle}, {0}}, serviceDefinition { diff --git a/src/components/ble/BleController.h b/src/components/ble/BleController.h index 2cba26a..72b8766 100644 --- a/src/components/ble/BleController.h +++ b/src/components/ble/BleController.h @@ -9,7 +9,7 @@ namespace Pinetime { public: using BleAddress = std::array; enum class FirmwareUpdateStates { Idle, Running, Validated, Error }; - enum class AddressTypes { Public, Random }; + enum class AddressTypes { Public, Random, RPA_Public, RPA_Random }; Ble() = default; bool IsConnected() const { @@ -48,6 +48,12 @@ namespace Pinetime { void AddressType(AddressTypes t) { addressType = t; } + void SetPairingKey(uint32_t k) { + pairingKey = k; + } + uint32_t GetPairingKey() const { + return pairingKey; + } private: bool isConnected = false; @@ -57,6 +63,7 @@ namespace Pinetime { FirmwareUpdateStates firmwareUpdateState = FirmwareUpdateStates::Idle; BleAddress address; AddressTypes addressType; + uint32_t pairingKey = 0; }; } -} \ No newline at end of file +} diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 43a8b0d..01901e0 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -1,4 +1,6 @@ #include "components/ble/NimbleController.h" +#include + #include #define min // workaround: nimble's min/max macros conflict with libstdc++ #define max @@ -6,6 +8,7 @@ #include #include #include +#include #undef max #undef min #include @@ -45,16 +48,18 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, } void nimble_on_reset(int reason) { - NRF_LOG_INFO("Resetting state; reason=%d\n", reason); + NRF_LOG_INFO("Nimble lost sync, resetting state; reason=%d", reason); } void nimble_on_sync(void) { - int rc; + int rc; - rc = ble_hs_util_ensure_addr(0); - ASSERT(rc == 0); + NRF_LOG_INFO("Nimble is synced"); + + rc = ble_hs_util_ensure_addr(0); + ASSERT(rc == 0); - nptr->StartAdvertising(); + nptr->StartAdvertising(); } int GAPEventCallback(struct ble_gap_event* event, void* arg) { @@ -69,6 +74,7 @@ void NimbleController::Init() { nptr = this; ble_hs_cfg.reset_cb = nimble_on_reset; ble_hs_cfg.sync_cb = nimble_on_sync; + ble_hs_cfg.store_status_cb = ble_store_util_status_rr; ble_svc_gap_init(); ble_svc_gatt_init(); @@ -97,8 +103,22 @@ void NimbleController::Init() { Pinetime::Controllers::Ble::BleAddress address; rc = ble_hs_id_copy_addr(addrType, address.data(), nullptr); ASSERT(rc == 0); - bleController.AddressType((addrType == 0) ? Ble::AddressTypes::Public : Ble::AddressTypes::Random); + bleController.Address(std::move(address)); + switch (addrType) { + case BLE_OWN_ADDR_PUBLIC: + bleController.AddressType(Ble::AddressTypes::Public); + break; + case BLE_OWN_ADDR_RANDOM: + bleController.AddressType(Ble::AddressTypes::Random); + break; + case BLE_OWN_ADDR_RPA_PUBLIC_DEFAULT: + bleController.AddressType(Ble::AddressTypes::RPA_Public); + break; + case BLE_OWN_ADDR_RPA_RANDOM_DEFAULT: + bleController.AddressType(Ble::AddressTypes::RPA_Random); + break; + } rc = ble_gatts_start(); ASSERT(rc == 0); @@ -108,17 +128,10 @@ void NimbleController::Init() { } void NimbleController::StartAdvertising() { - int rc; - - /* set adv parameters */ struct ble_gap_adv_params adv_params; struct ble_hs_adv_fields fields; - /* advertising payload is split into advertising data and advertising - response, because all data cannot fit into single packet; name of device - is sent as response to scan request */ struct ble_hs_adv_fields rsp_fields; - /* fill all fields and parameters with zeros */ memset(&adv_params, 0, sizeof(adv_params)); memset(&fields, 0, sizeof(fields)); memset(&rsp_fields, 0, sizeof(rsp_fields)); @@ -141,10 +154,11 @@ void NimbleController::StartAdvertising() { fields.uuids128_is_complete = 1; fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO; - rsp_fields.name = (uint8_t*) deviceName; + rsp_fields.name = reinterpret_cast(deviceName); rsp_fields.name_len = strlen(deviceName); rsp_fields.name_is_complete = 1; + int rc; rc = ble_gap_adv_set_fields(&fields); ASSERT(rc == 0); @@ -159,15 +173,14 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { switch (event->type) { case BLE_GAP_EVENT_ADV_COMPLETE: NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_ADV_COMPLETE"); - NRF_LOG_INFO("reason=%d; status=%d", event->adv_complete.reason, event->connect.status); + NRF_LOG_INFO("reason=%d; status=%0X", event->adv_complete.reason, event->connect.status); StartAdvertising(); break; case BLE_GAP_EVENT_CONNECT: - NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_CONNECT"); - /* A new connection was established or a connection attempt failed. */ - NRF_LOG_INFO("connection %s; status=%d ", event->connect.status == 0 ? "established" : "failed", event->connect.status); + NRF_LOG_INFO("Connect event : BLE_GAP_EVENT_CONNECT"); + NRF_LOG_INFO("connection %s; status=%0X ", event->connect.status == 0 ? "established" : "failed", event->connect.status); if (event->connect.status != 0) { /* Connection failed; resume advertising. */ @@ -186,10 +199,9 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { break; case BLE_GAP_EVENT_DISCONNECT: - NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_DISCONNECT"); - NRF_LOG_INFO("disconnect reason=%d", event->disconnect.reason); - /* Connection terminated; resume advertising. */ + NRF_LOG_INFO("Disconnect event : BLE_GAP_EVENT_DISCONNECT"); + NRF_LOG_INFO("disconnect reason=%d", event->disconnect.reason); currentTimeClient.Reset(); alertNotificationClient.Reset(); connectionHandle = BLE_HS_CONN_HANDLE_NONE; @@ -199,18 +211,45 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { break; case BLE_GAP_EVENT_CONN_UPDATE: - NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_CONN_UPDATE"); /* The central has updated the connection parameters. */ - NRF_LOG_INFO("update status=%d ", event->conn_update.status); + NRF_LOG_INFO("Update event : BLE_GAP_EVENT_CONN_UPDATE"); + NRF_LOG_INFO("update status=%0X ", event->conn_update.status); + break; + + case BLE_GAP_EVENT_CONN_UPDATE_REQ: + /* The central has requested updated connection parameters */ + NRF_LOG_INFO("Update event : BLE_GAP_EVENT_CONN_UPDATE_REQ"); + NRF_LOG_INFO("update request : itvl_min=%d itvl_max=%d latency=%d supervision=%d", + event->conn_update_req.peer_params->itvl_min, + event->conn_update_req.peer_params->itvl_max, + event->conn_update_req.peer_params->latency, + event->conn_update_req.peer_params->supervision_timeout); break; case BLE_GAP_EVENT_ENC_CHANGE: /* Encryption has been enabled or disabled for this connection. */ - NRF_LOG_INFO("encryption change event; status=%d ", event->enc_change.status); + NRF_LOG_INFO("Security event : BLE_GAP_EVENT_ENC_CHANGE"); + NRF_LOG_INFO("encryption change event; status=%0X ", event->enc_change.status); + break; + + case BLE_GAP_EVENT_PASSKEY_ACTION: + /* Authentication has been requested for this connection. + * Standards insist that the rand() PRNG be deterministic. + * Use the nimble TRNG since rand() is predictable. + */ + NRF_LOG_INFO("Security event : BLE_GAP_EVENT_PASSKEY_ACTION"); + if (event->passkey.params.action == BLE_SM_IOACT_DISP) { + struct ble_sm_io pkey = {0}; + pkey.action = event->passkey.params.action; + pkey.passkey = ble_ll_rand() % 1000000; + bleController.SetPairingKey(pkey.passkey); + systemTask.PushMessage(Pinetime::System::Messages::OnPairing); + ble_sm_inject_io(event->passkey.conn_handle, &pkey); + } break; case BLE_GAP_EVENT_SUBSCRIBE: - NRF_LOG_INFO("subscribe event; conn_handle=%d attr_handle=%d " + NRF_LOG_INFO("Subscribe event; conn_handle=%d attr_handle=%d " "reason=%d prevn=%d curn=%d previ=%d curi=???\n", event->subscribe.conn_handle, event->subscribe.attr_handle, @@ -234,11 +273,11 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { break; case BLE_GAP_EVENT_MTU: - NRF_LOG_INFO("mtu update event; conn_handle=%d cid=%d mtu=%d\n", - event->mtu.conn_handle, event->mtu.channel_id, event->mtu.value); + NRF_LOG_INFO("MTU Update event; conn_handle=%d cid=%d mtu=%d", event->mtu.conn_handle, event->mtu.channel_id, event->mtu.value); break; case BLE_GAP_EVENT_REPEAT_PAIRING: { + NRF_LOG_INFO("Pairing event : BLE_GAP_EVENT_REPEAT_PAIRING"); /* We already have a bond with the peer, but it is attempting to * establish a new secure link. This app sacrifices security for * convenience: just throw away the old bond and accept the new link. @@ -257,6 +296,8 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { case BLE_GAP_EVENT_NOTIFY_RX: { /* Peer sent us a notification or indication. */ + /* Attribute data is contained in event->notify_rx.attr_data. */ + NRF_LOG_INFO("Notify event : BLE_GAP_EVENT_NOTIFY_RX"); size_t notifSize = OS_MBUF_PKTLEN(event->notify_rx.om); NRF_LOG_INFO("received %s; conn_handle=%d attr_handle=%d " @@ -268,10 +309,17 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { alertNotificationClient.OnNotification(event); } break; - /* Attribute data is contained in event->notify_rx.attr_data. */ + + case BLE_GAP_EVENT_NOTIFY_TX: + NRF_LOG_INFO("Notify event : BLE_GAP_EVENT_NOTIFY_TX"); + break; + + case BLE_GAP_EVENT_IDENTITY_RESOLVED: + NRF_LOG_INFO("Identity event : BLE_GAP_EVENT_IDENTITY_RESOLVED"); + break; default: - // NRF_LOG_INFO("Advertising event : %d", event->type); + NRF_LOG_INFO("UNHANDLED GAP event : %d", event->type); break; } return 0; diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h index d340efe..935a61a 100644 --- a/src/displayapp/Apps.h +++ b/src/displayapp/Apps.h @@ -25,6 +25,7 @@ namespace Pinetime { Metronome, Motion, Steps, + PassKey, QuickSettings, Settings, SettingWatchFace, diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 8015518..08a7646 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -29,6 +29,7 @@ #include "displayapp/screens/FlashLight.h" #include "displayapp/screens/BatteryInfo.h" #include "displayapp/screens/Steps.h" +#include "displayapp/screens/PassKey.h" #include "displayapp/screens/Error.h" #include "drivers/Cst816s.h" @@ -288,6 +289,9 @@ void DisplayApp::Refresh() { // Added to remove warning // What should happen here? break; + case Messages::ShowPairingKey: + LoadApp(Apps::PassKey, DisplayApp::FullRefreshDirections::Up); + break; } } @@ -351,6 +355,11 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None); break; + case Apps::PassKey: + currentScreen = std::make_unique(this, bleController.GetPairingKey()); + ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::SwipeDown); + break; + case Apps::Notifications: currentScreen = std::make_unique( this, notificationManager, systemTask->nimble().alertService(), motorController, Screens::Notifications::Modes::Normal); diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h index 29e09eb..b22d6c3 100644 --- a/src/displayapp/Messages.h +++ b/src/displayapp/Messages.h @@ -19,6 +19,7 @@ namespace Pinetime { UpdateTimeOut, DimScreen, RestoreBrightness, + ShowPairingKey, AlarmTriggered }; } diff --git a/src/displayapp/screens/PassKey.cpp b/src/displayapp/screens/PassKey.cpp new file mode 100644 index 0000000..66bf0c2 --- /dev/null +++ b/src/displayapp/screens/PassKey.cpp @@ -0,0 +1,17 @@ +#include "PassKey.h" +#include "displayapp/DisplayApp.h" + +using namespace Pinetime::Applications::Screens; + +PassKey::PassKey(Pinetime::Applications::DisplayApp* app, uint32_t key) : Screen(app) { + lpasskey = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(lpasskey, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFFFF00)); + lv_obj_set_style_local_text_font(lpasskey, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); + lv_label_set_text_fmt(lpasskey, "%06u", key); + lv_obj_align(lpasskey, nullptr, LV_ALIGN_CENTER, 0, -20); +} + +PassKey::~PassKey() { + lv_obj_clean(lv_scr_act()); +} + diff --git a/src/displayapp/screens/PassKey.h b/src/displayapp/screens/PassKey.h new file mode 100644 index 0000000..34e0d59 --- /dev/null +++ b/src/displayapp/screens/PassKey.h @@ -0,0 +1,20 @@ +#pragma once + +#include "Screen.h" +#include + +namespace Pinetime { + namespace Applications { + namespace Screens { + + class PassKey : public Screen { + public: + PassKey(DisplayApp* app, uint32_t key); + ~PassKey() override; + + private: + lv_obj_t* lpasskey; + }; + } + } +} diff --git a/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h b/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h index 94b72cb..b3f2341 100644 --- a/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h +++ b/src/libs/mynewt-nimble/porting/nimble/include/syscfg/syscfg.h @@ -699,11 +699,11 @@ #endif #ifndef MYNEWT_VAL_BLE_SM_BONDING -#define MYNEWT_VAL_BLE_SM_BONDING (0) +#define MYNEWT_VAL_BLE_SM_BONDING (1) #endif #ifndef MYNEWT_VAL_BLE_SM_IO_CAP -#define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_NO_INPUT_OUTPUT) +#define MYNEWT_VAL_BLE_SM_IO_CAP (BLE_HS_IO_DISPLAY_ONLY) #endif #ifndef MYNEWT_VAL_BLE_SM_KEYPRESS @@ -711,7 +711,7 @@ #endif #ifndef MYNEWT_VAL_BLE_SM_LEGACY -#define MYNEWT_VAL_BLE_SM_LEGACY (1) +#define MYNEWT_VAL_BLE_SM_LEGACY (0) #endif #ifndef MYNEWT_VAL_BLE_SM_MAX_PROCS @@ -719,7 +719,7 @@ #endif #ifndef MYNEWT_VAL_BLE_SM_MITM -#define MYNEWT_VAL_BLE_SM_MITM (0) +#define MYNEWT_VAL_BLE_SM_MITM (1) #endif #ifndef MYNEWT_VAL_BLE_SM_OOB_DATA_FLAG @@ -727,11 +727,11 @@ #endif #ifndef MYNEWT_VAL_BLE_SM_OUR_KEY_DIST -#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (0) +#define MYNEWT_VAL_BLE_SM_OUR_KEY_DIST (7) #endif #ifndef MYNEWT_VAL_BLE_SM_SC -#define MYNEWT_VAL_BLE_SM_SC (0) +#define MYNEWT_VAL_BLE_SM_SC (1) #endif #ifndef MYNEWT_VAL_BLE_SM_SC_DEBUG_KEYS @@ -739,7 +739,7 @@ #endif #ifndef MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST -#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (0) +#define MYNEWT_VAL_BLE_SM_THEIR_KEY_DIST (3) #endif #ifndef MYNEWT_VAL_BLE_STORE_MAX_BONDS @@ -1089,7 +1089,7 @@ /* Overridden by @apache-mynewt-nimble/targets/riot (defined by @apache-mynewt-nimble/nimble/controller) */ #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY -#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY (0) +#define MYNEWT_VAL_BLE_LL_CFG_FEAT_LL_PRIVACY (1) #endif #ifndef MYNEWT_VAL_BLE_LL_CFG_FEAT_SLAVE_INIT_FEAT_XCHG diff --git a/src/sdk_config.h b/src/sdk_config.h index 38d47a7..7634dca 100644 --- a/src/sdk_config.h +++ b/src/sdk_config.h @@ -12580,4 +12580,4 @@ #endif // <<< end of configuration section >>> -#endif // SDK_CONFIG_H \ No newline at end of file +#endif // SDK_CONFIG_H diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h index b714270..516f646 100644 --- a/src/systemtask/Messages.h +++ b/src/systemtask/Messages.h @@ -22,6 +22,7 @@ namespace Pinetime { DisableSleeping, OnNewDay, OnChargingEvent, + OnPairing, SetOffAlarm, StopRinging, MeasureBatteryTimerExpired, diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 1120b80..2fb4de5 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -396,6 +396,13 @@ void SystemTask::Work() { case Messages::BatteryPercentageUpdated: nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining()); break; + case Messages::OnPairing: + if (isSleeping && !isWakingUp) { + GoToRunning(); + } + motorController.RunForDuration(35); + displayApp.PushMessage(Pinetime::Applications::Display::Messages::ShowPairingKey); + break; default: break; -- cgit v0.10.2 From 1e4130a9cfe6e1385d83d93e544d1e1cd79f11f8 Mon Sep 17 00:00:00 2001 From: "James A. Jerkins" Date: Mon, 1 Nov 2021 15:12:25 -0500 Subject: Fix for passkey screen scramble When a passkey is displayed, screen on or off, and another passkey is displayed the screen may become scrambled. Fix the issue by insuring the whole screen is drawn every time. diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 08a7646..0a675c8 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -215,6 +215,9 @@ void DisplayApp::Refresh() { } else { LoadApp(Apps::Alarm, DisplayApp::FullRefreshDirections::None); } + case Messages::ShowPairingKey: + LoadApp(Apps::PassKey, DisplayApp::FullRefreshDirections::Up); + break; case Messages::TouchEvent: { if (state != States::Running) { break; @@ -289,9 +292,6 @@ void DisplayApp::Refresh() { // Added to remove warning // What should happen here? break; - case Messages::ShowPairingKey: - LoadApp(Apps::PassKey, DisplayApp::FullRefreshDirections::Up); - break; } } diff --git a/src/displayapp/screens/PassKey.cpp b/src/displayapp/screens/PassKey.cpp index 66bf0c2..9e43a54 100644 --- a/src/displayapp/screens/PassKey.cpp +++ b/src/displayapp/screens/PassKey.cpp @@ -4,11 +4,18 @@ using namespace Pinetime::Applications::Screens; PassKey::PassKey(Pinetime::Applications::DisplayApp* app, uint32_t key) : Screen(app) { - lpasskey = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(lpasskey, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFFFF00)); - lv_obj_set_style_local_text_font(lpasskey, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); - lv_label_set_text_fmt(lpasskey, "%06u", key); - lv_obj_align(lpasskey, nullptr, LV_ALIGN_CENTER, 0, -20); + passkeyLabel = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(passkeyLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFFFF00)); + lv_obj_set_style_local_text_font(passkeyLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); + lv_label_set_text_fmt(passkeyLabel, "%06u", key); + lv_obj_align(passkeyLabel, nullptr, LV_ALIGN_CENTER, 0, -20); + + backgroundLabel = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_click(backgroundLabel, true); + lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP); + lv_obj_set_size(backgroundLabel, 240, 240); + lv_obj_set_pos(backgroundLabel, 0, 0); + lv_label_set_text(backgroundLabel, ""); } PassKey::~PassKey() { diff --git a/src/displayapp/screens/PassKey.h b/src/displayapp/screens/PassKey.h index 34e0d59..16e72a3 100644 --- a/src/displayapp/screens/PassKey.h +++ b/src/displayapp/screens/PassKey.h @@ -13,7 +13,8 @@ namespace Pinetime { ~PassKey() override; private: - lv_obj_t* lpasskey; + lv_obj_t* passkeyLabel; + lv_obj_t* backgroundLabel; }; } } -- cgit v0.10.2 From 150fa3b6615e524a072a1af6d6728519381fa737 Mon Sep 17 00:00:00 2001 From: "James A. Jerkins" Date: Sat, 4 Dec 2021 14:49:49 -0600 Subject: Persist bond between reboots Save bond information in the FS after a disconnect or encryption change if the bond is not already stored. The bond is restored on boot enabling automatic reconnection to a previously bonded central. Two consecutive watch reboots with the central out of range (or BLE off) will remove the stored bond from the watch. diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 01901e0..ec41198 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #undef max #undef min #include @@ -16,6 +17,7 @@ #include "components/ble/BleController.h" #include "components/ble/NotificationManager.h" #include "components/datetime/DateTimeController.h" +#include "components/fs/FS.h" #include "systemtask/SystemTask.h" using namespace Pinetime::Controllers; @@ -27,7 +29,8 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, Controllers::Battery& batteryController, Pinetime::Drivers::SpiNorFlash& spiNorFlash, Controllers::HeartRateController& heartRateController, - Controllers::MotionController& motionController) + Controllers::MotionController& motionController, + Pinetime::Controllers::FS& fs) : systemTask {systemTask}, bleController {bleController}, dateTimeController {dateTimeController}, @@ -43,7 +46,8 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, batteryInformationService {batteryController}, immediateAlertService {systemTask, notificationManager}, heartRateService {systemTask, heartRateController}, - motionService{systemTask, motionController}, + fs {fs}, + motionService {systemTask, motionController}, serviceDiscovery({¤tTimeClient, &alertNotificationClient}) { } @@ -123,6 +127,8 @@ void NimbleController::Init() { rc = ble_gatts_start(); ASSERT(rc == 0); + RestoreBond(); + if (!ble_gap_adv_active() && !bleController.IsConnected()) StartAdvertising(); } @@ -202,6 +208,10 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { /* Connection terminated; resume advertising. */ NRF_LOG_INFO("Disconnect event : BLE_GAP_EVENT_DISCONNECT"); NRF_LOG_INFO("disconnect reason=%d", event->disconnect.reason); + + if (event->disconnect.conn.sec_state.bonded) + PersistBond(event->disconnect.conn); + currentTimeClient.Reset(); alertNotificationClient.Reset(); connectionHandle = BLE_HS_CONN_HANDLE_NONE; @@ -230,6 +240,19 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { /* Encryption has been enabled or disabled for this connection. */ NRF_LOG_INFO("Security event : BLE_GAP_EVENT_ENC_CHANGE"); NRF_LOG_INFO("encryption change event; status=%0X ", event->enc_change.status); + + if (event->enc_change.status == 0) { + struct ble_gap_conn_desc desc; + ble_gap_conn_find(event->enc_change.conn_handle, &desc); + if (desc.sec_state.bonded) + PersistBond(desc); + + NRF_LOG_INFO("new state: encrypted=%d authenticated=%d bonded=%d key_size=%d", + desc.sec_state.encrypted, + desc.sec_state.authenticated, + desc.sec_state.bonded, + desc.sec_state.key_size); + } break; case BLE_GAP_EVENT_PASSKEY_ACTION: @@ -258,15 +281,13 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { event->subscribe.cur_notify, event->subscribe.prev_indicate); - if(event->subscribe.reason == BLE_GAP_SUBSCRIBE_REASON_TERM) { + if (event->subscribe.reason == BLE_GAP_SUBSCRIBE_REASON_TERM) { heartRateService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); motionService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); - } - else if(event->subscribe.prev_notify == 0 && event->subscribe.cur_notify == 1) { + } else if (event->subscribe.prev_notify == 0 && event->subscribe.cur_notify == 1) { heartRateService.SubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); motionService.SubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); - } - else if(event->subscribe.prev_notify == 1 && event->subscribe.cur_notify == 0) { + } else if (event->subscribe.prev_notify == 1 && event->subscribe.cur_notify == 0) { heartRateService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); motionService.UnsubscribeNotification(event->subscribe.conn_handle, event->subscribe.attr_handle); } @@ -340,3 +361,81 @@ void NimbleController::NotifyBatteryLevel(uint8_t level) { batteryInformationService.NotifyBatteryLevel(connectionHandle, level); } } + +void NimbleController::PersistBond(struct ble_gap_conn_desc& desc) { + union ble_store_key key; + union ble_store_value our_sec, peer_sec, peer_cccd_set[MYNEWT_VAL(BLE_STORE_MAX_CCCDS)] = {0}; + int rc; + + memset(&key, 0, sizeof key); + memset(&our_sec, 0, sizeof our_sec); + key.sec.peer_addr = desc.peer_id_addr; + rc = ble_store_read_our_sec(&key.sec, &our_sec.sec); + + if (memcmp(&our_sec.sec, &bondId, sizeof bondId) == 0) + return; + + memcpy(&bondId, &our_sec.sec, sizeof bondId); + + memset(&key, 0, sizeof key); + memset(&peer_sec, 0, sizeof peer_sec); + key.sec.peer_addr = desc.peer_id_addr; + rc += ble_store_read_peer_sec(&key.sec, &peer_sec.sec); + + if (rc == 0) { + memset(&key, 0, sizeof key); + key.cccd.peer_addr = desc.peer_id_addr; + int peer_count = 0; + ble_store_util_count(BLE_STORE_OBJ_TYPE_CCCD, &peer_count); + for (int i = 0; i < peer_count; i++) { + key.cccd.idx = peer_count; + ble_store_read_cccd(&key.cccd, &peer_cccd_set[i].cccd); + } + + /* Wakeup Spi and SpiNorFlash before accessing the file system + * This should be fixed in the FS driver + */ + systemTask.PushMessage(Pinetime::System::Messages::GoToRunning); + systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping); + vTaskDelay(10); + + lfs_file_t file_p; + + rc = fs.FileOpen(&file_p, "/bond.dat", LFS_O_WRONLY | LFS_O_CREAT); + if (rc == 0) { + fs.FileWrite(&file_p, reinterpret_cast(&our_sec.sec), sizeof our_sec); + fs.FileWrite(&file_p, reinterpret_cast(&peer_sec.sec), sizeof peer_sec); + fs.FileWrite(&file_p, reinterpret_cast(&peer_count), 1); + for (int i = 0; i < peer_count; i++) { + fs.FileWrite(&file_p, reinterpret_cast(&peer_cccd_set[i].cccd), sizeof(struct ble_store_value_cccd)); + } + fs.FileClose(&file_p); + } + systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping); + } +} + +void NimbleController::RestoreBond() { + lfs_file_t file_p; + union ble_store_value sec, cccd; + uint8_t peer_count = 0; + + if (fs.FileOpen(&file_p, "/bond.dat", LFS_O_RDONLY) == 0) { + memset(&sec, 0, sizeof sec); + fs.FileRead(&file_p, reinterpret_cast(&sec.sec), sizeof sec); + ble_store_write_our_sec(&sec.sec); + + memset(&sec, 0, sizeof sec); + fs.FileRead(&file_p, reinterpret_cast(&sec.sec), sizeof sec); + ble_store_write_peer_sec(&sec.sec); + + fs.FileRead(&file_p, &peer_count, 1); + for (int i = 0; i < peer_count; i++) { + fs.FileRead(&file_p, reinterpret_cast(&cccd.cccd), sizeof(struct ble_store_value_cccd)); + ble_store_write_cccd(&cccd.cccd); + } + + fs.FileClose(&file_p); + fs.FileDelete("/bond.dat"); + } +} diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 895b87f..944e8ca 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -20,6 +20,7 @@ #include "components/ble/ServiceDiscovery.h" #include "components/ble/HeartRateService.h" #include "components/ble/MotionService.h" +#include "components/fs/FS.h" namespace Pinetime { namespace Drivers { @@ -45,7 +46,8 @@ namespace Pinetime { Controllers::Battery& batteryController, Pinetime::Drivers::SpiNorFlash& spiNorFlash, Controllers::HeartRateController& heartRateController, - Controllers::MotionController& motionController); + Controllers::MotionController& motionController, + Pinetime::Controllers::FS& fs); void Init(); void StartAdvertising(); int OnGAPEvent(ble_gap_event* event); @@ -78,6 +80,9 @@ namespace Pinetime { fastAdvCount = 0; } + void PersistBond(struct ble_gap_conn_desc &desc); + void RestoreBond(); + private: static constexpr const char* deviceName = "InfiniTime"; Pinetime::System::SystemTask& systemTask; @@ -98,10 +103,12 @@ namespace Pinetime { ImmediateAlertService immediateAlertService; HeartRateService heartRateService; MotionService motionService; + Pinetime::Controllers::FS& fs; uint8_t addrType; // 1 = Random, 0 = PUBLIC uint16_t connectionHandle = BLE_HS_CONN_HANDLE_NONE; uint8_t fastAdvCount = 0; + uint8_t bondId[16] = {0}; ble_uuid128_t dfuServiceUuid { .u {.type = BLE_UUID_TYPE_128}, @@ -110,6 +117,6 @@ namespace Pinetime { ServiceDiscovery serviceDiscovery; }; - static NimbleController* nptr; + static NimbleController* nptr; } } diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 2fb4de5..215c78a 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -109,7 +109,8 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi, batteryController, spiNorFlash, heartRateController, - motionController) { + motionController, + fs) { } void SystemTask::Start() { -- cgit v0.10.2 From 048ecd41e414a9abc8c3d09423b8f5cb99304309 Mon Sep 17 00:00:00 2001 From: "James A. Jerkins" Date: Wed, 8 Dec 2021 00:10:54 -0600 Subject: Adjust BLE/LL stacks, style, comments, refactoring Increase BLE task stack +200 and decrease LL task stack -200 more braces! diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index ec41198..0f20aef 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -10,10 +10,10 @@ #include #include #include -#undef max -#undef min #include #include +#undef max +#undef min #include "components/ble/BleController.h" #include "components/ble/NotificationManager.h" #include "components/datetime/DateTimeController.h" @@ -36,7 +36,9 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, dateTimeController {dateTimeController}, notificationManager {notificationManager}, spiNorFlash {spiNorFlash}, + fs {fs}, dfuService {systemTask, bleController, spiNorFlash}, + currentTimeClient {dateTimeController}, anService {systemTask, notificationManager}, alertNotificationClient {systemTask, notificationManager}, @@ -46,7 +48,6 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, batteryInformationService {batteryController}, immediateAlertService {systemTask, notificationManager}, heartRateService {systemTask, heartRateController}, - fs {fs}, motionService {systemTask, motionController}, serviceDiscovery({¤tTimeClient, &alertNotificationClient}) { } @@ -129,8 +130,9 @@ void NimbleController::Init() { RestoreBond(); - if (!ble_gap_adv_active() && !bleController.IsConnected()) + if (!ble_gap_adv_active() && !bleController.IsConnected()) { StartAdvertising(); + } } void NimbleController::StartAdvertising() { @@ -209,8 +211,9 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { NRF_LOG_INFO("Disconnect event : BLE_GAP_EVENT_DISCONNECT"); NRF_LOG_INFO("disconnect reason=%d", event->disconnect.reason); - if (event->disconnect.conn.sec_state.bonded) + if (event->disconnect.conn.sec_state.bonded) { PersistBond(event->disconnect.conn); + } currentTimeClient.Reset(); alertNotificationClient.Reset(); @@ -244,8 +247,9 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { if (event->enc_change.status == 0) { struct ble_gap_conn_desc desc; ble_gap_conn_find(event->enc_change.conn_handle, &desc); - if (desc.sec_state.bonded) + if (desc.sec_state.bonded) { PersistBond(desc); + } NRF_LOG_INFO("new state: encrypted=%d authenticated=%d bonded=%d key_size=%d", desc.sec_state.encrypted, @@ -257,8 +261,16 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { case BLE_GAP_EVENT_PASSKEY_ACTION: /* Authentication has been requested for this connection. + * + * BLE authentication is determined by the combination of I/O capabilities + * on the central and peripheral. When the peripheral is display only and + * the central has a keyboard and display then passkey auth is selected. + * When both the central and peripheral have displays and support yes/no + * buttons then numeric comparison is selected. We currently advertise + * display capability only so we only handle the "display" action here. + * * Standards insist that the rand() PRNG be deterministic. - * Use the nimble TRNG since rand() is predictable. + * Use the nimble TRNG here since rand() is predictable. */ NRF_LOG_INFO("Security event : BLE_GAP_EVENT_PASSKEY_ACTION"); if (event->passkey.params.action == BLE_SM_IOACT_DISP) { @@ -372,8 +384,9 @@ void NimbleController::PersistBond(struct ble_gap_conn_desc& desc) { key.sec.peer_addr = desc.peer_id_addr; rc = ble_store_read_our_sec(&key.sec, &our_sec.sec); - if (memcmp(&our_sec.sec, &bondId, sizeof bondId) == 0) + if (memcmp(&our_sec.sec, &bondId, sizeof bondId) == 0) { return; + } memcpy(&bondId, &our_sec.sec, sizeof bondId); diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 944e8ca..7569ce2 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -14,11 +14,11 @@ #include "components/ble/CurrentTimeService.h" #include "components/ble/DeviceInformationService.h" #include "components/ble/DfuService.h" +#include "components/ble/HeartRateService.h" #include "components/ble/ImmediateAlertService.h" #include "components/ble/MusicService.h" #include "components/ble/NavigationService.h" #include "components/ble/ServiceDiscovery.h" -#include "components/ble/HeartRateService.h" #include "components/ble/MotionService.h" #include "components/fs/FS.h" @@ -80,16 +80,17 @@ namespace Pinetime { fastAdvCount = 0; } - void PersistBond(struct ble_gap_conn_desc &desc); + private: + void PersistBond(struct ble_gap_conn_desc& desc); void RestoreBond(); - private: static constexpr const char* deviceName = "InfiniTime"; Pinetime::System::SystemTask& systemTask; Pinetime::Controllers::Ble& bleController; DateTime& dateTimeController; Pinetime::Controllers::NotificationManager& notificationManager; Pinetime::Drivers::SpiNorFlash& spiNorFlash; + Pinetime::Controllers::FS& fs; Pinetime::Controllers::DfuService dfuService; DeviceInformationService deviceInformationService; @@ -103,9 +104,9 @@ namespace Pinetime { ImmediateAlertService immediateAlertService; HeartRateService heartRateService; MotionService motionService; - Pinetime::Controllers::FS& fs; + ServiceDiscovery serviceDiscovery; - uint8_t addrType; // 1 = Random, 0 = PUBLIC + uint8_t addrType; uint16_t connectionHandle = BLE_HS_CONN_HANDLE_NONE; uint8_t fastAdvCount = 0; uint8_t bondId[16] = {0}; @@ -113,8 +114,6 @@ namespace Pinetime { ble_uuid128_t dfuServiceUuid { .u {.type = BLE_UUID_TYPE_128}, .value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00}}; - - ServiceDiscovery serviceDiscovery; }; static NimbleController* nptr; diff --git a/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c b/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c index 8ee3475..b990278 100644 --- a/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c +++ b/src/libs/mynewt-nimble/porting/npl/freertos/src/nimble_port_freertos.c @@ -37,7 +37,7 @@ nimble_port_freertos_init(TaskFunction_t host_task_fn) * provided by NimBLE and in case of FreeRTOS it does not need to be wrapped * since it has compatible prototype. */ - xTaskCreate(nimble_port_ll_task_func, "ll", configMINIMAL_STACK_SIZE + 400, + xTaskCreate(nimble_port_ll_task_func, "ll", configMINIMAL_STACK_SIZE + 200, NULL, configMAX_PRIORITIES - 1, &ll_task_h); #endif @@ -46,6 +46,6 @@ nimble_port_freertos_init(TaskFunction_t host_task_fn) * have separate task for NimBLE host, but since something needs to handle * default queue it is just easier to make separate task which does this. */ - xTaskCreate(host_task_fn, "ble", configMINIMAL_STACK_SIZE + 400, + xTaskCreate(host_task_fn, "ble", configMINIMAL_STACK_SIZE + 600, NULL, tskIDLE_PRIORITY + 1, &host_task_h); } diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 215c78a..79384a5 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -259,8 +259,9 @@ void SystemTask::Work() { displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToRunning); heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::WakeUp); - if (!bleController.IsConnected()) + if (!bleController.IsConnected()) { nimbleController.RestartFastAdv(); + } isSleeping = false; isWakingUp = false; -- cgit v0.10.2 From f1fc7ee6593aa7dd2212ee362729b9cd06b054a9 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Fri, 12 Nov 2021 02:11:39 +0000 Subject: Adjust systemtask to respect doNotGoToSleep. diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 79384a5..0244045 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -280,6 +280,9 @@ void SystemTask::Work() { } } break; case Messages::GoToSleep: + if (doNotGoToSleep) { + return; + } isGoingToSleep = true; NRF_LOG_INFO("[systemtask] Going to sleep"); xTimerStop(idleTimer, 0); @@ -506,7 +509,7 @@ void SystemTask::OnTouchEvent() { } void SystemTask::PushMessage(System::Messages msg) { - if (msg == Messages::GoToSleep) { + if (msg == Messages::GoToSleep && !doNotGoToSleep) { isGoingToSleep = true; } -- cgit v0.10.2 From cd593c3862b1cb43865fb9075273dc97dfe5b7f1 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Mon, 15 Nov 2021 15:27:36 +0000 Subject: Break not return thanks @FintasticMan diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 0244045..4076d57 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -281,7 +281,7 @@ void SystemTask::Work() { } break; case Messages::GoToSleep: if (doNotGoToSleep) { - return; + break; } isGoingToSleep = true; NRF_LOG_INFO("[systemtask] Going to sleep"); -- cgit v0.10.2 From b946b8d156175309ab778038dab75ec7996c05bc Mon Sep 17 00:00:00 2001 From: "James A. Jerkins" Date: Fri, 3 Dec 2021 19:10:34 -0600 Subject: Fix assertion failure in ButtonHandler FreeRTOS says zero is not a valid value for xTimerPeriodInTicks. Zero value fires an assertion on line 361 in timers.h diff --git a/src/buttonhandler/ButtonHandler.cpp b/src/buttonhandler/ButtonHandler.cpp index 91e8bbd..02ee22c 100644 --- a/src/buttonhandler/ButtonHandler.cpp +++ b/src/buttonhandler/ButtonHandler.cpp @@ -8,7 +8,7 @@ void ButtonTimerCallback(TimerHandle_t xTimer) { } void ButtonHandler::Init(Pinetime::System::SystemTask* systemTask) { - buttonTimer = xTimerCreate("buttonTimer", 0, pdFALSE, systemTask, ButtonTimerCallback); + buttonTimer = xTimerCreate("buttonTimer", pdMS_TO_TICKS(200), pdFALSE, systemTask, ButtonTimerCallback); } ButtonActions ButtonHandler::HandleEvent(Events event) { -- cgit v0.10.2 From 8539db0884c73c929399ed684051318ebff6a3aa Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Mon, 6 Dec 2021 10:55:45 +0100 Subject: Alignment fixes diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index 781a359..e80f3e6 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -67,19 +67,19 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app, lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Convert(settingsController.GetPTSColorBG())); lv_obj_set_style_local_radius(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); lv_obj_set_size(timebar, 200, 240); - lv_obj_align(timebar, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 5, 0); + lv_obj_align(timebar, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 0, 0); // Display the time timeDD1 = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &open_sans_light); lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(settingsController.GetPTSColorTime())); - lv_label_set_text(timeDD1, "12"); + lv_label_set_text(timeDD1, "00"); lv_obj_align(timeDD1, timebar, LV_ALIGN_IN_TOP_MID, 5, 5); timeDD2 = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_font(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &open_sans_light); lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, Convert(settingsController.GetPTSColorTime())); - lv_label_set_text(timeDD2, "34"); + lv_label_set_text(timeDD2, "00"); lv_obj_align(timeDD2, timebar, LV_ALIGN_IN_BOTTOM_MID, 5, -5); timeAMPM = lv_label_create(lv_scr_act(), nullptr); @@ -104,11 +104,9 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app, bleIcon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); - lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); notificationIcon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); - lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 40); // Calendar icon calendarOuter = lv_obj_create(lv_scr_act(), nullptr); @@ -235,6 +233,15 @@ void PineTimeStyle::Refresh() { lv_obj_realign(notificationIcon); } + if (notificationState.Get() && bleState.Get()) { + lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 8, 25); + lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, -8, 25); + } else if (notificationState.Get() && !bleState.Get()) { + lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); + } else { + lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); + } + currentDateTime = dateTimeController.CurrentDateTime(); if (currentDateTime.IsUpdated()) { auto newDateTime = currentDateTime.Get(); -- cgit v0.10.2 From f4daf63679d309ff761f087fa1436524281bf5b9 Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Mon, 6 Dec 2021 22:01:49 +0100 Subject: Adjust icon alignment only on IsUpdated() diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index e80f3e6..f0a6592 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -104,9 +104,11 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app, bleIcon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_label_set_text(bleIcon, ""); notificationIcon = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_label_set_text(notificationIcon, ""); // Calendar icon calendarOuter = lv_obj_create(lv_scr_act(), nullptr); @@ -205,6 +207,17 @@ void PineTimeStyle::SetBatteryIcon() { lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent)); } +void PineTimeStyle::AlignIcons() { + if (notificationState.Get() && bleState.Get()) { + lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 8, 25); + lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, -8, 25); + } else if (notificationState.Get() && !bleState.Get()) { + lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); + } else { + lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); + } +} + void PineTimeStyle::Refresh() { isCharging = batteryController.IsCharging(); if (isCharging.IsUpdated()) { @@ -224,22 +237,15 @@ void PineTimeStyle::Refresh() { bleState = bleController.IsConnected(); if (bleState.IsUpdated()) { lv_label_set_text(bleIcon, BleIcon::GetIcon(bleState.Get())); - lv_obj_realign(bleIcon); + //lv_obj_realign(bleIcon); + AlignIcons(); } notificationState = notificatioManager.AreNewNotificationsAvailable(); if (notificationState.IsUpdated()) { lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(notificationState.Get())); - lv_obj_realign(notificationIcon); - } - - if (notificationState.Get() && bleState.Get()) { - lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 8, 25); - lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, -8, 25); - } else if (notificationState.Get() && !bleState.Get()) { - lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); - } else { - lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25); + //lv_obj_realign(notificationIcon); + AlignIcons(); } currentDateTime = dateTimeController.CurrentDateTime(); diff --git a/src/displayapp/screens/PineTimeStyle.h b/src/displayapp/screens/PineTimeStyle.h index f86f4c5..8382c53 100644 --- a/src/displayapp/screens/PineTimeStyle.h +++ b/src/displayapp/screens/PineTimeStyle.h @@ -77,6 +77,7 @@ namespace Pinetime { Controllers::MotionController& motionController; void SetBatteryIcon(); + void AlignIcons(); lv_task_t* taskRefresh; }; -- cgit v0.10.2 From 645f6f43dc956e90243aa9230876e537af84e1f6 Mon Sep 17 00:00:00 2001 From: Kieran Cawthray Date: Mon, 6 Dec 2021 22:04:38 +0100 Subject: Remove commented code diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp index f0a6592..d436869 100644 --- a/src/displayapp/screens/PineTimeStyle.cpp +++ b/src/displayapp/screens/PineTimeStyle.cpp @@ -237,14 +237,12 @@ void PineTimeStyle::Refresh() { bleState = bleController.IsConnected(); if (bleState.IsUpdated()) { lv_label_set_text(bleIcon, BleIcon::GetIcon(bleState.Get())); - //lv_obj_realign(bleIcon); AlignIcons(); } notificationState = notificatioManager.AreNewNotificationsAvailable(); if (notificationState.IsUpdated()) { lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(notificationState.Get())); - //lv_obj_realign(notificationIcon); AlignIcons(); } -- cgit v0.10.2 From 6a442b90a1d310d082e2626128d0f2bf8e932851 Mon Sep 17 00:00:00 2001 From: Avamander Date: Sun, 5 Dec 2021 22:22:06 +0200 Subject: Improved format specifiers, bracing, removed C-style casts, whitespace fixes and removed Tiles shadowing diff --git a/src/displayapp/screens/Alarm.cpp b/src/displayapp/screens/Alarm.cpp index 772e5d4..537ac0e 100644 --- a/src/displayapp/screens/Alarm.cpp +++ b/src/displayapp/screens/Alarm.cpp @@ -36,7 +36,7 @@ Alarm::Alarm(DisplayApp* app, Controllers::AlarmController& alarmController) alarmHours = alarmController.Hours(); alarmMinutes = alarmController.Minutes(); - lv_label_set_text_fmt(time, "%02lu:%02lu", alarmHours, alarmMinutes); + lv_label_set_text_fmt(time, "%02hhu:%02hhu", alarmHours, alarmMinutes); lv_obj_align(time, lv_scr_act(), LV_ALIGN_CENTER, 0, -25); @@ -223,7 +223,7 @@ void Alarm::ShowInfo() { auto secToAlarm = timeToAlarm % 60; lv_label_set_text_fmt( - txtMessage, "Time to\nalarm:\n%2d Days\n%2d Hours\n%2d Minutes\n%2d Seconds", daysToAlarm, hrsToAlarm, minToAlarm, secToAlarm); + txtMessage, "Time to\nalarm:\n%2lu Days\n%2lu Hours\n%2lu Minutes\n%2lu Seconds", daysToAlarm, hrsToAlarm, minToAlarm, secToAlarm); } else { lv_label_set_text(txtMessage, "Alarm\nis not\nset."); } diff --git a/src/displayapp/screens/FirmwareValidation.cpp b/src/displayapp/screens/FirmwareValidation.cpp index ea41713..c7a5b27 100644 --- a/src/displayapp/screens/FirmwareValidation.cpp +++ b/src/displayapp/screens/FirmwareValidation.cpp @@ -18,7 +18,7 @@ FirmwareValidation::FirmwareValidation(Pinetime::Applications::DisplayApp* app, : Screen {app}, validator {validator} { labelVersion = lv_label_create(lv_scr_act(), nullptr); lv_label_set_text_fmt(labelVersion, - "Version : %d.%d.%d\n" + "Version : %lu.%lu.%lu\n" "ShortRef : %s", Version::Major(), Version::Minor(), diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp index 0762626..e0138f8 100644 --- a/src/displayapp/screens/SystemInfo.cpp +++ b/src/displayapp/screens/SystemInfo.cpp @@ -1,3 +1,5 @@ +#include +#include #include "displayapp/screens/SystemInfo.h" #include #include "displayapp/DisplayApp.h" @@ -41,8 +43,8 @@ SystemInfo::SystemInfo(Pinetime::Applications::DisplayApp* app, brightnessController {brightnessController}, bleController {bleController}, watchdog {watchdog}, - motionController{motionController}, - touchPanel{touchPanel}, + motionController {motionController}, + touchPanel {touchPanel}, screens {app, 0, {[this]() -> std::unique_ptr { @@ -182,7 +184,7 @@ std::unique_ptr SystemInfo::CreateScreen3() { " #444444 used# %d (%d%%)\n" " #444444 max used# %lu\n" " #444444 frag# %d%%\n" - " #444444 free# %d", + " #444444 free# %d", bleAddr[5], bleAddr[4], bleAddr[3], diff --git a/src/displayapp/screens/Twos.cpp b/src/displayapp/screens/Twos.cpp index a1f0ba2..b15332f 100644 --- a/src/displayapp/screens/Twos.cpp +++ b/src/displayapp/screens/Twos.cpp @@ -129,7 +129,7 @@ bool Twos::placeNewTile() { return true; } -bool Twos::tryMerge(Tile grid[][4], int& newRow, int& newCol, int oldRow, int oldCol) { +bool Twos::tryMerge(TwosTile grid[][4], int& newRow, int& newCol, int oldRow, int oldCol) { if ((grid[newRow][newCol].value == grid[oldRow][oldCol].value)) { if ((newCol != oldCol) || (newRow != oldRow)) { if (!grid[newRow][newCol].merged) { @@ -146,7 +146,7 @@ bool Twos::tryMerge(Tile grid[][4], int& newRow, int& newCol, int oldRow, int ol return false; } -bool Twos::tryMove(Tile grid[][4], int newRow, int newCol, int oldRow, int oldCol) { +bool Twos::tryMove(TwosTile grid[][4], int newRow, int newCol, int oldRow, int oldCol) { if (((newCol >= 0) && (newCol != oldCol)) || ((newRow >= 0) && (newRow != oldRow))) { grid[newRow][newCol].value = grid[oldRow][oldCol].value; grid[oldRow][oldCol].value = 0; @@ -261,7 +261,7 @@ bool Twos::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return false; } -void Twos::updateGridDisplay(Tile grid[][4]) { +void Twos::updateGridDisplay(TwosTile grid[][4]) { for (int row = 0; row < 4; row++) { for (int col = 0; col < 4; col++) { if (grid[row][col].value) { diff --git a/src/displayapp/screens/Twos.h b/src/displayapp/screens/Twos.h index 48ea079..5a0c435 100644 --- a/src/displayapp/screens/Twos.h +++ b/src/displayapp/screens/Twos.h @@ -5,7 +5,7 @@ namespace Pinetime { namespace Applications { - struct Tile { + struct TwosTile { bool merged = false; unsigned int value = 0; }; @@ -26,11 +26,11 @@ namespace Pinetime { lv_obj_t* scoreText; lv_obj_t* gridDisplay; - Tile grid[4][4]; + TwosTile grid[4][4]; unsigned int score = 0; - void updateGridDisplay(Tile grid[][4]); - bool tryMerge(Tile grid[][4], int& newRow, int& newCol, int oldRow, int oldCol); - bool tryMove(Tile grid[][4], int newRow, int newCol, int oldRow, int oldCol); + void updateGridDisplay(TwosTile grid[][4]); + bool tryMerge(TwosTile grid[][4], int& newRow, int& newCol, int oldRow, int oldCol); + bool tryMove(TwosTile grid[][4], int newRow, int newCol, int oldRow, int oldCol); bool placeNewTile(); }; } diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 4076d57..24790a1 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -115,8 +115,9 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi, void SystemTask::Start() { systemTasksMsgQueue = xQueueCreate(10, 1); - if (pdPASS != xTaskCreate(SystemTask::Process, "MAIN", 350, this, 0, &taskHandle)) + if (pdPASS != xTaskCreate(SystemTask::Process, "MAIN", 350, this, 0, &taskHandle)) { APP_ERROR_HANDLER(NRF_ERROR_NO_MEM); + } } void SystemTask::Process(void* instance) { @@ -187,20 +188,22 @@ void SystemTask::Work() { pinConfig.skip_gpio_setup = false; pinConfig.hi_accuracy = false; pinConfig.is_watcher = false; - pinConfig.sense = (nrf_gpiote_polarity_t) NRF_GPIOTE_POLARITY_TOGGLE; - pinConfig.pull = (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pulldown; + pinConfig.sense = static_cast(NRF_GPIOTE_POLARITY_TOGGLE); + pinConfig.pull = static_cast(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); + nrf_gpio_cfg_sense_input(PinMap::Cst816sIrq, + static_cast(GPIO_PIN_CNF_PULL_Pullup), + static_cast GPIO_PIN_CNF_SENSE_Low); pinConfig.skip_gpio_setup = true; pinConfig.hi_accuracy = false; pinConfig.is_watcher = false; - pinConfig.sense = (nrf_gpiote_polarity_t) NRF_GPIOTE_POLARITY_HITOLO; - pinConfig.pull = (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pullup; + pinConfig.sense = static_cast(NRF_GPIOTE_POLARITY_HITOLO); + pinConfig.pull = static_cast GPIO_PIN_CNF_PULL_Pullup; nrfx_gpiote_in_init(PinMap::Cst816sIrq, &pinConfig, nrfx_gpiote_evt_handler); @@ -328,8 +331,9 @@ void SystemTask::Work() { break; case Messages::BleFirmwareUpdateStarted: doNotGoToSleep = true; - if (isSleeping && !isWakingUp) + if (isSleeping && !isWakingUp) { GoToRunning(); + } displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted); break; case Messages::BleFirmwareUpdateFinished: @@ -429,18 +433,20 @@ void SystemTask::Work() { uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG); dateTimeController.UpdateTime(systick_counter); NoInit_BackUpTime = dateTimeController.CurrentDateTime(); - if (!nrf_gpio_pin_read(PinMap::Button)) + if (!nrf_gpio_pin_read(PinMap::Button)) { watchdog.Kick(); + } } -// Clear diagnostic suppression -#pragma clang diagnostic pop } + void SystemTask::UpdateMotion() { - if (isGoingToSleep or isWakingUp) + if (isGoingToSleep or isWakingUp) { return; + } - if (isSleeping && !settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist)) + if (isSleeping && !settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist)) { return; + } if (stepCounterMustBeReset) { motionSensor.ResetStepCounter(); @@ -489,15 +495,17 @@ void SystemTask::HandleButtonAction(Controllers::ButtonActions action) { } void SystemTask::GoToRunning() { - if (isGoingToSleep or (not isSleeping) or isWakingUp) + if (isGoingToSleep or (not isSleeping) or isWakingUp) { return; + } isWakingUp = true; PushMessage(Messages::GoToRunning); } void SystemTask::OnTouchEvent() { - if (isGoingToSleep) + if (isGoingToSleep) { return; + } if (!isSleeping) { PushMessage(Messages::OnTouchEvent); } else if (!isWakingUp) { @@ -527,8 +535,9 @@ void SystemTask::PushMessage(System::Messages msg) { } void SystemTask::OnDim() { - if (doNotGoToSleep) + if (doNotGoToSleep) { return; + } NRF_LOG_INFO("Dim timeout -> Dim screen") displayApp.PushMessage(Pinetime::Applications::Display::Messages::DimScreen); xTimerStart(idleTimer, 0); @@ -536,15 +545,17 @@ void SystemTask::OnDim() { } void SystemTask::OnIdle() { - if (doNotGoToSleep) + if (doNotGoToSleep) { return; + } NRF_LOG_INFO("Idle timeout -> Going to sleep") PushMessage(Messages::GoToSleep); } void SystemTask::ReloadIdleTimer() { - if (isSleeping || isGoingToSleep) + if (isSleeping || isGoingToSleep) { return; + } if (isDimmed) { displayApp.PushMessage(Pinetime::Applications::Display::Messages::RestoreBrightness); isDimmed = false; -- cgit v0.10.2 From 9db5d64441562a61216fd9c62067f33b24df751f Mon Sep 17 00:00:00 2001 From: Avamander Date: Mon, 6 Dec 2021 19:15:03 +0200 Subject: Fixed unpopped diagnostic diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 24790a1..28f8124 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -224,7 +224,6 @@ void SystemTask::Work() { xTimerStart(dimTimer, 0); xTimerStart(measureBatteryTimer, portMAX_DELAY); -// Suppress endless loop diagnostic #pragma clang diagnostic push #pragma ide diagnostic ignored "EndlessLoop" while (true) { @@ -437,6 +436,7 @@ void SystemTask::Work() { watchdog.Kick(); } } +#pragma clang diagnostic pop } void SystemTask::UpdateMotion() { -- cgit v0.10.2 From 23f318c3d09d9707b9a38528eaf6c37b2754f6e2 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Sun, 5 Dec 2021 14:32:26 +0100 Subject: TouchHandler: remove unused FreeRTOS.h and task.h includes from header FreeRTOS and task.h aren't used in the Header file. Furthermore the SystemTask forward declaration isn't needed as it isn't used in the header. diff --git a/src/touchhandler/TouchHandler.h b/src/touchhandler/TouchHandler.h index f544293..ed452b3 100644 --- a/src/touchhandler/TouchHandler.h +++ b/src/touchhandler/TouchHandler.h @@ -1,8 +1,6 @@ #pragma once #include "drivers/Cst816s.h" #include "systemtask/SystemTask.h" -#include -#include namespace Pinetime { namespace Components { @@ -11,9 +9,6 @@ namespace Pinetime { namespace Drivers { class Cst816S; } - namespace System { - class SystemTask; - } namespace Controllers { class TouchHandler { public: -- cgit v0.10.2 From e104f17b1bc7bbdccacae4a068413ae3838cb96b Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Sun, 5 Dec 2021 12:03:16 +0100 Subject: AlarmController: remove unused app_timer.h include in header diff --git a/src/components/alarm/AlarmController.h b/src/components/alarm/AlarmController.h index bf85d43..f39fbde 100644 --- a/src/components/alarm/AlarmController.h +++ b/src/components/alarm/AlarmController.h @@ -18,7 +18,6 @@ #pragma once #include -#include "app_timer.h" #include "components/datetime/DateTimeController.h" namespace Pinetime { -- cgit v0.10.2 From 589733d11e623ea66ee0bba231f53c67ce04ce7a Mon Sep 17 00:00:00 2001 From: Avamander Date: Sat, 4 Dec 2021 22:25:02 +0200 Subject: Style improvements diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index 0a675c8..f050e65 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -506,8 +506,9 @@ void DisplayApp::SetFullRefresh(DisplayApp::FullRefreshDirections direction) { } void DisplayApp::PushMessageToSystemTask(Pinetime::System::Messages message) { - if (systemTask != nullptr) + if (systemTask != nullptr) { systemTask->PushMessage(message); + } } void DisplayApp::Register(Pinetime::System::SystemTask* systemTask) { -- cgit v0.10.2 From 9ffd28f735fd2a184f03b2ce4a46a24b7de10ba4 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 20 Sep 2021 15:13:46 +0300 Subject: Style checkboxes as radio buttons diff --git a/src/displayapp/lv_pinetime_theme.c b/src/displayapp/lv_pinetime_theme.c index 1780e64..b74b2fd 100644 --- a/src/displayapp/lv_pinetime_theme.c +++ b/src/displayapp/lv_pinetime_theme.c @@ -119,7 +119,6 @@ static void basic_init(void) { lv_style_set_bg_color(&style_btn, LV_STATE_DISABLED | LV_STATE_CHECKED, lv_color_hex3(0x888)); lv_style_set_border_color(&style_btn, LV_STATE_DEFAULT, theme.color_primary); lv_style_set_border_width(&style_btn, LV_STATE_DEFAULT, 0); - lv_style_set_border_opa(&style_btn, LV_STATE_CHECKED, LV_OPA_TRANSP); lv_style_set_text_color(&style_btn, LV_STATE_DEFAULT, lv_color_hex(0xffffff)); lv_style_set_text_color(&style_btn, LV_STATE_CHECKED, lv_color_hex(0xffffff)); diff --git a/src/displayapp/screens/settings/SettingDisplay.cpp b/src/displayapp/screens/settings/SettingDisplay.cpp index 666dfb8..9e835f6 100644 --- a/src/displayapp/screens/settings/SettingDisplay.cpp +++ b/src/displayapp/screens/settings/SettingDisplay.cpp @@ -40,39 +40,24 @@ SettingDisplay::SettingDisplay(Pinetime::Applications::DisplayApp* app, Pinetime lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); - optionsTotal = 0; - cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " 5 seconds"); - cbOption[optionsTotal]->user_data = this; - lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.GetScreenTimeOut() == 5000) { - lv_checkbox_set_checked(cbOption[optionsTotal], true); - } - optionsTotal++; - cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " 15 seconds"); - cbOption[optionsTotal]->user_data = this; - lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.GetScreenTimeOut() == 15000) { - lv_checkbox_set_checked(cbOption[optionsTotal], true); - } - optionsTotal++; - cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " 20 seconds"); - cbOption[optionsTotal]->user_data = this; - lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.GetScreenTimeOut() == 20000) { - lv_checkbox_set_checked(cbOption[optionsTotal], true); - } - optionsTotal++; - cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " 30 seconds"); - cbOption[optionsTotal]->user_data = this; - lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.GetScreenTimeOut() == 30000) { - lv_checkbox_set_checked(cbOption[optionsTotal], true); + char buffer[12]; + for (unsigned int i = 0; i < options.size(); i++) { + cbOption[i] = lv_checkbox_create(container1, nullptr); + sprintf(buffer, "%3d seconds", options[i] / 1000); + lv_checkbox_set_text(cbOption[i], buffer); + cbOption[i]->user_data = this; + lv_obj_set_event_cb(cbOption[i], event_handler); + + // radio button style + lv_obj_set_style_local_radius(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); + lv_obj_set_style_local_border_width(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, 9); + lv_obj_set_style_local_border_color(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_GREEN); + lv_obj_set_style_local_bg_color(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_WHITE); + + if (settingsController.GetScreenTimeOut() == options[i]) { + lv_checkbox_set_checked(cbOption[i], true); + } } - optionsTotal++; } SettingDisplay::~SettingDisplay() { @@ -82,25 +67,11 @@ SettingDisplay::~SettingDisplay() { void SettingDisplay::UpdateSelected(lv_obj_t* object, lv_event_t event) { if (event == LV_EVENT_CLICKED) { - for (int i = 0; i < optionsTotal; i++) { + for (unsigned int i = 0; i < options.size(); i++) { if (object == cbOption[i]) { lv_checkbox_set_checked(cbOption[i], true); - - if (i == 0) { - settingsController.SetScreenTimeOut(5000); - }; - if (i == 1) { - settingsController.SetScreenTimeOut(15000); - }; - if (i == 2) { - settingsController.SetScreenTimeOut(20000); - }; - if (i == 3) { - settingsController.SetScreenTimeOut(30000); - }; - + settingsController.SetScreenTimeOut(options[i]); app->PushMessage(Applications::Display::Messages::UpdateTimeOut); - } else { lv_checkbox_set_checked(cbOption[i], false); } diff --git a/src/displayapp/screens/settings/SettingDisplay.h b/src/displayapp/screens/settings/SettingDisplay.h index 51b23ac..dba6b43 100644 --- a/src/displayapp/screens/settings/SettingDisplay.h +++ b/src/displayapp/screens/settings/SettingDisplay.h @@ -1,9 +1,10 @@ #pragma once -#include -#include #include "components/settings/Settings.h" #include "displayapp/screens/Screen.h" +#include +#include +#include namespace Pinetime { @@ -18,8 +19,8 @@ namespace Pinetime { void UpdateSelected(lv_obj_t* object, lv_event_t event); private: + const std::array options = {5000, 15000, 20000, 30000}; Controllers::Settings& settingsController; - uint8_t optionsTotal; lv_obj_t* cbOption[4]; }; } diff --git a/src/displayapp/screens/settings/SettingTimeFormat.cpp b/src/displayapp/screens/settings/SettingTimeFormat.cpp index c6bdf40..52ce94b 100644 --- a/src/displayapp/screens/settings/SettingTimeFormat.cpp +++ b/src/displayapp/screens/settings/SettingTimeFormat.cpp @@ -39,24 +39,24 @@ SettingTimeFormat::SettingTimeFormat(Pinetime::Applications::DisplayApp* app, Pi lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); - optionsTotal = 0; - cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " 12-hour"); - cbOption[optionsTotal]->user_data = this; - lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { - lv_checkbox_set_checked(cbOption[optionsTotal], true); + for (unsigned int i = 0; i < options.size(); i++) { + cbOption[i] = lv_checkbox_create(container1, nullptr); + lv_checkbox_set_text(cbOption[i], options[i].c_str()); + cbOption[i]->user_data = this; + lv_obj_set_event_cb(cbOption[i], event_handler); + + // radio button style + lv_obj_set_style_local_radius(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); + lv_obj_set_style_local_border_width(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, 9); + lv_obj_set_style_local_border_color(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_GREEN); + lv_obj_set_style_local_bg_color(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_WHITE); } - optionsTotal++; - cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " 24-hour"); - cbOption[optionsTotal]->user_data = this; - lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) { - lv_checkbox_set_checked(cbOption[optionsTotal], true); + if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { + lv_checkbox_set_checked(cbOption[0], true); + } else if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) { + lv_checkbox_set_checked(cbOption[1], true); } - optionsTotal++; } SettingTimeFormat::~SettingTimeFormat() { @@ -66,7 +66,7 @@ SettingTimeFormat::~SettingTimeFormat() { void SettingTimeFormat::UpdateSelected(lv_obj_t* object, lv_event_t event) { if (event == LV_EVENT_VALUE_CHANGED) { - for (int i = 0; i < optionsTotal; i++) { + for (unsigned int i = 0; i < options.size(); i++) { if (object == cbOption[i]) { lv_checkbox_set_checked(cbOption[i], true); diff --git a/src/displayapp/screens/settings/SettingTimeFormat.h b/src/displayapp/screens/settings/SettingTimeFormat.h index eac4bdc..0113e35 100644 --- a/src/displayapp/screens/settings/SettingTimeFormat.h +++ b/src/displayapp/screens/settings/SettingTimeFormat.h @@ -1,9 +1,10 @@ #pragma once -#include -#include #include "components/settings/Settings.h" #include "displayapp/screens/Screen.h" +#include +#include +#include namespace Pinetime { @@ -18,8 +19,9 @@ namespace Pinetime { void UpdateSelected(lv_obj_t* object, lv_event_t event); private: + const std::array options = {" 12-hour", " 24-hour"}; + Controllers::Settings& settingsController; - uint8_t optionsTotal; lv_obj_t* cbOption[2]; }; } diff --git a/src/displayapp/screens/settings/SettingWatchFace.cpp b/src/displayapp/screens/settings/SettingWatchFace.cpp index 8e6e7cf..8bb8759 100644 --- a/src/displayapp/screens/settings/SettingWatchFace.cpp +++ b/src/displayapp/screens/settings/SettingWatchFace.cpp @@ -40,34 +40,22 @@ SettingWatchFace::SettingWatchFace(Pinetime::Applications::DisplayApp* app, Pine lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER); lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0); - optionsTotal = 0; - cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " Digital face"); - cbOption[optionsTotal]->user_data = this; - lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.GetClockFace() == 0) { - lv_checkbox_set_checked(cbOption[optionsTotal], true); - } + for (unsigned int i = 0; i < options.size(); i++) { + cbOption[i] = lv_checkbox_create(container1, nullptr); + lv_checkbox_set_text(cbOption[i], options[i].c_str()); + cbOption[i]->user_data = this; + lv_obj_set_event_cb(cbOption[i], event_handler); - optionsTotal++; - cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " Analog face"); - cbOption[optionsTotal]->user_data = this; - lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.GetClockFace() == 1) { - lv_checkbox_set_checked(cbOption[optionsTotal], true); - } + // radio button style + lv_obj_set_style_local_radius(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); + lv_obj_set_style_local_border_width(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, 9); + lv_obj_set_style_local_border_color(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_GREEN); + lv_obj_set_style_local_bg_color(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_WHITE); - optionsTotal++; - cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text_static(cbOption[optionsTotal], " PineTimeStyle"); - cbOption[optionsTotal]->user_data = this; - lv_obj_set_event_cb(cbOption[optionsTotal], event_handler); - if (settingsController.GetClockFace() == 2) { - lv_checkbox_set_checked(cbOption[optionsTotal], true); + if (settingsController.GetClockFace() == i) { + lv_checkbox_set_checked(cbOption[i], true); + } } - - optionsTotal++; } SettingWatchFace::~SettingWatchFace() { @@ -77,7 +65,7 @@ SettingWatchFace::~SettingWatchFace() { void SettingWatchFace::UpdateSelected(lv_obj_t* object, lv_event_t event) { if (event == LV_EVENT_VALUE_CHANGED) { - for (uint8_t i = 0; i < optionsTotal; i++) { + for (unsigned int i = 0; i < options.size(); i++) { if (object == cbOption[i]) { lv_checkbox_set_checked(cbOption[i], true); settingsController.SetClockFace(i); diff --git a/src/displayapp/screens/settings/SettingWatchFace.h b/src/displayapp/screens/settings/SettingWatchFace.h index d4a96c6..1863458 100644 --- a/src/displayapp/screens/settings/SettingWatchFace.h +++ b/src/displayapp/screens/settings/SettingWatchFace.h @@ -1,9 +1,10 @@ #pragma once -#include -#include #include "components/settings/Settings.h" #include "displayapp/screens/Screen.h" +#include +#include +#include namespace Pinetime { @@ -18,8 +19,9 @@ namespace Pinetime { void UpdateSelected(lv_obj_t* object, lv_event_t event); private: + const std::array options = {" Digital face", " Analog face", " PineTimeStyle"}; Controllers::Settings& settingsController; - uint8_t optionsTotal; + lv_obj_t* cbOption[2]; }; } -- cgit v0.10.2 From 494448b7ccada7e314310bb471c33c550e0e8bdf Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 20 Sep 2021 15:27:32 +0300 Subject: Fix too small array diff --git a/src/displayapp/screens/settings/SettingWatchFace.h b/src/displayapp/screens/settings/SettingWatchFace.h index 1863458..8c6f653 100644 --- a/src/displayapp/screens/settings/SettingWatchFace.h +++ b/src/displayapp/screens/settings/SettingWatchFace.h @@ -22,7 +22,7 @@ namespace Pinetime { const std::array options = {" Digital face", " Analog face", " PineTimeStyle"}; Controllers::Settings& settingsController; - lv_obj_t* cbOption[2]; + lv_obj_t* cbOption[3]; }; } } -- cgit v0.10.2 From 736ae08fcdd3f87a6412985eec131179d8cc6664 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Thu, 23 Sep 2021 02:27:09 +0300 Subject: Optimize arrays diff --git a/src/displayapp/screens/settings/SettingDisplay.cpp b/src/displayapp/screens/settings/SettingDisplay.cpp index 9e835f6..a92d76f 100644 --- a/src/displayapp/screens/settings/SettingDisplay.cpp +++ b/src/displayapp/screens/settings/SettingDisplay.cpp @@ -14,6 +14,8 @@ namespace { } } +constexpr std::array SettingDisplay::options; + SettingDisplay::SettingDisplay(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) : Screen(app), settingsController {settingsController} { diff --git a/src/displayapp/screens/settings/SettingDisplay.h b/src/displayapp/screens/settings/SettingDisplay.h index dba6b43..1309f8c 100644 --- a/src/displayapp/screens/settings/SettingDisplay.h +++ b/src/displayapp/screens/settings/SettingDisplay.h @@ -19,9 +19,10 @@ namespace Pinetime { void UpdateSelected(lv_obj_t* object, lv_event_t event); private: - const std::array options = {5000, 15000, 20000, 30000}; + static constexpr std::array options = {5000, 15000, 20000, 30000}; + Controllers::Settings& settingsController; - lv_obj_t* cbOption[4]; + lv_obj_t* cbOption[options.size()]; }; } } diff --git a/src/displayapp/screens/settings/SettingTimeFormat.cpp b/src/displayapp/screens/settings/SettingTimeFormat.cpp index 52ce94b..e65cb9e 100644 --- a/src/displayapp/screens/settings/SettingTimeFormat.cpp +++ b/src/displayapp/screens/settings/SettingTimeFormat.cpp @@ -13,6 +13,8 @@ namespace { } } +constexpr std::array SettingTimeFormat::options; + SettingTimeFormat::SettingTimeFormat(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) : Screen(app), settingsController {settingsController} { @@ -41,7 +43,7 @@ SettingTimeFormat::SettingTimeFormat(Pinetime::Applications::DisplayApp* app, Pi for (unsigned int i = 0; i < options.size(); i++) { cbOption[i] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text(cbOption[i], options[i].c_str()); + lv_checkbox_set_text(cbOption[i], options[i]); cbOption[i]->user_data = this; lv_obj_set_event_cb(cbOption[i], event_handler); diff --git a/src/displayapp/screens/settings/SettingTimeFormat.h b/src/displayapp/screens/settings/SettingTimeFormat.h index 0113e35..fa24eab 100644 --- a/src/displayapp/screens/settings/SettingTimeFormat.h +++ b/src/displayapp/screens/settings/SettingTimeFormat.h @@ -19,10 +19,9 @@ namespace Pinetime { void UpdateSelected(lv_obj_t* object, lv_event_t event); private: - const std::array options = {" 12-hour", " 24-hour"}; - + static constexpr std::array options = {" 12-hour", " 24-hour"}; Controllers::Settings& settingsController; - lv_obj_t* cbOption[2]; + lv_obj_t* cbOption[options.size()]; }; } } diff --git a/src/displayapp/screens/settings/SettingWatchFace.cpp b/src/displayapp/screens/settings/SettingWatchFace.cpp index 8bb8759..0166ae9 100644 --- a/src/displayapp/screens/settings/SettingWatchFace.cpp +++ b/src/displayapp/screens/settings/SettingWatchFace.cpp @@ -13,6 +13,8 @@ namespace { } } +constexpr std::array SettingWatchFace::options; + SettingWatchFace::SettingWatchFace(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController) : Screen(app), settingsController {settingsController} { @@ -42,7 +44,7 @@ SettingWatchFace::SettingWatchFace(Pinetime::Applications::DisplayApp* app, Pine for (unsigned int i = 0; i < options.size(); i++) { cbOption[i] = lv_checkbox_create(container1, nullptr); - lv_checkbox_set_text(cbOption[i], options[i].c_str()); + lv_checkbox_set_text(cbOption[i], options[i]); cbOption[i]->user_data = this; lv_obj_set_event_cb(cbOption[i], event_handler); diff --git a/src/displayapp/screens/settings/SettingWatchFace.h b/src/displayapp/screens/settings/SettingWatchFace.h index 8c6f653..281c4ba 100644 --- a/src/displayapp/screens/settings/SettingWatchFace.h +++ b/src/displayapp/screens/settings/SettingWatchFace.h @@ -19,10 +19,10 @@ namespace Pinetime { void UpdateSelected(lv_obj_t* object, lv_event_t event); private: - const std::array options = {" Digital face", " Analog face", " PineTimeStyle"}; + static constexpr std::array options = {" Digital face", " Analog face", " PineTimeStyle"}; Controllers::Settings& settingsController; - lv_obj_t* cbOption[3]; + lv_obj_t* cbOption[options.size()]; }; } } -- cgit v0.10.2 From ec9b5a0bd2847d972c285d46e28deba0241d3a47 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Thu, 23 Sep 2021 02:53:10 +0300 Subject: Move radio button styling to a single place diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5591dbc..480b4e6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -434,6 +434,7 @@ list(APPEND SOURCE_FILES displayapp/screens/PassKey.cpp displayapp/screens/Error.cpp displayapp/screens/Alarm.cpp + displayapp/screens/Styles.cpp displayapp/Colors.cpp ## Settings diff --git a/src/displayapp/screens/Styles.cpp b/src/displayapp/screens/Styles.cpp new file mode 100644 index 0000000..7f43fb9 --- /dev/null +++ b/src/displayapp/screens/Styles.cpp @@ -0,0 +1,8 @@ +#include "Styles.h" + +void Pinetime::Applications::Screens::SetRadioButtonStyle(lv_obj_t* checkbox) { + lv_obj_set_style_local_radius(checkbox, LV_CHECKBOX_PART_BULLET, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); + lv_obj_set_style_local_border_width(checkbox, LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, 9); + lv_obj_set_style_local_border_color(checkbox, LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_GREEN); + lv_obj_set_style_local_bg_color(checkbox, LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_WHITE); +} diff --git a/src/displayapp/screens/Styles.h b/src/displayapp/screens/Styles.h new file mode 100644 index 0000000..a5fbb9f --- /dev/null +++ b/src/displayapp/screens/Styles.h @@ -0,0 +1,9 @@ +#include + +namespace Pinetime { + namespace Applications { + namespace Screens { + void SetRadioButtonStyle(lv_obj_t* checkbox); + } + } +} diff --git a/src/displayapp/screens/settings/SettingDisplay.cpp b/src/displayapp/screens/settings/SettingDisplay.cpp index a92d76f..9e972af 100644 --- a/src/displayapp/screens/settings/SettingDisplay.cpp +++ b/src/displayapp/screens/settings/SettingDisplay.cpp @@ -2,6 +2,7 @@ #include #include "displayapp/DisplayApp.h" #include "displayapp/Messages.h" +#include "displayapp/screens/Styles.h" #include "displayapp/screens/Screen.h" #include "displayapp/screens/Symbols.h" @@ -49,12 +50,7 @@ SettingDisplay::SettingDisplay(Pinetime::Applications::DisplayApp* app, Pinetime lv_checkbox_set_text(cbOption[i], buffer); cbOption[i]->user_data = this; lv_obj_set_event_cb(cbOption[i], event_handler); - - // radio button style - lv_obj_set_style_local_radius(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); - lv_obj_set_style_local_border_width(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, 9); - lv_obj_set_style_local_border_color(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_GREEN); - lv_obj_set_style_local_bg_color(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_WHITE); + SetRadioButtonStyle(cbOption[i]); if (settingsController.GetScreenTimeOut() == options[i]) { lv_checkbox_set_checked(cbOption[i], true); diff --git a/src/displayapp/screens/settings/SettingTimeFormat.cpp b/src/displayapp/screens/settings/SettingTimeFormat.cpp index e65cb9e..bd9af15 100644 --- a/src/displayapp/screens/settings/SettingTimeFormat.cpp +++ b/src/displayapp/screens/settings/SettingTimeFormat.cpp @@ -1,6 +1,7 @@ #include "displayapp/screens/settings/SettingTimeFormat.h" #include #include "displayapp/DisplayApp.h" +#include "displayapp/screens/Styles.h" #include "displayapp/screens/Screen.h" #include "displayapp/screens/Symbols.h" @@ -46,12 +47,7 @@ SettingTimeFormat::SettingTimeFormat(Pinetime::Applications::DisplayApp* app, Pi lv_checkbox_set_text(cbOption[i], options[i]); cbOption[i]->user_data = this; lv_obj_set_event_cb(cbOption[i], event_handler); - - // radio button style - lv_obj_set_style_local_radius(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); - lv_obj_set_style_local_border_width(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, 9); - lv_obj_set_style_local_border_color(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_GREEN); - lv_obj_set_style_local_bg_color(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_WHITE); + SetRadioButtonStyle(cbOption[i]); } if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { diff --git a/src/displayapp/screens/settings/SettingWatchFace.cpp b/src/displayapp/screens/settings/SettingWatchFace.cpp index 0166ae9..a24eaa1 100644 --- a/src/displayapp/screens/settings/SettingWatchFace.cpp +++ b/src/displayapp/screens/settings/SettingWatchFace.cpp @@ -2,6 +2,7 @@ #include #include "displayapp/DisplayApp.h" #include "displayapp/screens/Screen.h" +#include "displayapp/screens/Styles.h" #include "displayapp/screens/Symbols.h" using namespace Pinetime::Applications::Screens; @@ -47,12 +48,7 @@ SettingWatchFace::SettingWatchFace(Pinetime::Applications::DisplayApp* app, Pine lv_checkbox_set_text(cbOption[i], options[i]); cbOption[i]->user_data = this; lv_obj_set_event_cb(cbOption[i], event_handler); - - // radio button style - lv_obj_set_style_local_radius(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE); - lv_obj_set_style_local_border_width(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, 9); - lv_obj_set_style_local_border_color(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_GREEN); - lv_obj_set_style_local_bg_color(cbOption[i], LV_CHECKBOX_PART_BULLET, LV_STATE_CHECKED, LV_COLOR_WHITE); + SetRadioButtonStyle(cbOption[i]); if (settingsController.GetClockFace() == i) { lv_checkbox_set_checked(cbOption[i], true); -- cgit v0.10.2 From 32ea01b2e94a2acd5084eacf49df8695ab488a19 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Fri, 3 Dec 2021 21:39:18 +0200 Subject: Organize includes diff --git a/src/displayapp/screens/settings/SettingDisplay.h b/src/displayapp/screens/settings/SettingDisplay.h index 1309f8c..dc56419 100644 --- a/src/displayapp/screens/settings/SettingDisplay.h +++ b/src/displayapp/screens/settings/SettingDisplay.h @@ -1,11 +1,12 @@ #pragma once -#include "components/settings/Settings.h" -#include "displayapp/screens/Screen.h" #include #include #include +#include "components/settings/Settings.h" +#include "displayapp/screens/Screen.h" + namespace Pinetime { namespace Applications { diff --git a/src/displayapp/screens/settings/SettingTimeFormat.h b/src/displayapp/screens/settings/SettingTimeFormat.h index fa24eab..818edf0 100644 --- a/src/displayapp/screens/settings/SettingTimeFormat.h +++ b/src/displayapp/screens/settings/SettingTimeFormat.h @@ -1,11 +1,12 @@ #pragma once -#include "components/settings/Settings.h" -#include "displayapp/screens/Screen.h" #include #include #include +#include "components/settings/Settings.h" +#include "displayapp/screens/Screen.h" + namespace Pinetime { namespace Applications { diff --git a/src/displayapp/screens/settings/SettingWatchFace.h b/src/displayapp/screens/settings/SettingWatchFace.h index 281c4ba..ccba7d1 100644 --- a/src/displayapp/screens/settings/SettingWatchFace.h +++ b/src/displayapp/screens/settings/SettingWatchFace.h @@ -1,11 +1,12 @@ #pragma once -#include "components/settings/Settings.h" -#include "displayapp/screens/Screen.h" #include #include #include +#include "components/settings/Settings.h" +#include "displayapp/screens/Screen.h" + namespace Pinetime { namespace Applications { -- cgit v0.10.2 From 6354511c20f611659c63801c9f6d3129d30b6d50 Mon Sep 17 00:00:00 2001 From: Avamander Date: Thu, 9 Dec 2021 22:51:42 +0200 Subject: Hotfix for other build targets diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 480b4e6..d08ea07 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1023,7 +1023,7 @@ endif() set(EXECUTABLE_RECOVERYLOADER_NAME "pinetime-recovery-loader") set(EXECUTABLE_RECOVERYLOADER_FILE_NAME ${EXECUTABLE_RECOVERYLOADER_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}) add_executable(${EXECUTABLE_RECOVERYLOADER_NAME} ${RECOVERYLOADER_SOURCE_FILES}) -target_link_libraries(${EXECUTABLE_RECOVERYLOADER_NAME} nrf-sdk) +target_link_libraries(${EXECUTABLE_RECOVERYLOADER_NAME} nrf-sdk QCBOR) set_target_properties(${EXECUTABLE_RECOVERYLOADER_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERYLOADER_FILE_NAME}) target_compile_options(${EXECUTABLE_RECOVERYLOADER_NAME} PUBLIC $<$,$>: ${COMMON_FLAGS} -Og -g3> @@ -1056,7 +1056,7 @@ set(EXECUTABLE_MCUBOOT_RECOVERYLOADER_FILE_NAME ${EXECUTABLE_MCUBOOT_RECOVERYLOA set(IMAGE_MCUBOOT_RECOVERYLOADER_FILE_NAME ${EXECUTABLE_MCUBOOT_RECOVERYLOADER_NAME}-image-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.bin) set(DFU_MCUBOOT_RECOVERYLOADER_FILE_NAME ${EXECUTABLE_MCUBOOT_RECOVERYLOADER_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip) add_executable(${EXECUTABLE_MCUBOOT_RECOVERYLOADER_NAME} ${RECOVERYLOADER_SOURCE_FILES}) -target_link_libraries(${EXECUTABLE_MCUBOOT_RECOVERYLOADER_NAME} nrf-sdk) +target_link_libraries(${EXECUTABLE_MCUBOOT_RECOVERYLOADER_NAME} nrf-sdk QCBOR) set_target_properties(${EXECUTABLE_MCUBOOT_RECOVERYLOADER_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_MCUBOOT_RECOVERYLOADER_FILE_NAME}) target_compile_options(${EXECUTABLE_MCUBOOT_RECOVERYLOADER_NAME} PUBLIC $<$,$>: ${COMMON_FLAGS} -Og -g3> -- cgit v0.10.2 From 42a5cdb5b776c2cdeb08a8c6f26606282a809178 Mon Sep 17 00:00:00 2001 From: Avamander Date: Thu, 9 Dec 2021 22:56:37 +0200 Subject: Added QCBOR to pinetime-mcuboot-recovery diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d08ea07..bb9f76f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -985,7 +985,7 @@ set(EXECUTABLE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-${ set(IMAGE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-image-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.bin) set(DFU_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip) add_executable(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} ${RECOVERY_SOURCE_FILES}) -target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk littlefs) +target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk littlefs QCBOR) set_target_properties(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_FILE_NAME}) target_compile_definitions(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC "PINETIME_IS_RECOVERY") target_compile_options(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC -- cgit v0.10.2 From f57f797ff54d9ee8864d3fc62f0c8662df13aad8 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sun, 17 Oct 2021 01:09:26 +0000 Subject: Added Blank FSService that exposes only version info diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index bb9f76f..809544c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -487,6 +487,7 @@ list(APPEND SOURCE_FILES components/ble/NavigationService.cpp displayapp/fonts/lv_font_navi_80.c components/ble/BatteryInformationService.cpp + components/ble/FSService.cpp components/ble/ImmediateAlertService.cpp components/ble/ServiceDiscovery.cpp components/ble/HeartRateService.cpp @@ -557,6 +558,7 @@ list(APPEND RECOVERY_SOURCE_FILES components/ble/MusicService.cpp components/ble/weather/WeatherService.cpp components/ble/BatteryInformationService.cpp + components/ble/FSService.cpp components/ble/ImmediateAlertService.cpp components/ble/ServiceDiscovery.cpp components/ble/NavigationService.cpp @@ -669,6 +671,7 @@ set(INCLUDE_FILES components/ble/DfuService.h components/firmwarevalidator/FirmwareValidator.h components/ble/BatteryInformationService.h + components/ble/FSService.h components/ble/ImmediateAlertService.h components/ble/ServiceDiscovery.h components/ble/BleClient.h diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp new file mode 100644 index 0000000..6551c20 --- /dev/null +++ b/src/components/ble/FSService.cpp @@ -0,0 +1,55 @@ +#include +#include "FSService.h" + +using namespace Pinetime::Controllers; + +constexpr ble_uuid128_t FSService::fsServiceUuid; +constexpr ble_uuid128_t FSService::fsVersionUuid; +constexpr ble_uuid128_t FSService::fsTransferUuid; + +int FSServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) { + auto* fsService = static_cast(arg); + return fsService->OnFSServiceRequested(conn_handle, attr_handle, ctxt); +} + +FSService::FSService(Pinetime::Controllers::FS& fs) + : fs {fs}, + characteristicDefinition {{.uuid = &fsVersionUuid.u, + .access_cb = FSServiceCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_READ, + .val_handle = &versionCharacteristicHandle}, + { + .uuid = &fsTransferUuid.u, + .access_cb = FSServiceCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, + .val_handle = nullptr, + }, + {0}}, + serviceDefinition { + {/* Device Information Service */ + .type = BLE_GATT_SVC_TYPE_PRIMARY, + .uuid = &fsServiceUuid.u, + .characteristics = characteristicDefinition}, + {0}, + } { +} + +void FSService::Init() { + int res = 0; + res = ble_gatts_count_cfg(serviceDefinition); + ASSERT(res == 0); + + res = ble_gatts_add_svcs(serviceDefinition); + ASSERT(res == 0); +} + +int FSService::OnFSServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context) { + if (attributeHandle == versionCharacteristicHandle) { + NRF_LOG_INFO("FS_S : handle = %d", versionCharacteristicHandle); + int res = os_mbuf_append(context->om, &fsVersion, sizeof(fsVersion)); + return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + } + return 0; +} diff --git a/src/components/ble/FSService.h b/src/components/ble/FSService.h new file mode 100644 index 0000000..85b484a --- /dev/null +++ b/src/components/ble/FSService.h @@ -0,0 +1,65 @@ +#pragma once +#define min // workaround: nimble's min/max macros conflict with libstdc++ +#define max +#include +#undef max +#undef min +#include "components/fs/FS.h" + +namespace Pinetime { + namespace System { + class SystemTask; + } + namespace Controllers { + class Ble; + class FSService { + public: + FSService(Pinetime::Controllers::FS& fs); + void Init(); + + int OnFSServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context); + void NotifyFSRaw(uint16_t connectionHandle); + + private: + Pinetime::Controllers::FS& fs; + static constexpr uint16_t FSServiceId {0xFEBB}; + static constexpr uint16_t fsVersionId {0x0100}; + static constexpr uint16_t fsTransferId {0x0200}; + uint16_t fsVersion = {0x0004}; + + static constexpr ble_uuid128_t fsServiceUuid { + .u {.type = BLE_UUID_TYPE_128}, + .value = {0x72, 0x65, 0x66, 0x73, 0x6e, 0x61, 0x72, 0x54, 0x65, 0x6c, 0x69, 0x46, 0xBB, 0xFE, 0xAF, 0xAD}}; + + static constexpr ble_uuid128_t fsVersionUuid { + .u {.type = BLE_UUID_TYPE_128}, + .value = {0x72, 0x65, 0x66, 0x73, 0x6e, 0x61, 0x72, 0x54, 0x65, 0x6c, 0x69, 0x46, 0x00, 0x01, 0xAF, 0xAD}}; + + static constexpr ble_uuid128_t fsTransferUuid { + .u {.type = BLE_UUID_TYPE_128}, + .value = {0x72, 0x65, 0x66, 0x73, 0x6e, 0x61, 0x72, 0x54, 0x65, 0x6c, 0x69, 0x46, 0x00, 0x02, 0xAF, 0xAD}}; + + struct ble_gatt_chr_def characteristicDefinition[3]; + struct ble_gatt_svc_def serviceDefinition[2]; + uint16_t versionCharacteristicHandle; + + enum class commands { + INVALID = 0x00, + READ = 0x10, + READ_DATA = 0x11, + READ_PACING = 0x12, + WRITE = 0x20, + WRITE_PACING = 0x21, + WRITE_DATA = 0x22, + DELETE = 0x30, + DELETE_STATUS = 0x31, + MKDIR = 0x40, + MKDIR_STATUS = 0x41, + LISTDIR = 0x50, + LISTDIR_ENTRY = 0x51, + MOVE = 0x60, + MOVE_STATUS = 0x61, + } + }; + } +} diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index acf4f94..b5eb46b 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -30,7 +30,7 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, Pinetime::Drivers::SpiNorFlash& spiNorFlash, Controllers::HeartRateController& heartRateController, Controllers::MotionController& motionController, - Pinetime::Controllers::FS& fs) + Controllers::FS& fs) : systemTask {systemTask}, bleController {bleController}, dateTimeController {dateTimeController}, @@ -49,7 +49,9 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, batteryInformationService {batteryController}, immediateAlertService {systemTask, notificationManager}, heartRateService {systemTask, heartRateController}, - motionService {systemTask, motionController}, + motionService{systemTask, motionController}, + fs {fs}, + fsService {fs}, serviceDiscovery({¤tTimeClient, &alertNotificationClient}) { } @@ -97,7 +99,8 @@ void NimbleController::Init() { immediateAlertService.Init(); heartRateService.Init(); motionService.Init(); - + fsService.Init(); + int rc; rc = ble_hs_util_ensure_addr(0); ASSERT(rc == 0); diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 12bd692..14749b8 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -22,6 +22,7 @@ #include "components/ble/MotionService.h" #include "components/ble/weather/WeatherService.h" #include "components/fs/FS.h" +#include "components/ble/FSService.h" namespace Pinetime { namespace Drivers { @@ -110,6 +111,8 @@ namespace Pinetime { HeartRateService heartRateService; MotionService motionService; ServiceDiscovery serviceDiscovery; + FS fs; + FSService fsService; uint8_t addrType; uint16_t connectionHandle = BLE_HS_CONN_HANDLE_NONE; -- cgit v0.10.2 From 91c644b43c250b0a03047349182828df31ddcbd2 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sun, 17 Oct 2021 16:04:23 +0000 Subject: direcetory listings maybe? Added LISTDIR command and notify responses. diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 6551c20..2cfd5cc 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -1,5 +1,6 @@ #include #include "FSService.h" +#include "components/ble/BleController.h" using namespace Pinetime::Controllers; @@ -13,8 +14,8 @@ int FSServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gat } FSService::FSService(Pinetime::Controllers::FS& fs) - : fs {fs}, - characteristicDefinition {{.uuid = &fsVersionUuid.u, + : fs {fs}, + characteristicDefinition {{.uuid = &fsVersionUuid.u, .access_cb = FSServiceCallback, .arg = this, .flags = BLE_GATT_CHR_F_READ, @@ -24,7 +25,7 @@ FSService::FSService(Pinetime::Controllers::FS& fs) .access_cb = FSServiceCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, - .val_handle = nullptr, + .val_handle = &transferCharacteristicHandle, }, {0}}, serviceDefinition { @@ -51,5 +52,71 @@ int FSService::OnFSServiceRequested(uint16_t connectionHandle, uint16_t attribut int res = os_mbuf_append(context->om, &fsVersion, sizeof(fsVersion)); return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; } + if (attributeHandle == transferCharacteristicHandle) { + return FSCommandHandler(connectionHandle, context->om); + } + return 0; +} + +int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { + auto command = static_cast(om->om_data[0]); + NRF_LOG_INFO("[FS_S] -> FSCommandHandler"); + + switch (command) { + case commands::LISTDIR: { + NRF_LOG_INFO("[FS_S] -> ListDir"); + ListDirHeader *header = (ListDirHeader *)&om->om_data[0]; + uint16_t plen = header->pathlen; + char path[plen+1] = {0}; + memcpy(path, header->pathstr, plen); + NRF_LOG_INFO("[FS_S] -> DIR %.10s", path); + lfs_dir_t dir; + struct lfs_info info; + + ListDirResponse resp; + resp.command = 0x51; // LISTDIR_ENTRY; + resp.status = 1; // TODO actually use res above! + resp.totalentries = 0; + resp.entry = 0; + int res = fs.DirOpen(path, &dir); + while (fs.DirRead(&dir, &info)) { + resp.totalentries++; + } + NRF_LOG_INFO("[FS_S] -> %d ", resp.totalentries); + fs.DirClose(&dir); + fs.DirOpen(path, &dir); + while (fs.DirRead(&dir, &info)) { + switch(info.type){ + case LFS_TYPE_REG: + { + resp.flags = 0; + resp.file_size = info.size; + break; + } + case LFS_TYPE_DIR: + { + resp.flags = 1; + resp.file_size = 0; + break; + } + } + resp.modification_time = 0; // TODO Does LFS actually support TS? + strcpy(resp.path,info.name); + resp.path_length = strlen(info.name); + NRF_LOG_INFO("[FS_S] ->Path %s ,", info.name); + auto* om = ble_hs_mbuf_from_flat(&resp,sizeof(ListDirResponse)); + ble_gattc_notify_custom(connectionHandle,transferCharacteristicHandle,om); + resp.entry++; + } + resp.entry++; + resp.file_size = 0; + resp.path_length = 0; + resp.flags = 0; + //Todo this better + auto* om = ble_hs_mbuf_from_flat(&resp,sizeof(ListDirResponse)-70+resp.path_length); + ble_gattc_notify_custom(connectionHandle,transferCharacteristicHandle,om); + NRF_LOG_INFO("[FS_S] -> done "); + } + } return 0; } diff --git a/src/components/ble/FSService.h b/src/components/ble/FSService.h index 85b484a..eb4b34d 100644 --- a/src/components/ble/FSService.h +++ b/src/components/ble/FSService.h @@ -4,6 +4,7 @@ #include #undef max #undef min + #include "components/fs/FS.h" namespace Pinetime { @@ -42,8 +43,26 @@ namespace Pinetime { struct ble_gatt_chr_def characteristicDefinition[3]; struct ble_gatt_svc_def serviceDefinition[2]; uint16_t versionCharacteristicHandle; + uint16_t transferCharacteristicHandle; + typedef struct __attribute__((packed)) { + uint8_t command; + uint8_t padding; + uint16_t pathlen; + char pathstr[70]; + } ListDirHeader; + typedef struct __attribute__((packed)) { + uint8_t command; + uint8_t status; + uint16_t path_length; + uint32_t entry; + uint32_t totalentries; + uint32_t flags; + uint32_t modification_time; + uint32_t file_size; + char path[70]; + } ListDirResponse; - enum class commands { + enum class commands : uint8_t { INVALID = 0x00, READ = 0x10, READ_DATA = 0x11, @@ -58,8 +77,10 @@ namespace Pinetime { LISTDIR = 0x50, LISTDIR_ENTRY = 0x51, MOVE = 0x60, - MOVE_STATUS = 0x61, - } + MOVE_STATUS = 0x61 + }; + + int FSCommandHandler(uint16_t connectionHandle, os_mbuf* om); }; } } diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp index 1cad4f0..f287c28 100644 --- a/src/components/fs/FS.cpp +++ b/src/components/fs/FS.cpp @@ -5,29 +5,28 @@ using namespace Pinetime::Controllers; -FS::FS(Pinetime::Drivers::SpiNorFlash& driver) : - flashDriver{ driver }, - lfsConfig{ - .context = this, - .read = SectorRead, - .prog = SectorProg, - .erase = SectorErase, - .sync = SectorSync, - - .read_size = 16, - .prog_size = 8, - .block_size = blockSize, - .block_count = size / blockSize, - .block_cycles = 1000u, - - .cache_size = 16, - .lookahead_size = 16, - - .name_max = 50, - .attr_max = 50, - } -{ } - +FS::FS(Pinetime::Drivers::SpiNorFlash& driver) + : flashDriver {driver}, + lfsConfig { + .context = this, + .read = SectorRead, + .prog = SectorProg, + .erase = SectorErase, + .sync = SectorSync, + + .read_size = 16, + .prog_size = 8, + .block_size = blockSize, + .block_count = size / blockSize, + .block_cycles = 1000u, + + .cache_size = 16, + .lookahead_size = 16, + + .name_max = 50, + .attr_max = 50, + } { +} void FS::Init() { @@ -48,7 +47,6 @@ void FS::Init() { VerifyResource(); LVGLFileSystemInit(); #endif - } void FS::VerifyResource() { @@ -56,7 +54,7 @@ void FS::VerifyResource() { resourcesValid = true; } -int FS::FileOpen(lfs_file_t* file_p, const char* fileName, const int flags) { +int FS::FileOpen(lfs_file_t* file_p, const char* fileName, const int flags) { return lfs_file_open(&lfs, file_p, fileName, flags); } @@ -80,6 +78,17 @@ int FS::FileDelete(const char* fileName) { return lfs_remove(&lfs, fileName); } +int FS::DirOpen(const char* path, lfs_dir_t* lfs_dir) { + return lfs_dir_open(&lfs, lfs_dir, path); +} + +int FS::DirClose(lfs_dir_t* lfs_dir) { + return lfs_dir_close(&lfs, lfs_dir); +} + +int FS::DirRead(lfs_dir_t* dir, lfs_info* info) { + return lfs_dir_read(&lfs, dir, info); +} int FS::DirCreate(const char* path) { return lfs_mkdir(&lfs, path); @@ -148,8 +157,7 @@ namespace { if (file->type == 0) { return LV_FS_RES_FS_ERR; - } - else { + } else { return LV_FS_RES_OK; } } @@ -193,5 +201,4 @@ void FS::LVGLFileSystemInit() { fs_drv.user_data = this; lv_fs_drv_register(&fs_drv); - } \ No newline at end of file diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h index 75ba16c..28d28d3 100644 --- a/src/components/fs/FS.h +++ b/src/components/fs/FS.h @@ -21,6 +21,9 @@ namespace Pinetime { int FileDelete(const char* fileName); + int DirOpen(const char* path, lfs_dir_t* lfs_dir); + int DirClose(lfs_dir_t* lfs_dir); + int DirRead(lfs_dir_t* dir, lfs_info* info); int DirCreate(const char* path); int DirDelete(const char* path); -- cgit v0.10.2 From 1dd71744802b4ae80c8952f73bbf0051fbe12cf3 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sun, 17 Oct 2021 20:48:34 +0000 Subject: More reliable FS listing diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 2cfd5cc..2f02cd9 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -70,21 +70,26 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { char path[plen+1] = {0}; memcpy(path, header->pathstr, plen); NRF_LOG_INFO("[FS_S] -> DIR %.10s", path); - lfs_dir_t dir; - struct lfs_info info; + lfs_dir_t dir = {}; + struct lfs_info info = {}; - ListDirResponse resp; + ListDirResponse resp = {}; resp.command = 0x51; // LISTDIR_ENTRY; resp.status = 1; // TODO actually use res above! resp.totalentries = 0; resp.entry = 0; + int sr; int res = fs.DirOpen(path, &dir); + + NRF_LOG_INFO("[FS_S] ->diropen %d ", res); while (fs.DirRead(&dir, &info)) { resp.totalentries++; + } NRF_LOG_INFO("[FS_S] -> %d ", resp.totalentries); - fs.DirClose(&dir); - fs.DirOpen(path, &dir); + + fs.DirRewind(&dir); + while (fs.DirRead(&dir, &info)) { switch(info.type){ case LFS_TYPE_REG: @@ -106,8 +111,10 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { NRF_LOG_INFO("[FS_S] ->Path %s ,", info.name); auto* om = ble_hs_mbuf_from_flat(&resp,sizeof(ListDirResponse)); ble_gattc_notify_custom(connectionHandle,transferCharacteristicHandle,om); + vTaskDelay(1); //Allow stuff to actually go out over the BLE conn resp.entry++; } + fs.DirClose(&dir); resp.entry++; resp.file_size = 0; resp.path_length = 0; diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp index f287c28..353193d 100644 --- a/src/components/fs/FS.cpp +++ b/src/components/fs/FS.cpp @@ -89,7 +89,9 @@ int FS::DirClose(lfs_dir_t* lfs_dir) { int FS::DirRead(lfs_dir_t* dir, lfs_info* info) { return lfs_dir_read(&lfs, dir, info); } - +int FS::DirRewind(lfs_dir_t* dir) { + return lfs_dir_rewind(&lfs, dir); +} int FS::DirCreate(const char* path) { return lfs_mkdir(&lfs, path); } diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h index 28d28d3..ccff240 100644 --- a/src/components/fs/FS.h +++ b/src/components/fs/FS.h @@ -24,6 +24,7 @@ namespace Pinetime { int DirOpen(const char* path, lfs_dir_t* lfs_dir); int DirClose(lfs_dir_t* lfs_dir); int DirRead(lfs_dir_t* dir, lfs_info* info); + int DirRewind(lfs_dir_t* dir); int DirCreate(const char* path); int DirDelete(const char* path); -- cgit v0.10.2 From 2690c274af72cfbac88a8c83fce311665a917a93 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sun, 17 Oct 2021 21:33:01 +0000 Subject: Workaround for SPI bus being asleep. This needs to get cherrypicked to another PR as SPI Sleep needs to use a semaphore or something diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp index 747dbc8..4492e89 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/SpiMaster.cpp @@ -10,7 +10,7 @@ SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters } bool SpiMaster::Init() { - if(mutex == nullptr) { + if (mutex == nullptr) { mutex = xSemaphoreCreateBinary(); ASSERT(mutex != nullptr); } @@ -179,6 +179,10 @@ void SpiMaster::PrepareRx(const volatile uint32_t cmdAddress, bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size) { if (data == nullptr) return false; + + if (!active) { + Wakeup(); + } auto ok = xSemaphoreTake(mutex, portMAX_DELAY); ASSERT(ok == true); taskToNotify = xTaskGetCurrentTaskHandle(); @@ -215,7 +219,9 @@ bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size) { bool SpiMaster::Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) { xSemaphoreTake(mutex, portMAX_DELAY); - + if (!active) { + Wakeup(); + } taskToNotify = nullptr; this->pinCsn = pinCsn; @@ -253,12 +259,16 @@ void SpiMaster::Sleep() { nrf_gpio_cfg_default(params.pinSCK); nrf_gpio_cfg_default(params.pinMOSI); nrf_gpio_cfg_default(params.pinMISO); - + active = false; NRF_LOG_INFO("[SPIMASTER] sleep") } void SpiMaster::Wakeup() { + if (active) { + return; + } Init(); + active = true; NRF_LOG_INFO("[SPIMASTER] Wakeup"); } diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h index 5ea624f..f5d2b12 100644 --- a/src/drivers/SpiMaster.h +++ b/src/drivers/SpiMaster.h @@ -60,6 +60,8 @@ namespace Pinetime { volatile size_t currentBufferSize = 0; volatile TaskHandle_t taskToNotify; SemaphoreHandle_t mutex = nullptr; + + bool active; }; } } -- cgit v0.10.2 From eabbbfa373de04d1dc694618d5a9d475f0918592 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sun, 17 Oct 2021 22:07:43 +0000 Subject: Fix folder count in output diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 2f02cd9..40679e5 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -78,7 +78,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.status = 1; // TODO actually use res above! resp.totalentries = 0; resp.entry = 0; - int sr; + int res = fs.DirOpen(path, &dir); NRF_LOG_INFO("[FS_S] ->diropen %d ", res); @@ -115,7 +115,6 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.entry++; } fs.DirClose(&dir); - resp.entry++; resp.file_size = 0; resp.path_length = 0; resp.flags = 0; @@ -123,6 +122,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { auto* om = ble_hs_mbuf_from_flat(&resp,sizeof(ListDirResponse)-70+resp.path_length); ble_gattc_notify_custom(connectionHandle,transferCharacteristicHandle,om); NRF_LOG_INFO("[FS_S] -> done "); + break; } } return 0; diff --git a/src/components/ble/FSService.h b/src/components/ble/FSService.h index eb4b34d..a1c42aa 100644 --- a/src/components/ble/FSService.h +++ b/src/components/ble/FSService.h @@ -44,23 +44,8 @@ namespace Pinetime { struct ble_gatt_svc_def serviceDefinition[2]; uint16_t versionCharacteristicHandle; uint16_t transferCharacteristicHandle; - typedef struct __attribute__((packed)) { - uint8_t command; - uint8_t padding; - uint16_t pathlen; - char pathstr[70]; - } ListDirHeader; - typedef struct __attribute__((packed)) { - uint8_t command; - uint8_t status; - uint16_t path_length; - uint32_t entry; - uint32_t totalentries; - uint32_t flags; - uint32_t modification_time; - uint32_t file_size; - char path[70]; - } ListDirResponse; + + int FSCommandHandler(uint16_t connectionHandle, os_mbuf* om); enum class commands : uint8_t { INVALID = 0x00, @@ -80,7 +65,42 @@ namespace Pinetime { MOVE_STATUS = 0x61 }; - int FSCommandHandler(uint16_t connectionHandle, os_mbuf* om); + using ListDirHeader = struct __attribute__((packed)) { + uint8_t command; + uint8_t padding; + uint16_t pathlen; + char pathstr[70]; + }; + + using ListDirResponse = struct __attribute__((packed)) { + uint8_t command; + uint8_t status; + uint16_t path_length; + uint32_t entry; + uint32_t totalentries; + uint32_t flags; + uint32_t modification_time; + uint32_t file_size; + char path[70]; + }; + + using MKDirHeader = struct __attribute__((packed)) { + uint8_t command; + uint8_t padding; + uint16_t pathlen; + uint32_t padding2; + uint64_t time; + char pathstr[70]; + }; + + using MKDirResponse = struct __attribute__((packed)) { + uint8_t command; + uint8_t status; + uint32_t padding1; + uint16_t padding2; + uint64_t modification_time; + }; + }; } } -- cgit v0.10.2 From 3a8e66a52fcc6317a7dffa15cb161f37a645d36c Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sun, 17 Oct 2021 23:07:43 +0000 Subject: Added Delete file Added FS Stat. diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 40679e5..0cf2b93 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -63,64 +63,112 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { NRF_LOG_INFO("[FS_S] -> FSCommandHandler"); switch (command) { + case commands::DELETE: { + NRF_LOG_INFO("[FS_S] -> Delete"); + auto* header = (DelHeader*)om->om_data; + uint16_t plen = header->pathlen; + char path[plen + 1] = {0}; + struct lfs_info info = {}; + DelResponse resp = {}; + resp.command = commands::DELETE_STATUS; + int res = fs.Stat(path, &info); + // Get Info about path + // branch for DirDel of FileDelete + if (info.type == LFS_TYPE_DIR) { + res = fs.DirDelete(path); + } else { + res = fs.FileDelete(path); + } + switch (res) { + case LFS_ERR_OK: + resp.status = 0x01; + break; + default: + resp.status = 0x02; + break; + } + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(DelResponse)); + ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); + break; + } + case commands::MKDIR: { + NRF_LOG_INFO("[FS_S] -> MKDir"); + auto* header = (MKDirHeader*) om->om_data; + uint16_t plen = header->pathlen; + char path[plen + 1] = {0}; + memcpy(path, header->pathstr, plen); + NRF_LOG_INFO("[FS_S] -> MKDIR %.10s", path); + MKDirResponse resp = {}; + resp.command = commands::MKDIR_STATUS; + int res = fs.DirCreate(path); + switch (res) { + case LFS_ERR_OK: + resp.status = 0x01; + break; + default: + resp.status = 0x02; + break; + } + resp.modification_time = 0; // We should timestamp..but no + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(MKDirResponse)); + ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); + break; + } case commands::LISTDIR: { NRF_LOG_INFO("[FS_S] -> ListDir"); - ListDirHeader *header = (ListDirHeader *)&om->om_data[0]; + ListDirHeader* header = (ListDirHeader*)om->om_data; uint16_t plen = header->pathlen; - char path[plen+1] = {0}; + char path[plen + 1] = {0}; memcpy(path, header->pathstr, plen); NRF_LOG_INFO("[FS_S] -> DIR %.10s", path); lfs_dir_t dir = {}; struct lfs_info info = {}; ListDirResponse resp = {}; - resp.command = 0x51; // LISTDIR_ENTRY; - resp.status = 1; // TODO actually use res above! + resp.command = commands::LISTDIR_ENTRY; + resp.status = 1; // TODO actually use res above! resp.totalentries = 0; resp.entry = 0; int res = fs.DirOpen(path, &dir); - + NRF_LOG_INFO("[FS_S] ->diropen %d ", res); while (fs.DirRead(&dir, &info)) { resp.totalentries++; - } NRF_LOG_INFO("[FS_S] -> %d ", resp.totalentries); - + fs.DirRewind(&dir); - + while (fs.DirRead(&dir, &info)) { - switch(info.type){ - case LFS_TYPE_REG: - { + switch (info.type) { + case LFS_TYPE_REG: { resp.flags = 0; resp.file_size = info.size; break; - } - case LFS_TYPE_DIR: - { - resp.flags = 1; - resp.file_size = 0; - break; + } + case LFS_TYPE_DIR: { + resp.flags = 1; + resp.file_size = 0; + break; } } resp.modification_time = 0; // TODO Does LFS actually support TS? - strcpy(resp.path,info.name); + strcpy(resp.path, info.name); resp.path_length = strlen(info.name); NRF_LOG_INFO("[FS_S] ->Path %s ,", info.name); - auto* om = ble_hs_mbuf_from_flat(&resp,sizeof(ListDirResponse)); - ble_gattc_notify_custom(connectionHandle,transferCharacteristicHandle,om); - vTaskDelay(1); //Allow stuff to actually go out over the BLE conn + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)); + ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); + vTaskDelay(1); // Allow stuff to actually go out over the BLE conn resp.entry++; } fs.DirClose(&dir); resp.file_size = 0; resp.path_length = 0; resp.flags = 0; - //Todo this better - auto* om = ble_hs_mbuf_from_flat(&resp,sizeof(ListDirResponse)-70+resp.path_length); - ble_gattc_notify_custom(connectionHandle,transferCharacteristicHandle,om); + // TODO Handle Size of response better. + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse) - 70 + resp.path_length); + ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); NRF_LOG_INFO("[FS_S] -> done "); break; } diff --git a/src/components/ble/FSService.h b/src/components/ble/FSService.h index a1c42aa..3ca6d93 100644 --- a/src/components/ble/FSService.h +++ b/src/components/ble/FSService.h @@ -66,14 +66,14 @@ namespace Pinetime { }; using ListDirHeader = struct __attribute__((packed)) { - uint8_t command; + commands command; uint8_t padding; uint16_t pathlen; char pathstr[70]; }; using ListDirResponse = struct __attribute__((packed)) { - uint8_t command; + commands command; uint8_t status; uint16_t path_length; uint32_t entry; @@ -85,7 +85,7 @@ namespace Pinetime { }; using MKDirHeader = struct __attribute__((packed)) { - uint8_t command; + commands command; uint8_t padding; uint16_t pathlen; uint32_t padding2; @@ -94,13 +94,25 @@ namespace Pinetime { }; using MKDirResponse = struct __attribute__((packed)) { - uint8_t command; + commands command; uint8_t status; uint32_t padding1; uint16_t padding2; uint64_t modification_time; }; + using DelHeader = struct __attribute__((packed)) { + commands command; + uint8_t padding; + uint16_t pathlen; + char pathstr[70]; + }; + + using DelResponse = struct __attribute__((packed)) { + commands command; + uint8_t status; + }; + }; } } diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp index 353193d..d30b737 100644 --- a/src/components/fs/FS.cpp +++ b/src/components/fs/FS.cpp @@ -96,6 +96,10 @@ int FS::DirCreate(const char* path) { return lfs_mkdir(&lfs, path); } +int FS::Stat(const char* path, lfs_info* info){ + return lfs_stat(&lfs,path,info); +} + // Delete directory and all files inside int FS::DirDelete(const char* path) { diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h index ccff240..e50ff10 100644 --- a/src/components/fs/FS.h +++ b/src/components/fs/FS.h @@ -28,6 +28,7 @@ namespace Pinetime { int DirCreate(const char* path); int DirDelete(const char* path); + int Stat(const char* path, lfs_info* info); void VerifyResource(); private: -- cgit v0.10.2 From 1b4b422ab6d7588e21e58fcf1d2ba04470abc611 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Mon, 18 Oct 2021 04:20:11 +0000 Subject: More attempted SPI fixes diff --git a/src/drivers/Spi.cpp b/src/drivers/Spi.cpp index e477622..4655243 100644 --- a/src/drivers/Spi.cpp +++ b/src/drivers/Spi.cpp @@ -10,14 +10,24 @@ Spi::Spi(SpiMaster& spiMaster, uint8_t pinCsn) : spiMaster {spiMaster}, pinCsn { } bool Spi::Write(const uint8_t* data, size_t size) { + if(!active){ + Wakeup(); + } return spiMaster.Write(pinCsn, data, size); } bool Spi::Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) { + if(!active){ + Wakeup(); + } return spiMaster.Read(pinCsn, cmd, cmdSize, data, dataSize); } void Spi::Sleep() { + if(!active){ + return; + } + active = false; nrf_gpio_cfg_default(pinCsn); NRF_LOG_INFO("[SPI] Sleep") } @@ -32,7 +42,11 @@ bool Spi::Init() { } void Spi::Wakeup() { + if(active){ + return; + } nrf_gpio_cfg_output(pinCsn); nrf_gpio_pin_set(pinCsn); + active=true; NRF_LOG_INFO("[SPI] Wakeup") } diff --git a/src/drivers/Spi.h b/src/drivers/Spi.h index 9b6a30f..51de2b3 100644 --- a/src/drivers/Spi.h +++ b/src/drivers/Spi.h @@ -23,6 +23,7 @@ namespace Pinetime { private: SpiMaster& spiMaster; uint8_t pinCsn; + bool active; }; } } -- cgit v0.10.2 From 8f6a390c36007eecb875bca6d8be860dbec6bd9c Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Mon, 18 Oct 2021 04:20:26 +0000 Subject: Start of read command diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 0cf2b93..52cfafb 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -4,7 +4,7 @@ using namespace Pinetime::Controllers; -constexpr ble_uuid128_t FSService::fsServiceUuid; +constexpr ble_uuid16_t FSService::fsServiceUuid; constexpr ble_uuid128_t FSService::fsVersionUuid; constexpr ble_uuid128_t FSService::fsTransferUuid; @@ -63,9 +63,90 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { NRF_LOG_INFO("[FS_S] -> FSCommandHandler"); switch (command) { + case commands::READ: { + NRF_LOG_INFO("[FS_S] -> Read"); + if (state != FSState::IDLE) { + return -1; + } + state = FSState::READ; + auto* header = (ReadHeader*) om->om_data; + uint16_t plen = header->pathlen; + if (plen > maxpathlen - 1) { + return -1; + } + memcpy(filepath, header->pathstr, plen); + filepath[plen + 1] = 0; // Copy and null teminate string + ReadResponse resp; + resp.command = commands::READ_DATA; + resp.chunkoff = header->chunkoff; + resp.status = 0x01; + struct lfs_info info = {}; + int res = fs.Stat(filepath, &info); + if (res == LFS_ERR_NOENT && info.type != LFS_TYPE_DIR) { + resp.status = 0x03; + resp.chunklen = 0; + resp.totallen = 0; + } else { + lfs_file f; + resp.chunklen = std::min(header->chunksize, info.size); + resp.totallen = info.size; + fs.FileOpen(&f, filepath, LFS_O_RDONLY); + fs.FileSeek(&f, header->chunkoff); + resp.chunklen = fs.FileRead(&f, resp.chunk, resp.chunklen); + fs.FileClose(&f); + } + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse)); + ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); + if (header->chunksize >= resp.totallen) { // probably removeable...but then usafe + state = FSState::IDLE; + } + } + case commands::READ_PACING: { + NRF_LOG_INFO("[FS_S] -> ReadPacing"); + if (state != FSState::READ) { + return -1; + } + auto* header = (ReadPacing*) om->om_data; + ReadResponse resp = {}; + + resp.command = commands::READ_DATA; + resp.chunkoff = header->chunkoff; + resp.status = 0x01; + struct lfs_info info = {}; + int res = fs.Stat(filepath, &info); + if (res == LFS_ERR_NOENT && info.type != LFS_TYPE_DIR) { + resp.status = 0x03; + resp.chunklen = 0; + resp.totallen = 0; + } else { + lfs_file f; + resp.chunklen = std::min(header->chunksize, info.size); + resp.totallen = info.size; + fs.FileOpen(&f, filepath, LFS_O_RDONLY); + fs.FileSeek(&f, header->chunkoff); + resp.chunklen = fs.FileRead(&f, resp.chunk, resp.chunklen); + fs.FileClose(&f); + } + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse)); + ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); + if (resp.chunklen >= header->chunksize) { // is this right? + state = FSState::IDLE; + } + } + case commands::WRITE: { + if (state != FSState::IDLE) { + return -1; + } + } + case commands::WRITE_PACING: { + if (state != FSState::WRITE) { + return -1; + } + } + case commands::DELETE: { NRF_LOG_INFO("[FS_S] -> Delete"); - auto* header = (DelHeader*)om->om_data; + auto* header = (DelHeader*) om->om_data; uint16_t plen = header->pathlen; char path[plen + 1] = {0}; struct lfs_info info = {}; @@ -116,7 +197,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { } case commands::LISTDIR: { NRF_LOG_INFO("[FS_S] -> ListDir"); - ListDirHeader* header = (ListDirHeader*)om->om_data; + ListDirHeader* header = (ListDirHeader*) om->om_data; uint16_t plen = header->pathlen; char path[plen + 1] = {0}; memcpy(path, header->pathstr, plen); @@ -140,7 +221,11 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { fs.DirRewind(&dir); - while (fs.DirRead(&dir, &info)) { + while (true) { + int res = fs.DirRead(&dir, &info); + if(res <= 0){ + break; + } switch (info.type) { case LFS_TYPE_REG: { resp.flags = 0; @@ -157,9 +242,9 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { strcpy(resp.path, info.name); resp.path_length = strlen(info.name); NRF_LOG_INFO("[FS_S] ->Path %s ,", info.name); - auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)); + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)+resp.path_length); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); - vTaskDelay(1); // Allow stuff to actually go out over the BLE conn + vTaskDelay(5); // Allow stuff to actually go out over the BLE conn resp.entry++; } fs.DirClose(&dir); @@ -167,7 +252,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.path_length = 0; resp.flags = 0; // TODO Handle Size of response better. - auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse) - 70 + resp.path_length); + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)+resp.path_length); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); NRF_LOG_INFO("[FS_S] -> done "); break; @@ -175,3 +260,25 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { } return 0; } +// Loads resp with file data given a valid filepath header and resp +void FSService::prepareReadDataResp(ReadHeader* header, ReadResponse* resp) { + uint16_t plen = header->pathlen; + resp->command = commands::READ_DATA; + resp->chunkoff = header->chunkoff; + resp->status = 0x01; + struct lfs_info info = {}; + int res = fs.Stat(filepath, &info); + if (res == LFS_ERR_NOENT && info.type != LFS_TYPE_DIR) { + resp->status = 0x03; + resp->chunklen = 0; + resp->totallen = 0; + } else { + lfs_file f; + resp->chunklen = std::min(header->chunksize, info.size); + resp->totallen = info.size; + fs.FileOpen(&f, filepath, LFS_O_RDONLY); + fs.FileSeek(&f, header->chunkoff); + resp->chunklen = fs.FileRead(&f, resp->chunk, resp->chunklen); + fs.FileClose(&f); + } +} diff --git a/src/components/ble/FSService.h b/src/components/ble/FSService.h index 3ca6d93..93205e5 100644 --- a/src/components/ble/FSService.h +++ b/src/components/ble/FSService.h @@ -27,10 +27,10 @@ namespace Pinetime { static constexpr uint16_t fsVersionId {0x0100}; static constexpr uint16_t fsTransferId {0x0200}; uint16_t fsVersion = {0x0004}; - - static constexpr ble_uuid128_t fsServiceUuid { - .u {.type = BLE_UUID_TYPE_128}, - .value = {0x72, 0x65, 0x66, 0x73, 0x6e, 0x61, 0x72, 0x54, 0x65, 0x6c, 0x69, 0x46, 0xBB, 0xFE, 0xAF, 0xAD}}; + static constexpr uint8_t maxpathlen = 100; + static constexpr ble_uuid16_t fsServiceUuid { + .u {.type = BLE_UUID_TYPE_16}, + .value = {0xFEBB}};// {0x72, 0x65, 0x66, 0x73, 0x6e, 0x61, 0x72, 0x54, 0x65, 0x6c, 0x69, 0x46, 0xBB, 0xFE, 0xAF, 0xAD}}; static constexpr ble_uuid128_t fsVersionUuid { .u {.type = BLE_UUID_TYPE_128}, @@ -45,8 +45,6 @@ namespace Pinetime { uint16_t versionCharacteristicHandle; uint16_t transferCharacteristicHandle; - int FSCommandHandler(uint16_t connectionHandle, os_mbuf* om); - enum class commands : uint8_t { INVALID = 0x00, READ = 0x10, @@ -64,12 +62,44 @@ namespace Pinetime { MOVE = 0x60, MOVE_STATUS = 0x61 }; + enum class FSState : uint8_t { + IDLE = 0x00, + READ = 0x01, + WRITE = 0x02, + }; + FSState state; + char filepath[maxpathlen]; // TODO ..ugh fixed filepath len + using ReadHeader = struct __attribute__((packed)) { + commands command; + uint8_t padding; + uint16_t pathlen; + uint32_t chunkoff; + uint32_t chunksize; + char pathstr[]; + }; + + using ReadResponse = struct __attribute__((packed)) { + commands command; + uint8_t status; + uint16_t padding; + uint32_t chunkoff; + uint32_t totallen; + uint32_t chunklen; + uint8_t chunk[]; + }; + using ReadPacing = struct __attribute__((packed)) { + commands command; + uint8_t status; + uint16_t padding; + uint32_t chunkoff; + uint32_t chunksize; + }; using ListDirHeader = struct __attribute__((packed)) { commands command; uint8_t padding; uint16_t pathlen; - char pathstr[70]; + char pathstr[]; }; using ListDirResponse = struct __attribute__((packed)) { @@ -81,7 +111,7 @@ namespace Pinetime { uint32_t flags; uint32_t modification_time; uint32_t file_size; - char path[70]; + char path[]; }; using MKDirHeader = struct __attribute__((packed)) { @@ -90,7 +120,7 @@ namespace Pinetime { uint16_t pathlen; uint32_t padding2; uint64_t time; - char pathstr[70]; + char pathstr[]; }; using MKDirResponse = struct __attribute__((packed)) { @@ -100,19 +130,21 @@ namespace Pinetime { uint16_t padding2; uint64_t modification_time; }; - + using DelHeader = struct __attribute__((packed)) { commands command; uint8_t padding; uint16_t pathlen; - char pathstr[70]; + char pathstr[]; }; using DelResponse = struct __attribute__((packed)) { commands command; uint8_t status; }; - + + int FSCommandHandler(uint16_t connectionHandle, os_mbuf* om); + void prepareReadDataResp(ReadHeader *header, ReadResponse *resp); }; } } -- cgit v0.10.2 From d89e38d3bf9e84e69635f0cb10cc42f0071fa038 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Tue, 19 Oct 2021 19:03:00 +0000 Subject: Focus on getting flash access working properly diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 52cfafb..0a1fabb 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -60,9 +60,10 @@ int FSService::OnFSServiceRequested(uint16_t connectionHandle, uint16_t attribut int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { auto command = static_cast(om->om_data[0]); - NRF_LOG_INFO("[FS_S] -> FSCommandHandler"); - + NRF_LOG_INFO("[FS_S] -> FSCommandHandler %d",command); + fs.Mount(); switch (command) { + /* case commands::READ: { NRF_LOG_INFO("[FS_S] -> Read"); if (state != FSState::IDLE) { @@ -194,7 +195,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(MKDirResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); break; - } + }*/ case commands::LISTDIR: { NRF_LOG_INFO("[FS_S] -> ListDir"); ListDirHeader* header = (ListDirHeader*) om->om_data; @@ -244,7 +245,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { NRF_LOG_INFO("[FS_S] ->Path %s ,", info.name); auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)+resp.path_length); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); - vTaskDelay(5); // Allow stuff to actually go out over the BLE conn + vTaskDelay(10); // Allow stuff to actually go out over the BLE conn resp.entry++; } fs.DirClose(&dir); @@ -258,6 +259,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { break; } } + fs.UnMount(); return 0; } // Loads resp with file data given a valid filepath header and resp diff --git a/src/components/ble/FSService.h b/src/components/ble/FSService.h index 93205e5..114c1e0 100644 --- a/src/components/ble/FSService.h +++ b/src/components/ble/FSService.h @@ -109,7 +109,7 @@ namespace Pinetime { uint32_t entry; uint32_t totalentries; uint32_t flags; - uint32_t modification_time; + uint64_t modification_time; uint32_t file_size; char path[]; }; diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp index d30b737..c8a5a2e 100644 --- a/src/components/fs/FS.cpp +++ b/src/components/fs/FS.cpp @@ -54,6 +54,14 @@ void FS::VerifyResource() { resourcesValid = true; } +void FS::Mount() { + flashDriver.Wakeup(); +} + +void FS::UnMount() { + flashDriver.Sleep(); +} + int FS::FileOpen(lfs_file_t* file_p, const char* fileName, const int flags) { return lfs_file_open(&lfs, file_p, fileName, flags); } @@ -96,8 +104,8 @@ int FS::DirCreate(const char* path) { return lfs_mkdir(&lfs, path); } -int FS::Stat(const char* path, lfs_info* info){ - return lfs_stat(&lfs,path,info); +int FS::Stat(const char* path, lfs_info* info) { + return lfs_stat(&lfs, path, info); } // Delete directory and all files inside diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h index e50ff10..1aa8d5f 100644 --- a/src/components/fs/FS.h +++ b/src/components/fs/FS.h @@ -13,6 +13,9 @@ namespace Pinetime { void Init(); void LVGLFileSystemInit(); + void Mount(); + void UnMount(); + int FileOpen(lfs_file_t* file_p, const char* fileName, const int flags); int FileClose(lfs_file_t* file_p); int FileRead(lfs_file_t* file_p, uint8_t* buff, uint32_t size); @@ -32,31 +35,30 @@ namespace Pinetime { void VerifyResource(); private: - Pinetime::Drivers::SpiNorFlash& flashDriver; /* - * External Flash MAP (4 MBytes) - * - * 0x000000 +---------------------------------------+ - * | Bootloader Assets | - * | 256 KBytes | - * | | - * 0x040000 +---------------------------------------+ - * | OTA | - * | 464 KBytes | - * | | - * | | - * | | - * 0x0B4000 +---------------------------------------+ - * | File System | - * | | - * | | - * | | - * | | - * 0x400000 +---------------------------------------+ - * - */ + * External Flash MAP (4 MBytes) + * + * 0x000000 +---------------------------------------+ + * | Bootloader Assets | + * | 256 KBytes | + * | | + * 0x040000 +---------------------------------------+ + * | OTA | + * | 464 KBytes | + * | | + * | | + * | | + * 0x0B4000 +---------------------------------------+ + * | File System | + * | | + * | | + * | | + * | | + * 0x400000 +---------------------------------------+ + * + */ static constexpr size_t startAddress = 0x0B4000; static constexpr size_t size = 0x34C000; static constexpr size_t blockSize = 4096; @@ -70,7 +72,6 @@ namespace Pinetime { static int SectorErase(const struct lfs_config* c, lfs_block_t block); static int SectorProg(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, const void* buffer, lfs_size_t size); static int SectorRead(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size); - }; } } -- cgit v0.10.2 From a5a64800eda02358aebe4d0f23d43ee33f363c56 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Tue, 19 Oct 2021 19:15:41 +0000 Subject: Revert "Workaround for SPI bus being asleep." This reverts commit 1edeb5cb65489707c26b7a65f3b54520086d363a. diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp index 4492e89..747dbc8 100644 --- a/src/drivers/SpiMaster.cpp +++ b/src/drivers/SpiMaster.cpp @@ -10,7 +10,7 @@ SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters } bool SpiMaster::Init() { - if (mutex == nullptr) { + if(mutex == nullptr) { mutex = xSemaphoreCreateBinary(); ASSERT(mutex != nullptr); } @@ -179,10 +179,6 @@ void SpiMaster::PrepareRx(const volatile uint32_t cmdAddress, bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size) { if (data == nullptr) return false; - - if (!active) { - Wakeup(); - } auto ok = xSemaphoreTake(mutex, portMAX_DELAY); ASSERT(ok == true); taskToNotify = xTaskGetCurrentTaskHandle(); @@ -219,9 +215,7 @@ bool SpiMaster::Write(uint8_t pinCsn, const uint8_t* data, size_t size) { bool SpiMaster::Read(uint8_t pinCsn, uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) { xSemaphoreTake(mutex, portMAX_DELAY); - if (!active) { - Wakeup(); - } + taskToNotify = nullptr; this->pinCsn = pinCsn; @@ -259,16 +253,12 @@ void SpiMaster::Sleep() { nrf_gpio_cfg_default(params.pinSCK); nrf_gpio_cfg_default(params.pinMOSI); nrf_gpio_cfg_default(params.pinMISO); - active = false; + NRF_LOG_INFO("[SPIMASTER] sleep") } void SpiMaster::Wakeup() { - if (active) { - return; - } Init(); - active = true; NRF_LOG_INFO("[SPIMASTER] Wakeup"); } diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h index f5d2b12..5ea624f 100644 --- a/src/drivers/SpiMaster.h +++ b/src/drivers/SpiMaster.h @@ -60,8 +60,6 @@ namespace Pinetime { volatile size_t currentBufferSize = 0; volatile TaskHandle_t taskToNotify; SemaphoreHandle_t mutex = nullptr; - - bool active; }; } } -- cgit v0.10.2 From f841b8c98498a01211036fd0720a1f8c949e28f2 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Tue, 19 Oct 2021 19:15:48 +0000 Subject: Revert "More attempted SPI fixes" This reverts commit bed7e731b206961117b717adb1031ab3011e7db9. diff --git a/src/drivers/Spi.cpp b/src/drivers/Spi.cpp index 4655243..e477622 100644 --- a/src/drivers/Spi.cpp +++ b/src/drivers/Spi.cpp @@ -10,24 +10,14 @@ Spi::Spi(SpiMaster& spiMaster, uint8_t pinCsn) : spiMaster {spiMaster}, pinCsn { } bool Spi::Write(const uint8_t* data, size_t size) { - if(!active){ - Wakeup(); - } return spiMaster.Write(pinCsn, data, size); } bool Spi::Read(uint8_t* cmd, size_t cmdSize, uint8_t* data, size_t dataSize) { - if(!active){ - Wakeup(); - } return spiMaster.Read(pinCsn, cmd, cmdSize, data, dataSize); } void Spi::Sleep() { - if(!active){ - return; - } - active = false; nrf_gpio_cfg_default(pinCsn); NRF_LOG_INFO("[SPI] Sleep") } @@ -42,11 +32,7 @@ bool Spi::Init() { } void Spi::Wakeup() { - if(active){ - return; - } nrf_gpio_cfg_output(pinCsn); nrf_gpio_pin_set(pinCsn); - active=true; NRF_LOG_INFO("[SPI] Wakeup") } diff --git a/src/drivers/Spi.h b/src/drivers/Spi.h index 51de2b3..9b6a30f 100644 --- a/src/drivers/Spi.h +++ b/src/drivers/Spi.h @@ -23,7 +23,6 @@ namespace Pinetime { private: SpiMaster& spiMaster; uint8_t pinCsn; - bool active; }; } } -- cgit v0.10.2 From 6393a17d7402b92e00cd748bc7e901ba053135de Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Wed, 20 Oct 2021 01:30:04 +0000 Subject: List Dir works? diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 0a1fabb..cd2cc07 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -1,6 +1,7 @@ #include #include "FSService.h" #include "components/ble/BleController.h" +#include "systemtask/SystemTask.h" using namespace Pinetime::Controllers; @@ -13,8 +14,9 @@ int FSServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gat return fsService->OnFSServiceRequested(conn_handle, attr_handle, ctxt); } -FSService::FSService(Pinetime::Controllers::FS& fs) - : fs {fs}, +FSService::FSService(Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::FS& fs) + : systemTask {systemTask}, + fs {fs}, characteristicDefinition {{.uuid = &fsVersionUuid.u, .access_cb = FSServiceCallback, .arg = this, @@ -60,8 +62,13 @@ int FSService::OnFSServiceRequested(uint16_t connectionHandle, uint16_t attribut int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { auto command = static_cast(om->om_data[0]); - NRF_LOG_INFO("[FS_S] -> FSCommandHandler %d",command); - fs.Mount(); + NRF_LOG_INFO("[FS_S] -> FSCommandHandler Command %d", command); + // Just always make sure we are awake... + systemTask.PushMessage(Pinetime::System::Messages::StartFileTransfer); + vTaskDelay(10); + while (systemTask.IsSleeping()) { + vTaskDelay(100); // 50ms + } switch (command) { /* case commands::READ: { @@ -203,6 +210,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { char path[plen + 1] = {0}; memcpy(path, header->pathstr, plen); NRF_LOG_INFO("[FS_S] -> DIR %.10s", path); + lfs_dir_t dir = {}; struct lfs_info info = {}; @@ -212,9 +220,11 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.totalentries = 0; resp.entry = 0; - int res = fs.DirOpen(path, &dir); + if (fs.DirOpen(path, &dir)) { + return 0; + } - NRF_LOG_INFO("[FS_S] ->diropen %d ", res); + // NRF_LOG_INFO("[FS_S] ->diropen %d ", res); while (fs.DirRead(&dir, &info)) { resp.totalentries++; } @@ -222,9 +232,11 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { fs.DirRewind(&dir); - while (true) { + // NRF_LOG_INFO("[FS_S] ->diropen %d ", res); + + while (resp.entry < resp.totalentries) { int res = fs.DirRead(&dir, &info); - if(res <= 0){ + if (res <= 0) { break; } switch (info.type) { @@ -243,23 +255,26 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { strcpy(resp.path, info.name); resp.path_length = strlen(info.name); NRF_LOG_INFO("[FS_S] ->Path %s ,", info.name); - auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)+resp.path_length); + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse) + resp.path_length); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); - vTaskDelay(10); // Allow stuff to actually go out over the BLE conn + vTaskDelay(100); // Allow stuff to actually go out over the BLE conn resp.entry++; } - fs.DirClose(&dir); + + if (fs.DirClose(&dir)) { + return 0; + } resp.file_size = 0; resp.path_length = 0; resp.flags = 0; // TODO Handle Size of response better. - auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)+resp.path_length); + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse) + resp.path_length); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); NRF_LOG_INFO("[FS_S] -> done "); break; } } - fs.UnMount(); + systemTask.PushMessage(Pinetime::System::Messages::StopFileTransfer); return 0; } // Loads resp with file data given a valid filepath header and resp diff --git a/src/components/ble/FSService.h b/src/components/ble/FSService.h index 114c1e0..69ed094 100644 --- a/src/components/ble/FSService.h +++ b/src/components/ble/FSService.h @@ -15,13 +15,15 @@ namespace Pinetime { class Ble; class FSService { public: - FSService(Pinetime::Controllers::FS& fs); + FSService(Pinetime::System::SystemTask& systemTask, + Pinetime::Controllers::FS& fs); void Init(); int OnFSServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context); void NotifyFSRaw(uint16_t connectionHandle); private: + Pinetime::System::SystemTask& systemTask; Pinetime::Controllers::FS& fs; static constexpr uint16_t FSServiceId {0xFEBB}; static constexpr uint16_t fsVersionId {0x0100}; @@ -30,7 +32,7 @@ namespace Pinetime { static constexpr uint8_t maxpathlen = 100; static constexpr ble_uuid16_t fsServiceUuid { .u {.type = BLE_UUID_TYPE_16}, - .value = {0xFEBB}};// {0x72, 0x65, 0x66, 0x73, 0x6e, 0x61, 0x72, 0x54, 0x65, 0x6c, 0x69, 0x46, 0xBB, 0xFE, 0xAF, 0xAD}}; + .value = {0xFEBB}}; // {0x72, 0x65, 0x66, 0x73, 0x6e, 0x61, 0x72, 0x54, 0x65, 0x6c, 0x69, 0x46, 0xBB, 0xFE, 0xAF, 0xAD}}; static constexpr ble_uuid128_t fsVersionUuid { .u {.type = BLE_UUID_TYPE_128}, @@ -144,7 +146,7 @@ namespace Pinetime { }; int FSCommandHandler(uint16_t connectionHandle, os_mbuf* om); - void prepareReadDataResp(ReadHeader *header, ReadResponse *resp); + void prepareReadDataResp(ReadHeader* header, ReadResponse* resp); }; } } diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index b5eb46b..0123066 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -51,7 +51,7 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, heartRateService {systemTask, heartRateController}, motionService{systemTask, motionController}, fs {fs}, - fsService {fs}, + fsService {systemTask,fs}, serviceDiscovery({¤tTimeClient, &alertNotificationClient}) { } diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h index 516f646..cc30fdc 100644 --- a/src/systemtask/Messages.h +++ b/src/systemtask/Messages.h @@ -27,6 +27,8 @@ namespace Pinetime { StopRinging, MeasureBatteryTimerExpired, BatteryPercentageUpdated, + StartFileTransfer, + StopFileTransfer, }; } } diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp index 28f8124..a95d479 100644 --- a/src/systemtask/SystemTask.cpp +++ b/src/systemtask/SystemTask.cpp @@ -342,6 +342,19 @@ void SystemTask::Work() { doNotGoToSleep = false; xTimerStart(dimTimer, 0); break; + case Messages::StartFileTransfer: + NRF_LOG_INFO("[systemtask] FS Started"); + doNotGoToSleep = true; + if (isSleeping && !isWakingUp) + GoToRunning(); + //TODO add intent of fs access icon or something + break; + case Messages::StopFileTransfer: + NRF_LOG_INFO("[systemtask] FS Stopped"); + doNotGoToSleep = false; + xTimerStart(dimTimer, 0); + //TODO add intent of fs access icon or something + break; case Messages::OnTouchEvent: if (touchHandler.GetNewTouchInfo()) { touchHandler.UpdateLvglTouchPoint(); -- cgit v0.10.2 From faa05eb57b7d6214e53d0b147a796793496a89ae Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Thu, 21 Oct 2021 04:02:50 +0000 Subject: Actually fix memory corruption, seems stable now ListDir MKDIR delete all seem to work Co-authored-by: Iambian diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index cd2cc07..0ba3e10 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -69,8 +69,9 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { while (systemTask.IsSleeping()) { vTaskDelay(100); // 50ms } + lfs_dir_t dir; + lfs_info info; switch (command) { - /* case commands::READ: { NRF_LOG_INFO("[FS_S] -> Read"); if (state != FSState::IDLE) { @@ -151,31 +152,15 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { return -1; } } - case commands::DELETE: { NRF_LOG_INFO("[FS_S] -> Delete"); auto* header = (DelHeader*) om->om_data; uint16_t plen = header->pathlen; - char path[plen + 1] = {0}; - struct lfs_info info = {}; - DelResponse resp = {}; + char path[plen + 1] {0}; + memcpy(path, header->pathstr, plen); + DelResponse resp {}; resp.command = commands::DELETE_STATUS; - int res = fs.Stat(path, &info); - // Get Info about path - // branch for DirDel of FileDelete - if (info.type == LFS_TYPE_DIR) { - res = fs.DirDelete(path); - } else { - res = fs.FileDelete(path); - } - switch (res) { - case LFS_ERR_OK: - resp.status = 0x01; - break; - default: - resp.status = 0x02; - break; - } + resp.status = fs.FileDelete(path) ? 0x02 : 0x01; auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(DelResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); break; @@ -184,57 +169,43 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { NRF_LOG_INFO("[FS_S] -> MKDir"); auto* header = (MKDirHeader*) om->om_data; uint16_t plen = header->pathlen; - char path[plen + 1] = {0}; + char path[plen + 1] {0}; memcpy(path, header->pathstr, plen); - NRF_LOG_INFO("[FS_S] -> MKDIR %.10s", path); - MKDirResponse resp = {}; + MKDirResponse resp {}; resp.command = commands::MKDIR_STATUS; - int res = fs.DirCreate(path); - switch (res) { - case LFS_ERR_OK: - resp.status = 0x01; - break; - default: - resp.status = 0x02; - break; - } - resp.modification_time = 0; // We should timestamp..but no + resp.modification_time = 0; + resp.status = fs.DirCreate(path) ? 0x02 : 0x01; auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(MKDirResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); break; - }*/ + } case commands::LISTDIR: { NRF_LOG_INFO("[FS_S] -> ListDir"); ListDirHeader* header = (ListDirHeader*) om->om_data; uint16_t plen = header->pathlen; - char path[plen + 1] = {0}; + char path[plen + 1] {0}; memcpy(path, header->pathstr, plen); NRF_LOG_INFO("[FS_S] -> DIR %.10s", path); - lfs_dir_t dir = {}; - struct lfs_info info = {}; + ListDirResponse resp {}; - ListDirResponse resp = {}; resp.command = commands::LISTDIR_ENTRY; - resp.status = 1; // TODO actually use res above! + resp.status = 1; resp.totalentries = 0; resp.entry = 0; - - if (fs.DirOpen(path, &dir)) { - return 0; - } - - // NRF_LOG_INFO("[FS_S] ->diropen %d ", res); + resp.modification_time = 0; // TODO Does LFS actually support TS? + if (fs.DirOpen(path, &dir) != 0) { + resp.status = 0x02; + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)); + ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); + break; + }; + // Count Total files in directory. while (fs.DirRead(&dir, &info)) { resp.totalentries++; } - NRF_LOG_INFO("[FS_S] -> %d ", resp.totalentries); - fs.DirRewind(&dir); - - // NRF_LOG_INFO("[FS_S] ->diropen %d ", res); - - while (resp.entry < resp.totalentries) { + while (true) { int res = fs.DirRead(&dir, &info); if (res <= 0) { break; @@ -251,35 +222,39 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { break; } } - resp.modification_time = 0; // TODO Does LFS actually support TS? - strcpy(resp.path, info.name); + + //strcpy(resp.path, info.name); resp.path_length = strlen(info.name); - NRF_LOG_INFO("[FS_S] ->Path %s ,", info.name); - auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse) + resp.path_length); + NRF_LOG_INFO("[FS_S] -> DIR %.10s", path); + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)); + os_mbuf_append(om,info.name,resp.path_length); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); + /* + * Todo Figure out how to know when the previous Notify was TX'd + * For now just delay 100ms to make sure that the data went out... + */ vTaskDelay(100); // Allow stuff to actually go out over the BLE conn resp.entry++; } - - if (fs.DirClose(&dir)) { - return 0; - } + assert(fs.DirClose(&dir) == 0); resp.file_size = 0; resp.path_length = 0; resp.flags = 0; - // TODO Handle Size of response better. - auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse) + resp.path_length); + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); - NRF_LOG_INFO("[FS_S] -> done "); break; } + default: + break; } + NRF_LOG_INFO("[FS_S] -> done "); systemTask.PushMessage(Pinetime::System::Messages::StopFileTransfer); return 0; } + // Loads resp with file data given a valid filepath header and resp void FSService::prepareReadDataResp(ReadHeader* header, ReadResponse* resp) { - uint16_t plen = header->pathlen; + // uint16_t plen = header->pathlen; resp->command = commands::READ_DATA; resp->chunkoff = header->chunkoff; resp->status = 0x01; diff --git a/src/components/ble/FSService.h b/src/components/ble/FSService.h index 69ed094..e9c98fb 100644 --- a/src/components/ble/FSService.h +++ b/src/components/ble/FSService.h @@ -29,7 +29,7 @@ namespace Pinetime { static constexpr uint16_t fsVersionId {0x0100}; static constexpr uint16_t fsTransferId {0x0200}; uint16_t fsVersion = {0x0004}; - static constexpr uint8_t maxpathlen = 100; + static constexpr uint16_t maxpathlen = 256; static constexpr ble_uuid16_t fsServiceUuid { .u {.type = BLE_UUID_TYPE_16}, .value = {0xFEBB}}; // {0x72, 0x65, 0x66, 0x73, 0x6e, 0x61, 0x72, 0x54, 0x65, 0x6c, 0x69, 0x46, 0xBB, 0xFE, 0xAF, 0xAD}}; @@ -47,6 +47,9 @@ namespace Pinetime { uint16_t versionCharacteristicHandle; uint16_t transferCharacteristicHandle; + // lfs_dir_t dir; + // lfs_info info; + enum class commands : uint8_t { INVALID = 0x00, READ = 0x10, -- cgit v0.10.2 From 8fb99471c38c2efd7af88d4888c5792bdd8deafb Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Fri, 22 Oct 2021 03:34:23 +0000 Subject: Reading Seems to work? diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 0ba3e10..68fd5ea 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -73,74 +73,76 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { lfs_info info; switch (command) { case commands::READ: { + lfs_file f; NRF_LOG_INFO("[FS_S] -> Read"); - if (state != FSState::IDLE) { - return -1; - } - state = FSState::READ; auto* header = (ReadHeader*) om->om_data; uint16_t plen = header->pathlen; - if (plen > maxpathlen - 1) { + if (plen > maxpathlen) { //> counts for null term return -1; } memcpy(filepath, header->pathstr, plen); filepath[plen + 1] = 0; // Copy and null teminate string ReadResponse resp; resp.command = commands::READ_DATA; - resp.chunkoff = header->chunkoff; resp.status = 0x01; - struct lfs_info info = {}; + resp.chunkoff = header->chunkoff; int res = fs.Stat(filepath, &info); if (res == LFS_ERR_NOENT && info.type != LFS_TYPE_DIR) { resp.status = 0x03; resp.chunklen = 0; resp.totallen = 0; } else { - lfs_file f; - resp.chunklen = std::min(header->chunksize, info.size); + resp.chunklen = std::min(header->chunksize, info.size); // TODO add mtu somehow resp.totallen = info.size; fs.FileOpen(&f, filepath, LFS_O_RDONLY); fs.FileSeek(&f, header->chunkoff); - resp.chunklen = fs.FileRead(&f, resp.chunk, resp.chunklen); - fs.FileClose(&f); } - auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse)); - ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); - if (header->chunksize >= resp.totallen) { // probably removeable...but then usafe - state = FSState::IDLE; + os_mbuf* om; + if (resp.chunklen > 0) { + uint8_t fileData[resp.chunklen] {0}; + resp.chunklen = fs.FileRead(&f, fileData, resp.chunklen); + om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse)); + os_mbuf_append(om, fileData, resp.chunklen); + } else { + resp.chunklen = 0; + om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse)); } + fs.FileClose(&f); + ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); + break; } case commands::READ_PACING: { - NRF_LOG_INFO("[FS_S] -> ReadPacing"); - if (state != FSState::READ) { - return -1; - } - auto* header = (ReadPacing*) om->om_data; - ReadResponse resp = {}; - + lfs_file f; + NRF_LOG_INFO("[FS_S] -> Readpacing"); + auto* header = (ReadHeader*) om->om_data; + ReadResponse resp; resp.command = commands::READ_DATA; - resp.chunkoff = header->chunkoff; resp.status = 0x01; - struct lfs_info info = {}; + resp.chunkoff = header->chunkoff; int res = fs.Stat(filepath, &info); if (res == LFS_ERR_NOENT && info.type != LFS_TYPE_DIR) { resp.status = 0x03; resp.chunklen = 0; resp.totallen = 0; } else { - lfs_file f; - resp.chunklen = std::min(header->chunksize, info.size); + resp.chunklen = std::min(header->chunksize, info.size); // TODO add mtu somehow resp.totallen = info.size; fs.FileOpen(&f, filepath, LFS_O_RDONLY); fs.FileSeek(&f, header->chunkoff); - resp.chunklen = fs.FileRead(&f, resp.chunk, resp.chunklen); - fs.FileClose(&f); } - auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse)); - ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); - if (resp.chunklen >= header->chunksize) { // is this right? - state = FSState::IDLE; + os_mbuf* om; + if (resp.chunklen > 0) { + uint8_t fileData[resp.chunklen] {0}; + resp.chunklen = fs.FileRead(&f, fileData, resp.chunklen); + om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse)); + os_mbuf_append(om, fileData, resp.chunklen); + } else { + resp.chunklen = 0; + om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse)); } + fs.FileClose(&f); + ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); + break; } case commands::WRITE: { if (state != FSState::IDLE) { @@ -185,7 +187,6 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { uint16_t plen = header->pathlen; char path[plen + 1] {0}; memcpy(path, header->pathstr, plen); - NRF_LOG_INFO("[FS_S] -> DIR %.10s", path); ListDirResponse resp {}; @@ -223,16 +224,15 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { } } - //strcpy(resp.path, info.name); + // strcpy(resp.path, info.name); resp.path_length = strlen(info.name); - NRF_LOG_INFO("[FS_S] -> DIR %.10s", path); auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)); - os_mbuf_append(om,info.name,resp.path_length); + os_mbuf_append(om, info.name, resp.path_length); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); /* - * Todo Figure out how to know when the previous Notify was TX'd - * For now just delay 100ms to make sure that the data went out... - */ + * Todo Figure out how to know when the previous Notify was TX'd + * For now just delay 100ms to make sure that the data went out... + */ vTaskDelay(100); // Allow stuff to actually go out over the BLE conn resp.entry++; } -- cgit v0.10.2 From c1aa5a5ea7d5ecde63a786827a866312c04507f9 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Mon, 25 Oct 2021 03:02:02 +0000 Subject: Write works diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 68fd5ea..c784a8c 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -83,6 +83,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { memcpy(filepath, header->pathstr, plen); filepath[plen + 1] = 0; // Copy and null teminate string ReadResponse resp; + os_mbuf* om; resp.command = commands::READ_DATA; resp.status = 0x01; resp.chunkoff = header->chunkoff; @@ -91,23 +92,19 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.status = 0x03; resp.chunklen = 0; resp.totallen = 0; + om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse)); } else { resp.chunklen = std::min(header->chunksize, info.size); // TODO add mtu somehow resp.totallen = info.size; fs.FileOpen(&f, filepath, LFS_O_RDONLY); fs.FileSeek(&f, header->chunkoff); - } - os_mbuf* om; - if (resp.chunklen > 0) { uint8_t fileData[resp.chunklen] {0}; resp.chunklen = fs.FileRead(&f, fileData, resp.chunklen); om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse)); os_mbuf_append(om, fileData, resp.chunklen); - } else { - resp.chunklen = 0; - om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse)); + fs.FileClose(&f); } - fs.FileClose(&f); + ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); break; } @@ -145,14 +142,45 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { break; } case commands::WRITE: { - if (state != FSState::IDLE) { + lfs_file f; + NRF_LOG_INFO("[FS_S] -> Write"); + auto* header = (WriteHeader*) om->om_data; + uint16_t plen = header->pathlen; + if (plen > maxpathlen) { //> counts for null term return -1; } + memcpy(filepath, header->pathstr, plen); + filepath[plen + 1] = 0; // Copy and null teminate string + fileSize = header->totalSize; + WriteResponse resp; + resp.command = commands::WRITE_PACING; + resp.offset = header->offset; + resp.modTime = 0; + int res = fs.FileOpen(&f, filepath, LFS_O_RDWR | LFS_O_CREAT); + resp.status = res ? 0x02 : 0x01; + fs.FileClose(&f); + resp.freespace = std::min(fs.getSize() - (fs.GetFSSize() * fs.getBlockSize()), fileSize - header->offset); + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(WriteResponse)); + ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); + break; } - case commands::WRITE_PACING: { - if (state != FSState::WRITE) { - return -1; - } + case commands::WRITE_DATA: { + lfs_file f; + NRF_LOG_INFO("[FS_S] -> WriteData"); + auto* header = (WritePacing*) om->om_data; + WriteResponse resp; + resp.command = commands::WRITE_PACING; + resp.offset = header->offset; + int res = fs.FileOpen(&f, filepath, LFS_O_RDWR | LFS_O_CREAT); + resp.status = res ? 0x02 : 0x01; + fs.FileSeek(&f, header->offset); + fs.FileWrite(&f, header->data, header->dataSize); + fs.FileClose(&f); + resp.freespace = std::min(fs.getSize() - (fs.GetFSSize() * fs.getBlockSize()), fileSize - header->offset); + // NRF_LOG_INFO('[FS_S] Used Blocks -> %u',resp.freespace); + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(WriteResponse)); + ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); + break; } case commands::DELETE: { NRF_LOG_INFO("[FS_S] -> Delete"); diff --git a/src/components/ble/FSService.h b/src/components/ble/FSService.h index e9c98fb..17f52eb 100644 --- a/src/components/ble/FSService.h +++ b/src/components/ble/FSService.h @@ -47,9 +47,6 @@ namespace Pinetime { uint16_t versionCharacteristicHandle; uint16_t transferCharacteristicHandle; - // lfs_dir_t dir; - // lfs_info info; - enum class commands : uint8_t { INVALID = 0x00, READ = 0x10, @@ -74,6 +71,7 @@ namespace Pinetime { }; FSState state; char filepath[maxpathlen]; // TODO ..ugh fixed filepath len + int fileSize; using ReadHeader = struct __attribute__((packed)) { commands command; uint8_t padding; @@ -100,6 +98,33 @@ namespace Pinetime { uint32_t chunksize; }; + using WriteHeader = struct __attribute__((packed)) { + commands command; + uint8_t padding; + uint16_t pathlen; + uint32_t offset; + uint64_t modTime; + uint32_t totalSize; + char pathstr[]; + }; + + using WriteResponse = struct __attribute__((packed)) { + commands command; + uint8_t status; + uint16_t padding; + uint32_t offset; + uint64_t modTime; + uint32_t freespace; + }; + + using WritePacing = struct __attribute__((packed)) { + commands command; + uint8_t status; + uint16_t padding; + uint32_t offset; + uint32_t dataSize; + uint8_t data[]; + }; using ListDirHeader = struct __attribute__((packed)) { commands command; uint8_t padding; diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp index c8a5a2e..297706f 100644 --- a/src/components/fs/FS.cpp +++ b/src/components/fs/FS.cpp @@ -107,7 +107,9 @@ int FS::DirCreate(const char* path) { int FS::Stat(const char* path, lfs_info* info) { return lfs_stat(&lfs, path, info); } - +lfs_ssize_t FS::GetFSSize(){ + return lfs_fs_size(&lfs); +} // Delete directory and all files inside int FS::DirDelete(const char* path) { diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h index 1aa8d5f..e4df956 100644 --- a/src/components/fs/FS.h +++ b/src/components/fs/FS.h @@ -10,6 +10,8 @@ namespace Pinetime { public: FS(Pinetime::Drivers::SpiNorFlash&); + + void Init(); void LVGLFileSystemInit(); @@ -30,10 +32,11 @@ namespace Pinetime { int DirRewind(lfs_dir_t* dir); int DirCreate(const char* path); int DirDelete(const char* path); - + lfs_ssize_t GetFSSize(); int Stat(const char* path, lfs_info* info); void VerifyResource(); - + static size_t getSize(){return size;} + static size_t getBlockSize(){return blockSize;} private: Pinetime::Drivers::SpiNorFlash& flashDriver; @@ -62,6 +65,7 @@ namespace Pinetime { static constexpr size_t startAddress = 0x0B4000; static constexpr size_t size = 0x34C000; static constexpr size_t blockSize = 4096; + bool resourcesValid = false; const struct lfs_config lfsConfig; -- cgit v0.10.2 From 2e10b0fe645f74d0ab057ac11b96f4eb3fffc4ae Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Tue, 26 Oct 2021 00:10:39 +0000 Subject: Remove mount/unmount. No longer needed diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp index 297706f..8d82c39 100644 --- a/src/components/fs/FS.cpp +++ b/src/components/fs/FS.cpp @@ -54,14 +54,6 @@ void FS::VerifyResource() { resourcesValid = true; } -void FS::Mount() { - flashDriver.Wakeup(); -} - -void FS::UnMount() { - flashDriver.Sleep(); -} - int FS::FileOpen(lfs_file_t* file_p, const char* fileName, const int flags) { return lfs_file_open(&lfs, file_p, fileName, flags); } @@ -107,7 +99,7 @@ int FS::DirCreate(const char* path) { int FS::Stat(const char* path, lfs_info* info) { return lfs_stat(&lfs, path, info); } -lfs_ssize_t FS::GetFSSize(){ +lfs_ssize_t FS::GetFSSize() { return lfs_fs_size(&lfs); } // Delete directory and all files inside diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h index e4df956..60dd8e5 100644 --- a/src/components/fs/FS.h +++ b/src/components/fs/FS.h @@ -10,14 +10,9 @@ namespace Pinetime { public: FS(Pinetime::Drivers::SpiNorFlash&); - - void Init(); void LVGLFileSystemInit(); - void Mount(); - void UnMount(); - int FileOpen(lfs_file_t* file_p, const char* fileName, const int flags); int FileClose(lfs_file_t* file_p); int FileRead(lfs_file_t* file_p, uint8_t* buff, uint32_t size); @@ -35,8 +30,13 @@ namespace Pinetime { lfs_ssize_t GetFSSize(); int Stat(const char* path, lfs_info* info); void VerifyResource(); - static size_t getSize(){return size;} - static size_t getBlockSize(){return blockSize;} + static size_t getSize() { + return size; + } + static size_t getBlockSize() { + return blockSize; + } + private: Pinetime::Drivers::SpiNorFlash& flashDriver; @@ -65,7 +65,6 @@ namespace Pinetime { static constexpr size_t startAddress = 0x0B4000; static constexpr size_t size = 0x34C000; static constexpr size_t blockSize = 4096; - bool resourcesValid = false; const struct lfs_config lfsConfig; -- cgit v0.10.2 From f4322841ffc011ea5c541e40e6aa73ab11ebd988 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Tue, 26 Oct 2021 00:48:25 +0000 Subject: Remove DirDelete, implementation did not work and memory contraints are recursive. Better implemented on client side... diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp index 8d82c39..79fb222 100644 --- a/src/components/fs/FS.cpp +++ b/src/components/fs/FS.cpp @@ -102,23 +102,6 @@ int FS::Stat(const char* path, lfs_info* info) { lfs_ssize_t FS::GetFSSize() { return lfs_fs_size(&lfs); } -// Delete directory and all files inside -int FS::DirDelete(const char* path) { - - lfs_dir_t lfs_dir; - lfs_info entryInfo; - - int err; - err = lfs_dir_open(&lfs, &lfs_dir, path); - if (err) { - return err; - } - while (lfs_dir_read(&lfs, &lfs_dir, &entryInfo)) { - lfs_remove(&lfs, entryInfo.name); - } - lfs_dir_close(&lfs, &lfs_dir); - return LFS_ERR_OK; -} /* diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h index 60dd8e5..da3bd27 100644 --- a/src/components/fs/FS.h +++ b/src/components/fs/FS.h @@ -26,10 +26,11 @@ namespace Pinetime { int DirRead(lfs_dir_t* dir, lfs_info* info); int DirRewind(lfs_dir_t* dir); int DirCreate(const char* path); - int DirDelete(const char* path); + lfs_ssize_t GetFSSize(); int Stat(const char* path, lfs_info* info); void VerifyResource(); + static size_t getSize() { return size; } -- cgit v0.10.2 From 8f46908d387cc4fe3f911bc0ca517719238418ed Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Tue, 26 Oct 2021 03:42:34 +0000 Subject: Fix lvgl_open to respect littlefs open errors diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index c784a8c..0230ea1 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -156,7 +156,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.command = commands::WRITE_PACING; resp.offset = header->offset; resp.modTime = 0; - int res = fs.FileOpen(&f, filepath, LFS_O_RDWR | LFS_O_CREAT); + int res = fs.FileOpen(&f, filepath, LFS_O_WRONLY | LFS_O_CREAT); resp.status = res ? 0x02 : 0x01; fs.FileClose(&f); resp.freespace = std::min(fs.getSize() - (fs.GetFSSize() * fs.getBlockSize()), fileSize - header->offset); @@ -177,7 +177,6 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { fs.FileWrite(&f, header->data, header->dataSize); fs.FileClose(&f); resp.freespace = std::min(fs.getSize() - (fs.GetFSSize() * fs.getBlockSize()), fileSize - header->offset); - // NRF_LOG_INFO('[FS_S] Used Blocks -> %u',resp.freespace); auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(WriteResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); break; @@ -222,14 +221,13 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.status = 1; resp.totalentries = 0; resp.entry = 0; - resp.modification_time = 0; // TODO Does LFS actually support TS? + resp.modification_time = 0; if (fs.DirOpen(path, &dir) != 0) { resp.status = 0x02; auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); break; }; - // Count Total files in directory. while (fs.DirRead(&dir, &info)) { resp.totalentries++; } diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp index 79fb222..78b0f5c 100644 --- a/src/components/fs/FS.cpp +++ b/src/components/fs/FS.cpp @@ -141,16 +141,17 @@ int FS::SectorRead(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, namespace { lv_fs_res_t lvglOpen(lv_fs_drv_t* drv, void* file_p, const char* path, lv_fs_mode_t mode) { - lfs_file_t* file = static_cast(file_p); FS* filesys = static_cast(drv->user_data); - filesys->FileOpen(file, path, LFS_O_RDONLY); - - if (file->type == 0) { - return LV_FS_RES_FS_ERR; - } else { - return LV_FS_RES_OK; + int res = filesys->FileOpen(file, path, LFS_O_RDONLY); + if (res == 0) { + if (file->type == 0) { + return LV_FS_RES_FS_ERR; + } else { + return LV_FS_RES_OK; + } } + return LV_FS_RES_NOT_EX; } lv_fs_res_t lvglClose(lv_fs_drv_t* drv, void* file_p) { -- cgit v0.10.2 From 362a5ef1136399c178cf881f7569e3d291432ec1 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Tue, 16 Nov 2021 04:32:53 +0000 Subject: Added move function diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 0230ea1..1082d24 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -270,6 +270,21 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); break; } + case commands::MOVE: { + NRF_LOG_INFO("[FS_S] -> Move"); + MoveHeader* header = (MoveHeader*) om->om_data; + uint16_t plen = header->OldPathLength; + // Null Terminate string + header->pathstr[plen] = 0; + char path[header->NewPathLength + 1] {0}; + memcpy(path, &header->pathstr[plen + 1], header->NewPathLength); + MoveResponse resp {}; + resp.command = commands::MOVE_STATUS; + int res = fs.Rename(header->pathstr, path); + resp.status = (res == 0) ? 1 : 2; + auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(MoveResponse)); + ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); + } default: break; } diff --git a/src/components/ble/FSService.h b/src/components/ble/FSService.h index 17f52eb..828925a 100644 --- a/src/components/ble/FSService.h +++ b/src/components/ble/FSService.h @@ -15,8 +15,7 @@ namespace Pinetime { class Ble; class FSService { public: - FSService(Pinetime::System::SystemTask& systemTask, - Pinetime::Controllers::FS& fs); + FSService(Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::FS& fs); void Init(); int OnFSServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context); @@ -116,7 +115,7 @@ namespace Pinetime { uint64_t modTime; uint32_t freespace; }; - + using WritePacing = struct __attribute__((packed)) { commands command; uint8_t status; @@ -172,6 +171,18 @@ namespace Pinetime { commands command; uint8_t status; }; + using MoveHeader = struct __attribute__((packed)) { + commands command; + uint8_t padding; + uint16_t OldPathLength; + uint16_t NewPathLength; + char pathstr[]; + }; + + using MoveResponse = struct __attribute__((packed)) { + commands command; + uint8_t status; + }; int FSCommandHandler(uint16_t connectionHandle, os_mbuf* om); void prepareReadDataResp(ReadHeader* header, ReadResponse* resp); diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp index 78b0f5c..8c98ae3 100644 --- a/src/components/fs/FS.cpp +++ b/src/components/fs/FS.cpp @@ -95,7 +95,9 @@ int FS::DirRewind(lfs_dir_t* dir) { int FS::DirCreate(const char* path) { return lfs_mkdir(&lfs, path); } - +int FS::Rename(const char* oldPath, const char* newPath){ + return lfs_rename(&lfs,oldPath,newPath); +} int FS::Stat(const char* path, lfs_info* info) { return lfs_stat(&lfs, path, info); } diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h index da3bd27..2b27ae5 100644 --- a/src/components/fs/FS.h +++ b/src/components/fs/FS.h @@ -28,6 +28,7 @@ namespace Pinetime { int DirCreate(const char* path); lfs_ssize_t GetFSSize(); + int Rename(const char* oldPath, const char* newPath); int Stat(const char* path, lfs_info* info); void VerifyResource(); -- cgit v0.10.2 From 09b9130244a7d5e448612d4a9a70988c2610d686 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sat, 20 Nov 2021 04:57:02 +0000 Subject: Fix string nullterminations, Expand error codes. diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 1082d24..e1d5bae 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -81,7 +81,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { return -1; } memcpy(filepath, header->pathstr, plen); - filepath[plen + 1] = 0; // Copy and null teminate string + filepath[plen] = 0; // Copy and null teminate string ReadResponse resp; os_mbuf* om; resp.command = commands::READ_DATA; @@ -150,14 +150,14 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { return -1; } memcpy(filepath, header->pathstr, plen); - filepath[plen + 1] = 0; // Copy and null teminate string + filepath[plen] = 0; // Copy and null teminate string fileSize = header->totalSize; WriteResponse resp; resp.command = commands::WRITE_PACING; resp.offset = header->offset; resp.modTime = 0; int res = fs.FileOpen(&f, filepath, LFS_O_WRONLY | LFS_O_CREAT); - resp.status = res ? 0x02 : 0x01; + resp.status = (res==0) ? 0x01: (int8_t)res; fs.FileClose(&f); resp.freespace = std::min(fs.getSize() - (fs.GetFSSize() * fs.getBlockSize()), fileSize - header->offset); auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(WriteResponse)); @@ -171,11 +171,14 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { WriteResponse resp; resp.command = commands::WRITE_PACING; resp.offset = header->offset; - int res = fs.FileOpen(&f, filepath, LFS_O_RDWR | LFS_O_CREAT); - resp.status = res ? 0x02 : 0x01; + resp.status = 1; + fs.FileOpen(&f, filepath, LFS_O_RDWR | LFS_O_CREAT); fs.FileSeek(&f, header->offset); - fs.FileWrite(&f, header->data, header->dataSize); + int res = fs.FileWrite(&f, header->data, header->dataSize); fs.FileClose(&f); + if(res < 0 ){ + resp.status = (int8_t)res; + } resp.freespace = std::min(fs.getSize() - (fs.GetFSSize() * fs.getBlockSize()), fileSize - header->offset); auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(WriteResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); @@ -187,9 +190,11 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { uint16_t plen = header->pathlen; char path[plen + 1] {0}; memcpy(path, header->pathstr, plen); + path[plen] = 0; // Copy and null teminate string DelResponse resp {}; resp.command = commands::DELETE_STATUS; - resp.status = fs.FileDelete(path) ? 0x02 : 0x01; + int res = fs.FileDelete(path); + resp.status = (res==0) ? 0x01 : (int8_t)res; auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(DelResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); break; @@ -200,10 +205,12 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { uint16_t plen = header->pathlen; char path[plen + 1] {0}; memcpy(path, header->pathstr, plen); + path[plen] = 0; // Copy and null teminate string MKDirResponse resp {}; resp.command = commands::MKDIR_STATUS; resp.modification_time = 0; - resp.status = fs.DirCreate(path) ? 0x02 : 0x01; + int res = fs.DirCreate(path); + resp.status = (res==0) ? 0x01 : (int8_t)res; auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(MKDirResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); break; @@ -213,6 +220,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { ListDirHeader* header = (ListDirHeader*) om->om_data; uint16_t plen = header->pathlen; char path[plen + 1] {0}; + path[plen] = 0; // Copy and null teminate string memcpy(path, header->pathstr, plen); ListDirResponse resp {}; @@ -222,8 +230,9 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.totalentries = 0; resp.entry = 0; resp.modification_time = 0; - if (fs.DirOpen(path, &dir) != 0) { - resp.status = 0x02; + int res = fs.DirOpen(path, &dir); + if (res != 0) { + resp.status = (int8_t)res; auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); break; @@ -233,7 +242,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { } fs.DirRewind(&dir); while (true) { - int res = fs.DirRead(&dir, &info); + res = fs.DirRead(&dir, &info); if (res <= 0) { break; } @@ -278,10 +287,11 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { header->pathstr[plen] = 0; char path[header->NewPathLength + 1] {0}; memcpy(path, &header->pathstr[plen + 1], header->NewPathLength); + path[header->NewPathLength] = 0; // Copy and null teminate string MoveResponse resp {}; resp.command = commands::MOVE_STATUS; - int res = fs.Rename(header->pathstr, path); - resp.status = (res == 0) ? 1 : 2; + int8_t res = (int8_t)fs.Rename(header->pathstr, path); + resp.status = (res == 0) ? 1 : res; auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(MoveResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); } -- cgit v0.10.2 From b62c62ee1f62d3371bfa29855bf2fd59b4dcecf8 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sat, 20 Nov 2021 20:18:14 +0000 Subject: Change read to return LFS return values when reading a directory or nonexistant file diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index e1d5bae..4cefcdc 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -89,7 +89,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.chunkoff = header->chunkoff; int res = fs.Stat(filepath, &info); if (res == LFS_ERR_NOENT && info.type != LFS_TYPE_DIR) { - resp.status = 0x03; + resp.status = (int8_t) res; resp.chunklen = 0; resp.totallen = 0; om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse)); @@ -118,7 +118,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.chunkoff = header->chunkoff; int res = fs.Stat(filepath, &info); if (res == LFS_ERR_NOENT && info.type != LFS_TYPE_DIR) { - resp.status = 0x03; + resp.status = (int8_t) res; resp.chunklen = 0; resp.totallen = 0; } else { @@ -157,7 +157,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.offset = header->offset; resp.modTime = 0; int res = fs.FileOpen(&f, filepath, LFS_O_WRONLY | LFS_O_CREAT); - resp.status = (res==0) ? 0x01: (int8_t)res; + resp.status = (res == 0) ? 0x01 : (int8_t) res; fs.FileClose(&f); resp.freespace = std::min(fs.getSize() - (fs.GetFSSize() * fs.getBlockSize()), fileSize - header->offset); auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(WriteResponse)); @@ -171,13 +171,13 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { WriteResponse resp; resp.command = commands::WRITE_PACING; resp.offset = header->offset; - resp.status = 1; + resp.status = 0x01; fs.FileOpen(&f, filepath, LFS_O_RDWR | LFS_O_CREAT); fs.FileSeek(&f, header->offset); - int res = fs.FileWrite(&f, header->data, header->dataSize); + int res = fs.FileWrite(&f, header->data, header->dataSize); fs.FileClose(&f); - if(res < 0 ){ - resp.status = (int8_t)res; + if (res < 0) { + resp.status = (int8_t) res; } resp.freespace = std::min(fs.getSize() - (fs.GetFSSize() * fs.getBlockSize()), fileSize - header->offset); auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(WriteResponse)); @@ -194,7 +194,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { DelResponse resp {}; resp.command = commands::DELETE_STATUS; int res = fs.FileDelete(path); - resp.status = (res==0) ? 0x01 : (int8_t)res; + resp.status = (res == 0) ? 0x01 : (int8_t) res; auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(DelResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); break; @@ -210,7 +210,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.command = commands::MKDIR_STATUS; resp.modification_time = 0; int res = fs.DirCreate(path); - resp.status = (res==0) ? 0x01 : (int8_t)res; + resp.status = (res == 0) ? 0x01 : (int8_t) res; auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(MKDirResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); break; @@ -226,13 +226,13 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { ListDirResponse resp {}; resp.command = commands::LISTDIR_ENTRY; - resp.status = 1; + resp.status = 0x01; resp.totalentries = 0; resp.entry = 0; resp.modification_time = 0; int res = fs.DirOpen(path, &dir); if (res != 0) { - resp.status = (int8_t)res; + resp.status = (int8_t) res; auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(ListDirResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); break; @@ -290,7 +290,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { path[header->NewPathLength] = 0; // Copy and null teminate string MoveResponse resp {}; resp.command = commands::MOVE_STATUS; - int8_t res = (int8_t)fs.Rename(header->pathstr, path); + int8_t res = (int8_t) fs.Rename(header->pathstr, path); resp.status = (res == 0) ? 1 : res; auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(MoveResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); -- cgit v0.10.2 From fdb5e27aea99c3a5117661948de75e7853165ff5 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sun, 21 Nov 2021 03:33:00 +0000 Subject: Attempt at a more robust File handler diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 4cefcdc..2222ae9 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -147,7 +147,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { auto* header = (WriteHeader*) om->om_data; uint16_t plen = header->pathlen; if (plen > maxpathlen) { //> counts for null term - return -1; + return -1; // TODO make this actually return a BLE notif } memcpy(filepath, header->pathstr, plen); filepath[plen] = 0; // Copy and null teminate string @@ -156,9 +156,12 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.command = commands::WRITE_PACING; resp.offset = header->offset; resp.modTime = 0; + int res = fs.FileOpen(&f, filepath, LFS_O_WRONLY | LFS_O_CREAT); - resp.status = (res == 0) ? 0x01 : (int8_t) res; - fs.FileClose(&f); + if(res == 0){ + fs.FileClose(&f); + resp.status = (res == 0) ? 0x01 : (int8_t) res; + } resp.freespace = std::min(fs.getSize() - (fs.GetFSSize() * fs.getBlockSize()), fileSize - header->offset); auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(WriteResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); @@ -171,14 +174,18 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { WriteResponse resp; resp.command = commands::WRITE_PACING; resp.offset = header->offset; - resp.status = 0x01; - fs.FileOpen(&f, filepath, LFS_O_RDWR | LFS_O_CREAT); - fs.FileSeek(&f, header->offset); - int res = fs.FileWrite(&f, header->data, header->dataSize); - fs.FileClose(&f); + int res = 0; + + if (!(res = fs.FileOpen(&f, filepath, LFS_O_RDWR | LFS_O_CREAT))) { + if (!(res = fs.FileSeek(&f, header->offset))) { + res = fs.FileWrite(&f, header->data, header->dataSize); + } + fs.FileClose(&f); + } if (res < 0) { resp.status = (int8_t) res; } + resp.freespace = std::min(fs.getSize() - (fs.GetFSSize() * fs.getBlockSize()), fileSize - header->offset); auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(WriteResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); -- cgit v0.10.2 From d1e9aa107617565b456f05e20e9468ab270d323e Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sun, 21 Nov 2021 06:17:07 +0000 Subject: Force variable cleanup because LFS makes assumptions about variable initialization state diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 2222ae9..03d4673 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -71,9 +71,11 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { } lfs_dir_t dir; lfs_info info; + lfs_file f; + memset(&f, 0, sizeof(lfs_file_t)); + memset(&dir, 0, sizeof(lfs_dir_t)); switch (command) { case commands::READ: { - lfs_file f; NRF_LOG_INFO("[FS_S] -> Read"); auto* header = (ReadHeader*) om->om_data; uint16_t plen = header->pathlen; @@ -109,7 +111,6 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { break; } case commands::READ_PACING: { - lfs_file f; NRF_LOG_INFO("[FS_S] -> Readpacing"); auto* header = (ReadHeader*) om->om_data; ReadResponse resp; @@ -142,7 +143,6 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { break; } case commands::WRITE: { - lfs_file f; NRF_LOG_INFO("[FS_S] -> Write"); auto* header = (WriteHeader*) om->om_data; uint16_t plen = header->pathlen; @@ -157,8 +157,8 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.offset = header->offset; resp.modTime = 0; - int res = fs.FileOpen(&f, filepath, LFS_O_WRONLY | LFS_O_CREAT); - if(res == 0){ + int res = fs.FileOpen(&f, filepath, LFS_O_RDWR | LFS_O_CREAT); + if (res == 0) { fs.FileClose(&f); resp.status = (res == 0) ? 0x01 : (int8_t) res; } @@ -168,7 +168,6 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { break; } case commands::WRITE_DATA: { - lfs_file f; NRF_LOG_INFO("[FS_S] -> WriteData"); auto* header = (WritePacing*) om->om_data; WriteResponse resp; @@ -185,7 +184,6 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { if (res < 0) { resp.status = (int8_t) res; } - resp.freespace = std::min(fs.getSize() - (fs.GetFSSize() * fs.getBlockSize()), fileSize - header->offset); auto* om = ble_hs_mbuf_from_flat(&resp, sizeof(WriteResponse)); ble_gattc_notify_custom(connectionHandle, transferCharacteristicHandle, om); -- cgit v0.10.2 From b9a2db1a49976cbfe92a9941bce17ffdbae7d0b3 Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sun, 21 Nov 2021 06:33:24 +0000 Subject: Fix large file support that broke due to a refactor. diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index 03d4673..d82596c 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -176,7 +176,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { int res = 0; if (!(res = fs.FileOpen(&f, filepath, LFS_O_RDWR | LFS_O_CREAT))) { - if (!(res = fs.FileSeek(&f, header->offset))) { + if ((res = fs.FileSeek(&f, header->offset) ) >= 0) { res = fs.FileWrite(&f, header->data, header->dataSize); } fs.FileClose(&f); -- cgit v0.10.2 From 0a0d1f270328001e1e80a2ac6c26feb111bfa27a Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Sun, 21 Nov 2021 21:35:41 +0000 Subject: Fix more initializers diff --git a/src/components/ble/FSService.cpp b/src/components/ble/FSService.cpp index d82596c..8dc9ed6 100644 --- a/src/components/ble/FSService.cpp +++ b/src/components/ble/FSService.cpp @@ -69,11 +69,9 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { while (systemTask.IsSleeping()) { vTaskDelay(100); // 50ms } - lfs_dir_t dir; - lfs_info info; - lfs_file f; - memset(&f, 0, sizeof(lfs_file_t)); - memset(&dir, 0, sizeof(lfs_dir_t)); + lfs_dir_t dir = {0}; + lfs_info info = {0}; + lfs_file f = {0}; switch (command) { case commands::READ: { NRF_LOG_INFO("[FS_S] -> Read"); @@ -100,7 +98,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { resp.totallen = info.size; fs.FileOpen(&f, filepath, LFS_O_RDONLY); fs.FileSeek(&f, header->chunkoff); - uint8_t fileData[resp.chunklen] {0}; + uint8_t fileData[resp.chunklen] = {0}; resp.chunklen = fs.FileRead(&f, fileData, resp.chunklen); om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse)); os_mbuf_append(om, fileData, resp.chunklen); @@ -130,7 +128,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { } os_mbuf* om; if (resp.chunklen > 0) { - uint8_t fileData[resp.chunklen] {0}; + uint8_t fileData[resp.chunklen] = {0}; resp.chunklen = fs.FileRead(&f, fileData, resp.chunklen); om = ble_hs_mbuf_from_flat(&resp, sizeof(ReadResponse)); os_mbuf_append(om, fileData, resp.chunklen); @@ -176,7 +174,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { int res = 0; if (!(res = fs.FileOpen(&f, filepath, LFS_O_RDWR | LFS_O_CREAT))) { - if ((res = fs.FileSeek(&f, header->offset) ) >= 0) { + if ((res = fs.FileSeek(&f, header->offset)) >= 0) { res = fs.FileWrite(&f, header->data, header->dataSize); } fs.FileClose(&f); @@ -193,7 +191,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { NRF_LOG_INFO("[FS_S] -> Delete"); auto* header = (DelHeader*) om->om_data; uint16_t plen = header->pathlen; - char path[plen + 1] {0}; + char path[plen + 1] = {0}; memcpy(path, header->pathstr, plen); path[plen] = 0; // Copy and null teminate string DelResponse resp {}; @@ -208,7 +206,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { NRF_LOG_INFO("[FS_S] -> MKDir"); auto* header = (MKDirHeader*) om->om_data; uint16_t plen = header->pathlen; - char path[plen + 1] {0}; + char path[plen + 1] = {0}; memcpy(path, header->pathstr, plen); path[plen] = 0; // Copy and null teminate string MKDirResponse resp {}; @@ -224,7 +222,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { NRF_LOG_INFO("[FS_S] -> ListDir"); ListDirHeader* header = (ListDirHeader*) om->om_data; uint16_t plen = header->pathlen; - char path[plen + 1] {0}; + char path[plen + 1] = {0}; path[plen] = 0; // Copy and null teminate string memcpy(path, header->pathstr, plen); @@ -290,7 +288,7 @@ int FSService::FSCommandHandler(uint16_t connectionHandle, os_mbuf* om) { uint16_t plen = header->OldPathLength; // Null Terminate string header->pathstr[plen] = 0; - char path[header->NewPathLength + 1] {0}; + char path[header->NewPathLength + 1] = {0}; memcpy(path, &header->pathstr[plen + 1], header->NewPathLength); path[header->NewPathLength] = 0; // Copy and null teminate string MoveResponse resp {}; -- cgit v0.10.2 From 1470489e7b14fdfe4871cdc714c4a3c98917c4bb Mon Sep 17 00:00:00 2001 From: Tim Keller Date: Fri, 10 Dec 2021 01:49:03 +0000 Subject: Fix Failed rebase. diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 0123066..3bf1ec8 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -49,9 +49,8 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask, batteryInformationService {batteryController}, immediateAlertService {systemTask, notificationManager}, heartRateService {systemTask, heartRateController}, - motionService{systemTask, motionController}, - fs {fs}, - fsService {systemTask,fs}, + motionService {systemTask, motionController}, + fsService {systemTask, fs}, serviceDiscovery({¤tTimeClient, &alertNotificationClient}) { } @@ -100,7 +99,7 @@ void NimbleController::Init() { heartRateService.Init(); motionService.Init(); fsService.Init(); - + int rc; rc = ble_hs_util_ensure_addr(0); ASSERT(rc == 0); diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 14749b8..7a38703 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -111,7 +111,6 @@ namespace Pinetime { HeartRateService heartRateService; MotionService motionService; ServiceDiscovery serviceDiscovery; - FS fs; FSService fsService; uint8_t addrType; -- cgit v0.10.2 From 645a071b704c201a3c717061e07ab859a6e94f07 Mon Sep 17 00:00:00 2001 From: "James A. Jerkins" Date: Sat, 11 Dec 2021 21:34:51 -0600 Subject: FIX: AlarmTriggered fall through to ShowPairingKey diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp index f050e65..233f433 100644 --- a/src/displayapp/DisplayApp.cpp +++ b/src/displayapp/DisplayApp.cpp @@ -215,6 +215,7 @@ void DisplayApp::Refresh() { } else { LoadApp(Apps::Alarm, DisplayApp::FullRefreshDirections::None); } + break; case Messages::ShowPairingKey: LoadApp(Apps::PassKey, DisplayApp::FullRefreshDirections::Up); break; -- cgit v0.10.2 From eca0588c2328a72aee3c6132c7c4221277cb8b28 Mon Sep 17 00:00:00 2001 From: "James A. Jerkins" Date: Tue, 21 Dec 2021 16:02:01 -0600 Subject: Optional secure pairing with a passkey Support passkey pairing when requested by the central Fix a comment and reorder warning diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp index 82df7b1..9a3f86f 100644 --- a/src/components/ble/BatteryInformationService.cpp +++ b/src/components/ble/BatteryInformationService.cpp @@ -17,7 +17,7 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte characteristicDefinition {{.uuid = &batteryLevelUuid.u, .access_cb = BatteryInformationServiceCallback, .arg = this, - .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_READ_ENC | BLE_GATT_CHR_F_READ_AUTHEN | BLE_GATT_CHR_F_NOTIFY, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, .val_handle = &batteryLevelHandle}, {0}}, serviceDefinition { diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp index 3bf1ec8..d8510bd 100644 --- a/src/components/ble/NimbleController.cpp +++ b/src/components/ble/NimbleController.cpp @@ -134,9 +134,7 @@ void NimbleController::Init() { RestoreBond(); - if (!ble_gap_adv_active() && !bleController.IsConnected()) { - StartAdvertising(); - } + StartAdvertising(); } void NimbleController::StartAdvertising() { @@ -274,7 +272,7 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) { * display capability only so we only handle the "display" action here. * * Standards insist that the rand() PRNG be deterministic. - * Use the nimble TRNG here since rand() is predictable. + * Use the tinycrypt prng here since rand() is predictable. */ NRF_LOG_INFO("Security event : BLE_GAP_EVENT_PASSKEY_ACTION"); if (event->passkey.params.action == BLE_SM_IOACT_DISP) { diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h index 7a38703..2b300e6 100644 --- a/src/components/ble/NimbleController.h +++ b/src/components/ble/NimbleController.h @@ -110,8 +110,8 @@ namespace Pinetime { ImmediateAlertService immediateAlertService; HeartRateService heartRateService; MotionService motionService; - ServiceDiscovery serviceDiscovery; FSService fsService; + ServiceDiscovery serviceDiscovery; uint8_t addrType; uint16_t connectionHandle = BLE_HS_CONN_HANDLE_NONE; -- cgit v0.10.2 From 86ee7a70b741c970f6cd90827c1bf9874fd50975 Mon Sep 17 00:00:00 2001 From: hubmartin Date: Wed, 4 Aug 2021 15:22:41 +0200 Subject: WatchFaceDigital - BLE symbol changed to white color diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index 8769579..f71b51f 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -44,7 +44,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app, lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0); bleIcon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x0000FF)); + lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); lv_label_set_text(bleIcon, Symbols::bluetooth); lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0); -- cgit v0.10.2 From f52d6bfa677d1884f8df03af190a5521fa6809f9 Mon Sep 17 00:00:00 2001 From: hubmartin Date: Wed, 4 Aug 2021 15:26:19 +0200 Subject: Real white now diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index f71b51f..1b8547f 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -44,7 +44,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app, lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0); bleIcon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); + lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFFFFFF)); lv_label_set_text(bleIcon, Symbols::bluetooth); lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0); -- cgit v0.10.2 From 204fc56672e3200f18993219fb290607f41b78d6 Mon Sep 17 00:00:00 2001 From: hubmartin Date: Wed, 4 Aug 2021 19:11:22 +0200 Subject: Use Bluetooth brand color for BLE logo #0082FC diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp index 1b8547f..4d9eaf3 100644 --- a/src/displayapp/screens/WatchFaceDigital.cpp +++ b/src/displayapp/screens/WatchFaceDigital.cpp @@ -44,7 +44,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app, lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0); bleIcon = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xFFFFFF)); + lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x0082FC)); lv_label_set_text(bleIcon, Symbols::bluetooth); lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0); -- cgit v0.10.2 From 1832a6c23114a2a1d824de3aa519c70e6f78cfa8 Mon Sep 17 00:00:00 2001 From: Eli Weiss Date: Mon, 29 Nov 2021 21:03:23 -0600 Subject: Update buildAndProgram.md Improved documentation readability. diff --git a/doc/buildAndProgram.md b/doc/buildAndProgram.md index 3686871..feef9f6 100644 --- a/doc/buildAndProgram.md +++ b/doc/buildAndProgram.md @@ -4,7 +4,7 @@ To build this project, you'll need: - A cross-compiler : [ARM-GCC (9-2020-q2-update)](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads/9-2020-q2-update) - The NRF52 SDK 15.3.0 : [nRF-SDK v15.3.0](https://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v15.x.x/nRF5_SDK_15.3.0_59ac345.zip) - The Python 3 modules `cbor`, `intelhex`, `click` and `cryptography` modules for the `mcuboot` tool (see [requirements.txt](../tools/mcuboot/requirements.txt)) - - To to keep the system clean a python virtual environment (`venv`) can be used to install the python modules into + - To keep the system clean, you can install python modules into a python virtual environment (`venv`) ```sh python -m venv .venv source .venv/bin/activate @@ -260,4 +260,4 @@ Finally, merge them together with **mergehex**: This file must be flashed at offset **0x00** of the internal memory of the NRF52832. #### spinor.bin -This file is the MCUBoot image of the last stable version of the recovery firmware. It must be flashed at offset **0x00** of the external SPINOR flash memory. \ No newline at end of file +This file is the MCUBoot image of the last stable version of the recovery firmware. It must be flashed at offset **0x00** of the external SPINOR flash memory. -- cgit v0.10.2 From f66fcdd3ca64fcbecfa264a506b7973b47ba1213 Mon Sep 17 00:00:00 2001 From: Eli Weiss Date: Mon, 29 Nov 2021 21:51:35 -0600 Subject: Improved documentation readability Removed extra space in contribute.md and cleaned up MemoryAnalysis.md phrasing and confusing punctuation. diff --git a/doc/MemoryAnalysis.md b/doc/MemoryAnalysis.md index 7304e3f..20bb928 100644 --- a/doc/MemoryAnalysis.md +++ b/doc/MemoryAnalysis.md @@ -32,13 +32,13 @@ In this analysis, I used [Linkermapviz](https://github.com/PromyLOPh/linkermapvi ### Linkermapviz -[Linkermapviz](https://github.com/PromyLOPh/linkermapviz) parses the MAP file and displays its content in a graphical way into an HTML page: +[Linkermapviz](https://github.com/PromyLOPh/linkermapviz) parses the MAP file and displays its content on an HTML page as a graphic: ![linkermapviz](./memoryAnalysis/linkermapviz.png) -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,... +Using this tool, you can compare the relative size of symbols. This can be helpful for checking memory usage at a glance. -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... +Also, as Linkermapviz is written in Python, you can easily modify and adapt it to your firmware or export data in another format. For example, [here it is modified to parse the contents of the MAP file and export it in a CSV file](https://github.com/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-842338620). This file could later be opened in LibreOffice Calc where sort/filter functionality could be used 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... @@ -46,8 +46,8 @@ Also, as Linkermapviz is written in Python, you can easily modify it to adapt it Puncover is really easy to install: - - clone the repo and cd into the cloned directory - - setup a venv + - Clone the repo and cd into the cloned directory + - Setup a venv - `python -m virtualenv venv` - `source venv/bin/activate` - Install : `pip install .` @@ -60,13 +60,13 @@ Puncover is really easy to install: - Launch a browser at http://localhost:5000/ ### Analysis -Using the MAP file and tools, we can easily see what symbols are using most of the FLASH memory space. In this case, with no surprise, fonts and graphics are the biggest flash space consumer. +Using the MAP file and tools, we can easily see what symbols are using most of the flash memory. In this case, with no surprise, fonts and graphics are the largest use of flash memory. ![Puncover](./memoryAnalysis/puncover-all-symbols.png) -This way, you can easily check what needs to be optimized : we should find a way to store big static data (like fonts and graphics) in the external flash memory, for example. +This way, you can easily check what needs to be optimized. We should find a way to store big static data (like fonts and graphics) in the external flash memory, for example. -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. +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/InfiniTimeOrg/InfiniTime/issues/313#issuecomment-842338620 @@ -210,7 +210,7 @@ NRF_LOG_INFO("heap : %d", m.uordblks); ``` #### Analysis -According to my experimentation, InfiniTime uses ~6000bytes of heap most of the time. Except when the Navigation app is launched, where the heap usage increases to... more than 9500 bytes (meaning that the heap overflows and could potentially corrupt the stack!!!). This is a bug that should be fixed in #362. +According to my experimentation, InfiniTime uses ~6000bytes of heap most of the time. Except when the Navigation app is launched, where the heap usage exceeds 9500 bytes (meaning that the heap overflows and could potentially corrupt the stack). This is a bug that should be fixed in #362. To know exactly what's consuming heap memory, you can `wrap` functions like `malloc()` into your own functions. In this wrapper, you can add logging code or put breakpoints: diff --git a/doc/contribute.md b/doc/contribute.md index b1be84a..f2a4aea 100644 --- a/doc/contribute.md +++ b/doc/contribute.md @@ -46,7 +46,7 @@ Other contributors can post comments about the pull request, maybe ask for more Once the pull request is reviewed and accepted, it'll be merged into **develop** and will be released in the next version of the firmware. -## Why all these rules? +## Why all these rules? Reviewing pull requests is a **very time consuming task**. Everything you do to make reviewing easier will **get your PR merged faster**. -- cgit v0.10.2 From c8214bc666a5daf1b0c1c323ae4af7cb5ae2510b Mon Sep 17 00:00:00 2001 From: Eli Weiss Date: Tue, 30 Nov 2021 13:22:47 -0600 Subject: Update MemoryAnalysis.md Cleaned up MemoryAnalysis.md for greater readability diff --git a/doc/MemoryAnalysis.md b/doc/MemoryAnalysis.md index 20bb928..376f98f 100644 --- a/doc/MemoryAnalysis.md +++ b/doc/MemoryAnalysis.md @@ -60,7 +60,7 @@ Puncover is really easy to install: - Launch a browser at http://localhost:5000/ ### Analysis -Using the MAP file and tools, we can easily see what symbols are using most of the flash memory. In this case, with no surprise, fonts and graphics are the largest use of flash memory. +Using the MAP file and tools, we can easily see what symbols are using most of the flash memory. In this case, unsuprisingly, fonts and graphics are the largest use of flash memory. ![Puncover](./memoryAnalysis/puncover-all-symbols.png) @@ -245,7 +245,7 @@ Using this technique, I was able to trace all malloc calls at boot (boot -> digi - https://www.embedded.com/mastering-stack-and-heap-for-system-reliability-part-3-avoiding-heap-errors/ ## LVGL -I did a deep analysis of the usage of the buffer dedicated for lvgl (managed by lv_mem). +I did a deep analysis of the usage of the buffer dedicated to lvgl (managed by lv_mem). This buffer is used by lvgl to allocated memory for drivers (display/touch), screens, themes, and all widgets created by the apps. The usage of this buffer can be monitored using this code : @@ -256,7 +256,7 @@ lv_mem_monitor(&mon); NRF_LOG_INFO("\t Free %d / %d -- max %d", mon.free_size, mon.total_size, mon.max_used); ``` -The most interesting metric is `mon.max_used` which specifies the maximum number of bytes that were used from this buffer since the initialization of lvgl. +The most interesting metric is `mon.max_used` which specifies the maximum number of bytes used from this buffer since the initialization of lvgl. According to my measurements, initializing the theme, display/touch driver and screens cost **4752** bytes! Then, initializing the digital clock face costs **1541 bytes**. For example a simple lv_label needs **~140 bytes** of memory. -- cgit v0.10.2 From 90352af626cc0087143e824f62f5dcee9f58f29c Mon Sep 17 00:00:00 2001 From: Eli Weiss Date: Thu, 2 Dec 2021 14:50:59 -0600 Subject: Improved documentation readability Improved documentation readability by rephrasing confusing sentences. Added Sitronix ST7789V datasheet link to SPI-LCD-driver.md for easier reference. diff --git a/doc/NavigationService.md b/doc/NavigationService.md index fd81d0b..b24a03b 100644 --- a/doc/NavigationService.md +++ b/doc/NavigationService.md @@ -1,6 +1,6 @@ # Navigation Service ## Introduction -The navigation ble service provides 4 characteristics to allow the the watch to display navigation instructions from a companion application. The intended purpose is when performing some outdoor activities, for example running or cycling. +The navigation ble service provides 4 characteristics to allow the the watch to display navigation instructions from a companion application. This service is intended to be used when performing some outdoor activities, for example running or cycling. The 4 characteristics are: flag (string) - Upcoming icon name @@ -22,7 +22,7 @@ This is a client supplied string describing the upcoming instruction such as "At This is a short string describing the distance to the upcoming instruction such as "50 m". ## 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. +The percent complete in a uint8. The watch displays this as an overall progress in a progress bar. ## Full icon list * arrive diff --git a/doc/PinetimeStubWithNrf52DK.md b/doc/PinetimeStubWithNrf52DK.md index c485792..e85bd55 100644 --- a/doc/PinetimeStubWithNrf52DK.md +++ b/doc/PinetimeStubWithNrf52DK.md @@ -1,11 +1,11 @@ # Build a stub for PineTime using NRF52-DK -[NRF52-DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52-DK) is the official developpment kit for NRF52832 SoC from Nordic Semiconductor. +[NRF52-DK](https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52-DK) is the official developpment kit for the NRF52832 SoC from Nordic Semiconductor used in the PineTime. -It can be very useful for PineTime development: - * You can use it embedded JLink SWD programmer/debugger to program and debug you code on the PineTime - * As it's based on the same SoC than the PineTime, you can program it to actually run the same code than the PineTime. +This development kit can be very useful for PineTime development: + * You can use its embedded JLink SWD programmer/debugger to program and debug your code on the PineTime + * As it's based on the same SoC than the PineTime, you can program it to actually run the same code as the PineTime. -This page is about the 2nd point : we will build a stub that will allow us to run the same code than the one you could run on the PineTime. This will allow you to work more easily if you don't have a PineTime dev kit around, if you don't want to modify your dev kit for SWD programming, or if you want to use some feature from the DK (like power measurement). +This page is about the 2nd point : we will build a stub that will allow us to run the same code you can run on the PineTime. This will allow you to work more easily if you don't have a PineTime dev kit around, if you don't want to modify your dev kit for SWD programming, or if you want to use some feature from the NRF52-DK (like power measurement). This stub only implements the display, the button and the BLE radio. The other features from the pintime are missing: * heart rate sensor @@ -41,7 +41,7 @@ You just need to make the following connections: | P0.13 | Button IN (D3 in my case) | | GND | GND | -You also need to enable the I/O expander to disconnect pins from buttons and led on the NRF52-DK and leave them available on the pin headers: +You also need to enable the I/O expander to disconnect pins from the buttons and LED on the NRF52-DK and leave them available on the pin headers: | NRF52 -DK | NRF52- DK | | --------- | --------- | diff --git a/doc/SPI-LCD-driver.md b/doc/SPI-LCD-driver.md index f787aab..29f3bbf 100644 --- a/doc/SPI-LCD-driver.md +++ b/doc/SPI-LCD-driver.md @@ -1,6 +1,6 @@ # The SPI LCD driver ## Introduction -The LCD controller that drive the display of the Pinetime is the Sitronix ST7789V. This controller is easy to integrate with an MCU thanks to its SPI interface, and has some interesting features like: +The LCD controller that drives the display of the Pinetime is the [Sitronix ST7789V](https://wiki.pine64.org/images/5/54/ST7789V_v1.6.pdf). This controller is easy to integrate with an MCU thanks to its SPI interface, and has some interesting features like: - an on-chip display data RAM that can store the whole framebuffer - partial screen update - hardware assisted vertical scrolling diff --git a/doc/SWD.md b/doc/SWD.md index 4146e6a..668eaa5 100644 --- a/doc/SWD.md +++ b/doc/SWD.md @@ -4,9 +4,9 @@ Download the files **bootloader.bin**, **image-x.y.z.bin** and **pinetime-graphi ![Image file](imageFile.png) The bootloader reads a boot logo from the external SPI flash memory. The first step consists of flashing a tool in the MCU that will flash the boot logo into this SPI flash memory. This first step is optional but recommended (the bootloader will display garbage on screen for a few second if you don't do it). -Using your SWD tool, flash **pinetime-graphics-x.y.z.bin** at offset **0x0000**. Reset the MCU and wait for a few second, until the logo is completely drawn on the display. +Using your SWD tool, flash **pinetime-graphics-x.y.z.bin** at offset **0x0000**. Reset the MCU and wait for a few seconds until the logo is completely drawn on the display. -Then, using your SWD tool, flash those file at specific offset: +Then, using your SWD tool. Flash those file at specific offset: - bootloader.bin : **0x0000** - image-x.y.z.bin : **0x8000** diff --git a/doc/ble.md b/doc/ble.md index 314097d..d250263 100644 --- a/doc/ble.md +++ b/doc/ble.md @@ -120,11 +120,11 @@ Reading a value from the firmware version characteristic will yield a UTF-8 enco #### Battery Level -Reading from the battery level characteristic yields a single byte of data. This byte can be converted to an unsigned 8-bit integer which will be the battery percentage. This characteristic allows notify for updates as the value changes. +Reading from the battery level characteristic yields a single byte of data. This byte can be converted to an unsigned 8-bit integer which will be the battery percentage. This characteristic allows notifications for updates as the value changes. #### Heart Rate -Reading from the heart rate characteristic yields two bytes of data. I am not sure of the function of the first byte. It appears to always be zero. The second byte can be converted to an unsigned 8-bit integer which is the current heart rate. This characteristic also allows notify for updates as the value changes. +Reading from the heart rate characteristic yields two bytes of data. I am not sure of the function of the first byte. It appears to always be zero. The second byte can be converted to an unsigned 8-bit integer which is the current heart rate. This characteristic also allows notifications for updates as the value changes. --- diff --git a/doc/branches.md b/doc/branches.md index ef280f4..b06c10c 100644 --- a/doc/branches.md +++ b/doc/branches.md @@ -9,4 +9,4 @@ New features should be implemented in **feature branches** created from **develo To release a new version of the application, when develop is considered stable, a **release** branch is created from **develop**. This can be considered as a *release candidate* branch. When everything is OK, this release branch is merged into **master** and the release is generated (a tag is applied to git, the release note is finalized, binaries are built,...) from **master**. -Git flow also supports the creation of **hotfix** branches when a bug is discovered in a released version. The **hotfix** branch is created from **master** and will be used only to implement a fix to this bug. Multiple hotfix branches can be created for the same release if more than one bugs are discovered. \ No newline at end of file +Git flow also supports the creation of **hotfix** branches when a bug is discovered in a released version. The **hotfix** branch is created from **master** and will be used only to implement a fix to this bug. Multiple hotfix branches can be created for the same release if multiple bugs are discovered. \ No newline at end of file diff --git a/doc/openOCD.md b/doc/openOCD.md index b3661ce..a7386e3 100644 --- a/doc/openOCD.md +++ b/doc/openOCD.md @@ -1,12 +1,12 @@ # OpenOCD and STLink OpenOCD (**Open O**n **C**hip **D**ebugger) is an open source tool that interfaces with many SWD/JTAG debugger to provide debugging and *in-system* programming for embedded target devices. -It supports the **NRF52** (the CPU of the PineTime) and the **STLinkV2**, a cheap SWD debugger. +OpenOCD supports the **NRF52** (the CPU of the PineTime) and the **STLinkV2**, a cheap SWD debugger. -It works on X86 computers, as well as ARM/ARM64 computers and SBC (like the RaspberryPi and Pine64 Pinebook Pro) ! +OpenOCD works on X86 computers, ARM/ARM64 computers, and SBCs (like the RaspberryPi and Pine64 Pinebook Pro)! ## Installation -We will build OpenOCD from sources, as packages from Linux distributions are most of the time outdated and do not support the NRF52 correctly. +We will build OpenOCD from sources, as packages from Linux distributions are often outdated and do not support the NRF52 correctly. - Fetch the sources from GIT, and build and install it: @@ -27,7 +27,7 @@ sudo cp contrib/60-openocd.rules /etc/udev/rules.d/ sudo udevadm control --reload-rules ``` - - You can now plug your STLinkV2 in a USB port and run OpenOCD to see if it's working correctly: + - You can now plug your STLinkV2 into a USB port and run OpenOCD to see if it's working correctly: ``` $ openocd -f interface/stlink.cfg -f target/nrf52.cfg @@ -63,7 +63,7 @@ gdb_breakpoint_override hard source [find target/nrf52.cfg] ``` -This file specifies to OpenOCD which debugger and target it will be connected to.. +This file specifies to OpenOCD which debugger and target it will be connected to. Then, we use various *user files* to use OpenOCD to flash InfiniTime binary files. -- cgit v0.10.2 From 97668c775bb5e501b32fce2fc92f4a5995aec1b1 Mon Sep 17 00:00:00 2001 From: Eli Weiss Date: Sun, 5 Dec 2021 10:41:01 -0600 Subject: Improved "Getting Started" readability Clarified ambiguous references, clarified phrasing diff --git a/doc/branches.md b/doc/branches.md index b06c10c..3c86375 100644 --- a/doc/branches.md +++ b/doc/branches.md @@ -1,7 +1,7 @@ # Branches The branching model of this project is based on the workflow named [Git flow](https://nvie.com/posts/a-successful-git-branching-model/). -It is based on 2 main branches: +The project is based on 2 main branches: - **master** : this branch is always ready to be deployed. It means that at any time, we should be able to build the branch and release a new version of the application. - **develop** : this branch contains the latest development that will be integrated in the next release once it's considered as stable. diff --git a/doc/code/Apps.md b/doc/code/Apps.md index b1c7d20..0e6d13c 100644 --- a/doc/code/Apps.md +++ b/doc/code/Apps.md @@ -8,8 +8,8 @@ This page will teach you: The user interface of InfiniTime is made up of **screens**. Screens that are opened from the app launcher are considered **apps**. 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)). +An instance of the class is created when the app is launched, and destroyed when the user exits the app. +Apps 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. @@ -21,7 +21,7 @@ A destructor is needed to clean up LVGL and restore any changes (for example re- 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. +If you have any doubts, you can always look at how the other apps function for examples. ### Continuous updating If your app needs to be updated continuously, you can do so by overriding the `Refresh()` function in your class diff --git a/doc/code/Intro.md b/doc/code/Intro.md index bf68c7a..23b3ade 100644 --- a/doc/code/Intro.md +++ b/doc/code/Intro.md @@ -24,9 +24,9 @@ There are also other tasks that are responsible for Bluetooth ("ll" and "ble" in 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) +If you absolutely need to create another task, try to estimate 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. +You can use `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. diff --git a/doc/gettingStarted/about-software.md b/doc/gettingStarted/about-software.md index b19a610..e935d93 100644 --- a/doc/gettingStarted/about-software.md +++ b/doc/gettingStarted/about-software.md @@ -12,15 +12,15 @@ InfiniTime has three distinct firmwares: **OTA** (**O**ver **T**he **A**ir) refers to updating of the firmware over BLE (**B**luetooth **L**ow **E**nergy). This is a functionality that allows the user to update the firmware on their device wirelessly. -**DFU** (**D**evice **F**irmware **U**pdate) is 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). +**DFU** (**D**evice **F**irmware **U**pdate) is the file format and protocol used to send the update of the firmware to the watch over-the-air. InfiniTime implements the (legacy) DFU protocol from Nordic Semiconductor (NRF). ## Bootloader -Most of the time, the bootloader just runs without your intervention (update and load the firmware). +Most of the time, the bootloader just runs without your intervention (updating and loading the firmware). -However, you can enable 2 functionalities using the push button: +However, you can use the bootloader to rollback to the previous firmware, or load the recovery firmware using the push button: - - Push the button until the pine cone is drawn in **blue** to force the rollback of the previous version of the firmware, even if you've already validated the updated one - - Push the button until the pine cone is drawn in **red** to load the recovery firmware. This recovery firmware only provides BLE connectivity and OTA functionality. + - Press and hold the button until the pine cone is drawn in **blue** to force the rollback of the previous version of the firmware, even if you've already validated the current one. + - Press and hold the button until the pine cone is drawn in **red** to load the recovery firmware. This recovery firmware only provides BLE connectivity and OTA functionality. More info about the bootloader in [its project page](https://github.com/JF002/pinetime-mcuboot-bootloader/blob/master/README.md). diff --git a/doc/gettingStarted/gettingStarted-1.0.md b/doc/gettingStarted/gettingStarted-1.0.md index 30b8bdb..890164f 100644 --- a/doc/gettingStarted/gettingStarted-1.0.md +++ b/doc/gettingStarted/gettingStarted-1.0.md @@ -18,7 +18,7 @@ You can sync the time using companion apps. You can also set the time in the settings without a companion app. (version >1.7.0) -InfiniTime doesn't handle daylight savings automatically, so make sure to set the correct the time or sync it with a companion app +InfiniTime doesn't handle daylight savings automatically, so make sure to set the correct the time or sync it with a companion app. ### Digital watch face diff --git a/doc/gettingStarted/ota-gadgetbridge.md b/doc/gettingStarted/ota-gadgetbridge.md index 022b5e4..fe26c03 100644 --- a/doc/gettingStarted/ota-gadgetbridge.md +++ b/doc/gettingStarted/ota-gadgetbridge.md @@ -18,7 +18,7 @@ Now that Gadgetbridge is connected to your PineTime, use a file browser applicat ![Gadgetbridge 3](gadgetbridge3.jpg) -Read carefully the warning and tap **Install**: +Read the warning carefully and tap **Install**: ![Gadgetbridge 4](gadgetbridge4.jpg) diff --git a/doc/openOCD.md b/doc/openOCD.md index a7386e3..df24b30 100644 --- a/doc/openOCD.md +++ b/doc/openOCD.md @@ -6,7 +6,7 @@ OpenOCD supports the **NRF52** (the CPU of the PineTime) and the **STLinkV2**, a OpenOCD works on X86 computers, ARM/ARM64 computers, and SBCs (like the RaspberryPi and Pine64 Pinebook Pro)! ## Installation -We will build OpenOCD from sources, as packages from Linux distributions are often outdated and do not support the NRF52 correctly. +We will build OpenOCD from sources, as packages from Linux distributions are most of the time outdated and do not support the NRF52 properly. - Fetch the sources from GIT, and build and install it: -- cgit v0.10.2 From ab059b90044981b0feb3f37201fcf6635d2c4e1f Mon Sep 17 00:00:00 2001 From: Eli Weiss Date: Sun, 5 Dec 2021 14:04:35 -0600 Subject: Revised documentation diff --git a/doc/NavigationService.md b/doc/NavigationService.md index b24a03b..5a4f69e 100644 --- a/doc/NavigationService.md +++ b/doc/NavigationService.md @@ -1,6 +1,6 @@ # Navigation Service ## Introduction -The navigation ble service provides 4 characteristics to allow the the watch to display navigation instructions from a companion application. This service is intended to be used when performing some outdoor activities, for example running or cycling. +The navigation ble service provides 4 characteristics to allow the watch to display navigation instructions from a companion application. This service is intended to be used when performing some outdoor activities, for example running or cycling. The 4 characteristics are: flag (string) - Upcoming icon name diff --git a/doc/PinetimeStubWithNrf52DK.md b/doc/PinetimeStubWithNrf52DK.md index e85bd55..dcaad69 100644 --- a/doc/PinetimeStubWithNrf52DK.md +++ b/doc/PinetimeStubWithNrf52DK.md @@ -5,7 +5,7 @@ This development kit can be very useful for PineTime development: * You can use its embedded JLink SWD programmer/debugger to program and debug your code on the PineTime * As it's based on the same SoC than the PineTime, you can program it to actually run the same code as the PineTime. -This page is about the 2nd point : we will build a stub that will allow us to run the same code you can run on the PineTime. This will allow you to work more easily if you don't have a PineTime dev kit around, if you don't want to modify your dev kit for SWD programming, or if you want to use some feature from the NRF52-DK (like power measurement). +This page is about the 2nd point. We will build a stub that will allow us to run the same code you can run on the PineTime. This will allow you to work more easily if you don't have a PineTime dev kit around, if you don't want to modify your dev kit for SWD programming, or if you want to use some feature from the NRF52-DK (like power measurement). This stub only implements the display, the button and the BLE radio. The other features from the pintime are missing: * heart rate sensor diff --git a/doc/SWD.md b/doc/SWD.md index 668eaa5..155983b 100644 --- a/doc/SWD.md +++ b/doc/SWD.md @@ -6,7 +6,7 @@ Download the files **bootloader.bin**, **image-x.y.z.bin** and **pinetime-graphi The bootloader reads a boot logo from the external SPI flash memory. The first step consists of flashing a tool in the MCU that will flash the boot logo into this SPI flash memory. This first step is optional but recommended (the bootloader will display garbage on screen for a few second if you don't do it). Using your SWD tool, flash **pinetime-graphics-x.y.z.bin** at offset **0x0000**. Reset the MCU and wait for a few seconds until the logo is completely drawn on the display. -Then, using your SWD tool. Flash those file at specific offset: +Then, using your SWD tool, flash these file at the following offsets: - bootloader.bin : **0x0000** - image-x.y.z.bin : **0x8000** diff --git a/doc/code/Apps.md b/doc/code/Apps.md index 0e6d13c..f067b58 100644 --- a/doc/code/Apps.md +++ b/doc/code/Apps.md @@ -21,7 +21,7 @@ A destructor is needed to clean up LVGL and restore any changes (for example re- 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 function for examples. +If you have any doubts, you can always look at how the other apps function for reference. ### Continuous updating If your app needs to be updated continuously, you can do so by overriding the `Refresh()` function in your class -- cgit v0.10.2 From fb1946b06ec8fcdeca0936e3ac0f0ed36bd42e9a Mon Sep 17 00:00:00 2001 From: Eli Weiss Date: Wed, 15 Dec 2021 13:29:39 -0500 Subject: Update .gitignore diff --git a/.gitignore b/.gitignore index 39fb672..0474017 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,7 @@ Testing/Temporary/ #VSCODE .vscode/.cortex-debug.registers.state.json .vscode/.cortex-debug.peripherals.state.json + +#build files +src/nRF5_SDK_15.3.0_59ac345 +src/arm-none-eabi -- cgit v0.10.2 From 5b7915b5c9474ba74f7d31eae5e62c5d4793b0f6 Mon Sep 17 00:00:00 2001 From: Reinhold Gschweicher Date: Wed, 13 Oct 2021 23:35:54 +0200 Subject: InfiniPaint: add missing include algorithm for std::fill diff --git a/src/displayapp/screens/InfiniPaint.cpp b/src/displayapp/screens/InfiniPaint.cpp index 93c3c4a..d279faf 100644 --- a/src/displayapp/screens/InfiniPaint.cpp +++ b/src/displayapp/screens/InfiniPaint.cpp @@ -2,6 +2,8 @@ #include "displayapp/DisplayApp.h" #include "displayapp/LittleVgl.h" +#include // std::fill + using namespace Pinetime::Applications::Screens; InfiniPaint::InfiniPaint(Pinetime::Applications::DisplayApp* app, -- cgit v0.10.2 From 86d180a85590f742f2f8e27ce2751e988f194245 Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 4 Oct 2021 11:13:45 +0300 Subject: Improve gesture consistency across the firmware diff --git a/src/displayapp/screens/Metronome.cpp b/src/displayapp/screens/Metronome.cpp index 8347e1b..6b6ad2c 100644 --- a/src/displayapp/screens/Metronome.cpp +++ b/src/displayapp/screens/Metronome.cpp @@ -113,9 +113,15 @@ void Metronome::OnEvent(lv_obj_t* obj, lv_event_t event) { lv_label_set_text_fmt(bpmValue, "%03d", bpm); } tappedTime = xTaskGetTickCount(); + allowExit = true; } break; } + case LV_EVENT_RELEASED: + case LV_EVENT_PRESS_LOST: + if (obj == bpmTap) { + allowExit = false; + } case LV_EVENT_CLICKED: { if (obj == playPause) { metronomeStarted = !metronomeStarted; @@ -135,3 +141,11 @@ void Metronome::OnEvent(lv_obj_t* obj, lv_event_t event) { break; } } + +bool Metronome::OnTouchEvent(TouchEvents event) { + if (event == TouchEvents::SwipeDown && allowExit) { + running = false; + return true; + } + return false; +} diff --git a/src/displayapp/screens/Metronome.h b/src/displayapp/screens/Metronome.h index 373c884..6e6589f 100644 --- a/src/displayapp/screens/Metronome.h +++ b/src/displayapp/screens/Metronome.h @@ -14,6 +14,7 @@ namespace Pinetime { ~Metronome() override; void Refresh() override; void OnEvent(lv_obj_t* obj, lv_event_t event); + bool OnTouchEvent(TouchEvents event) override; private: TickType_t startTime = 0; @@ -25,6 +26,7 @@ namespace Pinetime { uint8_t counter = 1; bool metronomeStarted = false; + bool allowExit = false; lv_obj_t *bpmArc, *bpmTap, *bpmValue; lv_obj_t *bpbDropdown, *currentBpbText; diff --git a/src/displayapp/screens/Music.cpp b/src/displayapp/screens/Music.cpp index 8a01a6f..9f17b95 100644 --- a/src/displayapp/screens/Music.cpp +++ b/src/displayapp/screens/Music.cpp @@ -277,12 +277,14 @@ bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) { return true; } case TouchEvents::SwipeDown: { - lv_obj_set_hidden(btnNext, false); - lv_obj_set_hidden(btnPrev, false); - - lv_obj_set_hidden(btnVolDown, true); - lv_obj_set_hidden(btnVolUp, true); - return true; + if (lv_obj_get_hidden(btnNext)) { + lv_obj_set_hidden(btnNext, false); + lv_obj_set_hidden(btnPrev, false); + lv_obj_set_hidden(btnVolDown, true); + lv_obj_set_hidden(btnVolUp, true); + return true; + } + return false; } case TouchEvents::SwipeLeft: { musicService.event(Controllers::MusicService::EVENT_MUSIC_NEXT); -- cgit v0.10.2 From 54f588ce6314708f50cc4cff96d8d3d921733dee Mon Sep 17 00:00:00 2001 From: Riku Isokoski Date: Mon, 4 Oct 2021 11:32:50 +0300 Subject: Add missing break diff --git a/src/displayapp/screens/Metronome.cpp b/src/displayapp/screens/Metronome.cpp index 6b6ad2c..f6f269d 100644 --- a/src/displayapp/screens/Metronome.cpp +++ b/src/displayapp/screens/Metronome.cpp @@ -122,6 +122,7 @@ void Metronome::OnEvent(lv_obj_t* obj, lv_event_t event) { if (obj == bpmTap) { allowExit = false; } + break; case LV_EVENT_CLICKED: { if (obj == playPause) { metronomeStarted = !metronomeStarted; -- cgit v0.10.2 From 51d2888b52cb5d8563426954ac4b06679314cee5 Mon Sep 17 00:00:00 2001 From: Jackson Date: Mon, 29 Nov 2021 12:54:30 -0500 Subject: Switch CI/CD to build using ninja vs. make By switching the CI/CD workflow to use CMake's `ninja` backend, the build time goes down considerably (~4.5 minutes to ~2) compared to GNU Make diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3b753a3..ac0611c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -113,7 +113,7 @@ jobs: run: | mkdir -p build cd build - cmake -DARM_NONE_EABI_TOOLCHAIN_PATH=${{ runner.temp }}/arm-none-eabi -DNRF5_SDK_PATH=${{ runner.temp }}/nrf5_sdk -DUSE_OPENOCD=1 -DBUILD_DFU=1 ../ + cmake -G Ninja -DARM_NONE_EABI_TOOLCHAIN_PATH=${{ runner.temp }}/arm-none-eabi -DNRF5_SDK_PATH=${{ runner.temp }}/nrf5_sdk -DUSE_OPENOCD=1 -DBUILD_DFU=1 ../ ######################################################################################### # Make and Upload DFU Package @@ -126,7 +126,7 @@ jobs: - name: Make pinetime-mcuboot-app run: | cd build - make pinetime-mcuboot-app + ninja pinetime-mcuboot-app - name: Unzip DFU package run: | @@ -145,7 +145,7 @@ jobs: - name: Make pinetime-app run: | cd build - make pinetime-app + ninja pinetime-app - name: Upload standalone firmware uses: actions/upload-artifact@v2 @@ -159,7 +159,7 @@ jobs: - name: Make pinetime-recovery run: | cd build - make pinetime-recovery + ninja pinetime-recovery ######################################################################################### # Finish -- cgit v0.10.2 From baa5954724a91b81e35812ffd1939438689f3446 Mon Sep 17 00:00:00 2001 From: Jackson Date: Tue, 7 Dec 2021 15:38:53 -0500 Subject: Use CMake universal build command Rather than using generator-specific build commands (ex. `make` or `ninja`), the CI build now uses `cmake --build` for a more modern, best practices approach. diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ac0611c..58a6393 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -125,8 +125,7 @@ jobs: - name: Make pinetime-mcuboot-app run: | - cd build - ninja pinetime-mcuboot-app + cmake --build build --target pinetime-mcuboot-app - name: Unzip DFU package run: | @@ -144,8 +143,7 @@ jobs: - name: Make pinetime-app run: | - cd build - ninja pinetime-app + cmake --build build --target pinetime-app - name: Upload standalone firmware uses: actions/upload-artifact@v2 @@ -158,8 +156,7 @@ jobs: - name: Make pinetime-recovery run: | - cd build - ninja pinetime-recovery + cmake --build build --target pinetime-recovery ######################################################################################### # Finish -- cgit v0.10.2 From d034bd131e11fd2a2ab33058991802aab7cfa305 Mon Sep 17 00:00:00 2001 From: Stephanie Date: Tue, 19 Oct 2021 23:42:48 -0400 Subject: Added "lap" button to step counter diff --git a/src/components/motion/MotionController.h b/src/components/motion/MotionController.h index c72d8a4..3b4d78b 100644 --- a/src/components/motion/MotionController.h +++ b/src/components/motion/MotionController.h @@ -28,6 +28,12 @@ namespace Pinetime { uint32_t NbSteps() const { return nbSteps; } + void SetPrevTotalSteps(uint32_t steps) { + stepsAtLastLap = steps; + } + uint32_t GetPrevTotalSteps() const { + return stepsAtLastLap; + } bool ShouldWakeUp(bool isSleeping); void IsSensorOk(bool isOk); @@ -44,6 +50,7 @@ namespace Pinetime { private: uint32_t nbSteps; + uint32_t stepsAtLastLap = 0; int16_t x; int16_t y; int16_t z; diff --git a/src/displayapp/screens/Steps.cpp b/src/displayapp/screens/Steps.cpp index 916138e..572b9fb 100644 --- a/src/displayapp/screens/Steps.cpp +++ b/src/displayapp/screens/Steps.cpp @@ -5,6 +5,11 @@ using namespace Pinetime::Applications::Screens; +static void lap_event_handler(lv_obj_t* obj, lv_event_t event) { + auto* steps = static_cast(obj->user_data); + steps->lapBtnEventHandler(event); +} + Steps::Steps(Pinetime::Applications::DisplayApp* app, Controllers::MotionController& motionController, Controllers::Settings& settingsController) @@ -17,30 +22,31 @@ Steps::Steps(Pinetime::Applications::DisplayApp* app, lv_obj_set_style_local_radius(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, 0); lv_obj_set_style_local_line_color(stepsArc, LV_ARC_PART_INDIC, LV_STATE_DEFAULT, lv_color_hex(0x0000FF)); lv_arc_set_end_angle(stepsArc, 200); - lv_obj_set_size(stepsArc, 220, 220); + lv_obj_set_size(stepsArc, 200, 200); lv_arc_set_range(stepsArc, 0, 500); - lv_obj_align(stepsArc, nullptr, LV_ALIGN_CENTER, 0, 0); + lv_obj_align(stepsArc, nullptr, LV_ALIGN_CENTER, 0, -20); stepsCount = motionController.NbSteps(); + currentLapSteps = stepsCount - motionController.GetPrevTotalSteps(); lv_arc_set_value(stepsArc, int16_t(500 * stepsCount / settingsController.GetStepsGoal())); lSteps = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(lSteps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00)); lv_obj_set_style_local_text_font(lSteps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); - lv_label_set_text_fmt(lSteps, "%li", stepsCount); - lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -20); + lv_label_set_text_fmt(lSteps, "%li", currentLapSteps); + lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -40); lv_obj_t* lstepsL = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(lstepsL, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111)); lv_label_set_text_static(lstepsL, "Steps"); - lv_obj_align(lstepsL, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 10); + lv_obj_align(lstepsL, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 5); lv_obj_t* lstepsGoal = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(lstepsGoal, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_CYAN); lv_label_set_text_fmt(lstepsGoal, "Goal\n%lu", settingsController.GetStepsGoal()); lv_label_set_align(lstepsGoal, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lstepsGoal, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 60); + lv_obj_align(lstepsGoal, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 30); lv_obj_t* backgroundLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP); @@ -48,6 +54,22 @@ Steps::Steps(Pinetime::Applications::DisplayApp* app, lv_obj_set_pos(backgroundLabel, 0, 0); lv_label_set_text_static(backgroundLabel, ""); + btnLap = lv_btn_create(lv_scr_act(), nullptr); + btnLap->user_data = this; + lv_obj_set_event_cb(btnLap, lap_event_handler); + lv_obj_set_height(btnLap, 50); + lv_obj_set_width(btnLap, 115); + lv_obj_align(btnLap, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); + lv_obj_set_style_local_bg_color(btnLap, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x080808)); + txtLap = lv_label_create(btnLap, nullptr); + lv_obj_set_style_local_text_color(btnLap, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x888888)); + lv_label_set_text(txtLap, Symbols::lapsFlag); + + totalStepsText = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(totalStepsText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); + lv_label_set_text_fmt(totalStepsText, "Total\n%li", motionController.GetPrevTotalSteps()); + lv_obj_align(totalStepsText, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + taskRefresh = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this); } @@ -58,9 +80,23 @@ Steps::~Steps() { void Steps::Refresh() { stepsCount = motionController.NbSteps(); + currentLapSteps = stepsCount - motionController.GetPrevTotalSteps(); + + lv_label_set_text_fmt(lSteps, "%li", currentLapSteps); + lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -40); - lv_label_set_text_fmt(lSteps, "%li", stepsCount); - lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -20); + lv_label_set_text_fmt(totalStepsText, "Total\n%li", stepsCount); + lv_obj_align(totalStepsText, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); lv_arc_set_value(stepsArc, int16_t(500 * stepsCount / settingsController.GetStepsGoal())); } + +void Steps::lapBtnEventHandler(lv_event_t event) { + if (event != LV_EVENT_CLICKED) { + return; + } + stepsCount = motionController.NbSteps(); + motionController.SetPrevTotalSteps(stepsCount); + Refresh(); +} + diff --git a/src/displayapp/screens/Steps.h b/src/displayapp/screens/Steps.h index 68daf16..08f8ea2 100644 --- a/src/displayapp/screens/Steps.h +++ b/src/displayapp/screens/Steps.h @@ -20,14 +20,20 @@ namespace Pinetime { ~Steps() override; void Refresh() override; + void lapBtnEventHandler(lv_event_t event); private: Controllers::MotionController& motionController; Controllers::Settings& settingsController; + uint32_t currentLapSteps = 0; + lv_obj_t* lSteps; lv_obj_t* lStepsIcon; lv_obj_t* stepsArc; + lv_obj_t* btnLap; + lv_obj_t* txtLap; + lv_obj_t* totalStepsText; uint32_t stepsCount; -- cgit v0.10.2 From fb87fdb2d9720ce1bca2c4920b859658a6480167 Mon Sep 17 00:00:00 2001 From: Stephanie Date: Wed, 20 Oct 2021 14:29:10 -0400 Subject: Changed lap counter to trip meter diff --git a/src/components/motion/MotionController.h b/src/components/motion/MotionController.h index 3b4d78b..aea82f7 100644 --- a/src/components/motion/MotionController.h +++ b/src/components/motion/MotionController.h @@ -28,11 +28,11 @@ namespace Pinetime { uint32_t NbSteps() const { return nbSteps; } - void SetPrevTotalSteps(uint32_t steps) { - stepsAtLastLap = steps; + void SetTripSteps(uint32_t steps) { + stepsAtLastTrip = steps; } - uint32_t GetPrevTotalSteps() const { - return stepsAtLastLap; + uint32_t GetTripSteps() const { + return stepsAtLastTrip; } bool ShouldWakeUp(bool isSleeping); @@ -50,7 +50,7 @@ namespace Pinetime { private: uint32_t nbSteps; - uint32_t stepsAtLastLap = 0; + uint32_t stepsAtLastTrip = 0; int16_t x; int16_t y; int16_t z; diff --git a/src/displayapp/screens/Steps.cpp b/src/displayapp/screens/Steps.cpp index 572b9fb..5d8c386 100644 --- a/src/displayapp/screens/Steps.cpp +++ b/src/displayapp/screens/Steps.cpp @@ -22,19 +22,19 @@ Steps::Steps(Pinetime::Applications::DisplayApp* app, lv_obj_set_style_local_radius(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, 0); lv_obj_set_style_local_line_color(stepsArc, LV_ARC_PART_INDIC, LV_STATE_DEFAULT, lv_color_hex(0x0000FF)); lv_arc_set_end_angle(stepsArc, 200); - lv_obj_set_size(stepsArc, 200, 200); + lv_obj_set_size(stepsArc, 240, 240); lv_arc_set_range(stepsArc, 0, 500); - lv_obj_align(stepsArc, nullptr, LV_ALIGN_CENTER, 0, -20); + lv_obj_align(stepsArc, nullptr, LV_ALIGN_CENTER, 0, 0); stepsCount = motionController.NbSteps(); - currentLapSteps = stepsCount - motionController.GetPrevTotalSteps(); + currentTripSteps = stepsCount - motionController.GetTripSteps(); lv_arc_set_value(stepsArc, int16_t(500 * stepsCount / settingsController.GetStepsGoal())); lSteps = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(lSteps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00)); lv_obj_set_style_local_text_font(lSteps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42); - lv_label_set_text_fmt(lSteps, "%li", currentLapSteps); + lv_label_set_text_fmt(lSteps, "%li", stepsCount); lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -40); lv_obj_t* lstepsL = lv_label_create(lv_scr_act(), nullptr); @@ -44,7 +44,7 @@ Steps::Steps(Pinetime::Applications::DisplayApp* app, lv_obj_t* lstepsGoal = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(lstepsGoal, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_CYAN); - lv_label_set_text_fmt(lstepsGoal, "Goal\n%lu", settingsController.GetStepsGoal()); + lv_label_set_text_fmt(lstepsGoal, "Goal: %lu", settingsController.GetStepsGoal()); lv_label_set_align(lstepsGoal, LV_LABEL_ALIGN_CENTER); lv_obj_align(lstepsGoal, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 30); @@ -54,21 +54,27 @@ Steps::Steps(Pinetime::Applications::DisplayApp* app, lv_obj_set_pos(backgroundLabel, 0, 0); lv_label_set_text_static(backgroundLabel, ""); - btnLap = lv_btn_create(lv_scr_act(), nullptr); - btnLap->user_data = this; - lv_obj_set_event_cb(btnLap, lap_event_handler); - lv_obj_set_height(btnLap, 50); - lv_obj_set_width(btnLap, 115); - lv_obj_align(btnLap, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); - lv_obj_set_style_local_bg_color(btnLap, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x080808)); - txtLap = lv_label_create(btnLap, nullptr); - lv_obj_set_style_local_text_color(btnLap, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x888888)); - lv_label_set_text(txtLap, Symbols::lapsFlag); - - totalStepsText = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(totalStepsText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); - lv_label_set_text_fmt(totalStepsText, "Total\n%li", motionController.GetPrevTotalSteps()); - lv_obj_align(totalStepsText, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + btnTrip = lv_btn_create(lv_scr_act(), nullptr); + btnTrip->user_data = this; + lv_obj_set_event_cb(btnTrip, lap_event_handler); + lv_obj_set_height(btnTrip, 50); + lv_obj_set_width(btnTrip, 115); + lv_obj_align(btnTrip, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); + lv_obj_set_style_local_bg_color(btnTrip, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x080808)); + txtTrip = lv_label_create(btnTrip, nullptr); + lv_obj_set_style_local_text_color(btnTrip, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x888888)); + lv_label_set_text(txtTrip, "Reset"); + + if(stepsCount >= motionController.GetTripSteps()){ + currentTripSteps = stepsCount - motionController.GetTripSteps(); + } else { + currentTripSteps = stepsCount + motionController.GetTripSteps(); + } + + tripText = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(tripText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); + lv_label_set_text_fmt(tripText, "Trip: %li", currentTripSteps); + lv_obj_align(tripText, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 50); taskRefresh = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this); } @@ -80,13 +86,17 @@ Steps::~Steps() { void Steps::Refresh() { stepsCount = motionController.NbSteps(); - currentLapSteps = stepsCount - motionController.GetPrevTotalSteps(); + if(stepsCount >= motionController.GetTripSteps()){ + currentTripSteps = stepsCount - motionController.GetTripSteps(); + } else { + currentTripSteps = stepsCount + motionController.GetTripSteps(); + } - lv_label_set_text_fmt(lSteps, "%li", currentLapSteps); + lv_label_set_text_fmt(lSteps, "%li", stepsCount); lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -40); - lv_label_set_text_fmt(totalStepsText, "Total\n%li", stepsCount); - lv_obj_align(totalStepsText, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); + lv_label_set_text_fmt(tripText, "Trip: %li", currentTripSteps); + lv_obj_align(tripText, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 50); lv_arc_set_value(stepsArc, int16_t(500 * stepsCount / settingsController.GetStepsGoal())); } @@ -96,7 +106,7 @@ void Steps::lapBtnEventHandler(lv_event_t event) { return; } stepsCount = motionController.NbSteps(); - motionController.SetPrevTotalSteps(stepsCount); + motionController.SetTripSteps(stepsCount); Refresh(); } diff --git a/src/displayapp/screens/Steps.h b/src/displayapp/screens/Steps.h index 08f8ea2..3510c50 100644 --- a/src/displayapp/screens/Steps.h +++ b/src/displayapp/screens/Steps.h @@ -26,14 +26,14 @@ namespace Pinetime { Controllers::MotionController& motionController; Controllers::Settings& settingsController; - uint32_t currentLapSteps = 0; + uint32_t currentTripSteps = 0; lv_obj_t* lSteps; lv_obj_t* lStepsIcon; lv_obj_t* stepsArc; - lv_obj_t* btnLap; - lv_obj_t* txtLap; - lv_obj_t* totalStepsText; + lv_obj_t* btnTrip; + lv_obj_t* txtTrip; + lv_obj_t* tripText; uint32_t stepsCount; -- cgit v0.10.2 From f7d1b3f36847bcbd0699feeb8515bb6517690066 Mon Sep 17 00:00:00 2001 From: Stephanie Date: Thu, 21 Oct 2021 23:37:35 -0400 Subject: Moved trip meter update to MotionController and changed trip meter logic diff --git a/src/components/motion/MotionController.cpp b/src/components/motion/MotionController.cpp index cae4910..59114f4 100644 --- a/src/components/motion/MotionController.cpp +++ b/src/components/motion/MotionController.cpp @@ -14,7 +14,11 @@ void MotionController::Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps) this->x = x; this->y = y; this->z = z; + deltaSteps = nbSteps - this->nbSteps; this->nbSteps = nbSteps; + if(deltaSteps > 0){ + currentTripSteps += deltaSteps; + } } bool MotionController::ShouldWakeUp(bool isSleeping) { diff --git a/src/components/motion/MotionController.h b/src/components/motion/MotionController.h index aea82f7..17bdc52 100644 --- a/src/components/motion/MotionController.h +++ b/src/components/motion/MotionController.h @@ -28,11 +28,12 @@ namespace Pinetime { uint32_t NbSteps() const { return nbSteps; } - void SetTripSteps(uint32_t steps) { - stepsAtLastTrip = steps; + + void ResetTrip() { + currentTripSteps = 0; } uint32_t GetTripSteps() const { - return stepsAtLastTrip; + return currentTripSteps; } bool ShouldWakeUp(bool isSleeping); @@ -50,7 +51,8 @@ namespace Pinetime { private: uint32_t nbSteps; - uint32_t stepsAtLastTrip = 0; + int32_t deltaSteps = 0; + uint32_t currentTripSteps = 0; int16_t x; int16_t y; int16_t z; diff --git a/src/displayapp/screens/Steps.cpp b/src/displayapp/screens/Steps.cpp index 5d8c386..cb1297b 100644 --- a/src/displayapp/screens/Steps.cpp +++ b/src/displayapp/screens/Steps.cpp @@ -65,11 +65,7 @@ Steps::Steps(Pinetime::Applications::DisplayApp* app, lv_obj_set_style_local_text_color(btnTrip, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x888888)); lv_label_set_text(txtTrip, "Reset"); - if(stepsCount >= motionController.GetTripSteps()){ - currentTripSteps = stepsCount - motionController.GetTripSteps(); - } else { - currentTripSteps = stepsCount + motionController.GetTripSteps(); - } + currentTripSteps = motionController.GetTripSteps(); tripText = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(tripText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); @@ -86,11 +82,7 @@ Steps::~Steps() { void Steps::Refresh() { stepsCount = motionController.NbSteps(); - if(stepsCount >= motionController.GetTripSteps()){ - currentTripSteps = stepsCount - motionController.GetTripSteps(); - } else { - currentTripSteps = stepsCount + motionController.GetTripSteps(); - } + currentTripSteps = motionController.GetTripSteps(); lv_label_set_text_fmt(lSteps, "%li", stepsCount); lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -40); @@ -106,7 +98,7 @@ void Steps::lapBtnEventHandler(lv_event_t event) { return; } stepsCount = motionController.NbSteps(); - motionController.SetTripSteps(stepsCount); + motionController.ResetTrip(); Refresh(); } -- cgit v0.10.2 From 7eff1dbcc631c41e05b372e993383be3554f348c Mon Sep 17 00:00:00 2001 From: Stephanie Date: Fri, 22 Oct 2021 19:21:51 -0400 Subject: Changed text to left pad diff --git a/src/displayapp/screens/Steps.cpp b/src/displayapp/screens/Steps.cpp index cb1297b..ea11ca6 100644 --- a/src/displayapp/screens/Steps.cpp +++ b/src/displayapp/screens/Steps.cpp @@ -44,9 +44,9 @@ Steps::Steps(Pinetime::Applications::DisplayApp* app, lv_obj_t* lstepsGoal = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(lstepsGoal, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_CYAN); - lv_label_set_text_fmt(lstepsGoal, "Goal: %lu", settingsController.GetStepsGoal()); + lv_label_set_text_fmt(lstepsGoal, "Goal: %5lu", settingsController.GetStepsGoal()); lv_label_set_align(lstepsGoal, LV_LABEL_ALIGN_CENTER); - lv_obj_align(lstepsGoal, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 30); + lv_obj_align(lstepsGoal, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 40); lv_obj_t* backgroundLabel = lv_label_create(lv_scr_act(), nullptr); lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP); @@ -69,8 +69,8 @@ Steps::Steps(Pinetime::Applications::DisplayApp* app, tripText = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_style_local_text_color(tripText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); - lv_label_set_text_fmt(tripText, "Trip: %li", currentTripSteps); - lv_obj_align(tripText, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 50); + lv_label_set_text_fmt(tripText, "Trip: %5li", currentTripSteps); + lv_obj_align(tripText, lstepsGoal, LV_ALIGN_IN_LEFT_MID, 0, 20); taskRefresh = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this); } @@ -87,9 +87,11 @@ void Steps::Refresh() { lv_label_set_text_fmt(lSteps, "%li", stepsCount); lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -40); - lv_label_set_text_fmt(tripText, "Trip: %li", currentTripSteps); - lv_obj_align(tripText, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 50); - + if (currentTripSteps < 100000){ + lv_label_set_text_fmt(tripText, "Trip: %5li", currentTripSteps); + } else { + lv_label_set_text_fmt(tripText, "Trip: 99999+"); + } lv_arc_set_value(stepsArc, int16_t(500 * stepsCount / settingsController.GetStepsGoal())); } -- cgit v0.10.2 From a65f173e3c63730c7db3c29bf44e538773971dc7 Mon Sep 17 00:00:00 2001 From: Stephanie Date: Sat, 23 Oct 2021 13:41:10 -0400 Subject: Renamed confusing variables and general cleanup diff --git a/src/components/motion/MotionController.cpp b/src/components/motion/MotionController.cpp index 59114f4..f2b36ad 100644 --- a/src/components/motion/MotionController.cpp +++ b/src/components/motion/MotionController.cpp @@ -14,7 +14,7 @@ void MotionController::Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps) this->x = x; this->y = y; this->z = z; - deltaSteps = nbSteps - this->nbSteps; + int32_t deltaSteps = nbSteps - this->nbSteps; this->nbSteps = nbSteps; if(deltaSteps > 0){ currentTripSteps += deltaSteps; diff --git a/src/components/motion/MotionController.h b/src/components/motion/MotionController.h index 17bdc52..3de03d1 100644 --- a/src/components/motion/MotionController.h +++ b/src/components/motion/MotionController.h @@ -51,7 +51,6 @@ namespace Pinetime { private: uint32_t nbSteps; - int32_t deltaSteps = 0; uint32_t currentTripSteps = 0; int16_t x; int16_t y; diff --git a/src/displayapp/screens/Steps.cpp b/src/displayapp/screens/Steps.cpp index ea11ca6..3ab28e4 100644 --- a/src/displayapp/screens/Steps.cpp +++ b/src/displayapp/screens/Steps.cpp @@ -54,23 +54,21 @@ Steps::Steps(Pinetime::Applications::DisplayApp* app, lv_obj_set_pos(backgroundLabel, 0, 0); lv_label_set_text_static(backgroundLabel, ""); - btnTrip = lv_btn_create(lv_scr_act(), nullptr); - btnTrip->user_data = this; - lv_obj_set_event_cb(btnTrip, lap_event_handler); - lv_obj_set_height(btnTrip, 50); - lv_obj_set_width(btnTrip, 115); - lv_obj_align(btnTrip, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); - lv_obj_set_style_local_bg_color(btnTrip, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x080808)); - txtTrip = lv_label_create(btnTrip, nullptr); - lv_obj_set_style_local_text_color(btnTrip, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x888888)); - lv_label_set_text(txtTrip, "Reset"); + resetBtn = lv_btn_create(lv_scr_act(), nullptr); + resetBtn->user_data = this; + lv_obj_set_event_cb(resetBtn, lap_event_handler); + lv_obj_set_height(resetBtn, 50); + lv_obj_set_width(resetBtn, 115); + lv_obj_align(resetBtn, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, 0); + resetButtonLabel = lv_label_create(resetBtn, nullptr); + lv_label_set_text(resetButtonLabel, "Reset"); currentTripSteps = motionController.GetTripSteps(); - tripText = lv_label_create(lv_scr_act(), nullptr); - lv_obj_set_style_local_text_color(tripText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); - lv_label_set_text_fmt(tripText, "Trip: %5li", currentTripSteps); - lv_obj_align(tripText, lstepsGoal, LV_ALIGN_IN_LEFT_MID, 0, 20); + tripLabel = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(tripLabel, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW); + lv_label_set_text_fmt(tripLabel, "Trip: %5li", currentTripSteps); + lv_obj_align(tripLabel, lstepsGoal, LV_ALIGN_IN_LEFT_MID, 0, 20); taskRefresh = lv_task_create(RefreshTaskCallback, 100, LV_TASK_PRIO_MID, this); } @@ -88,9 +86,9 @@ void Steps::Refresh() { lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -40); if (currentTripSteps < 100000){ - lv_label_set_text_fmt(tripText, "Trip: %5li", currentTripSteps); + lv_label_set_text_fmt(tripLabel, "Trip: %5li", currentTripSteps); } else { - lv_label_set_text_fmt(tripText, "Trip: 99999+"); + lv_label_set_text_fmt(tripLabel, "Trip: 99999+"); } lv_arc_set_value(stepsArc, int16_t(500 * stepsCount / settingsController.GetStepsGoal())); } diff --git a/src/displayapp/screens/Steps.h b/src/displayapp/screens/Steps.h index 3510c50..f109e0f 100644 --- a/src/displayapp/screens/Steps.h +++ b/src/displayapp/screens/Steps.h @@ -31,9 +31,9 @@ namespace Pinetime { lv_obj_t* lSteps; lv_obj_t* lStepsIcon; lv_obj_t* stepsArc; - lv_obj_t* btnTrip; - lv_obj_t* txtTrip; - lv_obj_t* tripText; + lv_obj_t* resetBtn; + lv_obj_t* resetButtonLabel; + lv_obj_t* tripLabel; uint32_t stepsCount; -- cgit v0.10.2 From e0013e730448f4dc142e3610f970f22c807ac41e Mon Sep 17 00:00:00 2001 From: Stephanie Date: Sun, 31 Oct 2021 11:53:13 -0400 Subject: Ran clang-format diff --git a/src/components/motion/MotionController.cpp b/src/components/motion/MotionController.cpp index f2b36ad..97a8feb 100644 --- a/src/components/motion/MotionController.cpp +++ b/src/components/motion/MotionController.cpp @@ -16,7 +16,7 @@ void MotionController::Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps) this->z = z; int32_t deltaSteps = nbSteps - this->nbSteps; this->nbSteps = nbSteps; - if(deltaSteps > 0){ + if (deltaSteps > 0) { currentTripSteps += deltaSteps; } } @@ -47,10 +47,16 @@ void MotionController::IsSensorOk(bool isOk) { isSensorOk = isOk; } void MotionController::Init(Pinetime::Drivers::Bma421::DeviceTypes types) { - switch(types){ - case Drivers::Bma421::DeviceTypes::BMA421: this->deviceType = DeviceTypes::BMA421; break; - case Drivers::Bma421::DeviceTypes::BMA425: this->deviceType = DeviceTypes::BMA425; break; - default: this->deviceType = DeviceTypes::Unknown; break; + switch (types) { + case Drivers::Bma421::DeviceTypes::BMA421: + this->deviceType = DeviceTypes::BMA421; + break; + case Drivers::Bma421::DeviceTypes::BMA425: + this->deviceType = DeviceTypes::BMA425; + break; + default: + this->deviceType = DeviceTypes::Unknown; + break; } } void MotionController::SetService(Pinetime::Controllers::MotionService* service) { diff --git a/src/components/motion/MotionController.h b/src/components/motion/MotionController.h index 3de03d1..3eac717 100644 --- a/src/components/motion/MotionController.h +++ b/src/components/motion/MotionController.h @@ -8,7 +8,7 @@ namespace Pinetime { namespace Controllers { class MotionController { public: - enum class DeviceTypes{ + enum class DeviceTypes { Unknown, BMA421, BMA425, @@ -28,7 +28,7 @@ namespace Pinetime { uint32_t NbSteps() const { return nbSteps; } - + void ResetTrip() { currentTripSteps = 0; } diff --git a/src/displayapp/screens/Steps.cpp b/src/displayapp/screens/Steps.cpp index 3ab28e4..3e7f820 100644 --- a/src/displayapp/screens/Steps.cpp +++ b/src/displayapp/screens/Steps.cpp @@ -85,7 +85,7 @@ void Steps::Refresh() { lv_label_set_text_fmt(lSteps, "%li", stepsCount); lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -40); - if (currentTripSteps < 100000){ + if (currentTripSteps < 100000) { lv_label_set_text_fmt(tripLabel, "Trip: %5li", currentTripSteps); } else { lv_label_set_text_fmt(tripLabel, "Trip: 99999+"); @@ -101,4 +101,3 @@ void Steps::lapBtnEventHandler(lv_event_t event) { motionController.ResetTrip(); Refresh(); } - -- cgit v0.10.2