Merge branch 'develop' into new_touch_handler

This commit is contained in:
Riku Isokoski 2021-08-10 20:58:42 +03:00
commit f1346f098e
15 changed files with 106 additions and 226 deletions

View file

@ -23,7 +23,6 @@ void Battery::Update() {
return; return;
} }
// Non blocking read // Non blocking read
samples = 0;
isReading = true; isReading = true;
SaadcInit(); SaadcInit();
@ -40,9 +39,9 @@ void Battery::SaadcInit() {
nrf_saadc_channel_config_t adcChannelConfig = {.resistor_p = NRF_SAADC_RESISTOR_DISABLED, nrf_saadc_channel_config_t adcChannelConfig = {.resistor_p = NRF_SAADC_RESISTOR_DISABLED,
.resistor_n = NRF_SAADC_RESISTOR_DISABLED, .resistor_n = NRF_SAADC_RESISTOR_DISABLED,
.gain = NRF_SAADC_GAIN1_5, .gain = NRF_SAADC_GAIN1_4,
.reference = NRF_SAADC_REFERENCE_INTERNAL, .reference = NRF_SAADC_REFERENCE_INTERNAL,
.acq_time = NRF_SAADC_ACQTIME_3US, .acq_time = NRF_SAADC_ACQTIME_40US,
.mode = NRF_SAADC_MODE_SINGLE_ENDED, .mode = NRF_SAADC_MODE_SINGLE_ENDED,
.burst = NRF_SAADC_BURST_ENABLED, .burst = NRF_SAADC_BURST_ENABLED,
.pin_p = batteryVoltageAdcInput, .pin_p = batteryVoltageAdcInput,
@ -60,22 +59,21 @@ void Battery::SaadcEventHandler(nrfx_saadc_evt_t const* p_event) {
APP_ERROR_CHECK(nrfx_saadc_buffer_convert(&saadc_value, 1)); APP_ERROR_CHECK(nrfx_saadc_buffer_convert(&saadc_value, 1));
// A hardware voltage divider divides the battery voltage by 2 // A hardware voltage divider divides the battery voltage by 2
// ADC gain is 1/5 // ADC gain is 1/4
// thus adc_voltage = battery_voltage / 2 * gain = battery_voltage / 10 // thus adc_voltage = battery_voltage / 2 * gain = battery_voltage / 8
// reference_voltage is 0.6V // reference_voltage is 600mV
// p_event->data.done.p_buffer[0] = (adc_voltage / reference_voltage) * 1024 // p_event->data.done.p_buffer[0] = (adc_voltage / reference_voltage) * 1024
voltage = p_event->data.done.p_buffer[0] * 6000 / 1024; voltage = p_event->data.done.p_buffer[0] * (8 * 600) / 1024;
percentRemaining = (voltage - battery_min) * 100 / (battery_max - battery_min);
percentRemaining = std::max(percentRemaining, 0); if (voltage > battery_max) {
percentRemaining = std::min(percentRemaining, 100); percentRemaining = 100;
percentRemainingBuffer.Insert(percentRemaining); } else if (voltage < battery_min) {
percentRemaining = 0;
} else {
percentRemaining = (voltage - battery_min) * 100 / (battery_max - battery_min);
}
samples++;
if (samples > percentRemainingSamples) {
nrfx_saadc_uninit(); nrfx_saadc_uninit();
isReading = false; isReading = false;
} else {
nrfx_saadc_sample();
}
} }
} }

View file

