Compare commits
9 Commits
wb/fucktim
...
wb/roman-n
| Author | SHA1 | Date | |
|---|---|---|---|
|
49c801b827
|
|||
|
|
f6a5588544 | ||
|
|
41518cc529 | ||
|
|
c20db14c43 | ||
|
|
9520b2ec9b | ||
|
|
8cf38a3469 | ||
|
|
83cae9b5bc | ||
|
|
bb743689e1 | ||
|
|
4b854a5d09 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -50,3 +50,5 @@ src/arm-none-eabi
|
||||
|
||||
# clangd
|
||||
.cache/
|
||||
|
||||
nRF5_SDK/
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -10,3 +10,6 @@
|
||||
[submodule "src/libs/arduinoFFT"]
|
||||
path = src/libs/arduinoFFT
|
||||
url = https://github.com/kosme/arduinoFFT.git
|
||||
[submodule "src/libs/sunset"]
|
||||
path = src/libs/sunset
|
||||
url = https://github.com/buelowp/sunset.git
|
||||
|
||||
50
shell.nix
Normal file
50
shell.nix
Normal 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";
|
||||
}
|
||||
@@ -174,6 +174,11 @@ set(LITTLEFS_SRC
|
||||
libs/littlefs/lfs.c
|
||||
)
|
||||
|
||||
set(SUNSET_SRC
|
||||
libs/sunset/src/sunset.h
|
||||
libs/sunset/src/sunset.cpp
|
||||
)
|
||||
|
||||
set(LVGL_SRC
|
||||
libs/lv_conf.h
|
||||
libs/lvgl/lvgl.h
|
||||
@@ -366,8 +371,6 @@ list(APPEND SOURCE_FILES
|
||||
displayapp/DisplayApp.cpp
|
||||
displayapp/screens/Screen.cpp
|
||||
displayapp/screens/Tile.cpp
|
||||
displayapp/screens/InfiniPaint.cpp
|
||||
displayapp/screens/Paddle.cpp
|
||||
displayapp/screens/StopWatch.cpp
|
||||
displayapp/screens/BatteryIcon.cpp
|
||||
displayapp/screens/BleIcon.cpp
|
||||
@@ -376,14 +379,9 @@ list(APPEND SOURCE_FILES
|
||||
displayapp/screens/Label.cpp
|
||||
displayapp/screens/FirmwareUpdate.cpp
|
||||
displayapp/screens/Music.cpp
|
||||
displayapp/screens/Navigation.cpp
|
||||
displayapp/screens/Metronome.cpp
|
||||
displayapp/screens/Motion.cpp
|
||||
displayapp/screens/Weather.cpp
|
||||
displayapp/screens/FirmwareValidation.cpp
|
||||
displayapp/screens/ApplicationList.cpp
|
||||
displayapp/screens/Notifications.cpp
|
||||
displayapp/screens/Twos.cpp
|
||||
displayapp/screens/HeartRate.cpp
|
||||
displayapp/screens/FlashLight.cpp
|
||||
displayapp/screens/List.cpp
|
||||
@@ -418,14 +416,12 @@ list(APPEND SOURCE_FILES
|
||||
displayapp/screens/settings/SettingChimes.cpp
|
||||
displayapp/screens/settings/SettingShakeThreshold.cpp
|
||||
displayapp/screens/settings/SettingBluetooth.cpp
|
||||
displayapp/screens/settings/SettingLocation.cpp
|
||||
|
||||
## Watch faces
|
||||
displayapp/screens/WatchFaceAnalog.cpp
|
||||
displayapp/screens/WatchFaceDigital.cpp
|
||||
displayapp/screens/WatchFaceInfineat.cpp
|
||||
displayapp/screens/WatchFaceTerminal.cpp
|
||||
displayapp/screens/WatchFacePineTimeStyle.cpp
|
||||
displayapp/screens/WatchFaceCasioStyleG7710.cpp
|
||||
displayapp/screens/WatchFaceFuzzy.cpp
|
||||
displayapp/screens/WatchFaceSundial.cpp
|
||||
|
||||
##
|
||||
|
||||
@@ -590,9 +586,7 @@ set(INCLUDE_FILES
|
||||
displayapp/TouchEvents.h
|
||||
displayapp/screens/Screen.h
|
||||
displayapp/screens/Tile.h
|
||||
displayapp/screens/InfiniPaint.h
|
||||
displayapp/screens/StopWatch.h
|
||||
displayapp/screens/Paddle.h
|
||||
displayapp/screens/BatteryIcon.h
|
||||
displayapp/screens/BleIcon.h
|
||||
displayapp/screens/NotificationIcon.h
|
||||
@@ -606,11 +600,7 @@ set(INCLUDE_FILES
|
||||
displayapp/Apps.h
|
||||
displayapp/screens/Notifications.h
|
||||
displayapp/screens/HeartRate.h
|
||||
displayapp/screens/Metronome.h
|
||||
displayapp/screens/Motion.h
|
||||
displayapp/screens/Timer.h
|
||||
displayapp/screens/Dice.h
|
||||
displayapp/screens/Alarm.h
|
||||
displayapp/Colors.h
|
||||
displayapp/widgets/Counter.h
|
||||
displayapp/widgets/PageIndicator.h
|
||||
@@ -899,13 +889,25 @@ target_compile_options(littlefs PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:ASM>: ${ASM_FLAGS}>
|
||||
)
|
||||
|
||||
# SUNSET_SRC
|
||||
add_library(sunset STATIC ${SUNSET_SRC})
|
||||
target_include_directories(sunset SYSTEM PUBLIC . ../)
|
||||
target_include_directories(sunset SYSTEM PUBLIC ${INCLUDES_FROM_LIBS})
|
||||
target_compile_options(sunset PRIVATE
|
||||
${COMMON_FLAGS}
|
||||
$<$<CONFIG:DEBUG>: ${DEBUG_FLAGS}>
|
||||
$<$<CONFIG:RELEASE>: ${RELEASE_FLAGS}>
|
||||
$<$<COMPILE_LANGUAGE:CXX>: ${CXX_FLAGS}>
|
||||
$<$<COMPILE_LANGUAGE:ASM>: ${ASM_FLAGS}>
|
||||
)
|
||||
|
||||
# Build autonomous binary (without support for bootloader)
|
||||
set(EXECUTABLE_NAME "pinetime-app")
|
||||
set(EXECUTABLE_FILE_NAME ${EXECUTABLE_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH})
|
||||
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 infinitime_fonts infinitime_apps)
|
||||
target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl littlefs sunset infinitime_fonts infinitime_apps)
|
||||
target_compile_options(${EXECUTABLE_NAME} PUBLIC
|
||||
${COMMON_FLAGS}
|
||||
${WARNING_FLAGS}
|
||||
@@ -939,7 +941,7 @@ set(IMAGE_MCUBOOT_FILE_NAME_BIN ${EXECUTABLE_MCUBOOT_NAME}-image-${pinetime_VERS
|
||||
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 infinitime_fonts infinitime_apps)
|
||||
target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl littlefs sunset infinitime_fonts infinitime_apps)
|
||||
set_target_properties(${EXECUTABLE_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_MCUBOOT_FILE_NAME})
|
||||
target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC
|
||||
${COMMON_FLAGS}
|
||||
@@ -981,7 +983,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 infinitime_fonts infinitime_apps)
|
||||
target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk littlefs sunset infinitime_fonts infinitime_apps)
|
||||
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
|
||||
@@ -1013,7 +1015,7 @@ set(IMAGE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-image-$
|
||||
set(IMAGE_RECOVERY_MCUBOOT_FILE_NAME_HEX ${IMAGE_RECOVERY_MCUBOOT_FILE_NAME}.hex)
|
||||
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 infinitime_fonts infinitime_apps)
|
||||
target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk littlefs sunset infinitime_fonts infinitime_apps)
|
||||
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
|
||||
|
||||
@@ -62,7 +62,8 @@
|
||||
#define configTICK_RATE_HZ 1024
|
||||
#define configMAX_PRIORITIES (3)
|
||||
#define configMINIMAL_STACK_SIZE (120)
|
||||
#define configTOTAL_HEAP_SIZE (1024 * 40)
|
||||
// how much heap can one smartwatch need, michael, 40kb?
|
||||
#define configTOTAL_HEAP_SIZE (1024 * 39)
|
||||
#define configMAX_TASK_NAME_LEN (4)
|
||||
#define configUSE_16_BIT_TICKS 0
|
||||
#define configIDLE_SHOULD_YIELD 1
|
||||
|
||||
@@ -129,7 +129,7 @@ std::string DateTime::FormattedTime() {
|
||||
auto hour = Hours();
|
||||
auto minute = Minutes();
|
||||
// Return time as a string in 12- or 24-hour format
|
||||
char buff[9];
|
||||
char buff[11];
|
||||
if (settingsController.GetClockType() == ClockType::H12) {
|
||||
uint8_t hour12;
|
||||
const char* amPmStr;
|
||||
|
||||
@@ -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 };
|
||||
@@ -50,6 +50,12 @@ namespace Pinetime {
|
||||
int colorIndex = 0;
|
||||
};
|
||||
|
||||
struct Location {
|
||||
int16_t latitude;
|
||||
int16_t longitude;
|
||||
int8_t tzOffset;
|
||||
};
|
||||
|
||||
Settings(Pinetime::Controllers::FS& fs);
|
||||
|
||||
Settings(const Settings&) = delete;
|
||||
@@ -275,6 +281,21 @@ namespace Pinetime {
|
||||
return settings.stepsGoal;
|
||||
};
|
||||
|
||||
void SetLocation(Location loc) {
|
||||
if (
|
||||
loc.latitude != settings.location.latitude ||
|
||||
loc.longitude != settings.location.longitude ||
|
||||
loc.tzOffset != settings.location.tzOffset
|
||||
) {
|
||||
settingsChanged = true;
|
||||
}
|
||||
settings.location = loc;
|
||||
};
|
||||
|
||||
Location GetLocation() const {
|
||||
return settings.location;
|
||||
};
|
||||
|
||||
void SetBleRadioEnabled(bool enabled) {
|
||||
bleRadioEnabled = enabled;
|
||||
};
|
||||
@@ -308,6 +329,8 @@ namespace Pinetime {
|
||||
uint16_t shakeWakeThreshold = 150;
|
||||
|
||||
Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium;
|
||||
|
||||
Location location = {(int16_t)44,(int16_t)-123,(int8_t)-8};
|
||||
};
|
||||
|
||||
SettingsData settings;
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "displayapp/screens/settings/SettingChimes.h"
|
||||
#include "displayapp/screens/settings/SettingShakeThreshold.h"
|
||||
#include "displayapp/screens/settings/SettingBluetooth.h"
|
||||
#include "displayapp/screens/settings/SettingLocation.h"
|
||||
|
||||
#include "libs/lv_conf.h"
|
||||
#include "UserApps.h"
|
||||
@@ -515,6 +516,9 @@ void DisplayApp::LoadScreen(Apps app, DisplayApp::FullRefreshDirections directio
|
||||
case Apps::SettingSetDateTime:
|
||||
currentScreen = std::make_unique<Screens::SettingSetDateTime>(this, dateTimeController, settingsController);
|
||||
break;
|
||||
case Apps::SettingLocation:
|
||||
currentScreen = std::make_unique<Screens::SettingLocation>(settingsController);
|
||||
break;
|
||||
case Apps::SettingChimes:
|
||||
currentScreen = std::make_unique<Screens::SettingChimes>(settingsController);
|
||||
break;
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
#include "displayapp/screens/WatchFaceInfineat.h"
|
||||
#include "displayapp/screens/WatchFacePineTimeStyle.h"
|
||||
#include "displayapp/screens/WatchFaceTerminal.h"
|
||||
#include "displayapp/screens/WatchFaceFuzzy.h"
|
||||
#include "displayapp/screens/WatchFaceSundial.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace Pinetime {
|
||||
SettingWakeUp,
|
||||
SettingSteps,
|
||||
SettingSetDateTime,
|
||||
SettingLocation,
|
||||
SettingChimes,
|
||||
SettingShakeThreshold,
|
||||
SettingBluetooth,
|
||||
@@ -50,6 +51,8 @@ namespace Pinetime {
|
||||
Analog,
|
||||
PineTimeStyle,
|
||||
Terminal,
|
||||
Fuzzy,
|
||||
Sundial,
|
||||
Infineat,
|
||||
CasioStyleG7710,
|
||||
};
|
||||
|
||||
@@ -2,19 +2,11 @@ if(DEFINED ENABLE_USERAPPS)
|
||||
set(USERAPP_TYPES ${ENABLE_USERAPPS} CACHE STRING "List of user apps to build into the firmware")
|
||||
else ()
|
||||
set(DEFAULT_USER_APP_TYPES "Apps::StopWatch")
|
||||
set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Alarm")
|
||||
set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Timer")
|
||||
set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Steps")
|
||||
set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::HeartRate")
|
||||
set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Music")
|
||||
set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paint")
|
||||
set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Paddle")
|
||||
set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Twos")
|
||||
set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Dice")
|
||||
set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Metronome")
|
||||
set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Navigation")
|
||||
set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Weather")
|
||||
#set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Motion")
|
||||
set(USERAPP_TYPES "${DEFAULT_USER_APP_TYPES}" CACHE STRING "List of user apps to build into the firmware")
|
||||
endif ()
|
||||
|
||||
@@ -22,11 +14,8 @@ if(DEFINED ENABLE_WATCHFACES)
|
||||
set(WATCHFACE_TYPES ${ENABLE_WATCHFACES} CACHE STRING "List of watch faces to build into the firmware")
|
||||
else()
|
||||
set(DEFAULT_WATCHFACE_TYPES "WatchFace::Digital")
|
||||
set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Analog")
|
||||
set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::PineTimeStyle")
|
||||
set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Terminal")
|
||||
set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Infineat")
|
||||
set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::CasioStyleG7710")
|
||||
set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Fuzzy")
|
||||
set(DEFAULT_WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}, WatchFace::Sundial")
|
||||
set(WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}" CACHE STRING "List of watch faces to build into the firmware")
|
||||
endif()
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
set(FONTS jetbrains_mono_42 jetbrains_mono_76 jetbrains_mono_bold_20
|
||||
set(FONTS jetbrains_mono_42 jetbrains_mono_76 jetbrains_mono_bold_20 jetbrains_mono_bold_24
|
||||
jetbrains_mono_extrabold_compressed lv_font_sys_48
|
||||
open_sans_light fontawesome_weathericons)
|
||||
find_program(LV_FONT_CONV "lv_font_conv" NO_CACHE REQUIRED
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
"jetbrains_mono_bold_20": {
|
||||
"sources": [
|
||||
{
|
||||
"file": "JetBrainsMono-Bold.ttf",
|
||||
"range": "0x20-0x7e, 0x410-0x44f, 0xB0"
|
||||
"file": "Vulf_Mono-Italic.woff",
|
||||
"range": "0x20-0x7e, 0xB0"
|
||||
},
|
||||
{
|
||||
"file": "FontAwesome5-Solid+Brands+Regular.woff",
|
||||
@@ -11,13 +11,26 @@
|
||||
}
|
||||
],
|
||||
"bpp": 1,
|
||||
"size": 20,
|
||||
"patches": ["jetbrains_mono_bold_20.c_zero.patch", "jetbrains_mono_bold_20.c_M.patch"]
|
||||
"size": 20
|
||||
},
|
||||
"jetbrains_mono_bold_24": {
|
||||
"sources": [
|
||||
{
|
||||
"file": "Vulf_Mono-Italic.woff",
|
||||
"range": "0x20-0x7e, 0xB0"
|
||||
},
|
||||
{
|
||||
"file": "FontAwesome5-Solid+Brands+Regular.woff",
|
||||
"range": "0xf294, 0xf242, 0xf54b, 0xf21e, 0xf1e6, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf06e, 0xf015, 0xf00c, 0xf0f3, 0xf522, 0xf743"
|
||||
}
|
||||
],
|
||||
"bpp": 1,
|
||||
"size": 26
|
||||
},
|
||||
"jetbrains_mono_42": {
|
||||
"sources": [
|
||||
{
|
||||
"file": "JetBrainsMono-Regular.ttf",
|
||||
"file": "Vulf Mono Light Italic.ttf",
|
||||
"range": "0x25, 0x2b, 0x2d, 0x2e, 0x30-0x3a, 0x43, 0x46, 0x4b-0x4d, 0x66, 0x69, 0x6b, 0x6d, 0x74, 0xb0"
|
||||
}
|
||||
],
|
||||
|
||||
189
src/displayapp/screens/WatchFaceFuzzy.cpp
Normal file
189
src/displayapp/screens/WatchFaceFuzzy.cpp
Normal file
@@ -0,0 +1,189 @@
|
||||
#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/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,
|
||||
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}
|
||||
{
|
||||
|
||||
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_bold_24);
|
||||
lv_label_set_recolor(label_time, true);
|
||||
lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_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() {
|
||||
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);
|
||||
|
||||
currentDateTime = std::chrono::time_point_cast<std::chrono::minutes>(dateTimeController.CurrentDateTime());
|
||||
if (currentDate.IsUpdated()) {
|
||||
uint16_t year = dateTimeController.Year();
|
||||
uint8_t day = dateTimeController.Day();
|
||||
lv_label_set_text_fmt(label_date,
|
||||
"%s %d %s %d",
|
||||
dateTimeController.DayOfWeekShortToString(),
|
||||
day,
|
||||
dateTimeController.MonthShortToString(),
|
||||
year);
|
||||
lv_obj_realign(label_date);
|
||||
}
|
||||
}
|
||||
|
||||
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]);
|
||||
}
|
||||
|
||||
printf("%s\n", timeStr);
|
||||
lv_label_set_text(label_time, timeStr);
|
||||
lv_obj_realign(label_time);
|
||||
}
|
||||
100
src/displayapp/screens/WatchFaceFuzzy.h
Normal file
100
src/displayapp/screens/WatchFaceFuzzy.h
Normal file
@@ -0,0 +1,100 @@
|
||||
#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"
|
||||
|
||||
extern lv_font_t jetbrains_mono_bold_24;
|
||||
|
||||
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,
|
||||
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_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;
|
||||
|
||||
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.notificationManager,
|
||||
controllers.settingsController,
|
||||
controllers.heartRateController,
|
||||
controllers.motionController,
|
||||
*controllers.weatherController);
|
||||
};
|
||||
|
||||
static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
259
src/displayapp/screens/WatchFaceSundial.cpp
Normal file
259
src/displayapp/screens/WatchFaceSundial.cpp
Normal file
@@ -0,0 +1,259 @@
|
||||
#include "displayapp/screens/WatchFaceSundial.h"
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <cstdio>
|
||||
// #include <cmath>
|
||||
#include "displayapp/screens/NotificationIcon.h"
|
||||
#include "displayapp/screens/Symbols.h"
|
||||
#include "displayapp/screens/WeatherSymbols.h"
|
||||
#include "displayapp/InfiniTimeTheme.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"
|
||||
#include "sunset/src/sunset.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
namespace {
|
||||
int16_t HourLength = 70;
|
||||
constexpr int16_t MinuteLength = 90;
|
||||
constexpr int16_t SecondLength = 110;
|
||||
constexpr int16_t SunDialVerticalOffset = 40;
|
||||
|
||||
// sin(90) = 1 so the value of _lv_trigo_sin(90) is the scaling factor
|
||||
const auto LV_TRIG_SCALE = _lv_trigo_sin(90);
|
||||
const lv_color_t DARK_GRAY = lv_color_make(48, 48, 48);
|
||||
const lv_color_t DARK_ORANGE = lv_color_make(48, 26, 0);
|
||||
|
||||
int16_t Cosine(int16_t angle) {
|
||||
return _lv_trigo_sin(angle + 90);
|
||||
}
|
||||
|
||||
int16_t Sine(int16_t angle) {
|
||||
return _lv_trigo_sin(angle);
|
||||
}
|
||||
|
||||
int16_t CoordinateXRelocate(int16_t x) {
|
||||
return (x + LV_HOR_RES / 2);
|
||||
}
|
||||
|
||||
|
||||
int16_t CoordinateYRelocateSundial(int16_t y) {
|
||||
return std::abs(y - SunDialVerticalOffset);
|
||||
}
|
||||
|
||||
lv_point_t CoordinateRelocateSundial(int16_t radius, int16_t angle) {
|
||||
return lv_point_t {.x = CoordinateXRelocate(radius * static_cast<int32_t>(Sine(angle)) / LV_TRIG_SCALE),
|
||||
.y = CoordinateYRelocateSundial(radius * static_cast<int32_t>(Cosine(angle)) / LV_TRIG_SCALE)};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
WatchFaceSundial::WatchFaceSundial(Controllers::DateTime& dateTimeController,
|
||||
Controllers::NotificationManager& notificationManager,
|
||||
Controllers::Settings& settingsController)
|
||||
: currentDateTime {{}},
|
||||
dateTimeController {dateTimeController},
|
||||
notificationManager {notificationManager},
|
||||
settingsController {settingsController}
|
||||
{
|
||||
// minor_scales = lv_linemeter_create(lv_scr_act(), nullptr);
|
||||
// lv_linemeter_set_scale(minor_scales, 300, 51);
|
||||
// lv_linemeter_set_angle_offset(minor_scales, 180);
|
||||
// lv_obj_set_size(minor_scales, 240, 240);
|
||||
// lv_obj_align(minor_scales, nullptr, LV_ALIGN_CENTER, 0, 0);
|
||||
// lv_obj_set_style_local_bg_opa(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
|
||||
// lv_obj_set_style_local_scale_width(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4);
|
||||
// lv_obj_set_style_local_scale_end_line_width(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 1);
|
||||
// lv_obj_set_style_local_scale_end_color(minor_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
|
||||
|
||||
// major_scales = lv_linemeter_create(lv_scr_act(), nullptr);
|
||||
// lv_linemeter_set_scale(major_scales, 300, 11);
|
||||
// lv_linemeter_set_angle_offset(major_scales, 180);
|
||||
// lv_obj_set_size(major_scales, 240, 240);
|
||||
// lv_obj_align(major_scales, nullptr, LV_ALIGN_CENTER, 0, 0);
|
||||
// lv_obj_set_style_local_bg_opa(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
|
||||
// lv_obj_set_style_local_scale_width(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 6);
|
||||
// lv_obj_set_style_local_scale_end_line_width(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4);
|
||||
// lv_obj_set_style_local_scale_end_color(major_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
|
||||
// large_scales = lv_linemeter_create(lv_scr_act(), nullptr);
|
||||
// lv_linemeter_set_scale(large_scales, 180, 3);
|
||||
// lv_linemeter_set_angle_offset(large_scales, 180);
|
||||
// lv_obj_set_size(large_scales, 240, 240);
|
||||
// lv_obj_align(large_scales, nullptr, LV_ALIGN_CENTER, 0, 0);
|
||||
// lv_obj_set_style_local_bg_opa(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
|
||||
// lv_obj_set_style_local_scale_width(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 20);
|
||||
// lv_obj_set_style_local_scale_end_line_width(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, 4);
|
||||
// lv_obj_set_style_local_scale_end_color(large_scales, LV_LINEMETER_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_AQUA);
|
||||
|
||||
twelve = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_label_set_align(twelve, LV_LABEL_ALIGN_RIGHT);
|
||||
lv_label_set_text_static(twelve, "XII");
|
||||
lv_obj_align(twelve, NULL, LV_ALIGN_IN_TOP_RIGHT, -20, SunDialVerticalOffset-20);
|
||||
lv_obj_set_style_local_text_color(twelve, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
|
||||
one = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_label_set_align(one, LV_LABEL_ALIGN_LEFT);
|
||||
lv_label_set_text(one, "I");
|
||||
lv_obj_align(one, NULL, LV_ALIGN_IN_TOP_LEFT, 20, SunDialVerticalOffset-20);
|
||||
lv_obj_set_style_local_text_color(one, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
|
||||
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);
|
||||
|
||||
// Date - Day / Week day
|
||||
label_date_day = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(label_date_day, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, DARK_ORANGE);
|
||||
lv_label_set_text_fmt(label_date_day, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), dateTimeController.Day());
|
||||
lv_label_set_align(label_date_day, LV_LABEL_ALIGN_CENTER);
|
||||
lv_obj_align(label_date_day, nullptr, LV_ALIGN_CENTER, 50, 0);
|
||||
|
||||
minute_body = lv_line_create(lv_scr_act(), nullptr);
|
||||
minute_body_trace = lv_line_create(lv_scr_act(), nullptr);
|
||||
hour_body = lv_line_create(lv_scr_act(), nullptr);
|
||||
hour_body_trace = lv_line_create(lv_scr_act(), nullptr);
|
||||
second_body = lv_line_create(lv_scr_act(), nullptr);
|
||||
|
||||
lv_style_init(&second_line_style);
|
||||
lv_style_set_line_width(&second_line_style, LV_STATE_DEFAULT, 3);
|
||||
lv_style_set_line_color(&second_line_style, LV_STATE_DEFAULT, LV_COLOR_RED);
|
||||
lv_style_set_line_rounded(&second_line_style, LV_STATE_DEFAULT, true);
|
||||
lv_obj_add_style(second_body, LV_LINE_PART_MAIN, &second_line_style);
|
||||
|
||||
lv_style_init(&minute_line_style);
|
||||
lv_style_set_line_width(&minute_line_style, LV_STATE_DEFAULT, 7);
|
||||
lv_style_set_line_color(&minute_line_style, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
lv_style_set_line_rounded(&minute_line_style, LV_STATE_DEFAULT, true);
|
||||
lv_obj_add_style(minute_body, LV_LINE_PART_MAIN, &minute_line_style);
|
||||
|
||||
lv_style_init(&minute_line_style_trace);
|
||||
lv_style_set_line_width(&minute_line_style_trace, LV_STATE_DEFAULT, 3);
|
||||
lv_style_set_line_color(&minute_line_style_trace, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
lv_style_set_line_rounded(&minute_line_style_trace, LV_STATE_DEFAULT, false);
|
||||
lv_obj_add_style(minute_body_trace, LV_LINE_PART_MAIN, &minute_line_style_trace);
|
||||
|
||||
lv_style_init(&hour_line_style);
|
||||
lv_style_set_line_width(&hour_line_style, LV_STATE_DEFAULT, 7);
|
||||
lv_style_set_line_color(&hour_line_style, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
lv_style_set_line_rounded(&hour_line_style, LV_STATE_DEFAULT, true);
|
||||
lv_obj_add_style(hour_body, LV_LINE_PART_MAIN, &hour_line_style);
|
||||
|
||||
lv_style_init(&hour_line_style_trace);
|
||||
lv_style_set_line_width(&hour_line_style_trace, LV_STATE_DEFAULT, 3);
|
||||
lv_style_set_line_color(&hour_line_style_trace, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
lv_style_set_line_rounded(&hour_line_style_trace, LV_STATE_DEFAULT, false);
|
||||
lv_obj_add_style(hour_body_trace, LV_LINE_PART_MAIN, &hour_line_style_trace);
|
||||
|
||||
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
|
||||
UpdateClock();
|
||||
Refresh();
|
||||
}
|
||||
|
||||
WatchFaceSundial::~WatchFaceSundial() {
|
||||
lv_task_del(taskRefresh);
|
||||
|
||||
lv_style_reset(&hour_line_style);
|
||||
lv_style_reset(&hour_line_style_trace);
|
||||
lv_style_reset(&minute_line_style);
|
||||
lv_style_reset(&minute_line_style_trace);
|
||||
lv_style_reset(&second_line_style);
|
||||
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
void WatchFaceSundial::Refresh() {
|
||||
currentDateTime = std::chrono::time_point_cast<std::chrono::minutes>(dateTimeController.CurrentDateTime());
|
||||
if (currentDateTime.IsUpdated()) {
|
||||
currentDateTime = std::chrono::time_point_cast<std::chrono::minutes>(dateTimeController.CurrentDateTime());
|
||||
UpdateClock();
|
||||
if (currentDate.IsUpdated()) {
|
||||
char const* MonthsString[] = {"--", "IANUARIUS","FEBRUARIUS","MARTIUS","APRILIS","MARTIUSIUNIUS","QUINTILIS","SEXTILIS","SEPTEMBER","OCTOBER","NOVEMBER","DECEMBER"};
|
||||
char const* DaysString[] = {"--", "LUNAE", "MARTIS", "MERCURII", "IOVIS", "VENERIS", "SATURNI", "SOLIS"};
|
||||
char const* RomanNumeralsString[] = {"--", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII"};
|
||||
lv_label_set_text_fmt(label_date_day, "%s\n%s %s",
|
||||
DaysString[static_cast<uint8_t>(dateTimeController.DayOfWeek())],
|
||||
RomanNumeralsString[static_cast<uint8_t>(dateTimeController.Day())],
|
||||
MonthsString[static_cast<uint8_t>(dateTimeController.Month())]);
|
||||
lv_obj_align(label_date_day, nullptr, LV_ALIGN_IN_BOTTOM_MID, 0, -20);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void WatchFaceSundial::UpdateClock() {
|
||||
uint8_t hour = dateTimeController.Hours();
|
||||
uint8_t minute = dateTimeController.Minutes();
|
||||
location = settingsController.GetLocation();
|
||||
|
||||
if (sHour != hour || sMinute != minute) {
|
||||
// sun.setPosition(settings.lat.toFloat(), settings.lon.toFloat(), settings.gmtOffset / 3600);
|
||||
sun.setPosition((float)location.latitude, (float)location.longitude, location.tzOffset);
|
||||
|
||||
//from minutes past midnight
|
||||
sun.setCurrentDate(dateTimeController.Year(), static_cast<uint8_t>(dateTimeController.Month())+1, dateTimeController.Day());
|
||||
sun.setTZOffset(location.tzOffset);
|
||||
|
||||
minutesSunrise = sun.calcSunrise(); //360;
|
||||
minutesSunset = sun.calcSunset(); //1080;
|
||||
minutesDaytime = (minutesSunset - minutesSunrise);
|
||||
minutesNighttime = (1440 - minutesDaytime);
|
||||
|
||||
minutesBeforeSunset = minutesSunset - (hour * 60 + minute); // i.e.zero degrees
|
||||
HourLength = 90; // sundial hand length
|
||||
|
||||
int16_t hourAngle;
|
||||
|
||||
if(minutesBeforeSunset > 0 && minutesBeforeSunset < minutesDaytime) { // day (after sunrise)
|
||||
hourAngle = 180.0 * minutesBeforeSunset / minutesDaytime + 90;
|
||||
lv_style_set_line_color(&hour_line_style, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
lv_style_set_line_color(&hour_line_style_trace, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
lv_obj_set_style_local_text_color(label_date_day, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE);
|
||||
lv_obj_set_style_local_text_color(one, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
lv_obj_set_style_local_text_color(twelve, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
} else { // night (before sunrise or after sunset)
|
||||
lv_style_set_line_color(&hour_line_style, LV_STATE_DEFAULT, DARK_GRAY);
|
||||
lv_style_set_line_color(&hour_line_style_trace, LV_STATE_DEFAULT, DARK_GRAY);
|
||||
lv_obj_set_style_local_text_color(label_date_day, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, DARK_ORANGE);
|
||||
lv_obj_set_style_local_text_color(one, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, DARK_GRAY);
|
||||
lv_obj_set_style_local_text_color(twelve, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, DARK_GRAY);
|
||||
|
||||
if(minutesBeforeSunset > minutesDaytime) { // before sunrise
|
||||
hourAngle = 180.0 * (minutesBeforeSunset - minutesDaytime) / minutesNighttime + 90;
|
||||
} else { // after sunset
|
||||
hourAngle = 180 + 180.0 * minutesBeforeSunset / minutesNighttime + 90;
|
||||
}
|
||||
}
|
||||
/*NRF_LOG_INFO("a: %d, la: %f, lo: %f, ri: %d, se: %d, be: %d",
|
||||
hourAngle,
|
||||
(float)location.latitude,
|
||||
(float)location.longitude,
|
||||
minutesSunrise,
|
||||
minutesSunset,
|
||||
minutesBeforeSunset);*/
|
||||
|
||||
sHour = hour;
|
||||
sMinute = minute;
|
||||
|
||||
printf("H%d:%d lat%f lng%f z%d\n", hour, minute, (float)location.latitude, (float)location.longitude, location.tzOffset);
|
||||
printf("%d before sunset, sunrise at %d:%d sunset at %d:%d angle %d\n",
|
||||
minutesBeforeSunset,
|
||||
minutesSunrise/60, minutesSunrise % 60,
|
||||
minutesSunset/60, minutesSunset % 60, hourAngle);
|
||||
|
||||
hour_point_trace[0] = CoordinateRelocateSundial(HourLength*.75, hourAngle);
|
||||
hour_point_trace[1] = CoordinateRelocateSundial(HourLength, hourAngle);
|
||||
|
||||
hour_point[0] = CoordinateRelocateSundial(0, hourAngle);
|
||||
hour_point[1] = CoordinateRelocateSundial(HourLength*.75, hourAngle);
|
||||
|
||||
lv_line_set_points(hour_body, hour_point, 2);
|
||||
lv_line_set_points(hour_body_trace, hour_point_trace, 2);
|
||||
}
|
||||
}
|
||||
111
src/displayapp/screens/WatchFaceSundial.h
Normal file
111
src/displayapp/screens/WatchFaceSundial.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#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/battery/BatteryController.h"
|
||||
#include "components/ble/BleController.h"
|
||||
#include "components/ble/NotificationManager.h"
|
||||
#include "displayapp/screens/BatteryIcon.h"
|
||||
#include "utility/DirtyValue.h"
|
||||
#include "sunset/src/sunset.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Controllers {
|
||||
class Settings;
|
||||
class Battery;
|
||||
class Ble;
|
||||
class NotificationManager;
|
||||
}
|
||||
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
|
||||
class WatchFaceSundial : public Screen {
|
||||
public:
|
||||
WatchFaceSundial(Controllers::DateTime& dateTimeController,
|
||||
Controllers::NotificationManager& notificationManager,
|
||||
Controllers::Settings& settingsController);
|
||||
|
||||
~WatchFaceSundial() override;
|
||||
|
||||
void Refresh() override;
|
||||
|
||||
private:
|
||||
uint8_t sHour, sMinute, sSecond;
|
||||
|
||||
Utility::DirtyValue<uint8_t> batteryPercentRemaining {0};
|
||||
Utility::DirtyValue<bool> isCharging {};
|
||||
Utility::DirtyValue<bool> bleState {};
|
||||
Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime;
|
||||
Utility::DirtyValue<bool> notificationState {false};
|
||||
using days = std::chrono::duration<int32_t, std::ratio<86400>>; // TODO: days is standard in c++20
|
||||
Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, days>> currentDate;
|
||||
|
||||
lv_obj_t* major_scales;
|
||||
lv_obj_t* one;
|
||||
lv_obj_t* twelve;
|
||||
|
||||
lv_obj_t* hour_body;
|
||||
lv_obj_t* hour_body_trace;
|
||||
lv_obj_t* minute_body;
|
||||
lv_obj_t* minute_body_trace;
|
||||
lv_obj_t* second_body;
|
||||
|
||||
lv_point_t hour_point[2];
|
||||
lv_point_t hour_point_trace[2];
|
||||
lv_point_t minute_point[2];
|
||||
lv_point_t minute_point_trace[2];
|
||||
lv_point_t second_point[2];
|
||||
|
||||
lv_style_t hour_line_style;
|
||||
lv_style_t hour_line_style_trace;
|
||||
lv_style_t minute_line_style;
|
||||
lv_style_t minute_line_style_trace;
|
||||
lv_style_t second_line_style;
|
||||
|
||||
lv_obj_t* label_date_day;
|
||||
lv_obj_t* plugIcon;
|
||||
lv_obj_t* notificationIcon;
|
||||
lv_obj_t* bleIcon;
|
||||
|
||||
Controllers::Settings::Location location;
|
||||
SunSet sun;
|
||||
int16_t minutesSunrise;
|
||||
int16_t minutesSunset;
|
||||
int16_t minutesDaytime;
|
||||
int16_t minutesNighttime;
|
||||
int16_t minutesBeforeSunset;
|
||||
|
||||
const Controllers::DateTime& dateTimeController;
|
||||
Controllers::NotificationManager& notificationManager;
|
||||
Controllers::Settings& settingsController;
|
||||
|
||||
void drawWatchFaceModeNight();
|
||||
void UpdateClock();
|
||||
void SetBatteryIcon();
|
||||
|
||||
lv_task_t* taskRefresh;
|
||||
};
|
||||
}
|
||||
|
||||
template <>
|
||||
struct WatchFaceTraits<WatchFace::Sundial> {
|
||||
static constexpr WatchFace watchFace = WatchFace::Sundial;
|
||||
static constexpr const char* name = "Sundial face";
|
||||
|
||||
static Screens::Screen* Create(AppControllers& controllers) {
|
||||
return new Screens::WatchFaceSundial(controllers.dateTimeController,
|
||||
controllers.notificationManager,
|
||||
controllers.settingsController);
|
||||
};
|
||||
|
||||
static bool IsAvailable(Pinetime::Controllers::FS& /*filesystem*/) {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
70
src/displayapp/screens/settings/SettingLocation.cpp
Normal file
70
src/displayapp/screens/settings/SettingLocation.cpp
Normal file
@@ -0,0 +1,70 @@
|
||||
#include "displayapp/screens/settings/SettingLocation.h"
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <nrf_log.h>
|
||||
#include "displayapp/DisplayApp.h"
|
||||
#include "displayapp/screens/Symbols.h"
|
||||
#include "components/settings/Settings.h"
|
||||
#include "displayapp/InfiniTimeTheme.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
namespace {
|
||||
constexpr int16_t POS_X_LAT = -80;
|
||||
constexpr int16_t POS_X_LONG = 0;
|
||||
constexpr int16_t POS_X_TZ = 80;
|
||||
constexpr int16_t POS_Y_TEXT = 25;
|
||||
|
||||
void ValueChangedHandler(void* userData) {
|
||||
auto* screen = static_cast<SettingLocation*>(userData);
|
||||
screen->UpdateScreen();
|
||||
}
|
||||
}
|
||||
|
||||
SettingLocation::SettingLocation(Pinetime::Controllers::Settings& settingsController)
|
||||
: settingsController {settingsController} {
|
||||
|
||||
lv_obj_t* title = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_label_set_text_static(title, "Set location\n(lat/long/tz)");
|
||||
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::map);
|
||||
lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER);
|
||||
lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0);
|
||||
|
||||
Controllers::Settings::Location loc = settingsController.GetLocation();
|
||||
|
||||
latCounter.Create();
|
||||
latCounter.SetValue(loc.latitude);
|
||||
lv_obj_align(latCounter.GetObject(), nullptr, LV_ALIGN_CENTER, POS_X_LAT, POS_Y_TEXT);
|
||||
latCounter.SetValueChangedEventCallback(this, ValueChangedHandler);
|
||||
|
||||
longCounter.Create();
|
||||
longCounter.SetValue(loc.longitude);
|
||||
lv_obj_align(longCounter.GetObject(), nullptr, LV_ALIGN_CENTER, POS_X_LONG, POS_Y_TEXT);
|
||||
longCounter.SetValueChangedEventCallback(this, ValueChangedHandler);
|
||||
|
||||
tzCounter.Create();
|
||||
tzCounter.SetValue(loc.tzOffset);
|
||||
lv_obj_align(tzCounter.GetObject(), nullptr, LV_ALIGN_CENTER, POS_X_TZ, POS_Y_TEXT);
|
||||
tzCounter.SetValueChangedEventCallback(this, ValueChangedHandler);
|
||||
|
||||
UpdateScreen();
|
||||
}
|
||||
|
||||
SettingLocation::~SettingLocation() {
|
||||
lv_obj_clean(lv_scr_act());
|
||||
settingsController.SaveSettings();
|
||||
}
|
||||
|
||||
void SettingLocation::UpdateScreen() {
|
||||
Controllers::Settings::Location loc = {
|
||||
latitude: (int16_t)latCounter.GetValue(),
|
||||
longitude: (int16_t)longCounter.GetValue(),
|
||||
tzOffset: (int8_t)tzCounter.GetValue(),
|
||||
};
|
||||
settingsController.SetLocation(loc);
|
||||
}
|
||||
31
src/displayapp/screens/settings/SettingLocation.h
Normal file
31
src/displayapp/screens/settings/SettingLocation.h
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <lvgl/lvgl.h>
|
||||
#include "components/datetime/DateTimeController.h"
|
||||
#include "components/settings/Settings.h"
|
||||
#include "displayapp/widgets/Counter.h"
|
||||
#include "displayapp/screens/Screen.h"
|
||||
#include "displayapp/widgets/DotIndicator.h"
|
||||
#include "displayapp/screens/settings/SettingSetDateTime.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
class SettingLocation : public Screen {
|
||||
public:
|
||||
SettingLocation(Pinetime::Controllers::Settings& settingsController);
|
||||
~SettingLocation() override;
|
||||
|
||||
void UpdateScreen();
|
||||
|
||||
private:
|
||||
Controllers::Settings& settingsController;
|
||||
|
||||
Widgets::Counter latCounter = Widgets::Counter(-90, 90, jetbrains_mono_bold_20);
|
||||
Widgets::Counter longCounter = Widgets::Counter(-180, 180, jetbrains_mono_bold_20);
|
||||
Widgets::Counter tzCounter = Widgets::Counter(-12, 12, jetbrains_mono_bold_20);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,8 @@
|
||||
#include "displayapp/screens/Screen.h"
|
||||
#include "displayapp/screens/Symbols.h"
|
||||
#include "displayapp/screens/CheckboxList.h"
|
||||
#include "displayapp/screens/WatchFaceInfineat.h"
|
||||
#include "displayapp/screens/WatchFaceCasioStyleG7710.h"
|
||||
// #include "displayapp/screens/WatchFaceInfineat.h"
|
||||
// #include "displayapp/screens/WatchFaceCasioStyleG7710.h"
|
||||
|
||||
namespace Pinetime {
|
||||
|
||||
|
||||
@@ -39,6 +39,7 @@ namespace Pinetime {
|
||||
|
||||
{Symbols::shoe, "Steps", Apps::SettingSteps},
|
||||
{Symbols::clock, "Date&Time", Apps::SettingSetDateTime},
|
||||
{Symbols::map, "Location", Apps::SettingLocation},
|
||||
{Symbols::cloudSunRain, "Weather", Apps::SettingWeatherFormat},
|
||||
{Symbols::batteryHalf, "Battery", Apps::BatteryInfo},
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ namespace Pinetime {
|
||||
int max;
|
||||
int value;
|
||||
const int leadingZeroCount;
|
||||
uint8_t containerHeight;
|
||||
static constexpr uint8_t btnHeight = 50;
|
||||
bool twelveHourMode = false;
|
||||
bool monthMode = false;
|
||||
lv_font_t& font;
|
||||
|
||||
1
src/libs/sunset
Submodule
1
src/libs/sunset
Submodule
Submodule src/libs/sunset added at 4b08734eb8
Reference in New Issue
Block a user