Merge branch 'JF002:develop' into set-datetime-manually
This commit is contained in:
@@ -166,6 +166,13 @@ set(NIMBLE_SRC
|
||||
libs/mynewt-nimble/nimble/host/util/src/addr.c
|
||||
)
|
||||
|
||||
set(LITTLEFS_SRC
|
||||
libs/littlefs/lfs_util.h
|
||||
libs/littlefs/lfs.h
|
||||
libs/littlefs/lfs_util.c
|
||||
libs/littlefs/lfs.c
|
||||
)
|
||||
|
||||
set(LVGL_SRC
|
||||
libs/lv_conf.h
|
||||
libs/lvgl/lvgl.h
|
||||
@@ -467,6 +474,7 @@ list(APPEND SOURCE_FILES
|
||||
components/motor/MotorController.cpp
|
||||
components/settings/Settings.cpp
|
||||
components/timer/TimerController.cpp
|
||||
components/fs/FS.cpp
|
||||
drivers/Cst816s.cpp
|
||||
FreeRTOS/port.c
|
||||
FreeRTOS/port_cmsis_systick.c
|
||||
@@ -545,6 +553,7 @@ list(APPEND RECOVERY_SOURCE_FILES
|
||||
components/heartrate/Biquad.cpp
|
||||
components/heartrate/Ptagc.cpp
|
||||
components/motor/MotorController.cpp
|
||||
components/fs/FS.cpp
|
||||
)
|
||||
|
||||
list(APPEND RECOVERYLOADER_SOURCE_FILES
|
||||
@@ -803,13 +812,25 @@ target_compile_options(lvgl PRIVATE
|
||||
$<$<COMPILE_LANGUAGE:ASM>: -MP -MD -x assembler-with-cpp>
|
||||
)
|
||||
|
||||
# LITTLEFS_SRC
|
||||
add_library(littlefs STATIC ${LITTLEFS_SRC})
|
||||
target_include_directories(littlefs SYSTEM PUBLIC . ../)
|
||||
target_include_directories(littlefs SYSTEM PUBLIC ${INCLUDES_FROM_LIBS})
|
||||
target_compile_options(littlefs PRIVATE
|
||||
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Wno-unused-function -Og -g3>
|
||||
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -Wno-unused-function -Os>
|
||||
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Wno-unused-function -Og -g3 -fno-rtti>
|
||||
$<$<AND:$<COMPILE_LANGUAGE:CXX>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -Wno-unused-function -Os -fno-rtti>
|
||||
$<$<COMPILE_LANGUAGE:ASM>: -MP -MD -x assembler-with-cpp>
|
||||
)
|
||||
|
||||
# Build autonomous binary (without support for bootloader)
|
||||
set(EXECUTABLE_NAME "pinetime-app")
|
||||
set(EXECUTABLE_FILE_NAME ${EXECUTABLE_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH})
|
||||
set(NRF5_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/gcc_nrf52.ld")
|
||||
add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES})
|
||||
set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_FILE_NAME})
|
||||
target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl)
|
||||
target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl littlefs)
|
||||
target_compile_options(${EXECUTABLE_NAME} PUBLIC
|
||||
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Og -g3>
|
||||
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:RELEASE>>: ${COMMON_FLAGS} -Os>
|
||||
@@ -838,7 +859,7 @@ set(IMAGE_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-image-${pinetime_VERSION_
|
||||
set(DFU_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip)
|
||||
set(NRF5_LINKER_SCRIPT_MCUBOOT "${CMAKE_SOURCE_DIR}/gcc_nrf52-mcuboot.ld")
|
||||
add_executable(${EXECUTABLE_MCUBOOT_NAME} ${SOURCE_FILES})
|
||||
target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl)
|
||||
target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl littlefs)
|
||||
set_target_properties(${EXECUTABLE_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_MCUBOOT_FILE_NAME})
|
||||
target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC
|
||||
$<$<AND:$<COMPILE_LANGUAGE:C>,$<CONFIG:DEBUG>>: ${COMMON_FLAGS} -Og -g3>
|
||||
@@ -874,7 +895,7 @@ endif()
|
||||
set(EXECUTABLE_RECOVERY_NAME "pinetime-recovery")
|
||||
set(EXECUTABLE_RECOVERY_FILE_NAME ${EXECUTABLE_RECOVERY_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH})
|
||||
add_executable(${EXECUTABLE_RECOVERY_NAME} ${RECOVERY_SOURCE_FILES})
|
||||
target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk)
|
||||
target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk littlefs)
|
||||
set_target_properties(${EXECUTABLE_RECOVERY_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_FILE_NAME})
|
||||
target_compile_definitions(${EXECUTABLE_RECOVERY_NAME} PUBLIC "PINETIME_IS_RECOVERY")
|
||||
target_compile_options(${EXECUTABLE_RECOVERY_NAME} PUBLIC
|
||||
@@ -904,7 +925,7 @@ set(EXECUTABLE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-${
|
||||
set(IMAGE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-image-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.bin)
|
||||
set(DFU_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip)
|
||||
add_executable(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} ${RECOVERY_SOURCE_FILES})
|
||||
target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk)
|
||||
target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk littlefs)
|
||||
set_target_properties(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_FILE_NAME})
|
||||
target_compile_definitions(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC "PINETIME_IS_RECOVERY")
|
||||
target_compile_options(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC
|
||||
|
@@ -77,7 +77,7 @@
|
||||
#define configENABLE_BACKWARD_COMPATIBILITY 1
|
||||
|
||||
/* Hook function related definitions. */
|
||||
#define configUSE_IDLE_HOOK 1
|
||||
#define configUSE_IDLE_HOOK 0
|
||||
#define configUSE_TICK_HOOK 0
|
||||
#define configCHECK_FOR_STACK_OVERFLOW 0
|
||||
#define configUSE_MALLOC_FAILED_HOOK 0
|
||||
|
@@ -1,9 +1,7 @@
|
||||
#include "BatteryController.h"
|
||||
#include <hal/nrf_gpio.h>
|
||||
#include <nrfx_saadc.h>
|
||||
#include <libraries/log/nrf_log.h>
|
||||
#include <algorithm>
|
||||
#include <math.h>
|
||||
|
||||
using namespace Pinetime::Controllers;
|
||||
|
||||
@@ -18,7 +16,6 @@ void Battery::Init() {
|
||||
}
|
||||
|
||||
void Battery::Update() {
|
||||
|
||||
isCharging = !nrf_gpio_pin_read(chargingPin);
|
||||
isPowerPresent = !nrf_gpio_pin_read(powerPresentPin);
|
||||
|
||||
@@ -33,13 +30,13 @@ void Battery::Update() {
|
||||
nrfx_saadc_sample();
|
||||
}
|
||||
|
||||
void Battery::adcCallbackStatic(nrfx_saadc_evt_t const* event) {
|
||||
void Battery::AdcCallbackStatic(nrfx_saadc_evt_t const* event) {
|
||||
instance->SaadcEventHandler(event);
|
||||
}
|
||||
|
||||
void Battery::SaadcInit() {
|
||||
nrfx_saadc_config_t adcConfig = NRFX_SAADC_DEFAULT_CONFIG;
|
||||
APP_ERROR_CHECK(nrfx_saadc_init(&adcConfig, adcCallbackStatic));
|
||||
APP_ERROR_CHECK(nrfx_saadc_init(&adcConfig, AdcCallbackStatic));
|
||||
|
||||
nrf_saadc_channel_config_t adcChannelConfig = {.resistor_p = NRF_SAADC_RESISTOR_DISABLED,
|
||||
.resistor_n = NRF_SAADC_RESISTOR_DISABLED,
|
||||
@@ -55,7 +52,6 @@ void Battery::SaadcInit() {
|
||||
}
|
||||
|
||||
void Battery::SaadcEventHandler(nrfx_saadc_evt_t const* p_event) {
|
||||
|
||||
const uint16_t battery_max = 4180; // maximum voltage of battery ( max charging voltage is 4.21 )
|
||||
const uint16_t battery_min = 3200; // minimum voltage of battery before shutdown ( depends on the battery )
|
||||
|
||||
@@ -69,13 +65,10 @@ void Battery::SaadcEventHandler(nrfx_saadc_evt_t const* p_event) {
|
||||
// reference_voltage is 0.6V
|
||||
// p_event->data.done.p_buffer[0] = (adc_voltage / reference_voltage) * 1024
|
||||
voltage = p_event->data.done.p_buffer[0] * 6000 / 1024;
|
||||
|
||||
percentRemaining = (voltage - battery_min) * 100 / (battery_max - battery_min);
|
||||
|
||||
percentRemaining = std::max(percentRemaining, 0);
|
||||
percentRemaining = std::min(percentRemaining, 100);
|
||||
|
||||
percentRemainingBuffer.insert(percentRemaining);
|
||||
percentRemainingBuffer.Insert(percentRemaining);
|
||||
|
||||
samples++;
|
||||
if (samples > percentRemainingSamples) {
|
||||
|
@@ -19,7 +19,7 @@ namespace Pinetime {
|
||||
insert member function overwrites the next data to the current
|
||||
HEAD and moves the HEAD to the newly inserted value.
|
||||
*/
|
||||
void insert(const int num) {
|
||||
void Insert(const uint8_t num) {
|
||||
head %= cap;
|
||||
arr[head++] = num;
|
||||
if (sz != cap) {
|
||||
@@ -27,13 +27,13 @@ namespace Pinetime {
|
||||
}
|
||||
}
|
||||
|
||||
int GetAverage() const {
|
||||
uint8_t GetAverage() const {
|
||||
int sum = std::accumulate(arr.begin(), arr.end(), 0);
|
||||
return (sum / sz);
|
||||
return static_cast<uint8_t>(sum / sz);
|
||||
}
|
||||
|
||||
private:
|
||||
std::array<int, N> arr; /**< internal array used to store the values*/
|
||||
std::array<uint8_t, N> arr; /**< internal array used to store the values*/
|
||||
uint8_t sz; /**< The current size of the array.*/
|
||||
uint8_t cap; /**< Total capacity of the CircBuffer.*/
|
||||
uint8_t head; /**< The current head of the CircBuffer*/
|
||||
@@ -46,8 +46,11 @@ namespace Pinetime {
|
||||
void Init();
|
||||
void Update();
|
||||
|
||||
int PercentRemaining() const {
|
||||
return percentRemainingBuffer.GetAverage();
|
||||
uint8_t PercentRemaining() const {
|
||||
auto avg = percentRemainingBuffer.GetAverage();
|
||||
avg = std::min(avg, static_cast<uint8_t>(100));
|
||||
avg = std::max(avg, static_cast<uint8_t>(0));
|
||||
return avg;
|
||||
}
|
||||
|
||||
uint16_t Voltage() const {
|
||||
@@ -57,6 +60,7 @@ namespace Pinetime {
|
||||
bool IsCharging() const {
|
||||
return isCharging;
|
||||
}
|
||||
|
||||
bool IsPowerPresent() const {
|
||||
return isPowerPresent;
|
||||
}
|
||||
@@ -80,7 +84,7 @@ namespace Pinetime {
|
||||
void SaadcInit();
|
||||
|
||||
void SaadcEventHandler(nrfx_saadc_evt_t const* p_event);
|
||||
static void adcCallbackStatic(nrfx_saadc_evt_t const* event);
|
||||
static void AdcCallbackStatic(nrfx_saadc_evt_t const* event);
|
||||
|
||||
bool isReading = false;
|
||||
uint8_t samples = 0;
|
||||
|
@@ -17,7 +17,7 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte
|
||||
characteristicDefinition {{.uuid = (ble_uuid_t*) &batteryLevelUuid,
|
||||
.access_cb = BatteryInformationServiceCallback,
|
||||
.arg = this,
|
||||
.flags = BLE_GATT_CHR_F_READ,
|
||||
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
|
||||
.val_handle = &batteryLevelHandle},
|
||||
{0}},
|
||||
serviceDefinition {
|
||||
@@ -48,4 +48,8 @@ int BatteryInformationService::OnBatteryServiceRequested(uint16_t connectionHand
|
||||
return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
void BatteryInformationService::NotifyBatteryLevel(uint16_t connectionHandle, uint8_t level) {
|
||||
auto* om = ble_hs_mbuf_from_flat(&level, 1);
|
||||
ble_gattc_notify_custom(connectionHandle, batteryLevelHandle, om);
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@ namespace Pinetime {
|
||||
void Init();
|
||||
|
||||
int OnBatteryServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context);
|
||||
|
||||
void NotifyBatteryLevel(uint16_t connectionHandle, uint8_t level);
|
||||
private:
|
||||
Controllers::Battery& batteryController;
|
||||
static constexpr uint16_t batteryInformationServiceId {0x180F};
|
||||
|
@@ -266,13 +266,14 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf* om) {
|
||||
static_cast<uint8_t>(ErrorCodes::NoError)};
|
||||
notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
|
||||
} else {
|
||||
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
|
||||
NRF_LOG_INFO("Image Error : bad CRC");
|
||||
|
||||
uint8_t data[3] {static_cast<uint8_t>(Opcodes::Response),
|
||||
static_cast<uint8_t>(Opcodes::ValidateFirmware),
|
||||
static_cast<uint8_t>(ErrorCodes::CrcError)};
|
||||
notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
|
||||
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
|
||||
Reset();
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -283,10 +284,8 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf* om) {
|
||||
return 0;
|
||||
}
|
||||
NRF_LOG_INFO("[DFU] -> Activate image and reset!");
|
||||
bleController.StopFirmwareUpdate();
|
||||
systemTask.PushMessage(Pinetime::System::Messages::BleFirmwareUpdateFinished);
|
||||
Reset();
|
||||
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated);
|
||||
Reset();
|
||||
return 0;
|
||||
default:
|
||||
return 0;
|
||||
@@ -294,6 +293,7 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf* om) {
|
||||
}
|
||||
|
||||
void DfuService::OnTimeout() {
|
||||
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
|
||||
Reset();
|
||||
}
|
||||
|
||||
@@ -307,7 +307,6 @@ void DfuService::Reset() {
|
||||
applicationSize = 0;
|
||||
expectedCrc = 0;
|
||||
notificationManager.Reset();
|
||||
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
|
||||
bleController.StopFirmwareUpdate();
|
||||
systemTask.PushMessage(Pinetime::System::Messages::BleFirmwareUpdateFinished);
|
||||
}
|
||||
|
@@ -235,3 +235,9 @@ void NimbleController::StartDiscovery() {
|
||||
uint16_t NimbleController::connHandle() {
|
||||
return connectionHandle;
|
||||
}
|
||||
|
||||
void NimbleController::NotifyBatteryLevel(uint8_t level) {
|
||||
if(connectionHandle != BLE_HS_CONN_HANDLE_NONE) {
|
||||
batteryInformationService.NotifyBatteryLevel(connectionHandle, level);
|
||||
}
|
||||
}
|
||||
|
@@ -70,6 +70,7 @@ namespace Pinetime {
|
||||
};
|
||||
|
||||
uint16_t connHandle();
|
||||
void NotifyBatteryLevel(uint8_t level);
|
||||
|
||||
private:
|
||||
static constexpr const char* deviceName = "InfiniTime";
|
||||
@@ -92,7 +93,7 @@ namespace Pinetime {
|
||||
HeartRateService heartRateService;
|
||||
|
||||
uint8_t addrType; // 1 = Random, 0 = PUBLIC
|
||||
uint16_t connectionHandle = 0;
|
||||
uint16_t connectionHandle = BLE_HS_CONN_HANDLE_NONE;
|
||||
|
||||
ble_uuid128_t dfuServiceUuid {
|
||||
.u {.type = BLE_UUID_TYPE_128},
|
||||
|
197
src/components/fs/FS.cpp
Normal file
197
src/components/fs/FS.cpp
Normal file
@@ -0,0 +1,197 @@
|
||||
#include "FS.h"
|
||||
#include <cstring>
|
||||
#include <littlefs/lfs.h>
|
||||
#include <lvgl/lvgl.h>
|
||||
|
||||
using namespace Pinetime::Controllers;
|
||||
|
||||
FS::FS(Pinetime::Drivers::SpiNorFlash& driver) :
|
||||
flashDriver{ driver },
|
||||
lfsConfig{
|
||||
.context = this,
|
||||
.read = SectorRead,
|
||||
.prog = SectorProg,
|
||||
.erase = SectorErase,
|
||||
.sync = SectorSync,
|
||||
|
||||
.read_size = 16,
|
||||
.prog_size = 8,
|
||||
.block_size = blockSize,
|
||||
.block_count = size / blockSize,
|
||||
.block_cycles = 1000u,
|
||||
|
||||
.cache_size = 16,
|
||||
.lookahead_size = 16,
|
||||
|
||||
.name_max = 50,
|
||||
.attr_max = 50,
|
||||
}
|
||||
{ }
|
||||
|
||||
|
||||
void FS::Init() {
|
||||
|
||||
// try mount
|
||||
int err = lfs_mount(&lfs, &lfsConfig);
|
||||
|
||||
// reformat if we can't mount the filesystem
|
||||
// this should only happen on the first boot
|
||||
if (err != LFS_ERR_OK) {
|
||||
lfs_format(&lfs, &lfsConfig);
|
||||
err = lfs_mount(&lfs, &lfsConfig);
|
||||
if (err != LFS_ERR_OK) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PINETIME_IS_RECOVERY
|
||||
VerifyResource();
|
||||
LVGLFileSystemInit();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
void FS::VerifyResource() {
|
||||
// validate the resource metadata
|
||||
resourcesValid = true;
|
||||
}
|
||||
|
||||
int FS::FileOpen(lfs_file_t* file_p, const char* fileName, const int flags) {
|
||||
return lfs_file_open(&lfs, file_p, fileName, flags);
|
||||
}
|
||||
|
||||
int FS::FileClose(lfs_file_t* file_p) {
|
||||
return lfs_file_close(&lfs, file_p);
|
||||
}
|
||||
|
||||
int FS::FileRead(lfs_file_t* file_p, uint8_t* buff, uint32_t size) {
|
||||
return lfs_file_read(&lfs, file_p, buff, size);
|
||||
}
|
||||
|
||||
int FS::FileWrite(lfs_file_t* file_p, const uint8_t* buff, uint32_t size) {
|
||||
return lfs_file_write(&lfs, file_p, buff, size);
|
||||
}
|
||||
|
||||
int FS::FileSeek(lfs_file_t* file_p, uint32_t pos) {
|
||||
return lfs_file_seek(&lfs, file_p, pos, LFS_SEEK_SET);
|
||||
}
|
||||
|
||||
int FS::FileDelete(const char* fileName) {
|
||||
return lfs_remove(&lfs, fileName);
|
||||
}
|
||||
|
||||
|
||||
int FS::DirCreate(const char* path) {
|
||||
return lfs_mkdir(&lfs, path);
|
||||
}
|
||||
|
||||
// Delete directory and all files inside
|
||||
int FS::DirDelete(const char* path) {
|
||||
|
||||
lfs_dir_t lfs_dir;
|
||||
lfs_info entryInfo;
|
||||
|
||||
int err;
|
||||
err = lfs_dir_open(&lfs, &lfs_dir, path);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
while (lfs_dir_read(&lfs, &lfs_dir, &entryInfo)) {
|
||||
lfs_remove(&lfs, entryInfo.name);
|
||||
}
|
||||
lfs_dir_close(&lfs, &lfs_dir);
|
||||
return LFS_ERR_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
----------- Interface between littlefs and SpiNorFlash -----------
|
||||
|
||||
*/
|
||||
int FS::SectorSync(const struct lfs_config* c) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FS::SectorErase(const struct lfs_config* c, lfs_block_t block) {
|
||||
Pinetime::Controllers::FS& lfs = *(static_cast<Pinetime::Controllers::FS*>(c->context));
|
||||
const size_t address = startAddress + (block * blockSize);
|
||||
lfs.flashDriver.SectorErase(address);
|
||||
return lfs.flashDriver.EraseFailed() ? -1 : 0;
|
||||
}
|
||||
|
||||
int FS::SectorProg(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, const void* buffer, lfs_size_t size) {
|
||||
Pinetime::Controllers::FS& lfs = *(static_cast<Pinetime::Controllers::FS*>(c->context));
|
||||
const size_t address = startAddress + (block * blockSize) + off;
|
||||
lfs.flashDriver.Write(address, (uint8_t*) buffer, size);
|
||||
return lfs.flashDriver.ProgramFailed() ? -1 : 0;
|
||||
}
|
||||
|
||||
int FS::SectorRead(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size) {
|
||||
Pinetime::Controllers::FS& lfs = *(static_cast<Pinetime::Controllers::FS*>(c->context));
|
||||
const size_t address = startAddress + (block * blockSize) + off;
|
||||
lfs.flashDriver.Read(address, static_cast<uint8_t*>(buffer), size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
----------- LVGL filesystem integration -----------
|
||||
|
||||
*/
|
||||
|
||||
namespace {
|
||||
lv_fs_res_t lvglOpen(lv_fs_drv_t* drv, void* file_p, const char* path, lv_fs_mode_t mode) {
|
||||
|
||||
lfs_file_t* file = static_cast<lfs_file_t*>(file_p);
|
||||
FS* filesys = static_cast<FS*>(drv->user_data);
|
||||
filesys->FileOpen(file, path, LFS_O_RDONLY);
|
||||
|
||||
if (file->type == 0) {
|
||||
return LV_FS_RES_FS_ERR;
|
||||
}
|
||||
else {
|
||||
return LV_FS_RES_OK;
|
||||
}
|
||||
}
|
||||
|
||||
lv_fs_res_t lvglClose(lv_fs_drv_t* drv, void* file_p) {
|
||||
FS* filesys = static_cast<FS*>(drv->user_data);
|
||||
lfs_file_t* file = static_cast<lfs_file_t*>(file_p);
|
||||
filesys->FileClose(file);
|
||||
|
||||
return LV_FS_RES_OK;
|
||||
}
|
||||
|
||||
lv_fs_res_t lvglRead(lv_fs_drv_t* drv, void* file_p, void* buf, uint32_t btr, uint32_t* br) {
|
||||
FS* filesys = static_cast<FS*>(drv->user_data);
|
||||
lfs_file_t* file = static_cast<lfs_file_t*>(file_p);
|
||||
filesys->FileRead(file, static_cast<uint8_t*>(buf), btr);
|
||||
*br = btr;
|
||||
return LV_FS_RES_OK;
|
||||
}
|
||||
|
||||
lv_fs_res_t lvglSeek(lv_fs_drv_t* drv, void* file_p, uint32_t pos) {
|
||||
FS* filesys = static_cast<FS*>(drv->user_data);
|
||||
lfs_file_t* file = static_cast<lfs_file_t*>(file_p);
|
||||
filesys->FileSeek(file, pos);
|
||||
return LV_FS_RES_OK;
|
||||
}
|
||||
}
|
||||
|
||||
void FS::LVGLFileSystemInit() {
|
||||
|
||||
lv_fs_drv_t fs_drv;
|
||||
lv_fs_drv_init(&fs_drv);
|
||||
|
||||
fs_drv.file_size = sizeof(lfs_file_t);
|
||||
fs_drv.letter = 'F';
|
||||
fs_drv.open_cb = lvglOpen;
|
||||
fs_drv.close_cb = lvglClose;
|
||||
fs_drv.read_cb = lvglRead;
|
||||
fs_drv.seek_cb = lvglSeek;
|
||||
|
||||
fs_drv.user_data = this;
|
||||
|
||||
lv_fs_drv_register(&fs_drv);
|
||||
|
||||
}
|
71
src/components/fs/FS.h
Normal file
71
src/components/fs/FS.h
Normal file
@@ -0,0 +1,71 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include "drivers/SpiNorFlash.h"
|
||||
#include <littlefs/lfs.h>
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Controllers {
|
||||
class FS {
|
||||
public:
|
||||
FS(Pinetime::Drivers::SpiNorFlash&);
|
||||
|
||||
void Init();
|
||||
void LVGLFileSystemInit();
|
||||
|
||||
int FileOpen(lfs_file_t* file_p, const char* fileName, const int flags);
|
||||
int FileClose(lfs_file_t* file_p);
|
||||
int FileRead(lfs_file_t* file_p, uint8_t* buff, uint32_t size);
|
||||
int FileWrite(lfs_file_t* file_p, const uint8_t* buff, uint32_t size);
|
||||
int FileSeek(lfs_file_t* file_p, uint32_t pos);
|
||||
|
||||
int FileDelete(const char* fileName);
|
||||
|
||||
int DirCreate(const char* path);
|
||||
int DirDelete(const char* path);
|
||||
|
||||
void VerifyResource();
|
||||
|
||||
private:
|
||||
|
||||
Pinetime::Drivers::SpiNorFlash& flashDriver;
|
||||
|
||||
/*
|
||||
* External Flash MAP (4 MBytes)
|
||||
*
|
||||
* 0x000000 +---------------------------------------+
|
||||
* | Bootloader Assets |
|
||||
* | 256 KBytes |
|
||||
* | |
|
||||
* 0x040000 +---------------------------------------+
|
||||
* | OTA |
|
||||
* | 464 KBytes |
|
||||
* | |
|
||||
* | |
|
||||
* | |
|
||||
* 0x0B4000 +---------------------------------------+
|
||||
* | File System |
|
||||
* | |
|
||||
* | |
|
||||
* | |
|
||||
* | |
|
||||
* 0x400000 +---------------------------------------+
|
||||
*
|
||||
*/
|
||||
static constexpr size_t startAddress = 0x0B4000;
|
||||
static constexpr size_t size = 0x3C0000;
|
||||
static constexpr size_t blockSize = 4096;
|
||||
|
||||
bool resourcesValid = false;
|
||||
const struct lfs_config lfsConfig;
|
||||
|
||||
lfs_t lfs;
|
||||
|
||||
static int SectorSync(const struct lfs_config* c);
|
||||
static int SectorErase(const struct lfs_config* c, lfs_block_t block);
|
||||
static int SectorProg(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, const void* buffer, lfs_size_t size);
|
||||
static int SectorRead(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size);
|
||||
|
||||
};
|
||||
}
|
||||
}
|
@@ -4,108 +4,44 @@
|
||||
|
||||
using namespace Pinetime::Controllers;
|
||||
|
||||
struct SettingsHeader {
|
||||
uint8_t isActive; // 0xF1 = Block is active, 0xF0 = Block is inactive
|
||||
uint16_t version; // Current version, to verify if the saved data is for the current Version
|
||||
};
|
||||
|
||||
#define HEADER_SIZE sizeof(SettingsHeader)
|
||||
|
||||
Settings::Settings(Pinetime::Drivers::SpiNorFlash& spiNorFlash) : spiNorFlash {spiNorFlash} {
|
||||
Settings::Settings(Pinetime::Controllers::FS& fs) : fs {fs} {
|
||||
}
|
||||
|
||||
void Settings::Init() {
|
||||
|
||||
// Load default settings from Flash
|
||||
LoadSettingsFromFlash();
|
||||
LoadSettingsFromFile();
|
||||
}
|
||||
|
||||
void Settings::SaveSettings() {
|
||||
|
||||
// verify if is necessary to save
|
||||
if (settingsChanged) {
|
||||
SaveSettingsToFlash();
|
||||
SaveSettingsToFile();
|
||||
}
|
||||
settingsChanged = false;
|
||||
}
|
||||
|
||||
bool Settings::FindHeader() {
|
||||
SettingsHeader settingsHeader;
|
||||
uint8_t bufferHead[sizeof(settingsHeader)];
|
||||
void Settings::LoadSettingsFromFile() {
|
||||
SettingsData bufferSettings;
|
||||
lfs_file_t settingsFile;
|
||||
|
||||
for (uint8_t block = 0; block < 10; block++) {
|
||||
|
||||
spiNorFlash.Read(settingsBaseAddr + (block * 0x1000), bufferHead, sizeof(settingsHeader));
|
||||
std::memcpy(&settingsHeader, bufferHead, sizeof(settingsHeader));
|
||||
if (settingsHeader.isActive == 0xF1 && settingsHeader.version == settingsVersion) {
|
||||
settingsFlashBlock = block;
|
||||
return true;
|
||||
}
|
||||
if ( fs.FileOpen(&settingsFile, "/settings.dat", LFS_O_RDWR | LFS_O_CREAT) != LFS_ERR_OK) {
|
||||
return;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Settings::ReadSettingsData() {
|
||||
uint8_t bufferSettings[sizeof(settings)];
|
||||
spiNorFlash.Read(settingsBaseAddr + (settingsFlashBlock * 0x1000) + HEADER_SIZE, bufferSettings, sizeof(settings));
|
||||
std::memcpy(&settings, bufferSettings, sizeof(settings));
|
||||
}
|
||||
|
||||
void Settings::EraseBlock() {
|
||||
|
||||
spiNorFlash.SectorErase(settingsBaseAddr + (settingsFlashBlock * 0x1000));
|
||||
}
|
||||
|
||||
void Settings::SetHeader(bool state) {
|
||||
SettingsHeader settingsHeader;
|
||||
uint8_t bufferHead[sizeof(settingsHeader)];
|
||||
settingsHeader.isActive = state ? 0xF1 : 0xF0;
|
||||
settingsHeader.version = settingsVersion;
|
||||
|
||||
std::memcpy(bufferHead, &settingsHeader, sizeof(settingsHeader));
|
||||
spiNorFlash.Write(settingsBaseAddr + (settingsFlashBlock * 0x1000), bufferHead, sizeof(settingsHeader));
|
||||
}
|
||||
|
||||
void Settings::SaveSettingsData() {
|
||||
uint8_t bufferSettings[sizeof(settings)];
|
||||
std::memcpy(bufferSettings, &settings, sizeof(settings));
|
||||
spiNorFlash.Write(settingsBaseAddr + (settingsFlashBlock * 0x1000) + HEADER_SIZE, bufferSettings, sizeof(settings));
|
||||
}
|
||||
|
||||
void Settings::LoadSettingsFromFlash() {
|
||||
|
||||
if (settingsFlashBlock == 99) {
|
||||
// Find current Block, if can't find use default settings and set block to 0 ans save !
|
||||
if (FindHeader()) {
|
||||
ReadSettingsData();
|
||||
} else {
|
||||
SaveSettingsToFlash();
|
||||
}
|
||||
} else {
|
||||
// Read Settings from flash...
|
||||
// never used :)
|
||||
ReadSettingsData();
|
||||
fs.FileRead(&settingsFile, reinterpret_cast<uint8_t*>(&bufferSettings), sizeof(settings));
|
||||
fs.FileClose(&settingsFile);
|
||||
if ( bufferSettings.version == settingsVersion ) {
|
||||
settings = bufferSettings;
|
||||
}
|
||||
}
|
||||
|
||||
void Settings::SaveSettingsToFlash() {
|
||||
void Settings::SaveSettingsToFile() {
|
||||
lfs_file_t settingsFile;
|
||||
|
||||
// calculate where to save...
|
||||
// mark current to inactive
|
||||
// erase the new location and save
|
||||
// set settingsFlashBlock
|
||||
|
||||
// if first time hever, only saves to block 0 and set settingsFlashBlock
|
||||
|
||||
if (settingsFlashBlock != 99) {
|
||||
SetHeader(false);
|
||||
if ( fs.FileOpen(&settingsFile, "/settings.dat", LFS_O_RDWR | LFS_O_CREAT) != LFS_ERR_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
settingsFlashBlock++;
|
||||
if (settingsFlashBlock > 9)
|
||||
settingsFlashBlock = 0;
|
||||
|
||||
EraseBlock();
|
||||
SetHeader(true);
|
||||
SaveSettingsData();
|
||||
fs.FileWrite(&settingsFile, reinterpret_cast<uint8_t*>(&settings), sizeof(settings));
|
||||
fs.FileClose(&settingsFile);
|
||||
}
|
||||
|
@@ -1,26 +1,32 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
#include <bitset>
|
||||
#include "components/datetime/DateTimeController.h"
|
||||
#include "components/brightness/BrightnessController.h"
|
||||
#include "drivers/SpiNorFlash.h"
|
||||
#include "components/fs/FS.h"
|
||||
#include "drivers/Cst816s.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Controllers {
|
||||
class Settings {
|
||||
public:
|
||||
enum class ClockType { H24, H12 };
|
||||
enum class Vibration { ON, OFF };
|
||||
enum class WakeUpMode { None, SingleTap, DoubleTap, RaiseWrist };
|
||||
enum class ClockType : uint8_t { H24, H12 };
|
||||
enum class Vibration : uint8_t { ON, OFF };
|
||||
enum class WakeUpMode : uint8_t {
|
||||
SingleTap = 0,
|
||||
DoubleTap = 1,
|
||||
RaiseWrist = 2,
|
||||
};
|
||||
|
||||
Settings(Pinetime::Drivers::SpiNorFlash& spiNorFlash);
|
||||
Settings(Pinetime::Controllers::FS& fs);
|
||||
|
||||
void Init();
|
||||
void SaveSettings();
|
||||
|
||||
void SetClockFace(uint8_t face) {
|
||||
if (face != settings.clockFace)
|
||||
if (face != settings.clockFace) {
|
||||
settingsChanged = true;
|
||||
}
|
||||
settings.clockFace = face;
|
||||
};
|
||||
uint8_t GetClockFace() const {
|
||||
@@ -42,8 +48,9 @@ namespace Pinetime {
|
||||
};
|
||||
|
||||
void SetClockType(ClockType clocktype) {
|
||||
if (clocktype != settings.clockType)
|
||||
if (clocktype != settings.clockType) {
|
||||
settingsChanged = true;
|
||||
}
|
||||
settings.clockType = clocktype;
|
||||
};
|
||||
ClockType GetClockType() const {
|
||||
@@ -51,8 +58,9 @@ namespace Pinetime {
|
||||
};
|
||||
|
||||
void SetVibrationStatus(Vibration status) {
|
||||
if (status != settings.vibrationStatus)
|
||||
if (status != settings.vibrationStatus) {
|
||||
settingsChanged = true;
|
||||
}
|
||||
settings.vibrationStatus = status;
|
||||
};
|
||||
Vibration GetVibrationStatus() const {
|
||||
@@ -60,26 +68,47 @@ namespace Pinetime {
|
||||
};
|
||||
|
||||
void SetScreenTimeOut(uint32_t timeout) {
|
||||
if (timeout != settings.screenTimeOut)
|
||||
if (timeout != settings.screenTimeOut) {
|
||||
settingsChanged = true;
|
||||
}
|
||||
settings.screenTimeOut = timeout;
|
||||
};
|
||||
uint32_t GetScreenTimeOut() const {
|
||||
return settings.screenTimeOut;
|
||||
};
|
||||
|
||||
void setWakeUpMode(WakeUpMode wakeUp) {
|
||||
if (wakeUp != settings.wakeUpMode)
|
||||
void setWakeUpMode(WakeUpMode wakeUp, bool enabled) {
|
||||
if (!isWakeUpModeOn(wakeUp)) {
|
||||
settingsChanged = true;
|
||||
settings.wakeUpMode = wakeUp;
|
||||
};
|
||||
WakeUpMode getWakeUpMode() const {
|
||||
return settings.wakeUpMode;
|
||||
}
|
||||
settings.wakeUpMode.set(static_cast<size_t>(wakeUp), enabled);
|
||||
// Handle special behavior
|
||||
if (enabled) {
|
||||
switch (wakeUp) {
|
||||
case WakeUpMode::SingleTap:
|
||||
settings.wakeUpMode.set(static_cast<size_t>(WakeUpMode::DoubleTap), false);
|
||||
break;
|
||||
case WakeUpMode::DoubleTap:
|
||||
settings.wakeUpMode.set(static_cast<size_t>(WakeUpMode::SingleTap), false);
|
||||
break;
|
||||
case WakeUpMode::RaiseWrist:
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::bitset<3> getWakeUpModes() const {
|
||||
return settings.wakeUpMode;
|
||||
}
|
||||
|
||||
bool isWakeUpModeOn(const WakeUpMode mode) const {
|
||||
return getWakeUpModes()[static_cast<size_t>(mode)];
|
||||
}
|
||||
|
||||
void SetBrightness(Controllers::BrightnessController::Levels level) {
|
||||
if (level != settings.brightLevel)
|
||||
if (level != settings.brightLevel) {
|
||||
settingsChanged = true;
|
||||
}
|
||||
settings.brightLevel = level;
|
||||
};
|
||||
Controllers::BrightnessController::Levels GetBrightness() const {
|
||||
@@ -87,26 +116,30 @@ namespace Pinetime {
|
||||
};
|
||||
|
||||
void SetStepsGoal( uint32_t goal ) {
|
||||
if ( goal != settings.stepsGoal )
|
||||
if ( goal != settings.stepsGoal ) {
|
||||
settingsChanged = true;
|
||||
}
|
||||
settings.stepsGoal = goal;
|
||||
};
|
||||
|
||||
uint32_t GetStepsGoal() const { return settings.stepsGoal; };
|
||||
|
||||
private:
|
||||
Pinetime::Drivers::SpiNorFlash& spiNorFlash;
|
||||
Pinetime::Controllers::FS& fs;
|
||||
|
||||
static constexpr uint32_t settingsVersion = 0x0001;
|
||||
struct SettingsData {
|
||||
|
||||
uint32_t version = settingsVersion;
|
||||
uint32_t stepsGoal = 10000;
|
||||
uint32_t screenTimeOut = 15000;
|
||||
|
||||
ClockType clockType = ClockType::H24;
|
||||
Vibration vibrationStatus = Vibration::ON;
|
||||
|
||||
uint8_t clockFace = 0;
|
||||
|
||||
uint32_t stepsGoal = 10000;
|
||||
uint32_t screenTimeOut = 15000;
|
||||
|
||||
WakeUpMode wakeUpMode = WakeUpMode::None;
|
||||
std::bitset<3> wakeUpMode {0};
|
||||
|
||||
Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium;
|
||||
};
|
||||
@@ -117,20 +150,8 @@ namespace Pinetime {
|
||||
uint8_t appMenu = 0;
|
||||
uint8_t settingsMenu = 0;
|
||||
|
||||
// There are 10 blocks of reserved flash to save settings
|
||||
// to minimize wear, the recording is done in a rotating way by the 10 blocks
|
||||
uint8_t settingsFlashBlock = 99; // default to indicate it needs to find the active block
|
||||
|
||||
static constexpr uint32_t settingsBaseAddr = 0x3F6000; // Flash Settings Location
|
||||
static constexpr uint16_t settingsVersion = 0x0100; // Flash Settings Version
|
||||
|
||||
bool FindHeader();
|
||||
void ReadSettingsData();
|
||||
void EraseBlock();
|
||||
void SetHeader(bool state);
|
||||
void SaveSettingsData();
|
||||
void LoadSettingsFromFlash();
|
||||
void SaveSettingsToFlash();
|
||||
void LoadSettingsFromFile();
|
||||
void SaveSettingsToFile();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -45,6 +45,8 @@
|
||||
#include "displayapp/screens/settings/SettingSetDate.h"
|
||||
#include "displayapp/screens/settings/SettingSetTime.h"
|
||||
|
||||
#include "libs/lv_conf.h"
|
||||
|
||||
using namespace Pinetime::Applications;
|
||||
using namespace Pinetime::Applications::Display;
|
||||
|
||||
@@ -52,6 +54,31 @@ namespace {
|
||||
static inline bool in_isr(void) {
|
||||
return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0;
|
||||
}
|
||||
|
||||
TouchEvents Convert(Pinetime::Drivers::Cst816S::TouchInfos info) {
|
||||
if (info.isTouch) {
|
||||
switch (info.gesture) {
|
||||
case Pinetime::Drivers::Cst816S::Gestures::SingleTap:
|
||||
return TouchEvents::Tap;
|
||||
case Pinetime::Drivers::Cst816S::Gestures::LongPress:
|
||||
return TouchEvents::LongTap;
|
||||
case Pinetime::Drivers::Cst816S::Gestures::DoubleTap:
|
||||
return TouchEvents::DoubleTap;
|
||||
case Pinetime::Drivers::Cst816S::Gestures::SlideRight:
|
||||
return TouchEvents::SwipeRight;
|
||||
case Pinetime::Drivers::Cst816S::Gestures::SlideLeft:
|
||||
return TouchEvents::SwipeLeft;
|
||||
case Pinetime::Drivers::Cst816S::Gestures::SlideDown:
|
||||
return TouchEvents::SwipeDown;
|
||||
case Pinetime::Drivers::Cst816S::Gestures::SlideUp:
|
||||
return TouchEvents::SwipeUp;
|
||||
case Pinetime::Drivers::Cst816S::Gestures::None:
|
||||
default:
|
||||
return TouchEvents::None;
|
||||
}
|
||||
}
|
||||
return TouchEvents::None;
|
||||
}
|
||||
}
|
||||
|
||||
DisplayApp::DisplayApp(Drivers::St7789& lcd,
|
||||
@@ -116,6 +143,7 @@ uint32_t count = 0;
|
||||
bool toggle = true;
|
||||
void DisplayApp::Refresh() {
|
||||
TickType_t queueTimeout;
|
||||
TickType_t delta;
|
||||
switch (state) {
|
||||
case States::Idle:
|
||||
IdleState();
|
||||
@@ -123,7 +151,11 @@ void DisplayApp::Refresh() {
|
||||
break;
|
||||
case States::Running:
|
||||
RunningState();
|
||||
queueTimeout = 20;
|
||||
delta = xTaskGetTickCount() - lastWakeTime;
|
||||
if (delta > LV_DISP_DEF_REFR_PERIOD) {
|
||||
delta = LV_DISP_DEF_REFR_PERIOD;
|
||||
}
|
||||
queueTimeout = LV_DISP_DEF_REFR_PERIOD - delta;
|
||||
break;
|
||||
default:
|
||||
queueTimeout = portMAX_DELAY;
|
||||
@@ -131,10 +163,19 @@ void DisplayApp::Refresh() {
|
||||
}
|
||||
|
||||
Messages msg;
|
||||
if (xQueueReceive(msgQueue, &msg, queueTimeout)) {
|
||||
bool messageReceived = xQueueReceive(msgQueue, &msg, queueTimeout);
|
||||
lastWakeTime = xTaskGetTickCount();
|
||||
if (messageReceived) {
|
||||
switch (msg) {
|
||||
case Messages::GoToSleep:
|
||||
case Messages::DimScreen:
|
||||
// Backup brightness is the brightness to return to after dimming or sleeping
|
||||
brightnessController.Backup();
|
||||
brightnessController.Set(Controllers::BrightnessController::Levels::Low);
|
||||
break;
|
||||
case Messages::RestoreBrightness:
|
||||
brightnessController.Restore();
|
||||
break;
|
||||
case Messages::GoToSleep:
|
||||
while (brightnessController.Level() != Controllers::BrightnessController::Levels::Off) {
|
||||
brightnessController.Lower();
|
||||
vTaskDelay(100);
|
||||
@@ -163,16 +204,21 @@ void DisplayApp::Refresh() {
|
||||
break;
|
||||
case Messages::TimerDone:
|
||||
if (currentApp == Apps::Timer) {
|
||||
auto *timer = static_cast<Screens::Timer*>(currentScreen.get());
|
||||
auto* timer = static_cast<Screens::Timer*>(currentScreen.get());
|
||||
timer->setDone();
|
||||
} else {
|
||||
LoadApp(Apps::Timer, DisplayApp::FullRefreshDirections::Down);
|
||||
}
|
||||
break;
|
||||
case Messages::TouchEvent: {
|
||||
if (state != States::Running)
|
||||
if (state != States::Running) {
|
||||
break;
|
||||
auto gesture = OnTouchEvent();
|
||||
}
|
||||
auto info = touchPanel.GetTouchInfo();
|
||||
auto gesture = Convert(info);
|
||||
if (gesture == TouchEvents::None) {
|
||||
break;
|
||||
}
|
||||
if (!currentScreen->OnTouchEvent(gesture)) {
|
||||
if (currentApp == Apps::Clock) {
|
||||
switch (gesture) {
|
||||
@@ -193,6 +239,12 @@ void DisplayApp::Refresh() {
|
||||
}
|
||||
} else if (returnTouchEvent == gesture) {
|
||||
LoadApp(returnToApp, returnDirection);
|
||||
brightnessController.Set(settingsController.GetBrightness());
|
||||
brightnessController.Backup();
|
||||
} else if (touchMode == TouchModes::Gestures) {
|
||||
if (gesture == TouchEvents::Tap) {
|
||||
lvgl.SetNewTapEvent(info.x, info.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@@ -202,6 +254,8 @@ void DisplayApp::Refresh() {
|
||||
} else {
|
||||
if (!currentScreen->OnButtonPushed()) {
|
||||
LoadApp(returnToApp, returnDirection);
|
||||
brightnessController.Set(settingsController.GetBrightness());
|
||||
brightnessController.Backup();
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -216,7 +270,7 @@ void DisplayApp::Refresh() {
|
||||
}
|
||||
}
|
||||
|
||||
if(nextApp != Apps::None) {
|
||||
if (nextApp != Apps::None) {
|
||||
LoadApp(nextApp, nextDirection);
|
||||
nextApp = Apps::None;
|
||||
}
|
||||
@@ -279,6 +333,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
|
||||
break;
|
||||
case Apps::FirmwareUpdate:
|
||||
currentScreen = std::make_unique<Screens::FirmwareUpdate>(this, bleController);
|
||||
ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None);
|
||||
break;
|
||||
|
||||
case Apps::Notifications:
|
||||
@@ -338,8 +393,8 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
|
||||
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
|
||||
break;
|
||||
case Apps::SysInfo:
|
||||
currentScreen =
|
||||
std::make_unique<Screens::SystemInfo>(this, dateTimeController, batteryController, brightnessController, bleController, watchdog, motionController);
|
||||
currentScreen = std::make_unique<Screens::SystemInfo>(
|
||||
this, dateTimeController, batteryController, brightnessController, bleController, watchdog, motionController);
|
||||
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
|
||||
break;
|
||||
case Apps::FlashLight:
|
||||
@@ -384,7 +439,7 @@ void DisplayApp::IdleState() {
|
||||
}
|
||||
|
||||
void DisplayApp::PushMessage(Messages msg) {
|
||||
if(in_isr()) {
|
||||
if (in_isr()) {
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
xHigherPriorityTaskWoken = pdFALSE;
|
||||
xQueueSendFromISR(msgQueue, &msg, &xHigherPriorityTaskWoken);
|
||||
@@ -396,35 +451,6 @@ void DisplayApp::PushMessage(Messages msg) {
|
||||
}
|
||||
}
|
||||
|
||||
TouchEvents DisplayApp::OnTouchEvent() {
|
||||
auto info = touchPanel.GetTouchInfo();
|
||||
if (info.isTouch) {
|
||||
switch (info.gesture) {
|
||||
case Pinetime::Drivers::Cst816S::Gestures::SingleTap:
|
||||
if (touchMode == TouchModes::Gestures) {
|
||||
lvgl.SetNewTapEvent(info.x, info.y);
|
||||
}
|
||||
return TouchEvents::Tap;
|
||||
case Pinetime::Drivers::Cst816S::Gestures::LongPress:
|
||||
return TouchEvents::LongTap;
|
||||
case Pinetime::Drivers::Cst816S::Gestures::DoubleTap:
|
||||
return TouchEvents::DoubleTap;
|
||||
case Pinetime::Drivers::Cst816S::Gestures::SlideRight:
|
||||
return TouchEvents::SwipeRight;
|
||||
case Pinetime::Drivers::Cst816S::Gestures::SlideLeft:
|
||||
return TouchEvents::SwipeLeft;
|
||||
case Pinetime::Drivers::Cst816S::Gestures::SlideDown:
|
||||
return TouchEvents::SwipeDown;
|
||||
case Pinetime::Drivers::Cst816S::Gestures::SlideUp:
|
||||
return TouchEvents::SwipeUp;
|
||||
case Pinetime::Drivers::Cst816S::Gestures::None:
|
||||
default:
|
||||
return TouchEvents::None;
|
||||
}
|
||||
}
|
||||
return TouchEvents::None;
|
||||
}
|
||||
|
||||
void DisplayApp::SetFullRefresh(DisplayApp::FullRefreshDirections direction) {
|
||||
switch (direction) {
|
||||
case DisplayApp::FullRefreshDirections::Down:
|
||||
@@ -455,7 +481,7 @@ void DisplayApp::SetTouchMode(DisplayApp::TouchModes mode) {
|
||||
}
|
||||
|
||||
void DisplayApp::PushMessageToSystemTask(Pinetime::System::Messages message) {
|
||||
if(systemTask != nullptr)
|
||||
if (systemTask != nullptr)
|
||||
systemTask->PushMessage(message);
|
||||
}
|
||||
|
||||
|
@@ -102,7 +102,6 @@ namespace Pinetime {
|
||||
|
||||
TouchModes touchMode = TouchModes::Gestures;
|
||||
|
||||
TouchEvents OnTouchEvent();
|
||||
void RunningState();
|
||||
void IdleState();
|
||||
static void Process(void* instance);
|
||||
@@ -114,6 +113,7 @@ namespace Pinetime {
|
||||
|
||||
Apps nextApp = Apps::None;
|
||||
DisplayApp::FullRefreshDirections nextDirection;
|
||||
TickType_t lastWakeTime;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -13,8 +13,10 @@ namespace Pinetime {
|
||||
NewNotification,
|
||||
TimerDone,
|
||||
BleFirmwareUpdateStarted,
|
||||
UpdateTimeOut
|
||||
UpdateTimeOut,
|
||||
DimScreen,
|
||||
RestoreBrightness
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -13,7 +13,7 @@
|
||||
* Do not enable font compression and horizontal subpixel hinting
|
||||
* Load the file `JetBrainsMono-Bold.tff` (use the file in this repo to ensure the version matches) and specify the following range : `0x20-0x7f, 0x410-0x44f`
|
||||
* Add a 2nd font, load the file `FontAwesome5-Solid+Brands+Regular.woff` and specify the following
|
||||
range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569`
|
||||
range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569, 0xf201, 0xf06e, 0xf015`
|
||||
* Click on Convert, and download the file `jetbrains_mono_bold_20.c` and copy it in `src/DisplayApp/Fonts`
|
||||
* Add the font .c file path to src/CMakeLists.txt
|
||||
* Add an LV_FONT_DECLARE line in src/libs/lv_conf.h
|
||||
|
@@ -734,6 +734,15 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
0xff, 0x7, 0xef, 0xf0, 0x10, 0xff, 0x0, 0x3,
|
||||
0xc0, 0x0,
|
||||
|
||||
/* U+F015 "" */
|
||||
0x0, 0x38, 0xe0, 0x0, 0xf9, 0xc0, 0x3, 0xfb,
|
||||
0x80, 0x1e, 0x3f, 0x0, 0x79, 0x3e, 0x1, 0xe7,
|
||||
0x3c, 0xf, 0x9f, 0xbc, 0x3c, 0xff, 0x9e, 0xf3,
|
||||
0xff, 0x9e, 0xcf, 0xff, 0x98, 0x3f, 0xff, 0x80,
|
||||
0x7f, 0xff, 0x0, 0xfc, 0x7e, 0x1, 0xf8, 0xfc,
|
||||
0x3, 0xf1, 0xf8, 0x7, 0xe3, 0xf0, 0xf, 0xc7,
|
||||
0xe0,
|
||||
|
||||
/* U+F017 "" */
|
||||
0x3, 0xf8, 0x1, 0xff, 0xc0, 0x7f, 0xfc, 0x1f,
|
||||
0xff, 0xc7, 0xf1, 0xfc, 0xfe, 0x3f, 0x9f, 0xc7,
|
||||
@@ -823,6 +832,14 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
0xdf, 0x9e, 0x38, 0xf3, 0x7, 0x6, 0x0, 0xe0,
|
||||
0x0, 0x1c, 0x0, 0x3, 0x80, 0x0, 0x70, 0x0,
|
||||
|
||||
/* U+F06E "" */
|
||||
0x0, 0xfe, 0x0, 0xf, 0xff, 0x80, 0x3e, 0xf,
|
||||
0x80, 0xf8, 0xf, 0x83, 0xe3, 0x8f, 0x8f, 0x87,
|
||||
0x8f, 0xbf, 0x1f, 0x9f, 0xfe, 0xff, 0x3f, 0xfd,
|
||||
0xfe, 0x7e, 0xf9, 0xf8, 0xf8, 0xf9, 0xe3, 0xe0,
|
||||
0xf8, 0xf, 0x80, 0xf8, 0x3e, 0x0, 0xff, 0xf0,
|
||||
0x0, 0x3f, 0x80, 0x0,
|
||||
|
||||
/* U+F095 "" */
|
||||
0x0, 0x0, 0x0, 0x0, 0x3e, 0x0, 0x7, 0xf0,
|
||||
0x0, 0x7f, 0x0, 0x7, 0xf0, 0x0, 0xff, 0x0,
|
||||
@@ -861,6 +878,13 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
|
||||
0x1, 0xf8, 0x0, 0x9f, 0xc0, 0xf, 0xfc, 0x0,
|
||||
0x7f, 0xc0, 0x7, 0xf8, 0x0, 0x1f, 0x0, 0x0,
|
||||
|
||||
/* U+F201 "" */
|
||||
0x40, 0x0, 0x7, 0x0, 0x0, 0x38, 0x1, 0xf9,
|
||||
0xc0, 0x7, 0xce, 0x18, 0x1e, 0x71, 0xe1, 0xf3,
|
||||
0x9f, 0x9d, 0x9d, 0xff, 0xc4, 0xe6, 0x7c, 0x7,
|
||||
0x1, 0xc0, 0x38, 0x0, 0x1, 0xc0, 0x0, 0xe,
|
||||
0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xe0,
|
||||
|
||||
/* U+F21E "" */
|
||||
0x1e, 0x7, 0x83, 0xf9, 0xfe, 0x7f, 0xff, 0xef,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xfc,
|
||||
@@ -1182,42 +1206,45 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
||||
{.bitmap_index = 2484, .adv_w = 192, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2498, .adv_w = 192, .box_w = 9, .box_h = 11, .ofs_x = 1, .ofs_y = 0},
|
||||
{.bitmap_index = 2511, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 2561, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 2609, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 2659, .adv_w = 240, .box_w = 15, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 2688, .adv_w = 360, .box_w = 23, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2743, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||
{.bitmap_index = 2782, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||
{.bitmap_index = 2825, .adv_w = 280, .box_w = 13, .box_h = 17, .ofs_x = 2, .ofs_y = -1},
|
||||
{.bitmap_index = 2853, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 2901, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||
{.bitmap_index = 2940, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||
{.bitmap_index = 2979, .adv_w = 280, .box_w = 13, .box_h = 17, .ofs_x = 2, .ofs_y = -1},
|
||||
{.bitmap_index = 3007, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 3055, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 3108, .adv_w = 120, .box_w = 8, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 3127, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 3177, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 3213, .adv_w = 320, .box_w = 20, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 3261, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||
{.bitmap_index = 3304, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1},
|
||||
{.bitmap_index = 3342, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1},
|
||||
{.bitmap_index = 3380, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1},
|
||||
{.bitmap_index = 3418, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1},
|
||||
{.bitmap_index = 3456, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1},
|
||||
{.bitmap_index = 3494, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 3530, .adv_w = 280, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = -3},
|
||||
{.bitmap_index = 3568, .adv_w = 200, .box_w = 11, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 3597, .adv_w = 280, .box_w = 16, .box_h = 19, .ofs_x = 1, .ofs_y = -2},
|
||||
{.bitmap_index = 3635, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 3701, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||
{.bitmap_index = 3750, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 3800, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 3860, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 3913, .adv_w = 360, .box_w = 23, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 3974, .adv_w = 360, .box_w = 22, .box_h = 20, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 4029, .adv_w = 360, .box_w = 22, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 4082, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0}
|
||||
{.bitmap_index = 2561, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||
{.bitmap_index = 2610, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 2658, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 2708, .adv_w = 240, .box_w = 15, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 2737, .adv_w = 360, .box_w = 23, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 2792, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||
{.bitmap_index = 2831, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||
{.bitmap_index = 2874, .adv_w = 280, .box_w = 13, .box_h = 17, .ofs_x = 2, .ofs_y = -1},
|
||||
{.bitmap_index = 2902, .adv_w = 280, .box_w = 18, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 2950, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||
{.bitmap_index = 2989, .adv_w = 280, .box_w = 18, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||
{.bitmap_index = 3028, .adv_w = 280, .box_w = 13, .box_h = 17, .ofs_x = 2, .ofs_y = -1},
|
||||
{.bitmap_index = 3056, .adv_w = 320, .box_w = 19, .box_h = 20, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 3104, .adv_w = 360, .box_w = 23, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 3148, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 3201, .adv_w = 120, .box_w = 8, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 3220, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 3270, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 3306, .adv_w = 320, .box_w = 20, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 3354, .adv_w = 320, .box_w = 21, .box_h = 15, .ofs_x = 0, .ofs_y = 0},
|
||||
{.bitmap_index = 3394, .adv_w = 320, .box_w = 20, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||
{.bitmap_index = 3437, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1},
|
||||
{.bitmap_index = 3475, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1},
|
||||
{.bitmap_index = 3513, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1},
|
||||
{.bitmap_index = 3551, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1},
|
||||
{.bitmap_index = 3589, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1},
|
||||
{.bitmap_index = 3627, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 3663, .adv_w = 280, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = -3},
|
||||
{.bitmap_index = 3701, .adv_w = 200, .box_w = 11, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 3730, .adv_w = 280, .box_w = 16, .box_h = 19, .ofs_x = 1, .ofs_y = -2},
|
||||
{.bitmap_index = 3768, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 3834, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
|
||||
{.bitmap_index = 3883, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 3933, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 3993, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 4046, .adv_w = 360, .box_w = 23, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
|
||||
{.bitmap_index = 4107, .adv_w = 360, .box_w = 22, .box_h = 20, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 4162, .adv_w = 360, .box_w = 22, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
|
||||
{.bitmap_index = 4215, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0}
|
||||
};
|
||||
|
||||
/*---------------------
|
||||
@@ -1225,11 +1252,11 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
|
||||
*--------------------*/
|
||||
|
||||
static const uint16_t unicode_list_2[] = {
|
||||
0x0, 0x16, 0x23, 0x26, 0x27, 0x28, 0x39, 0x47,
|
||||
0x4a, 0x4b, 0x4c, 0x50, 0x68, 0x94, 0x128, 0x184,
|
||||
0x1e5, 0x1fb, 0x21d, 0x23f, 0x240, 0x241, 0x242, 0x243,
|
||||
0x251, 0x292, 0x293, 0x2f1, 0x3dc, 0x3fc, 0x45c, 0x54a,
|
||||
0x55f, 0x568, 0x59e, 0x59f, 0x6a8
|
||||
0x0, 0x14, 0x16, 0x23, 0x26, 0x27, 0x28, 0x39,
|
||||
0x47, 0x4a, 0x4b, 0x4c, 0x50, 0x68, 0x6d, 0x94,
|
||||
0x128, 0x184, 0x1e5, 0x1fb, 0x200, 0x21d, 0x23f, 0x240,
|
||||
0x241, 0x242, 0x243, 0x251, 0x292, 0x293, 0x2f1, 0x3dc,
|
||||
0x3fc, 0x45c, 0x54a, 0x55f, 0x568, 0x59e, 0x59f, 0x6a8
|
||||
};
|
||||
|
||||
/*Collect the unicode lists and glyph_id offsets*/
|
||||
@@ -1245,7 +1272,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] =
|
||||
},
|
||||
{
|
||||
.range_start = 61441, .range_length = 1705, .glyph_id_start = 160,
|
||||
.unicode_list = unicode_list_2, .glyph_id_ofs_list = NULL, .list_length = 37, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
|
||||
.unicode_list = unicode_list_2, .glyph_id_ofs_list = NULL, .list_length = 40, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -62,7 +62,7 @@ std::unique_ptr<Screen> ApplicationList::CreateScreen2() {
|
||||
{Symbols::paintbrush, Apps::Paint},
|
||||
{Symbols::paddle, Apps::Paddle},
|
||||
{"2", Apps::Twos},
|
||||
{"M", Apps::Motion},
|
||||
{Symbols::chartLine, Apps::Motion},
|
||||
{Symbols::drum, Apps::Metronome},
|
||||
{"", Apps::None},
|
||||
}};
|
||||
|
@@ -1,9 +1,10 @@
|
||||
#include <cstdint>
|
||||
#include "BatteryIcon.h"
|
||||
#include "Symbols.h"
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
const char* BatteryIcon::GetBatteryIcon(int batteryPercent) {
|
||||
const char* BatteryIcon::GetBatteryIcon(uint8_t batteryPercent) {
|
||||
if (batteryPercent > 90)
|
||||
return Symbols::batteryFull;
|
||||
if (batteryPercent > 75)
|
||||
|
@@ -6,7 +6,7 @@ namespace Pinetime {
|
||||
class BatteryIcon {
|
||||
public:
|
||||
static const char* GetUnknownIcon();
|
||||
static const char* GetBatteryIcon(int batteryPercent);
|
||||
static const char* GetBatteryIcon(uint8_t batteryPercent);
|
||||
static const char* GetPlugIcon(bool isCharging);
|
||||
};
|
||||
}
|
||||
|
@@ -9,11 +9,6 @@ static void lv_update_task(struct _lv_task_t* task) {
|
||||
user_data->UpdateScreen();
|
||||
}
|
||||
|
||||
static void lv_anim_task(struct _lv_task_t* task) {
|
||||
auto user_data = static_cast<BatteryInfo*>(task->user_data);
|
||||
user_data->UpdateAnim();
|
||||
}
|
||||
|
||||
BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Battery& batteryController)
|
||||
: Screen(app), batteryController {batteryController} {
|
||||
|
||||
@@ -24,12 +19,12 @@ BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Cont
|
||||
lv_obj_set_size(charging_bar, 200, 15);
|
||||
lv_bar_set_range(charging_bar, 0, 100);
|
||||
lv_obj_align(charging_bar, nullptr, LV_ALIGN_CENTER, 0, 10);
|
||||
lv_bar_set_anim_time(charging_bar, 2000);
|
||||
lv_bar_set_anim_time(charging_bar, 1000);
|
||||
lv_obj_set_style_local_radius(charging_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE);
|
||||
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, lv_color_hex(0x222222));
|
||||
lv_obj_set_style_local_bg_opa(charging_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_OPA_100);
|
||||
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, lv_color_hex(0xFF0000));
|
||||
lv_bar_set_value(charging_bar, batteryPercent, LV_ANIM_OFF);
|
||||
lv_bar_set_value(charging_bar, batteryPercent, LV_ANIM_ON);
|
||||
|
||||
status = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_label_set_text_static(status, "Reading Battery status");
|
||||
@@ -38,11 +33,7 @@ BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Cont
|
||||
|
||||
percent = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_font(percent, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76);
|
||||
if (batteryPercent >= 0) {
|
||||
lv_label_set_text_fmt(percent, "%02i%%", batteryPercent);
|
||||
} else {
|
||||
lv_label_set_text(percent, "--%");
|
||||
}
|
||||
lv_label_set_text_fmt(percent, "%02i%%", batteryPercent);
|
||||
lv_label_set_align(percent, LV_LABEL_ALIGN_LEFT);
|
||||
lv_obj_align(percent, nullptr, LV_ALIGN_CENTER, 0, -60);
|
||||
|
||||
@@ -58,40 +49,15 @@ BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Cont
|
||||
lv_obj_set_pos(backgroundLabel, 0, 0);
|
||||
lv_label_set_text_static(backgroundLabel, "");
|
||||
|
||||
taskUpdate = lv_task_create(lv_update_task, 500000, LV_TASK_PRIO_LOW, this);
|
||||
taskAnim = lv_task_create(lv_anim_task, 1000, LV_TASK_PRIO_LOW, this);
|
||||
taskUpdate = lv_task_create(lv_update_task, 5000, LV_TASK_PRIO_LOW, this);
|
||||
UpdateScreen();
|
||||
}
|
||||
|
||||
BatteryInfo::~BatteryInfo() {
|
||||
lv_task_del(taskUpdate);
|
||||
lv_task_del(taskAnim);
|
||||
lv_obj_clean(lv_scr_act());
|
||||
}
|
||||
|
||||
void BatteryInfo::UpdateAnim() {
|
||||
batteryPercent = batteryController.PercentRemaining();
|
||||
|
||||
if (batteryPercent >= 0) {
|
||||
if (batteryController.IsCharging() and batteryPercent < 100) {
|
||||
animation += 1;
|
||||
if (animation >= 100) {
|
||||
animation = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (animation > batteryPercent) {
|
||||
animation--;
|
||||
}
|
||||
if (animation < batteryPercent) {
|
||||
animation++;
|
||||
}
|
||||
}
|
||||
|
||||
lv_bar_set_value(charging_bar, animation, LV_ANIM_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
void BatteryInfo::UpdateScreen() {
|
||||
|
||||
batteryController.Update();
|
||||
@@ -99,33 +65,27 @@ void BatteryInfo::UpdateScreen() {
|
||||
batteryPercent = batteryController.PercentRemaining();
|
||||
batteryVoltage = batteryController.Voltage();
|
||||
|
||||
if (batteryPercent >= 0) {
|
||||
if (batteryController.IsCharging() and batteryPercent < 100) {
|
||||
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_RED);
|
||||
lv_label_set_text_static(status, "Battery charging");
|
||||
} else if (batteryPercent == 100) {
|
||||
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_BLUE);
|
||||
lv_label_set_text_static(status, "Battery is fully charged");
|
||||
} else if (batteryPercent < 10) {
|
||||
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
|
||||
lv_label_set_text_static(status, "Battery is low");
|
||||
} else {
|
||||
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_GREEN);
|
||||
lv_label_set_text_static(status, "Battery discharging");
|
||||
}
|
||||
|
||||
lv_label_set_text_fmt(percent, "%02i%%", batteryPercent);
|
||||
|
||||
if (batteryController.IsCharging() and batteryPercent < 100) {
|
||||
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_RED);
|
||||
lv_label_set_text_static(status, "Charging");
|
||||
} else if (batteryPercent == 100) {
|
||||
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_BLUE);
|
||||
lv_label_set_text_static(status, "Fully charged");
|
||||
} else if (batteryPercent < 10) {
|
||||
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
|
||||
lv_label_set_text_static(status, "Battery low");
|
||||
} else {
|
||||
lv_label_set_text_static(status, "Reading Battery status");
|
||||
lv_label_set_text(percent, "--%");
|
||||
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_GREEN);
|
||||
lv_label_set_text_static(status, "Discharging");
|
||||
}
|
||||
|
||||
lv_label_set_text_fmt(percent, "%02i%%", batteryPercent);
|
||||
|
||||
lv_obj_align(status, charging_bar, LV_ALIGN_OUT_BOTTOM_MID, 0, 20);
|
||||
lv_label_set_text_fmt(voltage, "%1i.%02i volts", batteryVoltage / 1000, batteryVoltage % 1000 / 10);
|
||||
lv_bar_set_value(charging_bar, batteryPercent, LV_ANIM_ON);
|
||||
}
|
||||
|
||||
bool BatteryInfo::Refresh() {
|
||||
|
||||
return running;
|
||||
}
|
||||
|
@@ -22,7 +22,6 @@ namespace Pinetime {
|
||||
bool Refresh() override;
|
||||
|
||||
void UpdateScreen();
|
||||
void UpdateAnim();
|
||||
|
||||
private:
|
||||
Pinetime::Controllers::Battery& batteryController;
|
||||
@@ -33,10 +32,8 @@ namespace Pinetime {
|
||||
lv_obj_t* status;
|
||||
|
||||
lv_task_t* taskUpdate;
|
||||
lv_task_t* taskAnim;
|
||||
|
||||
int8_t animation = 0;
|
||||
int8_t batteryPercent = -1;
|
||||
uint8_t batteryPercent = 0;
|
||||
uint16_t batteryVoltage = 0;
|
||||
};
|
||||
}
|
||||
|
@@ -27,9 +27,10 @@ FirmwareUpdate::FirmwareUpdate(Pinetime::Applications::DisplayApp* app, Pinetime
|
||||
lv_bar_set_value(bar1, 0, LV_ANIM_OFF);
|
||||
|
||||
percentLabel = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_label_set_text(percentLabel, "");
|
||||
lv_label_set_text(percentLabel, "Waiting...");
|
||||
lv_obj_set_auto_realign(percentLabel, true);
|
||||
lv_obj_align(percentLabel, bar1, LV_ALIGN_OUT_TOP_MID, 0, 60);
|
||||
startTime = xTaskGetTickCount();
|
||||
}
|
||||
|
||||
FirmwareUpdate::~FirmwareUpdate() {
|
||||
@@ -40,26 +41,42 @@ bool FirmwareUpdate::Refresh() {
|
||||
switch (bleController.State()) {
|
||||
default:
|
||||
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Idle:
|
||||
// This condition makes sure that the app is exited if somehow it got
|
||||
// launched without a firmware update. This should never happen.
|
||||
if (state != States::Error) {
|
||||
if (xTaskGetTickCount() - startTime > (60 * 1024)) {
|
||||
UpdateError();
|
||||
state = States::Error;
|
||||
}
|
||||
} else if (xTaskGetTickCount() - startTime > (5 * 1024)) {
|
||||
running = false;
|
||||
}
|
||||
break;
|
||||
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Running:
|
||||
if (state != States::Running)
|
||||
state = States::Running;
|
||||
return DisplayProgression();
|
||||
DisplayProgression();
|
||||
break;
|
||||
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated:
|
||||
if (state != States::Validated) {
|
||||
UpdateValidated();
|
||||
state = States::Validated;
|
||||
}
|
||||
return running;
|
||||
break;
|
||||
case Pinetime::Controllers::Ble::FirmwareUpdateStates::Error:
|
||||
if (state != States::Error) {
|
||||
UpdateError();
|
||||
state = States::Error;
|
||||
}
|
||||
return running;
|
||||
if (xTaskGetTickCount() - startTime > (5 * 1024)) {
|
||||
running = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return running;
|
||||
}
|
||||
|
||||
bool FirmwareUpdate::DisplayProgression() const {
|
||||
void FirmwareUpdate::DisplayProgression() const {
|
||||
float current = bleController.FirmwareUpdateCurrentBytes() / 1024.0f;
|
||||
float total = bleController.FirmwareUpdateTotalBytes() / 1024.0f;
|
||||
int16_t pc = (current / total) * 100.0f;
|
||||
@@ -67,7 +84,6 @@ bool FirmwareUpdate::DisplayProgression() const {
|
||||
lv_label_set_text(percentLabel, percentStr);
|
||||
|
||||
lv_bar_set_value(bar1, pc, LV_ANIM_OFF);
|
||||
return running;
|
||||
}
|
||||
|
||||
void FirmwareUpdate::UpdateValidated() {
|
||||
@@ -78,4 +94,9 @@ void FirmwareUpdate::UpdateValidated() {
|
||||
void FirmwareUpdate::UpdateError() {
|
||||
lv_label_set_recolor(percentLabel, true);
|
||||
lv_label_set_text(percentLabel, "#ff0000 Error!#");
|
||||
startTime = xTaskGetTickCount();
|
||||
}
|
||||
|
||||
bool FirmwareUpdate::OnButtonPushed() {
|
||||
return true;
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "Screen.h"
|
||||
#include <lvgl/src/lv_core/lv_obj.h>
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
namespace Pinetime {
|
||||
namespace Controllers {
|
||||
@@ -25,13 +26,17 @@ namespace Pinetime {
|
||||
lv_obj_t* titleLabel;
|
||||
mutable char percentStr[10];
|
||||
|
||||
States state;
|
||||
States state = States::Idle;
|
||||
|
||||
bool DisplayProgression() const;
|
||||
void DisplayProgression() const;
|
||||
|
||||
bool OnButtonPushed() override;
|
||||
|
||||
void UpdateValidated();
|
||||
|
||||
void UpdateError();
|
||||
|
||||
TickType_t startTime;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -70,5 +70,5 @@ bool FlashLight::Refresh() {
|
||||
}
|
||||
|
||||
bool FlashLight::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@@ -15,8 +15,6 @@ namespace Pinetime {
|
||||
bool Refresh() override;
|
||||
|
||||
private:
|
||||
bool running = true;
|
||||
|
||||
lv_obj_t* labelText = nullptr;
|
||||
lv_point_t pageIndicatorBasePoints[2];
|
||||
lv_point_t pageIndicatorPoints[2];
|
||||
@@ -25,4 +23,4 @@ namespace Pinetime {
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -32,11 +32,10 @@ Motion::Motion(Pinetime::Applications::DisplayApp* app, Controllers::MotionContr
|
||||
lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
|
||||
lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_MID, 0, 10);
|
||||
lv_label_set_recolor(label, true);
|
||||
|
||||
|
||||
labelStep = lv_label_create(lv_scr_act(), NULL);
|
||||
lv_obj_align(labelStep, chart, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
|
||||
lv_label_set_text(labelStep, "Steps ---");
|
||||
|
||||
}
|
||||
|
||||
Motion::~Motion() {
|
||||
@@ -50,13 +49,12 @@ bool Motion::Refresh() {
|
||||
|
||||
lv_label_set_text_fmt(labelStep, "Steps %lu", motionController.NbSteps());
|
||||
|
||||
lv_label_set_text_fmt(label, "X #FF0000 %d# Y #008000 %d# Z #FFFF00 %d#", motionController.X() / 0x10, motionController.Y() / 0x10, motionController.Z() / 0x10);
|
||||
lv_label_set_text_fmt(label,
|
||||
"X #FF0000 %d# Y #008000 %d# Z #FFFF00 %d#",
|
||||
motionController.X() / 0x10,
|
||||
motionController.Y() / 0x10,
|
||||
motionController.Z() / 0x10);
|
||||
lv_obj_align(label, NULL, LV_ALIGN_IN_TOP_MID, 0, 10);
|
||||
|
||||
return running;
|
||||
}
|
||||
|
||||
bool Motion::OnButtonPushed() {
|
||||
running = false;
|
||||
return true;
|
||||
}
|
||||
|
@@ -18,7 +18,6 @@ namespace Pinetime {
|
||||
~Motion() override;
|
||||
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
|
||||
private:
|
||||
Controllers::MotionController& motionController;
|
||||
@@ -29,10 +28,7 @@ namespace Pinetime {
|
||||
lv_obj_t* label;
|
||||
|
||||
lv_obj_t* labelStep;
|
||||
static constexpr uint8_t nbStepsBufferSize = 9;
|
||||
char nbStepsBuffer[nbStepsBufferSize + 1];
|
||||
bool running = true;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -119,7 +119,6 @@ Music::Music(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Mus
|
||||
constexpr int8_t MIDDLE_OFFSET = -25;
|
||||
txtArtist = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_label_set_long_mode(txtArtist, LV_LABEL_LONG_SROLL_CIRC);
|
||||
lv_label_set_anim_speed(txtArtist, 1);
|
||||
lv_obj_align(txtArtist, nullptr, LV_ALIGN_IN_LEFT_MID, 12, MIDDLE_OFFSET + 1 * FONT_HEIGHT);
|
||||
lv_label_set_align(txtArtist, LV_ALIGN_IN_LEFT_MID);
|
||||
lv_obj_set_width(txtArtist, LV_HOR_RES - 12);
|
||||
@@ -127,7 +126,6 @@ Music::Music(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Mus
|
||||
|
||||
txtTrack = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_label_set_long_mode(txtTrack, LV_LABEL_LONG_SROLL_CIRC);
|
||||
lv_label_set_anim_speed(txtTrack, 1);
|
||||
lv_obj_align(txtTrack, nullptr, LV_ALIGN_IN_LEFT_MID, 12, MIDDLE_OFFSET + 2 * FONT_HEIGHT + LINE_PAD);
|
||||
|
||||
lv_label_set_align(txtTrack, LV_ALIGN_IN_LEFT_MID);
|
||||
@@ -303,4 +301,4 @@ bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -184,7 +184,6 @@ Notifications::NotificationItem::NotificationItem(const char* title,
|
||||
}
|
||||
lv_label_set_text(alert_type, title);
|
||||
lv_label_set_long_mode(alert_type, LV_LABEL_LONG_SROLL_CIRC);
|
||||
lv_label_set_anim_speed(alert_type, 3);
|
||||
lv_obj_set_width(alert_type, 180);
|
||||
lv_obj_align(alert_type, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 16);
|
||||
|
||||
|
@@ -179,8 +179,8 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app,
|
||||
lv_obj_align(stepGauge, sidebar, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
|
||||
lv_gauge_set_scale(stepGauge, 360, 11, 0);
|
||||
lv_gauge_set_angle_offset(stepGauge, 180);
|
||||
lv_gauge_set_critical_value(stepGauge, (settingsController.GetStepsGoal() / 100));
|
||||
lv_gauge_set_range(stepGauge, 0, (settingsController.GetStepsGoal() / 100));
|
||||
lv_gauge_set_critical_value(stepGauge, 100);
|
||||
lv_gauge_set_range(stepGauge, 0, 100);
|
||||
lv_gauge_set_value(stepGauge, 0, 0);
|
||||
|
||||
lv_obj_set_style_local_pad_right(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 3);
|
||||
@@ -264,23 +264,23 @@ bool PineTimeStyle::Refresh() {
|
||||
char hoursChar[3];
|
||||
char ampmChar[5];
|
||||
|
||||
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) {
|
||||
sprintf(hoursChar, "%02d", hour);
|
||||
} else {
|
||||
if (hour == 0 && hour != 12) {
|
||||
hour = 12;
|
||||
sprintf(ampmChar, "A\nM");
|
||||
} else if (hour == 12 && hour != 0) {
|
||||
hour = 12;
|
||||
sprintf(ampmChar, "P\nM");
|
||||
} else if (hour < 12 && hour != 0) {
|
||||
sprintf(ampmChar, "A\nM");
|
||||
} else if (hour > 12 && hour != 0) {
|
||||
hour = hour - 12;
|
||||
sprintf(ampmChar, "P\nM");
|
||||
}
|
||||
sprintf(hoursChar, "%02d", hour);
|
||||
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) {
|
||||
sprintf(hoursChar, "%02d", hour);
|
||||
} else {
|
||||
if (hour == 0 && hour != 12) {
|
||||
hour = 12;
|
||||
sprintf(ampmChar, "A\nM");
|
||||
} else if (hour == 12 && hour != 0) {
|
||||
hour = 12;
|
||||
sprintf(ampmChar, "P\nM");
|
||||
} else if (hour < 12 && hour != 0) {
|
||||
sprintf(ampmChar, "A\nM");
|
||||
} else if (hour > 12 && hour != 0) {
|
||||
hour = hour - 12;
|
||||
sprintf(ampmChar, "P\nM");
|
||||
}
|
||||
sprintf(hoursChar, "%02d", hour);
|
||||
}
|
||||
|
||||
if (hoursChar[0] != displayedChar[0] || hoursChar[1] != displayedChar[1] || minutesChar[0] != displayedChar[2] ||
|
||||
minutesChar[1] != displayedChar[3]) {
|
||||
@@ -292,9 +292,9 @@ bool PineTimeStyle::Refresh() {
|
||||
char hourStr[3];
|
||||
char minStr[3];
|
||||
|
||||
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
|
||||
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
|
||||
lv_label_set_text(timeAMPM, ampmChar);
|
||||
}
|
||||
}
|
||||
|
||||
/* Display the time as 2 pairs of digits */
|
||||
sprintf(hourStr, "%c%c", hoursChar[0], hoursChar[1]);
|
||||
@@ -328,7 +328,7 @@ bool PineTimeStyle::Refresh() {
|
||||
stepCount = motionController.NbSteps();
|
||||
motionSensorOk = motionController.IsSensorOk();
|
||||
if (stepCount.IsUpdated() || motionSensorOk.IsUpdated()) {
|
||||
lv_gauge_set_value(stepGauge, 0, (stepCount.Get() / 100));
|
||||
lv_gauge_set_value(stepGauge, 0, (stepCount.Get() / (settingsController.GetStepsGoal() / 100)));
|
||||
lv_obj_realign(stepGauge);
|
||||
if (stepCount.Get() > settingsController.GetStepsGoal()) {
|
||||
lv_obj_set_style_local_line_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
|
||||
|
@@ -42,7 +42,7 @@ namespace Pinetime {
|
||||
Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown;
|
||||
uint8_t currentDay = 0;
|
||||
|
||||
DirtyValue<int> batteryPercentRemaining {};
|
||||
DirtyValue<uint8_t> batteryPercentRemaining {};
|
||||
DirtyValue<bool> bleState {};
|
||||
DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime {};
|
||||
DirtyValue<bool> motionSensorOk {};
|
||||
|
@@ -13,8 +13,12 @@ namespace Pinetime {
|
||||
DirtyValue() = default; // Use NSDMI
|
||||
explicit DirtyValue(T const& v) : value {v} {
|
||||
} // Use MIL and const-lvalue-ref
|
||||
bool IsUpdated() const {
|
||||
return isUpdated;
|
||||
bool IsUpdated() {
|
||||
if (this->isUpdated) {
|
||||
this->isUpdated = false;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
T const& Get() {
|
||||
this->isUpdated = false;
|
||||
|
@@ -5,13 +5,10 @@
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
Steps::Steps(
|
||||
Pinetime::Applications::DisplayApp *app,
|
||||
Controllers::MotionController& motionController,
|
||||
Controllers::Settings &settingsController)
|
||||
: Screen(app),
|
||||
motionController{motionController},
|
||||
settingsController{settingsController} {
|
||||
Steps::Steps(Pinetime::Applications::DisplayApp* app,
|
||||
Controllers::MotionController& motionController,
|
||||
Controllers::Settings& settingsController)
|
||||
: Screen(app), motionController {motionController}, settingsController {settingsController} {
|
||||
|
||||
stepsArc = lv_arc_create(lv_scr_act(), nullptr);
|
||||
|
||||
@@ -34,12 +31,12 @@ Steps::Steps(
|
||||
lv_label_set_text_fmt(lSteps, "%li", stepsCount);
|
||||
lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -20);
|
||||
|
||||
lv_obj_t * lstepsL = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_t* lstepsL = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(lstepsL, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111));
|
||||
lv_label_set_text_static(lstepsL, "Steps");
|
||||
lv_obj_align(lstepsL, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
|
||||
|
||||
lv_obj_t * lstepsGoal = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_t* lstepsGoal = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(lstepsGoal, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_CYAN);
|
||||
lv_label_set_text_fmt(lstepsGoal, "Goal\n%lu", settingsController.GetStepsGoal());
|
||||
lv_label_set_align(lstepsGoal, LV_LABEL_ALIGN_CENTER);
|
||||
@@ -59,10 +56,10 @@ Steps::~Steps() {
|
||||
bool Steps::Refresh() {
|
||||
|
||||
stepsCount = motionController.NbSteps();
|
||||
|
||||
|
||||
lv_label_set_text_fmt(lSteps, "%li", stepsCount);
|
||||
lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -20);
|
||||
|
||||
|
||||
lv_arc_set_value(stepsArc, int16_t(500 * stepsCount / settingsController.GetStepsGoal()));
|
||||
|
||||
return running;
|
||||
|
@@ -41,6 +41,9 @@ namespace Pinetime {
|
||||
static constexpr const char* hourGlass = "\xEF\x89\x92";
|
||||
static constexpr const char* lapsFlag = "\xEF\x80\xA4";
|
||||
static constexpr const char* drum = "\xEF\x95\xA9";
|
||||
static constexpr const char* chartLine = "\xEF\x88\x81";
|
||||
static constexpr const char* eye = "\xEF\x81\xAE";
|
||||
static constexpr const char* home = "\xEF\x80\x95";
|
||||
|
||||
// lv_font_sys_48.c
|
||||
static constexpr const char* settings = "\xEE\xA4\x82"; // e902
|
||||
|
@@ -20,6 +20,8 @@ namespace {
|
||||
return "BMA421";
|
||||
case Pinetime::Controllers::MotionController::DeviceTypes::BMA425:
|
||||
return "BMA425";
|
||||
case Pinetime::Controllers::MotionController::DeviceTypes::Unknown:
|
||||
return "???";
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
@@ -70,11 +72,6 @@ bool SystemInfo::Refresh() {
|
||||
return running;
|
||||
}
|
||||
|
||||
bool SystemInfo::OnButtonPushed() {
|
||||
running = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SystemInfo::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||
return screens.OnTouchEvent(event);
|
||||
}
|
||||
@@ -103,7 +100,7 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen1() {
|
||||
}
|
||||
|
||||
std::unique_ptr<Screen> SystemInfo::CreateScreen2() {
|
||||
auto batteryPercent = static_cast<uint8_t>(batteryController.PercentRemaining());
|
||||
auto batteryPercent = batteryController.PercentRemaining();
|
||||
auto resetReason = [this]() {
|
||||
switch (watchdog.ResetReason()) {
|
||||
case Drivers::Watchdog::ResetReasons::Watchdog:
|
||||
@@ -212,28 +209,50 @@ bool SystemInfo::sortById(const TaskStatus_t& lhs, const TaskStatus_t& rhs) {
|
||||
std::unique_ptr<Screen> SystemInfo::CreateScreen4() {
|
||||
TaskStatus_t tasksStatus[7];
|
||||
lv_obj_t* infoTask = lv_table_create(lv_scr_act(), NULL);
|
||||
lv_table_set_col_cnt(infoTask, 3);
|
||||
lv_table_set_col_cnt(infoTask, 4);
|
||||
lv_table_set_row_cnt(infoTask, 8);
|
||||
lv_obj_set_pos(infoTask, 10, 10);
|
||||
lv_obj_set_pos(infoTask, 0, 10);
|
||||
|
||||
lv_table_set_cell_value(infoTask, 0, 0, "#");
|
||||
lv_table_set_col_width(infoTask, 0, 50);
|
||||
lv_table_set_cell_value(infoTask, 0, 1, "Task");
|
||||
lv_table_set_col_width(infoTask, 1, 80);
|
||||
lv_table_set_cell_value(infoTask, 0, 2, "Free");
|
||||
lv_table_set_col_width(infoTask, 2, 90);
|
||||
lv_table_set_col_width(infoTask, 0, 30);
|
||||
lv_table_set_cell_value(infoTask, 0, 1, "S"); // State
|
||||
lv_table_set_col_width(infoTask, 1, 30);
|
||||
lv_table_set_cell_value(infoTask, 0, 2, "Task");
|
||||
lv_table_set_col_width(infoTask, 2, 80);
|
||||
lv_table_set_cell_value(infoTask, 0, 3, "Free");
|
||||
lv_table_set_col_width(infoTask, 3, 90);
|
||||
|
||||
auto nb = uxTaskGetSystemState(tasksStatus, 7, nullptr);
|
||||
std::sort(tasksStatus, tasksStatus + nb, sortById);
|
||||
for (uint8_t i = 0; i < nb; i++) {
|
||||
|
||||
lv_table_set_cell_value(infoTask, i + 1, 0, std::to_string(tasksStatus[i].xTaskNumber).c_str());
|
||||
lv_table_set_cell_value(infoTask, i + 1, 1, tasksStatus[i].pcTaskName);
|
||||
char state[2] = {0};
|
||||
switch (tasksStatus[i].eCurrentState) {
|
||||
case eReady:
|
||||
case eRunning:
|
||||
state[0] = 'R';
|
||||
break;
|
||||
case eBlocked:
|
||||
state[0] = 'B';
|
||||
break;
|
||||
case eSuspended:
|
||||
state[0] = 'S';
|
||||
break;
|
||||
case eDeleted:
|
||||
state[0] = 'D';
|
||||
break;
|
||||
default:
|
||||
state[0] = 'I'; // Invalid
|
||||
break;
|
||||
}
|
||||
lv_table_set_cell_value(infoTask, i + 1, 1, state);
|
||||
lv_table_set_cell_value(infoTask, i + 1, 2, tasksStatus[i].pcTaskName);
|
||||
if (tasksStatus[i].usStackHighWaterMark < 20) {
|
||||
std::string str1 = std::to_string(tasksStatus[i].usStackHighWaterMark) + " low";
|
||||
lv_table_set_cell_value(infoTask, i + 1, 2, str1.c_str());
|
||||
lv_table_set_cell_value(infoTask, i + 1, 3, str1.c_str());
|
||||
} else {
|
||||
lv_table_set_cell_value(infoTask, i + 1, 2, std::to_string(tasksStatus[i].usStackHighWaterMark).c_str());
|
||||
lv_table_set_cell_value(infoTask, i + 1, 3, std::to_string(tasksStatus[i].usStackHighWaterMark).c_str());
|
||||
}
|
||||
}
|
||||
return std::make_unique<Screens::Label>(3, 5, app, infoTask);
|
||||
|
@@ -31,12 +31,9 @@ namespace Pinetime {
|
||||
Pinetime::Controllers::MotionController& motionController);
|
||||
~SystemInfo() override;
|
||||
bool Refresh() override;
|
||||
bool OnButtonPushed() override;
|
||||
bool OnTouchEvent(TouchEvents event) override;
|
||||
|
||||
private:
|
||||
bool running = true;
|
||||
|
||||
Pinetime::Controllers::DateTime& dateTimeController;
|
||||
Pinetime::Controllers::Battery& batteryController;
|
||||
Pinetime::Controllers::BrightnessController& brightnessController;
|
||||
@@ -56,4 +53,4 @@ namespace Pinetime {
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -6,15 +6,17 @@ using namespace Pinetime::Applications::Screens;
|
||||
|
||||
namespace {
|
||||
static void lv_update_task(struct _lv_task_t* task) {
|
||||
auto user_data = static_cast<Tile*>(task->user_data);
|
||||
auto* user_data = static_cast<Tile*>(task->user_data);
|
||||
user_data->UpdateScreen();
|
||||
}
|
||||
|
||||
static void event_handler(lv_obj_t* obj, lv_event_t event) {
|
||||
if (event != LV_EVENT_VALUE_CHANGED) return;
|
||||
|
||||
Tile* screen = static_cast<Tile*>(obj->user_data);
|
||||
uint32_t* eventDataPtr = (uint32_t*) lv_event_get_data();
|
||||
auto* eventDataPtr = (uint32_t*) lv_event_get_data();
|
||||
uint32_t eventData = *eventDataPtr;
|
||||
screen->OnObjectEvent(obj, event, eventData);
|
||||
screen->OnValueChangedEvent(obj, eventData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +109,7 @@ Tile::Tile(uint8_t screenID,
|
||||
lv_obj_set_pos(backgroundLabel, 0, 0);
|
||||
lv_label_set_text_static(backgroundLabel, "");
|
||||
|
||||
taskUpdate = lv_task_create(lv_update_task, 500000, LV_TASK_PRIO_MID, this);
|
||||
taskUpdate = lv_task_create(lv_update_task, 5000, LV_TASK_PRIO_MID, this);
|
||||
}
|
||||
|
||||
Tile::~Tile() {
|
||||
@@ -124,9 +126,9 @@ bool Tile::Refresh() {
|
||||
return running;
|
||||
}
|
||||
|
||||
void Tile::OnObjectEvent(lv_obj_t* obj, lv_event_t event, uint32_t buttonId) {
|
||||
if (event == LV_EVENT_VALUE_CHANGED) {
|
||||
app->StartApp(apps[buttonId], DisplayApp::FullRefreshDirections::Up);
|
||||
running = false;
|
||||
}
|
||||
void Tile::OnValueChangedEvent(lv_obj_t* obj, uint32_t buttonId) {
|
||||
if(obj != btnm1) return;
|
||||
|
||||
app->StartApp(apps[buttonId], DisplayApp::FullRefreshDirections::Up);
|
||||
running = false;
|
||||
}
|
||||
|
@@ -32,7 +32,7 @@ namespace Pinetime {
|
||||
|
||||
bool Refresh() override;
|
||||
void UpdateScreen();
|
||||
void OnObjectEvent(lv_obj_t* obj, lv_event_t event, uint32_t buttonId);
|
||||
void OnValueChangedEvent(lv_obj_t* obj, uint32_t buttonId);
|
||||
|
||||
private:
|
||||
Pinetime::Controllers::Battery& batteryController;
|
||||
|
@@ -5,27 +5,44 @@
|
||||
#include "Symbols.h"
|
||||
#include "NotificationIcon.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
LV_IMG_DECLARE(bg_clock);
|
||||
|
||||
using namespace Pinetime::Applications::Screens;
|
||||
|
||||
#define HOUR_LENGTH 70
|
||||
#define MINUTE_LENGTH 90
|
||||
#define SECOND_LENGTH 110
|
||||
#define PI 3.14159265358979323846
|
||||
namespace {
|
||||
|
||||
// ##
|
||||
static int16_t coordinate_x_relocate(int16_t x) {
|
||||
return ((x) + LV_HOR_RES / 2);
|
||||
constexpr auto HOUR_LENGTH = 70;
|
||||
constexpr auto MINUTE_LENGTH = 90;
|
||||
constexpr auto SECOND_LENGTH = 110;
|
||||
|
||||
// sin(90) = 1 so the value of _lv_trigo_sin(90) is the scaling factor
|
||||
const auto LV_TRIG_SCALE = _lv_trigo_sin(90);
|
||||
|
||||
int16_t cosine(int16_t angle) {
|
||||
return _lv_trigo_sin(angle + 90);
|
||||
}
|
||||
|
||||
// ##
|
||||
static int16_t coordinate_y_relocate(int16_t y) {
|
||||
return (((y) -LV_HOR_RES / 2) < 0) ? (0 - ((y) -LV_HOR_RES / 2)) : ((y) -LV_HOR_RES / 2);
|
||||
int16_t sine(int16_t angle) {
|
||||
return _lv_trigo_sin(angle);
|
||||
}
|
||||
|
||||
int16_t coordinate_x_relocate(int16_t x) {
|
||||
return (x + LV_HOR_RES / 2);
|
||||
}
|
||||
|
||||
int16_t coordinate_y_relocate(int16_t y) {
|
||||
return std::abs(y - LV_HOR_RES / 2);
|
||||
}
|
||||
|
||||
lv_point_t coordinate_relocate(int16_t radius, int16_t angle) {
|
||||
return lv_point_t{
|
||||
.x = coordinate_x_relocate(radius * static_cast<int32_t>(sine(angle)) / LV_TRIG_SCALE),
|
||||
.y = coordinate_y_relocate(radius * static_cast<int32_t>(cosine(angle)) / LV_TRIG_SCALE)
|
||||
};
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app,
|
||||
Controllers::DateTime& dateTimeController,
|
||||
Controllers::Battery& batteryController,
|
||||
@@ -123,15 +140,12 @@ void WatchFaceAnalog::UpdateClock() {
|
||||
second = dateTimeController.Seconds();
|
||||
|
||||
if (sMinute != minute) {
|
||||
minute_point[0].x = coordinate_x_relocate(30 * sin(minute * 6 * PI / 180));
|
||||
minute_point[0].y = coordinate_y_relocate(30 * cos(minute * 6 * PI / 180));
|
||||
minute_point[1].x = coordinate_x_relocate(MINUTE_LENGTH * sin(minute * 6 * PI / 180));
|
||||
minute_point[1].y = coordinate_y_relocate(MINUTE_LENGTH * cos(minute * 6 * PI / 180));
|
||||
auto const angle = minute * 6;
|
||||
minute_point[0] = coordinate_relocate(30, angle);
|
||||
minute_point[1] = coordinate_relocate(MINUTE_LENGTH, angle);
|
||||
|
||||
minute_point_trace[0].x = coordinate_x_relocate(5 * sin(minute * 6 * PI / 180));
|
||||
minute_point_trace[0].y = coordinate_y_relocate(5 * cos(minute * 6 * PI / 180));
|
||||
minute_point_trace[1].x = coordinate_x_relocate(31 * sin(minute * 6 * PI / 180));
|
||||
minute_point_trace[1].y = coordinate_y_relocate(31 * cos(minute * 6 * PI / 180));
|
||||
minute_point_trace[0] = coordinate_relocate(5, angle);
|
||||
minute_point_trace[1] = coordinate_relocate(31, angle);
|
||||
|
||||
lv_line_set_points(minute_body, minute_point, 2);
|
||||
lv_line_set_points(minute_body_trace, minute_point_trace, 2);
|
||||
@@ -140,15 +154,13 @@ void WatchFaceAnalog::UpdateClock() {
|
||||
if (sHour != hour || sMinute != minute) {
|
||||
sHour = hour;
|
||||
sMinute = minute;
|
||||
hour_point[0].x = coordinate_x_relocate(30 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
hour_point[0].y = coordinate_y_relocate(30 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
hour_point[1].x = coordinate_x_relocate(HOUR_LENGTH * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
hour_point[1].y = coordinate_y_relocate(HOUR_LENGTH * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
auto const angle = (hour * 30 + minute / 2);
|
||||
|
||||
hour_point_trace[0].x = coordinate_x_relocate(5 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
hour_point_trace[0].y = coordinate_y_relocate(5 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
hour_point_trace[1].x = coordinate_x_relocate(31 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
hour_point_trace[1].y = coordinate_y_relocate(31 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
|
||||
hour_point[0] = coordinate_relocate(30, angle);
|
||||
hour_point[1] = coordinate_relocate(HOUR_LENGTH, angle);
|
||||
|
||||
hour_point_trace[0] = coordinate_relocate(5, angle);
|
||||
hour_point_trace[1] = coordinate_relocate(31, angle);
|
||||
|
||||
lv_line_set_points(hour_body, hour_point, 2);
|
||||
lv_line_set_points(hour_body_trace, hour_point_trace, 2);
|
||||
@@ -156,16 +168,15 @@ void WatchFaceAnalog::UpdateClock() {
|
||||
|
||||
if (sSecond != second) {
|
||||
sSecond = second;
|
||||
second_point[0].x = coordinate_x_relocate(20 * sin((180 + second * 6) * PI / 180));
|
||||
second_point[0].y = coordinate_y_relocate(20 * cos((180 + second * 6) * PI / 180));
|
||||
second_point[1].x = coordinate_x_relocate(SECOND_LENGTH * sin(second * 6 * PI / 180));
|
||||
second_point[1].y = coordinate_y_relocate(SECOND_LENGTH * cos(second * 6 * PI / 180));
|
||||
auto const angle = second * 6;
|
||||
|
||||
second_point[0] = coordinate_relocate(-20, angle);
|
||||
second_point[1] = coordinate_relocate(SECOND_LENGTH, angle);
|
||||
lv_line_set_points(second_body, second_point, 2);
|
||||
}
|
||||
}
|
||||
|
||||
bool WatchFaceAnalog::Refresh() {
|
||||
|
||||
batteryPercentRemaining = batteryController.PercentRemaining();
|
||||
if (batteryPercentRemaining.IsUpdated()) {
|
||||
auto batteryPercent = batteryPercentRemaining.Get();
|
||||
|
@@ -48,7 +48,7 @@ namespace Pinetime {
|
||||
Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown;
|
||||
uint8_t currentDay = 0;
|
||||
|
||||
DirtyValue<float> batteryPercentRemaining {0};
|
||||
DirtyValue<uint8_t> batteryPercentRemaining {0};
|
||||
DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime;
|
||||
DirtyValue<bool> notificationState {false};
|
||||
|
||||
|
@@ -45,7 +45,7 @@ namespace Pinetime {
|
||||
Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown;
|
||||
uint8_t currentDay = 0;
|
||||
|
||||
DirtyValue<int> batteryPercentRemaining {};
|
||||
DirtyValue<uint8_t> batteryPercentRemaining {};
|
||||
DirtyValue<bool> bleState {};
|
||||
DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime {};
|
||||
DirtyValue<bool> motionSensorOk {};
|
||||
|
@@ -27,7 +27,7 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
|
||||
batteryController {batteryController},
|
||||
dateTimeController {dateTimeController},
|
||||
brightness {brightness},
|
||||
motorController{motorController},
|
||||
motorController {motorController},
|
||||
settingsController {settingsController} {
|
||||
|
||||
// Time
|
||||
@@ -110,7 +110,7 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
|
||||
lv_obj_set_pos(backgroundLabel, 0, 0);
|
||||
lv_label_set_text_static(backgroundLabel, "");
|
||||
|
||||
taskUpdate = lv_task_create(lv_update_task, 500000, LV_TASK_PRIO_MID, this);
|
||||
taskUpdate = lv_task_create(lv_update_task, 5000, LV_TASK_PRIO_MID, this);
|
||||
}
|
||||
|
||||
QuickSettings::~QuickSettings() {
|
||||
@@ -154,17 +154,6 @@ void QuickSettings::OnButtonEvent(lv_obj_t* object, lv_event_t event) {
|
||||
}
|
||||
}
|
||||
|
||||
bool QuickSettings::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
|
||||
switch (event) {
|
||||
case Pinetime::Applications::TouchEvents::SwipeLeft:
|
||||
running = false;
|
||||
return false;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool QuickSettings::Refresh() {
|
||||
return running;
|
||||
}
|
||||
|
@@ -29,7 +29,6 @@ namespace Pinetime {
|
||||
|
||||
bool Refresh() override;
|
||||
|
||||
bool OnTouchEvent(Pinetime::Applications::TouchEvents event) override;
|
||||
void OnButtonEvent(lv_obj_t* object, lv_event_t event);
|
||||
|
||||
void UpdateScreen();
|
||||
|
@@ -16,7 +16,7 @@ namespace {
|
||||
|
||||
SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Settings& settingsController)
|
||||
: Screen(app), settingsController {settingsController} {
|
||||
|
||||
ignoringEvents = false;
|
||||
lv_obj_t* container1 = lv_cont_create(lv_scr_act(), nullptr);
|
||||
|
||||
lv_obj_set_style_local_bg_opa(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
|
||||
@@ -36,24 +36,16 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::
|
||||
|
||||
lv_obj_t* icon = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE);
|
||||
lv_label_set_text_static(icon, Symbols::clock);
|
||||
lv_label_set_text_static(icon, Symbols::eye);
|
||||
lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER);
|
||||
lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0);
|
||||
|
||||
optionsTotal = 0;
|
||||
cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr);
|
||||
lv_checkbox_set_text_static(cbOption[optionsTotal], " None");
|
||||
cbOption[optionsTotal]->user_data = this;
|
||||
lv_obj_set_event_cb(cbOption[optionsTotal], event_handler);
|
||||
if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::None) {
|
||||
lv_checkbox_set_checked(cbOption[optionsTotal], true);
|
||||
}
|
||||
optionsTotal++;
|
||||
cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr);
|
||||
lv_checkbox_set_text_static(cbOption[optionsTotal], " Single Tap");
|
||||
cbOption[optionsTotal]->user_data = this;
|
||||
lv_obj_set_event_cb(cbOption[optionsTotal], event_handler);
|
||||
if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::SingleTap) {
|
||||
if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)) {
|
||||
lv_checkbox_set_checked(cbOption[optionsTotal], true);
|
||||
}
|
||||
optionsTotal++;
|
||||
@@ -61,7 +53,7 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::
|
||||
lv_checkbox_set_text_static(cbOption[optionsTotal], " Double Tap");
|
||||
cbOption[optionsTotal]->user_data = this;
|
||||
lv_obj_set_event_cb(cbOption[optionsTotal], event_handler);
|
||||
if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::DoubleTap) {
|
||||
if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
|
||||
lv_checkbox_set_checked(cbOption[optionsTotal], true);
|
||||
}
|
||||
optionsTotal++;
|
||||
@@ -69,7 +61,7 @@ SettingWakeUp::SettingWakeUp(Pinetime::Applications::DisplayApp* app, Pinetime::
|
||||
lv_checkbox_set_text_static(cbOption[optionsTotal], " Raise Wrist");
|
||||
cbOption[optionsTotal]->user_data = this;
|
||||
lv_obj_set_event_cb(cbOption[optionsTotal], event_handler);
|
||||
if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist) {
|
||||
if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist)) {
|
||||
lv_checkbox_set_checked(cbOption[optionsTotal], true);
|
||||
}
|
||||
optionsTotal++;
|
||||
@@ -85,27 +77,31 @@ bool SettingWakeUp::Refresh() {
|
||||
}
|
||||
|
||||
void SettingWakeUp::UpdateSelected(lv_obj_t* object, lv_event_t event) {
|
||||
if (event == LV_EVENT_VALUE_CHANGED) {
|
||||
for (int i = 0; i < optionsTotal; i++) {
|
||||
if (object == cbOption[i]) {
|
||||
lv_checkbox_set_checked(cbOption[i], true);
|
||||
using WakeUpMode = Pinetime::Controllers::Settings::WakeUpMode;
|
||||
if (event == LV_EVENT_VALUE_CHANGED && !ignoringEvents) {
|
||||
ignoringEvents = true;
|
||||
|
||||
if (i == 0) {
|
||||
settingsController.setWakeUpMode(Pinetime::Controllers::Settings::WakeUpMode::None);
|
||||
};
|
||||
if (i == 1) {
|
||||
settingsController.setWakeUpMode(Pinetime::Controllers::Settings::WakeUpMode::SingleTap);
|
||||
};
|
||||
if (i == 2) {
|
||||
settingsController.setWakeUpMode(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap);
|
||||
};
|
||||
if (i == 3) {
|
||||
settingsController.setWakeUpMode(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist);
|
||||
};
|
||||
|
||||
} else {
|
||||
lv_checkbox_set_checked(cbOption[i], false);
|
||||
// Find the index of the checkbox that triggered the event
|
||||
int index = 0;
|
||||
for (; index < optionsTotal; ++index) {
|
||||
if (cbOption[index] == object) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle needed wakeup mode
|
||||
auto mode = static_cast<WakeUpMode>(index);
|
||||
auto currentState = settingsController.isWakeUpModeOn(mode);
|
||||
settingsController.setWakeUpMode(mode, !currentState);
|
||||
|
||||
// Update checkbox according to current wakeup modes.
|
||||
// This is needed because we can have extra logic when setting or unsetting wakeup modes,
|
||||
// for example, when setting SingleTap, DoubleTap is unset and vice versa.
|
||||
auto modes = settingsController.getWakeUpModes();
|
||||
for (int i = 0; i < optionsTotal; ++i) {
|
||||
lv_checkbox_set_checked(cbOption[i], modes[i]);
|
||||
}
|
||||
|
||||
ignoringEvents = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -22,6 +22,11 @@ namespace Pinetime {
|
||||
Controllers::Settings& settingsController;
|
||||
uint8_t optionsTotal;
|
||||
lv_obj_t* cbOption[4];
|
||||
// When UpdateSelected is called, it uses lv_checkbox_set_checked,
|
||||
// which can cause extra events to be fired,
|
||||
// which might trigger UpdateSelected again, causing a loop.
|
||||
// This variable is used as a mutex to prevent that.
|
||||
bool ignoringEvents;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@@ -36,7 +36,7 @@ SettingWatchFace::SettingWatchFace(Pinetime::Applications::DisplayApp* app, Pine
|
||||
|
||||
lv_obj_t* icon = lv_label_create(lv_scr_act(), nullptr);
|
||||
lv_obj_set_style_local_text_color(icon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE);
|
||||
lv_label_set_text_static(icon, Symbols::clock);
|
||||
lv_label_set_text_static(icon, Symbols::home);
|
||||
lv_label_set_align(icon, LV_LABEL_ALIGN_CENTER);
|
||||
lv_obj_align(icon, title, LV_ALIGN_OUT_LEFT_MID, -10, 0);
|
||||
|
||||
@@ -90,4 +90,4 @@ void SettingWatchFace::UpdateSelected(lv_obj_t* object, lv_event_t event) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -44,9 +44,9 @@ std::unique_ptr<Screen> Settings::CreateScreen1() {
|
||||
|
||||
std::array<Screens::List::Applications, 4> applications {{
|
||||
{Symbols::sun, "Display", Apps::SettingDisplay},
|
||||
{Symbols::clock, "Wake Up", Apps::SettingWakeUp},
|
||||
{Symbols::eye, "Wake Up", Apps::SettingWakeUp},
|
||||
{Symbols::clock, "Time format", Apps::SettingTimeFormat},
|
||||
{Symbols::clock, "Watch face", Apps::SettingWatchFace},
|
||||
{Symbols::home, "Watch face", Apps::SettingWatchFace},
|
||||
}};
|
||||
|
||||
return std::make_unique<Screens::List>(0, 3, app, settingsController, applications);
|
||||
|
1
src/libs/littlefs
Submodule
1
src/libs/littlefs
Submodule
Submodule src/libs/littlefs added at ead50807f1
@@ -42,7 +42,7 @@
|
||||
|
||||
/* Default display refresh period.
|
||||
* Can be changed in the display driver (`lv_disp_drv_t`).*/
|
||||
#define LV_DISP_DEF_REFR_PERIOD 30 /*[ms]*/
|
||||
#define LV_DISP_DEF_REFR_PERIOD 20 /*[ms]*/
|
||||
|
||||
/* Dot Per Inch: used to initialize default sizes.
|
||||
* E.g. a button with width = LV_DPI / 2 -> half inch wide
|
||||
@@ -112,7 +112,7 @@ typedef int16_t lv_coord_t;
|
||||
* Can be changed in the Input device driver (`lv_indev_drv_t`)*/
|
||||
|
||||
/* Input device read period in milliseconds */
|
||||
#define LV_INDEV_DEF_READ_PERIOD 30
|
||||
#define LV_INDEV_DEF_READ_PERIOD 20
|
||||
|
||||
/* Drag threshold in pixels */
|
||||
#define LV_INDEV_DEF_DRAG_LIMIT 10
|
||||
@@ -128,7 +128,6 @@ typedef int16_t lv_coord_t;
|
||||
* Time between `LV_EVENT_LONG_PRESSED_REPEAT */
|
||||
#define LV_INDEV_DEF_LONG_PRESS_REP_TIME 100
|
||||
|
||||
|
||||
/* Gesture threshold in pixels */
|
||||
#define LV_INDEV_DEF_GESTURE_LIMIT 50
|
||||
|
||||
@@ -204,7 +203,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h" */
|
||||
|
||||
/* 1: Enable file system (might be required for images */
|
||||
// TODO: Enable FS
|
||||
#define LV_USE_FILESYSTEM 0
|
||||
#define LV_USE_FILESYSTEM 1
|
||||
#if LV_USE_FILESYSTEM
|
||||
/*Declare the type of the user data of file system drivers (can be e.g. `void *`, `int`, `struct`)*/
|
||||
typedef void * lv_fs_drv_user_data_t;
|
||||
@@ -236,7 +235,7 @@ typedef void * lv_fs_drv_user_data_t;
|
||||
* With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images.
|
||||
* However the opened images might consume additional RAM.
|
||||
* LV_IMG_CACHE_DEF_SIZE must be >= 1 */
|
||||
#define LV_IMG_CACHE_DEF_SIZE 1
|
||||
#define LV_IMG_CACHE_DEF_SIZE 6
|
||||
|
||||
/*Declare the type of the user data of image decoder (can be e.g. `void *`, `int`, `struct`)*/
|
||||
typedef void* lv_img_decoder_user_data_t;
|
||||
@@ -293,10 +292,11 @@ typedef void* lv_img_decoder_user_data_t;
|
||||
|
||||
/* 1: use a custom tick source.
|
||||
* It removes the need to manually update the tick with `lv_tick_inc`) */
|
||||
#define LV_TICK_CUSTOM 0
|
||||
#define LV_TICK_CUSTOM 1
|
||||
#if LV_TICK_CUSTOM == 1
|
||||
#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/
|
||||
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/
|
||||
#define LV_TICK_CUSTOM_INCLUDE "FreeRTOS.h" /*Header for the system time function*/
|
||||
uint32_t xTaskGetTickCount(); /*Forward declare to avoid compiler warning*/
|
||||
#define LV_TICK_CUSTOM_SYS_TIME_EXPR (xTaskGetTickCount()) /*Expression evaluating to current system time in ms*/
|
||||
#endif /*LV_TICK_CUSTOM*/
|
||||
|
||||
typedef void* lv_disp_drv_user_data_t; /*Type of user data in the display driver*/
|
||||
@@ -759,4 +759,4 @@ typedef void* lv_obj_user_data_t;
|
||||
|
||||
/*--END OF LV_CONF_H--*/
|
||||
|
||||
#endif /*LV_CONF_H*/
|
||||
#endif /*LV_CONF_H*/
|
||||
|
20
src/main.cpp
20
src/main.cpp
@@ -35,6 +35,7 @@
|
||||
#include "components/motor/MotorController.h"
|
||||
#include "components/datetime/DateTimeController.h"
|
||||
#include "components/heartrate/HeartRateController.h"
|
||||
#include "components/fs/FS.h"
|
||||
#include "drivers/Spi.h"
|
||||
#include "drivers/SpiMaster.h"
|
||||
#include "drivers/SpiNorFlash.h"
|
||||
@@ -108,10 +109,6 @@ void ble_manager_set_ble_disconnection_callback(void (*disconnection)());
|
||||
static constexpr uint8_t pinTouchIrq = 28;
|
||||
static constexpr uint8_t pinPowerPresentIrq = 19;
|
||||
|
||||
Pinetime::Controllers::Settings settingsController {spiNorFlash};
|
||||
|
||||
Pinetime::Controllers::MotorController motorController {settingsController};
|
||||
|
||||
Pinetime::Controllers::HeartRateController heartRateController;
|
||||
Pinetime::Applications::HeartRateTask heartRateApp(heartRateSensor, heartRateController);
|
||||
|
||||
@@ -122,6 +119,11 @@ Pinetime::Controllers::NotificationManager notificationManager;
|
||||
Pinetime::Controllers::MotionController motionController;
|
||||
Pinetime::Controllers::TimerController timerController;
|
||||
|
||||
Pinetime::Controllers::FS fs {spiNorFlash};
|
||||
Pinetime::Controllers::Settings settingsController {fs};
|
||||
Pinetime::Controllers::MotorController motorController {settingsController};
|
||||
|
||||
|
||||
Pinetime::Applications::DisplayApp displayApp(lcd,
|
||||
lvgl,
|
||||
touchPanel,
|
||||
@@ -155,7 +157,8 @@ Pinetime::System::SystemTask systemTask(spi,
|
||||
settingsController,
|
||||
heartRateController,
|
||||
displayApp,
|
||||
heartRateApp);
|
||||
heartRateApp,
|
||||
fs);
|
||||
|
||||
void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
|
||||
if (pin == pinTouchIrq) {
|
||||
@@ -175,13 +178,6 @@ void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action
|
||||
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
void vApplicationIdleHook(void) {
|
||||
if (!isFactory)
|
||||
lv_tick_inc(1);
|
||||
}
|
||||
}
|
||||
|
||||
void DebounceTimerChargeCallback(TimerHandle_t xTimer) {
|
||||
xTimerStop(xTimer, 0);
|
||||
systemTask.PushMessage(Pinetime::System::Messages::OnChargingEvent);
|
||||
|
@@ -33,6 +33,13 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
void DimTimerCallback(TimerHandle_t xTimer) {
|
||||
|
||||
NRF_LOG_INFO("DimTimerCallback");
|
||||
auto sysTask = static_cast<SystemTask*>(pvTimerGetTimerID(xTimer));
|
||||
sysTask->OnDim();
|
||||
}
|
||||
|
||||
void IdleTimerCallback(TimerHandle_t xTimer) {
|
||||
|
||||
NRF_LOG_INFO("IdleTimerCallback");
|
||||
@@ -59,7 +66,8 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
|
||||
Controllers::Settings& settingsController,
|
||||
Pinetime::Controllers::HeartRateController& heartRateController,
|
||||
Pinetime::Applications::DisplayApp& displayApp,
|
||||
Pinetime::Applications::HeartRateTask& heartRateApp)
|
||||
Pinetime::Applications::HeartRateTask& heartRateApp,
|
||||
Pinetime::Controllers::FS& fs)
|
||||
: spi {spi},
|
||||
lcd {lcd},
|
||||
spiNorFlash {spiNorFlash},
|
||||
@@ -77,10 +85,11 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
|
||||
motionSensor {motionSensor},
|
||||
settingsController {settingsController},
|
||||
heartRateController{heartRateController},
|
||||
nimbleController(*this, bleController, dateTimeController, notificationManager, batteryController, spiNorFlash, heartRateController),
|
||||
motionController{motionController},
|
||||
displayApp{displayApp},
|
||||
heartRateApp(heartRateApp) {
|
||||
heartRateApp(heartRateApp),
|
||||
fs{fs},
|
||||
nimbleController(*this, bleController, dateTimeController, notificationManager, batteryController, spiNorFlash, heartRateController) {
|
||||
|
||||
}
|
||||
|
||||
@@ -103,13 +112,15 @@ void SystemTask::Work() {
|
||||
APP_GPIOTE_INIT(2);
|
||||
|
||||
app_timer_init();
|
||||
|
||||
|
||||
spi.Init();
|
||||
spiNorFlash.Init();
|
||||
spiNorFlash.Wakeup();
|
||||
|
||||
fs.Init();
|
||||
|
||||
nimbleController.Init();
|
||||
nimbleController.StartAdvertising();
|
||||
brightnessController.Init();
|
||||
lcd.Init();
|
||||
|
||||
twiMaster.Init();
|
||||
@@ -174,8 +185,9 @@ void SystemTask::Work() {
|
||||
nrf_gpio_cfg_sense_input(pinPowerPresentIrq, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH);
|
||||
}
|
||||
|
||||
idleTimer = xTimerCreate("idleTimer", pdMS_TO_TICKS(settingsController.GetScreenTimeOut()), pdFALSE, this, IdleTimerCallback);
|
||||
xTimerStart(idleTimer, 0);
|
||||
idleTimer = xTimerCreate("idleTimer", pdMS_TO_TICKS(2000), pdFALSE, this, IdleTimerCallback);
|
||||
dimTimer = xTimerCreate("dimTimer", pdMS_TO_TICKS(settingsController.GetScreenTimeOut() - 2000), pdFALSE, this, DimTimerCallback);
|
||||
xTimerStart(dimTimer, 0);
|
||||
|
||||
// Suppress endless loop diagnostic
|
||||
#pragma clang diagnostic push
|
||||
@@ -193,25 +205,29 @@ void SystemTask::Work() {
|
||||
Messages message = static_cast<Messages>(msg);
|
||||
switch (message) {
|
||||
case Messages::EnableSleeping:
|
||||
doNotGoToSleep = false;
|
||||
// Make sure that exiting an app doesn't enable sleeping,
|
||||
// if the exiting was caused by a firmware update
|
||||
if (!bleController.IsFirmwareUpdating()) {
|
||||
doNotGoToSleep = false;
|
||||
}
|
||||
break;
|
||||
case Messages::DisableSleeping:
|
||||
doNotGoToSleep = true;
|
||||
break;
|
||||
case Messages::UpdateTimeOut:
|
||||
xTimerChangePeriod(idleTimer, pdMS_TO_TICKS(settingsController.GetScreenTimeOut()), 0);
|
||||
xTimerChangePeriod(dimTimer, pdMS_TO_TICKS(settingsController.GetScreenTimeOut() - 2000), 0);
|
||||
break;
|
||||
case Messages::GoToRunning:
|
||||
spi.Wakeup();
|
||||
twiMaster.Wakeup();
|
||||
|
||||
// Double Tap needs the touch screen to be in normal mode
|
||||
if (settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::DoubleTap) {
|
||||
if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
|
||||
touchPanel.Wakeup();
|
||||
}
|
||||
|
||||
nimbleController.StartAdvertising();
|
||||
xTimerStart(idleTimer, 0);
|
||||
xTimerStart(dimTimer, 0);
|
||||
spiNorFlash.Wakeup();
|
||||
lcd.Wakeup();
|
||||
|
||||
@@ -221,15 +237,16 @@ void SystemTask::Work() {
|
||||
|
||||
isSleeping = false;
|
||||
isWakingUp = false;
|
||||
isDimmed = false;
|
||||
break;
|
||||
case Messages::TouchWakeUp: {
|
||||
twiMaster.Wakeup();
|
||||
auto touchInfo = touchPanel.GetTouchInfo();
|
||||
twiMaster.Sleep();
|
||||
if (touchInfo.isTouch and ((touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap and
|
||||
settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::DoubleTap) or
|
||||
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) or
|
||||
(touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::SingleTap and
|
||||
settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::SingleTap))) {
|
||||
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) {
|
||||
GoToRunning();
|
||||
}
|
||||
} break;
|
||||
@@ -237,6 +254,7 @@ void SystemTask::Work() {
|
||||
isGoingToSleep = true;
|
||||
NRF_LOG_INFO("[systemtask] Going to sleep");
|
||||
xTimerStop(idleTimer, 0);
|
||||
xTimerStop(dimTimer, 0);
|
||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToSleep);
|
||||
heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep);
|
||||
break;
|
||||
@@ -270,16 +288,19 @@ void SystemTask::Work() {
|
||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted);
|
||||
break;
|
||||
case Messages::BleFirmwareUpdateFinished:
|
||||
doNotGoToSleep = false;
|
||||
xTimerStart(idleTimer, 0);
|
||||
if (bleController.State() == Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated)
|
||||
if (bleController.State() == Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated) {
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
doNotGoToSleep = false;
|
||||
xTimerStart(dimTimer, 0);
|
||||
break;
|
||||
case Messages::OnTouchEvent:
|
||||
ReloadIdleTimer();
|
||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent);
|
||||
break;
|
||||
case Messages::OnButtonEvent:
|
||||
ReloadIdleTimer();
|
||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonPushed);
|
||||
break;
|
||||
case Messages::OnDisplayTaskSleeping:
|
||||
if (BootloaderVersion::IsValid()) {
|
||||
@@ -291,7 +312,7 @@ void SystemTask::Work() {
|
||||
spi.Sleep();
|
||||
|
||||
// Double Tap needs the touch screen to be in normal mode
|
||||
if (settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::DoubleTap) {
|
||||
if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
|
||||
touchPanel.Sleep();
|
||||
}
|
||||
twiMaster.Sleep();
|
||||
@@ -325,6 +346,11 @@ void SystemTask::Work() {
|
||||
}
|
||||
}
|
||||
|
||||
if (xTaskGetTickCount() - batteryNotificationTick > batteryNotificationPeriod) {
|
||||
nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining());
|
||||
batteryNotificationTick = xTaskGetTickCount();
|
||||
}
|
||||
|
||||
monitor.Process();
|
||||
uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG);
|
||||
dateTimeController.UpdateTime(systick_counter);
|
||||
@@ -338,7 +364,7 @@ void SystemTask::UpdateMotion() {
|
||||
if (isGoingToSleep or isWakingUp)
|
||||
return;
|
||||
|
||||
if (isSleeping && settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist)
|
||||
if (isSleeping && !settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist))
|
||||
return;
|
||||
|
||||
if (isSleeping)
|
||||
@@ -366,7 +392,6 @@ void SystemTask::OnButtonPushed() {
|
||||
if (!isSleeping) {
|
||||
NRF_LOG_INFO("[systemtask] Button pushed");
|
||||
PushMessage(Messages::OnButtonEvent);
|
||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonPushed);
|
||||
} else {
|
||||
if (!isWakingUp) {
|
||||
NRF_LOG_INFO("[systemtask] Button pushed, waking up");
|
||||
@@ -387,12 +412,11 @@ void SystemTask::OnTouchEvent() {
|
||||
return;
|
||||
if (!isSleeping) {
|
||||
PushMessage(Messages::OnTouchEvent);
|
||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent);
|
||||
} else if (!isWakingUp) {
|
||||
if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::None or
|
||||
settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist)
|
||||
return;
|
||||
PushMessage(Messages::TouchWakeUp);
|
||||
if (settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap) or
|
||||
settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
|
||||
PushMessage(Messages::TouchWakeUp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,6 +439,15 @@ void SystemTask::PushMessage(System::Messages msg) {
|
||||
}
|
||||
}
|
||||
|
||||
void SystemTask::OnDim() {
|
||||
if (doNotGoToSleep)
|
||||
return;
|
||||
NRF_LOG_INFO("Dim timeout -> Dim screen")
|
||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::DimScreen);
|
||||
xTimerStart(idleTimer, 0);
|
||||
isDimmed = true;
|
||||
}
|
||||
|
||||
void SystemTask::OnIdle() {
|
||||
if (doNotGoToSleep)
|
||||
return;
|
||||
@@ -422,8 +455,13 @@ void SystemTask::OnIdle() {
|
||||
PushMessage(Messages::GoToSleep);
|
||||
}
|
||||
|
||||
void SystemTask::ReloadIdleTimer() const {
|
||||
void SystemTask::ReloadIdleTimer() {
|
||||
if (isSleeping || isGoingToSleep)
|
||||
return;
|
||||
xTimerReset(idleTimer, 0);
|
||||
if (isDimmed) {
|
||||
displayApp.PushMessage(Pinetime::Applications::Display::Messages::RestoreBrightness);
|
||||
isDimmed = false;
|
||||
}
|
||||
xTimerReset(dimTimer, 0);
|
||||
xTimerStop(idleTimer, 0);
|
||||
}
|
||||
|
@@ -16,13 +16,15 @@
|
||||
#include "components/ble/NotificationManager.h"
|
||||
#include "components/motor/MotorController.h"
|
||||
#include "components/timer/TimerController.h"
|
||||
#include "components/fs/FS.h"
|
||||
|
||||
#ifdef PINETIME_IS_RECOVERY
|
||||
#include "displayapp/DisplayAppRecovery.h"
|
||||
#include "displayapp/DummyLittleVgl.h"
|
||||
#else
|
||||
#include "components/settings/Settings.h"
|
||||
#include "displayapp/DisplayApp.h"
|
||||
#include "displayapp/LittleVgl.h"
|
||||
#include "displayapp/LittleVgl.h"
|
||||
#endif
|
||||
|
||||
#include "drivers/Watchdog.h"
|
||||
@@ -59,7 +61,8 @@ namespace Pinetime {
|
||||
Controllers::Settings& settingsController,
|
||||
Pinetime::Controllers::HeartRateController& heartRateController,
|
||||
Pinetime::Applications::DisplayApp& displayApp,
|
||||
Pinetime::Applications::HeartRateTask& heartRateApp);
|
||||
Pinetime::Applications::HeartRateTask& heartRateApp,
|
||||
Pinetime::Controllers::FS& fs);
|
||||
|
||||
void Start();
|
||||
void PushMessage(Messages msg);
|
||||
@@ -68,6 +71,7 @@ namespace Pinetime {
|
||||
void OnTouchEvent();
|
||||
|
||||
void OnIdle();
|
||||
void OnDim();
|
||||
|
||||
Pinetime::Controllers::NimbleController& nimble() {
|
||||
return nimbleController;
|
||||
@@ -96,6 +100,7 @@ namespace Pinetime {
|
||||
std::atomic<bool> isSleeping {false};
|
||||
std::atomic<bool> isGoingToSleep {false};
|
||||
std::atomic<bool> isWakingUp {false};
|
||||
std::atomic<bool> isDimmed {false};
|
||||
Pinetime::Drivers::Watchdog& watchdog;
|
||||
Pinetime::Controllers::NotificationManager& notificationManager;
|
||||
Pinetime::Controllers::MotorController& motorController;
|
||||
@@ -103,13 +108,12 @@ namespace Pinetime {
|
||||
Pinetime::Drivers::Bma421& motionSensor;
|
||||
Pinetime::Controllers::Settings& settingsController;
|
||||
Pinetime::Controllers::HeartRateController& heartRateController;
|
||||
Pinetime::Controllers::NimbleController nimbleController;
|
||||
Controllers::BrightnessController brightnessController;
|
||||
Pinetime::Controllers::MotionController& motionController;
|
||||
|
||||
Pinetime::Applications::DisplayApp& displayApp;
|
||||
Pinetime::Applications::HeartRateTask& heartRateApp;
|
||||
|
||||
Pinetime::Controllers::FS& fs;
|
||||
Pinetime::Controllers::NimbleController nimbleController;
|
||||
|
||||
static constexpr uint8_t pinSpiSck = 2;
|
||||
static constexpr uint8_t pinSpiMosi = 3;
|
||||
@@ -122,15 +126,18 @@ namespace Pinetime {
|
||||
|
||||
static void Process(void* instance);
|
||||
void Work();
|
||||
void ReloadIdleTimer() const;
|
||||
void ReloadIdleTimer();
|
||||
bool isBleDiscoveryTimerRunning = false;
|
||||
uint8_t bleDiscoveryTimer = 0;
|
||||
TimerHandle_t dimTimer;
|
||||
TimerHandle_t idleTimer;
|
||||
bool doNotGoToSleep = false;
|
||||
|
||||
void GoToRunning();
|
||||
void UpdateMotion();
|
||||
bool stepCounterMustBeReset = false;
|
||||
static constexpr TickType_t batteryNotificationPeriod = 1000 * 60 * 10; // 1 tick ~= 1ms. 1ms * 60 * 10 = 10 minutes
|
||||
TickType_t batteryNotificationTick = 0;
|
||||
|
||||
#if configUSE_TRACE_FACILITY == 1
|
||||
SystemMonitor<FreeRtosMonitor> monitor;
|
||||
|
Reference in New Issue
Block a user