@ -7,38 +7,6 @@
namespace Pinetime { namespace Pinetime {
namespace Controllers { namespace Controllers {
/** A simple circular buffer that can be used to average
out the sensor values. The total capacity of the CircBuffer
is given as the template parameter N.
*/
template <int N> class CircBuffer {
public:
CircBuffer() : arr {}, sz {}, cap {N}, head {} {
}
/**
insert member function overwrites the next data to the current
HEAD and moves the HEAD to the newly inserted value.
*/
void Insert(const uint8_t num) {
head %= cap;
arr[head++] = num;
if (sz != cap) {
sz++;
}
}
uint8_t GetAverage() const {
int sum = std::accumulate(arr.begin(), arr.end(), 0);
return static_cast<uint8_t>(sum / sz);
}
private:
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*/
};
class Battery { class Battery {
public: public:
Battery(); Battery();
@ -47,10 +15,7 @@ namespace Pinetime {
void Update(); void Update();
uint8_t PercentRemaining() const { uint8_t PercentRemaining() const {
auto avg = percentRemainingBuffer.GetAverage(); return percentRemaining;
avg = std::min(avg, static_cast<uint8_t>(100));
avg = std::max(avg, static_cast<uint8_t>(0));
return avg;
} }
uint16_t Voltage() const { uint16_t Voltage() const {
@ -69,14 +34,11 @@ namespace Pinetime {
static Battery* instance; static Battery* instance;
nrf_saadc_value_t saadc_value; nrf_saadc_value_t saadc_value;
static constexpr uint8_t percentRemainingSamples = 5;
CircBuffer<percentRemainingSamples> percentRemainingBuffer {};
static constexpr uint32_t chargingPin = 12; static constexpr uint32_t chargingPin = 12;
static constexpr uint32_t powerPresentPin = 19; static constexpr uint32_t powerPresentPin = 19;
static constexpr nrf_saadc_input_t batteryVoltageAdcInput = NRF_SAADC_INPUT_AIN7; static constexpr nrf_saadc_input_t batteryVoltageAdcInput = NRF_SAADC_INPUT_AIN7;
uint16_t voltage = 0; uint16_t voltage = 0;
int percentRemaining = -1; uint8_t percentRemaining = 0;
bool isCharging = false; bool isCharging = false;
bool isPowerPresent = false; bool isPowerPresent = false;
@ -87,7 +49,6 @@ namespace Pinetime {
static void AdcCallbackStatic(nrfx_saadc_evt_t const* event); static void AdcCallbackStatic(nrfx_saadc_evt_t const* event);
bool isReading = false; bool isReading = false;
uint8_t samples = 0;
}; };
} }
} }

View file

@ -55,9 +55,9 @@ void DateTime::UpdateTime(uint32_t systickCounter) {
auto time = date::make_time(currentDateTime - dp); auto time = date::make_time(currentDateTime - dp);
auto yearMonthDay = date::year_month_day(dp); auto yearMonthDay = date::year_month_day(dp);
year = (int) yearMonthDay.year(); year = static_cast<int>(yearMonthDay.year());
month = static_cast<Months>((unsigned) yearMonthDay.month()); month = static_cast<Months>(static_cast<unsigned>(yearMonthDay.month()));
day = (unsigned) yearMonthDay.day(); day = static_cast<unsigned>(yearMonthDay.day());
dayOfWeek = static_cast<Days>(date::weekday(yearMonthDay).iso_encoding()); dayOfWeek = static_cast<Days>(date::weekday(yearMonthDay).iso_encoding());
hour = time.hours().count(); hour = time.hours().count();
@ -75,31 +75,31 @@ void DateTime::UpdateTime(uint32_t systickCounter) {
} }
const char* DateTime::MonthShortToString() { const char* DateTime::MonthShortToString() {
return DateTime::MonthsString[(uint8_t) month]; return DateTime::MonthsString[static_cast<uint8_t>(month)];
} }
const char* DateTime::MonthShortToStringLow() { const char* DateTime::MonthShortToStringLow() {
return DateTime::MonthsStringLow[(uint8_t) month]; return DateTime::MonthsStringLow[static_cast<uint8_t>(month)];
} }
const char* DateTime::MonthsToStringLow() { const char* DateTime::MonthsToStringLow() {
return DateTime::MonthsLow[(uint8_t) month]; return DateTime::MonthsLow[static_cast<uint8_t>(month)];
} }
const char* DateTime::DayOfWeekToString() { const char* DateTime::DayOfWeekToString() {
return DateTime::DaysString[(uint8_t) dayOfWeek]; return DateTime::DaysString[static_cast<uint8_t>(dayOfWeek)];
} }
const char* DateTime::DayOfWeekShortToString() { const char* DateTime::DayOfWeekShortToString() {
return DateTime::DaysStringShort[(uint8_t) dayOfWeek]; return DateTime::DaysStringShort[static_cast<uint8_t>(dayOfWeek)];
} }
const char* DateTime::DayOfWeekToStringLow() { const char* DateTime::DayOfWeekToStringLow() {
return DateTime::DaysStringLow[(uint8_t) dayOfWeek]; return DateTime::DaysStringLow[static_cast<uint8_t>(dayOfWeek)];
} }
const char* DateTime::DayOfWeekShortToStringLow() { const char* DateTime::DayOfWeekShortToStringLow() {
return DateTime::DaysStringShortLow[(uint8_t) dayOfWeek]; return DateTime::DaysStringShortLow[static_cast<uint8_t>(dayOfWeek)];
} }
void DateTime::Register(Pinetime::System::SystemTask* systemTask) { void DateTime::Register(Pinetime::System::SystemTask* systemTask) {

View file

@ -5,13 +5,13 @@
using namespace Pinetime::Applications::Screens; using namespace Pinetime::Applications::Screens;
const char* BatteryIcon::GetBatteryIcon(uint8_t batteryPercent) { const char* BatteryIcon::GetBatteryIcon(uint8_t batteryPercent) {
if (batteryPercent > 90) if (batteryPercent > 87)
return Symbols::batteryFull; return Symbols::batteryFull;
if (batteryPercent > 75) if (batteryPercent > 62)
return Symbols::batteryThreeQuarter; return Symbols::batteryThreeQuarter;
if (batteryPercent > 50) if (batteryPercent > 37)
return Symbols::batteryHalf; return Symbols::batteryHalf;
if (batteryPercent > 25) if (batteryPercent > 12)
return Symbols::batteryOneQuarter; return Symbols::batteryOneQuarter;
return Symbols::batteryEmpty; return Symbols::batteryEmpty;
} }

View file

@ -2,11 +2,6 @@
#include <date/date.h> #include <date/date.h>
#include <lvgl/lvgl.h> #include <lvgl/lvgl.h>
#include <cstdio>
#include "BatteryIcon.h"
#include "BleIcon.h"
#include "NotificationIcon.h"
#include "Symbols.h"
#include "components/battery/BatteryController.h" #include "components/battery/BatteryController.h"
#include "components/motion/MotionController.h" #include "components/motion/MotionController.h"
#include "components/ble/BleController.h" #include "components/ble/BleController.h"
@ -89,16 +84,3 @@ std::unique_ptr<Screen> Clock::PineTimeStyleScreen() {
settingsController, settingsController,
motionController); motionController);
} }
/*
// Examples for more watch faces
std::unique_ptr<Screen> Clock::WatchFaceMinimalScreen() {
return std::make_unique<Screens::WatchFaceMinimal>(app, dateTimeController, batteryController, bleController, notificatioManager,
settingsController);
}
std::unique_ptr<Screen> Clock::WatchFaceCustomScreen() {
return std::make_unique<Screens::WatchFaceCustom>(app, dateTimeController, batteryController, bleController, notificatioManager,
settingsController);
}
*/

View file

@ -9,9 +9,6 @@
#include "components/datetime/DateTimeController.h" #include "components/datetime/DateTimeController.h"
namespace Pinetime { namespace Pinetime {
namespace Drivers {
class BMA421;
}
namespace Controllers { namespace Controllers {
class Settings; class Settings;
class Battery; class Battery;
@ -51,10 +48,6 @@ namespace Pinetime {
std::unique_ptr<Screen> WatchFaceDigitalScreen(); std::unique_ptr<Screen> WatchFaceDigitalScreen();
std::unique_ptr<Screen> WatchFaceAnalogScreen(); std::unique_ptr<Screen> WatchFaceAnalogScreen();
std::unique_ptr<Screen> PineTimeStyleScreen(); std::unique_ptr<Screen> PineTimeStyleScreen();
// Examples for more watch faces
// std::unique_ptr<Screen> WatchFaceMinimalScreen();
// std::unique_ptr<Screen> WatchFaceCustomScreen();
}; };
} }
} }

View file

@ -51,7 +51,6 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app,
notificatioManager {notificatioManager}, notificatioManager {notificatioManager},
settingsController {settingsController}, settingsController {settingsController},
motionController {motionController} { motionController {motionController} {
/* This sets the watchface number to return to after leaving the menu */ /* This sets the watchface number to return to after leaving the menu */
settingsController.SetClockFace(2); settingsController.SetClockFace(2);
@ -62,7 +61,6 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app,
displayedChar[4] = 0; displayedChar[4] = 0;
/* Create a 200px wide background rectangle */ /* Create a 200px wide background rectangle */
timebar = lv_obj_create(lv_scr_act(), nullptr); timebar = lv_obj_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); lv_obj_set_style_local_bg_color(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_obj_set_style_local_radius(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); lv_obj_set_style_local_radius(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
@ -70,7 +68,6 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app,
lv_obj_align(timebar, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 5, 0); lv_obj_align(timebar, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 5, 0);
/* Display the time */ /* Display the time */
timeDD1 = lv_label_create(lv_scr_act(), nullptr); timeDD1 = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_font(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &open_sans_light); lv_obj_set_style_local_text_font(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &open_sans_light);
lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080)); lv_obj_set_style_local_text_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080));
@ -90,7 +87,6 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app,
lv_obj_align(timeAMPM, timebar, LV_ALIGN_IN_BOTTOM_LEFT, 2, -20); lv_obj_align(timeAMPM, timebar, LV_ALIGN_IN_BOTTOM_LEFT, 2, -20);
/* Create a 40px wide bar down the right side of the screen */ /* Create a 40px wide bar down the right side of the screen */
sidebar = lv_obj_create(lv_scr_act(), nullptr); sidebar = lv_obj_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080)); lv_obj_set_style_local_bg_color(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080));
lv_obj_set_style_local_radius(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); lv_obj_set_style_local_radius(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
@ -98,7 +94,6 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app,
lv_obj_align(sidebar, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0); lv_obj_align(sidebar, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0);
/* Display icons */ /* Display icons */
batteryIcon = lv_label_create(lv_scr_act(), nullptr); batteryIcon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(batteryIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); 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_label_set_text(batteryIcon, Symbols::batteryFull);
@ -117,7 +112,6 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app,
lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 40); lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 40);
/* Calendar icon */ /* Calendar icon */
calendarOuter = lv_obj_create(lv_scr_act(), nullptr); calendarOuter = lv_obj_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_bg_color(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); lv_obj_set_style_local_bg_color(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_obj_set_style_local_radius(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0); lv_obj_set_style_local_radius(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
@ -155,7 +149,6 @@ PineTimeStyle::PineTimeStyle(DisplayApp* app,
lv_obj_align(calendarCrossBar2, calendarBar2, LV_ALIGN_IN_BOTTOM_MID, 0, 0); lv_obj_align(calendarCrossBar2, calendarBar2, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
/* Display date */ /* Display date */
dateDayOfWeek = lv_label_create(lv_scr_act(), nullptr); dateDayOfWeek = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(dateDayOfWeek, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000)); lv_obj_set_style_local_text_color(dateDayOfWeek, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
lv_label_set_text(dateDayOfWeek, "THU"); lv_label_set_text(dateDayOfWeek, "THU");
@ -223,26 +216,17 @@ bool PineTimeStyle::Refresh() {
bleState = bleController.IsConnected(); bleState = bleController.IsConnected();
if (bleState.IsUpdated()) { if (bleState.IsUpdated()) {
if (bleState.Get() == true) { lv_label_set_text(bleIcon, BleIcon::GetIcon(bleState.Get()));
lv_label_set_text(bleIcon, BleIcon::GetIcon(true));
lv_obj_realign(bleIcon); lv_obj_realign(bleIcon);
} else {
lv_label_set_text(bleIcon, BleIcon::GetIcon(false));
}
} }
notificationState = notificatioManager.AreNewNotificationsAvailable(); notificationState = notificatioManager.AreNewNotificationsAvailable();
if (notificationState.IsUpdated()) { if (notificationState.IsUpdated()) {
if (notificationState.Get() == true) { lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(notificationState.Get()));
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(true));
lv_obj_realign(notificationIcon); lv_obj_realign(notificationIcon);
} else {
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false));
}
} }
currentDateTime = dateTimeController.CurrentDateTime(); currentDateTime = dateTimeController.CurrentDateTime();
if (currentDateTime.IsUpdated()) { if (currentDateTime.IsUpdated()) {
auto newDateTime = currentDateTime.Get(); auto newDateTime = currentDateTime.Get();
@ -250,9 +234,9 @@ bool PineTimeStyle::Refresh() {
auto time = date::make_time(newDateTime - dp); auto time = date::make_time(newDateTime - dp);
auto yearMonthDay = date::year_month_day(dp); auto yearMonthDay = date::year_month_day(dp);
auto year = (int) yearMonthDay.year(); auto year = static_cast<int>(yearMonthDay.year());
auto month = static_cast<Pinetime::Controllers::DateTime::Months>((unsigned) yearMonthDay.month()); auto month = static_cast<Pinetime::Controllers::DateTime::Months>(static_cast<unsigned>(yearMonthDay.month()));
auto day = (unsigned) yearMonthDay.day(); auto day = static_cast<unsigned>(yearMonthDay.day());
auto dayOfWeek = static_cast<Pinetime::Controllers::DateTime::Days>(date::weekday(yearMonthDay).iso_encoding()); auto dayOfWeek = static_cast<Pinetime::Controllers::DateTime::Days>(date::weekday(yearMonthDay).iso_encoding());
int hour = time.hours().count(); int hour = time.hours().count();
@ -263,7 +247,6 @@ bool PineTimeStyle::Refresh() {
char hoursChar[3]; char hoursChar[3];
char ampmChar[5]; char ampmChar[5];
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) { if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) {
sprintf(hoursChar, "%02d", hour); sprintf(hoursChar, "%02d", hour);
} else { } else {
@ -282,41 +265,26 @@ bool PineTimeStyle::Refresh() {
sprintf(hoursChar, "%02d", hour); sprintf(hoursChar, "%02d", hour);
} }
if (hoursChar[0] != displayedChar[0] || hoursChar[1] != displayedChar[1] || minutesChar[0] != displayedChar[2] || if (hoursChar[0] != displayedChar[0] or hoursChar[1] != displayedChar[1] or minutesChar[0] != displayedChar[2] or
minutesChar[1] != displayedChar[3]) { minutesChar[1] != displayedChar[3]) {
displayedChar[0] = hoursChar[0]; displayedChar[0] = hoursChar[0];
displayedChar[1] = hoursChar[1]; displayedChar[1] = hoursChar[1];
displayedChar[2] = minutesChar[0]; displayedChar[2] = minutesChar[0];
displayedChar[3] = minutesChar[1]; displayedChar[3] = minutesChar[1];
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); lv_label_set_text(timeAMPM, ampmChar);
} }
/* Display the time as 2 pairs of digits */ lv_label_set_text_fmt(timeDD1, "%s", hoursChar);
sprintf(hourStr, "%c%c", hoursChar[0], hoursChar[1]); lv_label_set_text_fmt(timeDD2, "%s", minutesChar);
lv_label_set_text(timeDD1, hourStr);
sprintf(minStr, "%c%c", minutesChar[0], minutesChar[1]);
lv_label_set_text(timeDD2, minStr);
} }
if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) { if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) {
char dayOfWeekStr[4]; lv_label_set_text_fmt(dateDayOfWeek, "%s", dateTimeController.DayOfWeekShortToString());
char dayStr[3]; lv_label_set_text_fmt(dateDay, "%d", day);
char monthStr[4];
sprintf(dayOfWeekStr, "%s", dateTimeController.DayOfWeekShortToString());
sprintf(dayStr, "%d", day);
sprintf(monthStr, "%s", dateTimeController.MonthShortToString());
lv_label_set_text(dateDayOfWeek, dayOfWeekStr);
lv_label_set_text(dateDay, dayStr);
lv_obj_realign(dateDay); lv_obj_realign(dateDay);
lv_label_set_text(dateMonth, monthStr); lv_label_set_text_fmt(dateMonth, "%s", dateTimeController.MonthShortToString());
currentYear = year; currentYear = year;
currentMonth = month; currentMonth = month;

View file

@ -32,8 +32,6 @@ namespace Pinetime {
bool Refresh() override; bool Refresh() override;
void OnObjectEvent(lv_obj_t* pObj, lv_event_t i);
private: private:
char displayedChar[5]; char displayedChar[5];
@ -67,9 +65,6 @@ namespace Pinetime {
lv_obj_t* calendarBar2; lv_obj_t* calendarBar2;
lv_obj_t* calendarCrossBar1; lv_obj_t* calendarCrossBar1;
lv_obj_t* calendarCrossBar2; lv_obj_t* calendarCrossBar2;
lv_obj_t* heartbeatIcon;
lv_obj_t* heartbeatValue;
lv_obj_t* heartbeatBpm;
lv_obj_t* notificationIcon; lv_obj_t* notificationIcon;
lv_obj_t* stepGauge; lv_obj_t* stepGauge;
lv_color_t needle_colors[1]; lv_color_t needle_colors[1];

View file

@ -6,15 +6,17 @@ using namespace Pinetime::Applications::Screens;
namespace { namespace {
static void lv_update_task(struct _lv_task_t* task) { 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(); user_data->UpdateScreen();
} }
static void event_handler(lv_obj_t* obj, lv_event_t event) { 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); 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; uint32_t eventData = *eventDataPtr;
screen->OnObjectEvent(obj, event, eventData); screen->OnValueChangedEvent(obj, eventData);
} }
} }
@ -125,9 +127,9 @@ bool Tile::Refresh() {
return running; return running;
} }
void Tile::OnObjectEvent(lv_obj_t* obj, lv_event_t event, uint32_t buttonId) { void Tile::OnValueChangedEvent(lv_obj_t* obj, uint32_t buttonId) {
if (event == LV_EVENT_VALUE_CHANGED) { if(obj != btnm1) return;
app->StartApp(apps[buttonId], DisplayApp::FullRefreshDirections::Up); app->StartApp(apps[buttonId], DisplayApp::FullRefreshDirections::Up);
running = false; running = false;
} }
}

