Initial draft

This commit is contained in:
Will Bradley 2024-12-06 18:53:52 -08:00
parent 2105a7b63d
commit 0cae5609ae
Signed by: will
GPG Key ID: 7753374769D155F8
3 changed files with 141 additions and 89 deletions

50
shell.nix Normal file
View File

@ -0,0 +1,50 @@
{ pkgs ? import <nixpkgs> {} }:
with pkgs; let
py4McuBoot = python3.withPackages (ps: with ps; [
cbor
intelhex
click
cryptography
pillow
]);
lv_img_convWrapper = pkgs.writeScriptBin "lv_img_conv" ''
npm install lv_img_conv
nodejs node_modules/lv_img_conv/lv_img_conv.js
'';
buildInfinitime = pkgs.writeScriptBin "build-infinitime" ''
mkdir -p build/
cmake -DARM_NONE_EABI_TOOLCHAIN_PATH=$ARM_NONE_EABI_TOOLCHAIN_PATH \
-DNRF5_SDK_PATH=$NRF5_SDK_PATH \
-DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE \
-DBUILD_DFU=$BUILD_DFU \
-DBUILD_RESOURCES=$BUILD_RESOURCES \
-DTARGET_DEVICE=$TARGET_DEVICE \
-S . -B build
cmake --build build -j6
'';
in mkShell {
packages = [
gcc-arm-embedded-10
nrf5-sdk
cmake
nodePackages.lv_font_conv
lv_img_convWrapper
# lv_img_conv
nodejs
py4McuBoot
clang-tools
SDL2
libpng
adafruit-nrfutil
buildInfinitime
# watchmate # wish this worked -- use flatpak run io.gitlab.azymohliad.WatchMate
];
ARM_NONE_EABI_TOOLCHAIN_PATH="${gcc-arm-embedded-10}";
NRF5_SDK_PATH="${nrf5-sdk}/share/nRF5_SDK";
CMAKE_BUILD_TYPE="Release";
BUILD_DFU=1;
BUILD_RESOURCES=1;
TARGET_DEVICE="PINETIME";
}

View File

