Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ list(APPEND SOURCE_FILES
displayapp/screens/settings/SettingPineTimeStyle.cpp
displayapp/screens/settings/SettingSetDate.cpp
displayapp/screens/settings/SettingSetTime.cpp
displayapp/screens/settings/SettingStopWatch.cpp

## Watch faces
displayapp/icons/bg_clock.c
Expand Down
12 changes: 12 additions & 0 deletions src/components/settings/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace Pinetime {
enum class Colors : uint8_t {
White, Silver, Gray, Black, Red, Maroon, Yellow, Olive, Lime, Green, Cyan, Teal, Blue, Navy, Magenta, Purple, Orange
};
enum class StopWatchSleepMode : uint8_t { Enable, Disable };
struct PineTimeStyle {
Colors ColorTime = Colors::Teal;
Colors ColorBar = Colors::Teal;
Expand Down Expand Up @@ -160,6 +161,15 @@ namespace Pinetime {

uint32_t GetStepsGoal() const { return settings.stepsGoal; };

void SetStopWatchSleepMode(StopWatchSleepMode mode) {
if ( mode != settings.stopWatchSleepMode ) {
settingsChanged = true;
}
settings.stopWatchSleepMode = mode;
};

StopWatchSleepMode GetStopWatchSleepMode() const { return settings.stopWatchSleepMode; };

private:
Pinetime::Controllers::FS& fs;

Expand All @@ -179,6 +189,8 @@ namespace Pinetime {
std::bitset<3> wakeUpMode {0};

Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium;

StopWatchSleepMode stopWatchSleepMode = StopWatchSleepMode::Disable;
};

SettingsData settings;
Expand Down
1 change: 1 addition & 0 deletions src/displayapp/Apps.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace Pinetime {
SettingPineTimeStyle,
SettingSetDate,
SettingSetTime,
SettingStopWatch,
Error,
};
}
Expand Down
7 changes: 6 additions & 1 deletion src/displayapp/DisplayApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "displayapp/screens/settings/SettingPineTimeStyle.h"
#include "displayapp/screens/settings/SettingSetDate.h"
#include "displayapp/screens/settings/SettingSetTime.h"
#include "displayapp/screens/settings/SettingStopWatch.h"

#include "libs/lv_conf.h"

Expand Down Expand Up @@ -378,6 +379,10 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
currentScreen = std::make_unique<Screens::SettingSteps>(this, settingsController);
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
case Apps::SettingStopWatch:
currentScreen = std::make_unique<Screens::SettingStopWatch>(this, settingsController);
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
case Apps::SettingSetDate:
currentScreen = std::make_unique<Screens::SettingSetDate>(this, dateTimeController);
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
Expand All @@ -404,7 +409,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None);
break;
case Apps::StopWatch:
currentScreen = std::make_unique<Screens::StopWatch>(this, *systemTask);
currentScreen = std::make_unique<Screens::StopWatch>(this, *systemTask, settingsController);
break;
case Apps::Twos:
currentScreen = std::make_unique<Screens::Twos>(this);
Expand Down
11 changes: 8 additions & 3 deletions src/displayapp/screens/StopWatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
#include "projdefs.h"
#include "FreeRTOSConfig.h"
#include "task.h"
#include "components/settings/Settings.h"

#include <tuple>

using namespace Pinetime::Applications::Screens;
using namespace Pinetime::Controllers;

// Anonymous namespace for local functions
namespace {
Expand Down Expand Up @@ -45,9 +47,10 @@ static void stop_lap_event_handler(lv_obj_t* obj, lv_event_t event) {
stopWatch->stopLapBtnEventHandler(event);
}

StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask)
StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask, Controllers::Settings& settingsController)
: Screen(app),
systemTask {systemTask},
settingsController {settingsController},
currentState {States::Init},
startTime {},
oldTimeElapsed {},
Expand Down Expand Up @@ -136,7 +139,9 @@ void StopWatch::start() {
lv_label_set_text(txtStopLap, Symbols::lapsFlag);
startTime = xTaskGetTickCount();
currentState = States::Running;
systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
if (settingsController.GetStopWatchSleepMode() == Settings::StopWatchSleepMode::Disable) {
systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
}
}

void StopWatch::pause() {
Expand Down Expand Up @@ -195,7 +200,7 @@ void StopWatch::stopLapBtnEventHandler(lv_event_t event) {
}

bool StopWatch::OnButtonPushed() {
if (currentState == States::Running) {
if (currentState == States::Running && settingsController.GetStopWatchSleepMode() == Settings::StopWatchSleepMode::Disable) {
pause();
return true;
}
Expand Down
148 changes: 78 additions & 70 deletions src/displayapp/screens/StopWatch.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,82 +10,90 @@
#include <array>
#include "systemtask/SystemTask.h"

namespace Pinetime::Applications::Screens {
namespace Pinetime {

enum class States { Init, Running, Halted };
namespace Controllers {
class Settings;
}

struct TimeSeparated_t {
int mins;
int secs;
int hundredths;
};
namespace Applications::Screens {

// A simple buffer to hold the latest two laps
template <int N> struct LapTextBuffer_t {
LapTextBuffer_t() : buffer {}, currentSize {}, capacity {N}, head {-1} {
}
enum class States { Init, Running, Halted };

void addLaps(const TimeSeparated_t& timeVal) {
head++;
head %= capacity;
buffer[head] = timeVal;
struct TimeSeparated_t {
int mins;
int secs;
int hundredths;
};

if (currentSize < capacity) {
currentSize++;
// A simple buffer to hold the latest two laps
template <int N> struct LapTextBuffer_t {
LapTextBuffer_t() : buffer {}, currentSize {}, capacity {N}, head {-1} {
}
}

void clearBuffer() {
buffer = {};
currentSize = 0;
head = -1;
}

TimeSeparated_t* operator[](std::size_t idx) {
// Sanity check for out-of-bounds
if (idx >= 0 && idx < capacity) {
if (idx < currentSize) {
// This transformation is to ensure that head is always pointing to index 0.
const auto transformed_idx = (head - idx) % capacity;
return (&buffer[transformed_idx]);

void addLaps(const TimeSeparated_t& timeVal) {
head++;
head %= capacity;
buffer[head] = timeVal;

if (currentSize < capacity) {
currentSize++;
}
}

void clearBuffer() {
buffer = {};
currentSize = 0;
head = -1;
}

TimeSeparated_t* operator[](std::size_t idx) {
// Sanity check for out-of-bounds
if (idx >= 0 && idx < capacity) {
if (idx < currentSize) {
// This transformation is to ensure that head is always pointing to index 0.
const auto transformed_idx = (head - idx) % capacity;
return (&buffer[transformed_idx]);
}
}
return nullptr;
}
return nullptr;
}

private:
std::array<TimeSeparated_t, N> buffer;
uint8_t currentSize;
uint8_t capacity;
int8_t head;
};

class StopWatch : public Screen {
public:
StopWatch(DisplayApp* app, System::SystemTask& systemTask);
~StopWatch() override;
void Refresh() override;

void playPauseBtnEventHandler(lv_event_t event);
void stopLapBtnEventHandler(lv_event_t event);
bool OnButtonPushed() override;

void reset();
void start();
void pause();

private:
Pinetime::System::SystemTask& systemTask;
TickType_t timeElapsed;
States currentState;
TickType_t startTime;
TickType_t oldTimeElapsed;
TimeSeparated_t currentTimeSeparated; // Holds Mins, Secs, millisecs
LapTextBuffer_t<2> lapBuffer;
int lapNr = 0;
lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap;
lv_obj_t *lapOneText, *lapTwoText;

lv_task_t* taskRefresh;
};

private:
std::array<TimeSeparated_t, N> buffer;
uint8_t currentSize;
uint8_t capacity;
int8_t head;
};

class StopWatch : public Screen {
public:
StopWatch(DisplayApp* app, System::SystemTask& systemTask, Controllers::Settings& settingsController);
~StopWatch() override;
void Refresh() override;

void playPauseBtnEventHandler(lv_event_t event);
void stopLapBtnEventHandler(lv_event_t event);
bool OnButtonPushed() override;

void reset();
void start();
void pause();

private:
Pinetime::System::SystemTask& systemTask;
Controllers::Settings& settingsController;
TickType_t timeElapsed;
States currentState;
TickType_t startTime;
TickType_t oldTimeElapsed;
TimeSeparated_t currentTimeSeparated; // Holds Mins, Secs, millisecs
LapTextBuffer_t<2> lapBuffer;
int lapNr = 0;
lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap;
lv_obj_t *lapOneText, *lapTwoText;

lv_task_t* taskRefresh;
};
}
}
96 changes: 96 additions & 0 deletions src/displayapp/screens/settings/SettingStopWatch.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#include "SettingStopWatch.h"
#include <lvgl/lvgl.h>
#include "displayapp/DisplayApp.h"
#include "displayapp/screens/Screen.h"
#include "displayapp/screens/Symbols.h"

using namespace Pinetime::Applications::Screens;

namespace {
static void event_handler(lv_obj_t* obj, lv_event_t event) {
SettingStopWatch* screen = static_cast<SettingStopWatch*>(obj->user_data);
screen->UpdateSelected(obj, event);
}
}

SettingStopWatch::SettingStopWatch(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController)
: Screen(app), settingsController {settingsController} {

lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr);

lv_obj_set_style_local_bg_opa(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
lv_obj_set_style_local_pad_all(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 10);
lv_obj_set_style_local_pad_inner(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5);
lv_obj_set_style_local_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);

lv_obj_set_pos(container1, 10, 140);
lv_obj_set_width(container1, LV_HOR_RES - 20);
lv_obj_set_height(container1, LV_VER_RES - 50);
lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT);

lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_static(title,
"Stopwatch\n"
"sleep mode");
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(), nullptr);
lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE);
lv_label_set_text_static(icon, Symbols::clock);
lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER);
lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0);

lv_obj_t* description = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(description, true);
lv_label_set_text_static(description,
"#444444 Sleep screen while#\n"
"#444444 the stopwatch#\n"
"#444444 is running.#");
lv_label_set_align(description, LV_LABEL_ALIGN_CENTER);
lv_obj_align(description, lv_scr_act(), LV_ALIGN_CENTER, 0, -20);

optionsTotal = 0;
cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr);
lv_checkbox_set_text_static(cbOption[optionsTotal], " Disable");
cbOption[optionsTotal]->user_data = this;
lv_obj_set_event_cb(cbOption[optionsTotal], event_handler);
if (settingsController.GetStopWatchSleepMode() == Controllers::Settings::StopWatchSleepMode::Disable) {
lv_checkbox_set_checked(cbOption[optionsTotal], true);
}

optionsTotal++;
cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr);
lv_checkbox_set_text_static(cbOption[optionsTotal], " Enable");
cbOption[optionsTotal]->user_data = this;
lv_obj_set_event_cb(cbOption[optionsTotal], event_handler);
if (settingsController.GetStopWatchSleepMode() == Controllers::Settings::StopWatchSleepMode::Enable) {
lv_checkbox_set_checked(cbOption[optionsTotal], true);
}
optionsTotal++;
}

SettingStopWatch::~SettingStopWatch() {
lv_obj_clean(lv_scr_act());
settingsController.SaveSettings();
}

void SettingStopWatch::UpdateSelected(lv_obj_t* object, lv_event_t event) {
if (event == LV_EVENT_VALUE_CHANGED) {
for (int i = 0; i < optionsTotal; i++) {
if (object == cbOption[i]) {
lv_checkbox_set_checked(cbOption[i], true);

if (i == 0) {
settingsController.SetStopWatchSleepMode(Controllers::Settings::StopWatchSleepMode::Disable);
};
if (i == 1) {
settingsController.SetStopWatchSleepMode(Controllers::Settings::StopWatchSleepMode::Enable);
};

} else {
lv_checkbox_set_checked(cbOption[i], false);
}
}
}
}
Loading