WIP fuzzy
This commit is contained in:
parent
9e406c70f9
commit
4b854a5d09
54
shell.nix
Normal file
54
shell.nix
Normal file
|
@ -0,0 +1,54 @@
|
|||
{ 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 build
|
||||
cd 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 \
|
||||
-DENABLE_WATCHFACES="WatchFace::Analog,WatchFace::Digital,WatchFace::Fuzzy" \
|
||||
..
|
||||
|
||||
cd ..
|
||||
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";
|
||||
}
|
|
@ -426,6 +426,7 @@ list(APPEND SOURCE_FILES
|
|||
displayapp/screens/WatchFaceTerminal.cpp
|
||||
displayapp/screens/WatchFacePineTimeStyle.cpp
|
||||
displayapp/screens/WatchFaceCasioStyleG7710.cpp
|
||||
displayapp/screens/WatchFaceFuzzy.cpp
|
||||
|
||||
##
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace Pinetime {
|
|||
namespace Controllers {
|
||||
class Settings {
|
||||
public:
|
||||
enum class ClockType : uint8_t { H24, H12 };
|
||||
enum class ClockType : uint8_t { H24, H12, FUZZY };
|
||||
enum class WeatherFormat : uint8_t { Metric, Imperial };
|
||||
enum class Notification : uint8_t { On, Off, Sleep };
|
||||
enum class ChimesOption : uint8_t { None, Hours, HalfHours };
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "displayapp/screens/Tile.h"
|
||||
#include "displayapp/screens/ApplicationList.h"
|
||||
#include "displayapp/screens/WatchFaceDigital.h"
|
||||
#include "displayapp/screens/WatchFaceFuzzy.h"
|
||||
#include "displayapp/screens/WatchFaceAnalog.h"
|
||||
#include "displayapp/screens/WatchFaceCasioStyleG7710.h"
|
||||
#include "displayapp/screens/WatchFaceInfineat.h"
|
||||
|
|
|
@ -50,6 +50,7 @@ namespace Pinetime {
|
|||
Analog,
|
||||
PineTimeStyle,
|
||||
Terminal,
|
||||
Fuzzy,
|
||||
Infineat,
|
||||
CasioStyleG7710,
|
||||
};
|
||||
|
|
182
src/displayapp/screens/WatchFaceFuzzy.cpp
Normal file
182
src/displayapp/screens/WatchFaceFuzzy.cpp
Normal file
|
@ -0,0 +1,182 @@
|
|||
#include "displayapp/screens/WatchFaceFuzzy.h"
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <cstdio>
|
||||
#include "displayapp/screens/NotificationIcon.h"
|
||||
#include "displayapp/screens/Symbols.h"
|
||||
#include "displayapp/screens/WeatherSymbols.h"
|
||||
#include "components/battery/BatteryController.h"
|
||||
#include "components/ble/BleController.h"
|
||||
#include "components/ble/NotificationManager.h"
|
||||
#include "components/heartrate/HeartRateController.h"
|
||||
#include "components/motion/MotionController.h"
|
||||
#include "components/ble/SimpleWeatherService.h"
|
||||
#include "components/settings/Settings.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
WatchFaceFuzzy::WatchFaceFuzzy(Controllers::DateTime& dateTimeController,
|
||||
const Controllers::Battery& batteryController,
|
||||
const Controllers::Ble& bleController,
|
||||
Controllers::NotificationManager& notificationManager,
|
||||
Controllers::Settings& settingsController,
|
||||
Controllers::HeartRateController& heartRateController,
|
||||
Controllers::MotionController& motionController,
|
||||
Controllers::SimpleWeatherService& weatherService)
|
||||
: currentDateTime {{}},
|
||||
dateTimeController {dateTimeController},
|
||||
notificationManager {notificationManager},
|
||||
settingsController {settingsController},
|
||||
heartRateController {heartRateController},
|
||||
motionController {motionController},
|
||||
weatherService {weatherService},
|
||||
statusIcons(batteryController, bleController) {
|
||||
|
||||
statusIcons.Create();
|
||||
|
||||
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_LIME);
|
||||
lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(false));
|
||||
lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0);
|
||||
|
||||
weatherIcon = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(weatherIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x999999));
|
||||
lv_obj_set_style_local_text_font(weatherIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &fontawesome_weathericons);
|
||||
lv_label_set_text(weatherIcon, "");
|
||||
lv_obj_align(weatherIcon, nullptr, LV_ALIGN_IN_TOP_MID, -20, 50);
|
||||
lv_obj_set_auto_realign(weatherIcon, true);
|
||||
|
||||
temperature = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x999999));
|
||||
lv_label_set_text(temperature, "");
|
||||
lv_obj_align(temperature, nullptr, LV_ALIGN_IN_TOP_MID, 20, 50);
|
||||
|
||||
label_date = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_CENTER, 0, 60);
|
||||
lv_obj_set_style_local_text_color(label_date, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x999999));
|
||||
|
||||
label_time = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_font(label_time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_extrabold_compressed);
|
||||
|
||||
lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0);
|
||||
|
||||
heartbeatIcon = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_label_set_text_static(heartbeatIcon, Symbols::heartBeat);
|
||||
lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B));
|
||||
lv_obj_align(heartbeatIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
|
||||
|
||||
heartbeatValue = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(heartbeatValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B));
|
||||
lv_label_set_text_static(heartbeatValue, "");
|
||||
lv_obj_align(heartbeatValue, heartbeatIcon, LV_ALIGN_OUT_RIGHT_MID, 5, 0);
|
||||
|
||||
stepValue = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FFE7));
|
||||
lv_label_set_text_static(stepValue, "0");
|
||||
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
|
||||
|
||||
stepIcon = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(stepIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FFE7));
|
||||
lv_label_set_text_static(stepIcon, Symbols::shoe);
|
||||
lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||
|
||||
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
WatchFaceFuzzy::~WatchFaceFuzzy() {
|
||||
lv_task_del(taskRefresh);
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
void WatchFaceFuzzy::Refresh() {
|
||||
statusIcons.Update();
|
||||
|
||||
notificationState = notificationManager.AreNewNotificationsAvailable();
|
||||
if (notificationState.IsUpdated()) {
|
||||
lv_label_set_text_static(notificationIcon, NotificationIcon::GetIcon(notificationState.Get()));
|
||||
}
|
||||
|
||||
currentDateTime = std::chrono::time_point_cast<std::chrono::minutes>(dateTimeController.CurrentDateTime());
|
||||
|
||||
if (currentDateTime.IsUpdated()) {
|
||||
uint8_t hour = dateTimeController.Hours();
|
||||
uint8_t minute = dateTimeController.Minutes();
|
||||
|
||||
printTimeWords(hour, minute);
|
||||
}
|
||||
|
||||
heartbeat = heartRateController.HeartRate();
|
||||
heartbeatRunning = heartRateController.State() != Controllers::HeartRateController::States::Stopped;
|
||||
if (heartbeat.IsUpdated() || heartbeatRunning.IsUpdated()) {
|
||||
if (heartbeatRunning.Get()) {
|
||||
lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xCE1B1B));
|
||||
lv_label_set_text_fmt(heartbeatValue, "%d", heartbeat.Get());
|
||||
} else {
|
||||
lv_obj_set_style_local_text_color(heartbeatIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x1B1B1B));
|
||||
lv_label_set_text_static(heartbeatValue, "");
|
||||
}
|
||||
|
||||
lv_obj_realign(heartbeatIcon);
|
||||
lv_obj_realign(heartbeatValue);
|
||||
}
|
||||
|
||||
stepCount = motionController.NbSteps();
|
||||
if (stepCount.IsUpdated()) {
|
||||
lv_label_set_text_fmt(stepValue, "%lu", stepCount.Get());
|
||||
lv_obj_realign(stepValue);
|
||||
lv_obj_realign(stepIcon);
|
||||
}
|
||||
|
||||
currentWeather = weatherService.Current();
|
||||
if (currentWeather.IsUpdated()) {
|
||||
auto optCurrentWeather = currentWeather.Get();
|
||||
if (optCurrentWeather) {
|
||||
int16_t temp = optCurrentWeather->temperature;
|
||||
char tempUnit = 'C';
|
||||
if (settingsController.GetWeatherFormat() == Controllers::Settings::WeatherFormat::Imperial) {
|
||||
temp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(temp);
|
||||
tempUnit = 'F';
|
||||
}
|
||||
temp = temp / 100 + (temp % 100 >= 50 ? 1 : 0);
|
||||
lv_label_set_text_fmt(temperature, "%d°%c", temp, tempUnit);
|
||||
lv_label_set_text(weatherIcon, Symbols::GetSymbol(optCurrentWeather->iconId));
|
||||
} else {
|
||||
lv_label_set_text_static(temperature, "");
|
||||
lv_label_set_text(weatherIcon, "");
|
||||
}
|
||||
lv_obj_realign(temperature);
|
||||
lv_obj_realign(weatherIcon);
|
||||
}
|
||||
}
|
||||
|
||||
char const* WatchFaceFuzzy::mods[] = {"", "five", "ten", "quarter", "twenty", "twenty five", "half"};
|
||||
char const* WatchFaceFuzzy::nums[] = {"twelve", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve"};
|
||||
|
||||
void WatchFaceFuzzy::printTimeWords(int h, int m) {
|
||||
const char* mod;
|
||||
|
||||
if (m <= 30) {
|
||||
mod = mods[m / 5];
|
||||
} else {
|
||||
mod = mods[(60-m) / 5];
|
||||
}
|
||||
h = (h % 12);
|
||||
|
||||
if (m >= 57) {
|
||||
sprintf(timeStr, "#ffffff nearly %s#\n#808080 o' clock#", nums[(h+1) % 12]);
|
||||
}
|
||||
else if (m == 0 || m <= 4) {
|
||||
sprintf(timeStr, "#ffffff %s#\n#808080 o' clock#", nums[h]);
|
||||
}
|
||||
|
||||
else if (m <= 32) {
|
||||
sprintf(timeStr, "#ffffff %s#\n#808080 past# #FFFFFF %s#", mod, nums[h]);
|
||||
}
|
||||
|
||||
else if (m > 32) {
|
||||
sprintf(timeStr, "#ffffff %s#\n#808080 to# #FFFFFF %s#", mod, nums[(h+1) % 12]);
|
||||
}
|
||||
|
||||
lv_label_set_text(label_time, timeStr);
|
||||
}
|
105
src/displayapp/screens/WatchFaceFuzzy.h
Normal file
105
src/displayapp/screens/WatchFaceFuzzy.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
#pragma once
|
||||
|
||||
#include <lvgl/src/lv_core/lv_obj.h>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include "displayapp/screens/Screen.h"
|
||||
#include "components/datetime/DateTimeController.h"
|
||||
#include "components/ble/SimpleWeatherService.h"
|
||||
#include "components/ble/BleController.h"
|
||||
#include "displayapp/widgets/StatusIcons.h"
|
||||
#include "utility/DirtyValue.h"
|
||||
#include "displayapp/apps/Apps.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Controllers {
|
||||
class Settings;
|
||||
class Battery;
|
||||
class Ble;
|
||||
class NotificationManager;
|
||||
class HeartRateController;
|
||||
class MotionController;
|
||||
}
|
||||
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
|
||||
class WatchFaceFuzzy : public Screen {
|
||||
public:
|
||||
WatchFaceFuzzy(Controllers::DateTime& dateTimeController,
|
||||
const Controllers::Battery& batteryController,
|
||||
const Controllers::Ble& bleController,
|
||||
Controllers::NotificationManager& notificationManager,
|
||||
Controllers::Settings& settingsController,
|
||||
Controllers::HeartRateController& heartRateController,
|
||||
Controllers::MotionController& motionController,
|
||||
Controllers::SimpleWeatherService& weather);
|
||||
~WatchFaceFuzzy() override;
|
||||
|
||||
void Refresh() override;
|
||||
|
||||
private:
|
||||
uint8_t displayedHour = -1;
|
||||
uint8_t displayedMinute = -1;
|
||||
|
||||
Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>> currentDateTime {};
|
||||
Utility::DirtyValue<uint32_t> stepCount {};
|
||||
Utility::DirtyValue<uint8_t> heartbeat {};
|
||||
Utility::DirtyValue<bool> heartbeatRunning {};
|
||||
Utility::DirtyValue<bool> notificationState {};
|
||||
Utility::DirtyValue<std::optional<Pinetime::Controllers::SimpleWeatherService::CurrentWeather>> currentWeather {};
|
||||
|
||||
Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::days>> currentDate;
|
||||
|
||||
lv_obj_t* label_time;
|
||||
lv_obj_t* label_time_ampm;
|
||||
lv_obj_t* label_date;
|
||||
lv_obj_t* heartbeatIcon;
|
||||
lv_obj_t* heartbeatValue;
|
||||
lv_obj_t* stepIcon;
|
||||
lv_obj_t* stepValue;
|
||||
lv_obj_t* notificationIcon;
|
||||
lv_obj_t* weatherIcon;
|
||||
lv_obj_t* temperature;
|
||||
|
||||
Controllers::DateTime& dateTimeController;
|
||||
Controllers::NotificationManager& notificationManager;
|
||||
Controllers::Settings& settingsController;
|
||||
Controllers::HeartRateController& heartRateController;
|
||||
Controllers::MotionController& motionController;
|
||||
Controllers::SimpleWeatherService& weatherService;
|
||||
|
||||
lv_task_t* taskRefresh;
|
||||
Widgets::StatusIcons statusIcons;
|
||||
|
||||
|
||||
static char const *nums[];
|
||||
static char const *mods[];
|
||||
char timeStr[64];
|
||||
void printTimeWords(int hour, int minute);
|
||||
};
|
||||
}
|
||||
|
||||
template <>
|
||||
struct WatchFaceTraits<WatchFace::Fuzzy> {
|
||||
static constexpr WatchFace watchFace = WatchFace::Fuzzy;
|
||||
static constexpr const char* name = "Fuzzy face";
|
||||
|
||||
static Screens::Screen* Create(AppControllers& controllers) {
|
||||
return new Screens::WatchFaceFuzzy(controllers.dateTimeController,
|
||||
controllers.batteryController,
|
||||
controllers.bleController,
|
||||
controllers.notificationManager,
|
||||
controllers.settingsController,
|
||||
controllers.heartRateController,
|
||||
controllers.motionController,
|
||||
*controllers.weatherController);
|
||||
};
|
||||
|
||||
static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user