@ -27,40 +27,49 @@ WatchFaceTerminal::WatchFaceTerminal(Controllers::DateTime& dateTimeController,
settingsController {settingsController}, settingsController {settingsController},
heartRateController {heartRateController}, heartRateController {heartRateController},
motionController {motionController} { motionController {motionController} {
batteryValue = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(batteryValue, true);
lv_obj_align(batteryValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -20);
connectState = lv_label_create(lv_scr_act(), nullptr); /*Create an array for the points of the line*/
lv_label_set_recolor(connectState, true); progress_points[0] = {0, 0};
lv_obj_align(connectState, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 40); progress_points[1] = {0, 0};
/*Create style*/
static lv_style_t style_progress;
lv_style_init(&style_progress);
lv_style_set_line_width(&style_progress, LV_STATE_DEFAULT, LV_HOR_RES);
lv_style_set_line_color(&style_progress, LV_STATE_DEFAULT, LV_COLOR_BLUE); // todo: #11cc55
// lv_style_set_line_rounded(&style_progress, LV_STATE_DEFAULT, true);
/*Create a line and apply the new style*/
progress_line = lv_line_create(lv_scr_act(), NULL);
lv_line_set_points(progress_line, progress_points, 2); /*Set the points*/
lv_obj_add_style(progress_line, LV_LINE_PART_MAIN, &style_progress); /*Set the points*/
lv_obj_align(progress_line, NULL, LV_ALIGN_IN_TOP_MID, 0, 0);
/* Current calendar */
label_now = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(label_now, true);
lv_obj_align(label_now, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 5, 10);
lv_label_set_long_mode(label_now, LV_LABEL_LONG_BREAK);
lv_obj_set_width(label_now, LV_HOR_RES-5);
// lv_obj_set_height(label_now, 40);
// batteryValue = lv_label_create(lv_scr_act(), nullptr);
// lv_label_set_recolor(batteryValue, true);
// lv_obj_align(batteryValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -20);
// connectState = lv_label_create(lv_scr_act(), nullptr);
// lv_label_set_recolor(connectState, true);
// lv_obj_align(connectState, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 40);
notificationIcon = lv_label_create(lv_scr_act(), nullptr); notificationIcon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_LEFT_MID, 0, -100); lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_LEFT_MID, 0, -100);
label_date = lv_label_create(lv_scr_act(), nullptr); label_next = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(label_date, true); lv_label_set_recolor(label_next, true);
lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -40); lv_obj_align(label_next, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -40);
lv_label_set_long_mode(label_next, LV_LABEL_LONG_BREAK);
label_prompt_1 = lv_label_create(lv_scr_act(), nullptr); lv_obj_set_width(label_next, LV_HOR_RES-5);
lv_obj_align(label_prompt_1, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -80); // lv_obj_set_height(label_next, 40);
lv_label_set_text_static(label_prompt_1, "user@watch:~ $ now");
label_prompt_2 = lv_label_create(lv_scr_act(), nullptr);
lv_obj_align(label_prompt_2, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);
lv_label_set_text_static(label_prompt_2, "user@watch:~ $");
label_time = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(label_time, true);
lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -60);
heartbeatValue = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(heartbeatValue, true);
lv_obj_align(heartbeatValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 20);
stepValue = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(stepValue, true);
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
Refresh(); Refresh();
@ -72,28 +81,28 @@ WatchFaceTerminal::~WatchFaceTerminal() {
} }
void WatchFaceTerminal::Refresh() { void WatchFaceTerminal::Refresh() {
powerPresent = batteryController.IsPowerPresent(); if (currentDuration == 0) {
batteryPercentRemaining = batteryController.PercentRemaining(); lv_label_set_text_fmt(label_now, "#007fff Now:# %s",calendar[calIndex].name);
if (batteryPercentRemaining.IsUpdated() || powerPresent.IsUpdated()) { if (calIndex+1 < sizeof(calendar)/sizeof(CalendarEntry)) {
lv_label_set_text_fmt(batteryValue, "[BATT]#387b54 %d%%", batteryPercentRemaining.Get()); lv_label_set_text_fmt(label_next, "#ee3377 Next:# %s", calendar[calIndex+1].name);
if (batteryController.IsPowerPresent()) { } else {
lv_label_ins_text(batteryValue, LV_LABEL_POS_LAST, " Charging"); lv_label_set_text_fmt(label_next, "");
} }
} }
bleState = bleController.IsConnected(); progress_points[1] = {0,(lv_coord_t)((double)LV_VER_RES*currentDuration/calendar[calIndex].duration)};
bleRadioEnabled = bleController.IsRadioEnabled(); lv_line_set_points(progress_line, progress_points, 2); /*Set the points*/
if (bleState.IsUpdated() || bleRadioEnabled.IsUpdated()) { // lv_label_set_text_fmt(batteryValue, "cI %d sO %d",calIndex, sizeof(calendar)/sizeof(CalendarEntry));
if (!bleRadioEnabled.Get()) {
lv_label_set_text_static(connectState, "[STAT]#0082fc Disabled#"); currentDuration++;
} else { if (currentDuration>calendar[calIndex].duration) {
if (bleState.Get()) { currentDuration = 0;
lv_label_set_text_static(connectState, "[STAT]#0082fc Connected#"); calIndex++;
} else { if (calIndex > sizeof(calendar)/sizeof(CalendarEntry)-1) {
lv_label_set_text_static(connectState, "[STAT]#0082fc Disconnected#"); calIndex = 0;
}
} }
} }
notificationState = notificationManager.AreNewNotificationsAvailable(); notificationState = notificationManager.AreNewNotificationsAvailable();
if (notificationState.IsUpdated()) { if (notificationState.IsUpdated()) {
@ -106,46 +115,8 @@ void WatchFaceTerminal::Refresh() {
currentDateTime = std::chrono::time_point_cast<std::chrono::seconds>(dateTimeController.CurrentDateTime()); currentDateTime = std::chrono::time_point_cast<std::chrono::seconds>(dateTimeController.CurrentDateTime());
if (currentDateTime.IsUpdated()) { if (currentDateTime.IsUpdated()) {
uint8_t hour = dateTimeController.Hours(); // uint8_t hour = dateTimeController.Hours();
uint8_t minute = dateTimeController.Minutes(); // uint8_t minute = dateTimeController.Minutes();
uint8_t second = dateTimeController.Seconds(); // uint8_t second = dateTimeController.Seconds();
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
char ampmChar[3] = "AM";
if (hour == 0) {
hour = 12;
} else if (hour == 12) {
ampmChar[0] = 'P';
} else if (hour > 12) {
hour = hour - 12;
ampmChar[0] = 'P';
}
lv_label_set_text_fmt(label_time, "[TIME]#11cc55 %02d:%02d:%02d %s#", hour, minute, second, ampmChar);
} else {
lv_label_set_text_fmt(label_time, "[TIME]#11cc55 %02d:%02d:%02d", hour, minute, second);
}
currentDate = std::chrono::time_point_cast<std::chrono::days>(currentDateTime.Get());
if (currentDate.IsUpdated()) {
uint16_t year = dateTimeController.Year();
Controllers::DateTime::Months month = dateTimeController.Month();
uint8_t day = dateTimeController.Day();
lv_label_set_text_fmt(label_date, "[DATE]#007fff %04d-%02d-%02d#", short(year), char(month), char(day));
}
}
heartbeat = heartRateController.HeartRate();
heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped;
if (heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) {
if (heartbeatRunning.Get()) {
lv_label_set_text_fmt(heartbeatValue, "[L_HR]#ee3311 %d bpm#", heartbeat.Get());
} else {
lv_label_set_text_static(heartbeatValue, "[L_HR]#ee3311 ---#");
}
}
stepCount = motionController.NbSteps();
if (stepCount.IsUpdated()) {
lv_label_set_text_fmt(stepValue, "[STEP]#ee3377 %lu steps#", stepCount.Get());
} }
} }

View File

@ -19,6 +19,11 @@ namespace Pinetime {
class MotionController; class MotionController;
} }
struct CalendarEntry {
char* name;
uint32_t duration;
};
namespace Applications { namespace Applications {
namespace Screens { namespace Screens {
@ -47,8 +52,34 @@ namespace Pinetime {
Utility::DirtyValue<bool> notificationState {}; Utility::DirtyValue<bool> notificationState {};
Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::days>> currentDate; Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::days>> currentDate;
lv_obj_t* label_time; CalendarEntry calendar[18] = {
lv_obj_t* label_date; {"Enjoy the last vestiges of sunlight", 15*2},
{"Present FuckTime", 30*2},
{"Enjoy the crisp night air", 10*2},
{"Party @ David's", 60*2},
{"Savor the moment", 10*2},
{"Sleep", 60*2}, // 8*
{"Wake up", 10*2},
{"Morning Work", 60*2}, // 4*
{"Eat Lunch", 60*2},
{"Afternoon Work", 60*2}, // 4*
{"Get groceries", 20*2},
{"Prepare dinner", 30*2},
{"Eat", 60*2},
{"Sleep", 60*2}, // 8*
{"Rave", 30*2},
{"Repeat", 10*2},
{"Wake up", 10*2},
{"Work", 300*2},
};
uint32_t calIndex = 0;
uint32_t currentDuration = 0;
lv_obj_t * progress_line;
lv_point_t progress_points[2];
lv_obj_t* label_now;
lv_obj_t* label_next;
lv_obj_t* label_prompt_1; lv_obj_t* label_prompt_1;
lv_obj_t* label_prompt_2; lv_obj_t* label_prompt_2;
lv_obj_t* batteryValue; lv_obj_t* batteryValue;