View file

@ -32,7 +32,7 @@ namespace Pinetime {
bool Refresh() override; bool Refresh() override;
void UpdateScreen(); 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: private:
Pinetime::Controllers::Battery& batteryController; Pinetime::Controllers::Battery& batteryController;

View file

@ -10,38 +10,37 @@ LV_IMG_DECLARE(bg_clock);
using namespace Pinetime::Applications::Screens; using namespace Pinetime::Applications::Screens;
namespace { namespace {
constexpr int16_t HourLength = 70;
constexpr auto HOUR_LENGTH = 70; constexpr int16_t MinuteLength = 90;
constexpr auto MINUTE_LENGTH = 90; constexpr int16_t SecondLength = 110;
constexpr auto SECOND_LENGTH = 110;
// sin(90) = 1 so the value of _lv_trigo_sin(90) is the scaling factor // sin(90) = 1 so the value of _lv_trigo_sin(90) is the scaling factor
const auto LV_TRIG_SCALE = _lv_trigo_sin(90); const auto LV_TRIG_SCALE = _lv_trigo_sin(90);
int16_t cosine(int16_t angle) { int16_t Cosine(int16_t angle) {
return _lv_trigo_sin(angle + 90); return _lv_trigo_sin(angle + 90);
} }
int16_t sine(int16_t angle) { int16_t Sine(int16_t angle) {
return _lv_trigo_sin(angle); return _lv_trigo_sin(angle);
} }
int16_t coordinate_x_relocate(int16_t x) { int16_t CoordinateXRelocate(int16_t x) {
return (x + LV_HOR_RES / 2); return (x + LV_HOR_RES / 2);
} }
int16_t coordinate_y_relocate(int16_t y) { int16_t CoordinateYRelocate(int16_t y) {
return std::abs(y - LV_HOR_RES / 2); return std::abs(y - LV_HOR_RES / 2);
} }
lv_point_t coordinate_relocate(int16_t radius, int16_t angle) { lv_point_t CoordinateRelocate(int16_t radius, int16_t angle) {
return lv_point_t{ return lv_point_t{
.x = coordinate_x_relocate(radius * static_cast<int32_t>(sine(angle)) / LV_TRIG_SCALE), .x = CoordinateXRelocate(radius * static_cast<int32_t>(Sine(angle)) / LV_TRIG_SCALE),
.y = coordinate_y_relocate(radius * static_cast<int32_t>(cosine(angle)) / LV_TRIG_SCALE) .y = CoordinateYRelocate(radius * static_cast<int32_t>(Cosine(angle)) / LV_TRIG_SCALE)
}; };
} }
} // namespace }
WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app, WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app,
Controllers::DateTime& dateTimeController, Controllers::DateTime& dateTimeController,
@ -123,7 +122,6 @@ WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app,
} }
WatchFaceAnalog::~WatchFaceAnalog() { WatchFaceAnalog::~WatchFaceAnalog() {
lv_style_reset(&hour_line_style); lv_style_reset(&hour_line_style);
lv_style_reset(&hour_line_style_trace); lv_style_reset(&hour_line_style_trace);
lv_style_reset(&minute_line_style); lv_style_reset(&minute_line_style);
@ -134,18 +132,17 @@ WatchFaceAnalog::~WatchFaceAnalog() {
} }
void WatchFaceAnalog::UpdateClock() { void WatchFaceAnalog::UpdateClock() {
hour = dateTimeController.Hours(); hour = dateTimeController.Hours();
minute = dateTimeController.Minutes(); minute = dateTimeController.Minutes();
second = dateTimeController.Seconds(); second = dateTimeController.Seconds();
if (sMinute != minute) { if (sMinute != minute) {
auto const angle = minute * 6; auto const angle = minute * 6;
minute_point[0] = coordinate_relocate(30, angle); minute_point[0] = CoordinateRelocate(30, angle);
minute_point[1] = coordinate_relocate(MINUTE_LENGTH, angle); minute_point[1] = CoordinateRelocate(MinuteLength, angle);
minute_point_trace[0] = coordinate_relocate(5, angle); minute_point_trace[0] = CoordinateRelocate(5, angle);
minute_point_trace[1] = coordinate_relocate(31, angle); minute_point_trace[1] = CoordinateRelocate(31, angle);
lv_line_set_points(minute_body, minute_point, 2); lv_line_set_points(minute_body, minute_point, 2);
lv_line_set_points(minute_body_trace, minute_point_trace, 2); lv_line_set_points(minute_body_trace, minute_point_trace, 2);
@ -156,11 +153,11 @@ void WatchFaceAnalog::UpdateClock() {
sMinute = minute; sMinute = minute;
auto const angle = (hour * 30 + minute / 2); auto const angle = (hour * 30 + minute / 2);
hour_point[0] = coordinate_relocate(30, angle); hour_point[0] = CoordinateRelocate(30, angle);
hour_point[1] = coordinate_relocate(HOUR_LENGTH, angle); hour_point[1] = CoordinateRelocate(HourLength, angle);
hour_point_trace[0] = coordinate_relocate(5, angle); hour_point_trace[0] = CoordinateRelocate(5, angle);
hour_point_trace[1] = coordinate_relocate(31, angle); hour_point_trace[1] = CoordinateRelocate(31, angle);
lv_line_set_points(hour_body, hour_point, 2); lv_line_set_points(hour_body, hour_point, 2);
lv_line_set_points(hour_body_trace, hour_point_trace, 2); lv_line_set_points(hour_body_trace, hour_point_trace, 2);
@ -170,8 +167,8 @@ void WatchFaceAnalog::UpdateClock() {
sSecond = second; sSecond = second;
auto const angle = second * 6; auto const angle = second * 6;
second_point[0] = coordinate_relocate(-20, angle); second_point[0] = CoordinateRelocate(-20, angle);
second_point[1] = coordinate_relocate(SECOND_LENGTH, angle); second_point[1] = CoordinateRelocate(SecondLength, angle);
lv_line_set_points(second_body, second_point, 2); lv_line_set_points(second_body, second_point, 2);
} }
} }
@ -186,16 +183,12 @@ bool WatchFaceAnalog::Refresh() {
notificationState = notificationManager.AreNewNotificationsAvailable(); notificationState = notificationManager.AreNewNotificationsAvailable();
if (notificationState.IsUpdated()) { if (notificationState.IsUpdated()) {
if (notificationState.Get() == true) lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(notificationState.Get()));
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(true));
else
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false));
} }
currentDateTime = dateTimeController.CurrentDateTime(); currentDateTime = dateTimeController.CurrentDateTime();
if (currentDateTime.IsUpdated()) { if (currentDateTime.IsUpdated()) {
month = dateTimeController.Month(); month = dateTimeController.Month();
day = dateTimeController.Day(); day = dateTimeController.Day();
dayOfWeek = dateTimeController.DayOfWeek(); dayOfWeek = dateTimeController.DayOfWeek();
@ -203,7 +196,6 @@ bool WatchFaceAnalog::Refresh() {
UpdateClock(); UpdateClock();
if ((month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) { if ((month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) {
lv_label_set_text_fmt(label_date_day, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), day); lv_label_set_text_fmt(label_date_day, "%s\n%02i", dateTimeController.DayOfWeekShortToString(), day);
currentMonth = month; currentMonth = month;

View file

@ -58,14 +58,12 @@ namespace Pinetime {
lv_obj_t* minute_body_trace; lv_obj_t* minute_body_trace;
lv_obj_t* second_body; lv_obj_t* second_body;
// ##
lv_point_t hour_point[2]; lv_point_t hour_point[2];
lv_point_t hour_point_trace[2]; lv_point_t hour_point_trace[2];
lv_point_t minute_point[2]; lv_point_t minute_point[2];
lv_point_t minute_point_trace[2]; lv_point_t minute_point_trace[2];
lv_point_t second_point[2]; lv_point_t second_point[2];
// ##
lv_style_t hour_line_style; lv_style_t hour_line_style;
lv_style_t hour_line_style_trace; lv_style_t hour_line_style_trace;
lv_style_t minute_line_style; lv_style_t minute_line_style;

View file

@ -12,9 +12,6 @@
#include "components/ble/NotificationManager.h" #include "components/ble/NotificationManager.h"
#include "components/heartrate/HeartRateController.h" #include "components/heartrate/HeartRateController.h"
#include "components/motion/MotionController.h" #include "components/motion/MotionController.h"
#include "components/settings/Settings.h"
#include "../DisplayApp.h"
using namespace Pinetime::Applications::Screens; using namespace Pinetime::Applications::Screens;
WatchFaceDigital::WatchFaceDigital(DisplayApp* app, WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
@ -36,12 +33,6 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
motionController {motionController} { motionController {motionController} {
settingsController.SetClockFace(0); settingsController.SetClockFace(0);
displayedChar[0] = 0;
displayedChar[1] = 0;
displayedChar[2] = 0;
displayedChar[3] = 0;
displayedChar[4] = 0;
batteryIcon = lv_label_create(lv_scr_act(), nullptr); batteryIcon = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text(batteryIcon, Symbols::batteryFull); lv_label_set_text(batteryIcon, Symbols::batteryFull);
lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 2); lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 2);
@ -56,7 +47,7 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app,
lv_label_set_text(bleIcon, Symbols::bluetooth); lv_label_set_text(bleIcon, Symbols::bluetooth);
lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0); lv_obj_align(bleIcon, batteryPlug, LV_ALIGN_OUT_LEFT_MID, -5, 0);
notificationIcon = lv_label_create(lv_scr_act(), NULL); notificationIcon = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00)); lv_obj_set_style_local_text_color(notificationIcon, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00));
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false)); lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false));
lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 10, 0); lv_obj_align(notificationIcon, nullptr, LV_ALIGN_IN_TOP_LEFT, 10, 0);
@ -111,17 +102,13 @@ bool WatchFaceDigital::Refresh() {
if (batteryPercentRemaining.IsUpdated()) { if (batteryPercentRemaining.IsUpdated()) {
auto batteryPercent = batteryPercentRemaining.Get(); auto batteryPercent = batteryPercentRemaining.Get();
lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent)); lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent));
auto isCharging = batteryController.IsCharging() || batteryController.IsPowerPresent(); auto isCharging = batteryController.IsCharging() or batteryController.IsPowerPresent();
lv_label_set_text(batteryPlug, BatteryIcon::GetPlugIcon(isCharging)); lv_label_set_text(batteryPlug, BatteryIcon::GetPlugIcon(isCharging));
} }
bleState = bleController.IsConnected(); bleState = bleController.IsConnected();
if (bleState.IsUpdated()) { if (bleState.IsUpdated()) {
if (bleState.Get() == true) { lv_label_set_text(bleIcon, BleIcon::GetIcon(bleState.Get()));
lv_label_set_text(bleIcon, BleIcon::GetIcon(true));
} else {
lv_label_set_text(bleIcon, BleIcon::GetIcon(false));
}
} }
lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 5); lv_obj_align(batteryIcon, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, -5, 5);
lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0); lv_obj_align(batteryPlug, batteryIcon, LV_ALIGN_OUT_LEFT_MID, -5, 0);
@ -129,10 +116,7 @@ bool WatchFaceDigital::Refresh() {
notificationState = notificatioManager.AreNewNotificationsAvailable(); notificationState = notificatioManager.AreNewNotificationsAvailable();
if (notificationState.IsUpdated()) { if (notificationState.IsUpdated()) {
if (notificationState.Get() == true) lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(notificationState.Get()));
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(true));
else
lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false));
} }
currentDateTime = dateTimeController.CurrentDateTime(); currentDateTime = dateTimeController.CurrentDateTime();
@ -144,9 +128,9 @@ bool WatchFaceDigital::Refresh() {
auto time = date::make_time(newDateTime - dp); auto time = date::make_time(newDateTime - dp);
auto yearMonthDay = date::year_month_day(dp); auto yearMonthDay = date::year_month_day(dp);
auto year = (int) yearMonthDay.year(); auto year = static_cast<int>(yearMonthDay.year());
auto month = static_cast<Pinetime::Controllers::DateTime::Months>((unsigned) yearMonthDay.month()); auto month = static_cast<Pinetime::Controllers::DateTime::Months>(static_cast<unsigned>(yearMonthDay.month()));
auto day = (unsigned) yearMonthDay.day(); auto day = static_cast<unsigned>(yearMonthDay.day());
auto dayOfWeek = static_cast<Pinetime::Controllers::DateTime::Days>(date::weekday(yearMonthDay).iso_encoding()); auto dayOfWeek = static_cast<Pinetime::Controllers::DateTime::Days>(date::weekday(yearMonthDay).iso_encoding());
int hour = time.hours().count(); int hour = time.hours().count();
@ -175,15 +159,13 @@ bool WatchFaceDigital::Refresh() {
sprintf(hoursChar, "%02d", hour); sprintf(hoursChar, "%02d", hour);
} }
if (hoursChar[0] != displayedChar[0] || hoursChar[1] != displayedChar[1] || minutesChar[0] != displayedChar[2] || if ((hoursChar[0] != displayedChar[0]) or (hoursChar[1] != displayedChar[1]) or (minutesChar[0] != displayedChar[2]) or
minutesChar[1] != displayedChar[3]) { (minutesChar[1] != displayedChar[3])) {
displayedChar[0] = hoursChar[0]; displayedChar[0] = hoursChar[0];
displayedChar[1] = hoursChar[1]; displayedChar[1] = hoursChar[1];
displayedChar[2] = minutesChar[0]; displayedChar[2] = minutesChar[0];
displayedChar[3] = minutesChar[1]; displayedChar[3] = minutesChar[1];
char timeStr[6];
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
lv_label_set_text(label_time_ampm, ampmChar); lv_label_set_text(label_time_ampm, ampmChar);
if (hoursChar[0] == '0') { if (hoursChar[0] == '0') {
@ -191,8 +173,7 @@ bool WatchFaceDigital::Refresh() {
} }
} }
sprintf(timeStr, "%c%c:%c%c", hoursChar[0], hoursChar[1], minutesChar[0], minutesChar[1]); lv_label_set_text_fmt(label_time, "%s:%s", hoursChar, minutesChar);
lv_label_set_text(label_time, timeStr);
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) { if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0); lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, 0, 0);
@ -202,13 +183,11 @@ bool WatchFaceDigital::Refresh() {
} }
if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) { if ((year != currentYear) || (month != currentMonth) || (dayOfWeek != currentDayOfWeek) || (day != currentDay)) {
char dateStr[22];
if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) { if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) {
sprintf(dateStr, "%s %d %s %d", dateTimeController.DayOfWeekShortToString(), day, dateTimeController.MonthShortToString(), year); lv_label_set_text_fmt(label_date, "%s %d %s %d", dateTimeController.DayOfWeekShortToString(), day, dateTimeController.MonthShortToString(), year);
} else { } else {
sprintf(dateStr, "%s %s %d %d", dateTimeController.DayOfWeekShortToString(), dateTimeController.MonthShortToString(), day, year); lv_label_set_text_fmt(label_date, "%s %s %d %d", dateTimeController.DayOfWeekShortToString(), dateTimeController.MonthShortToString(), day, year);
} }
lv_label_set_text(label_date, dateStr);
lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_CENTER, 0, 60); lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_CENTER, 0, 60);
currentYear = year; currentYear = year;

