A list of "user applications" is built at compile time. It contains all the info needed to create the application at runtime (ptr to a create() function) and to display the app in the application menu. All applications declare a TypeTrait with these information.
When a new app must be loaded, DisplayApp first check if this app is a System app (in which case it creates it like it did before). If it's not a System app, it looks for the app in the list of User applications and creates it if it found it.
Those changes allow to more easily add new app and to select which app must be built into the firmware.
Switch to C++20 (and fix a few issues in SpiMaster.cpp and Watchdog.cpp.
When a notification is received, SystemTask sends messages to DisplayApp, which loads the Notifications apps that sends a few messages to SystemApp.
When notification are received too quickly, DisplayApp and SystemTask cannot process those messages fast enough (probably because of the time it takes to refresh the display) and the message queues fill up. When they are full, the current implementation just waits until there's room available to store the event. In this case, since both tasks exchange messages, they end up in a deadlock.
This fix consists in setting the timeout value to 0 (non-blocking mode) for the NewNotification messages on the DisplayApp side. This will prevent the SystemTask from being blocked (which would result in the watchdog reseting the watch). A more generic approach should be design in the future.
Create a minimal python port of the node.js module `lv_img_conv`. Only
the currently in use color formats `CF_INDEXED_1_BIT` and
`CF_TRUE_COLOR_ALPHA` are implemented.
Output only as binary with format `ARGB8565_RBSWAP`.
This is enough to create the `resources-1.13.0.zip`.
Python3 implements "propper" "banker's rounding" by rounding to the nearest
even number. Javascript rounds to the nearest integer.
To have the same output as the original JavaScript implementation add a custom
rounding function, which does "school" rounding (to the nearest integer)
Update CMake file in `resources` folder to call `lv_img_conf.py` instead of
node module.
For docker-files install `python3-pil` package for `lv_img_conv.py` script.
And remove the `lv_img_conv` node installation.
---
gen_img: special handling for python lv_img_conv script
Not needed on Linux systems, as the shebang of the python script is read
and used. But just to be sure use the python interpreter found by CMake.
Also helps if tried to run on Windows host.
---
doc: buildAndProgram: remove node script lv_img_conv mention
Remove node script `lv_img_conv` mention and replace it for
runtime-depency `python3-pil` of python script `lv_img_conv.py`.
Navigation app now needs 2 images to be loaded from the resources on the external filesystem. This PR adds an 'enabled' field to the Applications struct. This field is true for all applications expect for Navigation which calls Navigation::IsAvailable(). This methods returns true if the 2 files are available in the resources.
The application list disables the application (draws it in grey, disables the touch callback) if the enable flag is not set.
The TTF font used by the navigation app is ~20KB and is stored in internal flash memory.
To free this space, the TTF font is now converted in 2 "atlas pictures" (pictures that contain multiple concatenated images) stored in the external flash memory. The navigation app now accesses one of those 2 files and apply an offset to display the desired picture.
The corresponding documentation has also been updated.
Add comments about the layout of the pictures that contain the icon and about the indexing of those icons.
In documentation (buildAndProgram.md), edit the section about the debug compilation mode. Remove the part about removing the Navigation app to free some memory (since it's not relevant anymore) and explain how to selectively build parts of the firmware in Debug mode.
This new algorithm calculates the number of degrees that the wrist has
rolled, and checks if that is above a threshold.
First it checks if the wrist is still enough for the acceleration values
to be considered mostly from gravity. It does this by calculating the
mean over the past 2 SystemTask loops, and checking that the variance
from that mean is below a threshold.
Then it calculates the angle the wrist is being held at, and calculates
the difference from the angle some time ago. If this difference is above
the threshold, it wakes the watch.
The accumulated speed was calculated by dividing first and multiplying
after, which results in more rounding errors than if you multiply first
and then divide. The values aren't big enough to overflow.
* change background image to widgets
This commit removes the background image for the WatchFaceAnalog and replaces it with lvgl widgets. It aims to keep the original look.
* remove comments and background image
---------
Co-authored-by: minacode <minamoto9@web.de>
This commit changes the order for the notification struct fields to allow the creation of notifications using a string literal.
```cpp
NotificationManager::Notifiation notification {
"String literal with notification text",
42,
NotificationManager::Categories::SimpleAlert
};
```
Co-authored-by: minacode <minamoto9@web.de>
* ShakeWake: Fixed instant wake after sleep issue in certain positions
Add lastX var to track the previous x acceleration for correct calculation of speed.
Reorder axes for clarity.
---------
Co-authored-by: Isaac <114504394+isaacc27@users.noreply.github.com>
Co-authored-by: FintasticMan <52415484+FintasticMan@users.noreply.github.com>
Calls to Spi::Init() are not needed, pin initialization is already done in ctor().
Remove calls to Spi::Sleep()/Spi::Wakeup() to ensure that SPI CS pins are kept high even in sleep mode.
Ensure that all pins are set to their default configuration during sleep mode.
Disable the workaround for FTPAN58 (SPI freezes when transfering a single byte) at the end of the transfer. This disables the resources needed for the workaround.
Those changes reduce the power usage by 430-490µA.
The DC/DC regulator reduce the power consumption of the MCU compared to the default LDO regulator. The DC/DC regulator needs additional HW that is mounted on the PineTime.
This change reduces the power usage by 380µA during fast advertising, by 200µA during slow advertising and by 186µA when BLE is disabled.
Put the HRS3300 to sleep mode when InfiniTime is going to sleep. This change reduces the power consumption by 130µA when the heart rate sensor is disabled.
LVGL supports custom implementation of malloc() and free() so using pvPortMalloc() and vPortFree() is just a matter of setting the right variables.
Other libraries (NimBLE, LittleFS) and InfiniTime code (new) call malloc() and free() from stdlib. InfiniTime now provides the file stdlib.c that provides a custom implementation for malloc(), free(), calloc() and realloc(). This ensures that all calls to the standard allocator are redirected to the FreeRTOS memory manager.
Note that realloc() is needed by NimBLE.
* Refactor and document the Watchdog driver to make it more readable.
Fix the configuration of the behaviours configuration that was not properly implemented (but it didn't cause any side effect since the correct value was eventually set in NRF_WDT->CONFIG).
Fix the wrong interpretation of the reset reasons caused by implicit conversions of int to bool.
New implementation of the heart rate sensor data processing using a frequency based PPG algorithm.
The HRS3300 settings are fine-tuned for better signal to noise at 10Hz.
The measurement delay is now set to 100ms.
Enable and use the ambient light sensor.
FFT implementation based on ArduinoFFT (https://github.com/kosme/arduinoFFT, GPLv3.0).
Replace custom FreeRTOS inactivity timers with LVGL inactivity timers.
DisplayApp: Trigger display activity on timer done.
inactivity: Add additional checks
The backlight could be turned on by RestoreBrightness() on ble connect
event.
inactivity: Trigger activity on screen switch
A notification timing out could put the watch to sleep immediately.
While this could be ideal behaviour, it was caused by delay in
processing the EnableSleeping event and pushing RestoreBrightness to
DisplayApp.
Fixes#1467 "Double tapping PineTimeStyle steps style button sends watch to sleep"
Double tap is disabled on the color settings screen by checking if the Rnd button is visible, but this didn't work for the options screen as the Rnd button isn't visible. I've changed it to check if the Close button is visible instead, which is used on both settings screens, and resolves the bug. I also changed the button used to disable the long press behaviour which was an as-yet-undiscovered bug which would have allowed the long press action to be used when the options screen was visible.
Previously, the LVGL driver for the filesystem was initialized in the class FS. However, since 6f942e2, the order of the initializations was incorrect : the driver was initialized (FS::LVGLFileSystemInit()) before LVGL (LittleVgl.Init()), which means that the driver registration was probably dropped when LVGL was initialized.
The LVGL driver is now initialized in LittleVgl.Init(), which seems to make much more sense, since all LVGL drivers are initialized there. This way, we ensure that the initialization of the drivers is consistent.
LVGL is only a part of the main DisplayApp. Other "DisplayApps" can be
implemented without LVGL.
DummyLittleVgl isn't needed anymore and has been removed
The DisplayApp class isn't used in the Screen base class and most
screens, so requiring it is pointless.
In this commit, DisplayApp pointers were added to screens which use it
and the explicit Screen constructor was removed in those screens.
Long pressing will change the value by 1000, whereas clicks will change
it by 500. This allows setting more precise values, while also making it
easier to set any value.
The time used to be yellow while paused. Changing it to white made the
paused state less distinct. Blinking the time while paused makes the
state distinct again.
Replace separate SettingSetDate and SettingSetTime with a combined screenlist.
Add DotIndicators. Similar to PageIndicator, but for use when separating screens instead of pages of a list.
Co-authored-by: Riku Isokoski <riksu9000@gmail.com>
Each opened app (screen) is pushed on a stack, which is then popped from
when returning instead of hard coded "previous apps". Return swipe and
refresh directions are automatically determined from the app transition.
Removed/simplified some generator expressions that had more repeated
elements than they needed to. Extracted some repeated sets of options
into separate variables as well.