mirror of
https://github.com/InfiniTimeOrg/InfiniTime.git
synced 2024-10-22 15:11:51 +02:00
merge ??
This commit is contained in:
commit
b7b68f6362
|
@ -1,5 +0,0 @@
|
|||
[core]
|
||||
whitespace = blank-at-eol,blank-at-eof,space-before-tab
|
||||
autocrlf = input
|
||||
[apply]
|
||||
whitespace = fix
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -13,6 +13,10 @@ build
|
|||
tools
|
||||
node_modules
|
||||
|
||||
# My stuff
|
||||
#draft_pictures
|
||||
node_modules
|
||||
|
||||
# Resulting binary files
|
||||
*.a
|
||||
*.so
|
||||
|
|
38
README.md
38
README.md
|
@ -1,16 +1,48 @@
|
|||
# [InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime)
|
||||
# [InfiniTime](https://github.com/Eve1374/InfiniTime)
|
||||
|
||||
![InfiniTime logo](doc/logo/infinitime-logo-small.jpg "InfiniTime Logo")
|
||||
|
||||
Fast open-source firmware for the [PineTime smartwatch](https://pine64.org/devices/pinetime/) with many features, written in modern C++.
|
||||
|
||||
## Quick notes on this InfiniTime version
|
||||
|
||||
- I copied the source code from this git repo : [InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime)
|
||||
- I added a watch face "WatchFaceMeow" whose main features are to be pink and have info about the alarm status
|
||||
- I stored the compile commands in scripts compile.sh to run from InfiniTime/ folder, and make_pine_mcu.sh to build the image must be run from InfiniTime/build/ (compile.sh copies make_pine_mcu.sh to build/
|
||||
- The file to flash to the pinetime is InfiniTime/build/pinetime-mcuboot-app-dfu-1.14.0.zip : I didn't change the version compared to the one I downloaded from [InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime) so make sure not to keep keep a copy of it
|
||||
|
||||
Here are pictures with and without alarm set :
|
||||
|
||||
![Meow alarm set](doc/ui/meow_alarmset.png "Meow WatchFace, alarm set") ![Meow alarm not set](doc/ui/meow_alarmnotset.png "Meow WatchFace, alarm not set")
|
||||
|
||||
Original repo : [InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime)
|
||||
|
||||
- [Getting started with InfiniTime](doc/gettingStarted/gettingStarted-1.0.md)
|
||||
- [Updating the software](doc/gettingStarted/updating-software.md)
|
||||
- [About the firmware and bootloader](doc/gettingStarted/about-software.md)
|
||||
- [PineTimeStyle Watch face](https://pine64.org/documentation/PineTime/Watchfaces/PineTimeStyle)
|
||||
- [Weather integration](https://pine64.org/documentation/PineTime/Software/InfiniTime_weather/)
|
||||
|
||||
## Welcome to my InfiniTime fork ?!
|
||||
|
||||
Branches :
|
||||
|
||||
- main : shows this doc
|
||||
- alarm-status-on-infineat : shows the alarm status on infineat, can be enabled or disabled from the settigns menu that is updated accordingly :
|
||||
|
||||
![Infineat settings](doc/ui/infineat_settings.png "Infineat settings")
|
||||
|
||||
- my-custom-infinitime : branch were I put things that I want for myself, like a watchface with paw instead of shoe icon for steps counter :
|
||||
|
||||
![Meow watchface](doc/ui/meow_alarmset.png "Meow watchface")
|
||||
|
||||
## New to InfiniTime?
|
||||
|
||||
- [Getting started with InfiniTime](doc/gettingStarted/gettingStarted-1.0.md)
|
||||
- [Updating the software](doc/gettingStarted/updating-software.md)
|
||||
- [About the firmware and bootloader](doc/gettingStarted/about-software.md)
|
||||
- [PineTimeStyle Watch face](https://wiki.pine64.org/wiki/PineTimeStyle)
|
||||
- [Weather integration](https://wiki.pine64.org/wiki/Infinitime-Weather)
|
||||
- [PineTimeStyle Watch face](https://pine64.org/documentation/PineTime/Watchfaces/PineTimeStyle)
|
||||
- [Weather integration](https://pine64.org/documentation/PineTime/Software/InfiniTime_weather/)
|
||||
|
||||
### Companion apps
|
||||
|
||||
|
|
8
compile.sh
Executable file
8
compile.sh
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/bin/bash
|
||||
|
||||
rm -r build
|
||||
|
||||
cmake -DARM_NONE_EABI_TOOLCHAIN_PATH=/home/eve/Work/gcc-arm-none-eabi-10.3-2021.10 -DNRF5_SDK_PATH=/home/eve/Work/nRF5_SDK_17.1.0_ddde560 -DTARGET_DEVICE=PINETIME -DBUILD_DFU=1 -DBUILD_RESOURCES=1 -B build -DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
cp make_pine_mcu.sh build/
|
||||
|
BIN
doc/lvgl_align.png
Normal file
BIN
doc/lvgl_align.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
BIN
doc/palettes.xcf
Normal file
BIN
doc/palettes.xcf
Normal file
Binary file not shown.
BIN
doc/ui/infineat_settings.png
Normal file
BIN
doc/ui/infineat_settings.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.5 KiB |
BIN
doc/ui/meow_alarmnotset.png
Normal file
BIN
doc/ui/meow_alarmnotset.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.6 KiB |
BIN
doc/ui/meow_alarmset.png
Normal file
BIN
doc/ui/meow_alarmset.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6 KiB |
BIN
draft_pictures/cat.png
Normal file
BIN
draft_pictures/cat.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.8 KiB |
BIN
draft_pictures/cat.xcf
Normal file
BIN
draft_pictures/cat.xcf
Normal file
Binary file not shown.
BIN
draft_pictures/cat_clean.xcf
Normal file
BIN
draft_pictures/cat_clean.xcf
Normal file
Binary file not shown.
BIN
draft_pictures/cat_small.xcf
Normal file
BIN
draft_pictures/cat_small.xcf
Normal file
Binary file not shown.
BIN
draft_pictures/coordinates.xcf
Normal file
BIN
draft_pictures/coordinates.xcf
Normal file
Binary file not shown.
6
make_pine.sh
Executable file
6
make_pine.sh
Executable file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
#cp ./displayapp/apps/Apps.h ../src/displayapp/apps/Apps.h
|
||||
|
||||
make -j4 pinetime-app
|
||||
|
6
make_pine_mcu.sh
Executable file
6
make_pine_mcu.sh
Executable file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/bash
|
||||
|
||||
#cp ./displayapp/apps/Apps.h ../src/displayapp/apps/Apps.h
|
||||
|
||||
make clean -j4 pinetime-mcuboot-app
|
||||
|
183
package-lock.json
generated
183
package-lock.json
generated
|
@ -1,183 +0,0 @@
|
|||
{
|
||||
"name": "InfiniTime",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"lv_font_conv": "^1.5.2"
|
||||
}
|
||||
},
|
||||
"node_modules/lv_font_conv": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/lv_font_conv/-/lv_font_conv-1.5.2.tgz",
|
||||
"integrity": "sha512-0UapRSTkVP/pnB8Z4r2HDHx5p2dJx/xUG1+14u/WXo59mwuC7BahR+Bnx/66jKoDrG1wFQwn9ZzoyMxRHOD9bg==",
|
||||
"bundleDependencies": [
|
||||
"argparse",
|
||||
"bit-buffer",
|
||||
"debug",
|
||||
"make-error",
|
||||
"mkdirp",
|
||||
"opentype.js",
|
||||
"pngjs"
|
||||
],
|
||||
"dependencies": {
|
||||
"argparse": "^2.0.0",
|
||||
"bit-buffer": "^0.2.5",
|
||||
"debug": "^4.1.1",
|
||||
"make-error": "^1.3.5",
|
||||
"mkdirp": "^1.0.4",
|
||||
"opentype.js": "^1.1.0",
|
||||
"pngjs": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"lv_font_conv": "lv_font_conv.js"
|
||||
}
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/argparse": {
|
||||
"version": "2.0.1",
|
||||
"inBundle": true,
|
||||
"license": "Python-2.0"
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/bit-buffer": {
|
||||
"version": "0.2.5",
|
||||
"inBundle": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/debug": {
|
||||
"version": "4.3.1",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/make-error": {
|
||||
"version": "1.3.6",
|
||||
"inBundle": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/ms": {
|
||||
"version": "2.1.2",
|
||||
"inBundle": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/opentype.js": {
|
||||
"version": "1.3.3",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"string.prototype.codepointat": "^0.2.1",
|
||||
"tiny-inflate": "^1.0.3"
|
||||
},
|
||||
"bin": {
|
||||
"ot": "bin/ot"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/pngjs": {
|
||||
"version": "6.0.0",
|
||||
"inBundle": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/string.prototype.codepointat": {
|
||||
"version": "0.2.1",
|
||||
"inBundle": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lv_font_conv/node_modules/tiny-inflate": {
|
||||
"version": "1.0.3",
|
||||
"inBundle": true,
|
||||
"license": "MIT"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"lv_font_conv": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/lv_font_conv/-/lv_font_conv-1.5.2.tgz",
|
||||
"integrity": "sha512-0UapRSTkVP/pnB8Z4r2HDHx5p2dJx/xUG1+14u/WXo59mwuC7BahR+Bnx/66jKoDrG1wFQwn9ZzoyMxRHOD9bg==",
|
||||
"requires": {
|
||||
"argparse": "^2.0.0",
|
||||
"bit-buffer": "^0.2.5",
|
||||
"debug": "^4.1.1",
|
||||
"make-error": "^1.3.5",
|
||||
"mkdirp": "^1.0.4",
|
||||
"opentype.js": "^1.1.0",
|
||||
"pngjs": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"argparse": {
|
||||
"version": "2.0.1",
|
||||
"bundled": true
|
||||
},
|
||||
"bit-buffer": {
|
||||
"version": "0.2.5",
|
||||
"bundled": true
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.1",
|
||||
"bundled": true,
|
||||
"requires": {
|
||||
"ms": "2.1.2"
|
||||
}
|
||||
},
|
||||
"make-error": {
|
||||
"version": "1.3.6",
|
||||
"bundled": true
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "1.0.4",
|
||||
"bundled": true
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"bundled": true
|
||||
},
|
||||
"opentype.js": {
|
||||
"version": "1.3.3",
|
||||
"bundled": true,
|
||||
"requires": {
|
||||
"string.prototype.codepointat": "^0.2.1",
|
||||
"tiny-inflate": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"pngjs": {
|
||||
"version": "6.0.0",
|
||||
"bundled": true
|
||||
},
|
||||
"string.prototype.codepointat": {
|
||||
"version": "0.2.1",
|
||||
"bundled": true
|
||||
},
|
||||
"tiny-inflate": {
|
||||
"version": "1.0.3",
|
||||
"bundled": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"lv_font_conv": "^1.5.2"
|
||||
"lv_font_conv": "^1.5.3"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ int WeatherCallback(uint16_t /*connHandle*/, uint16_t /*attrHandle*/, struct ble
|
|||
return static_cast<Pinetime::Controllers::SimpleWeatherService*>(arg)->OnCommand(ctxt);
|
||||
}
|
||||
|
||||
SimpleWeatherService::SimpleWeatherService(const DateTime& dateTimeController) : dateTimeController(dateTimeController) {
|
||||
SimpleWeatherService::SimpleWeatherService(DateTime& dateTimeController) : dateTimeController(dateTimeController) {
|
||||
}
|
||||
|
||||
void SimpleWeatherService::Init() {
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace Pinetime {
|
|||
|
||||
class SimpleWeatherService {
|
||||
public:
|
||||
explicit SimpleWeatherService(const DateTime& dateTimeController);
|
||||
explicit SimpleWeatherService(DateTime& dateTimeController);
|
||||
|
||||
void Init();
|
||||
|
||||
|
@ -140,7 +140,7 @@ namespace Pinetime {
|
|||
|
||||
uint16_t eventHandle {};
|
||||
|
||||
const Pinetime::Controllers::DateTime& dateTimeController;
|
||||
Pinetime::Controllers::DateTime& dateTimeController;
|
||||
|
||||
std::optional<CurrentWeather> currentWeather;
|
||||
std::optional<Forecast> forecast;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "components/datetime/DateTimeController.h"
|
||||
#include <libraries/log/nrf_log.h>
|
||||
#include <systemtask/SystemTask.h>
|
||||
#include <hal/nrf_rtc.h>
|
||||
#include "nrf_assert.h"
|
||||
|
||||
using namespace Pinetime::Controllers;
|
||||
|
||||
|
@ -12,11 +14,16 @@ namespace {
|
|||
}
|
||||
|
||||
DateTime::DateTime(Controllers::Settings& settingsController) : settingsController {settingsController} {
|
||||
mutex = xSemaphoreCreateMutex();
|
||||
ASSERT(mutex != nullptr);
|
||||
xSemaphoreGive(mutex);
|
||||
}
|
||||
|
||||
void DateTime::SetCurrentTime(std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> t) {
|
||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||
this->currentDateTime = t;
|
||||
UpdateTime(previousSystickCounter); // Update internal state without updating the time
|
||||
UpdateTime(previousSystickCounter, true); // Update internal state without updating the time
|
||||
xSemaphoreGive(mutex);
|
||||
}
|
||||
|
||||
void DateTime::SetTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
|
||||
|
@ -29,13 +36,15 @@ void DateTime::SetTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour,
|
|||
/* .tm_year = */ year - 1900,
|
||||
};
|
||||
|
||||
tm.tm_isdst = -1; // Use DST value from local time zone
|
||||
currentDateTime = std::chrono::system_clock::from_time_t(std::mktime(&tm));
|
||||
|
||||
NRF_LOG_INFO("%d %d %d ", day, month, year);
|
||||
NRF_LOG_INFO("%d %d %d ", hour, minute, second);
|
||||
|
||||
UpdateTime(previousSystickCounter);
|
||||
tm.tm_isdst = -1; // Use DST value from local time zone
|
||||
|
||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||
currentDateTime = std::chrono::system_clock::from_time_t(std::mktime(&tm));
|
||||
UpdateTime(previousSystickCounter, true);
|
||||
xSemaphoreGive(mutex);
|
||||
|
||||
systemTask->PushMessage(System::Messages::OnNewTime);
|
||||
}
|
||||
|
@ -45,25 +54,34 @@ void DateTime::SetTimeZone(int8_t timezone, int8_t dst) {
|
|||
dstOffset = dst;
|
||||
}
|
||||
|
||||
void DateTime::UpdateTime(uint32_t systickCounter) {
|
||||
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> DateTime::CurrentDateTime() {
|
||||
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||
UpdateTime(nrf_rtc_counter_get(portNRF_RTC_REG), false);
|
||||
xSemaphoreGive(mutex);
|
||||
return currentDateTime;
|
||||
}
|
||||
|
||||
void DateTime::UpdateTime(uint32_t systickCounter, bool forceUpdate) {
|
||||
// Handle systick counter overflow
|
||||
uint32_t systickDelta = 0;
|
||||
if (systickCounter < previousSystickCounter) {
|
||||
systickDelta = 0xffffff - previousSystickCounter;
|
||||
systickDelta = static_cast<uint32_t>(portNRF_RTC_MAXTICKS) - previousSystickCounter;
|
||||
systickDelta += systickCounter + 1;
|
||||
} else {
|
||||
systickDelta = systickCounter - previousSystickCounter;
|
||||
}
|
||||
|
||||
/*
|
||||
* 1000 ms = 1024 ticks
|
||||
*/
|
||||
auto correctedDelta = systickDelta / 1024;
|
||||
auto rest = systickDelta % 1024;
|
||||
auto correctedDelta = systickDelta / configTICK_RATE_HZ;
|
||||
// If a second hasn't passed, there is nothing to do
|
||||
// If the time has been changed, set forceUpdate to trigger internal state updates
|
||||
if (correctedDelta == 0 && !forceUpdate) {
|
||||
return;
|
||||
}
|
||||
auto rest = systickDelta % configTICK_RATE_HZ;
|
||||
if (systickCounter >= rest) {
|
||||
previousSystickCounter = systickCounter - rest;
|
||||
} else {
|
||||
previousSystickCounter = 0xffffff - (rest - systickCounter);
|
||||
previousSystickCounter = static_cast<uint32_t>(portNRF_RTC_MAXTICKS) - (rest - systickCounter - 1);
|
||||
}
|
||||
|
||||
currentDateTime += std::chrono::seconds(correctedDelta);
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include <ctime>
|
||||
#include <string>
|
||||
#include "components/settings/Settings.h"
|
||||
#include <FreeRTOS.h>
|
||||
#include <semphr.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace System {
|
||||
|
@ -45,8 +47,6 @@ namespace Pinetime {
|
|||
*/
|
||||
void SetTimeZone(int8_t timezone, int8_t dst);
|
||||
|
||||
void UpdateTime(uint32_t systickCounter);
|
||||
|
||||
uint16_t Year() const {
|
||||
return 1900 + localTime.tm_year;
|
||||
}
|
||||
|
@ -124,12 +124,10 @@ namespace Pinetime {
|
|||
static const char* MonthShortToStringLow(Months month);
|
||||
static const char* DayOfWeekShortToStringLow(Days day);
|
||||
|
||||
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> CurrentDateTime() const {
|
||||
return currentDateTime;
|
||||
}
|
||||
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> CurrentDateTime();
|
||||
|
||||
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> UTCDateTime() const {
|
||||
return currentDateTime - std::chrono::seconds((tzOffset + dstOffset) * 15 * 60);
|
||||
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> UTCDateTime() {
|
||||
return CurrentDateTime() - std::chrono::seconds((tzOffset + dstOffset) * 15 * 60);
|
||||
}
|
||||
|
||||
std::chrono::seconds Uptime() const {
|
||||
|
@ -141,10 +139,14 @@ namespace Pinetime {
|
|||
std::string FormattedTime();
|
||||
|
||||
private:
|
||||
void UpdateTime(uint32_t systickCounter, bool forceUpdate);
|
||||
|
||||
std::tm localTime;
|
||||
int8_t tzOffset = 0;
|
||||
int8_t dstOffset = 0;
|
||||
|
||||
SemaphoreHandle_t mutex = nullptr;
|
||||
|
||||
uint32_t previousSystickCounter = 0;
|
||||
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> currentDateTime;
|
||||
std::chrono::seconds uptime {0};
|
||||
|
|
41
src/components/datetime/TODO.md
Normal file
41
src/components/datetime/TODO.md
Normal file
|
@ -0,0 +1,41 @@
|
|||
# Refactoring needed
|
||||
|
||||
## Context
|
||||
|
||||
The [PR #2041 - Continuous time updates](https://github.com/InfiniTimeOrg/InfiniTime/pull/2041) highlighted some
|
||||
limitations in the design of DateTimeController: the granularity of the time returned by `DateTime::CurrentDateTime()`
|
||||
is limited by the frequency at which SystemTask calls `DateTime::UpdateTime()`, which is currently set to 100ms.
|
||||
|
||||
@mark9064 provided more details
|
||||
in [this comment](https://github.com/InfiniTimeOrg/InfiniTime/pull/2041#issuecomment-2048528967).
|
||||
|
||||
The [PR #2041 - Continuous time updates](https://github.com/InfiniTimeOrg/InfiniTime/pull/2041) provided some changes
|
||||
to `DateTime` controller that improves the granularity of the time returned by `DateTime::CurrentDateTime()`.
|
||||
|
||||
However, the review showed that `DateTime` cannot be `const` anymore, even when it's only used to get the current time,
|
||||
since `DateTime::CurrentDateTime()` changes the internal state of the instance.
|
||||
|
||||
We tried to identify alternative implementation that would have maintained the "const correctness" but we eventually
|
||||
figured that this would lead to a re-design of `DateTime` which was out of scope of the initial PR (Continuous time
|
||||
updates and always on display).
|
||||
|
||||
So we decided to merge this PR #2041 and agree to fix/improve `DateTime` later on.
|
||||
|
||||
## What needs to be done?
|
||||
|
||||
Improve/redesign `DateTime` so that it
|
||||
|
||||
* provides a very granular (ideally down to the millisecond) date and time via `CurrentDateTime()`.
|
||||
* can be declared/passed as `const` when it's only used to **get** the time.
|
||||
* limits the use of mutex as much as possible (an ideal implementation would not use any mutex, but this might not be
|
||||
possible).
|
||||
* improves the design of `DateTime::Seconds()`, `DateTime::Minutes()`, `DateTime::Hours()`, etc as
|
||||
explained [in this comment](https://github.com/InfiniTimeOrg/InfiniTime/pull/2054#pullrequestreview-2037033105).
|
||||
|
||||
Once this redesign is implemented, all instances/references to `DateTime` should be reviewed and updated to use `const`
|
||||
where appropriate.
|
||||
|
||||
Please check the following PR to get more context about this redesign:
|
||||
|
||||
* [#2041 - Continuous time updates by @mark9064](https://github.com/InfiniTimeOrg/InfiniTime/pull/2041)
|
||||
* [#2054 - Continuous time update - Alternative implementation to #2041 by @JF002](https://github.com/InfiniTimeOrg/InfiniTime/pull/2054)
|
|
@ -124,17 +124,6 @@ namespace Pinetime {
|
|||
return settings.watchFaceInfineat.showSideCover;
|
||||
};
|
||||
|
||||
void SetInfineatShowAlarmStatus(bool show) {
|
||||
if (show != settings.watchFaceInfineat.showAlarmStatus) {
|
||||
settings.watchFaceInfineat.showAlarmStatus = show;
|
||||
settingsChanged = true;
|
||||
}
|
||||
};
|
||||
|
||||
bool GetInfineatShowAlarmStatus() const {
|
||||
return settings.watchFaceInfineat.showAlarmStatus;
|
||||
};
|
||||
|
||||
void SetInfineatColorIndex(int index) {
|
||||
if (index != settings.watchFaceInfineat.colorIndex) {
|
||||
settings.watchFaceInfineat.colorIndex = index;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "displayapp/screens/Metronome.h"
|
||||
#include "displayapp/screens/Music.h"
|
||||
#include "displayapp/screens/Navigation.h"
|
||||
#include "displayapp/screens/Calendar.h"
|
||||
#include "displayapp/screens/Notifications.h"
|
||||
#include "displayapp/screens/SystemInfo.h"
|
||||
#include "displayapp/screens/Tile.h"
|
||||
|
@ -125,6 +126,7 @@ void DisplayApp::Start(System::BootErrors error) {
|
|||
bootError = error;
|
||||
|
||||
lvgl.Init();
|
||||
motorController.Init();
|
||||
|
||||
if (error == System::BootErrors::TouchController) {
|
||||
LoadNewScreen(Apps::Error, DisplayApp::FullRefreshDirections::None);
|
||||
|
@ -150,7 +152,6 @@ void DisplayApp::Process(void* instance) {
|
|||
void DisplayApp::InitHw() {
|
||||
brightnessController.Init();
|
||||
ApplyBrightness();
|
||||
motorController.Init();
|
||||
lcd.Init();
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace Colors {
|
|||
static constexpr lv_color_t green = LV_COLOR_MAKE(0x0, 0xb0, 0x0);
|
||||
static constexpr lv_color_t blue = LV_COLOR_MAKE(0x0, 0x50, 0xff);
|
||||
static constexpr lv_color_t lightGray = LV_COLOR_MAKE(0xb0, 0xb0, 0xb0);
|
||||
static constexpr lv_color_t gray = LV_COLOR_MAKE(0x50, 0x50, 0x50);
|
||||
|
||||
static constexpr lv_color_t bg = LV_COLOR_MAKE(0x5d, 0x69, 0x7e);
|
||||
static constexpr lv_color_t bgAlt = LV_COLOR_MAKE(0x38, 0x38, 0x38);
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "displayapp/screens/WatchFaceAnalog.h"
|
||||
#include "displayapp/screens/WatchFaceCasioStyleG7710.h"
|
||||
#include "displayapp/screens/WatchFaceInfineat.h"
|
||||
#include "displayapp/screens/WatchFaceMeow.h"
|
||||
#include "displayapp/screens/WatchFacePineTimeStyle.h"
|
||||
#include "displayapp/screens/WatchFaceTerminal.h"
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace Pinetime {
|
|||
Twos,
|
||||
HeartRate,
|
||||
Navigation,
|
||||
Calendar,
|
||||
StopWatch,
|
||||
Metronome,
|
||||
Motion,
|
||||
|
@ -51,6 +52,7 @@ namespace Pinetime {
|
|||
PineTimeStyle,
|
||||
Terminal,
|
||||
Infineat,
|
||||
Meow,
|
||||
CasioStyleG7710,
|
||||
};
|
||||
|
||||
|
|
|
@ -8,12 +8,13 @@ else ()
|
|||
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::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::Navigation")
|
||||
#set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Weather")
|
||||
set(DEFAULT_USER_APP_TYPES "${DEFAULT_USER_APP_TYPES}, Apps::Calendar")
|
||||
#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 ()
|
||||
|
@ -21,10 +22,11 @@ endif ()
|
|||
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 "WatchFace::Meow")
|
||||
set(DEFAULT_WATCHFACE_TYPES "${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(WATCHFACE_TYPES "${DEFAULT_WATCHFACE_TYPES}" CACHE STRING "List of watch faces to build into the firmware")
|
||||
|
|
96
src/displayapp/screens/Calendar.cpp
Normal file
96
src/displayapp/screens/Calendar.cpp
Normal file
|
@ -0,0 +1,96 @@
|
|||
/* Copyright (C) 2024 thnikk, Boteium, JustScott
|
||||
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "displayapp/screens/Calendar.h"
|
||||
#include "components/datetime/DateTimeController.h"
|
||||
#include "displayapp/InfiniTimeTheme.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
Calendar::Calendar(Controllers::DateTime& dateTimeController) : dateTimeController {dateTimeController} {
|
||||
|
||||
// Create calendar object
|
||||
calendar = lv_calendar_create(lv_scr_act(), NULL);
|
||||
// Set size
|
||||
lv_obj_set_size(calendar, LV_HOR_RES, LV_VER_RES);
|
||||
// Set alignment
|
||||
lv_obj_align(calendar, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, -5);
|
||||
// Disable clicks
|
||||
lv_obj_set_click(calendar, false);
|
||||
|
||||
// Set style of today's date
|
||||
lv_obj_set_style_local_text_color(calendar, LV_CALENDAR_PART_DATE, LV_STATE_FOCUSED, Colors::deepOrange);
|
||||
|
||||
// Set style of inactive month's days
|
||||
lv_obj_set_style_local_text_color(calendar, LV_CALENDAR_PART_DATE, LV_STATE_DISABLED, Colors::gray);
|
||||
|
||||
// Get today's date
|
||||
current.year = static_cast<int>(dateTimeController.Year());
|
||||
current.month = static_cast<int>(dateTimeController.Month());
|
||||
current.day = static_cast<int>(dateTimeController.Day());
|
||||
|
||||
// Set today's date
|
||||
lv_calendar_set_today_date(calendar, ¤t);
|
||||
lv_calendar_set_showed_date(calendar, ¤t);
|
||||
}
|
||||
|
||||
bool Calendar::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||
switch (event) {
|
||||
case TouchEvents::SwipeLeft: {
|
||||
if (current.month == 12) {
|
||||
current.month = 1;
|
||||
current.year++;
|
||||
} else {
|
||||
current.month++;
|
||||
}
|
||||
|
||||
lv_calendar_set_showed_date(calendar, ¤t);
|
||||
return true;
|
||||
}
|
||||
case TouchEvents::SwipeRight: {
|
||||
if (current.month == 1) {
|
||||
current.month = 12;
|
||||
current.year--;
|
||||
} else {
|
||||
current.month--;
|
||||
}
|
||||
|
||||
lv_calendar_set_showed_date(calendar, ¤t);
|
||||
return true;
|
||||
}
|
||||
/*
|
||||
case TouchEvents::SwipeUp: {
|
||||
current.year++;
|
||||
lv_calendar_set_showed_date(calendar, ¤t);
|
||||
return true;
|
||||
}
|
||||
case TouchEvents::SwipeDown: {
|
||||
current.year--;
|
||||
lv_calendar_set_showed_date(calendar, ¤t);
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
default: {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Calendar::~Calendar() {
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
59
src/displayapp/screens/Calendar.h
Normal file
59
src/displayapp/screens/Calendar.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/* Copyright (C) 2024 thnikk, Boteium, JustScott
|
||||
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "displayapp/apps/Apps.h"
|
||||
#include "displayapp/Controllers.h"
|
||||
#include "displayapp/screens/Screen.h"
|
||||
#include "components/datetime/DateTimeController.h"
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
#include "Symbols.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Controllers {
|
||||
class Settings;
|
||||
}
|
||||
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
class Calendar : public Screen {
|
||||
public:
|
||||
Calendar(Controllers::DateTime& dateTimeController);
|
||||
~Calendar() override;
|
||||
|
||||
private:
|
||||
bool OnTouchEvent(TouchEvents event);
|
||||
Controllers::DateTime& dateTimeController;
|
||||
lv_obj_t* calendar;
|
||||
lv_calendar_date_t current;
|
||||
};
|
||||
}
|
||||
|
||||
template <>
|
||||
struct AppTraits<Apps::Calendar> {
|
||||
static constexpr Apps app = Apps::Calendar;
|
||||
static constexpr const char* icon = Screens::Symbols::calendar;
|
||||
|
||||
static Screens::Screen* Create(AppControllers& controllers) {
|
||||
return new Screens::Calendar(controllers.dateTimeController);
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
10
src/displayapp/screens/README.md
Normal file
10
src/displayapp/screens/README.md
Normal file
|
@ -0,0 +1,10 @@
|
|||
# Add a new watchface :
|
||||
## Modify the following files with the names of your source files :
|
||||
|
||||
- /src/displayapp/apps/Apps.h.in
|
||||
- /src/components/settings/Settings.h
|
||||
- /src/displayapp/UserApps.h
|
||||
- /src/displayapp/apps/CMakeLists.txt
|
||||
- CMakelists.txt
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ namespace Pinetime {
|
|||
|
||||
BatteryIcon batteryIcon;
|
||||
|
||||
const Controllers::DateTime& dateTimeController;
|
||||
Controllers::DateTime& dateTimeController;
|
||||
const Controllers::Battery& batteryController;
|
||||
const Controllers::Ble& bleController;
|
||||
Controllers::NotificationManager& notificationManager;
|
||||
|
|
|
@ -4,10 +4,12 @@
|
|||
#include <cstdio>
|
||||
#include "displayapp/screens/BatteryIcon.h"
|
||||
#include "displayapp/screens/BleIcon.h"
|
||||
#include "displayapp/screens/AlarmIcon.h"
|
||||
#include "displayapp/screens/NotificationIcon.h"
|
||||
#include "displayapp/screens/Symbols.h"
|
||||
#include "components/battery/BatteryController.h"
|
||||
#include "components/ble/BleController.h"
|
||||
#include "components/alarm/AlarmController.h"
|
||||
#include "components/ble/NotificationManager.h"
|
||||
#include "components/heartrate/HeartRateController.h"
|
||||
#include "components/motion/MotionController.h"
|
||||
|
@ -17,6 +19,7 @@ using namespace Pinetime::Applications::Screens;
|
|||
WatchFaceCasioStyleG7710::WatchFaceCasioStyleG7710(Controllers::DateTime& dateTimeController,
|
||||
const Controllers::Battery& batteryController,
|
||||
const Controllers::Ble& bleController,
|
||||
Controllers::AlarmController& alarmController,
|
||||
Controllers::NotificationManager& notificatioManager,
|
||||
Controllers::Settings& settingsController,
|
||||
Controllers::HeartRateController& heartRateController,
|
||||
|
@ -27,6 +30,7 @@ WatchFaceCasioStyleG7710::WatchFaceCasioStyleG7710(Controllers::DateTime& dateTi
|
|||
dateTimeController {dateTimeController},
|
||||
batteryController {batteryController},
|
||||
bleController {bleController},
|
||||
alarmController {alarmController},
|
||||
notificatioManager {notificatioManager},
|
||||
settingsController {settingsController},
|
||||
heartRateController {heartRateController},
|
||||
|
@ -168,6 +172,23 @@ WatchFaceCasioStyleG7710::WatchFaceCasioStyleG7710(Controllers::DateTime& dateTi
|
|||
lv_label_set_text_static(stepIcon, Symbols::shoe);
|
||||
lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||
|
||||
alarmIcon = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(alarmIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text);
|
||||
lv_label_set_text_static(alarmIcon, Symbols::notbell);
|
||||
lv_obj_align(alarmIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2);
|
||||
|
||||
labelAlarm = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(labelAlarm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text);
|
||||
// lv_obj_set_style_local_text_font(labelAlarm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_teko);
|
||||
lv_obj_align(labelAlarm, alarmIcon, LV_ALIGN_OUT_RIGHT_MID, 3, 0);
|
||||
lv_label_set_text_static(labelAlarm, "00:00");
|
||||
|
||||
labelTimeAmPmAlarm = lv_label_create(lv_scr_act(), nullptr);
|
||||
// lv_obj_set_style_local_text_font(labelTimeAmPmAlarm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_teko);
|
||||
lv_label_set_text_static(labelTimeAmPmAlarm, "");
|
||||
lv_obj_set_style_local_text_color(labelTimeAmPmAlarm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, color_text);
|
||||
lv_obj_align(labelTimeAmPmAlarm, labelAlarm, LV_ALIGN_OUT_RIGHT_MID, 3, 0);
|
||||
|
||||
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
|
||||
Refresh();
|
||||
}
|
||||
|
@ -310,6 +331,41 @@ void WatchFaceCasioStyleG7710::Refresh() {
|
|||
lv_obj_realign(stepValue);
|
||||
lv_obj_realign(stepIcon);
|
||||
}
|
||||
alarmState = alarmController.State()==Pinetime::Controllers::AlarmController::AlarmState::Set;
|
||||
// sets the icon as bell or barred bell
|
||||
lv_label_set_text_static(alarmIcon, AlarmIcon::GetIcon(alarmState));
|
||||
//displays the time of the alarm or nothing if the alarm is not set
|
||||
if (alarmState) {
|
||||
uint8_t alarmHours = alarmController.Hours();
|
||||
uint8_t alarmMinutes = alarmController.Minutes();
|
||||
//handles the am pm format.
|
||||
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
|
||||
char ampmChar[3] = "AM";
|
||||
if (alarmHours == 0) {
|
||||
alarmHours = 12;
|
||||
} else if (alarmHours == 12) {
|
||||
ampmChar[0]='P';
|
||||
} else if (alarmHours > 12) {
|
||||
alarmHours = alarmHours - 12;
|
||||
ampmChar[0]='P';
|
||||
}
|
||||
lv_label_set_text(labelTimeAmPmAlarm, ampmChar);
|
||||
// lv_obj_set_style_local_text_font(labelTimeAmPmAlarm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_teko);
|
||||
lv_obj_align(labelTimeAmPmAlarm, labelAlarm, LV_ALIGN_OUT_RIGHT_MID, 3, 0);
|
||||
}
|
||||
|
||||
lv_label_set_text_fmt(labelAlarm, "%02d:%02d", alarmHours, alarmMinutes);
|
||||
|
||||
lv_obj_align(alarmIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2);
|
||||
lv_obj_align(labelAlarm, alarmIcon, LV_ALIGN_OUT_RIGHT_MID, 3, 0);
|
||||
|
||||
}
|
||||
else {
|
||||
lv_label_set_text_static(labelAlarm, Symbols::none);
|
||||
lv_obj_align(alarmIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 5, -2);
|
||||
lv_obj_align(labelAlarm, alarmIcon, LV_ALIGN_OUT_RIGHT_MID, 3, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool WatchFaceCasioStyleG7710::IsAvailable(Pinetime::Controllers::FS& filesystem) {
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace Pinetime {
|
|||
WatchFaceCasioStyleG7710(Controllers::DateTime& dateTimeController,
|
||||
const Controllers::Battery& batteryController,
|
||||
const Controllers::Ble& bleController,
|
||||
Controllers::AlarmController& alarmController,
|
||||
Controllers::NotificationManager& notificatioManager,
|
||||
Controllers::Settings& settingsController,
|
||||
Controllers::HeartRateController& heartRateController,
|
||||
|
@ -46,6 +47,7 @@ namespace Pinetime {
|
|||
Utility::DirtyValue<bool> powerPresent {};
|
||||
Utility::DirtyValue<bool> bleState {};
|
||||
Utility::DirtyValue<bool> bleRadioEnabled {};
|
||||
bool alarmState {};
|
||||
Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>> currentDateTime {};
|
||||
Utility::DirtyValue<uint32_t> stepCount {};
|
||||
Utility::DirtyValue<uint8_t> heartbeat {};
|
||||
|
@ -76,6 +78,9 @@ namespace Pinetime {
|
|||
lv_obj_t* line_day_of_year;
|
||||
lv_obj_t* backgroundLabel;
|
||||
lv_obj_t* bleIcon;
|
||||
lv_obj_t* labelAlarm;
|
||||
lv_obj_t* labelTimeAmPmAlarm;
|
||||
lv_obj_t* alarmIcon;
|
||||
lv_obj_t* batteryPlug;
|
||||
lv_obj_t* label_battery_value;
|
||||
lv_obj_t* heartbeatIcon;
|
||||
|
@ -90,6 +95,7 @@ namespace Pinetime {
|
|||
Controllers::DateTime& dateTimeController;
|
||||
const Controllers::Battery& batteryController;
|
||||
const Controllers::Ble& bleController;
|
||||
Controllers::AlarmController& alarmController;
|
||||
Controllers::NotificationManager& notificatioManager;
|
||||
Controllers::Settings& settingsController;
|
||||
Controllers::HeartRateController& heartRateController;
|
||||
|
@ -111,6 +117,7 @@ namespace Pinetime {
|
|||
return new Screens::WatchFaceCasioStyleG7710(controllers.dateTimeController,
|
||||
controllers.batteryController,
|
||||
controllers.bleController,
|
||||
controllers.alarmController,
|
||||
controllers.notificationManager,
|
||||
controllers.settingsController,
|
||||
controllers.heartRateController,
|
||||
|
|
683
src/displayapp/screens/WatchFaceMeow.cpp
Normal file
683
src/displayapp/screens/WatchFaceMeow.cpp
Normal file
|
@ -0,0 +1,683 @@
|
|||
/*********************************************************/
|
||||
/*
|
||||
* I modified the watchface Infineat :
|
||||
* - added alarm info on the screen
|
||||
* - modified the colors
|
||||
* - modified step count icon
|
||||
* Except colors, modifications are at line 254 and 500
|
||||
*/
|
||||
/*********************************************************/
|
||||
|
||||
|
||||
|
||||
#include "displayapp/screens/WatchFaceMeow.h"
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <cstdio>
|
||||
#include "displayapp/screens/Symbols.h"
|
||||
#include "displayapp/screens/BleIcon.h"
|
||||
//#include "displayapp/screens/AlarmIcon.h"
|
||||
#include "components/settings/Settings.h"
|
||||
#include "components/battery/BatteryController.h"
|
||||
#include "components/ble/BleController.h"
|
||||
#include "components/alarm/AlarmController.h"
|
||||
#include "components/ble/NotificationManager.h"
|
||||
#include "components/motion/MotionController.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
namespace {
|
||||
void event_handler(lv_obj_t* obj, lv_event_t event) {
|
||||
auto* screen = static_cast<WatchFaceMeow*>(obj->user_data);
|
||||
screen->UpdateSelected(obj, event);
|
||||
}
|
||||
|
||||
enum class colors {
|
||||
orange,
|
||||
blue,
|
||||
green,
|
||||
rainbow,
|
||||
vivid,
|
||||
pink,
|
||||
nordGreen,
|
||||
};
|
||||
|
||||
constexpr int nColors = 7; // must match number of colors in InfineatColorsColors
|
||||
|
||||
constexpr int nLines = WatchFaceMeow::nLines;
|
||||
|
||||
constexpr std::array<lv_color_t, nLines> orangeColors = {LV_COLOR_MAKE(0xfd, 0x87, 0x2b),
|
||||
LV_COLOR_MAKE(0xdb, 0x33, 0x16),
|
||||
LV_COLOR_MAKE(0x6f, 0x10, 0x00),
|
||||
LV_COLOR_MAKE(0xfd, 0x7a, 0x0a),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xe8, 0x51, 0x02),
|
||||
LV_COLOR_MAKE(0xea, 0x1c, 0x00)};
|
||||
constexpr std::array<lv_color_t, nLines> blueColors = {LV_COLOR_MAKE(0xe7, 0xf8, 0xff),
|
||||
LV_COLOR_MAKE(0x22, 0x32, 0xd0),
|
||||
LV_COLOR_MAKE(0x18, 0x2a, 0x8b),
|
||||
LV_COLOR_MAKE(0xe7, 0xf8, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0x59, 0x91, 0xff),
|
||||
LV_COLOR_MAKE(0x16, 0x36, 0xff)};
|
||||
constexpr std::array<lv_color_t, nLines> greenColors = {LV_COLOR_MAKE(0xb8, 0xff, 0x9b),
|
||||
LV_COLOR_MAKE(0x08, 0x86, 0x08),
|
||||
LV_COLOR_MAKE(0x00, 0x4a, 0x00),
|
||||
LV_COLOR_MAKE(0xb8, 0xff, 0x9b),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0x62, 0xd5, 0x15),
|
||||
LV_COLOR_MAKE(0x00, 0x74, 0x00)};
|
||||
//added comments to say which color is which triangle
|
||||
constexpr std::array<lv_color_t, nLines> rainbowColors = {LV_COLOR_MAKE(0x2d, 0xa4, 0x00), //green, small triangle on top
|
||||
LV_COLOR_MAKE(0xac, 0x09, 0xc4), //purple, smalltriangle in the bottom half part on the clock display side
|
||||
LV_COLOR_MAKE(0xfe, 0x03, 0x03), //red, the two small triangles above and below the battery
|
||||
LV_COLOR_MAKE(0x0d, 0x57, 0xff), //blue, the small triangle at the bottom
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xe0, 0xb9, 0x00), //Yellow, large triangle on top left
|
||||
LV_COLOR_MAKE(0xe8, 0x51, 0x02)}; //orange, large triangle on bottom left
|
||||
|
||||
// Add new colors, still rainbow but more pastel like
|
||||
constexpr std::array<lv_color_t, nLines> rainbowVividColors ={LV_COLOR_MAKE(0xa5, 0xeb, 0x64),
|
||||
LV_COLOR_MAKE(0xfc, 0x42, 0xb5),
|
||||
LV_COLOR_MAKE(0xe7, 0xc1, 0xff),
|
||||
LV_COLOR_MAKE(0x11, 0xdf, 0xfa),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xec, 0x5d),
|
||||
LV_COLOR_MAKE(0xff, 0x93, 0xaf)};
|
||||
|
||||
constexpr std::array<lv_color_t, nLines> pinkColors = {LV_COLOR_MAKE(0xff, 0xe5, 0xec),
|
||||
LV_COLOR_MAKE(0xff, 0xb3, 0xc6),
|
||||
LV_COLOR_MAKE(0xfb, 0x6f, 0x92),
|
||||
LV_COLOR_MAKE(0xff, 0xe5, 0xec),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xc2, 0xd1),
|
||||
LV_COLOR_MAKE(0xff, 0x8f, 0xab)};
|
||||
constexpr std::array<lv_color_t, nLines> nordGreenColors = {LV_COLOR_MAKE(0xd5, 0xf0, 0xe9),
|
||||
LV_COLOR_MAKE(0x23, 0x83, 0x73),
|
||||
LV_COLOR_MAKE(0x1d, 0x41, 0x3f),
|
||||
LV_COLOR_MAKE(0xd5, 0xf0, 0xe9),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0xff, 0xff, 0xff),
|
||||
LV_COLOR_MAKE(0x2f, 0xb8, 0xa2),
|
||||
LV_COLOR_MAKE(0x11, 0x70, 0x5a)};
|
||||
|
||||
//define colors for texts and symbols
|
||||
// gray is used for text symbols and time. I changed it to pink, because I can.
|
||||
//static constexpr lv_color_t grayColor = LV_COLOR_MAKE(0x99, 0x99, 0x99);
|
||||
static constexpr lv_color_t pinkColor = LV_COLOR_MAKE(0xfc, 0x42, 0xb5);
|
||||
|
||||
constexpr const std::array<lv_color_t, nLines>* returnColor(colors color) {
|
||||
if (color == colors::orange) {
|
||||
return &orangeColors;
|
||||
}
|
||||
if (color == colors::blue) {
|
||||
return &blueColors;
|
||||
}
|
||||
if (color == colors::green) {
|
||||
return &greenColors;
|
||||
}
|
||||
if (color == colors::rainbow) {
|
||||
return &rainbowColors;
|
||||
}
|
||||
if (color == colors::vivid) {
|
||||
return &rainbowVividColors;
|
||||
}
|
||||
if (color == colors::pink) {
|
||||
return &pinkColors;
|
||||
}
|
||||
return &nordGreenColors;
|
||||
}
|
||||
}
|
||||
|
||||
WatchFaceMeow::WatchFaceMeow(Controllers::DateTime& dateTimeController,
|
||||
const Controllers::Battery& batteryController,
|
||||
const Controllers::Ble& bleController,
|
||||
Controllers::AlarmController& alarmController,
|
||||
Controllers::Timer& timerController,
|
||||
Controllers::NotificationManager& notificationManager,
|
||||
Controllers::Settings& settingsController,
|
||||
Controllers::MotionController& motionController,
|
||||
Controllers::FS& filesystem)
|
||||
: currentDateTime {{}},
|
||||
dateTimeController {dateTimeController},
|
||||
batteryController {batteryController},
|
||||
bleController {bleController},
|
||||
alarmController {alarmController},
|
||||
timerController {timerController},
|
||||
notificationManager {notificationManager},
|
||||
settingsController {settingsController},
|
||||
motionController {motionController} {
|
||||
lfs_file f = {};
|
||||
if (filesystem.FileOpen(&f, "/fonts/teko.bin", LFS_O_RDONLY) >= 0) {
|
||||
filesystem.FileClose(&f);
|
||||
font_teko = lv_font_load("F:/fonts/teko.bin");
|
||||
}
|
||||
|
||||
if (filesystem.FileOpen(&f, "/fonts/bebas.bin", LFS_O_RDONLY) >= 0) {
|
||||
filesystem.FileClose(&f);
|
||||
font_bebas = lv_font_load("F:/fonts/bebas.bin");
|
||||
}
|
||||
|
||||
// Side Cover
|
||||
//paires de points pour chaque ligne
|
||||
// les lignes sont pas les contours des triangles, elles sont des grosses bandes superposées
|
||||
|
||||
static constexpr lv_point_t linePoints[nLines][2] = {{{30, 25}, {68, -8}}, //1 small triangle on top
|
||||
{{26, 167}, {43, 216}}, //2 purple, smalltriangle in the bottom half part on the clock display side
|
||||
{{27, 40}, {27, 196}},// 3 small triangles up above and below battery
|
||||
{{12, 182}, {65, 249}}, //4 most bottom right triangle
|
||||
{{17, 97}, {17, 147}}, // 5 left part of battery zone, overlapped after by the large triangles
|
||||
{{16, 81}, {42, 127}}, //6 upper part of battery zone
|
||||
{{16, 163}, {42, 118}}, //7 lower part of battery zone
|
||||
{{-20, 124}, {25, -11}}, //8 large upper triangle
|
||||
{{-29, 89}, {27, 254}}}; //9 large lower triangle
|
||||
//largeur des bandes
|
||||
static constexpr lv_style_int_t lineWidths[nLines] = {18, 15, 14, 22, 20, 18, 18, 52, 48};
|
||||
|
||||
const std::array<lv_color_t, nLines>* colors = returnColor(static_cast<enum colors>(settingsController.GetInfineatColorIndex()));
|
||||
for (int i = 0; i < nLines; i++) {
|
||||
lines[i] = lv_line_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_line_width(lines[i], LV_LINE_PART_MAIN, LV_STATE_DEFAULT, lineWidths[i]);
|
||||
lv_color_t color = (*colors)[i];
|
||||
lv_obj_set_style_local_line_color(lines[i], LV_LINE_PART_MAIN, LV_STATE_DEFAULT, color);
|
||||
lv_line_set_points(lines[i], linePoints[i], 2);
|
||||
}
|
||||
|
||||
//Battery indicator
|
||||
logoCat = lv_img_create(lv_scr_act(), nullptr);
|
||||
lv_img_set_src(logoCat, "F:/images/cat_small.bin");
|
||||
lv_obj_set_pos(logoCat, 12, 108);
|
||||
//adjust position for cat
|
||||
lineBattery = lv_line_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_line_width(lineBattery, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 30);
|
||||
lv_obj_set_style_local_line_color(lineBattery, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, (*colors)[4]);
|
||||
lv_obj_set_style_local_line_opa(lineBattery, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, 190);
|
||||
lineBatteryPoints[0] = {27, 107};//27 = image x offset + image width / 2
|
||||
lineBatteryPoints[1] = {27, 108};// the line covering the image is initialized as 1 px high
|
||||
lv_line_set_points(lineBattery, lineBatteryPoints, 2);
|
||||
lv_obj_move_foreground(lineBattery);
|
||||
|
||||
notificationIcon = lv_obj_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_bg_color(notificationIcon, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, (*colors)[7]);
|
||||
lv_obj_set_style_local_radius(notificationIcon, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE);
|
||||
lv_obj_set_size(notificationIcon, 13, 13);
|
||||
lv_obj_set_hidden(notificationIcon, true);
|
||||
|
||||
if (!settingsController.GetInfineatShowSideCover()) {
|
||||
ToggleBatteryIndicatorColor(false);
|
||||
for (auto& line : lines) {
|
||||
lv_obj_set_hidden(line, true);
|
||||
}
|
||||
}
|
||||
|
||||
timeContainer = lv_obj_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_bg_opa(timeContainer, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
|
||||
lv_obj_set_size(timeContainer, 185, 185);
|
||||
lv_obj_align(timeContainer, lv_scr_act(), LV_ALIGN_CENTER, 0, -10);
|
||||
|
||||
labelHour = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_label_set_text_static(labelHour, "01");
|
||||
lv_obj_set_style_local_text_font(labelHour, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_bebas);
|
||||
lv_obj_set_style_local_text_color(labelHour, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, pinkColor);
|
||||
lv_obj_align(labelHour, timeContainer, LV_ALIGN_IN_TOP_MID, 0, 0);
|
||||
|
||||
labelMinutes = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_font(labelMinutes, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_bebas);
|
||||
lv_obj_set_style_local_text_color(labelMinutes, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, pinkColor);
|
||||
lv_label_set_text_static(labelMinutes, "00");
|
||||
lv_obj_align(labelMinutes, timeContainer, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
|
||||
|
||||
labelTimeAmPm = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_font(labelTimeAmPm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_teko);
|
||||
lv_obj_set_style_local_text_color(labelTimeAmPm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, pinkColor);
|
||||
|
||||
lv_label_set_text_static(labelTimeAmPm, "");
|
||||
lv_obj_align(labelTimeAmPm, timeContainer, LV_ALIGN_OUT_RIGHT_TOP, 0, 15);
|
||||
|
||||
dateContainer = lv_obj_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_bg_opa(dateContainer, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
|
||||
lv_obj_set_size(dateContainer, 60, 30);
|
||||
lv_obj_align(dateContainer, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 5);
|
||||
|
||||
labelDate = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(labelDate, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, pinkColor);
|
||||
lv_obj_set_style_local_text_font(labelDate, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_teko);
|
||||
lv_obj_align(labelDate, dateContainer, LV_ALIGN_IN_TOP_MID, 0, 0);
|
||||
lv_label_set_text_static(labelDate, "Mon 01");
|
||||
|
||||
bleIcon = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, pinkColor);
|
||||
lv_label_set_text_static(bleIcon, Symbols::bluetooth);
|
||||
lv_obj_align(bleIcon, dateContainer, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
|
||||
|
||||
|
||||
// Based on existing code, I understand that items on the screen (date, bluteooth status..)
|
||||
// are declared here with default states, and later below the state (date, ...) is assigned
|
||||
// So I do the same to add the alarm status : I put a symbol that has a default value
|
||||
// and a text that has a default value
|
||||
|
||||
// text
|
||||
labelAlarm = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(labelAlarm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, pinkColor);
|
||||
lv_obj_set_style_local_text_font(labelAlarm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_teko);
|
||||
//lv_obj_align(labelAlarm, dateContainer, LV_ALIGN_OUT_BOTTOM_MID, -10, 0);
|
||||
lv_obj_align(labelAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -3, 0);
|
||||
lv_label_set_text_static(labelAlarm, "00:00");
|
||||
|
||||
labelTimeAmPmAlarm = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_font(labelTimeAmPmAlarm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_teko);
|
||||
lv_label_set_text_static(labelTimeAmPmAlarm, "");
|
||||
lv_obj_set_style_local_text_color(labelTimeAmPmAlarm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, pinkColor);
|
||||
lv_obj_align(labelTimeAmPmAlarm, labelAlarm, LV_ALIGN_OUT_TOP_RIGHT, 0, 0);
|
||||
|
||||
// symbol
|
||||
alarmIcon = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(alarmIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, pinkColor);
|
||||
lv_label_set_text_static(alarmIcon, Symbols::zzz);
|
||||
lv_obj_align(alarmIcon, labelAlarm, LV_ALIGN_OUT_LEFT_MID, -3, 0);
|
||||
|
||||
// don't show the icons jsut set if we don't show alarm status
|
||||
if (!settingsController.GetInfineatShowAlarmStatus()) {
|
||||
lv_obj_set_hidden(labelAlarm, true);
|
||||
lv_obj_set_hidden(alarmIcon, true);
|
||||
lv_obj_set_hidden(labelTimeAmPmAlarm, true);
|
||||
}
|
||||
|
||||
// text
|
||||
labelTimer = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(labelTimer, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, pinkColor);
|
||||
lv_obj_set_style_local_text_font(labelTimer, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_teko);
|
||||
//lv_obj_align(labelAlarm, dateContainer, LV_ALIGN_OUT_BOTTOM_MID, -10, 0);
|
||||
lv_obj_align(labelAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -3, 0);
|
||||
lv_label_set_text_static(labelTimer, "00:00");
|
||||
|
||||
// symbol
|
||||
timerIcon = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(timerIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, pinkColor);
|
||||
lv_label_set_text_static(timerIcon, Symbols::hourGlass);
|
||||
lv_obj_align(timerIcon, labelTimer, LV_ALIGN_OUT_LEFT_MID, -3, 0);
|
||||
|
||||
// don't show the icons jsut set if we don't show alarm status
|
||||
if (!settingsController.GetInfineatShowAlarmStatus()) {
|
||||
lv_obj_set_hidden(labelTimer, true);
|
||||
lv_obj_set_hidden(timerIcon, true);
|
||||
}
|
||||
|
||||
stepValue = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, pinkColor);
|
||||
lv_obj_set_style_local_text_font(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_teko);
|
||||
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 10, 0);
|
||||
lv_label_set_text_static(stepValue, "0");
|
||||
|
||||
pawIcon = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(pawIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, pinkColor);
|
||||
lv_label_set_text_static(pawIcon, Symbols::paw);
|
||||
lv_obj_align(pawIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||
|
||||
|
||||
// Setting buttons
|
||||
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_70);
|
||||
lv_obj_t* lblClose = lv_label_create(btnClose, nullptr);
|
||||
lv_label_set_text_static(lblClose, "X");
|
||||
lv_obj_set_event_cb(btnClose, event_handler);
|
||||
lv_obj_set_hidden(btnClose, true);
|
||||
|
||||
btnNextColor = lv_btn_create(lv_scr_act(), nullptr);
|
||||
btnNextColor->user_data = this;
|
||||
lv_obj_set_size(btnNextColor, 60, 60);
|
||||
lv_obj_align(btnNextColor, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -15, 0);
|
||||
lv_obj_set_style_local_bg_opa(btnNextColor, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_70);
|
||||
lv_obj_t* lblNextColor = lv_label_create(btnNextColor, nullptr);
|
||||
lv_label_set_text_static(lblNextColor, ">");
|
||||
lv_obj_set_event_cb(btnNextColor, event_handler);
|
||||
lv_obj_set_hidden(btnNextColor, true);
|
||||
|
||||
btnPrevColor = lv_btn_create(lv_scr_act(), nullptr);
|
||||
btnPrevColor->user_data = this;
|
||||
lv_obj_set_size(btnPrevColor, 60, 60);
|
||||
lv_obj_align(btnPrevColor, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 15, 0);
|
||||
lv_obj_set_style_local_bg_opa(btnPrevColor, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_70);
|
||||
lv_obj_t* lblPrevColor = lv_label_create(btnPrevColor, nullptr);
|
||||
lv_label_set_text_static(lblPrevColor, "<");
|
||||
lv_obj_set_event_cb(btnPrevColor, event_handler);
|
||||
lv_obj_set_hidden(btnPrevColor, true);
|
||||
|
||||
btnToggleCover = lv_btn_create(lv_scr_act(), nullptr);
|
||||
btnToggleCover->user_data = this;
|
||||
lv_obj_set_size(btnToggleCover, 60, 60);
|
||||
lv_obj_align(btnToggleCover, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_local_bg_opa(btnToggleCover, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_70);
|
||||
const char* labelToggle = settingsController.GetInfineatShowSideCover() ? "ON" : "OFF";
|
||||
lblToggle = lv_label_create(btnToggleCover, nullptr);
|
||||
lv_label_set_text_static(lblToggle, labelToggle);
|
||||
lv_obj_set_event_cb(btnToggleCover, event_handler);
|
||||
lv_obj_set_hidden(btnToggleCover, true);
|
||||
|
||||
btnToggleAlarm = lv_btn_create(lv_scr_act(), nullptr);
|
||||
btnToggleAlarm->user_data = this;
|
||||
lv_obj_set_size(btnToggleAlarm, 60, 60);
|
||||
lv_obj_align(btnToggleAlarm, lv_scr_act(), LV_ALIGN_CENTER, 0, 80);
|
||||
lv_obj_set_style_local_bg_opa(btnToggleAlarm, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_70);
|
||||
const char* labelToggleAlarm = settingsController.GetInfineatShowAlarmStatus() ? Symbols::bell : Symbols::notbell;
|
||||
lblAlarm = lv_label_create(btnToggleAlarm, nullptr);
|
||||
lv_label_set_text_static(lblAlarm, labelToggleAlarm);
|
||||
lv_obj_set_event_cb(btnToggleAlarm, event_handler);
|
||||
lv_obj_set_hidden(btnToggleAlarm, true);
|
||||
|
||||
// Button to access the settings
|
||||
btnSettings = lv_btn_create(lv_scr_act(), nullptr);
|
||||
btnSettings->user_data = this;
|
||||
lv_obj_set_size(btnSettings, 150, 150);
|
||||
lv_obj_align(btnSettings, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
|
||||
lv_obj_set_style_local_radius(btnSettings, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 30);
|
||||
lv_obj_set_style_local_bg_opa(btnSettings, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_70);
|
||||
lv_obj_set_event_cb(btnSettings, event_handler);
|
||||
labelBtnSettings = lv_label_create(btnSettings, nullptr);
|
||||
lv_obj_set_style_local_text_font(labelBtnSettings, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48);
|
||||
lv_label_set_text_static(labelBtnSettings, Symbols::settings);
|
||||
lv_obj_set_hidden(btnSettings, true);
|
||||
|
||||
taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
WatchFaceMeow::~WatchFaceMeow() {
|
||||
lv_task_del(taskRefresh);
|
||||
|
||||
if (font_bebas != nullptr) {
|
||||
lv_font_free(font_bebas);
|
||||
}
|
||||
if (font_teko != nullptr) {
|
||||
lv_font_free(font_teko);
|
||||
}
|
||||
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
bool WatchFaceMeow::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||
if ((event == Pinetime::Applications::TouchEvents::LongTap) && lv_obj_get_hidden(btnSettings)) {
|
||||
lv_obj_set_hidden(btnSettings, false);
|
||||
savedTick = lv_tick_get();
|
||||
return true;
|
||||
}
|
||||
// Prevent screen from sleeping when double tapping with settings on
|
||||
if ((event == Pinetime::Applications::TouchEvents::DoubleTap) && !lv_obj_get_hidden(btnClose)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WatchFaceMeow::CloseMenu() {
|
||||
settingsController.SaveSettings();
|
||||
lv_obj_set_hidden(btnClose, true);
|
||||
lv_obj_set_hidden(btnNextColor, true);
|
||||
lv_obj_set_hidden(btnPrevColor, true);
|
||||
lv_obj_set_hidden(btnToggleCover, true);
|
||||
lv_obj_set_hidden(btnToggleAlarm, true);
|
||||
}
|
||||
|
||||
bool WatchFaceMeow::OnButtonPushed() {
|
||||
if (!lv_obj_get_hidden(btnClose)) {
|
||||
CloseMenu();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void WatchFaceMeow::UpdateSelected(lv_obj_t* object, lv_event_t event) {
|
||||
if (event == LV_EVENT_CLICKED) {
|
||||
bool showSideCover = settingsController.GetInfineatShowSideCover();
|
||||
int colorIndex = settingsController.GetInfineatColorIndex();
|
||||
bool showAlarmStatus = settingsController.GetInfineatShowAlarmStatus();
|
||||
|
||||
if (object == btnSettings) {
|
||||
lv_obj_set_hidden(btnSettings, true);
|
||||
lv_obj_set_hidden(btnClose, false);
|
||||
lv_obj_set_hidden(btnNextColor, !showSideCover);
|
||||
lv_obj_set_hidden(btnPrevColor, !showSideCover);
|
||||
lv_obj_set_hidden(btnToggleCover, false);
|
||||
lv_obj_set_hidden(btnToggleAlarm, false);
|
||||
}
|
||||
if (object == btnClose) {
|
||||
CloseMenu();
|
||||
}
|
||||
if (object == btnToggleCover) {
|
||||
settingsController.SetInfineatShowSideCover(!showSideCover);
|
||||
ToggleBatteryIndicatorColor(!showSideCover);
|
||||
for (auto& line : lines) {
|
||||
lv_obj_set_hidden(line, showSideCover);
|
||||
}
|
||||
lv_obj_set_hidden(btnNextColor, showSideCover);
|
||||
lv_obj_set_hidden(btnPrevColor, showSideCover);
|
||||
const char* labelToggle = showSideCover ? "OFF" : "ON";
|
||||
lv_label_set_text_static(lblToggle, labelToggle);
|
||||
}
|
||||
|
||||
if (object == btnToggleAlarm) {
|
||||
settingsController.SetInfineatShowAlarmStatus(!showAlarmStatus);
|
||||
bool newShowAlarmStatus = settingsController.GetInfineatShowAlarmStatus();
|
||||
lv_obj_set_hidden(labelAlarm, !newShowAlarmStatus);
|
||||
lv_obj_set_hidden(alarmIcon, !newShowAlarmStatus);
|
||||
lv_obj_set_hidden(labelTimeAmPmAlarm, !newShowAlarmStatus);
|
||||
const char* labelToggleAlarm = newShowAlarmStatus ? Symbols::bell : Symbols::notbell;
|
||||
lv_label_set_text_static(lblAlarm, labelToggleAlarm);
|
||||
}
|
||||
|
||||
|
||||
if (object == btnNextColor) {
|
||||
colorIndex = (colorIndex + 1) % nColors;
|
||||
settingsController.SetInfineatColorIndex(colorIndex);
|
||||
}
|
||||
if (object == btnPrevColor) {
|
||||
colorIndex -= 1;
|
||||
if (colorIndex < 0)
|
||||
colorIndex = nColors - 1;
|
||||
settingsController.SetInfineatColorIndex(colorIndex);
|
||||
}
|
||||
if (object == btnNextColor || object == btnPrevColor) {
|
||||
const std::array<lv_color_t, nLines>* colors = returnColor(static_cast<enum colors>(settingsController.GetInfineatColorIndex()));
|
||||
for (int i = 0; i < nLines; i++) {
|
||||
lv_color_t color = (*colors)[i];
|
||||
lv_obj_set_style_local_line_color(lines[i], LV_LINE_PART_MAIN, LV_STATE_DEFAULT, color);
|
||||
}
|
||||
lv_obj_set_style_local_line_color(lineBattery, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, (*colors)[4]);
|
||||
lv_obj_set_style_local_bg_color(notificationIcon, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, (*colors)[7]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WatchFaceMeow::Refresh() {
|
||||
notificationState = notificationManager.AreNewNotificationsAvailable();
|
||||
if (notificationState.IsUpdated()) {
|
||||
lv_obj_set_hidden(notificationIcon, !notificationState.Get());
|
||||
lv_obj_align(notificationIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0);
|
||||
}
|
||||
|
||||
currentDateTime = std::chrono::time_point_cast<std::chrono::minutes>(dateTimeController.CurrentDateTime());
|
||||
if (currentDateTime.IsUpdated()) {
|
||||
uint8_t hour = dateTimeController.Hours();
|
||||
uint8_t minute = dateTimeController.Minutes();
|
||||
|
||||
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(labelTimeAmPm, ampmChar);
|
||||
}
|
||||
lv_label_set_text_fmt(labelHour, "%02d", hour);
|
||||
lv_label_set_text_fmt(labelMinutes, "%02d", minute);
|
||||
|
||||
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
|
||||
lv_obj_align(labelTimeAmPm, timeContainer, LV_ALIGN_OUT_RIGHT_TOP, 0, 10);
|
||||
lv_obj_align(labelHour, timeContainer, LV_ALIGN_IN_TOP_MID, 0, 5);
|
||||
lv_obj_align(labelMinutes, timeContainer, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
|
||||
}
|
||||
|
||||
currentDate = std::chrono::time_point_cast<std::chrono::days>(currentDateTime.Get());
|
||||
if (currentDate.IsUpdated()) {
|
||||
uint8_t day = dateTimeController.Day();
|
||||
Controllers::DateTime::Days dayOfWeek = dateTimeController.DayOfWeek();
|
||||
lv_label_set_text_fmt(labelDate, "%s %02d", dateTimeController.DayOfWeekShortToStringLow(dayOfWeek), day);
|
||||
lv_obj_realign(labelDate);
|
||||
}
|
||||
}
|
||||
|
||||
batteryPercentRemaining = batteryController.PercentRemaining();
|
||||
isCharging = batteryController.IsCharging();
|
||||
if (batteryController.IsCharging()) { // Charging battery animation
|
||||
chargingBatteryPercent += 1;
|
||||
if (chargingBatteryPercent > 100) {
|
||||
chargingBatteryPercent = batteryPercentRemaining.Get();
|
||||
}
|
||||
SetBatteryLevel(chargingBatteryPercent);
|
||||
} else if (isCharging.IsUpdated() || batteryPercentRemaining.IsUpdated()) {
|
||||
chargingBatteryPercent = batteryPercentRemaining.Get();
|
||||
SetBatteryLevel(chargingBatteryPercent);
|
||||
}
|
||||
|
||||
bleState = bleController.IsConnected();
|
||||
bleRadioEnabled = bleController.IsRadioEnabled();
|
||||
if (bleState.IsUpdated()) {
|
||||
//bleState.Get : in displayapp/widgets/StatusIcons.cpp: bleState = bleController.IsConnected();
|
||||
//dynamic icons have their definitions in displayApp/screens/BleIcon.h / cpp
|
||||
lv_label_set_text_static(bleIcon, BleIcon::GetIcon(bleState.Get()));
|
||||
lv_obj_align(bleIcon, dateContainer, LV_ALIGN_OUT_BOTTOM_MID, 0, 3);
|
||||
}
|
||||
|
||||
// Add alarm state and time
|
||||
// AlarmState is an enum type in class AlarmController that is in namespace controllers
|
||||
if (settingsController.GetInfineatShowAlarmStatus()) {
|
||||
alarmState = alarmController.State()==Pinetime::Controllers::AlarmController::AlarmState::Set;
|
||||
timerRunning = Pinetime::Controllers::Timer::timerController.IsRunning()
|
||||
if(!timerRunning)
|
||||
// sets the icon as bird or bed
|
||||
const char* alarmSymbol = Symbols::zzz;
|
||||
if(alarmState) {
|
||||
alarmSymbol = Symbols::bird;
|
||||
}
|
||||
lv_label_set_text_static(alarmIcon, alarmSymbol);
|
||||
//displays the time of the alarm or nothing if the alarm is not set
|
||||
if (alarmState) {
|
||||
uint8_t alarmHours = alarmController.Hours();
|
||||
uint8_t alarmMinutes = alarmController.Minutes();
|
||||
//handles the am pm format.
|
||||
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
|
||||
char ampmChar[3] = "AM";
|
||||
if (alarmHours == 0) {
|
||||
alarmHours = 12;
|
||||
} else if (alarmHours == 12) {
|
||||
ampmChar[0]='P';
|
||||
} else if (alarmHours > 12) {
|
||||
alarmHours = alarmHours - 12;
|
||||
ampmChar[0]='P';
|
||||
}
|
||||
lv_label_set_text(labelTimeAmPmAlarm, ampmChar);
|
||||
lv_obj_set_style_local_text_font(labelTimeAmPmAlarm, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font_teko);
|
||||
lv_obj_align(labelTimeAmPmAlarm, labelAlarm, LV_ALIGN_OUT_TOP_RIGHT, 0, 0);
|
||||
}
|
||||
|
||||
lv_label_set_text_fmt(labelAlarm, "%02d:%02d", alarmHours, alarmMinutes);
|
||||
|
||||
lv_obj_align(alarmIcon, labelAlarm, LV_ALIGN_OUT_LEFT_MID, -3, 0);
|
||||
lv_obj_align(labelAlarm, dateContainer, LV_ALIGN_OUT_BOTTOM_MID, -10, 0);
|
||||
lv_obj_align(labelAlarm, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -3, 0);
|
||||
else{ //timer is running, display timer instead of alarm
|
||||
const char* timerSymbol = Symbols::hourGlass;
|
||||
lv_label_set_text_static(timerIcon, timerSymbol);
|
||||
auto secondsRemaining = std::chrono::duration_cast<std::chrono::seconds>(timer.GetTimeRemaining())/1000;
|
||||
timerMinutes = secondsRemaining.count() / 60;
|
||||
timerSeconds = secondsRemaining.count() % 60;
|
||||
lv_label_set_text_fmt(labelTimer, "%02d:%02d", timerMinutes, timerSeconds);
|
||||
|
||||
lv_obj_align(timerIcon, labelTimer, LV_ALIGN_OUT_LEFT_MID, -3, 0);
|
||||
lv_obj_align(labelTimer, dateContainer, LV_ALIGN_OUT_BOTTOM_MID, -10, 0);
|
||||
lv_obj_align(labelTimer, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -3, 0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
lv_label_set_text_static(labelAlarm, Symbols::none);
|
||||
lv_obj_align(alarmIcon, dateContainer, LV_ALIGN_OUT_BOTTOM_MID, 0, 0);
|
||||
lv_obj_align(alarmIcon, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -3, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
stepCount = motionController.NbSteps();
|
||||
if (stepCount.IsUpdated()) {
|
||||
lv_label_set_text_fmt(stepValue, "%lu", stepCount.Get());
|
||||
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 10, 0);
|
||||
lv_obj_align(pawIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0);
|
||||
}
|
||||
|
||||
if (!lv_obj_get_hidden(btnSettings)) {
|
||||
if ((savedTick > 0) && (lv_tick_get() - savedTick > 3000)) {
|
||||
lv_obj_set_hidden(btnSettings, true);
|
||||
savedTick = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void WatchFaceMeow::SetBatteryLevel(uint8_t batteryPercent) {
|
||||
// starting point (y) + Pine64 logo height * (100 - batteryPercent) / 100^
|
||||
//the ligne grows, it covers the icon starting from the top
|
||||
lineBatteryPoints[1] = {27, static_cast<lv_coord_t>(107 + 31 * (100 - batteryPercent) / 100)};
|
||||
lv_line_set_points(lineBattery, lineBatteryPoints, 2);
|
||||
}
|
||||
|
||||
void WatchFaceMeow::ToggleBatteryIndicatorColor(bool showSideCover) {
|
||||
if (!showSideCover) { // make indicator and notification icon color white
|
||||
lv_obj_set_style_local_image_recolor_opa(logoCat, LV_IMG_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_100);
|
||||
lv_obj_set_style_local_image_recolor(logoCat, LV_IMG_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
lv_obj_set_style_local_line_color(lineBattery, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
|
||||
lv_obj_set_style_local_bg_color(notificationIcon, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
} else {
|
||||
lv_obj_set_style_local_image_recolor_opa(logoCat, LV_IMG_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_0);
|
||||
const std::array<lv_color_t, nLines>* colors = returnColor(static_cast<enum colors>(settingsController.GetInfineatColorIndex()));
|
||||
lv_obj_set_style_local_line_color(lineBattery, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, (*colors)[4]);
|
||||
lv_obj_set_style_local_bg_color(notificationIcon, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, (*colors)[7]);
|
||||
}
|
||||
}
|
||||
|
||||
bool WatchFaceMeow::IsAvailable(Pinetime::Controllers::FS& filesystem) {
|
||||
lfs_file file = {};
|
||||
|
||||
if (filesystem.FileOpen(&file, "/fonts/teko.bin", LFS_O_RDONLY) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
filesystem.FileClose(&file);
|
||||
if (filesystem.FileOpen(&file, "/fonts/bebas.bin", LFS_O_RDONLY) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
filesystem.FileClose(&file);
|
||||
if (filesystem.FileOpen(&file, "/images/cat_small.bin", LFS_O_RDONLY) < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
filesystem.FileClose(&file);
|
||||
return true;
|
||||
}
|
141
src/displayapp/screens/WatchFaceMeow.h
Normal file
141
src/displayapp/screens/WatchFaceMeow.h
Normal file
|
@ -0,0 +1,141 @@
|
|||
#pragma once
|
||||
|
||||
#include <lvgl/lvgl.h>
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <displayapp/Controllers.h>
|
||||
#include "displayapp/screens/Screen.h"
|
||||
#include "components/datetime/DateTimeController.h"
|
||||
#include "displayapp/screens/Timer.h"
|
||||
#include "utility/DirtyValue.h"
|
||||
#include "displayapp/apps/Apps.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Controllers {
|
||||
class Settings;
|
||||
class Battery;
|
||||
class Ble;
|
||||
class NotificationManager;
|
||||
class MotionController;
|
||||
}
|
||||
|
||||
namespace Applications {
|
||||
namespace Screens {
|
||||
|
||||
class WatchFaceMeow : public Screen {
|
||||
public:
|
||||
static constexpr int nLines = 9;
|
||||
WatchFaceMeow(Controllers::DateTime& dateTimeController,
|
||||
const Controllers::Battery& batteryController,
|
||||
const Controllers::Ble& bleController,
|
||||
Controllers::AlarmController& alarmController,
|
||||
Controllers::Timer& timerController,
|
||||
Controllers::NotificationManager& notificationManager,
|
||||
Controllers::Settings& settingsController,
|
||||
Controllers::MotionController& motionController,
|
||||
Controllers::FS& fs);
|
||||
|
||||
~WatchFaceMeow() override;
|
||||
|
||||
bool OnTouchEvent(TouchEvents event) override;
|
||||
bool OnButtonPushed() override;
|
||||
void UpdateSelected(lv_obj_t* object, lv_event_t event);
|
||||
void CloseMenu();
|
||||
|
||||
void Refresh() override;
|
||||
|
||||
static bool IsAvailable(Pinetime::Controllers::FS& filesystem);
|
||||
|
||||
private:
|
||||
uint32_t savedTick = 0;
|
||||
uint8_t chargingBatteryPercent = 101; // not a mistake ;)
|
||||
|
||||
Utility::DirtyValue<uint8_t> batteryPercentRemaining {};
|
||||
Utility::DirtyValue<bool> isCharging {};
|
||||
Utility::DirtyValue<bool> bleState {};
|
||||
Utility::DirtyValue<bool> bleRadioEnabled {};
|
||||
bool alarmState {};
|
||||
Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>> currentDateTime {};
|
||||
bool timerRunning {};
|
||||
Utility::DirtyValue<uint32_t> stepCount {};
|
||||
Utility::DirtyValue<bool> notificationState {};
|
||||
Utility::DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::days>> currentDate;
|
||||
|
||||
// Lines making up the side cover
|
||||
lv_obj_t* lineBattery;
|
||||
|
||||
lv_point_t lineBatteryPoints[2];
|
||||
|
||||
lv_obj_t* logoCat;
|
||||
|
||||
lv_obj_t* timeContainer;
|
||||
lv_obj_t* labelHour;
|
||||
lv_obj_t* labelMinutes;
|
||||
lv_obj_t* labelTimeAmPm;
|
||||
lv_obj_t* dateContainer;
|
||||
lv_obj_t* labelDate;
|
||||
lv_obj_t* bleIcon;
|
||||
lv_obj_t* labelAlarm;
|
||||
lv_obj_t* labelTimeAmPmAlarm;
|
||||
lv_obj_t* alarmIcon;
|
||||
lv_obj_t* labelTimer;
|
||||
lv_obj_t* timerIcon;
|
||||
lv_obj_t* pawIcon;
|
||||
lv_obj_t* stepValue;
|
||||
lv_obj_t* notificationIcon;
|
||||
lv_obj_t* btnClose;
|
||||
lv_obj_t* btnNextColor;
|
||||
lv_obj_t* btnToggleCover;
|
||||
lv_obj_t* btnToggleAlarm;
|
||||
lv_obj_t* btnPrevColor;
|
||||
lv_obj_t* btnSettings;
|
||||
lv_obj_t* labelBtnSettings;
|
||||
lv_obj_t* lblToggle;
|
||||
lv_obj_t* lblAlarm;
|
||||
|
||||
lv_obj_t* lines[nLines];
|
||||
|
||||
Controllers::DateTime& dateTimeController;
|
||||
const Controllers::Battery& batteryController;
|
||||
const Controllers::Ble& bleController;
|
||||
Controllers::AlarmController& alarmController;
|
||||
Controllers::Timer& timerController;
|
||||
Controllers::NotificationManager& notificationManager;
|
||||
Controllers::Settings& settingsController;
|
||||
Controllers::MotionController& motionController;
|
||||
|
||||
void SetBatteryLevel(uint8_t batteryPercent);
|
||||
void ToggleBatteryIndicatorColor(bool showSideCover);
|
||||
|
||||
void ToggleShowAlarmStatus(bool showAlarmStatus);
|
||||
|
||||
lv_task_t* taskRefresh;
|
||||
lv_font_t* font_teko = nullptr;
|
||||
lv_font_t* font_bebas = nullptr;
|
||||
};
|
||||
}
|
||||
|
||||
template <>
|
||||
struct WatchFaceTraits<WatchFace::Meow> {
|
||||
static constexpr WatchFace watchFace = WatchFace::Meow;
|
||||
static constexpr const char* name = "Meow face";
|
||||
|
||||
static Screens::Screen* Create(AppControllers& controllers) {
|
||||
return new Screens::WatchFaceMeow(controllers.dateTimeController,
|
||||
controllers.batteryController,
|
||||
controllers.bleController,
|
||||
controllers.alarmController,
|
||||
controllers.timer,
|
||||
controllers.notificationManager,
|
||||
controllers.settingsController,
|
||||
controllers.motionController,
|
||||
controllers.filesystem);
|
||||
};
|
||||
|
||||
static bool IsAvailable(Pinetime::Controllers::FS& filesystem) {
|
||||
return Screens::WatchFaceMeow::IsAvailable(filesystem);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
11
src/displayapp/screens/addWatchface.md
Normal file
11
src/displayapp/screens/addWatchface.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
# Add a new watchface :
|
||||
## Modify the following files with the names of your source files :
|
||||
|
||||
- /src/displayapp/apps/Apps.h.in
|
||||
- /src/components/settings/Settings.h
|
||||
- /src/displayapp/screens/settings/SettingWatchFace.h
|
||||
- /src/displayapp/UserApps.h
|
||||
- /src/displayapp/apps/CMakeLists.txt
|
||||
- CMakelists.txt
|
||||
|
||||
|
|
@ -10,8 +10,11 @@
|
|||
#include "displayapp/screens/Symbols.h"
|
||||
#include "displayapp/screens/CheckboxList.h"
|
||||
#include "displayapp/screens/WatchFaceInfineat.h"
|
||||
#include "displayapp/screens/WatchFaceMeow.h"
|
||||
#include "displayapp/screens/WatchFaceCasioStyleG7710.h"
|
||||
|
||||
|
||||
|
||||
namespace Pinetime {
|
||||
|
||||
namespace Applications {
|
||||
|
|
4
src/displayapp/screens/todo.txt
Normal file
4
src/displayapp/screens/todo.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
compare infineat and meow .h files to make declaration correct
|
||||
faire en sorte to keep bell and not bell for inifneat wf
|
||||
check the orig files and the files in lib if they need to be in git
|
||||
|
|
@ -126,13 +126,6 @@ Bma421::Values Bma421::Process() {
|
|||
uint32_t steps = 0;
|
||||
bma423_step_counter_output(&steps, &bma);
|
||||
|
||||
int32_t temperature;
|
||||
bma4_get_temperature(&temperature, BMA4_DEG, &bma);
|
||||
temperature = temperature / 1000;
|
||||
|
||||
uint8_t activity = 0;
|
||||
bma423_activity_output(&activity, &bma);
|
||||
|
||||
// X and Y axis are swapped because of the way the sensor is mounted in the PineTime
|
||||
return {steps, data.y, data.x, data.z};
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <cstring>
|
||||
#include "drivers/St7789.h"
|
||||
#include <hal/nrf_gpio.h>
|
||||
#include <nrfx_log.h>
|
||||
|
@ -16,10 +17,9 @@ void St7789::Init() {
|
|||
HardwareReset();
|
||||
SoftwareReset();
|
||||
SleepOut();
|
||||
ColMod();
|
||||
PixelFormat();
|
||||
MemoryDataAccessControl();
|
||||
ColumnAddressSet();
|
||||
RowAddressSet();
|
||||
SetAddrWindow(0, 0, Width, Height);
|
||||
// P8B Mirrored version does not need display inversion.
|
||||
#ifndef DRIVER_DISPLAY_MIRROR
|
||||
DisplayInversionOn();
|
||||
|
@ -97,8 +97,9 @@ void St7789::SleepIn() {
|
|||
sleepIn = true;
|
||||
}
|
||||
|
||||
void St7789::ColMod() {
|
||||
WriteCommand(static_cast<uint8_t>(Commands::ColMod));
|
||||
void St7789::PixelFormat() {
|
||||
WriteCommand(static_cast<uint8_t>(Commands::PixelFormat));
|
||||
// 65K colours, 16-bit per pixel
|
||||
WriteData(0x55);
|
||||
}
|
||||
|
||||
|
@ -118,22 +119,6 @@ void St7789::MemoryDataAccessControl() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void St7789::ColumnAddressSet() {
|
||||
WriteCommand(static_cast<uint8_t>(Commands::ColumnAddressSet));
|
||||
WriteData(0x00);
|
||||
WriteData(0x00);
|
||||
WriteData(Width >> 8u);
|
||||
WriteData(Width & 0xffu);
|
||||
}
|
||||
|
||||
void St7789::RowAddressSet() {
|
||||
WriteCommand(static_cast<uint8_t>(Commands::RowAddressSet));
|
||||
WriteData(0x00);
|
||||
WriteData(0x00);
|
||||
WriteData(320u >> 8u);
|
||||
WriteData(320u & 0xffu);
|
||||
}
|
||||
|
||||
void St7789::DisplayInversionOn() {
|
||||
WriteCommand(static_cast<uint8_t>(Commands::DisplayInversionOn));
|
||||
}
|
||||
|
@ -148,16 +133,23 @@ void St7789::DisplayOn() {
|
|||
|
||||
void St7789::SetAddrWindow(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1) {
|
||||
WriteCommand(static_cast<uint8_t>(Commands::ColumnAddressSet));
|
||||
WriteData(x0 >> 8);
|
||||
WriteData(x0 & 0xff);
|
||||
WriteData(x1 >> 8);
|
||||
WriteData(x1 & 0xff);
|
||||
uint8_t colArgs[] = {
|
||||
static_cast<uint8_t>(x0 >> 8), // x start MSB
|
||||
static_cast<uint8_t>(x0), // x start LSB
|
||||
static_cast<uint8_t>(x1 >> 8), // x end MSB
|
||||
static_cast<uint8_t>(x1) // x end LSB
|
||||
};
|
||||
WriteData(colArgs, sizeof(colArgs));
|
||||
|
||||
WriteCommand(static_cast<uint8_t>(Commands::RowAddressSet));
|
||||
WriteData(y0 >> 8);
|
||||
WriteData(y0 & 0xff);
|
||||
WriteData(y1 >> 8);
|
||||
WriteData(y1 & 0xff);
|
||||
uint8_t rowArgs[] = {
|
||||
static_cast<uint8_t>(y0 >> 8), // y start MSB
|
||||
static_cast<uint8_t>(y0), // y start LSB
|
||||
static_cast<uint8_t>(y1 >> 8), // y end MSB
|
||||
static_cast<uint8_t>(y1) // y end LSB
|
||||
};
|
||||
memcpy(addrWindowArgs, rowArgs, sizeof(rowArgs));
|
||||
WriteData(addrWindowArgs, sizeof(addrWindowArgs));
|
||||
}
|
||||
|
||||
void St7789::WriteToRam(const uint8_t* data, size_t size) {
|
||||
|
@ -179,8 +171,12 @@ void St7789::DisplayOff() {
|
|||
void St7789::VerticalScrollStartAddress(uint16_t line) {
|
||||
verticalScrollingStartAddress = line;
|
||||
WriteCommand(static_cast<uint8_t>(Commands::VerticalScrollStartAddress));
|
||||
WriteData(line >> 8u);
|
||||
WriteData(line & 0x00ffu);
|
||||
uint8_t args[] = {
|
||||
static_cast<uint8_t>(line >> 8), // Frame memory line pointer MSB
|
||||
static_cast<uint8_t>(line) // Frame memory line pointer LSB
|
||||
};
|
||||
memcpy(verticalScrollArgs, args, sizeof(args));
|
||||
WriteData(verticalScrollArgs, sizeof(verticalScrollArgs));
|
||||
}
|
||||
|
||||
void St7789::Uninit() {
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace Pinetime {
|
|||
void SleepOut();
|
||||
void EnsureSleepOutPostDelay();
|
||||
void SleepIn();
|
||||
void ColMod();
|
||||
void PixelFormat();
|
||||
void MemoryDataAccessControl();
|
||||
void DisplayInversionOn();
|
||||
void NormalModeOn();
|
||||
|
@ -68,16 +68,17 @@ namespace Pinetime {
|
|||
MemoryDataAccessControl = 0x36,
|
||||
VerticalScrollDefinition = 0x33,
|
||||
VerticalScrollStartAddress = 0x37,
|
||||
ColMod = 0x3a,
|
||||
PixelFormat = 0x3a,
|
||||
VdvSet = 0xc4,
|
||||
};
|
||||
void WriteData(uint8_t data);
|
||||
void WriteData(const uint8_t* data, size_t size);
|
||||
void ColumnAddressSet();
|
||||
|
||||
static constexpr uint16_t Width = 240;
|
||||
static constexpr uint16_t Height = 320;
|
||||
void RowAddressSet();
|
||||
|
||||
uint8_t addrWindowArgs[4];
|
||||
uint8_t verticalScrollArgs[2];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -589,7 +589,7 @@ typedef void* lv_obj_user_data_t;
|
|||
/*Calendar (dependencies: -)*/
|
||||
#define LV_USE_CALENDAR 1
|
||||
#if LV_USE_CALENDAR
|
||||
#define LV_CALENDAR_WEEK_STARTS_MONDAY 0
|
||||
#define LV_CALENDAR_WEEK_STARTS_MONDAY 1
|
||||
#endif
|
||||
|
||||
/*Canvas (dependencies: lv_img)*/
|
||||
|
|
|
@ -6,6 +6,13 @@
|
|||
"binary_format": "ARGB8565_RBSWAP",
|
||||
"target_path": "/images/"
|
||||
},
|
||||
"cat_small" : {
|
||||
"sources": "images/cat_clean.png",
|
||||
"color_format": "CF_TRUE_COLOR_ALPHA",
|
||||
"output_format": "bin",
|
||||
"binary_format": "ARGB8565_RBSWAP",
|
||||
"target_path": "/images/"
|
||||
},
|
||||
"navigation0" : {
|
||||
"sources": "images/navigation0.png",
|
||||
"color_format": "CF_INDEXED_1_BIT",
|
||||
|
|
BIN
src/resources/images/cat_clean.png
Normal file
BIN
src/resources/images/cat_clean.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
|
@ -410,8 +410,6 @@ void SystemTask::Work() {
|
|||
}
|
||||
|
||||
monitor.Process();
|
||||
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) == 0) {
|
||||
watchdog.Reload();
|
||||
|
|
Loading…
Reference in a new issue