Merge branch 'develop' into update_touch_driver

This commit is contained in:
Riku Isokoski 2021-10-05 12:45:03 +03:00
commit f61e88b842
28 changed files with 110 additions and 107 deletions

View file

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.10)
project(pinetime VERSION 1.4.0 LANGUAGES C CXX ASM)
project(pinetime VERSION 1.6.0 LANGUAGES C CXX ASM)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 14)

View file

@ -67,7 +67,7 @@ As of now, here is the list of achievements of this project:
* **[Experimental]** [WebBLEWatch](https://hubmartin.github.io/WebBLEWatch/) Synchronize time directly from your web browser. [video](https://youtu.be/IakiuhVDdrY)
* **[Experimental]** [Infini-iOS](https://github.com/xan-m/Infini-iOS) (on iOS)
- OTA (Over-the-air) update via BLE
- [Bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader) based on [MCUBoot](https://juullabs-oss.github.io/mcuboot/)
- [Bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader) based on [MCUBoot](https://www.mcuboot.com)
## Documentation

View file

@ -22,14 +22,14 @@ The Pinetime is a cool open source project that deserves to be known. Talk about
## TL;DR
- Create a branch from develop;
- Work on a single subject in this branch. Create multiple branches/pulls-requests if you want to work on multiple subjects (bugs, features,...);
- Test your modifications on the actual hardware;
- Check the code formatting against our coding conventions and [clang-format](../.clang-format) and [clang-tidy](../.clang-tidy);
- Clean your code and remove files that are not needed;
- Write documentation related to your new feature if applicable;
- Create a pull request and write a great description about it : what does your PR do, why, how,... Add pictures and video if possible;
- Wait for someone to review your PR and take part in the review process;
- Create a branch from develop
- Work on a single subject in this branch. Create multiple branches/pulls-requests if you want to work on multiple subjects (bugs, features,...)
- Test your modifications on the actual hardware
- Check the code formatting against our coding conventions and [clang-format](../.clang-format) and [clang-tidy](../.clang-tidy)
- Clean your code and remove files that are not needed
- Write documentation related to your new feature if applicable
- Create a pull request and write a great description about it: what does your PR do, why, how,... Add pictures and video if possible
- Wait for someone to review your PR and take part in the review process
- Your PR will eventually be merged :)
Your contributions are more than welcome!

View file

@ -17,6 +17,12 @@ void Battery::Update() {
isCharging = !nrf_gpio_pin_read(PinMap::Charging);
isPowerPresent = !nrf_gpio_pin_read(PinMap::PowerPresent);
if (isPowerPresent && !isCharging) {
isFull = true;
} else if (!isPowerPresent) {
isFull = false;
}
if (isReading) {
return;
}
@ -63,12 +69,12 @@ void Battery::SaadcEventHandler(nrfx_saadc_evt_t const* p_event) {
// p_event->data.done.p_buffer[0] = (adc_voltage / reference_voltage) * 1024
voltage = p_event->data.done.p_buffer[0] * (8 * 600) / 1024;
if (voltage > battery_max) {
if (isFull) {
percentRemaining = 100;
} else if (voltage < battery_min) {
percentRemaining = 0;
} else {
percentRemaining = (voltage - battery_min) * 100 / (battery_max - battery_min);
percentRemaining = std::min((voltage - battery_min) * 100 / (battery_max - battery_min), isCharging ? 99 : 100);
}
nrfx_saadc_uninit();

View file

@ -22,7 +22,9 @@ namespace Pinetime {
}
bool IsCharging() const {
return isCharging;
// isCharging will go up and down when fully charged
// isFull makes sure this returns false while fully charged.
return isCharging && !isFull;
}
bool IsPowerPresent() const {
@ -37,6 +39,7 @@ namespace Pinetime {
uint16_t voltage = 0;
uint8_t percentRemaining = 0;
bool isFull = false;
bool isCharging = false;
bool isPowerPresent = false;

View file

@ -43,7 +43,7 @@ int BatteryInformationService::OnBatteryServiceRequested(uint16_t connectionHand
ble_gatt_access_ctxt* context) {
if (attributeHandle == batteryLevelHandle) {
NRF_LOG_INFO("BATTERY : handle = %d", batteryLevelHandle);
static uint8_t batteryValue = batteryController.PercentRemaining();
uint8_t batteryValue = batteryController.PercentRemaining();
int res = os_mbuf_append(context->om, &batteryValue, 1);
return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}

View file

@ -79,14 +79,6 @@ bool NotificationManager::AreNewNotificationsAvailable() {
return newNotification;
}
bool NotificationManager::IsVibrationEnabled() {
return vibrationEnabled;
}
void NotificationManager::ToggleVibrations() {
vibrationEnabled = !vibrationEnabled;
}
bool NotificationManager::ClearNewNotificationFlag() {
return newNotification.exchange(false);
}

View file

@ -44,8 +44,6 @@ namespace Pinetime {
Notification GetPrevious(Notification::Id id);
bool ClearNewNotificationFlag();
bool AreNewNotificationsAvailable();
bool IsVibrationEnabled();
void ToggleVibrations();
static constexpr size_t MaximumMessageSize() {
return MessageSize;
@ -60,7 +58,6 @@ namespace Pinetime {
uint8_t writeIndex = 0;
bool empty = true;
std::atomic<bool> newNotification {false};
bool vibrationEnabled = true;
};
}
}

View file

@ -7,6 +7,7 @@ using namespace Pinetime::Controllers;
void DateTime::SetCurrentTime(std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> t) {
this->currentDateTime = t;
UpdateTime(previousSystickCounter); // Update internal state without updating the time
}
void DateTime::SetTime(

View file

@ -53,7 +53,7 @@ namespace Pinetime {
*
*/
static constexpr size_t startAddress = 0x0B4000;
static constexpr size_t size = 0x3C0000;
static constexpr size_t size = 0x34C000;
static constexpr size_t blockSize = 4096;
bool resourcesValid = false;

View file

@ -9,9 +9,6 @@ APP_TIMER_DEF(longVibTimer);
using namespace Pinetime::Controllers;
MotorController::MotorController(Controllers::Settings& settingsController) : settingsController {settingsController} {
}
void MotorController::Init() {
nrf_gpio_cfg_output(PinMap::Motor);
nrf_gpio_pin_set(PinMap::Motor);
@ -27,18 +24,11 @@ void MotorController::Ring(void* p_context) {
}
void MotorController::RunForDuration(uint8_t motorDuration) {
if (settingsController.GetVibrationStatus() == Controllers::Settings::Vibration::OFF) {
return;
}
nrf_gpio_pin_clear(PinMap::Motor);
app_timer_start(shortVibTimer, APP_TIMER_TICKS(motorDuration), nullptr);
}
void MotorController::StartRinging() {
if (settingsController.GetVibrationStatus() == Controllers::Settings::Vibration::OFF) {
return;
}
Ring(this);
app_timer_start(longVibTimer, APP_TIMER_TICKS(1000), this);
}

View file

@ -1,14 +1,14 @@
#pragma once
#include <cstdint>
#include "components/settings/Settings.h"
namespace Pinetime {
namespace Controllers {
class MotorController {
public:
MotorController(Controllers::Settings& settingsController);
MotorController() = default;
void Init();
void RunForDuration(uint8_t motorDuration);
void StartRinging();
@ -16,7 +16,6 @@ namespace Pinetime {
private:
static void Ring(void* p_context);
Controllers::Settings& settingsController;
static void StopMotor(void* p_context);
};
}

View file

@ -11,7 +11,7 @@ namespace Pinetime {
class Settings {
public:
enum class ClockType : uint8_t { H24, H12 };
enum class Vibration : uint8_t { ON, OFF };
enum class Notification : uint8_t { ON, OFF };
enum class WakeUpMode : uint8_t {
SingleTap = 0,
DoubleTap = 1,
@ -93,14 +93,14 @@ namespace Pinetime {
return settings.clockType;
};
void SetVibrationStatus(Vibration status) {
if (status != settings.vibrationStatus) {
void SetNotificationStatus(Notification status) {
if (status != settings.notificationStatus) {
settingsChanged = true;
}
settings.vibrationStatus = status;
settings.notificationStatus = status;
};
Vibration GetVibrationStatus() const {
return settings.vibrationStatus;
Notification GetNotificationStatus() const {
return settings.notificationStatus;
};
void SetScreenTimeOut(uint32_t timeout) {
@ -170,7 +170,7 @@ namespace Pinetime {
uint32_t screenTimeOut = 15000;
ClockType clockType = ClockType::H24;
Vibration vibrationStatus = Vibration::ON;
Notification notificationStatus = Notification::ON;
uint8_t clockFace = 0;

View file

@ -147,19 +147,15 @@ void DisplayApp::InitHw() {
void DisplayApp::Refresh() {
TickType_t queueTimeout;
TickType_t delta;
switch (state) {
case States::Idle:
IdleState();
queueTimeout = portMAX_DELAY;
break;
case States::Running:
RunningState();
delta = xTaskGetTickCount() - lastWakeTime;
if (delta > LV_DISP_DEF_REFR_PERIOD) {
delta = LV_DISP_DEF_REFR_PERIOD;
if (!currentScreen->IsRunning()) {
LoadApp(returnToApp, returnDirection);
}
queueTimeout = LV_DISP_DEF_REFR_PERIOD - delta;
queueTimeout = lv_task_handler();
break;
default:
queueTimeout = portMAX_DELAY;
@ -167,9 +163,7 @@ void DisplayApp::Refresh() {
}
Messages msg;
bool messageReceived = xQueueReceive(msgQueue, &msg, queueTimeout);
lastWakeTime = xTaskGetTickCount();
if (messageReceived) {
if (xQueueReceive(msgQueue, &msg, queueTimeout)) {
switch (msg) {
case Messages::DimScreen:
// Backup brightness is the brightness to return to after dimming or sleeping
@ -285,13 +279,6 @@ void DisplayApp::Refresh() {
}
}
void DisplayApp::RunningState() {
if (!currentScreen->IsRunning()) {
LoadApp(returnToApp, returnDirection);
}
lv_task_handler();
}
void DisplayApp::StartApp(Apps app, DisplayApp::FullRefreshDirections direction) {
nextApp = app;
nextDirection = direction;
@ -441,9 +428,6 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
currentApp = app;
}
void DisplayApp::IdleState() {
}
void DisplayApp::PushMessage(Messages msg) {
if (in_isr()) {
BaseType_t xHigherPriorityTaskWoken;

View file

@ -108,8 +108,6 @@ namespace Pinetime {
TouchEvents returnTouchEvent = TouchEvents::None;
TouchEvents GetGesture();
void RunningState();
void IdleState();
static void Process(void* instance);
void InitHw();
void Refresh();
@ -119,8 +117,6 @@ namespace Pinetime {
Apps nextApp = Apps::None;
DisplayApp::FullRefreshDirections nextDirection;
TickType_t lastWakeTime;
System::BootErrors bootError;
};
}

View file

@ -58,7 +58,7 @@ void BatteryInfo::Refresh() {
batteryPercent = batteryController.PercentRemaining();
batteryVoltage = batteryController.Voltage();
if (batteryController.IsCharging() and batteryPercent < 100) {
if (batteryController.IsCharging()) {
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) {

View file

@ -78,7 +78,7 @@ Metronome::~Metronome() {
void Metronome::Refresh() {
if (metronomeStarted) {
if (xTaskGetTickCount() - startTime > 60 * configTICK_RATE_HZ / bpm) {
if (xTaskGetTickCount() - startTime > 60u * configTICK_RATE_HZ / static_cast<uint16_t>(bpm)) {
startTime += 60 * configTICK_RATE_HZ / bpm;
counter--;
if (counter == 0) {

View file

@ -129,10 +129,6 @@ bool Notifications::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
alertNotificationService);
}
return true;
case Pinetime::Applications::TouchEvents::LongTap: {
// notificationManager.ToggleVibrations();
return true;
}
default:
return false;
}

View file

@ -100,10 +100,7 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app,
lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_label_set_text(batteryIcon, Symbols::batteryFull);
lv_obj_align(batteryIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 2);
batteryPlug = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(batteryPlug, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_obj_align(batteryPlug, sidebar, LV_ALIGN_IN_TOP_MID, 0, 2);
lv_obj_set_auto_realign(batteryIcon, true);
bleIcon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(bleIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
@ -205,18 +202,24 @@ PineTimeStyle::~PineTimeStyle() {
lv_obj_clean(lv_scr_act());
}
void PineTimeStyle::SetBatteryIcon() {
auto batteryPercent = batteryPercentRemaining.Get();
lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent));
}
void PineTimeStyle::Refresh() {
isCharging = batteryController.IsCharging();
if (isCharging.IsUpdated()) {
if (isCharging.Get()) {
lv_label_set_text(batteryIcon, Symbols::plug);
} else {
SetBatteryIcon();
}
}
if (!isCharging.Get()) {
batteryPercentRemaining = batteryController.PercentRemaining();
if (batteryPercentRemaining.IsUpdated()) {
auto batteryPercent = batteryPercentRemaining.Get();
if (batteryController.IsCharging()) {
auto isCharging = batteryController.IsCharging() || batteryController.IsPowerPresent();
lv_label_set_text(batteryPlug, BatteryIcon::GetPlugIcon(isCharging));
lv_obj_realign(batteryPlug);
lv_label_set_text(batteryIcon, "");
} else {
lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent));
lv_label_set_text(batteryPlug, "");
SetBatteryIcon();
}
}

View file

@ -41,6 +41,7 @@ namespace Pinetime {
uint8_t currentDay = 0;
DirtyValue<uint8_t> batteryPercentRemaining {};
DirtyValue<bool> isCharging {};
DirtyValue<bool> bleState {};
DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime {};
DirtyValue<bool> motionSensorOk {};
@ -58,7 +59,6 @@ namespace Pinetime {
lv_obj_t* backgroundLabel;
lv_obj_t* batteryIcon;
lv_obj_t* bleIcon;
lv_obj_t* batteryPlug;
lv_obj_t* calendarOuter;
lv_obj_t* calendarInner;
lv_obj_t* calendarBar1;
@ -76,6 +76,8 @@ namespace Pinetime {
Controllers::Settings& settingsController;
Controllers::MotionController& motionController;
void SetBatteryIcon();
lv_task_t* taskRefresh;
};
}

View file

@ -68,6 +68,7 @@ WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app,
batteryIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(batteryIcon, Symbols::batteryHalf);
lv_obj_align(batteryIcon, NULL, LV_ALIGN_IN_TOP_RIGHT, 0, 0);
lv_obj_set_auto_realign(batteryIcon, true);
notificationIcon = lv_label_create(lv_scr_act(), NULL);
lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00));
@ -176,11 +177,31 @@ void WatchFaceAnalog::UpdateClock() {
}
}
void WatchFaceAnalog::SetBatteryIcon() {
auto batteryPercent = batteryPercentRemaining.Get();
if (batteryPercent == 100) {
lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
} else {
lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
}
lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent));
}
void WatchFaceAnalog::Refresh() {
isCharging = batteryController.IsCharging();
if (isCharging.IsUpdated()) {
if (isCharging.Get()) {
lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED);
lv_label_set_text(batteryIcon, Symbols::plug);
} else {
SetBatteryIcon();
}
}
if (!isCharging.Get()) {
batteryPercentRemaining = batteryController.PercentRemaining();
if (batteryPercentRemaining.IsUpdated()) {
auto batteryPercent = batteryPercentRemaining.Get();
lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent));
SetBatteryIcon();
}
}
notificationState = notificationManager.AreNewNotificationsAvailable();

View file

@ -49,6 +49,7 @@ namespace Pinetime {
uint8_t currentDay = 0;
DirtyValue<uint8_t> batteryPercentRemaining {0};
DirtyValue<bool> isCharging {};
DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime;
DirtyValue<bool> notificationState {false};
@ -81,6 +82,7 @@ namespace Pinetime {
Controllers::Settings& settingsController;
void UpdateClock();
void SetBatteryIcon();
lv_task_t* taskRefresh;
};

View file

@ -102,12 +102,20 @@ WatchFaceDigital::~WatchFaceDigital() {
}
void WatchFaceDigital::Refresh() {
powerPresent = batteryController.IsPowerPresent();
if (powerPresent.IsUpdated()) {
lv_label_set_text(batteryPlug, BatteryIcon::GetPlugIcon(powerPresent.Get()));
}
batteryPercentRemaining = batteryController.PercentRemaining();
if (batteryPercentRemaining.IsUpdated()) {
auto batteryPercent = batteryPercentRemaining.Get();
if (batteryPercent == 100) {
lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
} else {
lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
}
lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent));
auto isCharging = batteryController.IsCharging() or batteryController.IsPowerPresent();
lv_label_set_text(batteryPlug, BatteryIcon::GetPlugIcon(isCharging));
}
bleState = bleController.IsConnected();

View file

@ -44,6 +44,7 @@ namespace Pinetime {
uint8_t currentDay = 0;
DirtyValue<uint8_t> batteryPercentRemaining {};
DirtyValue<bool> powerPresent {};
DirtyValue<bool> bleState {};
DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime {};
DirtyValue<bool> motionSensorOk {};

View file

@ -88,7 +88,7 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
btn3_lvl = lv_label_create(btn3, nullptr);
lv_obj_set_style_local_text_font(btn3_lvl, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &lv_font_sys_48);
if (settingsController.GetVibrationStatus() == Controllers::Settings::Vibration::ON) {
if (settingsController.GetNotificationStatus() == Controllers::Settings::Notification::ON) {
lv_obj_add_state(btn3, LV_STATE_CHECKED);
lv_label_set_text_static(btn3_lvl, Symbols::notificationsOn);
} else {
@ -142,11 +142,11 @@ void QuickSettings::OnButtonEvent(lv_obj_t* object, lv_event_t event) {
} else if (object == btn3 && event == LV_EVENT_VALUE_CHANGED) {
if (lv_obj_get_state(btn3, LV_BTN_PART_MAIN) & LV_STATE_CHECKED) {
settingsController.SetVibrationStatus(Controllers::Settings::Vibration::ON);
settingsController.SetNotificationStatus(Controllers::Settings::Notification::ON);
motorController.RunForDuration(35);
lv_label_set_text_static(btn3_lvl, Symbols::notificationsOn);
} else {
settingsController.SetVibrationStatus(Controllers::Settings::Vibration::OFF);
settingsController.SetNotificationStatus(Controllers::Settings::Notification::OFF);
lv_label_set_text_static(btn3_lvl, Symbols::notificationsOff);
}

View file

@ -51,7 +51,7 @@ static inline void ble_ll_rfmgmt_reset(void) { }
static inline void ble_ll_rfmgmt_scan_changed(bool e, uint32_t n) { }
static inline void ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *f) { }
static inline void ble_ll_rfmgmt_release(void) { }
static inline uint32_t ble_ll_rfmgmt_enable_now(void) { return 0; }
static inline uint32_t ble_ll_rfmgmt_enable_now(void) { return os_cputime_get32(); }
static inline bool ble_ll_rfmgmt_is_enabled(void) { return true; }
#endif

View file

@ -113,7 +113,7 @@ Pinetime::Controllers::TouchHandler touchHandler(touchPanel, lvgl);
Pinetime::Controllers::FS fs {spiNorFlash};
Pinetime::Controllers::Settings settingsController {fs};
Pinetime::Controllers::MotorController motorController {settingsController};
Pinetime::Controllers::MotorController motorController {};
Pinetime::Applications::DisplayApp displayApp(lcd,
lvgl,

View file

@ -274,10 +274,12 @@ void SystemTask::Work() {
displayApp.PushMessage(Pinetime::Applications::Display::Messages::UpdateDateTime);
break;
case Messages::OnNewNotification:
if (settingsController.GetNotificationStatus() == Pinetime::Controllers::Settings::Notification::ON) {
if (isSleeping && !isWakingUp) {
GoToRunning();
}
displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification);
}
break;
case Messages::OnTimerDone:
if (isSleeping && !isWakingUp) {