Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Continuous time updates #2041

Merged
merged 3 commits into from
Jun 9, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/components/ble/SimpleWeatherService.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ int WeatherCallback(uint16_t /*connHandle*/, uint16_t /*attrHandle*/, struct ble
return static_cast<Pinetime::Controllers::SimpleWeatherService*>(arg)->OnCommand(ctxt);
}

SimpleWeatherService::SimpleWeatherService(const DateTime& dateTimeController) : dateTimeController(dateTimeController) {
SimpleWeatherService::SimpleWeatherService(DateTime& dateTimeController) : dateTimeController(dateTimeController) {
}

void SimpleWeatherService::Init() {
Expand Down
4 changes: 2 additions & 2 deletions src/components/ble/SimpleWeatherService.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ namespace Pinetime {

class SimpleWeatherService {
public:
explicit SimpleWeatherService(const DateTime& dateTimeController);
explicit SimpleWeatherService(DateTime& dateTimeController);

void Init();

Expand Down Expand Up @@ -140,7 +140,7 @@ namespace Pinetime {

uint16_t eventHandle {};

const Pinetime::Controllers::DateTime& dateTimeController;
Pinetime::Controllers::DateTime& dateTimeController;

std::optional<CurrentWeather> currentWeather;
std::optional<Forecast> forecast;
Expand Down
43 changes: 30 additions & 13 deletions src/components/datetime/DateTimeController.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "components/datetime/DateTimeController.h"
#include <libraries/log/nrf_log.h>
#include <systemtask/SystemTask.h>
#include <hal/nrf_rtc.h>

using namespace Pinetime::Controllers;

Expand All @@ -12,11 +13,16 @@ namespace {
}

DateTime::DateTime(Controllers::Settings& settingsController) : settingsController {settingsController} {
mutex = xSemaphoreCreateMutex();
ASSERT(mutex != nullptr);
xSemaphoreGive(mutex);
}

void DateTime::SetCurrentTime(std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> t) {
xSemaphoreTake(mutex, portMAX_DELAY);
this->currentDateTime = t;
UpdateTime(previousSystickCounter); // Update internal state without updating the time
UpdateTime(previousSystickCounter, true); // Update internal state without updating the time
xSemaphoreGive(mutex);
}

void DateTime::SetTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {
Expand All @@ -29,13 +35,15 @@ void DateTime::SetTime(uint16_t year, uint8_t month, uint8_t day, uint8_t hour,
/* .tm_year = */ year - 1900,
};

tm.tm_isdst = -1; // Use DST value from local time zone
currentDateTime = std::chrono::system_clock::from_time_t(std::mktime(&tm));

NRF_LOG_INFO("%d %d %d ", day, month, year);
NRF_LOG_INFO("%d %d %d ", hour, minute, second);

UpdateTime(previousSystickCounter);
tm.tm_isdst = -1; // Use DST value from local time zone

xSemaphoreTake(mutex, portMAX_DELAY);
currentDateTime = std::chrono::system_clock::from_time_t(std::mktime(&tm));
UpdateTime(previousSystickCounter, true);
xSemaphoreGive(mutex);

systemTask->PushMessage(System::Messages::OnNewTime);
}
Expand All @@ -45,25 +53,34 @@ void DateTime::SetTimeZone(int8_t timezone, int8_t dst) {
dstOffset = dst;
}

void DateTime::UpdateTime(uint32_t systickCounter) {
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> DateTime::CurrentDateTime() {
xSemaphoreTake(mutex, portMAX_DELAY);
UpdateTime(nrf_rtc_counter_get(portNRF_RTC_REG), false);
xSemaphoreGive(mutex);
return currentDateTime;
}

void DateTime::UpdateTime(uint32_t systickCounter, bool forceUpdate) {
// Handle systick counter overflow
uint32_t systickDelta = 0;
if (systickCounter < previousSystickCounter) {
systickDelta = 0xffffff - previousSystickCounter;
systickDelta = static_cast<uint32_t>(portNRF_RTC_MAXTICKS) - previousSystickCounter;
systickDelta += systickCounter + 1;
} else {
systickDelta = systickCounter - previousSystickCounter;
}

/*
* 1000 ms = 1024 ticks
*/
auto correctedDelta = systickDelta / 1024;
auto rest = systickDelta % 1024;
auto correctedDelta = systickDelta / configTICK_RATE_HZ;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I think about it, the RTOS tick rate isn't necessarily the RTC tick rate. But we drive the RTOS tick from the RTC. Part of me wonders whether we should separate the RTOS tick and RTC tick at all. The simplicity of a unified tick would be nice

// If a second hasn't passed, there is nothing to do
// If the time has been changed, set forceUpdate to trigger internal state updates
if (correctedDelta == 0 && !forceUpdate) {
return;
}
auto rest = systickDelta % configTICK_RATE_HZ;
if (systickCounter >= rest) {
previousSystickCounter = systickCounter - rest;
} else {
previousSystickCounter = 0xffffff - (rest - systickCounter);
previousSystickCounter = static_cast<uint32_t>(portNRF_RTC_MAXTICKS) - (rest - systickCounter - 1);
}

currentDateTime += std::chrono::seconds(correctedDelta);
Expand Down
16 changes: 9 additions & 7 deletions src/components/datetime/DateTimeController.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <ctime>
#include <string>
#include "components/settings/Settings.h"
#include <FreeRTOS.h>
#include <semphr.h>

namespace Pinetime {
namespace System {
Expand Down Expand Up @@ -45,8 +47,6 @@ namespace Pinetime {
*/
void SetTimeZone(int8_t timezone, int8_t dst);

void UpdateTime(uint32_t systickCounter);

uint16_t Year() const {
return 1900 + localTime.tm_year;
}
Expand Down Expand Up @@ -124,12 +124,10 @@ namespace Pinetime {
static const char* MonthShortToStringLow(Months month);
static const char* DayOfWeekShortToStringLow(Days day);

std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> CurrentDateTime() const {
return currentDateTime;
}
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> CurrentDateTime();

std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> UTCDateTime() const {
return currentDateTime - std::chrono::seconds((tzOffset + dstOffset) * 15 * 60);
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> UTCDateTime() {
return CurrentDateTime() - std::chrono::seconds((tzOffset + dstOffset) * 15 * 60);
}

std::chrono::seconds Uptime() const {
Expand All @@ -141,10 +139,14 @@ namespace Pinetime {
std::string FormattedTime();

private:
void UpdateTime(uint32_t systickCounter, bool forceUpdate);

std::tm localTime;
int8_t tzOffset = 0;
int8_t dstOffset = 0;

SemaphoreHandle_t mutex = nullptr;

uint32_t previousSystickCounter = 0;
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> currentDateTime;
std::chrono::seconds uptime {0};
Expand Down
2 changes: 1 addition & 1 deletion src/displayapp/screens/WatchFaceAnalog.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ namespace Pinetime {

BatteryIcon batteryIcon;

const Controllers::DateTime& dateTimeController;
Controllers::DateTime& dateTimeController;
const Controllers::Battery& batteryController;
const Controllers::Ble& bleController;
Controllers::NotificationManager& notificationManager;
Expand Down
2 changes: 0 additions & 2 deletions src/systemtask/SystemTask.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,6 @@ void SystemTask::Work() {
}

monitor.Process();
uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG);
dateTimeController.UpdateTime(systick_counter);
NoInit_BackUpTime = dateTimeController.CurrentDateTime();
if (nrf_gpio_pin_read(PinMap::Button) == 0) {
watchdog.Reload();
Expand Down
Loading