GeezerVisonThe World Wide Web, restored to 800 pixels of glory. | |||||||||||||||||||||||||||||||||||
| Home|About|Gaming cabinet|Archives|How it works|Starter sites | |||||||||||||||||||||||||||||||||||
GeezerVison is showing github.com — Continuous time updates by mark9064 · Pull Request #2041 · InfiniTimeOrg/InfiniTime Conversation
|
|
Build size and comparison to main:
|
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Hmm, not sure about simulator breakage. Anyone know what's causing the issue is there? Is FreeRTOS not available? |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Yeah, the sim doesn't use FreeRTOS. All the files using it are duplicated with the RTOS function calls removed in InfiniSim. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
| */ | ||
| auto correctedDelta = systickDelta / 1024; | ||
| auto rest = systickDelta % 1024; | ||
| auto correctedDelta = systickDelta / configTICK_RATE_HZ; |
There was a problem 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
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
(InfiniSim PR now ready) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I'm a little worried of this new mutex. I applied the original design on purpose : SystemTask is the only class with "write accesss" to the clock. It might not be a big deal but it adds complexity and synchronization between tasks.
Could you give more details about this? I'm not sure what frame pacing is in the context of the always on feature. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Yeah I don't love the mutex either. The reason why I went with this is because when anything on the watch calls CurrentDateTime(), it should get the current time. At the moment, it gets the time as of whenever the system task last executed its loop. This reduces the granularity of the main system clock to 100ms. Also, if something blocks the system task then the time can be more incorrect. Apps like the stopwatch which measure wall clock time should use the current time, but they can't due to this imprecision. So it uses the scheduler tick instead which is currently tied to the RTC (on NRF the RTC drives the scheduler tick), but semantically this is wrong (another platform may drive the scheduler another way). TLDR: I think CurrentDateTime() should provide the current time accurately Regarding frame pacing: Suppose LVGL runs at t=0ms, t=500ms, t=1000ms, t=1500ms etc as in always on, and that display scanout is perfectly synchronised with LVGL. Suppose system task runs at t=0ms,t=101,202,303,404,505,606,707,808,909,1010,1111,1212,... (it always takes a little longer than 100 ticks as that's the timeout, I'm assuming 1 tick=1ms to make the example clear) At t=0ms, LVGL will get the current time and display 00:00:00 as expected. In normal operation, LVGL runs every 20ms, so the time changing 20ms late isn't noticeable. But in always on, LVGL runs every 500ms and the time changing 500ms late is very noticeable for watchfaces that use seconds - in other words a second has appeared to last 1.5 seconds. This is what I referred to when I said there are problems with frame pacing. Another solution would be to have CurrentDateTime() fetch the current RTC time but not update any state within the controller, splitting out state updates to a new method. But this still has synchronisation problems as the system task could be halfway through updating state inside the time controller when another task calls CurrentDateTime() |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
Thank you very much for this detailed explanation. Fast, accurate and precise time is indeed a core functionality of a watch so this PR makes sense. However, if you don't mind, I would like to explore other options before we settle on this implementation. The 2 points to I would like to improve are
Here are a few options that I would like to explore:
Let me know what you think of those options. I'm willing to make a proof-of-concept if you want me to ;-) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
I'm totally happy with any implementation that results in up to date time, not attached to this one! Currently, this implementation will deadlock if the system task message queue is full, and the system task is currently waiting for the mutex. Priority inversion assures that a low priority task cannot block the system task (or any higher priority task) in any other way.
One thing I've just noticed. We could move just the system task messages out of the mutex. This would make it impossible for the function to block any other task (and therefore deadlock) in any scenario. Though of course the system task could still deadlock itself, but it can do this already. |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
This is an alternative implementation to #2041 we talked about in this comment (#2041 (comment)). This implementation does not change the state of the DateTime controller (previousSystickCounter and currentDateTime fields) in GetCurrentDateTime(). This allows to keep the method GetCurrentDateTime() const. I also applied a small refactoring of the methods UpdateTime() to avoid trying to lock the same mutex multiple times (FreeRTOS mutexes are not reentrant). Co-authored-by: [email protected]
|
@mark9064 If you're OK with this suggestion, I'll add the mentionned TODO file and merge this branch :) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
|
In hindsight, you're totally right that a full refactor would be out of scope for this, I really appreciate your feedback and explanation. Resolving to go ahead with this and rework later makes sense. The TODO file looks great, I've fixed a couple typos but other than that I think it's good to go. Adjusted version below + in code block Where exactly should this file go? PS: I'll rebase the branch after the TODO file is in Refactoring neededContextThe PR #2041 - Continuous time updates highlighted some limitations in the design of DateTimeController: the granularity of the time returned by @mark9064 provided more details in this comment. The PR #2041 - Continuous time updates provided some changes to However, the review showed that We tried to identify alternative implementation that would have maintained the "const correctness" but we eventually figured that this would lead to a re-design of So we decided to merge this PR #2041 and agree to fix/improve What needs to be done?Improve/redesign
Once this redesign is implemented, all instances/references to Please check the following PR to get more context about this redesign:
# Refactoring needed ## Context The [PR #2041 - Continuous time updates](https://github.com/InfiniTimeOrg/InfiniTime/pull/2041) highlighted some limitations in the design of DateTimeController: the granularity of the time returned by `DateTime::CurrentDateTime()` is limited by the frequency at which SystemTask calls `DateTime::UpdateTime()`, which is currently set to 100ms. @mark9064 provided more details in [this comment](https://github.com/InfiniTimeOrg/InfiniTime/pull/2041#issuecomment-2048528967). The [PR #2041 - Continuous time updates](https://github.com/InfiniTimeOrg/InfiniTime/pull/2041) provided some changes to `DateTime` controller that improves the granularity of the time returned by `DateTime::CurrentDateTime()`. However, the review showed that `DateTime` cannot be `const` anymore, even when it's only used to get the current time, since `DateTime::CurrentDateTime()` changes the internal state of the instance. We tried to identify alternative implementation that would have maintained the "const correctness" but we eventually figured that this would lead to a re-design of `DateTime` which was out of scope of the initial PR (Continuous time updates and always on display). So we decided to merge this PR #2041 and agree to fix/improve `DateTime` later on. ## What needs to be done? Improve/redesign `DateTime` so that it * provides a very granular (ideally down to the millisecond) date and time via `CurrentDateTime()`. * can be declared/passed as `const` when it's only used to **get** the time. * limits the use of mutex as much as possible (an ideal implementation would not use any mutex, but this might not be possible). * improves the design of `DateTime::Seconds()`, `DateTime::Minutes()`, `DateTime::Hours()`, etc as explained [in this comment](https://github.com/InfiniTimeOrg/InfiniTime/pull/2054#pullrequestreview-2037033105). Once this redesign is implemented, all instances/references to `DateTime` should be reviewed and updated to use `const` where appropriate. Please check the following PR to get more context about this redesign: * [#2041 - Continuous time updates by @mark9064](https://github.com/InfiniTimeOrg/InfiniTime/pull/2041) * [#2054 - Continuous time update - Alternative implementation to #2041 by @JF002](https://github.com/InfiniTimeOrg/InfiniTime/pull/2054) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
Add TODO.md in src/components/datetime. This file give detailed information about a refactoring of the DateTimeController that would be nice to do in the future.
|
@mark9064 I've just added the TODO file in src/components/datetime. I'll merge this branch as soon as the Actions are successful :) |
Sorry, something went wrong.
There was an error while loading. Please reload this page.
There was an error while loading. Please reload this page.
Successfully merging this pull request may close these issues.
There was an error while loading. Please reload this page.