View file

@ -35,10 +35,8 @@ namespace Pinetime {
bool Refresh() override; bool Refresh() override;
void OnObjectEvent(lv_obj_t* pObj, lv_event_t i);
private: private:
char displayedChar[5]; char displayedChar[5] {};
uint16_t currentYear = 1970; uint16_t currentYear = 1970;
Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown; Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown;
@ -63,7 +61,6 @@ namespace Pinetime {
lv_obj_t* batteryPlug; lv_obj_t* batteryPlug;
lv_obj_t* heartbeatIcon; lv_obj_t* heartbeatIcon;
lv_obj_t* heartbeatValue; lv_obj_t* heartbeatValue;
lv_obj_t* heartbeatBpm;
lv_obj_t* stepIcon; lv_obj_t* stepIcon;
lv_obj_t* stepValue; lv_obj_t* stepValue;
lv_obj_t* notificationIcon; lv_obj_t* notificationIcon;

View file

@ -5,6 +5,7 @@
#include <libraries/gpiote/app_gpiote.h> #include <libraries/gpiote/app_gpiote.h>
#include <libraries/timer/app_timer.h> #include <libraries/timer/app_timer.h>
#include <softdevice/common/nrf_sdh.h> #include <softdevice/common/nrf_sdh.h>
#include <nrf_delay.h>
// nimble // nimble
#define min // workaround: nimble's min/max macros conflict with libstdc++ #define min // workaround: nimble's min/max macros conflict with libstdc++
@ -305,6 +306,20 @@ int main(void) {
nrf_drv_clock_init(); nrf_drv_clock_init();
// Unblock i2c?
nrf_gpio_cfg(pinTwiScl,
NRF_GPIO_PIN_DIR_OUTPUT,
NRF_GPIO_PIN_INPUT_DISCONNECT,
NRF_GPIO_PIN_NOPULL,
NRF_GPIO_PIN_S0D1,
NRF_GPIO_PIN_NOSENSE);
nrf_gpio_pin_set(pinTwiScl);
for (uint8_t i = 0; i < 16; i++) {
nrf_gpio_pin_toggle(pinTwiScl);
nrf_delay_us(5);
}
nrf_gpio_cfg_default(pinTwiScl);
debounceTimer = xTimerCreate("debounceTimer", 200, pdFALSE, (void*) 0, DebounceTimerCallback); debounceTimer = xTimerCreate("debounceTimer", 200, pdFALSE, (void*) 0, DebounceTimerCallback);
debounceChargeTimer = xTimerCreate("debounceTimerCharge", 200, pdFALSE, (void*) 0, DebounceTimerChargeCallback); debounceChargeTimer = xTimerCreate("debounceTimerCharge", 200, pdFALSE, (void*) 0, DebounceTimerChargeCallback);