diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 2eb8a95990..247bd4af6b 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -46,25 +46,30 @@ jobs:
# Unzip the package because Upload Artifact will zip up the files
- name: Unzip DFU package
run: unzip ./build/output/pinetime-mcuboot-app-dfu-*.zip -d ./build/output/pinetime-mcuboot-app-dfu
+ - name: Set ref_name, but replace slashes with dashes.
+ shell: bash
+ env:
+ ref_name: ${{ github.head_ref || github.ref_name }}
+ run: echo "REF_NAME=${ref_name//\//-}" >> $GITHUB_ENV
- name: Upload DFU artifacts
uses: actions/upload-artifact@v3
with:
- name: InfiniTime DFU ${{ github.head_ref }}
+ name: InfiniTime DFU ${{ env.REF_NAME }}
path: ./build/output/pinetime-mcuboot-app-dfu/*
- name: Upload MCUBoot image artifacts
uses: actions/upload-artifact@v3
with:
- name: InfiniTime MCUBoot image ${{ github.head_ref }}
+ name: InfiniTime MCUBoot image ${{ env.REF_NAME }}
path: ./build/output/pinetime-mcuboot-app-image-*.bin
- name: Upload standalone ELF artifacts
uses: actions/upload-artifact@v3
with:
- name: InfiniTime image ${{ github.head_ref }}
+ name: InfiniTime image ${{ env.REF_NAME }}
path: ./build/output/src/pinetime-app-*.out
- name: Upload resources artifacts
uses: actions/upload-artifact@v3
with:
- name: InfiniTime resources ${{ github.head_ref }}
+ name: InfiniTime resources ${{ env.REF_NAME }}
path: ./build/output/infinitime-resources-*.zip
build-simulator:
@@ -105,7 +110,7 @@ jobs:
- name: Upload simulator executable
uses: actions/upload-artifact@v3
with:
- name: infinisim-${{ github.head_ref }}
+ name: infinisim-${{ env.REF_NAME }}
path: build_lv_sim/infinisim
get-base-ref-size:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9b5669b003..3250982d6a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release")
-project(pinetime VERSION 1.14.0 LANGUAGES C CXX ASM)
+project(pinetime VERSION 1.15.0 LANGUAGES C CXX ASM)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 20)
diff --git a/README.md b/README.md
index e8bbf172d4..68d8779d0e 100644
--- a/README.md
+++ b/README.md
@@ -1,40 +1,24 @@
-# [InfiniTime](https://github.com/Eve1374/InfiniTime)
+
-![InfiniTime logo](doc/logo/infinitime-logo-small.jpg "InfiniTime Logo")
+![Header Image](doc/logo/watchface_collage.png)
-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
+[![GitHub tag](https://img.shields.io/github/tag/InfiniTimeOrg/InfiniTime?include_prereleases=&sort=semver&color=blue)](https://github.com/InfiniTimeOrg/InfiniTime/releases)
+[![GitHub License](https://img.shields.io/github/license/InfiniTimeOrg/InfiniTime)](https://github.com/InfiniTimeOrg/InfiniLink/blob/main/LICENSE)
+[![Issues - InfiniTime](https://img.shields.io/github/issues/InfiniTimeOrg/InfiniTime)](https://github.com/InfiniTimeOrg/InfiniTime/issues)
+[![Pull Requests - InfiniTime](https://img.shields.io/github/issues-pr/InfiniTimeOrg/InfiniTime)](https://github.com/InfiniTimeOrg/InfiniTime/pulls)
+[![Downloads - InfiniTime](https://img.shields.io/github/downloads/InfiniTimeOrg/InfiniTime/total)](https://github.com/InfiniTimeOrg/InfiniTime)
+[![Stars - InfiniTime](https://img.shields.io/github/stars/InfiniTimeOrg/InfiniTime?style=social)](https://github.com/InfiniTimeOrg/InfiniTime/stargazers)
+[![Forks - InfiniTime](https://img.shields.io/github/forks/InfiniTimeOrg/InfiniTime?style=social)](https://github.com/InfiniTimeOrg/InfiniTime/network/members)
-- 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
+# InfiniTime
-Here are pictures with and without alarm set :
+*Fast open-source firmware for the [PineTime smartwatch](https://pine64.org/devices/pinetime/) with many features, written in modern C++.*
+
-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)
-- [Available apps](doc/gettingStarted/Applications.md)
-- [Available watch faces](/doc/gettingStarted/Watchfaces.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 :
-
+
## New to InfiniTime?
@@ -49,13 +33,18 @@ Branches :
### Companion apps
- [Gadgetbridge](https://gadgetbridge.org/) (Android)
-- [AmazFish](https://openrepos.net/content/piggz/amazfish/) (SailfishOS)
+- [Amazfish](https://github.com/piggz/harbour-amazfish/) ([SailfishOS](https://sailfishos-chum.github.io/apps/harbour-amazfish/), [Ubuntu Touch](https://open-store.io/app/uk.co.piggz.amazfish), [Flatpak](https://flathub.org/apps/uk.co.piggz.amazfish))
- [Siglo](https://github.com/alexr4535/siglo) (Linux)
- [InfiniLink](https://github.com/InfiniTimeOrg/InfiniLink) (iOS)
- [ITD](https://gitea.elara.ws/Elara6331/itd) (Linux)
- [WatchMate](https://github.com/azymohliad/watchmate) (Linux)
+- [InfiniTimeExplorer](https://infinitimeexplorer.netlify.app) (Web)
+
+
-***Note**: We removed mentions to NRFConnect as this app is closed source and recent versions do not work anymore with InfiniTime (the last version known to work is 4.24.3). If you used NRFConnect in the past, we recommend you switch to [Gadgetbridge](https://gadgetbridge.org/).*
+> *InfiniTimeExplorer is only compatible with web browsers that support Web BLE. Current fully supported browsers include Chrome and Microsoft Edge.*
+>
+> *We removed mentions to NRFConnect as this app is closed source and recent versions do not work anymore with InfiniTime (the last version known to work is 4.24.3). If you used NRFConnect in the past, we recommend you switch to [Gadgetbridge](https://gadgetbridge.org/).*
## Development
@@ -120,4 +109,3 @@ Here are some people I would like to highlight:
- [Atc1441](https://github.com/atc1441/): He works on an Arduino based firmware for the Pinetime and many other smartwatches based on similar hardware. He was of great help when I was implementing support for the BMA421 motion sensor and I²C driver.
- [Koen](https://github.com/bosmoment): He’s working on a firmware based on RiotOS. He integrated similar libs as me: NimBLE, LittleVGL,… His help was invaluable too!
- [Lup Yuen Lee](https://github.com/lupyuen): He is everywhere: he works on a Rust firmware, builds a MCUBoot based bootloader for the Pinetime, designs a Flutter based companion app for smartphones and writes a lot of articles about the Pinetime!
->>>>>>>>> Temporary merge branch 2
diff --git a/doc/logo/watchface_collage.png b/doc/logo/watchface_collage.png
new file mode 100644
index 0000000000..caeb74562f
Binary files /dev/null and b/doc/logo/watchface_collage.png differ
diff --git a/docker/Dockerfile b/docker/Dockerfile
index bb5d5f65be..e6d92aae96 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -64,6 +64,9 @@ RUN bash -c "source /opt/build.sh; GetMcuBoot;"
# Add the infinitime user for connecting devcontainer
RUN adduser infinitime
-
+
+# Configure Git to accept the /sources directory as safe
+RUN git config --global --add safe.directory /sources
+
ENV SOURCES_DIR /sources
CMD ["/opt/build.sh"]
diff --git a/src/components/ble/SimpleWeatherService.cpp b/src/components/ble/SimpleWeatherService.cpp
index 504cad14b5..51baf5433f 100644
--- a/src/components/ble/SimpleWeatherService.cpp
+++ b/src/components/ble/SimpleWeatherService.cpp
@@ -42,9 +42,9 @@ namespace {
std::memcpy(cityName.data(), &dataBuffer[16], 32);
cityName[32] = '\0';
return SimpleWeatherService::CurrentWeather(ToUInt64(&dataBuffer[2]),
- ToInt16(&dataBuffer[10]),
- ToInt16(&dataBuffer[12]),
- ToInt16(&dataBuffer[14]),
+ SimpleWeatherService::Temperature(ToInt16(&dataBuffer[10])),
+ SimpleWeatherService::Temperature(ToInt16(&dataBuffer[12])),
+ SimpleWeatherService::Temperature(ToInt16(&dataBuffer[14])),
SimpleWeatherService::Icons {dataBuffer[16 + 32]},
std::move(cityName));
}
@@ -52,12 +52,12 @@ namespace {
SimpleWeatherService::Forecast CreateForecast(const uint8_t* dataBuffer) {
auto timestamp = static_cast(ToUInt64(&dataBuffer[2]));
- std::array days;
+ std::array, SimpleWeatherService::MaxNbForecastDays> days;
const uint8_t nbDaysInBuffer = dataBuffer[10];
const uint8_t nbDays = std::min(SimpleWeatherService::MaxNbForecastDays, nbDaysInBuffer);
for (int i = 0; i < nbDays; i++) {
- days[i] = SimpleWeatherService::Forecast::Day {ToInt16(&dataBuffer[11 + (i * 5)]),
- ToInt16(&dataBuffer[13 + (i * 5)]),
+ days[i] = SimpleWeatherService::Forecast::Day {SimpleWeatherService::Temperature(ToInt16(&dataBuffer[11 + (i * 5)])),
+ SimpleWeatherService::Temperature(ToInt16(&dataBuffer[13 + (i * 5)])),
SimpleWeatherService::Icons {dataBuffer[15 + (i * 5)]}};
}
return SimpleWeatherService::Forecast {timestamp, nbDays, days};
@@ -98,9 +98,9 @@ int SimpleWeatherService::OnCommand(struct ble_gatt_access_ctxt* ctxt) {
currentWeather = CreateCurrentWeather(dataBuffer);
NRF_LOG_INFO("Current weather :\n\tTimestamp : %d\n\tTemperature:%d\n\tMin:%d\n\tMax:%d\n\tIcon:%d\n\tLocation:%s",
currentWeather->timestamp,
- currentWeather->temperature,
- currentWeather->minTemperature,
- currentWeather->maxTemperature,
+ currentWeather->temperature.PreciseCelsius(),
+ currentWeather->minTemperature.PreciseCelsius(),
+ currentWeather->maxTemperature.PreciseCelsius(),
currentWeather->iconId,
currentWeather->location.data());
}
@@ -112,9 +112,9 @@ int SimpleWeatherService::OnCommand(struct ble_gatt_access_ctxt* ctxt) {
for (int i = 0; i < 5; i++) {
NRF_LOG_INFO("\t[%d] Min: %d - Max : %d - Icon : %d",
i,
- forecast->days[i].minTemperature,
- forecast->days[i].maxTemperature,
- forecast->days[i].iconId);
+ forecast->days[i]->minTemperature.PreciseCelsius(),
+ forecast->days[i]->maxTemperature.PreciseCelsius(),
+ forecast->days[i]->iconId);
}
}
break;
diff --git a/src/components/ble/SimpleWeatherService.h b/src/components/ble/SimpleWeatherService.h
index 03d2f6ff03..0f8c181bd3 100644
--- a/src/components/ble/SimpleWeatherService.h
+++ b/src/components/ble/SimpleWeatherService.h
@@ -19,7 +19,7 @@
#include
#include
-#include
+#include
#include
#define min // workaround: nimble's min/max macros conflict with libstdc++
@@ -61,13 +61,42 @@ namespace Pinetime {
Unknown = 255
};
+ class Temperature {
+ public:
+ explicit Temperature(int16_t raw) : raw {raw} {
+ }
+
+ [[nodiscard]] int16_t PreciseCelsius() const {
+ return raw;
+ }
+
+ [[nodiscard]] int16_t PreciseFahrenheit() const {
+ return raw * 9 / 5 + 3200;
+ }
+
+ [[nodiscard]] int16_t Celsius() const {
+ return (PreciseCelsius() + 50) / 100;
+ }
+
+ [[nodiscard]] int16_t Fahrenheit() const {
+ return (PreciseFahrenheit() + 50) / 100;
+ }
+
+ bool operator==(const Temperature& other) const {
+ return raw == other.raw;
+ }
+
+ private:
+ int16_t raw;
+ };
+
using Location = std::array; // 32 char + \0 (end of string)
struct CurrentWeather {
CurrentWeather(uint64_t timestamp,
- int16_t temperature,
- int16_t minTemperature,
- int16_t maxTemperature,
+ Temperature temperature,
+ Temperature minTemperature,
+ Temperature maxTemperature,
Icons iconId,
Location&& location)
: timestamp {timestamp},
@@ -79,9 +108,9 @@ namespace Pinetime {
}
uint64_t timestamp;
- int16_t temperature;
- int16_t minTemperature;
- int16_t maxTemperature;
+ Temperature temperature;
+ Temperature minTemperature;
+ Temperature maxTemperature;
Icons iconId;
Location location;
@@ -93,14 +122,14 @@ namespace Pinetime {
uint8_t nbDays;
struct Day {
- int16_t minTemperature;
- int16_t maxTemperature;
+ Temperature minTemperature;
+ Temperature maxTemperature;
Icons iconId;
bool operator==(const Day& other) const;
};
- std::array days;
+ std::array, MaxNbForecastDays> days;
bool operator==(const Forecast& other) const;
};
@@ -108,10 +137,6 @@ namespace Pinetime {
std::optional Current() const;
std::optional GetForecast() const;
- static int16_t CelsiusToFahrenheit(int16_t celsius) {
- return celsius * 9 / 5 + 3200;
- }
-
private:
// 00050000-78fc-48fe-8e23-433b3a1942d0
static constexpr ble_uuid128_t BaseUuid() {
diff --git a/src/components/datetime/DateTimeController.cpp b/src/components/datetime/DateTimeController.cpp
index 7f58c9b397..d439821b90 100644
--- a/src/components/datetime/DateTimeController.cpp
+++ b/src/components/datetime/DateTimeController.cpp
@@ -7,16 +7,29 @@
using namespace Pinetime::Controllers;
namespace {
- char const* DaysStringShort[] = {"--", "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
- char const* DaysStringShortLow[] = {"--", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
- char const* MonthsString[] = {"--", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
- char const* MonthsStringLow[] = {"--", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+ constexpr const char* const DaysStringShort[] = {"--", "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
+ constexpr const char* const DaysStringShortLow[] = {"--", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
+ constexpr const char* const MonthsString[] = {"--", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
+ constexpr const char* const MonthsStringLow[] =
+ {"--", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+ constexpr int compileTimeAtoi(const char* str) {
+ int result = 0;
+ while (*str >= '0' && *str <= '9') {
+ result = result * 10 + *str - '0';
+ str++;
+ }
+ return result;
+ }
}
DateTime::DateTime(Controllers::Settings& settingsController) : settingsController {settingsController} {
mutex = xSemaphoreCreateMutex();
ASSERT(mutex != nullptr);
xSemaphoreGive(mutex);
+
+ // __DATE__ is a string of the format "MMM DD YYYY", so an offset of 7 gives the start of the year
+ SetTime(compileTimeAtoi(&__DATE__[7]), 1, 1, 0, 0, 0);
}
void DateTime::SetCurrentTime(std::chrono::time_point t) {
@@ -46,7 +59,9 @@ void DateTime::SetTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour,
UpdateTime(previousSystickCounter, true);
xSemaphoreGive(mutex);
- systemTask->PushMessage(System::Messages::OnNewTime);
+ if (systemTask != nullptr) {
+ systemTask->PushMessage(System::Messages::OnNewTime);
+ }
}
void DateTime::SetTimeZone(int8_t timezone, int8_t dst) {
diff --git a/src/components/datetime/DateTimeController.h b/src/components/datetime/DateTimeController.h
index 5a453f2060..a005f9ac43 100644
--- a/src/components/datetime/DateTimeController.h
+++ b/src/components/datetime/DateTimeController.h
@@ -41,7 +41,7 @@ namespace Pinetime {
*
* used to update difference between utc and local time (see UtcOffset())
*
- * parameters are in quarters of an our. Following the BLE CTS specification,
+ * parameters are in quarters of an hour. Following the BLE CTS specification,
* timezone is expected to be constant over DST which will be reported in
* dst field.
*/
diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp
index ff43bb8146..b1594f197c 100644
--- a/src/displayapp/DisplayApp.cpp
+++ b/src/displayapp/DisplayApp.cpp
@@ -157,12 +157,20 @@ void DisplayApp::InitHw() {
}
TickType_t DisplayApp::CalculateSleepTime() {
+ // Calculates how many system ticks DisplayApp should sleep before rendering the next AOD frame
+ // Next frame time is frame count * refresh period (ms) * tick rate
+
+ auto RoundedDiv = [](uint32_t a, uint32_t b) {
+ return ((a + (b / 2)) / b);
+ };
+ // RoundedDiv overflows when numerator + (denominator floordiv 2) > uint32 max
+ // in this case around 9 hours (=overflow frame count / always on refresh period)
+ constexpr TickType_t overflowFrameCount = (UINT32_MAX - (1000 / 16)) / ((configTICK_RATE_HZ / 8) * alwaysOnRefreshPeriod);
+
TickType_t ticksElapsed = xTaskGetTickCount() - alwaysOnStartTime;
- // Divide both the numerator and denominator by 8 to increase the number of ticks (frames) before the overflow tick is reached
- TickType_t elapsedTarget = ROUNDED_DIV((configTICK_RATE_HZ / 8) * alwaysOnTickCount * alwaysOnRefreshPeriod, 1000 / 8);
- // ROUNDED_DIV overflows when numerator + (denominator floordiv 2) > uint32 max
- // in this case around 9 hours
- constexpr TickType_t overflowTick = (UINT32_MAX - (1000 / 16)) / ((configTICK_RATE_HZ / 8) * alwaysOnRefreshPeriod);
+ // Divide both the numerator and denominator by 8 (=GCD(1000,1024))
+ // to increase the number of ticks (frames) before the overflow tick is reached
+ TickType_t targetRenderTick = RoundedDiv((configTICK_RATE_HZ / 8) * alwaysOnFrameCount * alwaysOnRefreshPeriod, 1000 / 8);
// Assumptions
@@ -170,17 +178,17 @@ TickType_t DisplayApp::CalculateSleepTime() {
// Needed for division trick above
static_assert(configTICK_RATE_HZ % 8 == 0);
- // Local tick count must always wraparound before the system tick count does
- // As a static assert we can use 64 bit ints and therefore dodge overflows
+ // Frame count must always wraparound more often than the system tick count does
// Always on overflow time (ms) < system tick overflow time (ms)
- static_assert((uint64_t) overflowTick * (uint64_t) alwaysOnRefreshPeriod < (uint64_t) UINT32_MAX * 1000ULL / configTICK_RATE_HZ);
+ // Using 64bit ints here to avoid overflow
+ static_assert((uint64_t) overflowFrameCount * (uint64_t) alwaysOnRefreshPeriod < (uint64_t) UINT32_MAX * 1000ULL / configTICK_RATE_HZ);
- if (alwaysOnTickCount == overflowTick) {
- alwaysOnTickCount = 0;
+ if (alwaysOnFrameCount == overflowFrameCount) {
+ alwaysOnFrameCount = 0;
alwaysOnStartTime = xTaskGetTickCount();
}
- if (elapsedTarget > ticksElapsed) {
- return elapsedTarget - ticksElapsed;
+ if (targetRenderTick > ticksElapsed) {
+ return targetRenderTick - ticksElapsed;
} else {
return 0;
}
@@ -220,28 +228,27 @@ void DisplayApp::Refresh() {
TickType_t queueTimeout;
switch (state) {
case States::Idle:
- if (settingsController.GetAlwaysOnDisplay()) {
- if (!currentScreen->IsRunning()) {
- LoadPreviousScreen();
- }
- // Check we've slept long enough
- // Might not be true if the loop received an event
- // If not true, then wait that amount of time
- queueTimeout = CalculateSleepTime();
- if (queueTimeout == 0) {
- // Only advance the tick count when LVGL is done
- // Otherwise keep running the task handler while it still has things to draw
- // Note: under high graphics load, LVGL will always have more work to do
- if (lv_task_handler() > 0) {
- // Drop frames that we've missed if drawing/event handling took way longer than expected
- while (queueTimeout == 0) {
- alwaysOnTickCount += 1;
- queueTimeout = CalculateSleepTime();
- }
- };
+ queueTimeout = portMAX_DELAY;
+ break;
+ case States::AOD:
+ if (!currentScreen->IsRunning()) {
+ LoadPreviousScreen();
+ }
+ // Check we've slept long enough
+ // Might not be true if the loop received an event
+ // If not true, then wait that amount of time
+ queueTimeout = CalculateSleepTime();
+ if (queueTimeout == 0) {
+ // Only advance the tick count when LVGL is done
+ // Otherwise keep running the task handler while it still has things to draw
+ // Note: under high graphics load, LVGL will always have more work to do
+ if (lv_task_handler() > 0) {
+ // Drop frames that we've missed if drawing/event handling took way longer than expected
+ while (queueTimeout == 0) {
+ alwaysOnFrameCount += 1;
+ queueTimeout = CalculateSleepTime();
+ }
}
- } else {
- queueTimeout = portMAX_DELAY;
}
break;
case States::Running:
@@ -284,7 +291,14 @@ void DisplayApp::Refresh() {
if (xQueueReceive(msgQueue, &msg, queueTimeout) == pdTRUE) {
switch (msg) {
case Messages::GoToSleep:
- if (state != States::Running) {
+ case Messages::GoToAOD:
+ // Checking if SystemTask is sleeping is purely an optimisation.
+ // If it's no longer sleeping since it sent GoToSleep, it has
+ // cancelled the sleep and transitioned directly from
+ // GoingToSleep->Running, so we are about to receive GoToRunning
+ // and can ignore this message. If it wasn't ignored, DisplayApp
+ // would go to sleep and then immediately re-wake
+ if (state != States::Running || !systemTask->IsSleeping()) {
break;
}
while (brightnessController.Level() != Controllers::BrightnessController::Levels::Low) {
@@ -292,7 +306,7 @@ void DisplayApp::Refresh() {
vTaskDelay(100);
}
// Turn brightness down (or set to AlwaysOn mode)
- if (settingsController.GetAlwaysOnDisplay()) {
+ if (msg == Messages::GoToAOD) {
brightnessController.Set(Controllers::BrightnessController::Levels::AlwaysOn);
} else {
brightnessController.Set(Controllers::BrightnessController::Levels::Off);
@@ -305,26 +319,34 @@ void DisplayApp::Refresh() {
while (!lv_task_handler()) {
};
}
- // Turn LCD display off (or set to low power for AlwaysOn mode)
- if (settingsController.GetAlwaysOnDisplay()) {
+ // Clear any ongoing touch pressed events
+ // Without this LVGL gets stuck in the pressed state and will keep refreshing the
+ // display activity timer causing the screen to never sleep after timeout
+ lvgl.ClearTouchState();
+ if (msg == Messages::GoToAOD) {
lcd.LowPowerOn();
// Record idle entry time
- alwaysOnTickCount = 0;
+ alwaysOnFrameCount = 0;
alwaysOnStartTime = xTaskGetTickCount();
+ PushMessageToSystemTask(Pinetime::System::Messages::OnDisplayTaskAOD);
+ state = States::AOD;
} else {
lcd.Sleep();
+ PushMessageToSystemTask(Pinetime::System::Messages::OnDisplayTaskSleeping);
+ state = States::Idle;
}
- PushMessageToSystemTask(Pinetime::System::Messages::OnDisplayTaskSleeping);
- state = States::Idle;
break;
case Messages::NotifyDeviceActivity:
lv_disp_trig_activity(nullptr);
break;
case Messages::GoToRunning:
- if (state == States::Running) {
+ // If SystemTask is sleeping, the GoToRunning message is old
+ // and must be ignored. Otherwise DisplayApp will use SPI
+ // that is powered down and cause bad behaviour
+ if (state == States::Running || systemTask->IsSleeping()) {
break;
}
- if (settingsController.GetAlwaysOnDisplay()) {
+ if (state == States::AOD) {
lcd.LowPowerOff();
} else {
lcd.Wakeup();
@@ -459,7 +481,7 @@ void DisplayApp::Refresh() {
}
}
- if (touchHandler.IsTouching()) {
+ if (state == States::Running && touchHandler.IsTouching()) {
currentScreen->OnTouchEvent(touchHandler.GetX(), touchHandler.GetY());
}
diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h
index d443b8b217..2f276eaf9e 100644
--- a/src/displayapp/DisplayApp.h
+++ b/src/displayapp/DisplayApp.h
@@ -49,7 +49,7 @@ namespace Pinetime {
namespace Applications {
class DisplayApp {
public:
- enum class States { Idle, Running };
+ enum class States { Idle, Running, AOD };
enum class FullRefreshDirections { None, Up, Down, Left, Right, LeftAnim, RightAnim };
DisplayApp(Drivers::St7789& lcd,
@@ -139,7 +139,7 @@ namespace Pinetime {
bool isDimmed = false;
TickType_t CalculateSleepTime();
- TickType_t alwaysOnTickCount;
+ TickType_t alwaysOnFrameCount;
TickType_t alwaysOnStartTime;
// If this is to be changed, make sure the actual always on refresh rate is changed
// by configuring the LCD refresh timings
diff --git a/src/displayapp/LittleVgl.cpp b/src/displayapp/LittleVgl.cpp
index c70a08565b..c6f6f78477 100644
--- a/src/displayapp/LittleVgl.cpp
+++ b/src/displayapp/LittleVgl.cpp
@@ -248,6 +248,8 @@ void LittleVgl::SetNewTouchPoint(int16_t x, int16_t y, bool contact) {
}
}
+// Cancel an ongoing tap
+// Signifies that LVGL should not handle the current tap
void LittleVgl::CancelTap() {
if (tapped) {
isCancelled = true;
@@ -255,6 +257,13 @@ void LittleVgl::CancelTap() {
}
}
+// Clear the current tapped state
+// Signifies that touch input processing is suspended
+void LittleVgl::ClearTouchState() {
+ touchPoint = {-1, -1};
+ tapped = false;
+}
+
bool LittleVgl::GetTouchPadInfo(lv_indev_data_t* ptr) {
ptr->point.x = touchPoint.x;
ptr->point.y = touchPoint.y;
diff --git a/src/displayapp/LittleVgl.h b/src/displayapp/LittleVgl.h
index 9a15ae1599..54505b365d 100644
--- a/src/displayapp/LittleVgl.h
+++ b/src/displayapp/LittleVgl.h
@@ -26,6 +26,7 @@ namespace Pinetime {
void SetFullRefresh(FullRefreshDirections direction);
void SetNewTouchPoint(int16_t x, int16_t y, bool contact);
void CancelTap();
+ void ClearTouchState();
bool GetFullRefresh() {
bool returnValue = fullRefresh;
diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h
index dcfff4c297..d2abc8e58d 100644
--- a/src/displayapp/Messages.h
+++ b/src/displayapp/Messages.h
@@ -6,6 +6,7 @@ namespace Pinetime {
namespace Display {
enum class Messages : uint8_t {
GoToSleep,
+ GoToAOD,
GoToRunning,
UpdateBleConnection,
TouchEvent,
diff --git a/src/displayapp/fonts/CMakeLists.txt b/src/displayapp/fonts/CMakeLists.txt
index 22627efcad..562f0801ad 100644
--- a/src/displayapp/fonts/CMakeLists.txt
+++ b/src/displayapp/fonts/CMakeLists.txt
@@ -11,6 +11,7 @@ configure_file(${CMAKE_CURRENT_LIST_DIR}/jetbrains_mono_bold_20.c_M.patch
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12)
# FindPython3 module introduces with CMake 3.12
# https://cmake.org/cmake/help/latest/module/FindPython3.html
+ set(Python3_FIND_STRATEGY LOCATION) # https://discourse.cmake.org/t/find-package-python3-is-not-finding-the-correct-python/10563
find_package(Python3 REQUIRED)
else()
set(Python3_EXECUTABLE "python")
diff --git a/src/displayapp/screens/Timer.h b/src/displayapp/screens/Timer.h
index 0cb2bb0802..a07c729b4d 100644
--- a/src/displayapp/screens/Timer.h
+++ b/src/displayapp/screens/Timer.h
@@ -1,7 +1,6 @@
#pragma once
#include "displayapp/screens/Screen.h"
-#include "components/datetime/DateTimeController.h"
#include "systemtask/SystemTask.h"
#include "displayapp/LittleVgl.h"
#include "displayapp/widgets/Counter.h"
diff --git a/src/displayapp/screens/WatchFaceDigital.cpp b/src/displayapp/screens/WatchFaceDigital.cpp
index 2e00ee9819..d944117dd7 100644
--- a/src/displayapp/screens/WatchFaceDigital.cpp
+++ b/src/displayapp/screens/WatchFaceDigital.cpp
@@ -2,6 +2,7 @@
#include
#include
+
#include "displayapp/screens/NotificationIcon.h"
#include "displayapp/screens/Symbols.h"
#include "displayapp/screens/WeatherSymbols.h"
@@ -174,13 +175,12 @@ void WatchFaceDigital::Refresh() {
if (currentWeather.IsUpdated()) {
auto optCurrentWeather = currentWeather.Get();
if (optCurrentWeather) {
- int16_t temp = optCurrentWeather->temperature;
+ int16_t temp = optCurrentWeather->temperature.Celsius();
char tempUnit = 'C';
if (settingsController.GetWeatherFormat() == Controllers::Settings::WeatherFormat::Imperial) {
- temp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(temp);
+ temp = optCurrentWeather->temperature.Fahrenheit();
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 {
diff --git a/src/displayapp/screens/WatchFacePineTimeStyle.cpp b/src/displayapp/screens/WatchFacePineTimeStyle.cpp
index e56031f74a..22ccefc722 100644
--- a/src/displayapp/screens/WatchFacePineTimeStyle.cpp
+++ b/src/displayapp/screens/WatchFacePineTimeStyle.cpp
@@ -22,7 +22,7 @@
#include "displayapp/screens/WatchFacePineTimeStyle.h"
#include
#include
-#include
+#include "displayapp/Colors.h"
#include "displayapp/screens/BatteryIcon.h"
#include "displayapp/screens/BleIcon.h"
#include "displayapp/screens/NotificationIcon.h"
@@ -543,11 +543,10 @@ void WatchFacePineTimeStyle::Refresh() {
if (currentWeather.IsUpdated()) {
auto optCurrentWeather = currentWeather.Get();
if (optCurrentWeather) {
- int16_t temp = optCurrentWeather->temperature;
+ int16_t temp = optCurrentWeather->temperature.Celsius();
if (settingsController.GetWeatherFormat() == Controllers::Settings::WeatherFormat::Imperial) {
- temp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(temp);
+ temp = optCurrentWeather->temperature.Fahrenheit();
}
- temp = temp / 100 + (temp % 100 >= 50 ? 1 : 0);
lv_label_set_text_fmt(temperature, "%d°", temp);
lv_label_set_text(weatherIcon, Symbols::GetSymbol(optCurrentWeather->iconId));
} else {
diff --git a/src/displayapp/screens/Weather.cpp b/src/displayapp/screens/Weather.cpp
index 5321b7cc29..d3ee78efee 100644
--- a/src/displayapp/screens/Weather.cpp
+++ b/src/displayapp/screens/Weather.cpp
@@ -1,5 +1,7 @@
#include "displayapp/screens/Weather.h"
+
#include
+
#include "components/ble/SimpleWeatherService.h"
#include "components/datetime/DateTimeController.h"
#include "components/settings/Settings.h"
@@ -10,31 +12,27 @@
using namespace Pinetime::Applications::Screens;
namespace {
- lv_color_t TemperatureColor(int16_t temperature) {
- if (temperature <= 0) { // freezing
+ lv_color_t TemperatureColor(Pinetime::Controllers::SimpleWeatherService::Temperature temp) {
+ if (temp.Celsius() <= 0) { // freezing
return Colors::blue;
- } else if (temperature <= 400) { // ice
+ } else if (temp.Celsius() <= 4) { // ice
return LV_COLOR_CYAN;
- } else if (temperature >= 2700) { // hot
+ } else if (temp.Celsius() >= 27) { // hot
return Colors::deepOrange;
}
return Colors::orange; // normal
}
- uint8_t TemperatureStyle(int16_t temperature) {
- if (temperature <= 0) { // freezing
+ uint8_t TemperatureStyle(Pinetime::Controllers::SimpleWeatherService::Temperature temp) {
+ if (temp.Celsius() <= 0) { // freezing
return LV_TABLE_PART_CELL3;
- } else if (temperature <= 400) { // ice
+ } else if (temp.Celsius() <= 4) { // ice
return LV_TABLE_PART_CELL4;
- } else if (temperature >= 2700) { // hot
+ } else if (temp.Celsius() >= 27) { // hot
return LV_TABLE_PART_CELL6;
}
return LV_TABLE_PART_CELL5; // normal
}
-
- int16_t RoundTemperature(int16_t temp) {
- return temp = temp / 100 + (temp % 100 >= 50 ? 1 : 0);
- }
}
Weather::Weather(Controllers::Settings& settingsController, Controllers::SimpleWeatherService& weatherService)
@@ -120,22 +118,25 @@ void Weather::Refresh() {
if (currentWeather.IsUpdated()) {
auto optCurrentWeather = currentWeather.Get();
if (optCurrentWeather) {
- int16_t temp = optCurrentWeather->temperature;
- int16_t minTemp = optCurrentWeather->minTemperature;
- int16_t maxTemp = optCurrentWeather->maxTemperature;
- lv_obj_set_style_local_text_color(temperature, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, TemperatureColor(temp));
+ int16_t temp = optCurrentWeather->temperature.Celsius();
+ int16_t minTemp = optCurrentWeather->minTemperature.Celsius();
+ int16_t maxTemp = optCurrentWeather->maxTemperature.Celsius();
char tempUnit = 'C';
if (settingsController.GetWeatherFormat() == Controllers::Settings::WeatherFormat::Imperial) {
- temp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(temp);
- minTemp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(minTemp);
- maxTemp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(maxTemp);
+ temp = optCurrentWeather->temperature.Fahrenheit();
+ minTemp = optCurrentWeather->minTemperature.Fahrenheit();
+ maxTemp = optCurrentWeather->maxTemperature.Fahrenheit();
tempUnit = 'F';
}
+ lv_obj_set_style_local_text_color(temperature,
+ LV_LABEL_PART_MAIN,
+ LV_STATE_DEFAULT,
+ TemperatureColor(optCurrentWeather->temperature));
lv_label_set_text(icon, Symbols::GetSymbol(optCurrentWeather->iconId));
lv_label_set_text(condition, Symbols::GetCondition(optCurrentWeather->iconId));
- lv_label_set_text_fmt(temperature, "%d°%c", RoundTemperature(temp), tempUnit);
- lv_label_set_text_fmt(minTemperature, "%d°", RoundTemperature(minTemp));
- lv_label_set_text_fmt(maxTemperature, "%d°", RoundTemperature(maxTemp));
+ lv_label_set_text_fmt(temperature, "%d°%c", temp, tempUnit);
+ lv_label_set_text_fmt(minTemperature, "%d°", minTemp);
+ lv_label_set_text_fmt(maxTemperature, "%d°", maxTemp);
} else {
lv_label_set_text(icon, "");
lv_label_set_text(condition, "");
@@ -152,24 +153,22 @@ void Weather::Refresh() {
if (optCurrentForecast) {
std::tm localTime = *std::localtime(reinterpret_cast(&optCurrentForecast->timestamp));
- for (int i = 0; i < Controllers::SimpleWeatherService::MaxNbForecastDays; i++) {
- int16_t maxTemp = optCurrentForecast->days[i].maxTemperature;
- int16_t minTemp = optCurrentForecast->days[i].minTemperature;
- lv_table_set_cell_type(forecast, 2, i, TemperatureStyle(maxTemp));
- lv_table_set_cell_type(forecast, 3, i, TemperatureStyle(minTemp));
+ for (int i = 0; i < optCurrentForecast->nbDays; i++) {
+ int16_t minTemp = optCurrentForecast->days[i]->minTemperature.Celsius();
+ int16_t maxTemp = optCurrentForecast->days[i]->maxTemperature.Celsius();
if (settingsController.GetWeatherFormat() == Controllers::Settings::WeatherFormat::Imperial) {
- maxTemp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(maxTemp);
- minTemp = Controllers::SimpleWeatherService::CelsiusToFahrenheit(minTemp);
+ minTemp = optCurrentForecast->days[i]->maxTemperature.Fahrenheit();
+ maxTemp = optCurrentForecast->days[i]->minTemperature.Fahrenheit();
}
+ lv_table_set_cell_type(forecast, 2, i, TemperatureStyle(optCurrentForecast->days[i]->maxTemperature));
+ lv_table_set_cell_type(forecast, 3, i, TemperatureStyle(optCurrentForecast->days[i]->minTemperature));
uint8_t wday = localTime.tm_wday + i + 1;
if (wday > 7) {
wday -= 7;
}
- maxTemp = RoundTemperature(maxTemp);
- minTemp = RoundTemperature(minTemp);
const char* dayOfWeek = Controllers::DateTime::DayOfWeekShortToStringLow(static_cast(wday));
lv_table_set_cell_value(forecast, 0, i, dayOfWeek);
- lv_table_set_cell_value(forecast, 1, i, Symbols::GetSymbol(optCurrentForecast->days[i].iconId));
+ lv_table_set_cell_value(forecast, 1, i, Symbols::GetSymbol(optCurrentForecast->days[i]->iconId));
// Pad cells based on the largest number of digits on each column
char maxPadding[3] = " ";
char minPadding[3] = " ";
diff --git a/src/displayapp/screens/settings/Settings.h b/src/displayapp/screens/settings/Settings.h
index a21b4ccd85..3722c2be39 100644
--- a/src/displayapp/screens/settings/Settings.h
+++ b/src/displayapp/screens/settings/Settings.h
@@ -38,7 +38,7 @@ namespace Pinetime {
{Symbols::home, "Watch face", Apps::SettingWatchFace},
{Symbols::shoe, "Steps", Apps::SettingSteps},
- {Symbols::clock, "Date&Time", Apps::SettingSetDateTime},
+ {Symbols::clock, "Date & Time", Apps::SettingSetDateTime},
{Symbols::cloudSunRain, "Weather", Apps::SettingWeatherFormat},
{Symbols::batteryHalf, "Battery", Apps::BatteryInfo},
diff --git a/src/drivers/St7789.cpp b/src/drivers/St7789.cpp
index 0df19b452e..482fbad6bd 100644
--- a/src/drivers/St7789.cpp
+++ b/src/drivers/St7789.cpp
@@ -175,9 +175,8 @@ void St7789::IdleFrameRateOn() {
// According to the datasheet, these controls should apply only to partial/idle mode
// However they appear to apply to normal mode, so we have to enable/disable
// every time we enter/exit always on
- // In testing this divider appears to actually be 16x?
constexpr uint8_t args[] = {
- 0x13, // Enable frame rate control for partial/idle mode, 8x frame divider
+ 0x12, // Enable frame rate control for partial/idle mode, 4x frame divider
0x1e, // Idle mode frame rate
0x1e, // Partial mode frame rate (unused)
};
diff --git a/src/main.cpp b/src/main.cpp
index 84f30eeffc..24f13caddd 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -168,7 +168,7 @@ std::chrono::time_point NoI
void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
if (pin == Pinetime::PinMap::Cst816sIrq) {
- systemTask.OnTouchEvent();
+ systemTask.PushMessage(Pinetime::System::Messages::OnTouchEvent);
return;
}
diff --git a/src/resources/CMakeLists.txt b/src/resources/CMakeLists.txt
index 3834e854fe..9181d4a626 100644
--- a/src/resources/CMakeLists.txt
+++ b/src/resources/CMakeLists.txt
@@ -10,6 +10,7 @@ message(STATUS "Using ${LV_IMG_CONV} to generate font files")
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12)
# FindPython3 module introduces with CMake 3.12
# https://cmake.org/cmake/help/latest/module/FindPython3.html
+ set(Python3_FIND_STRATEGY LOCATION) # https://discourse.cmake.org/t/find-package-python3-is-not-finding-the-correct-python/10563
find_package(Python3 REQUIRED)
else()
set(Python3_EXECUTABLE "python")
diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h
index 81be9151eb..fee94bb747 100644
--- a/src/systemtask/Messages.h
+++ b/src/systemtask/Messages.h
@@ -6,7 +6,6 @@ namespace Pinetime {
enum class Messages : uint8_t {
GoToSleep,
GoToRunning,
- TouchWakeUp,
OnNewTime,
OnNewNotification,
OnNewCall,
@@ -17,6 +16,7 @@ namespace Pinetime {
HandleButtonEvent,
HandleButtonTimerEvent,
OnDisplayTaskSleeping,
+ OnDisplayTaskAOD,
EnableSleeping,
DisableSleeping,
OnNewDay,
diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp
index fc4e8f7ec6..eb013d6d1a 100644
--- a/src/systemtask/SystemTask.cpp
+++ b/src/systemtask/SystemTask.cpp
@@ -198,20 +198,6 @@ void SystemTask::Work() {
case Messages::GoToRunning:
GoToRunning();
break;
- case Messages::TouchWakeUp: {
- if (touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo())) {
- auto gesture = touchHandler.GestureGet();
- if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep &&
- gesture != Pinetime::Applications::TouchEvents::None &&
- ((gesture == Pinetime::Applications::TouchEvents::DoubleTap &&
- settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) ||
- (gesture == Pinetime::Applications::TouchEvents::Tap &&
- settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) {
- GoToRunning();
- }
- }
- break;
- }
case Messages::GoToSleep:
GoToSleep();
break;
@@ -260,8 +246,23 @@ void SystemTask::Work() {
// TODO add intent of fs access icon or something
break;
case Messages::OnTouchEvent:
- if (touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo())) {
+ // Finish immediately if no new events
+ if (!touchHandler.ProcessTouchInfo(touchPanel.GetTouchInfo())) {
+ break;
+ }
+ if (state == SystemTaskState::Running) {
displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent);
+ } else {
+ // If asleep, check for touch panel wake triggers
+ auto gesture = touchHandler.GestureGet();
+ if (settingsController.GetNotificationStatus() != Controllers::Settings::Notification::Sleep &&
+ gesture != Pinetime::Applications::TouchEvents::None &&
+ ((gesture == Pinetime::Applications::TouchEvents::DoubleTap &&
+ settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) ||
+ (gesture == Pinetime::Applications::TouchEvents::Tap &&
+ settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) {
+ GoToRunning();
+ }
}
break;
case Messages::HandleButtonEvent: {
@@ -284,9 +285,10 @@ void SystemTask::Work() {
HandleButtonAction(action);
} break;
case Messages::OnDisplayTaskSleeping:
+ case Messages::OnDisplayTaskAOD:
// The state was set to GoingToSleep when GoToSleep() was called
// If the state is no longer GoingToSleep, we have since transitioned back to Running
- // In this case absorb the OnDisplayTaskSleeping
+ // In this case absorb the OnDisplayTaskSleeping/AOD
// as DisplayApp is about to receive GoToRunning
if (state != SystemTaskState::GoingToSleep) {
break;
@@ -298,7 +300,7 @@ void SystemTask::Work() {
}
// Must keep SPI awake when still updating the display for always on
- if (!settingsController.GetAlwaysOnDisplay()) {
+ if (msg == Messages::OnDisplayTaskSleeping) {
spi.Sleep();
}
@@ -307,7 +309,11 @@ void SystemTask::Work() {
touchPanel.Sleep();
}
- state = SystemTaskState::Sleeping;
+ if (msg == Messages::OnDisplayTaskSleeping) {
+ state = SystemTaskState::Sleeping;
+ } else {
+ state = SystemTaskState::AODSleeping;
+ }
break;
case Messages::OnNewDay:
// We might be sleeping (with TWI device disabled.
@@ -381,17 +387,19 @@ void SystemTask::GoToRunning() {
if (state == SystemTaskState::Running) {
return;
}
- // SPI doesn't go to sleep for always on mode
- if (!settingsController.GetAlwaysOnDisplay()) {
- spi.Wakeup();
- }
+ if (state == SystemTaskState::Sleeping || state == SystemTaskState::AODSleeping) {
+ // SPI only switched off when entering Sleeping, not AOD or GoingToSleep
+ if (state == SystemTaskState::Sleeping) {
+ spi.Wakeup();
+ }
- // Double Tap needs the touch screen to be in normal mode
- if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
- touchPanel.Wakeup();
- }
+ // Double Tap needs the touch screen to be in normal mode
+ if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
+ touchPanel.Wakeup();
+ }
- spiNorFlash.Wakeup();
+ spiNorFlash.Wakeup();
+ }
displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToRunning);
heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::WakeUp);
@@ -411,16 +419,22 @@ void SystemTask::GoToSleep() {
return;
}
NRF_LOG_INFO("[systemtask] Going to sleep");
- displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToSleep);
+ if (settingsController.GetAlwaysOnDisplay()) {
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToAOD);
+ } else {
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToSleep);
+ }
heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep);
state = SystemTaskState::GoingToSleep;
};
void SystemTask::UpdateMotion() {
- if (IsSleeping() && !(settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) ||
- settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) ||
- motionController.GetService()->IsMotionNotificationSubscribed())) {
+ // Only consider disabling motion updates specifically in the Sleeping state
+ // AOD needs motion on to show up to date step counts
+ if (state == SystemTaskState::Sleeping && !(settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) ||
+ settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::Shake) ||
+ motionController.GetService()->IsMotionNotificationSubscribed())) {
return;
}
@@ -479,17 +493,6 @@ void SystemTask::HandleButtonAction(Controllers::ButtonActions action) {
fastWakeUpDone = false;
}
-void SystemTask::OnTouchEvent() {
- if (state == SystemTaskState::Running) {
- PushMessage(Messages::OnTouchEvent);
- } else {
- if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap) or
- settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
- PushMessage(Messages::TouchWakeUp);
- }
- }
-}
-
void SystemTask::PushMessage(System::Messages msg) {
if (in_isr()) {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h
index 8a4e595486..0060e36096 100644
--- a/src/systemtask/SystemTask.h
+++ b/src/systemtask/SystemTask.h
@@ -52,7 +52,7 @@ namespace Pinetime {
namespace System {
class SystemTask {
public:
- enum class SystemTaskState { Sleeping, Running, GoingToSleep };
+ enum class SystemTaskState { Sleeping, Running, GoingToSleep, AODSleeping };
SystemTask(Drivers::SpiMaster& spi,
Pinetime::Drivers::SpiNorFlash& spiNorFlash,
Drivers::TwiMaster& twiMaster,
@@ -77,8 +77,6 @@ namespace Pinetime {
void Start();
void PushMessage(Messages msg);
- void OnTouchEvent();
-
bool IsSleepDisabled() {
return wakeLocksHeld > 0;
}