diff --git a/.clang-tidy b/.clang-tidy
index 8a7d38f0..8b9e7c0c 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -1,4 +1,5 @@
Checks: '*,
+ -altera-unroll-loops,
-llvmlibc-callee-namespace,
-llvm-header-guard,
-llvm-namespace-comment,
@@ -14,17 +15,20 @@ Checks: '*,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-avoid-non-const-global-variables,
-cppcoreguidelines-avoid-c-arrays,
+ -cppcoreguidelines-special-member-functions,
-readability-magic-numbers,
-readability-uppercase-literal-suffix,
-modernize-use-trailing-return-type,
-modernize-avoid-c-arrays,
- -hicpp-signed-bitwise,
- -hicpp-no-assembler,
-hicpp-avoid-c-arrays,
-hicpp-uppercase-literal-suffix,
+ -hicpp-vararg,
+ -hicpp-no-assembler,
-hicpp-no-array-decay,
+ -hicpp-signed-bitwise,
+ -hicpp-special-member-functions,
-cert-err58-cpp,
-cert-err60-cpp'
CheckOptions:
- key: readability-function-cognitive-complexity.Threshold
- value: 100
\ No newline at end of file
+ value: 100
diff --git a/.gitmodules b/.gitmodules
index 6f6d0e10..815fc022 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "src/libs/lvgl"]
path = src/libs/lvgl
url = https://github.com/joaquimorg/lvgl.git
+[submodule "src/libs/littlefs"]
+ path = src/libs/littlefs
+ url = https://github.com/littlefs-project/littlefs.git
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 7bdfbcb1..9c99b664 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -12,6 +12,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1a488eaa..f2e467e9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.10)
-project(pinetime VERSION 1.1.0 LANGUAGES C CXX ASM)
+project(pinetime VERSION 1.2.0 LANGUAGES C CXX ASM)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 14)
diff --git a/README.md b/README.md
index 396d7462..bd23c867 100644
--- a/README.md
+++ b/README.md
@@ -53,6 +53,7 @@ As of now, here is the list of achievements of this project:
* Two (2048 clone game)
* Stopwatch (with all the necessary functions such as play, pause, lap, stop)
* Motion sensor and step counter (displays the number of steps and the state of the motion sensor in real-time)
+ * Metronome (vibrates to a given bpm with a customizable beats per bar)
- User settings:
* Display timeout
* Wake-up condition
@@ -62,7 +63,7 @@ As of now, here is the list of achievements of this project:
* Firmware validation
* System information
- Supported by 3 companion apps (development is in progress):
- * [Gadgetbridge](https://codeberg.org/Freeyourgadget/Gadgetbridge/) (on Android)
+ * [Gadgetbridge](https://codeberg.org/Freeyourgadget/Gadgetbridge/) (on Android via F-Droid)
* [Amazfish](https://openrepos.net/content/piggz/amazfish) (on SailfishOS and Linux)
* [Siglo](https://github.com/alexr4535/siglo) (on Linux)
* **[Experimental]** [WebBLEWatch](https://hubmartin.github.io/WebBLEWatch/) Synchronize time directly from your web browser. [video](https://youtu.be/IakiuhVDdrY)
diff --git a/doc/MemoryAnalysis.md b/doc/MemoryAnalysis.md
index 95bd611c..3251c98d 100644
--- a/doc/MemoryAnalysis.md
+++ b/doc/MemoryAnalysis.md
@@ -1,7 +1,274 @@
# Memory analysis
+The PineTime is equipped with the following memories:
+ - The internal RAM : **64KB**
+ - The internal Flash : **512KB**
+ - The external (SPI) Flash : **4MB**
+
+Note that the NRF52832 cannot execute code stored in the external flash : we need to store the whole firmware in the internal flash memory, and use the external one to store graphicals assets, fonts...
+
+This document describes how the RAM and Flash memories are used in InfiniTime and how to analyze and monitor their usage. It was written in the context of [this memory analysis effort](https://github.com/JF002/InfiniTime/issues/313).
+
+## Code sections
+A binary is composed of multiple sections. Most of the time, these sections are : .text, .rodata, .data and .bss but more sections can be defined in the linker script.
+
+Here is a small description of these sections and where they end up in memory:
+
+ - **TEXT** = code (FLASH)
+ - **RODATA** = constants (FLASH)
+ - **DATA** = initialized variables (FLASH + RAM)
+ - **BSS** = uninitialized variables (RAM)
+
+
+## Internal FLASH
+The internal flash memory stores the whole firmware: code, variable that are not default-initialized, constants...
+
+The content of the flash memory can be easily analyzed thanks to the MAP file generated by the compiler. This file lists all the symbols from the program along with their size and location (section and addresses) in RAM and FLASH.
+
+![Map file](./memoryAnalysis/mapfile.png)
+
+As you can see on the picture above, this file contains a lot of information and is not easily readable by a human being. Fortunately, you can easily find tools that parse and display the content of the MAP file in a more understandable way.
+
+In this analysis, I used [Linkermapviz](https://github.com/PromyLOPh/linkermapviz).
+
+### Linkermapviz
+
+[Linkermapviz](https://github.com/PromyLOPh/linkermapviz) parses the MAP file and displays its content in a graphical way into an HTML page:
+
+![linkermapviz](./memoryAnalysis/linkermapviz.png)
+
+Using this tool, you can easily see the size of each symbol relative to the other one, and check what is using most of the space,...
+
+Also, as Linkermapviz is written in Python, you can easily modify it to adapt it to your firmware, export data in another format,... For example, [I modified it to parse the contents of the MAP file and export it in a CSV file](https://github.com/JF002/InfiniTime/issues/313#issuecomment-842338620). I could later on open this file in LibreOffice Calc and use sort/filter functionality to search for specific symbols in specific files...
+
+### Puncover
+[Puncover](https://github.com/HBehrens/puncover) is another useful tools that analyses the binary file generated by the compiler (the .out file that contains all debug information). It provides valuable information about the symbols (data and code): name, position, size, max stack of each functions, callers, callees...
+![Puncover](./memoryAnalysis/puncover.png)
+
+Puncover is really easy to install:
+
+ - clone the repo and cd into the cloned directory
+ - setup a venv
+ - `python -m virtualenv venv`
+ - `source venv/bin/activate`
+ - Install : `pip install .`
+ - Run : `puncover --gcc_tools_base=/path/to/gcc-arm-none-eabi-9-2020-q2-update/bin/arm-none-eabi- --elf_file /path/to/build/directory/src/pinetime-app-1.1.0.out --src_root /path/to/sources --build_dir /path/to/build/directory`
+ - Replace
+ * `/path/to/gcc-arm-none-eabi-9-2020-q2-update/bin` with the path to your gcc-arm-none-eabi toolchain
+ * `/path/to/build/directory/src/pinetime-app-1.1.0.out` with the path to the binary generated by GCC (.out file)
+ * `/path/to/sources` with the path to the root folder of the sources (checkout directory)
+ * `/path/to/build/directory` with the path to the build directory
+ - Launch a browser at http://localhost:5000/
+
+### Analysis
+Using the MAP file and tools, we can easily see what symbols are using most of the FLASH memory space. In this case, with no surprise, fonts and graphics are the biggest flash space consumer.
+
+![Puncover](./memoryAnalysis/puncover-all-symbols.png)
+
+This way, you can easily check what needs to be optimized : we should find a way to store big static data (like fonts and graphics) in the external flash memory, for example.
+
+It's always a good idea to check the flash memory space when working on the project : this way, you can easily check that your developments are using a reasonable amount of space.
+
+### Links
+ - Analysis with linkermapviz : https://github.com/JF002/InfiniTime/issues/313#issuecomment-842338620
+ - Analysis with Puncover : https://github.com/JF002/InfiniTime/issues/313#issuecomment-847311392
+
+## RAM
+RAM memory contains all the data that can be modified at run-time: variables, stack, heap...
+
+### Data
+RAM memory can be *statically* allocated, meaning that the size and position of the data are known at compile-time:
+
+You can easily analyze the memory used by variables declared in the global scope using the MAP. You'll find them in the .BSS or .DATA sections. Linkermapviz and Puncover can be used to analyze their memory usage.
+
+Variables declared in the scope of a function will be allocated on the stack. It means that the stack usage will vary according to the state of the program, and cannot be easily analyzed at compile time.
+```
+uint8_t buffer[1024]
+
+int main() {
+ int a;
+}
+```
+
+#### Analysis
+In Infinitime 1.1, the biggest buffers are the buffers allocated for LVGL (14KB) and the one for FreeRTOS (16KB). Nimble also allocated 9KB of RAM.
+
+### Stack
+The stack will be used for everything except tasks, which have their own stack allocated by FreeRTOS. The stack is 8192B and is allocated in the [linker script](https://github.com/JF002/InfiniTime/blob/develop/nrf_common.ld#L148).
+An easy way to monitor its usage is by filling the section with a known pattern at boot time, then use the firmware and dump the memory. You can then check the maximum stack usage by checking the address from the beginning of the stack that were overwritten.
+
+#### Fill the stack section by a known pattern:
+Edit /modules/nrfx/mdk/gcc_startup_nrf52.S and add the following code after the copy of the data from read only memory to RAM at around line 243:
+
+```
+/* Loop to copy data from read only memory to RAM.
+ * The ranges of copy from/to are specified by following symbols:
+ * __etext: LMA of start of the section to copy from. Usually end of text
+ * __data_start__: VMA of start of the section to copy to.
+ * __bss_start__: VMA of end of the section to copy to. Normally __data_end__ is used, but by using __bss_start__
+ * the user can add their own initialized data section before BSS section with the INTERT AFTER command.
+ *
+ * All addresses must be aligned to 4 bytes boundary.
+ */
+ ldr r1, =__etext
+ ldr r2, =__data_start__
+ ldr r3, =__bss_start__
+
+ subs r3, r3, r2
+ ble .L_loop1_done
+
+.L_loop1:
+ subs r3, r3, #4
+ ldr r0, [r1,r3]
+ str r0, [r2,r3]
+ bgt .L_loop1
+
+.L_loop1_done:
+
+
+/* Add this code to fill the stack section with 0xFFEEDDBB */
+ldr r0, =__StackLimit
+ ldr r1, =8192
+ldr r2, =0xFFEEDDBB
+.L_fill:
+str r2, [r0]
+adds r0, 4
+subs r1, 4
+bne .L_fill
+/* -- */
+```
+
+#### Dump RAM memory and check usage
+Dumping the content of the ram is easy using JLink debugger and `nrfjprog`:
+
+```
+nrfjprog --readram ram.bin
+```
+
+You can then display the file using objdump:
+
+```
+hexdump ram.bin -v | less
+```
+
+The stack is positionned at the end of the RAM -> 0xFFFF. Its size is 8192 bytes, so the end of the stack is at 0xE000.
+On the following dump, the maximum stack usage is 520 bytes (0xFFFF - 0xFDF8):
+
+```
+000fdb0 ddbb ffee ddbb ffee ddbb ffee ddbb ffee
+000fdc0 ddbb ffee ddbb ffee ddbb ffee ddbb ffee
+000fdd0 ddbb ffee ddbb ffee ddbb ffee ddbb ffee
+000fde0 ddbb ffee ddbb ffee ddbb ffee ddbb ffee
+000fdf0 ddbb ffee ddbb ffee ffff ffff c24b 0003
+000fe00 ffff ffff ffff ffff ffff ffff 0000 0000
+000fe10 0018 0000 0000 0000 0000 0000 fe58 2000
+000fe20 0000 0000 0000 00ff ddbb 00ff 0018 0000
+000fe30 929c 2000 0000 0000 0018 0000 0000 0000
+000fe40 92c4 2000 0458 2000 0000 0000 80e7 0003
+000fe50 0000 0000 8cd9 0003 ddbb ffee ddbb ffee
+000fe60 00dc 2000 92c4 2000 0005 0000 929c 2000
+000fe70 007f 0000 feb0 2000 92c4 2000 feb8 2000
+000fe80 ddbb ffee 0005 0000 929c 2000 0000 0000
+000fe90 aca0 2000 0000 0000 0028 0000 418b 0005
+000fea0 02f4 2000 001f 0000 0000 0000 0013 0000
+000feb0 b5a8 2000 2199 0005 b5a8 2000 2201 0005
+000fec0 b5a8 2000 001e 0000 0000 0000 0013 0000
+000fed0 b5b0 2000 0fe0 0006 b5a8 2000 0000 0000
+000fee0 0013 0000 2319 0005 0013 0000 0000 0000
+000fef0 0000 0000 3b1c 2000 3b1c 2000 d0e3 0000
+000ff00 4b70 2000 54ac 2000 4b70 2000 ffff ffff
+000ff10 0000 0000 1379 0003 6578 2000 0d75 0003
+000ff20 6578 2000 ffff ffff 0000 0000 1379 0003
+000ff30 000c 0000 cfeb 0002 39a1 2000 a824 2000
+000ff40 0015 0000 cfeb 0002 39a1 2000 a824 2000
+000ff50 39a1 2000 0015 0000 001b 0000 b4b9 0002
+000ff60 0000 0000 a9f4 2000 4b70 2000 0d75 0003
+000ff70 4b70 2000 ffff ffff 0000 0000 1379 0003
+000ff80 ed00 e000 a820 2000 1000 4001 7fc0 2000
+000ff90 7f64 2000 75a7 0001 a884 2000 7b04 2000
+000ffa0 a8c0 2000 0000 0000 0000 0000 0000 0000
+000ffb0 7fc0 2000 7f64 2000 8024 2000 a5a5 a5a5
+000ffc0 ed00 e000 3fd5 0001 0000 0000 72c0 2000
+000ffd0 0000 0000 72e4 2000 3f65 0001 7f64 2000
+000ffe0 0000 2001 0000 0000 ef30 e000 0010 0000
+000fff0 7fc0 2000 4217 0001 3f0a 0001 0000 6100
+```
+
+#### Analysis
+According to my experimentations, we don't use the stack that much, and 8192 bytes is probably way too big for InfiniTime!
+
+#### Links
+ - https://github.com/JF002/InfiniTime/issues/313#issuecomment-851035070
+
+### Heap
+The heap is declared in the [linker script](https://github.com/JF002/InfiniTime/blob/develop/nrf_common.ld#L136) and its current size is 8192 bytes. The heap is used for dynamic memory allocation(`malloc()`, `new`...).
+
+Heap monitoring is not easy, but it seems that we can use the following code to know the current usage of the heap:
+
+```
+auto m = mallinfo();
+NRF_LOG_INFO("heap : %d", m.uordblks);
+```
+
+#### Analysis
+According to my experimentation, InfiniTime uses ~6000bytes of heap most of the time. Except when the Navigation app is launched, where the heap usage increases to... more than 9500 bytes (meaning that the heap overflows and could potentially corrupt the stack!!!). This is a bug that should be fixed in #362.
+
+To know exactly what's consuming heap memory, you can `wrap` functions like `malloc()` into your own functions. In this wrapper, you can add logging code or put breakpoints:
+
+- Add ` -Wl,-wrap,malloc` to the cmake variable `LINK_FLAGS` of the target you want to debug (pinetime-app, most probably)
+- Add the following code in `main.cpp`
+
+```
+extern "C" {
+void *__real_malloc (size_t);
+void* __wrap_malloc(size_t size) {
+ return __real_malloc(size);
+}
+}
+```
+Now, your function `__wrap_malloc()` will be called instead of `malloc()`. You can call the actual malloc from the stdlib by calling `__real_malloc()`.
+
+Using this technique, I was able to trace all malloc calls at boot (boot -> digital watchface):
+
+- system task = 3464 bytes (SystemTask could potentially be declared as a global variable to avoid heap allocation here)
+- string music = 31 (maybe we should not use std::string when not needed, as it does heap allocation)
+- ble_att_svr_start = 1720
+- ble gatts start = 40 + 88
+- ble ll task = 24
+- display app = 104
+- digital clock = 96 + 152
+- hr task = 304
+
+#### Links
+ - https://github.com/JF002/InfiniTime/issues/313#issuecomment-851035625
+ - https://www.embedded.com/mastering-stack-and-heap-for-system-reliability-part-1-calculating-stack-size/
+ - https://www.embedded.com/mastering-stack-and-heap-for-system-reliability-part-2-properly-allocating-stacks/
+ - https://www.embedded.com/mastering-stack-and-heap-for-system-reliability-part-3-avoiding-heap-errors/
+
+## LVGL
+I did a deep analysis of the usage of the buffer dedicated for lvgl (managed by lv_mem).
+This buffer is used by lvgl to allocated memory for drivers (display/touch), screens, themes, and all widgets created by the apps.
+
+The usage of this buffer can be monitored using this code :
+
+```
+lv_mem_monitor_t mon;
+lv_mem_monitor(&mon);
+NRF_LOG_INFO("\t Free %d / %d -- max %d", mon.free_size, mon.total_size, mon.max_used);
+```
+
+The most interesting metric is `mon.max_used` which specifies the maximum number of bytes that were used from this buffer since the initialization of lvgl.
+According to my measurements, initializing the theme, display/touch driver and screens cost **4752** bytes!
+Then, initializing the digital clock face costs **1541 bytes**.
+For example a simple lv_label needs **~140 bytes** of memory.
+
+I tried to monitor this max value while going through all the apps of InfiniTime 1.1 : the max value I've seen is **5660 bytes**. It means that we could probably **reduce the size of the buffer from 14KB to 6 - 10 KB** (we have to take the fragmentation of the memory into account).
+### Links
+ - https://github.com/JF002/InfiniTime/issues/313#issuecomment-850890064
+
+
## FreeRTOS heap and task stack
FreeRTOS statically allocate its own heap buffer in a global variable named `ucHeap`. This is an array of *uint8_t*. Its size is specified by the definition `configTOTAL_HEAP_SIZE` in *FreeRTOSConfig.h*
-FreeRTOS uses this buffer to allocate memory for tasks stack and all the RTOS object created during runtime (timers, mutexes,...).
+FreeRTOS uses this buffer to allocate memory for tasks stack and all the RTOS object created during runtime (timers, mutexes...).
The function `xPortGetFreeHeapSize()` returns the amount of memory available in this *ucHeap* buffer. If this value reaches 0, FreeRTOS runs out of memory.
@@ -20,59 +287,3 @@ for (int i = 0; i < nb; i++) {
```
-## Global heap
-Heap is used for **dynamic memory allocation (malloc() / new)**. NRF SDK defaults the heap size to 8KB. The size of the heap can be specified by defining `__HEAP_SIZE=8192` in *src/CMakeLists.txt*:
-
-```
-add_definitions(-D__HEAP_SIZE=8192)
-```
-
-You can trace the dynamic memory allocation by using the flag `--wrap` of the linker. When this flag is enabled, the linker will replace the calls to a specific function by a call to __wrap_the_function(). For example, if you specify `-Wl,-wrap,malloc` in the linker flags, the linker will replace all calls to `void* malloc(size_t)` by calls to `void* __wrap_malloc(size_t)`. This is a function you'll have to define in your code. In this function, you can call `__real_malloc()` to call the actual `malloc()' function.
-
-This technic allows you to wrap all calls to malloc() with you own code.
-
-In *src/CMakeLists.txt*:
-
-```
-set_target_properties(${EXECUTABLE_NAME} PROPERTIES
- ...
- LINK_FLAGS "-Wl,-wrap,malloc ..."
- ...
- )
-
-```
-
-In *main.cpp*:
-
-```
-uint32_t totalMalloc = 0;
-extern "C" {
- extern void* __real_malloc(size_t s);
- void *__wrap_malloc(size_t s) {
- totalMalloc += s;
- return __real_malloc(s);
- }
-}
-```
-This function sums all the memory that is allocated during the runtime. You can monitor or log this value. You can also place breakpoints in this function to determine where the dynamic memory allocation occurs in your code.
-
-
-# Global stack
-The stack is used to allocate memory used by functions : **parameters and local variables**. NRF SDK defaults the heap size to 8KB. The size of the heap can be specified by defining `__STACK_SIZE=8192` in *src/CMakeLists.txt*:
-
-```
-add_definitions(-D__STACK_SIZE=8192)
-```
-
-*NOTE*: FreeRTOS uses its own stack buffer. Thus, the global stack is only used for main() and IRQ handlers. It should be possible to reduce its size to a much lower value.
-
-**NOTE**: [?] How to track the global stack usage?
-
-#LittleVGL buffer
-*TODO*
-
-#NimBLE buffers
-*TODO*
-
-#Tools
- - https://github.com/eliotstock/memory : display the memory usage (FLASH/RAM) using the .map file from GCC.
diff --git a/doc/buildAndProgram.md b/doc/buildAndProgram.md
index afd526e0..5fe593ae 100644
--- a/doc/buildAndProgram.md
+++ b/doc/buildAndProgram.md
@@ -27,7 +27,7 @@ CMake configures the project according to variables you specify the command line
**NRFJPROG**|Path to the NRFJProg executable. Used only if `USE_JLINK` is 1.|`-DNRFJPROG=/opt/nrfjprog/nrfjprog`
**GDB_CLIENT_BIN_PATH**|Path to arm-none-eabi-gdb executable. Used only if `USE_GDB_CLIENT` is 1.|`-DGDB_CLIENT_BIN_PATH=/home/jf/nrf52/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-gdb`
**GDB_CLIENT_TARGET_REMOTE**|Target remote connection string. Used only if `USE_GDB_CLIENT` is 1.|`-DGDB_CLIENT_TARGET_REMOTE=/dev/ttyACM0`
-**BUILD_DFU (\*\*)**|Build DFU files while building (needs [adafruit-nrfutil](https://github.com/adafruit/Adafruit_nRF52_nrfutil)).|`-BUILD_DFU=1`
+**BUILD_DFU (\*\*)**|Build DFU files while building (needs [adafruit-nrfutil](https://github.com/adafruit/Adafruit_nRF52_nrfutil)).|`-DBUILD_DFU=1`
####(**) Note about **CMAKE_BUILD_TYPE**:
By default, this variable is set to *Release*. It compiles the code with size and speed optimizations. We use this value for all the binaries we publish when we [release](https://github.com/JF002/InfiniTime/releases) new versions of InfiniTime.
diff --git a/doc/buildWithDocker.md b/doc/buildWithDocker.md
index 7a2f3727..17fb53d9 100644
--- a/doc/buildWithDocker.md
+++ b/doc/buildWithDocker.md
@@ -13,7 +13,7 @@ Based on Ubuntu 18.04 with the following build dependencies:
The `infinitime-build` image contains all the dependencies you need. The default `CMD` will compile sources found in `/sources`, so you need only mount your code.
-This example will build the firmware, generate the MCUBoot image and generate the DFU file. Outputs will be written to **/build/output**:
+This example will build the firmware, generate the MCUBoot image and generate the DFU file. For cloning the repo, see [these instructions](../doc/buildAndProgram.md#clone-the-repo). Outputs will be written to **/build/output**:
```bash
cd # e.g. cd ./work/Pinetime
diff --git a/doc/companionapps/Amazfish.md b/doc/companionapps/Amazfish.md
index eb9daa04..90ad20c2 100644
--- a/doc/companionapps/Amazfish.md
+++ b/doc/companionapps/Amazfish.md
@@ -8,8 +8,9 @@ The following features are implemented:
- Time synchronization
- Notifications
- Music control
+ - Navigation with Puremaps
## Demo
[This video](https://seafile.codingfield.com/f/21c5d023452740279e36/) shows how to connect to the Pinetime and control the playback of the music on the phone.
Amazfish and Sailfish OS are running on the [Pinephone](https://www.pine64.org/pinephone/), another awesome device from Pine64.
-
\ No newline at end of file
+
diff --git a/doc/companionapps/Gadgetbridge.md b/doc/companionapps/Gadgetbridge.md
index 1a25069c..974e2828 100644
--- a/doc/companionapps/Gadgetbridge.md
+++ b/doc/companionapps/Gadgetbridge.md
@@ -1,7 +1,7 @@
# Integration with Gadgetbridge
[Gadgetbridge](https://gadgetbridge.org/) is an Android application that supports many smartwatches and fitness trackers.
-The integration of InfiniTime (previously Pinetime-JF) is now merged into the master branch (https://codeberg.org/Freeyourgadget/Gadgetbridge/).
+The integration of InfiniTime (previously Pinetime-JF) is now merged into the master branch (https://codeberg.org/Freeyourgadget/Gadgetbridge/) and initial support is available [starting with version 0.47](https://codeberg.org/Freeyourgadget/Gadgetbridge/src/branch/master/CHANGELOG.md). Note that the official version is only available on F-Droid (as of May 2021), and the unofficial fork available on the Play Store is outdated and does not support Infinitime.
## Features
The following features are implemented:
diff --git a/doc/filesInReleaseNotes.md b/doc/filesInReleaseNotes.md
index f48a0c10..78c20b51 100644
--- a/doc/filesInReleaseNotes.md
+++ b/doc/filesInReleaseNotes.md
@@ -1,16 +1,16 @@
# Using the releases
-For each new *stable* version of Pinetime, a [release note](https://github.com/JF002/InfiniTime/releases) is created. It contains a description of the main changes in the release and some files you can use to flash the firmware in your Pinetime.
+For each new *stable* version of IniniTime, a [release note](https://github.com/JF002/InfiniTime/releases) is created. It contains a description of the main changes in the release and some files you can use to flash the firmware to your Pinetime.
This page describes the files from the release notes and how to use them.
-**NOTE :** the files included in different could be different. This page describes the release note of [version 0.7.1](https://github.com/JF002/InfiniTime/releases/tag/0.7.1), which is the version that'll probably be pre-programmed at the factory for the next batch of Pinetime devkits.
+**NOTE :** the files included in different Releases could be different. This page describes the release notes of [version 0.7.1](https://github.com/JF002/InfiniTime/releases/tag/0.7.1), which is the version that is pre-programmed for the last batches of pinetimes but will be replaced with [1.0.0](https://github.com/jF002/infiniTime/releases/tag/1.0.0) around june 2021.
-## Files included in the release note
+## Files included in the release notes
### Standalone firmware
-This firmware is standalone, meaning that it does not need a bootloader to actually run. It is intended to be flash at offset 0, meaning it will erase any bootloader that might be present in memory.
+This firmware is standalone, meaning that it does not need a bootloader to actually run. It is intended to be flashed at offset 0, meaning it will erase any bootloader that might be present in memory.
- - **pinetime-app.out** : Output file of GCC containing debug symbols, useful is you want to debug the firmware using GDB.
+ - **pinetime-app.out** : Output file of GCC containing debug symbols, useful if you want to debug the firmware using GDB.
- **pinetime-app.hex** : Firmware in Intel HEX file format. Easier to use because it contains the offset in memory where it must be flashed, you don't need to specify it.
- **pintime-app.bin** : Firmware in binary format. When programming it, you have to specify the offset (0x00) in memory where it must be flashed.
- **pinetime-app.map** : Map file containing all the symbols, addresses in memory,...
@@ -38,7 +38,7 @@ This firmware is a small utility firmware that writes the boot graphic in the ex
### Firmware with bootloader
This firmware is intended to be used with our [MCUBoot-based bootloader](../bootloader/README.md).
- - **pinetime-mcuboot-app-image.hex** : Firmware wrapped into an MCUBoot image. This is **the** file that must be flashed **@ 0x8000** into flash memory. If the [bootloader](../bootloader/README.md) has been successfully programmed, it should run this firmware after the next reset.
+ - **pinetime-mcuboot-app-image.hex**: Firmware wrapped into an MCUBoot image. This is **the** file that must be flashed at **0x8000** into the flash memory. If the [bootloader](../bootloader/README.md) has been successfully programmed, it should run this firmware after the next reset.
The following files are not directly usable by the bootloader:
diff --git a/doc/memoryAnalysis/linkermapviz.png b/doc/memoryAnalysis/linkermapviz.png
new file mode 100644
index 00000000..8edfc8f9
Binary files /dev/null and b/doc/memoryAnalysis/linkermapviz.png differ
diff --git a/doc/memoryAnalysis/mapfile.png b/doc/memoryAnalysis/mapfile.png
new file mode 100644
index 00000000..0badd104
Binary files /dev/null and b/doc/memoryAnalysis/mapfile.png differ
diff --git a/doc/memoryAnalysis/puncover-all-symbols.png b/doc/memoryAnalysis/puncover-all-symbols.png
new file mode 100644
index 00000000..6a984248
Binary files /dev/null and b/doc/memoryAnalysis/puncover-all-symbols.png differ
diff --git a/doc/memoryAnalysis/puncover.png b/doc/memoryAnalysis/puncover.png
new file mode 100644
index 00000000..b32e1784
Binary files /dev/null and b/doc/memoryAnalysis/puncover.png differ
diff --git a/src/BootloaderVersion.cpp b/src/BootloaderVersion.cpp
index 5eba7a1d..07a1da4e 100644
--- a/src/BootloaderVersion.cpp
+++ b/src/BootloaderVersion.cpp
@@ -1,26 +1,36 @@
#include
+#include
#include "BootloaderVersion.h"
using namespace Pinetime;
-// NOTE : current bootloader does not export its version to the application firmware.
+// NOTE : version < 1.0.0 of bootloader does not export its version to the application firmware.
-uint32_t BootloaderVersion::Major() {
- return 0;
+uint32_t BootloaderVersion::version = 0;
+char BootloaderVersion::versionString[BootloaderVersion::VERSION_STR_LEN] = "0.0.0";
+
+const uint32_t BootloaderVersion::Major() {
+ return (BootloaderVersion::version >> 16u) & 0xff;
}
-uint32_t BootloaderVersion::Minor() {
- return 0;
+const uint32_t BootloaderVersion::Minor() {
+ return (BootloaderVersion::version >> 8u) & 0xff;
}
-uint32_t BootloaderVersion::Patch() {
- return 0;
+const uint32_t BootloaderVersion::Patch() {
+ return BootloaderVersion::version & 0xff;
}
const char* BootloaderVersion::VersionString() {
- return "0.0.0";
+ return BootloaderVersion::versionString;
}
-bool BootloaderVersion::IsValid() {
- return false;
+const bool BootloaderVersion::IsValid() {
+ return BootloaderVersion::version >= 0x00010000;
+}
+
+void BootloaderVersion::SetVersion(uint32_t v) {
+ BootloaderVersion::version = v;
+ snprintf(BootloaderVersion::versionString, BootloaderVersion::VERSION_STR_LEN, "%ld.%ld.%ld",
+ BootloaderVersion::Major(), BootloaderVersion::Minor(), BootloaderVersion::Patch());
}
diff --git a/src/BootloaderVersion.h b/src/BootloaderVersion.h
index c1ede0f5..f8127414 100644
--- a/src/BootloaderVersion.h
+++ b/src/BootloaderVersion.h
@@ -3,10 +3,15 @@
namespace Pinetime {
class BootloaderVersion {
public:
- static uint32_t Major();
- static uint32_t Minor();
- static uint32_t Patch();
+ static const uint32_t Major();
+ static const uint32_t Minor();
+ static const uint32_t Patch();
static const char* VersionString();
- static bool IsValid();
+ static const bool IsValid();
+ static void SetVersion(uint32_t v);
+ private:
+ static uint32_t version;
+ static constexpr size_t VERSION_STR_LEN = 12;
+ static char versionString[VERSION_STR_LEN];
};
-}
\ No newline at end of file
+}
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index cd729921..40e1f2a5 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -166,6 +166,13 @@ set(NIMBLE_SRC
libs/mynewt-nimble/nimble/host/util/src/addr.c
)
+set(LITTLEFS_SRC
+ libs/littlefs/lfs_util.h
+ libs/littlefs/lfs.h
+ libs/littlefs/lfs_util.c
+ libs/littlefs/lfs.c
+ )
+
set(LVGL_SRC
libs/lv_conf.h
libs/lvgl/lvgl.h
@@ -235,6 +242,7 @@ set(LVGL_SRC
libs/lvgl/src/lv_widgets/lv_cont.h
libs/lvgl/src/lv_widgets/lv_cpicker.h
libs/lvgl/src/lv_widgets/lv_dropdown.h
+ libs/lvgl/src/lv_widgets/lv_gauge.h
libs/lvgl/src/lv_widgets/lv_img.h
libs/lvgl/src/lv_widgets/lv_imgbtn.h
libs/lvgl/src/lv_widgets/lv_keyboard.h
@@ -321,6 +329,7 @@ set(LVGL_SRC
libs/lvgl/src/lv_widgets/lv_cont.c
libs/lvgl/src/lv_widgets/lv_cpicker.c
libs/lvgl/src/lv_widgets/lv_dropdown.c
+ libs/lvgl/src/lv_widgets/lv_gauge.c
libs/lvgl/src/lv_widgets/lv_img.c
libs/lvgl/src/lv_widgets/lv_imgbtn.c
libs/lvgl/src/lv_widgets/lv_keyboard.c
@@ -396,6 +405,7 @@ list(APPEND SOURCE_FILES
displayapp/screens/FirmwareUpdate.cpp
displayapp/screens/Music.cpp
displayapp/screens/Navigation.cpp
+ displayapp/screens/Metronome.cpp
displayapp/screens/Motion.cpp
displayapp/screens/FirmwareValidation.cpp
displayapp/screens/ApplicationList.cpp
@@ -422,6 +432,7 @@ list(APPEND SOURCE_FILES
displayapp/icons/bg_clock.c
displayapp/screens/WatchFaceAnalog.cpp
displayapp/screens/WatchFaceDigital.cpp
+ displayapp/screens/PineTimeStyle.cpp
##
@@ -461,6 +472,7 @@ list(APPEND SOURCE_FILES
components/motor/MotorController.cpp
components/settings/Settings.cpp
components/timer/TimerController.cpp
+ components/fs/FS.cpp
drivers/Cst816s.cpp
FreeRTOS/port.c
FreeRTOS/port_cmsis_systick.c
@@ -472,6 +484,7 @@ list(APPEND SOURCE_FILES
displayapp/fonts/jetbrains_mono_76.c
displayapp/fonts/jetbrains_mono_42.c
displayapp/fonts/lv_font_sys_48.c
+ displayapp/fonts/open_sans_light.c
displayapp/lv_pinetime_theme.c
systemtask/SystemTask.cpp
@@ -531,7 +544,6 @@ list(APPEND RECOVERY_SOURCE_FILES
systemtask/SystemTask.cpp
drivers/TwiMaster.cpp
components/gfx/Gfx.cpp
- displayapp/icons/infinitime/infinitime-nb.c
components/rle/RleDecoder.cpp
components/heartrate/HeartRateController.cpp
heartratetask/HeartRateTask.cpp
@@ -539,6 +551,7 @@ list(APPEND RECOVERY_SOURCE_FILES
components/heartrate/Biquad.cpp
components/heartrate/Ptagc.cpp
components/motor/MotorController.cpp
+ components/fs/FS.cpp
)
list(APPEND RECOVERYLOADER_SOURCE_FILES
@@ -558,7 +571,6 @@ list(APPEND RECOVERYLOADER_SOURCE_FILES
drivers/St7789.cpp
components/brightness/BrightnessController.cpp
- displayapp/icons/infinitime/infinitime-nb.c
recoveryLoader.cpp
)
@@ -592,6 +604,7 @@ set(INCLUDE_FILES
displayapp/Apps.h
displayapp/screens/Notifications.h
displayapp/screens/HeartRate.h
+ displayapp/screens/Metronome.h
displayapp/screens/Motion.h
displayapp/screens/Timer.h
drivers/St7789.h
@@ -750,8 +763,8 @@ add_definitions(-DNIMBLE_CFG_CONTROLLER)
add_definitions(-DOS_CPUTIME_FREQ)
add_definitions(-DNRF52 -DNRF52832 -DNRF52832_XXAA -DNRF52_PAN_74 -DNRF52_PAN_64 -DNRF52_PAN_12 -DNRF52_PAN_58 -DNRF52_PAN_54 -DNRF52_PAN_31 -DNRF52_PAN_51 -DNRF52_PAN_36 -DNRF52_PAN_15 -DNRF52_PAN_20 -DNRF52_PAN_55 -DBOARD_PCA10040)
add_definitions(-DFREERTOS)
-add_definitions(-D__STACK_SIZE=8192)
-add_definitions(-D__HEAP_SIZE=8192)
+add_definitions(-D__STACK_SIZE=1024)
+add_definitions(-D__HEAP_SIZE=4096)
# NOTE : Add the following defines to enable debug mode of the NRF SDK:
#add_definitions(-DDEBUG)
@@ -797,13 +810,25 @@ target_compile_options(lvgl PRIVATE
$<$: -MP -MD -x assembler-with-cpp>
)
+# LITTLEFS_SRC
+add_library(littlefs STATIC ${LITTLEFS_SRC})
+target_include_directories(littlefs SYSTEM PUBLIC . ../)
+target_include_directories(littlefs SYSTEM PUBLIC ${INCLUDES_FROM_LIBS})
+target_compile_options(littlefs PRIVATE
+ $<$,$>: ${COMMON_FLAGS} -Wno-unused-function -Og -g3>
+ $<$,$>: ${COMMON_FLAGS} -Wno-unused-function -Os>
+ $<$,$>: ${COMMON_FLAGS} -Wno-unused-function -Og -g3 -fno-rtti>
+ $<$,$>: ${COMMON_FLAGS} -Wno-unused-function -Os -fno-rtti>
+ $<$: -MP -MD -x assembler-with-cpp>
+ )
+
# Build autonomous binary (without support for bootloader)
set(EXECUTABLE_NAME "pinetime-app")
set(EXECUTABLE_FILE_NAME ${EXECUTABLE_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH})
set(NRF5_LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/gcc_nrf52.ld")
add_executable(${EXECUTABLE_NAME} ${SOURCE_FILES})
set_target_properties(${EXECUTABLE_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_FILE_NAME})
-target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl)
+target_link_libraries(${EXECUTABLE_NAME} nimble nrf-sdk lvgl littlefs)
target_compile_options(${EXECUTABLE_NAME} PUBLIC
$<$,$>: ${COMMON_FLAGS} -Og -g3>
$<$,$>: ${COMMON_FLAGS} -Os>
@@ -832,7 +857,7 @@ set(IMAGE_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-image-${pinetime_VERSION_
set(DFU_MCUBOOT_FILE_NAME ${EXECUTABLE_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip)
set(NRF5_LINKER_SCRIPT_MCUBOOT "${CMAKE_SOURCE_DIR}/gcc_nrf52-mcuboot.ld")
add_executable(${EXECUTABLE_MCUBOOT_NAME} ${SOURCE_FILES})
-target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl)
+target_link_libraries(${EXECUTABLE_MCUBOOT_NAME} nimble nrf-sdk lvgl littlefs)
set_target_properties(${EXECUTABLE_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_MCUBOOT_FILE_NAME})
target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC
$<$,$>: ${COMMON_FLAGS} -Og -g3>
@@ -868,7 +893,7 @@ endif()
set(EXECUTABLE_RECOVERY_NAME "pinetime-recovery")
set(EXECUTABLE_RECOVERY_FILE_NAME ${EXECUTABLE_RECOVERY_NAME}-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH})
add_executable(${EXECUTABLE_RECOVERY_NAME} ${RECOVERY_SOURCE_FILES})
-target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk)
+target_link_libraries(${EXECUTABLE_RECOVERY_NAME} nimble nrf-sdk littlefs)
set_target_properties(${EXECUTABLE_RECOVERY_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_FILE_NAME})
target_compile_definitions(${EXECUTABLE_RECOVERY_NAME} PUBLIC "PINETIME_IS_RECOVERY")
target_compile_options(${EXECUTABLE_RECOVERY_NAME} PUBLIC
@@ -898,7 +923,7 @@ set(EXECUTABLE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-${
set(IMAGE_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-image-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.bin)
set(DFU_RECOVERY_MCUBOOT_FILE_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}-dfu-${pinetime_VERSION_MAJOR}.${pinetime_VERSION_MINOR}.${pinetime_VERSION_PATCH}.zip)
add_executable(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} ${RECOVERY_SOURCE_FILES})
-target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk)
+target_link_libraries(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} nimble nrf-sdk littlefs)
set_target_properties(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PROPERTIES OUTPUT_NAME ${EXECUTABLE_RECOVERY_MCUBOOT_FILE_NAME})
target_compile_definitions(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC "PINETIME_IS_RECOVERY")
target_compile_options(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC
diff --git a/src/FreeRTOSConfig.h b/src/FreeRTOSConfig.h
index 15185766..adbbc8f0 100644
--- a/src/FreeRTOSConfig.h
+++ b/src/FreeRTOSConfig.h
@@ -62,7 +62,7 @@
#define configTICK_RATE_HZ 1024
#define configMAX_PRIORITIES (3)
#define configMINIMAL_STACK_SIZE (120)
-#define configTOTAL_HEAP_SIZE (1024 * 16)
+#define configTOTAL_HEAP_SIZE (1024 * 17)
#define configMAX_TASK_NAME_LEN (4)
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 1
@@ -77,7 +77,7 @@
#define configENABLE_BACKWARD_COMPATIBILITY 1
/* Hook function related definitions. */
-#define configUSE_IDLE_HOOK 1
+#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 0
#define configCHECK_FOR_STACK_OVERFLOW 0
#define configUSE_MALLOC_FAILED_HOOK 0
diff --git a/src/components/battery/BatteryController.cpp b/src/components/battery/BatteryController.cpp
index bc146457..fa476ea3 100644
--- a/src/components/battery/BatteryController.cpp
+++ b/src/components/battery/BatteryController.cpp
@@ -1,9 +1,7 @@
#include "BatteryController.h"
#include
#include
-#include
#include
-#include
using namespace Pinetime::Controllers;
@@ -14,16 +12,16 @@ Battery::Battery() {
}
void Battery::Init() {
- nrf_gpio_cfg_input(chargingPin, (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pullup);
+ nrf_gpio_cfg_input(chargingPin, static_cast GPIO_PIN_CNF_PULL_Pullup);
}
void Battery::Update() {
-
isCharging = !nrf_gpio_pin_read(chargingPin);
isPowerPresent = !nrf_gpio_pin_read(powerPresentPin);
- if (isReading)
+ if (isReading) {
return;
+ }
// Non blocking read
samples = 0;
isReading = true;
@@ -32,13 +30,13 @@ void Battery::Update() {
nrfx_saadc_sample();
}
-void Battery::adcCallbackStatic(nrfx_saadc_evt_t const* event) {
+void Battery::AdcCallbackStatic(nrfx_saadc_evt_t const* event) {
instance->SaadcEventHandler(event);
}
void Battery::SaadcInit() {
nrfx_saadc_config_t adcConfig = NRFX_SAADC_DEFAULT_CONFIG;
- APP_ERROR_CHECK(nrfx_saadc_init(&adcConfig, adcCallbackStatic));
+ APP_ERROR_CHECK(nrfx_saadc_init(&adcConfig, AdcCallbackStatic));
nrf_saadc_channel_config_t adcChannelConfig = {.resistor_p = NRF_SAADC_RESISTOR_DISABLED,
.resistor_n = NRF_SAADC_RESISTOR_DISABLED,
@@ -54,23 +52,23 @@ void Battery::SaadcInit() {
}
void Battery::SaadcEventHandler(nrfx_saadc_evt_t const* p_event) {
-
- const float battery_max = 4.18; // maximum voltage of battery ( max charging voltage is 4.21 )
- const float battery_min = 3.20; // minimum voltage of battery before shutdown ( depends on the battery )
+ const uint16_t battery_max = 4180; // maximum voltage of battery ( max charging voltage is 4.21 )
+ const uint16_t battery_min = 3200; // minimum voltage of battery before shutdown ( depends on the battery )
if (p_event->type == NRFX_SAADC_EVT_DONE) {
APP_ERROR_CHECK(nrfx_saadc_buffer_convert(&saadc_value, 1));
- voltage = (static_cast(p_event->data.done.p_buffer[0]) * 2.04f) / (1024 / 3.0f);
- voltage = roundf(voltage * 100) / 100;
-
- percentRemaining = static_cast(((voltage - battery_min) / (battery_max - battery_min)) * 100);
-
+ // A hardware voltage divider divides the battery voltage by 2
+ // ADC gain is 1/5
+ // thus adc_voltage = battery_voltage / 2 * gain = battery_voltage / 10
+ // reference_voltage is 0.6V
+ // p_event->data.done.p_buffer[0] = (adc_voltage / reference_voltage) * 1024
+ voltage = p_event->data.done.p_buffer[0] * 6000 / 1024;
+ percentRemaining = (voltage - battery_min) * 100 / (battery_max - battery_min);
percentRemaining = std::max(percentRemaining, 0);
percentRemaining = std::min(percentRemaining, 100);
-
- percentRemainingBuffer.insert(percentRemaining);
+ percentRemainingBuffer.Insert(percentRemaining);
samples++;
if (samples > percentRemainingSamples) {
diff --git a/src/components/battery/BatteryController.h b/src/components/battery/BatteryController.h
index 04bcf6b8..1333ad0e 100644
--- a/src/components/battery/BatteryController.h
+++ b/src/components/battery/BatteryController.h
@@ -19,7 +19,7 @@ namespace Pinetime {
insert member function overwrites the next data to the current
HEAD and moves the HEAD to the newly inserted value.
*/
- void insert(const int num) {
+ void Insert(const uint8_t num) {
head %= cap;
arr[head++] = num;
if (sz != cap) {
@@ -27,13 +27,13 @@ namespace Pinetime {
}
}
- int GetAverage() const {
+ uint8_t GetAverage() const {
int sum = std::accumulate(arr.begin(), arr.end(), 0);
- return (sum / sz);
+ return static_cast(sum / sz);
}
private:
- std::array arr; /**< internal array used to store the values*/
+ std::array 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*/
@@ -46,17 +46,21 @@ namespace Pinetime {
void Init();
void Update();
- int PercentRemaining() const {
- return percentRemainingBuffer.GetAverage();
+ uint8_t PercentRemaining() const {
+ auto avg = percentRemainingBuffer.GetAverage();
+ avg = std::min(avg, static_cast(100));
+ avg = std::max(avg, static_cast(0));
+ return avg;
}
- float Voltage() const {
+ uint16_t Voltage() const {
return voltage;
}
bool IsCharging() const {
return isCharging;
}
+
bool IsPowerPresent() const {
return isPowerPresent;
}
@@ -71,7 +75,7 @@ namespace Pinetime {
static constexpr uint32_t chargingPin = 12;
static constexpr uint32_t powerPresentPin = 19;
static constexpr nrf_saadc_input_t batteryVoltageAdcInput = NRF_SAADC_INPUT_AIN7;
- float voltage = 0.0f;
+ uint16_t voltage = 0;
int percentRemaining = -1;
bool isCharging = false;
@@ -80,10 +84,10 @@ namespace Pinetime {
void SaadcInit();
void SaadcEventHandler(nrfx_saadc_evt_t const* p_event);
- static void adcCallbackStatic(nrfx_saadc_evt_t const* event);
+ static void AdcCallbackStatic(nrfx_saadc_evt_t const* event);
bool isReading = false;
uint8_t samples = 0;
};
}
-}
\ No newline at end of file
+}
diff --git a/src/components/ble/AlertNotificationClient.cpp b/src/components/ble/AlertNotificationClient.cpp
index 6043a129..c3d1d69a 100644
--- a/src/components/ble/AlertNotificationClient.cpp
+++ b/src/components/ble/AlertNotificationClient.cpp
@@ -159,7 +159,7 @@ void AlertNotificationClient::OnNotification(ble_gap_event* event) {
notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert;
notificationManager.Push(std::move(notif));
- systemTask.PushMessage(Pinetime::System::SystemTask::Messages::OnNewNotification);
+ systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification);
}
}
diff --git a/src/components/ble/AlertNotificationService.cpp b/src/components/ble/AlertNotificationService.cpp
index e9f5941e..d5fc7f65 100644
--- a/src/components/ble/AlertNotificationService.cpp
+++ b/src/components/ble/AlertNotificationService.cpp
@@ -79,7 +79,7 @@ int AlertNotificationService::OnAlert(uint16_t conn_handle, uint16_t attr_handle
break;
}
- auto event = Pinetime::System::SystemTask::Messages::OnNewNotification;
+ auto event = Pinetime::System::Messages::OnNewNotification;
notificationManager.Push(std::move(notif));
systemTask.PushMessage(event);
}
diff --git a/src/components/ble/BatteryInformationService.cpp b/src/components/ble/BatteryInformationService.cpp
index 10a78d67..7f176904 100644
--- a/src/components/ble/BatteryInformationService.cpp
+++ b/src/components/ble/BatteryInformationService.cpp
@@ -17,7 +17,7 @@ BatteryInformationService::BatteryInformationService(Controllers::Battery& batte
characteristicDefinition {{.uuid = (ble_uuid_t*) &batteryLevelUuid,
.access_cb = BatteryInformationServiceCallback,
.arg = this,
- .flags = BLE_GATT_CHR_F_READ,
+ .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
.val_handle = &batteryLevelHandle},
{0}},
serviceDefinition {
@@ -48,4 +48,8 @@ int BatteryInformationService::OnBatteryServiceRequested(uint16_t connectionHand
return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
return 0;
-}
\ No newline at end of file
+}
+void BatteryInformationService::NotifyBatteryLevel(uint16_t connectionHandle, uint8_t level) {
+ auto* om = ble_hs_mbuf_from_flat(&level, 1);
+ ble_gattc_notify_custom(connectionHandle, batteryLevelHandle, om);
+}
diff --git a/src/components/ble/BatteryInformationService.h b/src/components/ble/BatteryInformationService.h
index 7d060909..1303fd6c 100644
--- a/src/components/ble/BatteryInformationService.h
+++ b/src/components/ble/BatteryInformationService.h
@@ -17,7 +17,7 @@ namespace Pinetime {
void Init();
int OnBatteryServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context);
-
+ void NotifyBatteryLevel(uint16_t connectionHandle, uint8_t level);
private:
Controllers::Battery& batteryController;
static constexpr uint16_t batteryInformationServiceId {0x180F};
diff --git a/src/components/ble/DfuService.cpp b/src/components/ble/DfuService.cpp
index 2031668e..e6bcea81 100644
--- a/src/components/ble/DfuService.cpp
+++ b/src/components/ble/DfuService.cpp
@@ -121,6 +121,11 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf* om) {
NRF_LOG_INFO(
"[DFU] -> Start data received : SD size : %d, BT size : %d, app size : %d", softdeviceSize, bootloaderSize, applicationSize);
+ // wait until SystemTask has finished waking up all devices
+ while (systemTask.IsSleeping()) {
+ vTaskDelay(50); // 50ms
+ }
+
dfuImage.Erase();
uint8_t data[] {16, 1, 1};
@@ -205,7 +210,7 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf* om) {
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Running);
bleController.FirmwareUpdateTotalBytes(0xffffffffu);
bleController.FirmwareUpdateCurrentBytes(0);
- systemTask.PushMessage(Pinetime::System::SystemTask::Messages::BleFirmwareUpdateStarted);
+ systemTask.PushMessage(Pinetime::System::Messages::BleFirmwareUpdateStarted);
return 0;
} else {
NRF_LOG_INFO("[DFU] -> Start DFU, mode %d not supported!", imageType);
@@ -279,7 +284,7 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf* om) {
}
NRF_LOG_INFO("[DFU] -> Activate image and reset!");
bleController.StopFirmwareUpdate();
- systemTask.PushMessage(Pinetime::System::SystemTask::Messages::BleFirmwareUpdateFinished);
+ systemTask.PushMessage(Pinetime::System::Messages::BleFirmwareUpdateFinished);
Reset();
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated);
return 0;
@@ -304,7 +309,7 @@ void DfuService::Reset() {
notificationManager.Reset();
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
bleController.StopFirmwareUpdate();
- systemTask.PushMessage(Pinetime::System::SystemTask::Messages::BleFirmwareUpdateFinished);
+ systemTask.PushMessage(Pinetime::System::Messages::BleFirmwareUpdateFinished);
}
DfuService::NotificationManager::NotificationManager() {
diff --git a/src/components/ble/ImmediateAlertService.cpp b/src/components/ble/ImmediateAlertService.cpp
index fd6430af..820d3b6e 100644
--- a/src/components/ble/ImmediateAlertService.cpp
+++ b/src/components/ble/ImmediateAlertService.cpp
@@ -67,7 +67,7 @@ int ImmediateAlertService::OnAlertLevelChanged(uint16_t connectionHandle, uint16
notif.category = Pinetime::Controllers::NotificationManager::Categories::SimpleAlert;
notificationManager.Push(std::move(notif));
- systemTask.PushMessage(Pinetime::System::SystemTask::Messages::OnNewNotification);
+ systemTask.PushMessage(Pinetime::System::Messages::OnNewNotification);
}
}
diff --git a/src/components/ble/MusicService.cpp b/src/components/ble/MusicService.cpp
index 36bf2709..74fe9522 100644
--- a/src/components/ble/MusicService.cpp
+++ b/src/components/ble/MusicService.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2020 JF, Adam Pigg, Avamander
+/* Copyright (C) 2020-2021 JF, Adam Pigg, Avamander
This file is part of InfiniTime.
@@ -18,132 +18,103 @@
#include "MusicService.h"
#include "systemtask/SystemTask.h"
-int MSCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
- auto musicService = static_cast(arg);
- return musicService->OnCommand(conn_handle, attr_handle, ctxt);
+namespace {
+ // 0000yyxx-78fc-48fe-8e23-433b3a1942d0
+ constexpr ble_uuid128_t CharUuid(uint8_t x, uint8_t y) {
+ return ble_uuid128_t{
+ .u = {.type = BLE_UUID_TYPE_128},
+ .value = { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, x, y, 0x00, 0x00 }
+ };
+ }
+
+ // 00000000-78fc-48fe-8e23-433b3a1942d0
+ constexpr ble_uuid128_t BaseUuid() {
+ return CharUuid(0x00, 0x00);
+ }
+
+ constexpr ble_uuid128_t msUuid {BaseUuid()};
+
+ constexpr ble_uuid128_t msEventCharUuid {CharUuid(0x01, 0x00)};
+ constexpr ble_uuid128_t msStatusCharUuid {CharUuid(0x02, 0x00)};
+ constexpr ble_uuid128_t msArtistCharUuid {CharUuid(0x03, 0x00)};
+ constexpr ble_uuid128_t msTrackCharUuid {CharUuid(0x04, 0x00)};
+ constexpr ble_uuid128_t msAlbumCharUuid {CharUuid(0x05, 0x00)};
+ constexpr ble_uuid128_t msPositionCharUuid {CharUuid(0x06, 0x00)};
+ constexpr ble_uuid128_t msTotalLengthCharUuid {CharUuid(0x07, 0x00)};
+ constexpr ble_uuid128_t msTrackNumberCharUuid {CharUuid(0x08, 0x00)};
+ constexpr ble_uuid128_t msTrackTotalCharUuid {CharUuid(0x09, 0x00)};
+ constexpr ble_uuid128_t msPlaybackSpeedCharUuid {CharUuid(0x0a, 0x00)};
+ constexpr ble_uuid128_t msRepeatCharUuid {CharUuid(0x0b, 0x00)};
+ constexpr ble_uuid128_t msShuffleCharUuid {CharUuid(0x0c, 0x00)};
+
+ int MusicCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
+ return static_cast(arg)->OnCommand(conn_handle, attr_handle, ctxt);
+ }
}
Pinetime::Controllers::MusicService::MusicService(Pinetime::System::SystemTask& system) : m_system(system) {
- msUuid.value[14] = msId[0];
- msUuid.value[15] = msId[1];
-
- msEventCharUuid.value[12] = msEventCharId[0];
- msEventCharUuid.value[13] = msEventCharId[1];
- msEventCharUuid.value[14] = msId[0];
- msEventCharUuid.value[15] = msId[1];
-
- msStatusCharUuid.value[12] = msStatusCharId[0];
- msStatusCharUuid.value[13] = msStatusCharId[1];
- msStatusCharUuid.value[14] = msId[0];
- msStatusCharUuid.value[15] = msId[1];
-
- msTrackCharUuid.value[12] = msTrackCharId[0];
- msTrackCharUuid.value[13] = msTrackCharId[1];
- msTrackCharUuid.value[14] = msId[0];
- msTrackCharUuid.value[15] = msId[1];
-
- msArtistCharUuid.value[12] = msArtistCharId[0];
- msArtistCharUuid.value[13] = msArtistCharId[1];
- msArtistCharUuid.value[14] = msId[0];
- msArtistCharUuid.value[15] = msId[1];
-
- msAlbumCharUuid.value[12] = msAlbumCharId[0];
- msAlbumCharUuid.value[13] = msAlbumCharId[1];
- msAlbumCharUuid.value[14] = msId[0];
- msAlbumCharUuid.value[15] = msId[1];
-
- msPositionCharUuid.value[12] = msPositionCharId[0];
- msPositionCharUuid.value[13] = msPositionCharId[1];
- msPositionCharUuid.value[14] = msId[0];
- msPositionCharUuid.value[15] = msId[1];
-
- msTotalLengthCharUuid.value[12] = msTotalLengthCharId[0];
- msTotalLengthCharUuid.value[13] = msTotalLengthCharId[1];
- msTotalLengthCharUuid.value[14] = msId[0];
- msTotalLengthCharUuid.value[15] = msId[1];
-
- msTrackNumberCharUuid.value[12] = msTrackNumberCharId[0];
- msTrackNumberCharUuid.value[13] = msTrackNumberCharId[1];
- msTrackNumberCharUuid.value[14] = msId[0];
- msTrackNumberCharUuid.value[15] = msId[1];
-
- msTrackTotalCharUuid.value[12] = msTrackTotalCharId[0];
- msTrackTotalCharUuid.value[13] = msTrackTotalCharId[1];
- msTrackTotalCharUuid.value[14] = msId[0];
- msTrackTotalCharUuid.value[15] = msId[1];
-
- msPlaybackSpeedCharUuid.value[12] = msPlaybackSpeedCharId[0];
- msPlaybackSpeedCharUuid.value[13] = msPlaybackSpeedCharId[1];
- msPlaybackSpeedCharUuid.value[14] = msId[0];
- msPlaybackSpeedCharUuid.value[15] = msId[1];
-
- msRepeatCharUuid.value[12] = msRepeatCharId[0];
- msRepeatCharUuid.value[13] = msRepeatCharId[1];
- msRepeatCharUuid.value[14] = msId[0];
- msRepeatCharUuid.value[15] = msId[1];
-
- msShuffleCharUuid.value[12] = msShuffleCharId[0];
- msShuffleCharUuid.value[13] = msShuffleCharId[1];
- msShuffleCharUuid.value[14] = msId[0];
- msShuffleCharUuid.value[15] = msId[1];
-
- characteristicDefinition[0] = {.uuid = (ble_uuid_t*) (&msEventCharUuid),
- .access_cb = MSCallback,
+ characteristicDefinition[0] = {.uuid = &msEventCharUuid.u,
+ .access_cb = MusicCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_NOTIFY,
.val_handle = &eventHandle};
- characteristicDefinition[1] = {
- .uuid = (ble_uuid_t*) (&msStatusCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
- characteristicDefinition[2] = {
- .uuid = (ble_uuid_t*) (&msTrackCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
- characteristicDefinition[3] = {
- .uuid = (ble_uuid_t*) (&msArtistCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
- characteristicDefinition[4] = {
- .uuid = (ble_uuid_t*) (&msAlbumCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
- characteristicDefinition[5] = {
- .uuid = (ble_uuid_t*) (&msPositionCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
- characteristicDefinition[6] = {.uuid = (ble_uuid_t*) (&msTotalLengthCharUuid),
- .access_cb = MSCallback,
+ characteristicDefinition[1] = {.uuid = &msStatusCharUuid.u,
+ .access_cb = MusicCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
- characteristicDefinition[7] = {.uuid = (ble_uuid_t*) (&msTotalLengthCharUuid),
- .access_cb = MSCallback,
+ characteristicDefinition[2] = {.uuid = &msTrackCharUuid.u,
+ .access_cb = MusicCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
- characteristicDefinition[8] = {.uuid = (ble_uuid_t*) (&msTrackNumberCharUuid),
- .access_cb = MSCallback,
+ characteristicDefinition[3] = {.uuid = &msArtistCharUuid.u,
+ .access_cb = MusicCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
- characteristicDefinition[9] = {.uuid = (ble_uuid_t*) (&msTrackTotalCharUuid),
- .access_cb = MSCallback,
+ characteristicDefinition[4] = {.uuid = &msAlbumCharUuid.u,
+ .access_cb = MusicCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
- characteristicDefinition[10] = {.uuid = (ble_uuid_t*) (&msPlaybackSpeedCharUuid),
- .access_cb = MSCallback,
+ characteristicDefinition[5] = {.uuid = &msPositionCharUuid.u,
+ .access_cb = MusicCallback,
+ .arg = this,
+ .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
+ characteristicDefinition[6] = {.uuid = &msTotalLengthCharUuid.u,
+ .access_cb = MusicCallback,
+ .arg = this,
+ .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
+ characteristicDefinition[7] = {.uuid = &msTotalLengthCharUuid.u,
+ .access_cb = MusicCallback,
+ .arg = this,
+ .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
+ characteristicDefinition[8] = {.uuid = &msTrackNumberCharUuid.u,
+ .access_cb = MusicCallback,
+ .arg = this,
+ .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
+ characteristicDefinition[9] = {.uuid = &msTrackTotalCharUuid.u,
+ .access_cb = MusicCallback,
+ .arg = this,
+ .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
+ characteristicDefinition[10] = {.uuid = &msPlaybackSpeedCharUuid.u,
+ .access_cb = MusicCallback,
+ .arg = this,
+ .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
+ characteristicDefinition[11] = {.uuid = &msRepeatCharUuid.u,
+ .access_cb = MusicCallback,
+ .arg = this,
+ .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
+ characteristicDefinition[12] = {.uuid = &msShuffleCharUuid.u,
+ .access_cb = MusicCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
- characteristicDefinition[11] = {
- .uuid = (ble_uuid_t*) (&msRepeatCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
- characteristicDefinition[12] = {
- .uuid = (ble_uuid_t*) (&msShuffleCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[13] = {0};
- serviceDefinition[0] = {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = (ble_uuid_t*) &msUuid, .characteristics = characteristicDefinition};
+ serviceDefinition[0] = {
+ .type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &msUuid.u, .characteristics = characteristicDefinition};
serviceDefinition[1] = {0};
-
- artistName = "Waiting for";
- albumName = "";
- trackName = "track information..";
- playing = false;
- repeat = false;
- shuffle = false;
- playbackSpeed = 1.0f;
- trackProgress = 0;
- trackLength = 0;
}
void Pinetime::Controllers::MusicService::Init() {
- int res = 0;
+ uint8_t res = 0;
res = ble_gatts_count_cfg(serviceDefinition);
ASSERT(res == 0);
@@ -152,60 +123,67 @@ void Pinetime::Controllers::MusicService::Init() {
}
int Pinetime::Controllers::MusicService::OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) {
-
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
size_t notifSize = OS_MBUF_PKTLEN(ctxt->om);
- uint8_t data[notifSize + 1];
+ char data[notifSize + 1];
data[notifSize] = '\0';
os_mbuf_copydata(ctxt->om, 0, notifSize, data);
- char* s = (char*) &data[0];
- if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msArtistCharUuid) == 0) {
+ char* s = &data[0];
+ if (ble_uuid_cmp(ctxt->chr->uuid, &msArtistCharUuid.u) == 0) {
artistName = s;
- } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msTrackCharUuid) == 0) {
+ } else if (ble_uuid_cmp(ctxt->chr->uuid, &msTrackCharUuid.u) == 0) {
trackName = s;
- } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msAlbumCharUuid) == 0) {
+ } else if (ble_uuid_cmp(ctxt->chr->uuid, &msAlbumCharUuid.u) == 0) {
albumName = s;
- } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msStatusCharUuid) == 0) {
+ } else if (ble_uuid_cmp(ctxt->chr->uuid, &msStatusCharUuid.u) == 0) {
playing = s[0];
- } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msRepeatCharUuid) == 0) {
+ } else if (ble_uuid_cmp(ctxt->chr->uuid, &msRepeatCharUuid.u) == 0) {
repeat = s[0];
- } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msShuffleCharUuid) == 0) {
+ } else if (ble_uuid_cmp(ctxt->chr->uuid, &msShuffleCharUuid.u) == 0) {
shuffle = s[0];
- } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msPositionCharUuid) == 0) {
+ } else if (ble_uuid_cmp(ctxt->chr->uuid, &msPositionCharUuid.u) == 0) {
trackProgress = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
- } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msTotalLengthCharUuid) == 0) {
+ } else if (ble_uuid_cmp(ctxt->chr->uuid, &msTotalLengthCharUuid.u) == 0) {
trackLength = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
- } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msTrackNumberCharUuid) == 0) {
+ } else if (ble_uuid_cmp(ctxt->chr->uuid, &msTrackNumberCharUuid.u) == 0) {
trackNumber = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
- } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msTrackTotalCharUuid) == 0) {
+ } else if (ble_uuid_cmp(ctxt->chr->uuid, &msTrackTotalCharUuid.u) == 0) {
tracksTotal = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
- } else if (ble_uuid_cmp(ctxt->chr->uuid, (ble_uuid_t*) &msPlaybackSpeedCharUuid) == 0) {
+ } else if (ble_uuid_cmp(ctxt->chr->uuid, &msPlaybackSpeedCharUuid.u) == 0) {
playbackSpeed = static_cast(((s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3])) / 100.0f;
}
}
return 0;
}
-std::string Pinetime::Controllers::MusicService::getAlbum() {
+std::string Pinetime::Controllers::MusicService::getAlbum() const {
return albumName;
}
-std::string Pinetime::Controllers::MusicService::getArtist() {
+std::string Pinetime::Controllers::MusicService::getArtist() const {
return artistName;
}
-std::string Pinetime::Controllers::MusicService::getTrack() {
+std::string Pinetime::Controllers::MusicService::getTrack() const {
return trackName;
}
-bool Pinetime::Controllers::MusicService::isPlaying() {
+bool Pinetime::Controllers::MusicService::isPlaying() const {
return playing;
}
-float Pinetime::Controllers::MusicService::getPlaybackSpeed() {
+float Pinetime::Controllers::MusicService::getPlaybackSpeed() const {
return playbackSpeed;
}
+int Pinetime::Controllers::MusicService::getProgress() const {
+ return trackProgress;
+}
+
+int Pinetime::Controllers::MusicService::getTrackLength() const {
+ return trackLength;
+}
+
void Pinetime::Controllers::MusicService::event(char event) {
auto* om = ble_hs_mbuf_from_flat(&event, 1);
@@ -217,11 +195,3 @@ void Pinetime::Controllers::MusicService::event(char event) {
ble_gattc_notify_custom(connectionHandle, eventHandle, om);
}
-
-int Pinetime::Controllers::MusicService::getProgress() {
- return trackProgress;
-}
-
-int Pinetime::Controllers::MusicService::getTrackLength() {
- return trackLength;
-}
diff --git a/src/components/ble/MusicService.h b/src/components/ble/MusicService.h
index 5f5343e4..1ad9a420 100644
--- a/src/components/ble/MusicService.h
+++ b/src/components/ble/MusicService.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2020 JF, Adam Pigg, Avamander
+/* Copyright (C) 2020-2021 JF, Adam Pigg, Avamander
This file is part of InfiniTime.
@@ -26,16 +26,11 @@
#undef max
#undef min
-// 00000000-78fc-48fe-8e23-433b3a1942d0
-#define MUSIC_SERVICE_UUID_BASE \
- { 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00 }
-
namespace Pinetime {
namespace System {
class SystemTask;
}
namespace Controllers {
-
class MusicService {
public:
explicit MusicService(Pinetime::System::SystemTask& system);
@@ -46,19 +41,19 @@ namespace Pinetime {
void event(char event);
- std::string getArtist();
+ std::string getArtist() const;
- std::string getTrack();
+ std::string getTrack() const;
- std::string getAlbum();
+ std::string getAlbum() const;
- int getProgress();
+ int getProgress() const;
- int getTrackLength();
+ int getTrackLength() const;
- float getPlaybackSpeed();
+ float getPlaybackSpeed() const;
- bool isPlaying();
+ bool isPlaying() const;
static const char EVENT_MUSIC_OPEN = 0xe0;
static const char EVENT_MUSIC_PLAY = 0x00;
@@ -71,55 +66,26 @@ namespace Pinetime {
enum MusicStatus { NotPlaying = 0x00, Playing = 0x01 };
private:
- static constexpr uint8_t msId[2] = {0x00, 0x00};
- static constexpr uint8_t msEventCharId[2] = {0x01, 0x00};
- static constexpr uint8_t msStatusCharId[2] = {0x02, 0x00};
- static constexpr uint8_t msArtistCharId[2] = {0x03, 0x00};
- static constexpr uint8_t msTrackCharId[2] = {0x04, 0x00};
- static constexpr uint8_t msAlbumCharId[2] = {0x05, 0x00};
- static constexpr uint8_t msPositionCharId[2] = {0x06, 0x00};
- static constexpr uint8_t msTotalLengthCharId[2] = {0x07, 0x00};
- static constexpr uint8_t msTrackNumberCharId[2] = {0x08, 0x00};
- static constexpr uint8_t msTrackTotalCharId[2] = {0x09, 0x00};
- static constexpr uint8_t msPlaybackSpeedCharId[2] = {0x0a, 0x00};
- static constexpr uint8_t msRepeatCharId[2] = {0x0b, 0x00};
- static constexpr uint8_t msShuffleCharId[2] = {0x0c, 0x00};
-
- ble_uuid128_t msUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
-
- ble_uuid128_t msEventCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
- ble_uuid128_t msStatusCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
- ble_uuid128_t msArtistCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
- ble_uuid128_t msTrackCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
- ble_uuid128_t msAlbumCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
- ble_uuid128_t msPositionCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
- ble_uuid128_t msTotalLengthCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
- ble_uuid128_t msTrackNumberCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
- ble_uuid128_t msTrackTotalCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
- ble_uuid128_t msPlaybackSpeedCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
- ble_uuid128_t msRepeatCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
- ble_uuid128_t msShuffleCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
-
struct ble_gatt_chr_def characteristicDefinition[14];
struct ble_gatt_svc_def serviceDefinition[2];
- uint16_t eventHandle;
+ uint16_t eventHandle {};
- std::string artistName;
- std::string albumName;
- std::string trackName;
+ std::string artistName {"Waiting for"};
+ std::string albumName {};
+ std::string trackName {"track information.."};
- bool playing;
+ bool playing {false};
- int trackProgress;
- int trackLength;
- int trackNumber;
- int tracksTotal;
+ int trackProgress {0};
+ int trackLength {0};
+ int trackNumber {};
+ int tracksTotal {};
- float playbackSpeed;
+ float playbackSpeed {1.0f};
- bool repeat;
- bool shuffle;
+ bool repeat {false};
+ bool shuffle {false};
Pinetime::System::SystemTask& m_system;
};
diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp
index 67a6d691..5eb227bf 100644
--- a/src/components/ble/NimbleController.cpp
+++ b/src/components/ble/NimbleController.cpp
@@ -149,7 +149,7 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) {
bleController.Disconnect();
} else {
bleController.Connect();
- systemTask.PushMessage(Pinetime::System::SystemTask::Messages::BleConnected);
+ systemTask.PushMessage(Pinetime::System::Messages::BleConnected);
connectionHandle = event->connect.conn_handle;
// Service discovery is deffered via systemtask
}
@@ -235,3 +235,9 @@ void NimbleController::StartDiscovery() {
uint16_t NimbleController::connHandle() {
return connectionHandle;
}
+
+void NimbleController::NotifyBatteryLevel(uint8_t level) {
+ if(connectionHandle != BLE_HS_CONN_HANDLE_NONE) {
+ batteryInformationService.NotifyBatteryLevel(connectionHandle, level);
+ }
+}
diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h
index 5dd01e42..0cfe983c 100644
--- a/src/components/ble/NimbleController.h
+++ b/src/components/ble/NimbleController.h
@@ -70,6 +70,7 @@ namespace Pinetime {
};
uint16_t connHandle();
+ void NotifyBatteryLevel(uint8_t level);
private:
static constexpr const char* deviceName = "InfiniTime";
@@ -92,7 +93,7 @@ namespace Pinetime {
HeartRateService heartRateService;
uint8_t addrType; // 1 = Random, 0 = PUBLIC
- uint16_t connectionHandle = 0;
+ uint16_t connectionHandle = BLE_HS_CONN_HANDLE_NONE;
ble_uuid128_t dfuServiceUuid {
.u {.type = BLE_UUID_TYPE_128},
diff --git a/src/components/datetime/DateTimeController.cpp b/src/components/datetime/DateTimeController.cpp
index 4f9302eb..28a70abc 100644
--- a/src/components/datetime/DateTimeController.cpp
+++ b/src/components/datetime/DateTimeController.cpp
@@ -5,9 +5,6 @@
using namespace Pinetime::Controllers;
-DateTime::DateTime(System::SystemTask& systemTask) : systemTask {systemTask} {
-}
-
void DateTime::SetTime(
uint16_t year, uint8_t month, uint8_t day, uint8_t dayOfWeek, uint8_t hour, uint8_t minute, uint8_t second, uint32_t systickCounter) {
std::tm tm = {
@@ -70,7 +67,8 @@ void DateTime::UpdateTime(uint32_t systickCounter) {
// Notify new day to SystemTask
if (hour == 0 and not isMidnightAlreadyNotified) {
isMidnightAlreadyNotified = true;
- systemTask.PushMessage(System::SystemTask::Messages::OnNewDay);
+ if(systemTask != nullptr)
+ systemTask->PushMessage(System::Messages::OnNewDay);
} else if (hour != 0) {
isMidnightAlreadyNotified = false;
}
@@ -104,6 +102,10 @@ const char* DateTime::DayOfWeekShortToStringLow() {
return DateTime::DaysStringShortLow[(uint8_t) dayOfWeek];
}
+void DateTime::Register(Pinetime::System::SystemTask* systemTask) {
+ this->systemTask = systemTask;
+}
+
char const* DateTime::DaysStringLow[] = {"--", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
char const* DateTime::DaysStringShortLow[] = {"--", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
diff --git a/src/components/datetime/DateTimeController.h b/src/components/datetime/DateTimeController.h
index d0ae727e..265d6e9d 100644
--- a/src/components/datetime/DateTimeController.h
+++ b/src/components/datetime/DateTimeController.h
@@ -27,8 +27,6 @@ namespace Pinetime {
December
};
- DateTime(System::SystemTask& systemTask);
-
void SetTime(uint16_t year,
uint8_t month,
uint8_t day,
@@ -75,8 +73,9 @@ namespace Pinetime {
return uptime;
}
+ void Register(System::SystemTask* systemTask);
+
private:
- System::SystemTask& systemTask;
uint16_t year = 0;
Months month = Months::Unknown;
uint8_t day = 0;
@@ -90,6 +89,7 @@ namespace Pinetime {
std::chrono::seconds uptime {0};
bool isMidnightAlreadyNotified = false;
+ System::SystemTask* systemTask = nullptr;
static char const* DaysString[];
static char const* DaysStringShort[];
diff --git a/src/components/fs/FS.cpp b/src/components/fs/FS.cpp
new file mode 100644
index 00000000..857e6bf9
--- /dev/null
+++ b/src/components/fs/FS.cpp
@@ -0,0 +1,197 @@
+#include "FS.h"
+#include
+#include
+#include
+
+using namespace Pinetime::Controllers;
+
+FS::FS(Pinetime::Drivers::SpiNorFlash& driver) :
+ flashDriver{ driver },
+ lfsConfig{
+ .context = this,
+ .read = SectorRead,
+ .prog = SectorProg,
+ .erase = SectorErase,
+ .sync = SectorSync,
+
+ .read_size = 16,
+ .prog_size = 8,
+ .block_size = blockSize,
+ .block_count = size / blockSize,
+ .block_cycles = 1000u,
+
+ .cache_size = 16,
+ .lookahead_size = 16,
+
+ .name_max = 50,
+ .attr_max = 50,
+ }
+{ }
+
+
+void FS::Init() {
+
+ // try mount
+ int err = lfs_mount(&lfs, &lfsConfig);
+
+ // reformat if we can't mount the filesystem
+ // this should only happen on the first boot
+ if (err != LFS_ERR_OK) {
+ lfs_format(&lfs, &lfsConfig);
+ err = lfs_mount(&lfs, &lfsConfig);
+ if (err != LFS_ERR_OK) {
+ return;
+ }
+ }
+
+#ifndef PINETIME_IS_RECOVERY
+ VerifyResource();
+ LVGLFileSystemInit();
+#endif
+
+}
+
+void FS::VerifyResource() {
+ // validate the resource metadata
+ resourcesValid = true;
+}
+
+int FS::FileOpen(lfs_file_t* file_p, const char* fileName, const int flags) {
+ return lfs_file_open(&lfs, file_p, fileName, flags);
+}
+
+int FS::FileClose(lfs_file_t* file_p) {
+ return lfs_file_close(&lfs, file_p);
+}
+
+int FS::FileRead(lfs_file_t* file_p, uint8_t* buff, uint32_t size) {
+ return lfs_file_read(&lfs, file_p, buff, size);
+}
+
+int FS::FileWrite(lfs_file_t* file_p, const uint8_t* buff, uint32_t size) {
+ return lfs_file_write(&lfs, file_p, buff, size);
+}
+
+int FS::FileSeek(lfs_file_t* file_p, uint32_t pos) {
+ return lfs_file_seek(&lfs, file_p, pos, LFS_SEEK_SET);
+}
+
+int FS::FileDelete(const char* fileName) {
+ return lfs_remove(&lfs, fileName);
+}
+
+
+int FS::DirCreate(const char* path) {
+ return lfs_mkdir(&lfs, path);
+}
+
+// Delete directory and all files inside
+int FS::DirDelete(const char* path) {
+
+ lfs_dir_t lfs_dir;
+ lfs_info entryInfo;
+
+ int err;
+ err = lfs_dir_open(&lfs, &lfs_dir, path);
+ if (err) {
+ return err;
+ }
+ while (lfs_dir_read(&lfs, &lfs_dir, &entryInfo)) {
+ lfs_remove(&lfs, entryInfo.name);
+ }
+ lfs_dir_close(&lfs, &lfs_dir);
+ return LFS_ERR_OK;
+}
+
+/*
+
+ ----------- Interface between littlefs and SpiNorFlash -----------
+
+*/
+int FS::SectorSync(const struct lfs_config* c) {
+ return 0;
+}
+
+int FS::SectorErase(const struct lfs_config* c, lfs_block_t block) {
+ Pinetime::Controllers::FS& lfs = *(static_cast(c->context));
+ const size_t address = startAddress + (block * blockSize);
+ lfs.flashDriver.SectorErase(address);
+ return lfs.flashDriver.EraseFailed() ? -1 : 0;
+}
+
+int FS::SectorProg(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, const void* buffer, lfs_size_t size) {
+ Pinetime::Controllers::FS& lfs = *(static_cast(c->context));
+ const size_t address = startAddress + (block * blockSize) + off;
+ lfs.flashDriver.Write(address, (uint8_t*) buffer, size);
+ return lfs.flashDriver.ProgramFailed() ? -1 : 0;
+}
+
+int FS::SectorRead(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size) {
+ Pinetime::Controllers::FS& lfs = *(static_cast(c->context));
+ const size_t address = startAddress + (block * blockSize) + off;
+ lfs.flashDriver.Read(address, static_cast(buffer), size);
+ return 0;
+}
+
+/*
+
+ ----------- LVGL filesystem integration -----------
+
+*/
+
+namespace {
+ lv_fs_res_t lvglOpen(lv_fs_drv_t* drv, void* file_p, const char* path, lv_fs_mode_t mode) {
+
+ lfs_file_t* file = static_cast(file_p);
+ FS* filesys = static_cast(drv->user_data);
+ filesys->FileOpen(file, path, LFS_O_RDONLY);
+
+ if (file->type == 0) {
+ return LV_FS_RES_FS_ERR;
+ }
+ else {
+ return LV_FS_RES_OK;
+ }
+ }
+
+ lv_fs_res_t lvglClose(lv_fs_drv_t* drv, void* file_p) {
+ FS* filesys = static_cast(drv->user_data);
+ lfs_file_t* file = static_cast(file_p);
+ filesys->FileClose(file);
+
+ return LV_FS_RES_OK;
+ }
+
+ lv_fs_res_t lvglRead(lv_fs_drv_t* drv, void* file_p, void* buf, uint32_t btr, uint32_t* br) {
+ FS* filesys = static_cast(drv->user_data);
+ lfs_file_t* file = static_cast(file_p);
+ filesys->FileRead(file, static_cast(buf), btr);
+ *br = btr;
+ return LV_FS_RES_OK;
+ }
+
+ lv_fs_res_t lvglSeek(lv_fs_drv_t* drv, void* file_p, uint32_t pos) {
+ FS* filesys = static_cast(drv->user_data);
+ lfs_file_t* file = static_cast(file_p);
+ filesys->FileSeek(file, pos);
+ return LV_FS_RES_OK;
+ }
+}
+
+void FS::LVGLFileSystemInit() {
+
+ lv_fs_drv_t fs_drv;
+ lv_fs_drv_init(&fs_drv);
+
+ fs_drv.file_size = sizeof(lfs_file_t);
+ fs_drv.letter = 'F';
+ fs_drv.open_cb = lvglOpen;
+ fs_drv.close_cb = lvglClose;
+ fs_drv.read_cb = lvglRead;
+ fs_drv.seek_cb = lvglSeek;
+
+ fs_drv.user_data = this;
+
+ lv_fs_drv_register(&fs_drv);
+
+}
\ No newline at end of file
diff --git a/src/components/fs/FS.h b/src/components/fs/FS.h
new file mode 100644
index 00000000..1f2eb7e0
--- /dev/null
+++ b/src/components/fs/FS.h
@@ -0,0 +1,71 @@
+#pragma once
+
+#include
+#include "drivers/SpiNorFlash.h"
+#include
+
+namespace Pinetime {
+ namespace Controllers {
+ class FS {
+ public:
+ FS(Pinetime::Drivers::SpiNorFlash&);
+
+ void Init();
+ void LVGLFileSystemInit();
+
+ int FileOpen(lfs_file_t* file_p, const char* fileName, const int flags);
+ int FileClose(lfs_file_t* file_p);
+ int FileRead(lfs_file_t* file_p, uint8_t* buff, uint32_t size);
+ int FileWrite(lfs_file_t* file_p, const uint8_t* buff, uint32_t size);
+ int FileSeek(lfs_file_t* file_p, uint32_t pos);
+
+ int FileDelete(const char* fileName);
+
+ int DirCreate(const char* path);
+ int DirDelete(const char* path);
+
+ void VerifyResource();
+
+ private:
+
+ Pinetime::Drivers::SpiNorFlash& flashDriver;
+
+ /*
+ * External Flash MAP (4 MBytes)
+ *
+ * 0x000000 +---------------------------------------+
+ * | Bootloader Assets |
+ * | 256 KBytes |
+ * | |
+ * 0x040000 +---------------------------------------+
+ * | OTA |
+ * | 464 KBytes |
+ * | |
+ * | |
+ * | |
+ * 0x0B4000 +---------------------------------------+
+ * | File System |
+ * | |
+ * | |
+ * | |
+ * | |
+ * 0x400000 +---------------------------------------+
+ *
+ */
+ static constexpr size_t startAddress = 0x0B4000;
+ static constexpr size_t size = 0x3C0000;
+ static constexpr size_t blockSize = 4096;
+
+ bool resourcesValid = false;
+ const struct lfs_config lfsConfig;
+
+ lfs_t lfs;
+
+ static int SectorSync(const struct lfs_config* c);
+ static int SectorErase(const struct lfs_config* c, lfs_block_t block);
+ static int SectorProg(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, const void* buffer, lfs_size_t size);
+ static int SectorRead(const struct lfs_config* c, lfs_block_t block, lfs_off_t off, void* buffer, lfs_size_t size);
+
+ };
+ }
+}
diff --git a/src/components/heartrate/HeartRateController.cpp b/src/components/heartrate/HeartRateController.cpp
index e84d665a..716813b3 100644
--- a/src/components/heartrate/HeartRateController.cpp
+++ b/src/components/heartrate/HeartRateController.cpp
@@ -4,9 +4,6 @@
using namespace Pinetime::Controllers;
-HeartRateController::HeartRateController(Pinetime::System::SystemTask& systemTask) : systemTask {systemTask} {
-}
-
void HeartRateController::Update(HeartRateController::States newState, uint8_t heartRate) {
this->state = newState;
if (this->heartRate != heartRate) {
diff --git a/src/components/heartrate/HeartRateController.h b/src/components/heartrate/HeartRateController.h
index d3a8460d..a63f1a70 100644
--- a/src/components/heartrate/HeartRateController.h
+++ b/src/components/heartrate/HeartRateController.h
@@ -15,8 +15,7 @@ namespace Pinetime {
public:
enum class States { Stopped, NotEnoughData, NoTouch, Running };
- explicit HeartRateController(System::SystemTask& systemTask);
-
+ HeartRateController() = default;
void Start();
void Stop();
void Update(States newState, uint8_t heartRate);
@@ -32,7 +31,6 @@ namespace Pinetime {
void SetService(Pinetime::Controllers::HeartRateService* service);
private:
- System::SystemTask& systemTask;
Applications::HeartRateTask* task = nullptr;
States state = States::Stopped;
uint8_t heartRate = 0;
diff --git a/src/components/heartrate/Ppg.cpp b/src/components/heartrate/Ppg.cpp
index da0789e0..fcba3815 100644
--- a/src/components/heartrate/Ppg.cpp
+++ b/src/components/heartrate/Ppg.cpp
@@ -38,9 +38,8 @@ namespace {
}
}
-Ppg::Ppg(float spl)
- : offset {spl},
- hpf {0.87033078, -1.74066156, 0.87033078, -1.72377617, 0.75754694},
+Ppg::Ppg()
+ : hpf {0.87033078, -1.74066156, 0.87033078, -1.72377617, 0.75754694},
agc {20, 0.971, 2},
lpf {0.11595249, 0.23190498, 0.11595249, -0.72168143, 0.18549138} {
}
@@ -67,13 +66,7 @@ float Ppg::HeartRate() {
dataIndex = 0;
return hr;
}
-
-int cccount = 0;
float Ppg::ProcessHeartRate() {
-
- if (cccount > 2)
- asm("nop");
- cccount++;
auto t0 = Trough(data.data(), dataIndex, 7, 48);
if (t0 < 0)
return 0;
diff --git a/src/components/heartrate/Ppg.h b/src/components/heartrate/Ppg.h
index ee07dfcf..00014162 100644
--- a/src/components/heartrate/Ppg.h
+++ b/src/components/heartrate/Ppg.h
@@ -8,8 +8,7 @@ namespace Pinetime {
namespace Controllers {
class Ppg {
public:
- explicit Ppg(float spl);
-
+ Ppg();
int8_t Preprocess(float spl);
float HeartRate();
diff --git a/src/components/motion/MotionController.cpp b/src/components/motion/MotionController.cpp
index e9ee314b..b0dbada4 100644
--- a/src/components/motion/MotionController.cpp
+++ b/src/components/motion/MotionController.cpp
@@ -34,3 +34,10 @@ bool MotionController::ShouldWakeUp(bool isSleeping) {
void MotionController::IsSensorOk(bool isOk) {
isSensorOk = isOk;
}
+void MotionController::Init(Pinetime::Drivers::Bma421::DeviceTypes types) {
+ switch(types){
+ case Drivers::Bma421::DeviceTypes::BMA421: this->deviceType = DeviceTypes::BMA421; break;
+ case Drivers::Bma421::DeviceTypes::BMA425: this->deviceType = DeviceTypes::BMA425; break;
+ default: this->deviceType = DeviceTypes::Unknown; break;
+ }
+}
diff --git a/src/components/motion/MotionController.h b/src/components/motion/MotionController.h
index 3a238262..ff715093 100644
--- a/src/components/motion/MotionController.h
+++ b/src/components/motion/MotionController.h
@@ -1,11 +1,18 @@
#pragma once
#include
+#include
namespace Pinetime {
namespace Controllers {
class MotionController {
public:
+ enum class DeviceTypes{
+ Unknown,
+ BMA421,
+ BMA425,
+ };
+
void Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps);
int16_t X() const {
@@ -27,6 +34,12 @@ namespace Pinetime {
return isSensorOk;
}
+ DeviceTypes DeviceType() const {
+ return deviceType;
+ }
+
+ void Init(Pinetime::Drivers::Bma421::DeviceTypes types);
+
private:
uint32_t nbSteps;
int16_t x;
@@ -34,6 +47,7 @@ namespace Pinetime {
int16_t z;
int16_t lastYForWakeUp = 0;
bool isSensorOk = false;
+ DeviceTypes deviceType = DeviceTypes::Unknown;
};
}
}
\ No newline at end of file
diff --git a/src/components/rle/RleDecoder.h b/src/components/rle/RleDecoder.h
index 0f607fb8..31c1ed10 100644
--- a/src/components/rle/RleDecoder.h
+++ b/src/components/rle/RleDecoder.h
@@ -21,7 +21,7 @@ namespace Pinetime {
const uint8_t* buffer;
size_t size;
- int encodedBufferIndex = 0;
+ size_t encodedBufferIndex = 0;
int y = 0;
uint16_t bp = 0;
uint16_t foregroundColor = 0xffff;
diff --git a/src/components/settings/Settings.cpp b/src/components/settings/Settings.cpp
index 071940b8..37c09f91 100644
--- a/src/components/settings/Settings.cpp
+++ b/src/components/settings/Settings.cpp
@@ -4,108 +4,44 @@
using namespace Pinetime::Controllers;
-struct SettingsHeader {
- uint8_t isActive; // 0xF1 = Block is active, 0xF0 = Block is inactive
- uint16_t version; // Current version, to verify if the saved data is for the current Version
-};
-
-#define HEADER_SIZE sizeof(SettingsHeader)
-
-Settings::Settings(Pinetime::Drivers::SpiNorFlash& spiNorFlash) : spiNorFlash {spiNorFlash} {
+Settings::Settings(Pinetime::Controllers::FS& fs) : fs {fs} {
}
void Settings::Init() {
// Load default settings from Flash
- LoadSettingsFromFlash();
+ LoadSettingsFromFile();
}
void Settings::SaveSettings() {
// verify if is necessary to save
if (settingsChanged) {
- SaveSettingsToFlash();
+ SaveSettingsToFile();
}
settingsChanged = false;
}
-bool Settings::FindHeader() {
- SettingsHeader settingsHeader;
- uint8_t bufferHead[sizeof(settingsHeader)];
+void Settings::LoadSettingsFromFile() {
+ SettingsData bufferSettings;
+ lfs_file_t settingsFile;
- for (uint8_t block = 0; block < 10; block++) {
-
- spiNorFlash.Read(settingsBaseAddr + (block * 0x1000), bufferHead, sizeof(settingsHeader));
- std::memcpy(&settingsHeader, bufferHead, sizeof(settingsHeader));
- if (settingsHeader.isActive == 0xF1 && settingsHeader.version == settingsVersion) {
- settingsFlashBlock = block;
- return true;
- }
+ if ( fs.FileOpen(&settingsFile, "/settings.dat", LFS_O_RDWR | LFS_O_CREAT) != LFS_ERR_OK) {
+ return;
}
- return false;
-}
-
-void Settings::ReadSettingsData() {
- uint8_t bufferSettings[sizeof(settings)];
- spiNorFlash.Read(settingsBaseAddr + (settingsFlashBlock * 0x1000) + HEADER_SIZE, bufferSettings, sizeof(settings));
- std::memcpy(&settings, bufferSettings, sizeof(settings));
-}
-
-void Settings::EraseBlock() {
-
- spiNorFlash.SectorErase(settingsBaseAddr + (settingsFlashBlock * 0x1000));
-}
-
-void Settings::SetHeader(bool state) {
- SettingsHeader settingsHeader;
- uint8_t bufferHead[sizeof(settingsHeader)];
- settingsHeader.isActive = state ? 0xF1 : 0xF0;
- settingsHeader.version = settingsVersion;
-
- std::memcpy(bufferHead, &settingsHeader, sizeof(settingsHeader));
- spiNorFlash.Write(settingsBaseAddr + (settingsFlashBlock * 0x1000), bufferHead, sizeof(settingsHeader));
-}
-
-void Settings::SaveSettingsData() {
- uint8_t bufferSettings[sizeof(settings)];
- std::memcpy(bufferSettings, &settings, sizeof(settings));
- spiNorFlash.Write(settingsBaseAddr + (settingsFlashBlock * 0x1000) + HEADER_SIZE, bufferSettings, sizeof(settings));
-}
-
-void Settings::LoadSettingsFromFlash() {
-
- if (settingsFlashBlock == 99) {
- // Find current Block, if can't find use default settings and set block to 0 ans save !
- if (FindHeader()) {
- ReadSettingsData();
- } else {
- SaveSettingsToFlash();
- }
- } else {
- // Read Settings from flash...
- // never used :)
- ReadSettingsData();
+ fs.FileRead(&settingsFile, reinterpret_cast(&bufferSettings), sizeof(settings));
+ fs.FileClose(&settingsFile);
+ if ( bufferSettings.version == settingsVersion ) {
+ settings = bufferSettings;
}
}
-void Settings::SaveSettingsToFlash() {
+void Settings::SaveSettingsToFile() {
+ lfs_file_t settingsFile;
- // calculate where to save...
- // mark current to inactive
- // erase the new location and save
- // set settingsFlashBlock
-
- // if first time hever, only saves to block 0 and set settingsFlashBlock
-
- if (settingsFlashBlock != 99) {
- SetHeader(false);
+ if ( fs.FileOpen(&settingsFile, "/settings.dat", LFS_O_RDWR | LFS_O_CREAT) != LFS_ERR_OK) {
+ return;
}
-
- settingsFlashBlock++;
- if (settingsFlashBlock > 9)
- settingsFlashBlock = 0;
-
- EraseBlock();
- SetHeader(true);
- SaveSettingsData();
+ fs.FileWrite(&settingsFile, reinterpret_cast(&settings), sizeof(settings));
+ fs.FileClose(&settingsFile);
}
diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h
index 4409425b..577455eb 100644
--- a/src/components/settings/Settings.h
+++ b/src/components/settings/Settings.h
@@ -2,25 +2,26 @@
#include
#include "components/datetime/DateTimeController.h"
#include "components/brightness/BrightnessController.h"
-#include "drivers/SpiNorFlash.h"
+#include "components/fs/FS.h"
#include "drivers/Cst816s.h"
namespace Pinetime {
namespace Controllers {
class Settings {
public:
- enum class ClockType { H24, H12 };
- enum class Vibration { ON, OFF };
- enum class WakeUpMode { None, SingleTap, DoubleTap, RaiseWrist };
+ enum class ClockType : uint8_t { H24, H12 };
+ enum class Vibration : uint8_t { ON, OFF };
+ enum class WakeUpMode : uint8_t { None, SingleTap, DoubleTap, RaiseWrist };
- Settings(Pinetime::Drivers::SpiNorFlash& spiNorFlash);
+ Settings(Pinetime::Controllers::FS& fs);
void Init();
void SaveSettings();
void SetClockFace(uint8_t face) {
- if (face != settings.clockFace)
+ if (face != settings.clockFace) {
settingsChanged = true;
+ }
settings.clockFace = face;
};
uint8_t GetClockFace() const {
@@ -42,8 +43,9 @@ namespace Pinetime {
};
void SetClockType(ClockType clocktype) {
- if (clocktype != settings.clockType)
+ if (clocktype != settings.clockType) {
settingsChanged = true;
+ }
settings.clockType = clocktype;
};
ClockType GetClockType() const {
@@ -51,8 +53,9 @@ namespace Pinetime {
};
void SetVibrationStatus(Vibration status) {
- if (status != settings.vibrationStatus)
+ if (status != settings.vibrationStatus) {
settingsChanged = true;
+ }
settings.vibrationStatus = status;
};
Vibration GetVibrationStatus() const {
@@ -60,8 +63,9 @@ namespace Pinetime {
};
void SetScreenTimeOut(uint32_t timeout) {
- if (timeout != settings.screenTimeOut)
+ if (timeout != settings.screenTimeOut) {
settingsChanged = true;
+ }
settings.screenTimeOut = timeout;
};
uint32_t GetScreenTimeOut() const {
@@ -69,8 +73,9 @@ namespace Pinetime {
};
void setWakeUpMode(WakeUpMode wakeUp) {
- if (wakeUp != settings.wakeUpMode)
+ if (wakeUp != settings.wakeUpMode) {
settingsChanged = true;
+ }
settings.wakeUpMode = wakeUp;
};
WakeUpMode getWakeUpMode() const {
@@ -78,8 +83,9 @@ namespace Pinetime {
};
void SetBrightness(Controllers::BrightnessController::Levels level) {
- if (level != settings.brightLevel)
+ if (level != settings.brightLevel) {
settingsChanged = true;
+ }
settings.brightLevel = level;
};
Controllers::BrightnessController::Levels GetBrightness() const {
@@ -87,25 +93,29 @@ namespace Pinetime {
};
void SetStepsGoal( uint32_t goal ) {
- if ( goal != settings.stepsGoal )
+ if ( goal != settings.stepsGoal ) {
settingsChanged = true;
+ }
settings.stepsGoal = goal;
};
uint32_t GetStepsGoal() const { return settings.stepsGoal; };
private:
- Pinetime::Drivers::SpiNorFlash& spiNorFlash;
+ Pinetime::Controllers::FS& fs;
+
+ static constexpr uint32_t settingsVersion = 0x0001;
struct SettingsData {
+ uint32_t version = settingsVersion;
+ uint32_t stepsGoal = 10000;
+ uint32_t screenTimeOut = 15000;
+
ClockType clockType = ClockType::H24;
Vibration vibrationStatus = Vibration::ON;
uint8_t clockFace = 0;
- uint32_t stepsGoal = 10000;
- uint32_t screenTimeOut = 15000;
-
WakeUpMode wakeUpMode = WakeUpMode::None;
Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium;
@@ -117,20 +127,8 @@ namespace Pinetime {
uint8_t appMenu = 0;
uint8_t settingsMenu = 0;
- // There are 10 blocks of reserved flash to save settings
- // to minimize wear, the recording is done in a rotating way by the 10 blocks
- uint8_t settingsFlashBlock = 99; // default to indicate it needs to find the active block
-
- static constexpr uint32_t settingsBaseAddr = 0x3F6000; // Flash Settings Location
- static constexpr uint16_t settingsVersion = 0x0100; // Flash Settings Version
-
- bool FindHeader();
- void ReadSettingsData();
- void EraseBlock();
- void SetHeader(bool state);
- void SaveSettingsData();
- void LoadSettingsFromFlash();
- void SaveSettingsToFlash();
+ void LoadSettingsFromFile();
+ void SaveSettingsToFile();
};
}
}
\ No newline at end of file
diff --git a/src/components/timer/TimerController.cpp b/src/components/timer/TimerController.cpp
index 3b25901c..8d5f5c33 100644
--- a/src/components/timer/TimerController.cpp
+++ b/src/components/timer/TimerController.cpp
@@ -12,14 +12,17 @@ using namespace Pinetime::Controllers;
APP_TIMER_DEF(timerAppTimer);
-
-TimerController::TimerController(System::SystemTask& systemTask) : systemTask{systemTask} {
+namespace {
+ void TimerEnd(void* p_context) {
+ auto* controller = static_cast (p_context);
+ if(controller != nullptr)
+ controller->OnTimerEnd();
+ }
}
void TimerController::Init() {
- app_timer_create(&timerAppTimer, APP_TIMER_MODE_SINGLE_SHOT, timerEnd);
-
+ app_timer_create(&timerAppTimer, APP_TIMER_MODE_SINGLE_SHOT, TimerEnd);
}
void TimerController::StartTimer(uint32_t duration) {
@@ -47,13 +50,6 @@ uint32_t TimerController::GetTimeRemaining() {
return (static_cast(deltaTicks) / static_cast(configTICK_RATE_HZ)) * 1000;
}
-void TimerController::timerEnd(void* p_context) {
-
- auto* controller = static_cast (p_context);
- controller->timerRunning = false;
- controller->systemTask.PushMessage(System::SystemTask::Messages::OnTimerDone);
-}
-
void TimerController::StopTimer() {
app_timer_stop(timerAppTimer);
timerRunning = false;
@@ -61,4 +57,13 @@ void TimerController::StopTimer() {
bool TimerController::IsRunning() {
return timerRunning;
-}
\ No newline at end of file
+}
+void TimerController::OnTimerEnd() {
+ timerRunning = false;
+ if(systemTask != nullptr)
+ systemTask->PushMessage(System::Messages::OnTimerDone);
+}
+
+void TimerController::Register(Pinetime::System::SystemTask* systemTask) {
+ this->systemTask = systemTask;
+}
diff --git a/src/components/timer/TimerController.h b/src/components/timer/TimerController.h
index 5a0b293e..fa7bc90d 100644
--- a/src/components/timer/TimerController.h
+++ b/src/components/timer/TimerController.h
@@ -12,7 +12,7 @@ namespace Pinetime {
class TimerController {
public:
- TimerController(Pinetime::System::SystemTask& systemTask);
+ TimerController() = default;
void Init();
@@ -23,12 +23,13 @@ namespace Pinetime {
uint32_t GetTimeRemaining();
bool IsRunning();
-
+
+ void OnTimerEnd();
+
+ void Register(System::SystemTask* systemTask);
+
private:
- System::SystemTask& systemTask;
-
- static void timerEnd(void* p_context);
-
+ System::SystemTask* systemTask = nullptr;
TickType_t endTicks;
bool timerRunning = false;
};
diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h
index 2df517f8..684e3a46 100644
--- a/src/displayapp/Apps.h
+++ b/src/displayapp/Apps.h
@@ -21,6 +21,7 @@ namespace Pinetime {
HeartRate,
Navigation,
StopWatch,
+ Metronome,
Motion,
Steps,
QuickSettings,
diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp
index b45822de..1aacefd2 100644
--- a/src/displayapp/DisplayApp.cpp
+++ b/src/displayapp/DisplayApp.cpp
@@ -18,6 +18,7 @@
#include "displayapp/screens/Paddle.h"
#include "displayapp/screens/StopWatch.h"
#include "displayapp/screens/Meter.h"
+#include "displayapp/screens/Metronome.h"
#include "displayapp/screens/Music.h"
#include "displayapp/screens/Navigation.h"
#include "displayapp/screens/Notifications.h"
@@ -32,6 +33,7 @@
#include "drivers/St7789.h"
#include "drivers/Watchdog.h"
#include "systemtask/SystemTask.h"
+#include "systemtask/Messages.h"
#include "displayapp/screens/settings/QuickSettings.h"
#include "displayapp/screens/settings/Settings.h"
@@ -44,6 +46,12 @@
using namespace Pinetime::Applications;
using namespace Pinetime::Applications::Display;
+namespace {
+ static inline bool in_isr(void) {
+ return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0;
+ }
+}
+
DisplayApp::DisplayApp(Drivers::St7789& lcd,
Components::LittleVgl& lvgl,
Drivers::Cst816S& touchPanel,
@@ -51,7 +59,6 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
Controllers::Ble& bleController,
Controllers::DateTime& dateTimeController,
Drivers::WatchdogView& watchdog,
- System::SystemTask& systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
Controllers::Settings& settingsController,
@@ -65,19 +72,20 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
bleController {bleController},
dateTimeController {dateTimeController},
watchdog {watchdog},
- systemTask {systemTask},
notificationManager {notificationManager},
heartRateController {heartRateController},
settingsController {settingsController},
motorController {motorController},
motionController {motionController},
timerController {timerController} {
- msgQueue = xQueueCreate(queueSize, itemSize);
- // Start clock when smartwatch boots
- LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::None);
}
void DisplayApp::Start() {
+ msgQueue = xQueueCreate(queueSize, itemSize);
+
+ // Start clock when smartwatch boots
+ LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::None);
+
if (pdPASS != xTaskCreate(DisplayApp::Process, "displayapp", 800, this, 0, &taskHandle)) {
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}
@@ -106,6 +114,7 @@ uint32_t count = 0;
bool toggle = true;
void DisplayApp::Refresh() {
TickType_t queueTimeout;
+ TickType_t delta;
switch (state) {
case States::Idle:
IdleState();
@@ -113,7 +122,11 @@ void DisplayApp::Refresh() {
break;
case States::Running:
RunningState();
- queueTimeout = 20;
+ delta = xTaskGetTickCount() - lastWakeTime;
+ if (delta > 20) {
+ delta = 20;
+ }
+ queueTimeout = 20 - delta;
break;
default:
queueTimeout = portMAX_DELAY;
@@ -121,7 +134,9 @@ void DisplayApp::Refresh() {
}
Messages msg;
- if (xQueueReceive(msgQueue, &msg, queueTimeout)) {
+ bool messageReceived = xQueueReceive(msgQueue, &msg, queueTimeout);
+ lastWakeTime = xTaskGetTickCount();
+ if (messageReceived) {
switch (msg) {
case Messages::GoToSleep:
brightnessController.Backup();
@@ -130,7 +145,7 @@ void DisplayApp::Refresh() {
vTaskDelay(100);
}
lcd.DisplayOff();
- systemTask.PushMessage(System::SystemTask::Messages::OnDisplayTaskSleeping);
+ PushMessageToSystemTask(Pinetime::System::Messages::OnDisplayTaskSleeping);
state = States::Idle;
break;
case Messages::GoToRunning:
@@ -139,7 +154,7 @@ void DisplayApp::Refresh() {
state = States::Running;
break;
case Messages::UpdateTimeOut:
- systemTask.PushMessage(System::SystemTask::Messages::UpdateTimeOut);
+ PushMessageToSystemTask(System::Messages::UpdateTimeOut);
break;
case Messages::UpdateBleConnection:
// clockScreen.SetBleConnectionState(bleController.IsConnected() ? Screens::Clock::BleConnectionStates::Connected :
@@ -177,7 +192,7 @@ void DisplayApp::Refresh() {
LoadApp(Apps::QuickSettings, DisplayApp::FullRefreshDirections::RightAnim);
break;
case TouchEvents::DoubleTap:
- systemTask.PushMessage(System::SystemTask::Messages::GoToSleep);
+ PushMessageToSystemTask(System::Messages::GoToSleep);
break;
default:
break;
@@ -193,7 +208,7 @@ void DisplayApp::Refresh() {
} break;
case Messages::ButtonPushed:
if (currentApp == Apps::Clock) {
- systemTask.PushMessage(System::SystemTask::Messages::GoToSleep);
+ PushMessageToSystemTask(System::Messages::GoToSleep);
} else {
if (!currentScreen->OnButtonPushed()) {
LoadApp(returnToApp, returnDirection);
@@ -211,6 +226,11 @@ void DisplayApp::Refresh() {
}
}
+ if(nextApp != Apps::None) {
+ LoadApp(nextApp, nextDirection);
+ nextApp = Apps::None;
+ }
+
if (state != States::Idle && touchMode == TouchModes::Polling) {
auto info = touchPanel.GetTouchInfo();
if (info.action == 2) { // 2 = contact
@@ -229,7 +249,8 @@ void DisplayApp::RunningState() {
}
void DisplayApp::StartApp(Apps app, DisplayApp::FullRefreshDirections direction) {
- LoadApp(app, direction);
+ nextApp = app;
+ nextDirection = direction;
}
void DisplayApp::ReturnApp(Apps app, DisplayApp::FullRefreshDirections direction, TouchEvents touchEvent) {
@@ -272,12 +293,12 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
case Apps::Notifications:
currentScreen = std::make_unique(
- this, notificationManager, systemTask.nimble().alertService(), Screens::Notifications::Modes::Normal);
+ this, notificationManager, systemTask->nimble().alertService(), Screens::Notifications::Modes::Normal);
ReturnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp);
break;
case Apps::NotificationsPreview:
currentScreen = std::make_unique(
- this, notificationManager, systemTask.nimble().alertService(), Screens::Notifications::Modes::Preview);
+ this, notificationManager, systemTask->nimble().alertService(), Screens::Notifications::Modes::Preview);
ReturnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp);
break;
case Apps::Timer:
@@ -310,7 +331,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
currentScreen = std::make_unique(this, settingsController);
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
- case Apps::SettingSteps:
+ case Apps::SettingSteps:
currentScreen = std::make_unique(this, settingsController);
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
@@ -320,17 +341,15 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
break;
case Apps::SysInfo:
currentScreen =
- std::make_unique(this, dateTimeController, batteryController, brightnessController, bleController, watchdog);
+ std::make_unique(this, dateTimeController, batteryController, brightnessController, bleController, watchdog, motionController);
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
- //
-
case Apps::FlashLight:
- currentScreen = std::make_unique(this, systemTask, brightnessController);
+ currentScreen = std::make_unique(this, *systemTask, brightnessController);
ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None);
break;
case Apps::StopWatch:
- currentScreen = std::make_unique(this);
+ currentScreen = std::make_unique(this, *systemTask);
break;
case Apps::Twos:
currentScreen = std::make_unique(this);
@@ -342,18 +361,21 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
currentScreen = std::make_unique(this, lvgl);
break;
case Apps::Music:
- currentScreen = std::make_unique(this, systemTask.nimble().music());
+ currentScreen = std::make_unique(this, systemTask->nimble().music());
break;
case Apps::Navigation:
- currentScreen = std::make_unique(this, systemTask.nimble().navigation());
+ currentScreen = std::make_unique(this, systemTask->nimble().navigation());
break;
case Apps::HeartRate:
- currentScreen = std::make_unique(this, heartRateController, systemTask);
+ currentScreen = std::make_unique(this, heartRateController, *systemTask);
+ break;
+ case Apps::Metronome:
+ currentScreen = std::make_unique(this, motorController, *systemTask);
break;
case Apps::Motion:
currentScreen = std::make_unique(this, motionController);
break;
- case Apps::Steps:
+ case Apps::Steps:
currentScreen = std::make_unique(this, motionController, settingsController);
break;
}
@@ -364,12 +386,15 @@ void DisplayApp::IdleState() {
}
void DisplayApp::PushMessage(Messages msg) {
- BaseType_t xHigherPriorityTaskWoken;
- xHigherPriorityTaskWoken = pdFALSE;
- xQueueSendFromISR(msgQueue, &msg, &xHigherPriorityTaskWoken);
- if (xHigherPriorityTaskWoken) {
- /* Actual macro used here is port specific. */
- // TODO : should I do something here?
+ if(in_isr()) {
+ BaseType_t xHigherPriorityTaskWoken;
+ xHigherPriorityTaskWoken = pdFALSE;
+ xQueueSendFromISR(msgQueue, &msg, &xHigherPriorityTaskWoken);
+ if (xHigherPriorityTaskWoken) {
+ portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+ }
+ } else {
+ xQueueSend(msgQueue, &msg, portMAX_DELAY);
}
}
@@ -426,3 +451,12 @@ void DisplayApp::SetFullRefresh(DisplayApp::FullRefreshDirections direction) {
void DisplayApp::SetTouchMode(DisplayApp::TouchModes mode) {
touchMode = mode;
}
+
+void DisplayApp::PushMessageToSystemTask(Pinetime::System::Messages message) {
+ if(systemTask != nullptr)
+ systemTask->PushMessage(message);
+}
+
+void DisplayApp::Register(Pinetime::System::SystemTask* systemTask) {
+ this->systemTask = systemTask;
+}
diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h
index 14cd7ad5..ae80be23 100644
--- a/src/displayapp/DisplayApp.h
+++ b/src/displayapp/DisplayApp.h
@@ -4,6 +4,7 @@
#include
#include
#include
+#include
#include "Apps.h"
#include "LittleVgl.h"
#include "TouchEvents.h"
@@ -49,7 +50,6 @@ namespace Pinetime {
Controllers::Ble& bleController,
Controllers::DateTime& dateTimeController,
Drivers::WatchdogView& watchdog,
- System::SystemTask& systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
Controllers::Settings& settingsController,
@@ -64,6 +64,8 @@ namespace Pinetime {
void SetFullRefresh(FullRefreshDirections direction);
void SetTouchMode(TouchModes mode);
+ void Register(Pinetime::System::SystemTask* systemTask);
+
private:
Pinetime::Drivers::St7789& lcd;
Pinetime::Components::LittleVgl& lvgl;
@@ -72,7 +74,7 @@ namespace Pinetime {
Pinetime::Controllers::Ble& bleController;
Pinetime::Controllers::DateTime& dateTimeController;
Pinetime::Drivers::WatchdogView& watchdog;
- Pinetime::System::SystemTask& systemTask;
+ Pinetime::System::SystemTask* systemTask = nullptr;
Pinetime::Controllers::NotificationManager& notificationManager;
Pinetime::Controllers::HeartRateController& heartRateController;
Pinetime::Controllers::Settings& settingsController;
@@ -108,6 +110,11 @@ namespace Pinetime {
void Refresh();
void ReturnApp(Apps app, DisplayApp::FullRefreshDirections direction, TouchEvents touchEvent);
void LoadApp(Apps app, DisplayApp::FullRefreshDirections direction);
+ void PushMessageToSystemTask(Pinetime::System::Messages message);
+
+ Apps nextApp = Apps::None;
+ DisplayApp::FullRefreshDirections nextDirection;
+ TickType_t lastWakeTime;
};
}
}
diff --git a/src/displayapp/DisplayAppRecovery.cpp b/src/displayapp/DisplayAppRecovery.cpp
index 856eafd8..fd517b11 100644
--- a/src/displayapp/DisplayAppRecovery.cpp
+++ b/src/displayapp/DisplayAppRecovery.cpp
@@ -14,7 +14,6 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
Controllers::Ble& bleController,
Controllers::DateTime& dateTimeController,
Drivers::WatchdogView& watchdog,
- System::SystemTask& systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
Controllers::Settings& settingsController,
@@ -22,10 +21,11 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
Pinetime::Controllers::MotionController& motionController,
Pinetime::Controllers::TimerController& timerController)
: lcd {lcd}, bleController {bleController} {
- msgQueue = xQueueCreate(queueSize, itemSize);
+
}
void DisplayApp::Start() {
+ msgQueue = xQueueCreate(queueSize, itemSize);
if (pdPASS != xTaskCreate(DisplayApp::Process, "displayapp", 512, this, 0, &taskHandle))
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}
@@ -113,4 +113,8 @@ void DisplayApp::PushMessage(Display::Messages msg) {
/* Actual macro used here is port specific. */
// TODO : should I do something here?
}
-}
\ No newline at end of file
+}
+
+void DisplayApp::Register(Pinetime::System::SystemTask* systemTask) {
+
+}
diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h
index 2c5a36fb..638c0071 100644
--- a/src/displayapp/DisplayAppRecovery.h
+++ b/src/displayapp/DisplayAppRecovery.h
@@ -39,7 +39,6 @@ namespace Pinetime {
Controllers::Ble& bleController,
Controllers::DateTime& dateTimeController,
Drivers::WatchdogView& watchdog,
- System::SystemTask& systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
Controllers::Settings& settingsController,
@@ -48,6 +47,7 @@ namespace Pinetime {
Pinetime::Controllers::TimerController& timerController);
void Start();
void PushMessage(Pinetime::Applications::Display::Messages msg);
+ void Register(Pinetime::System::SystemTask* systemTask);
private:
TaskHandle_t taskHandle;
diff --git a/src/displayapp/DummyLittleVgl.h b/src/displayapp/DummyLittleVgl.h
index 96cf153f..016165b8 100644
--- a/src/displayapp/DummyLittleVgl.h
+++ b/src/displayapp/DummyLittleVgl.h
@@ -19,6 +19,10 @@ namespace Pinetime {
LittleVgl(LittleVgl&&) = delete;
LittleVgl& operator=(LittleVgl&&) = delete;
+ void Init() {
+
+ }
+
void FlushDisplay(const lv_area_t* area, lv_color_t* color_p) {
}
bool GetTouchPadInfo(lv_indev_data_t* ptr) {
diff --git a/src/displayapp/LittleVgl.cpp b/src/displayapp/LittleVgl.cpp
index 36df51b4..c069afa2 100644
--- a/src/displayapp/LittleVgl.cpp
+++ b/src/displayapp/LittleVgl.cpp
@@ -23,6 +23,10 @@ bool touchpad_read(lv_indev_drv_t* indev_drv, lv_indev_data_t* data) {
LittleVgl::LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::Cst816S& touchPanel)
: lcd {lcd}, touchPanel {touchPanel}, previousClick {0, 0} {
+
+}
+
+void LittleVgl::Init() {
lv_init();
InitTheme();
InitDisplay();
diff --git a/src/displayapp/LittleVgl.h b/src/displayapp/LittleVgl.h
index 7f7b76e0..41f934a7 100644
--- a/src/displayapp/LittleVgl.h
+++ b/src/displayapp/LittleVgl.h
@@ -19,6 +19,8 @@ namespace Pinetime {
LittleVgl(LittleVgl&&) = delete;
LittleVgl& operator=(LittleVgl&&) = delete;
+ void Init();
+
void FlushDisplay(const lv_area_t* area, lv_color_t* color_p);
bool GetTouchPadInfo(lv_indev_data_t* ptr);
void SetFullRefresh(FullRefreshDirections direction);
diff --git a/src/displayapp/fonts/JetBrainsMono-Bold.ttf b/src/displayapp/fonts/JetBrainsMono-Bold.ttf
new file mode 100644
index 00000000..0cd1cb66
Binary files /dev/null and b/src/displayapp/fonts/JetBrainsMono-Bold.ttf differ
diff --git a/src/displayapp/fonts/README.md b/src/displayapp/fonts/README.md
index 183ad7e4..ec4beb88 100644
--- a/src/displayapp/fonts/README.md
+++ b/src/displayapp/fonts/README.md
@@ -2,6 +2,7 @@
* [Jetbrains Mono](https://www.jetbrains.com/fr-fr/lp/mono/)
* [Awesome font from LVGL](https://lvgl.io/assets/others/FontAwesome5-Solid+Brands+Regular.woff)
+* [Open Sans Light from Google](https://fonts.google.com/specimen/Open+Sans)
## Generate the fonts:
@@ -10,10 +11,12 @@
* Size : 20
* Bpp : 1 bit-per-pixel
* Do not enable font compression and horizontal subpixel hinting
-* Load the file `JetBrainsMono-Bold.tff` and specify the following range : `0x20-0x7f, 0x410-0x44f`
+* Load the file `JetBrainsMono-Bold.tff` (use the file in this repo to ensure the version matches) and specify the following range : `0x20-0x7f, 0x410-0x44f`
* Add a 2nd font, load the file `FontAwesome5-Solid+Brands+Regular.woff` and specify the following
- range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252`
+ range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252, 0xf569`
* Click on Convert, and download the file `jetbrains_mono_bold_20.c` and copy it in `src/DisplayApp/Fonts`
+* Add the font .c file path to src/CMakeLists.txt
+* Add an LV_FONT_DECLARE line in src/libs/lv_conf.h
Add new symbols:
@@ -28,6 +31,21 @@ Add new symbols:
static constexpr const char* newSymbol = "\xEF\x86\x85";
```
+## Simple method to generate a font
+
+If you want to generate a basic font containing only numbers and letters, you can use the above settings but instead of specifying a range, simply list the characters you need in the Symbols field and leave the range blank. This is the approach used for the PineTimeStyle watchface.
+This works well for fonts which will only be used to display numbers, but will fail if you try to add a colon or other punctuation.
+
+* Open the [LVGL font converter](https://lvgl.io/tools/fontconverter)
+* Name : open_sans_light
+* Size : 150
+* Bpp : 1 bit-per-pixel
+* Do not enable font compression and horizontal subpixel hinting
+* Load the file `open_sans_light.tff` (use the file in this repo to ensure the version matches) and specify the following symbols : `0123456789`
+* Click on Convert, and download the file `open_sans_light.c` and copy it in `src/DisplayApp/Fonts`
+* Add the font .c file path to src/CMakeLists.txt (search for jetbrains to find the appropriate location/format)
+* Add an LV_FONT_DECLARE line in src/libs/lv_conf.h (as above)
+
#### Navigation font
To create the navigtion.ttf I use the web app [icomoon](https://icomoon.io/app)
diff --git a/src/displayapp/fonts/jetbrains_mono_bold_20.c b/src/displayapp/fonts/jetbrains_mono_bold_20.c
index 9174ff48..98243bb4 100644
--- a/src/displayapp/fonts/jetbrains_mono_bold_20.c
+++ b/src/displayapp/fonts/jetbrains_mono_bold_20.c
@@ -1,11 +1,15 @@
-#include "lvgl/lvgl.h"
-
/*******************************************************************************
* Size: 20 px
* Bpp: 1
* Opts:
******************************************************************************/
+#ifdef LV_LVGL_H_INCLUDE_SIMPLE
+#include "lvgl.h"
+#else
+#include "lvgl/lvgl.h"
+#endif
+
#ifndef JETBRAINS_MONO_BOLD_20
#define JETBRAINS_MONO_BOLD_20 1
#endif
@@ -17,707 +21,707 @@
*----------------*/
/*Store the image of the glyphs*/
-static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = {
- /* U+20 " " */
+static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
+ /* U+0020 " " */
0x0,
- /* U+21 "!" */
+ /* U+0021 "!" */
0xff, 0xff, 0xff, 0xfc, 0xf, 0xc0,
- /* U+22 "\"" */
+ /* U+0022 "\"" */
0xef, 0xdf, 0xbf, 0x7e, 0xfd, 0xc0,
- /* U+23 "#" */
+ /* U+0023 "#" */
0x8, 0xc3, 0x10, 0x66, 0x3f, 0xf7, 0xfe, 0x23,
0x4, 0x61, 0x88, 0x31, 0x1f, 0xfb, 0xff, 0x19,
0x82, 0x30, 0xc4, 0x0,
- /* U+24 "$" */
- 0x8, 0x2, 0x0, 0x80, 0xfc, 0x7f, 0xba, 0x7e,
+ /* U+0024 "$" */
+ 0x8, 0x2, 0x0, 0x81, 0xfc, 0x7f, 0xba, 0x7e,
0x9f, 0xa0, 0xf8, 0x1f, 0x83, 0xf8, 0x3f, 0x9,
0xfa, 0x7e, 0x9d, 0xfe, 0x7f, 0x2, 0x0, 0x80,
0x20,
- /* U+25 "%" */
+ /* U+0025 "%" */
0x78, 0x3f, 0xc6, 0xcc, 0xcc, 0xcc, 0xfd, 0x87,
0xb0, 0x6, 0x0, 0x7e, 0xf, 0xf1, 0xb3, 0x33,
0x33, 0x33, 0x63, 0xfc, 0x1e,
- /* U+26 "&" */
+ /* U+0026 "&" */
0x1e, 0xf, 0xe1, 0x8e, 0x30, 0x6, 0x0, 0x60,
0x1e, 0x7, 0xe6, 0xed, 0xdc, 0xf3, 0x9e, 0x73,
- 0xcf, 0xfc, 0x79, 0x80,
+ 0xcf, 0xfc, 0xf9, 0x80,
- /* U+27 "'" */
+ /* U+0027 "'" */
0xff, 0xff, 0xc0,
- /* U+28 "(" */
+ /* U+0028 "(" */
0x2, 0x1c, 0x79, 0xc7, 0x1e, 0x38, 0x70, 0xe1,
0xc3, 0x87, 0xe, 0x1c, 0x3c, 0x38, 0x3c, 0x3c,
0x38,
- /* U+29 ")" */
+ /* U+0029 ")" */
0x1, 0xc3, 0xc3, 0xc1, 0xc3, 0xc3, 0x87, 0xe,
0x1c, 0x38, 0x70, 0xe1, 0xc7, 0xe, 0x79, 0xe3,
0x0,
- /* U+2A "*" */
+ /* U+002A "*" */
0xc, 0x3, 0x8, 0xc7, 0xb7, 0x7f, 0x83, 0x1,
0xe0, 0xcc, 0x73, 0x80, 0x0,
- /* U+2B "+" */
+ /* U+002B "+" */
0x1c, 0x7, 0x1, 0xc3, 0xff, 0xff, 0xc7, 0x1,
0xc0, 0x70, 0x1c, 0x0,
- /* U+2C "," */
+ /* U+002C "," */
0x7b, 0x9c, 0xce, 0x60,
- /* U+2D "-" */
+ /* U+002D "-" */
0xff, 0xf0,
- /* U+2E "." */
+ /* U+002E "." */
0xff, 0xf0,
- /* U+2F "/" */
+ /* U+002F "/" */
0x1, 0xc0, 0x60, 0x38, 0xe, 0x3, 0x1, 0xc0,
0x70, 0x18, 0xe, 0x3, 0x1, 0xc0, 0x70, 0x18,
0xe, 0x3, 0x80, 0xc0, 0x70, 0x18, 0xe, 0x0,
- /* U+30 "0" */
+ /* U+0030 "0" */
0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe1, 0xf8, 0x7f,
0xdf, 0xf7, 0xe1, 0xf8, 0x7e, 0x1f, 0xcf, 0x7f,
0x8f, 0xc0,
- /* U+31 "1" */
+ /* U+0031 "1" */
0x1e, 0x3f, 0x3b, 0x99, 0xc8, 0xe0, 0x70, 0x38,
0x1c, 0xe, 0x7, 0x3, 0x81, 0xcf, 0xff, 0xfc,
- /* U+32 "2" */
+ /* U+0032 "2" */
0x3e, 0x3f, 0xbc, 0xfc, 0x70, 0x38, 0x1c, 0x1c,
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0xf, 0xff, 0xfc,
- /* U+33 "3" */
+ /* U+0033 "3" */
0x7f, 0x9f, 0xe0, 0x30, 0x18, 0xc, 0x7, 0xc1,
0xf8, 0xf, 0x1, 0xc0, 0x7e, 0x1f, 0xcf, 0x7f,
0x8f, 0xc0,
- /* U+34 "4" */
+ /* U+0034 "4" */
0x7, 0x7, 0x3, 0x83, 0x83, 0x83, 0xc1, 0xcf,
0xe7, 0xe3, 0xff, 0xff, 0xe0, 0x70, 0x38, 0x1c,
- /* U+35 "5" */
+ /* U+0035 "5" */
0x7f, 0x9f, 0xe7, 0x1, 0xc0, 0x77, 0x1f, 0xe7,
0x3c, 0x7, 0x1, 0xc0, 0x77, 0x1d, 0xcf, 0x7f,
0x87, 0xc0,
- /* U+36 "6" */
+ /* U+0036 "6" */
0xe, 0x3, 0x1, 0xc0, 0x60, 0x38, 0x1d, 0xc7,
0xfb, 0xcf, 0xe1, 0xf8, 0x7e, 0x1f, 0xcf, 0x7f,
- 0x87, 0x80,
+ 0x8f, 0x80,
- /* U+37 "7" */
+ /* U+0037 "7" */
0xff, 0xff, 0xfe, 0x1f, 0x86, 0x3, 0x80, 0xe0,
0x30, 0x1c, 0x6, 0x3, 0x80, 0xc0, 0x70, 0x1c,
0x6, 0x0,
- /* U+38 "8" */
+ /* U+0038 "8" */
0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe1, 0xdc, 0xe3,
0xf0, 0xfc, 0x73, 0xb8, 0x7e, 0x1f, 0xcf, 0x7f,
0x8f, 0xc0,
- /* U+39 "9" */
+ /* U+0039 "9" */
0x1e, 0x1f, 0xef, 0x3f, 0x87, 0xe1, 0xf8, 0x7f,
0x3d, 0xfe, 0x3b, 0x81, 0xc0, 0x60, 0x38, 0xc,
0x7, 0x0,
- /* U+3A ":" */
+ /* U+003A ":" */
0xff, 0x80, 0x0, 0xff, 0x80,
- /* U+3B ";" */
+ /* U+003B ";" */
0x7b, 0xde, 0x0, 0x0, 0x0, 0x3, 0xdc, 0xe6,
0x73, 0x0,
- /* U+3C "<" */
+ /* U+003C "<" */
0x0, 0x81, 0xc3, 0xe7, 0xcf, 0x6, 0x3, 0xc0,
0x7c, 0xf, 0x81, 0xc0, 0x20,
- /* U+3D "=" */
+ /* U+003D "=" */
0xff, 0xff, 0xc0, 0x0, 0x0, 0x7, 0xff, 0xfe,
- /* U+3E ">" */
+ /* U+003E ">" */
0x80, 0x70, 0x3e, 0x7, 0xc0, 0xf8, 0xc, 0x1e,
0x3c, 0xf8, 0x70, 0x20, 0x0,
- /* U+3F "?" */
+ /* U+003F "?" */
0xfc, 0xfe, 0xf, 0x7, 0x7, 0xf, 0x3e, 0x3c,
0x30, 0x30, 0x0, 0x0, 0x70, 0x70,
- /* U+40 "@" */
+ /* U+0040 "@" */
0x1f, 0x7, 0xf9, 0xc3, 0x70, 0x3c, 0x7, 0x8f,
0xf3, 0xfe, 0x63, 0xcc, 0x79, 0x8f, 0x31, 0xe6,
0x3c, 0xff, 0x8e, 0xf8, 0x3, 0x80, 0x3e, 0x3,
0xc0,
- /* U+41 "A" */
+ /* U+0041 "A" */
0x1e, 0x7, 0x81, 0xe0, 0xfc, 0x3f, 0xc, 0xc3,
0x31, 0xce, 0x73, 0x9f, 0xe7, 0xfb, 0x87, 0xe1,
0xf0, 0x30,
- /* U+42 "B" */
+ /* U+0042 "B" */
0xfe, 0x3f, 0xce, 0x3b, 0x8e, 0xe3, 0xb8, 0xcf,
0xe3, 0xfc, 0xe3, 0xb8, 0x7e, 0x1f, 0x8f, 0xff,
0xbf, 0xc0,
- /* U+43 "C" */
+ /* U+0043 "C" */
0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe0, 0x38, 0xe,
0x3, 0x80, 0xe0, 0x38, 0xe, 0x1f, 0xcf, 0x7f,
0x8f, 0xc0,
- /* U+44 "D" */
+ /* U+0044 "D" */
0xfe, 0x7f, 0xb9, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f,
0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0xff, 0xf7, 0xf0,
- /* U+45 "E" */
+ /* U+0045 "E" */
0xff, 0xff, 0xf8, 0x1c, 0xe, 0x7, 0x3, 0xfd,
0xfe, 0xe0, 0x70, 0x38, 0x1c, 0xf, 0xff, 0xfc,
- /* U+46 "F" */
+ /* U+0046 "F" */
0xff, 0xff, 0xf8, 0x1c, 0xe, 0x7, 0x3, 0xff,
0xff, 0xe0, 0x70, 0x38, 0x1c, 0xe, 0x7, 0x0,
- /* U+47 "G" */
- 0x3f, 0x1f, 0xef, 0x1f, 0x87, 0xe0, 0x38, 0xe,
+ /* U+0047 "G" */
+ 0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe0, 0x38, 0xe,
0x7f, 0x9f, 0xe1, 0xf8, 0x7e, 0x1f, 0xcf, 0x7f,
0x8f, 0xc0,
- /* U+48 "H" */
+ /* U+0048 "H" */
0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0xff,
0xff, 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1c,
- /* U+49 "I" */
+ /* U+0049 "I" */
0xff, 0xff, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
0x1c, 0x1c, 0x1c, 0x1c, 0xff, 0xff,
- /* U+4A "J" */
+ /* U+004A "J" */
0x1f, 0xc7, 0xf0, 0x1c, 0x7, 0x1, 0xc0, 0x70,
0x1c, 0x7, 0x1, 0xc0, 0x7e, 0x1f, 0xcf, 0x7f,
0x8f, 0xc0,
- /* U+4B "K" */
+ /* U+004B "K" */
0xe1, 0xf8, 0x7e, 0x3b, 0x8e, 0xe7, 0x39, 0xcf,
0xe3, 0xf8, 0xe7, 0x39, 0xce, 0x3b, 0x8e, 0xe1,
0xf8, 0x70,
- /* U+4C "L" */
+ /* U+004C "L" */
0xe0, 0x70, 0x38, 0x1c, 0xe, 0x7, 0x3, 0x81,
0xc0, 0xe0, 0x70, 0x38, 0x1c, 0xf, 0xff, 0xfc,
- /* U+4D "M" */
+ /* U+004D "M" */
0xe1, 0xf8, 0x7f, 0x3f, 0xcf, 0xd2, 0xf7, 0xbd,
0xef, 0x33, 0xc0, 0xf0, 0x3c, 0xf, 0x3, 0xc0,
0xf0, 0x30,
- /* U+4E "N" */
- 0xe1, 0xf0, 0xfc, 0x7e, 0x3d, 0x9e, 0xcf, 0x67,
- 0x9b, 0xcd, 0xe6, 0xf1, 0xf8, 0xfc, 0x3e, 0x1c,
+ /* U+004E "N" */
+ 0xe1, 0xf0, 0xfc, 0x7e, 0x3f, 0x9e, 0xcf, 0x67,
+ 0x9b, 0xcd, 0xe6, 0xf1, 0xf8, 0xfc, 0x7e, 0x1c,
- /* U+4F "O" */
+ /* U+004F "O" */
0x3e, 0x3f, 0xb8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f,
0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x77, 0xf1, 0xf0,
- /* U+50 "P" */
+ /* U+0050 "P" */
0xff, 0x3f, 0xee, 0x3f, 0x87, 0xe1, 0xf8, 0xff,
0xfb, 0xfc, 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0,
0x38, 0x0,
- /* U+51 "Q" */
+ /* U+0051 "Q" */
0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe1, 0xf8, 0x7e,
0x1f, 0x87, 0xe1, 0xf8, 0x7e, 0x1f, 0xcf, 0x7f,
0x8f, 0x80, 0x70, 0xe, 0x3, 0x80, 0x70,
- /* U+52 "R" */
+ /* U+0052 "R" */
0xff, 0x3f, 0xee, 0x3f, 0x87, 0xe1, 0xf8, 0xff,
0xfb, 0xf8, 0xe6, 0x39, 0xce, 0x33, 0x8e, 0xe3,
0xb8, 0x70,
- /* U+53 "S" */
+ /* U+0053 "S" */
0x3f, 0x1f, 0xee, 0x3f, 0x87, 0xe0, 0x3c, 0x7,
0xf0, 0xfe, 0x3, 0xc0, 0x7e, 0x1f, 0xcf, 0x7f,
0x8f, 0xc0,
- /* U+54 "T" */
+ /* U+0054 "T" */
0xff, 0xff, 0xf0, 0xe0, 0x38, 0xe, 0x3, 0x80,
0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, 0x38, 0xe,
0x3, 0x80,
- /* U+55 "U" */
+ /* U+0055 "U" */
0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f,
0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x77, 0xf1, 0xf0,
- /* U+56 "V" */
+ /* U+0056 "V" */
0xc0, 0xf8, 0x7e, 0x1d, 0x86, 0x61, 0x9c, 0xe7,
0x38, 0xcc, 0x33, 0xf, 0xc3, 0xf0, 0x78, 0x1e,
0x7, 0x80,
- /* U+57 "W" */
+ /* U+0057 "W" */
0xce, 0x79, 0xcf, 0x29, 0xe5, 0x3c, 0xa7, 0xd5,
0xda, 0xb3, 0x56, 0x7b, 0xcf, 0x79, 0xef, 0x38,
0xe7, 0x1c, 0xe3, 0x80,
- /* U+58 "X" */
+ /* U+0058 "X" */
0xe1, 0xd8, 0x67, 0x38, 0xcc, 0x3f, 0x7, 0x81,
0xe0, 0x78, 0x1e, 0xf, 0xc3, 0x31, 0xce, 0xe1,
0xf8, 0x70,
- /* U+59 "Y" */
+ /* U+0059 "Y" */
0xe0, 0xfc, 0x1d, 0xc7, 0x38, 0xe3, 0xb8, 0x77,
0x6, 0xc0, 0xf8, 0xe, 0x1, 0xc0, 0x38, 0x7,
0x0, 0xe0, 0x1c, 0x0,
- /* U+5A "Z" */
+ /* U+005A "Z" */
0xff, 0xff, 0xc0, 0xe0, 0xe0, 0x70, 0x70, 0x70,
0x38, 0x38, 0x38, 0x1c, 0x1c, 0xf, 0xff, 0xfc,
- /* U+5B "[" */
+ /* U+005B "[" */
0xff, 0xfe, 0x38, 0xe3, 0x8e, 0x38, 0xe3, 0x8e,
0x38, 0xe3, 0x8e, 0x38, 0xff, 0xf0,
- /* U+5C "\\" */
+ /* U+005C "\\" */
0xe0, 0x18, 0x7, 0x1, 0xc0, 0x30, 0xe, 0x3,
0x80, 0x60, 0x1c, 0x3, 0x0, 0xe0, 0x38, 0x6,
0x1, 0xc0, 0x70, 0xc, 0x3, 0x80, 0x60, 0x1c,
- /* U+5D "]" */
+ /* U+005D "]" */
0xff, 0xf1, 0xc7, 0x1c, 0x71, 0xc7, 0x1c, 0x71,
0xc7, 0x1c, 0x71, 0xc7, 0xff, 0xf0,
- /* U+5E "^" */
+ /* U+005E "^" */
0xc, 0x7, 0x81, 0xe0, 0xfc, 0x33, 0x1c, 0xe6,
0x19, 0x86,
- /* U+5F "_" */
+ /* U+005F "_" */
0xff, 0xff, 0xf0,
- /* U+60 "`" */
+ /* U+0060 "`" */
0xe3, 0x8c,
- /* U+61 "a" */
+ /* U+0061 "a" */
0x1f, 0x1f, 0xe7, 0x1c, 0x7, 0x3f, 0xdf, 0xfe,
0x1f, 0x87, 0xe3, 0xff, 0xf3, 0xdc,
- /* U+62 "b" */
+ /* U+0062 "b" */
0xe0, 0x70, 0x38, 0x1d, 0xcf, 0xf7, 0x1f, 0x8f,
0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x7f, 0xf7, 0x70,
- /* U+63 "c" */
+ /* U+0063 "c" */
0x3e, 0x3f, 0xb8, 0xfc, 0x7e, 0x7, 0x3, 0x81,
0xc7, 0xe3, 0xbf, 0x8f, 0x80,
- /* U+64 "d" */
+ /* U+0064 "d" */
0x3, 0x81, 0xc0, 0xe7, 0x77, 0xff, 0x1f, 0x8f,
0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x77, 0xf9, 0xdc,
- /* U+65 "e" */
+ /* U+0065 "e" */
0x3e, 0x3f, 0xb8, 0xfc, 0x7f, 0xff, 0xff, 0x81,
0xc0, 0xe3, 0xbf, 0x8f, 0x80,
- /* U+66 "f" */
+ /* U+0066 "f" */
0xf, 0xc7, 0xf1, 0xc0, 0x70, 0xff, 0xff, 0xf1,
0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, 0x1c,
0x7, 0x0,
- /* U+67 "g" */
+ /* U+0067 "g" */
0x3b, 0xbf, 0xfd, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f,
0xc7, 0xf7, 0xbf, 0xce, 0xe0, 0x70, 0x39, 0xf8,
0xf8,
- /* U+68 "h" */
+ /* U+0068 "h" */
0xe0, 0x70, 0x38, 0x1d, 0xcf, 0xf7, 0x1f, 0x8f,
0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1c,
- /* U+69 "i" */
+ /* U+0069 "i" */
0x1c, 0x7, 0x1, 0xc0, 0x0, 0x0, 0x3f, 0xf,
0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, 0x1c,
0x7, 0xf, 0xff, 0xff,
- /* U+6A "j" */
+ /* U+006A "j" */
0x7, 0x7, 0x7, 0x0, 0xff, 0xff, 0x7, 0x7,
0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7, 0x7,
0xf, 0xfe, 0xfc,
- /* U+6B "k" */
+ /* U+006B "k" */
0xe0, 0x38, 0xe, 0x3, 0x87, 0xe3, 0xb8, 0xee,
0x73, 0xf8, 0xfe, 0x39, 0xce, 0x33, 0x8e, 0xe1,
0xb8, 0x70,
- /* U+6C "l" */
+ /* U+006C "l" */
0xfe, 0x1f, 0xc0, 0x38, 0x7, 0x0, 0xe0, 0x1c,
0x3, 0x80, 0x70, 0xe, 0x1, 0xc0, 0x38, 0x7,
0x0, 0x7e, 0x7, 0xc0,
- /* U+6D "m" */
+ /* U+006D "m" */
0xd9, 0xbf, 0xfc, 0xcf, 0x33, 0xcc, 0xf3, 0x3c,
0xcf, 0x33, 0xcc, 0xf3, 0x3c, 0xcc,
- /* U+6E "n" */
+ /* U+006E "n" */
0xee, 0x7f, 0xb8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f,
0xc7, 0xe3, 0xf1, 0xf8, 0xe0,
- /* U+6F "o" */
+ /* U+006F "o" */
0x3e, 0x3f, 0xb8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f,
0xc7, 0xe3, 0xbf, 0x8f, 0x80,
- /* U+70 "p" */
+ /* U+0070 "p" */
0xee, 0x7f, 0xb8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f,
0xc7, 0xe3, 0xff, 0xbb, 0x9c, 0xe, 0x7, 0x3,
0x80,
- /* U+71 "q" */
+ /* U+0071 "q" */
0x3b, 0xbf, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f,
0xc7, 0xe3, 0xbf, 0xce, 0xe0, 0x70, 0x38, 0x1c,
0xe,
- /* U+72 "r" */
- 0xee, 0x7f, 0xb8, 0xfc, 0x7e, 0x3f, 0x3, 0x81,
+ /* U+0072 "r" */
+ 0xee, 0x7f, 0xb9, 0xfc, 0x7e, 0x3f, 0x3, 0x81,
0xc0, 0xe0, 0x70, 0x38, 0x0,
- /* U+73 "s" */
+ /* U+0073 "s" */
0x1f, 0x1f, 0xf7, 0x1d, 0xc0, 0x7c, 0xf, 0xe0,
0x3c, 0x7, 0x71, 0xdf, 0xe3, 0xf0,
- /* U+74 "t" */
+ /* U+0074 "t" */
0x1c, 0x7, 0x1, 0xc3, 0xff, 0xff, 0xc7, 0x1,
0xc0, 0x70, 0x1c, 0x7, 0x1, 0xc0, 0x70, 0x1f,
0xc3, 0xf0,
- /* U+75 "u" */
+ /* U+0075 "u" */
0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f,
0xc7, 0xe3, 0xbf, 0x8f, 0x80,
- /* U+76 "v" */
+ /* U+0076 "v" */
0xe0, 0xf8, 0x76, 0x19, 0x86, 0x73, 0x8c, 0xc3,
0x30, 0xfc, 0x1e, 0x7, 0x81, 0xe0,
- /* U+77 "w" */
+ /* U+0077 "w" */
0xe6, 0x36, 0x66, 0x66, 0x66, 0xf6, 0x6f, 0x66,
0x96, 0x69, 0x62, 0x94, 0x39, 0xc3, 0x9c, 0x39,
0xc0,
- /* U+78 "x" */
+ /* U+0078 "x" */
0xe1, 0xdc, 0xe3, 0x30, 0xfc, 0x1e, 0x7, 0x81,
- 0xe0, 0xfc, 0x73, 0x9c, 0x6e, 0x1c,
+ 0xe0, 0xfc, 0x73, 0x9c, 0xee, 0x1c,
- /* U+79 "y" */
+ /* U+0079 "y" */
0xe1, 0xf8, 0x76, 0x19, 0xce, 0x73, 0x8c, 0xc3,
0xf0, 0x7c, 0x1e, 0x7, 0x80, 0xe0, 0x30, 0x1c,
0x6, 0x3, 0x80,
- /* U+7A "z" */
+ /* U+007A "z" */
0xff, 0xff, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
0xe0, 0xe0, 0x7f, 0xff, 0xe0,
- /* U+7B "{" */
+ /* U+007B "{" */
0x3, 0x87, 0xc3, 0x81, 0xc0, 0xe0, 0x70, 0x38,
0x1c, 0xfc, 0x7e, 0x3, 0x81, 0xc0, 0xe0, 0x70,
0x38, 0x1c, 0xf, 0x81, 0xc0,
- /* U+7C "|" */
+ /* U+007C "|" */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc,
- /* U+7D "}" */
+ /* U+007D "}" */
0xf0, 0x3e, 0x1, 0xc0, 0x70, 0x1c, 0x7, 0x1,
0xc0, 0x70, 0xf, 0xc3, 0xf1, 0xc0, 0x70, 0x1c,
0x7, 0x1, 0xc0, 0x70, 0xf8, 0x3c, 0x0,
- /* U+7E "~" */
+ /* U+007E "~" */
0x78, 0xff, 0x3c, 0xcf, 0x3f, 0xc7, 0x80,
- /* U+410 "А" */
+ /* U+0410 "А" */
0x1e, 0x7, 0x81, 0xe0, 0xfc, 0x3f, 0xc, 0xc3,
0x31, 0xce, 0x73, 0x9f, 0xe7, 0xfb, 0x87, 0xe1,
0xf0, 0x30,
- /* U+411 "Б" */
+ /* U+0411 "Б" */
0xff, 0xbf, 0xee, 0x3, 0x80, 0xe0, 0x3f, 0xcf,
0xfb, 0x8f, 0xe1, 0xf8, 0x7e, 0x1f, 0x8f, 0xff,
- 0xbf, 0x80,
+ 0xbf, 0xc0,
- /* U+412 "В" */
+ /* U+0412 "В" */
0xfe, 0x3f, 0xce, 0x3b, 0x8e, 0xe3, 0xb8, 0xcf,
0xe3, 0xfc, 0xe3, 0xb8, 0x7e, 0x1f, 0x8f, 0xff,
0xbf, 0xc0,
- /* U+413 "Г" */
+ /* U+0413 "Г" */
0xff, 0xff, 0xf8, 0x1c, 0xe, 0x7, 0x3, 0x81,
0xc0, 0xe0, 0x70, 0x38, 0x1c, 0xe, 0x7, 0x0,
- /* U+414 "Д" */
+ /* U+0414 "Д" */
0x3f, 0xc7, 0xf8, 0xe7, 0x1c, 0xe3, 0x9c, 0x73,
0x8e, 0x71, 0xce, 0x39, 0xc7, 0x38, 0xe7, 0x38,
0xef, 0xff, 0xff, 0xf8, 0x3f, 0x7, 0xe0, 0xe0,
- /* U+415 "Е" */
+ /* U+0415 "Е" */
0xff, 0xff, 0xf8, 0x1c, 0xe, 0x7, 0x3, 0xfd,
0xfe, 0xe0, 0x70, 0x38, 0x1c, 0xf, 0xff, 0xfc,
- /* U+416 "Ж" */
+ /* U+0416 "Ж" */
0xe6, 0x76, 0x66, 0x66, 0x67, 0x66, 0x36, 0xc3,
0x6c, 0x3f, 0xc3, 0x6c, 0x36, 0xc7, 0x6e, 0x66,
0x66, 0x66, 0x66, 0x6c, 0x63,
- /* U+417 "З" */
+ /* U+0417 "З" */
0x1f, 0xf, 0xf3, 0xc7, 0x0, 0x60, 0x1c, 0x1e,
0x3, 0xf0, 0xe, 0x0, 0xe0, 0x1f, 0x83, 0xf8,
0xf7, 0xfc, 0x3e, 0x0,
- /* U+418 "И" */
+ /* U+0418 "И" */
0xc3, 0xe3, 0xf1, 0xf8, 0xfc, 0xde, 0x6f, 0x37,
0xb3, 0xd9, 0xfc, 0xfc, 0x7e, 0x3e, 0x1f, 0xc,
- /* U+419 "Й" */
+ /* U+0419 "Й" */
0x63, 0x31, 0x8f, 0x83, 0x80, 0x6, 0x1f, 0x1f,
0x8f, 0xc7, 0xe7, 0xf3, 0x79, 0xbd, 0x9e, 0xcf,
0xe7, 0xe3, 0xf1, 0xf8, 0xf8, 0x60,
- /* U+41A "К" */
+ /* U+041A "К" */
0xe1, 0xf8, 0x7e, 0x3b, 0x8e, 0xe7, 0x39, 0xcf,
0xe3, 0xf8, 0xe7, 0x39, 0xce, 0x3b, 0x8e, 0xe1,
0xf8, 0x70,
- /* U+41B "Л" */
+ /* U+041B "Л" */
0x3f, 0xcf, 0xf3, 0x9c, 0xe7, 0x39, 0xce, 0x73,
0x9c, 0xe7, 0x39, 0xce, 0x73, 0x9d, 0xe7, 0xf1,
0xf8, 0x70,
- /* U+41C "М" */
+ /* U+041C "М" */
0xe1, 0xf8, 0x7f, 0x3f, 0xcf, 0xd2, 0xf7, 0xbd,
0xef, 0x33, 0xc0, 0xf0, 0x3c, 0xf, 0x3, 0xc0,
0xf0, 0x30,
- /* U+41D "Н" */
+ /* U+041D "Н" */
0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0xff,
0xff, 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1c,
- /* U+41E "О" */
+ /* U+041E "О" */
0x3e, 0x3f, 0xb8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f,
0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x77, 0xf1, 0xf0,
- /* U+41F "П" */
+ /* U+041F "П" */
0xff, 0xff, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f,
0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1c,
- /* U+420 "Р" */
+ /* U+0420 "Р" */
0xff, 0x3f, 0xee, 0x3f, 0x87, 0xe1, 0xf8, 0xff,
0xfb, 0xfc, 0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0,
0x38, 0x0,
- /* U+421 "С" */
+ /* U+0421 "С" */
0x3f, 0x1f, 0xef, 0x3f, 0x87, 0xe0, 0x38, 0xe,
0x3, 0x80, 0xe0, 0x38, 0xe, 0x1f, 0xcf, 0x7f,
0x8f, 0xc0,
- /* U+422 "Т" */
+ /* U+0422 "Т" */
0xff, 0xff, 0xf0, 0xe0, 0x38, 0xe, 0x3, 0x80,
0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, 0x38, 0xe,
0x3, 0x80,
- /* U+423 "У" */
+ /* U+0423 "У" */
0xe1, 0xf8, 0x76, 0x19, 0xce, 0x33, 0x8c, 0xc3,
0xb0, 0x7c, 0x1e, 0x3, 0x80, 0xc0, 0x70, 0x1c,
0x6, 0x0,
- /* U+424 "Ф" */
+ /* U+0424 "Ф" */
0xc, 0xf, 0xc7, 0xfb, 0xb7, 0xcc, 0xf3, 0x3c,
0xcf, 0x33, 0xcc, 0xf3, 0x3c, 0xcf, 0xb7, 0x7f,
0x8f, 0xc0, 0xc0, 0x30,
- /* U+425 "Х" */
+ /* U+0425 "Х" */
0xe1, 0xd8, 0x67, 0x38, 0xcc, 0x3f, 0x7, 0x81,
0xe0, 0x78, 0x1e, 0xf, 0xc3, 0x31, 0xce, 0xe1,
0xf8, 0x70,
- /* U+426 "Ц" */
+ /* U+0426 "Ц" */
0xe3, 0xb8, 0xee, 0x3b, 0x8e, 0xe3, 0xb8, 0xee,
0x3b, 0x8e, 0xe3, 0xb8, 0xee, 0x3b, 0x8e, 0xff,
0xff, 0xf0, 0x1c, 0x7, 0x1, 0xc0,
- /* U+427 "Ч" */
+ /* U+0427 "Ч" */
0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0xce,
0xff, 0x3f, 0x81, 0xc0, 0xe0, 0x70, 0x38, 0x1c,
- /* U+428 "Ш" */
+ /* U+0428 "Ш" */
0xcc, 0xf3, 0x3c, 0xcf, 0x33, 0xcc, 0xf3, 0x3c,
0xcf, 0x33, 0xcc, 0xf3, 0x3c, 0xcf, 0x33, 0xff,
0xff, 0xf0,
- /* U+429 "Щ" */
+ /* U+0429 "Щ" */
0xcc, 0xd9, 0x9b, 0x33, 0x66, 0x6c, 0xcd, 0x99,
0xb3, 0x36, 0x66, 0xcc, 0xd9, 0x9b, 0x33, 0x66,
0x6f, 0xff, 0xff, 0xc0, 0x18, 0x3,
- /* U+42A "Ъ" */
+ /* U+042A "Ъ" */
0xfc, 0xf, 0xc0, 0x1c, 0x1, 0xc0, 0x1c, 0x1,
0xfc, 0x1f, 0xe1, 0xcf, 0x1c, 0x71, 0xc7, 0x1c,
- 0x71, 0xcf, 0x1f, 0xe1, 0xf8,
+ 0x71, 0xcf, 0x1f, 0xe1, 0xfc,
- /* U+42B "Ы" */
+ /* U+042B "Ы" */
0xc0, 0xf0, 0x3c, 0xf, 0x3, 0xc0, 0xfe, 0x3f,
0xcf, 0x3b, 0xc6, 0xf1, 0xbc, 0x6f, 0x3b, 0xfc,
0xfe, 0x30,
- /* U+42C "Ь" */
+ /* U+042C "Ь" */
0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0, 0x3f, 0xcf,
0xfb, 0x8f, 0xe1, 0xf8, 0x7e, 0x1f, 0x8f, 0xff,
0xbf, 0x80,
- /* U+42D "Э" */
+ /* U+042D "Э" */
0x3e, 0x3f, 0xb8, 0xfc, 0x70, 0x38, 0x1c, 0x7e,
0x3f, 0x3, 0x81, 0xf8, 0xfc, 0x77, 0xf1, 0xf0,
- /* U+42E "Ю" */
+ /* U+042E "Ю" */
0xc7, 0xb3, 0xfc, 0xcf, 0x33, 0xcc, 0xff, 0x3f,
0xcf, 0x33, 0xcc, 0xf3, 0x3c, 0xcf, 0x33, 0xcf,
0xf1, 0xe0,
- /* U+42F "Я" */
+ /* U+042F "Я" */
0x3f, 0xdf, 0xff, 0x1f, 0x87, 0xe1, 0xfc, 0x77,
0xfc, 0x7f, 0x19, 0xce, 0x73, 0x1d, 0xc7, 0x71,
0xf8, 0x70,
- /* U+430 "а" */
+ /* U+0430 "а" */
0x1f, 0x1f, 0xe7, 0x1c, 0x7, 0x3f, 0xdf, 0xfe,
0x1f, 0x87, 0xe3, 0xff, 0xf3, 0xdc,
- /* U+431 "б" */
+ /* U+0431 "б" */
0x1f, 0x3f, 0x9c, 0x1c, 0xe, 0xe7, 0xfb, 0x8f,
0xc7, 0xe3, 0xf1, 0xf8, 0xfc, 0x77, 0xf1, 0xf0,
- /* U+432 "в" */
+ /* U+0432 "в" */
0xff, 0x3f, 0xee, 0x3b, 0x8e, 0xfe, 0x3f, 0xee,
0x1f, 0x87, 0xe1, 0xff, 0xef, 0xf0,
- /* U+433 "г" */
+ /* U+0433 "г" */
0xff, 0xff, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0,
0xe0, 0xe0, 0xe0,
- /* U+434 "д" */
+ /* U+0434 "д" */
0x3f, 0xc7, 0xf8, 0xe7, 0x1c, 0xe3, 0x9c, 0x73,
0x8e, 0x71, 0xce, 0x71, 0xdf, 0xff, 0xff, 0xf0,
0x7e, 0xf, 0xc1, 0xc0,
- /* U+435 "е" */
+ /* U+0435 "е" */
0x3e, 0x3f, 0xb8, 0xfc, 0x7f, 0xff, 0xff, 0x81,
0xc0, 0xe3, 0xbf, 0x8f, 0x80,
- /* U+436 "ж" */
+ /* U+0436 "ж" */
0xe6, 0x76, 0x66, 0x66, 0x63, 0x6c, 0x36, 0xc3,
- 0xfc, 0x36, 0xc3, 0x6c, 0x66, 0x66, 0x66, 0xe6,
+ 0xfc, 0x36, 0xc3, 0x6e, 0x66, 0x66, 0x66, 0xe6,
0x70,
- /* U+437 "з" */
+ /* U+0437 "з" */
0x3f, 0x1f, 0xfe, 0x1c, 0x7, 0x1f, 0x87, 0xe0,
0x1c, 0x7, 0xe1, 0xdf, 0xe3, 0xf0,
- /* U+438 "и" */
+ /* U+0438 "и" */
0xc3, 0xe3, 0xf1, 0xf9, 0xfc, 0xde, 0xef, 0x67,
0xb3, 0xf1, 0xf8, 0xf8, 0x60,
- /* U+439 "й" */
+ /* U+0439 "й" */
0x63, 0x31, 0x8f, 0x83, 0x80, 0x6, 0x1f, 0x1f,
0x8f, 0xcf, 0xe6, 0xf7, 0x7b, 0x3f, 0x9f, 0x8f,
0xc7, 0xc3,
- /* U+43A "к" */
+ /* U+043A "к" */
0xe1, 0xf8, 0xee, 0x33, 0x9c, 0xfe, 0x3f, 0x8e,
0x73, 0x9c, 0xe3, 0xb8, 0x6e, 0x1c,
- /* U+43B "л" */
+ /* U+043B "л" */
0x3f, 0xcf, 0xf3, 0x9c, 0xe7, 0x39, 0xce, 0x73,
0x9c, 0xe7, 0x39, 0xfc, 0x7e, 0x1c,
- /* U+43C "м" */
+ /* U+043C "м" */
0xe1, 0xf8, 0x7f, 0x3f, 0xcf, 0xda, 0xf7, 0xbd,
0xef, 0x33, 0xc0, 0xf0, 0x3c, 0xc,
- /* U+43D "н" */
+ /* U+043D "н" */
0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3f, 0xff, 0xff,
0xc7, 0xe3, 0xf1, 0xf8, 0xe0,
- /* U+43E "о" */
+ /* U+043E "о" */
0x3e, 0x3f, 0xb8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f,
0xc7, 0xe3, 0xbf, 0x8f, 0x80,
- /* U+43F "п" */
+ /* U+043F "п" */
0xff, 0xff, 0xf8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f,
0xc7, 0xe3, 0xf1, 0xf8, 0xe0,
- /* U+440 "р" */
+ /* U+0440 "р" */
0xee, 0x7f, 0xb8, 0xfc, 0x7e, 0x3f, 0x1f, 0x8f,
0xc7, 0xe3, 0xff, 0xbb, 0x9c, 0xe, 0x7, 0x3,
0x80,
- /* U+441 "с" */
+ /* U+0441 "с" */
0x3e, 0x3f, 0xb8, 0xfc, 0x7e, 0x7, 0x3, 0x81,
0xc7, 0xe3, 0xbf, 0x8f, 0x80,
- /* U+442 "т" */
+ /* U+0442 "т" */
0xff, 0xff, 0xf0, 0xe0, 0x38, 0xe, 0x3, 0x80,
0xe0, 0x38, 0xe, 0x3, 0x80, 0xe0,
- /* U+443 "у" */
+ /* U+0443 "у" */
0xe1, 0xf8, 0x76, 0x19, 0xce, 0x73, 0x8c, 0xc3,
0xf0, 0x7c, 0x1e, 0x7, 0x80, 0xe0, 0x30, 0x1c,
0x6, 0x3, 0x80,
- /* U+444 "ф" */
+ /* U+0444 "ф" */
0xc, 0x3, 0x0, 0xc0, 0xfc, 0x7f, 0xbb, 0x7c,
0xcf, 0x33, 0xcc, 0xf3, 0x3c, 0xcf, 0xb7, 0x7f,
0x8f, 0xc0, 0xc0, 0x30, 0xc, 0x3, 0x0,
- /* U+445 "х" */
+ /* U+0445 "х" */
0xe1, 0xdc, 0xe3, 0x30, 0xfc, 0x1e, 0x7, 0x81,
- 0xe0, 0xfc, 0x73, 0x9c, 0x6e, 0x1c,
+ 0xe0, 0xfc, 0x73, 0x9c, 0xee, 0x1c,
- /* U+446 "ц" */
+ /* U+0446 "ц" */
0xe3, 0xb8, 0xee, 0x3b, 0x8e, 0xe3, 0xb8, 0xee,
0x3b, 0x8e, 0xe3, 0xbf, 0xff, 0xfc, 0x7, 0x1,
0xc0, 0x70,
- /* U+447 "ч" */
+ /* U+0447 "ч" */
0xe3, 0xf1, 0xf8, 0xfc, 0x7e, 0x3b, 0xfc, 0xfe,
0x7, 0x3, 0x81, 0xc0, 0xe0,
- /* U+448 "ш" */
+ /* U+0448 "ш" */
0xcc, 0xf3, 0x3c, 0xcf, 0x33, 0xcc, 0xf3, 0x3c,
0xcf, 0x33, 0xcc, 0xff, 0xff, 0xfc,
- /* U+449 "щ" */
+ /* U+0449 "щ" */
0xcc, 0xd9, 0x9b, 0x33, 0x66, 0x6c, 0xcd, 0x99,
0xb3, 0x36, 0x66, 0xcc, 0xdf, 0xff, 0xff, 0x80,
0x30, 0x6,
- /* U+44A "ъ" */
+ /* U+044A "ъ" */
0xfc, 0xf, 0xc0, 0x1c, 0x1, 0xc0, 0x1f, 0xc1,
0xfe, 0x1c, 0x71, 0xc7, 0x1c, 0x71, 0xfe, 0x1f,
0xc0,
- /* U+44B "ы" */
+ /* U+044B "ы" */
0xc0, 0xf0, 0x3c, 0xf, 0x3, 0xf8, 0xff, 0x3c,
- 0x6f, 0x1b, 0xc6, 0xff, 0x3f, 0x8c,
+ 0xef, 0x1b, 0xc6, 0xff, 0x3f, 0x8c,
- /* U+44C "ь" */
+ /* U+044C "ь" */
0xe0, 0x38, 0xe, 0x3, 0x80, 0xff, 0x3f, 0xee,
0x1f, 0x87, 0xe1, 0xff, 0xef, 0xf0,
- /* U+44D "э" */
+ /* U+044D "э" */
0x3e, 0x3f, 0xb8, 0xe0, 0x70, 0xf8, 0x7c, 0xf,
0xc7, 0xe7, 0xbf, 0x8f, 0x80,
- /* U+44E "ю" */
+ /* U+044E "ю" */
0xc7, 0xb3, 0xfc, 0xcf, 0x33, 0xfc, 0xff, 0x3c,
0xcf, 0x33, 0xcc, 0xf3, 0xfc, 0x78,
- /* U+44F "я" */
+ /* U+044F "я" */
0x3f, 0xbf, 0xf8, 0xfc, 0x7e, 0x3b, 0xfc, 0xfe,
0x77, 0x33, 0xb9, 0xf8, 0xe0,
@@ -727,7 +731,7 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = {
0xfc, 0x70, 0x7e, 0x7, 0x7, 0x0, 0x70, 0x70,
0x7, 0x7, 0x0, 0x70, 0x70, 0x7, 0x7, 0x0,
0x70, 0x70, 0x7f, 0x7, 0xf, 0xf7, 0xf0, 0xff,
- 0xff, 0x7, 0xef, 0xf0, 0x0, 0xff, 0x0, 0x3,
+ 0xff, 0x7, 0xef, 0xf0, 0x10, 0xff, 0x0, 0x3,
0xc0, 0x0,
/* U+F017 "" */
@@ -739,11 +743,11 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = {
0x1, 0xff, 0xc0, 0x1f, 0xf0, 0x0, 0x70, 0x0,
/* U+F024 "" */
- 0x70, 0x0, 0xf, 0x80, 0x0, 0xf8, 0x0, 0xf,
+ 0x70, 0x0, 0xf, 0x80, 0x0, 0xf9, 0x0, 0xf,
0xff, 0xf, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0x7f,
0xff, 0xf7, 0xff, 0xff, 0x7f, 0xff, 0xf7, 0xff,
0xff, 0x7f, 0xff, 0xf7, 0xff, 0xff, 0x7f, 0xff,
- 0xf7, 0xff, 0xff, 0x7f, 0x7f, 0xe7, 0x0, 0x78,
+ 0xf7, 0xff, 0xff, 0x7f, 0xff, 0xe7, 0x0, 0xf8,
0x70, 0x0, 0x7, 0x0, 0x0, 0x70, 0x0, 0x7,
0x0, 0x0,
@@ -869,35 +873,35 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = {
0x7f, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xb8, 0x0,
0x1, 0xfd, 0xff, 0xfe, 0xfe, 0xff, 0xff, 0x7f,
0x7f, 0xff, 0x9f, 0xbf, 0xff, 0xcf, 0xdf, 0xff,
- 0xe7, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff,
+ 0xef, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff,
0xff, 0xff, 0xcf, 0xff, 0xff, 0xe0,
/* U+F241 "" */
0x7f, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xb8, 0x0,
0x1, 0xfd, 0xff, 0xe0, 0xfe, 0xff, 0xf0, 0x7f,
0x7f, 0xf8, 0x1f, 0xbf, 0xfc, 0xf, 0xdf, 0xfe,
- 0x7, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff,
+ 0xf, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff,
0xff, 0xff, 0xcf, 0xff, 0xff, 0xe0,
/* U+F242 "" */
0x7f, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xb8, 0x0,
0x1, 0xfd, 0xfe, 0x0, 0xfe, 0xff, 0x0, 0x7f,
0x7f, 0x80, 0x1f, 0xbf, 0xc0, 0xf, 0xdf, 0xe0,
- 0x7, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff,
+ 0xf, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff,
0xff, 0xff, 0xcf, 0xff, 0xff, 0xe0,
/* U+F243 "" */
0x7f, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xb8, 0x0,
0x1, 0xfd, 0xf0, 0x0, 0xfe, 0xf8, 0x0, 0x7f,
0x7c, 0x0, 0x1f, 0xbe, 0x0, 0xf, 0xdf, 0x0,
- 0x7, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff,
+ 0xf, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff,
0xff, 0xff, 0xcf, 0xff, 0xff, 0xe0,
/* U+F244 "" */
0x7f, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xb8, 0x0,
0x1, 0xfc, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x7f,
0x0, 0x0, 0x1f, 0x80, 0x0, 0xf, 0xc0, 0x0,
- 0x7, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff,
+ 0xf, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff,
0xff, 0xff, 0xcf, 0xff, 0xff, 0xe0,
/* U+F252 "" */
@@ -933,9 +937,9 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = {
0x78, 0xf, 0xe0, 0x1e, 0x7, 0xf0, 0x3, 0xc1,
0xf8, 0x0, 0xf0, 0x78, 0x0, 0x3c, 0x3c, 0x0,
0xf, 0xbe, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x7e,
- 0x0, 0x1c, 0x1f, 0x0, 0x7f, 0x3, 0xc0, 0x7f,
+ 0x0, 0x1c, 0x1f, 0x0, 0x7f, 0x3, 0xc0, 0x3f,
0xf0, 0xf0, 0x1f, 0xfc, 0x3c, 0xf, 0xfe, 0x7,
- 0x87, 0xfe, 0x1, 0xe3, 0xf8, 0x0, 0x70, 0x0,
+ 0x87, 0xfe, 0x1, 0xe3, 0xf8, 0x0, 0x70, 0x80,
0x0, 0x10,
/* U+F3FD "" */
@@ -975,6 +979,16 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = {
0x1f, 0xf0, 0x0, 0xfe, 0x0, 0x7, 0xc0, 0x0,
0x38, 0x0, 0x1, 0x0, 0x0,
+ /* U+F569 "" */
+ 0x0, 0x0, 0x4, 0x0, 0x0, 0x3c, 0x0, 0x0,
+ 0xf0, 0x0, 0x7, 0xc0, 0x1f, 0xfe, 0x3, 0xff,
+ 0xfe, 0xf, 0x87, 0xfe, 0x38, 0x3e, 0xe, 0xc0,
+ 0xf8, 0x7, 0x81, 0xc0, 0xf, 0x0, 0x0, 0x1f,
+ 0x80, 0x0, 0xff, 0xe0, 0xf, 0xff, 0xff, 0xff,
+ 0xf9, 0xff, 0xf3, 0xf3, 0xe3, 0xe7, 0xe7, 0xc7,
+ 0xce, 0xcf, 0x8f, 0x98, 0x9f, 0x1f, 0x20, 0x3e,
+ 0x3e, 0x0, 0x4, 0x60, 0x0,
+
/* U+F59F "" */
0x0, 0x78, 0x0, 0x7, 0xf8, 0x0, 0x1f, 0xe0,
0x0, 0xff, 0xc0, 0x3, 0xff, 0x0, 0xf, 0xfc,
@@ -1200,9 +1214,10 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 3750, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3800, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3860, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
- {.bitmap_index = 3913, .adv_w = 360, .box_w = 22, .box_h = 20, .ofs_x = 0, .ofs_y = -2},
- {.bitmap_index = 3968, .adv_w = 360, .box_w = 22, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
- {.bitmap_index = 4021, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0}
+ {.bitmap_index = 3913, .adv_w = 360, .box_w = 23, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
+ {.bitmap_index = 3974, .adv_w = 360, .box_w = 22, .box_h = 20, .ofs_x = 0, .ofs_y = -2},
+ {.bitmap_index = 4029, .adv_w = 360, .box_w = 22, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
+ {.bitmap_index = 4082, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0}
};
/*---------------------
@@ -1214,7 +1229,7 @@ static const uint16_t unicode_list_2[] = {
0x4a, 0x4b, 0x4c, 0x50, 0x68, 0x94, 0x128, 0x184,
0x1e5, 0x1fb, 0x21d, 0x23f, 0x240, 0x241, 0x242, 0x243,
0x251, 0x292, 0x293, 0x2f1, 0x3dc, 0x3fc, 0x45c, 0x54a,
- 0x55f, 0x59e, 0x59f, 0x6a8
+ 0x55f, 0x568, 0x59e, 0x59f, 0x6a8
};
/*Collect the unicode lists and glyph_id offsets*/
@@ -1230,7 +1245,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] =
},
{
.range_start = 61441, .range_length = 1705, .glyph_id_start = 160,
- .unicode_list = unicode_list_2, .glyph_id_ofs_list = NULL, .list_length = 36, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
+ .unicode_list = unicode_list_2, .glyph_id_ofs_list = NULL, .list_length = 37, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
}
};
@@ -1240,9 +1255,14 @@ static const lv_font_fmt_txt_cmap_t cmaps[] =
* ALL CUSTOM DATA
*--------------------*/
+#if LV_VERSION_CHECK(8, 0, 0)
/*Store all the custom data of the font*/
+static lv_font_fmt_txt_glyph_cache_t cache;
+static const lv_font_fmt_txt_dsc_t font_dsc = {
+#else
static lv_font_fmt_txt_dsc_t font_dsc = {
- .glyph_bitmap = gylph_bitmap,
+#endif
+ .glyph_bitmap = glyph_bitmap,
.glyph_dsc = glyph_dsc,
.cmaps = cmaps,
.kern_dsc = NULL,
@@ -1250,7 +1270,10 @@ static lv_font_fmt_txt_dsc_t font_dsc = {
.cmap_num = 3,
.bpp = 1,
.kern_classes = 0,
- .bitmap_format = 0
+ .bitmap_format = 0,
+#if LV_VERSION_CHECK(8, 0, 0)
+ .cache = &cache
+#endif
};
@@ -1259,7 +1282,11 @@ static lv_font_fmt_txt_dsc_t font_dsc = {
*----------------*/
/*Initialize a public general font descriptor*/
+#if LV_VERSION_CHECK(8, 0, 0)
+const lv_font_t jetbrains_mono_bold_20 = {
+#else
lv_font_t jetbrains_mono_bold_20 = {
+#endif
.get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/
.get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/
.line_height = 23, /*The maximum line height required by the font*/
diff --git a/src/displayapp/fonts/open_sans_light.c b/src/displayapp/fonts/open_sans_light.c
new file mode 100644
index 00000000..15f0ddf6
--- /dev/null
+++ b/src/displayapp/fonts/open_sans_light.c
@@ -0,0 +1,1261 @@
+/*******************************************************************************
+ * Size: 150 px
+ * Bpp: 1
+ * Opts:
+ ******************************************************************************/
+
+#ifdef LV_LVGL_H_INCLUDE_SIMPLE
+#include "lvgl.h"
+#else
+#include "lvgl/lvgl.h"
+#endif
+
+#ifndef OPEN_SANS_LIGHT
+#define OPEN_SANS_LIGHT 1
+#endif
+
+#if OPEN_SANS_LIGHT
+
+/*-----------------
+ * BITMAPS
+ *----------------*/
+
+/*Store the image of the glyphs*/
+static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
+ /* U+0030 "0" */
+ 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xc0, 0x0,
+ 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff,
+ 0xfe, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff,
+ 0xff, 0xf8, 0x0, 0x0, 0x0, 0xf, 0xff, 0xe0,
+ 0x3, 0xff, 0xf0, 0x0, 0x0, 0x0, 0xff, 0xf8,
+ 0x0, 0x3, 0xff, 0xc0, 0x0, 0x0, 0xf, 0xfe,
+ 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x0, 0xff,
+ 0xe0, 0x0, 0x0, 0xf, 0xfc, 0x0, 0x0, 0x7,
+ 0xfe, 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0,
+ 0x7f, 0xc0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0,
+ 0x7, 0xfc, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0,
+ 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, 0xf, 0xf8,
+ 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x3f,
+ 0xc0, 0x0, 0x3f, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0xff, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0,
+ 0x3, 0xfc, 0x0, 0x1f, 0xf0, 0x0, 0x0, 0x0,
+ 0x0, 0x1f, 0xe0, 0x0, 0xff, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7f, 0x80, 0xf, 0xf8, 0x0, 0x0,
+ 0x0, 0x0, 0x3, 0xfc, 0x0, 0x7f, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0xf, 0xe0, 0x3, 0xfc, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x3f, 0xc0,
+ 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x1, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0xf,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80,
+ 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc,
+ 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xf0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7f, 0x81, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3, 0xfc, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xe0, 0xff, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7f, 0x87, 0xf8, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3, 0xfc, 0x3f, 0xc0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1f, 0xe1, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0x1f, 0xe0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0xff, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe7, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x3f,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf9,
+ 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f,
+ 0xcf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
+ 0xfe, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xf, 0xf3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x7f, 0xbf, 0xc0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3, 0xfd, 0xfe, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0xff, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xff, 0xfc, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xe0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff,
+ 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7f, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1f, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xff, 0xf8, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xff, 0xc0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1, 0xff, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xfc,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff,
+ 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7,
+ 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3f, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xfe, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1f, 0xe7, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x3f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xf9, 0xfe, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xcf, 0xf0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1, 0xfe, 0x7f, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xf, 0xf3, 0xfc, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x9f, 0xe0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x7f,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe3,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe,
+ 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xf0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7f, 0x87, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3, 0xfc, 0x1f, 0xc0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1f, 0xe0, 0xff, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1, 0xfe, 0x7, 0xf8, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xf, 0xf0, 0x3f, 0xc0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0x80, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7, 0xfc, 0x7, 0xf8, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x3f, 0xc0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf0, 0x7,
+ 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0,
+ 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8,
+ 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f,
+ 0x80, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xfc, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0x3f, 0xe0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xfe, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x1f, 0xf0, 0x0, 0x1f, 0xf0, 0x0, 0x0,
+ 0x0, 0x1, 0xff, 0x0, 0x0, 0x7f, 0xc0, 0x0,
+ 0x0, 0x0, 0x1f, 0xf0, 0x0, 0x1, 0xfe, 0x0,
+ 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0xf, 0xf8,
+ 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, 0x3f,
+ 0xf0, 0x0, 0x0, 0x1, 0xff, 0x80, 0x0, 0x0,
+ 0xff, 0xc0, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0,
+ 0x3, 0xff, 0x80, 0x0, 0x3, 0xff, 0x80, 0x0,
+ 0x0, 0xf, 0xff, 0x0, 0x0, 0x7f, 0xf8, 0x0,
+ 0x0, 0x0, 0x3f, 0xff, 0x0, 0x1f, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xf8,
+ 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff,
+ 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff,
+ 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7,
+ 0xff, 0xc0, 0x0, 0x0, 0x0,
+
+ /* U+0031 "1" */
+ 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x3,
+ 0xfc, 0x0, 0x0, 0x1, 0xff, 0x80, 0x0, 0x0,
+ 0x7f, 0xf0, 0x0, 0x0, 0x1f, 0xfe, 0x0, 0x0,
+ 0xf, 0xff, 0xc0, 0x0, 0x3, 0xff, 0xf8, 0x0,
+ 0x0, 0xff, 0xbf, 0x0, 0x0, 0x7f, 0xe7, 0xe0,
+ 0x0, 0x1f, 0xf8, 0xfc, 0x0, 0x7, 0xfe, 0x1f,
+ 0x80, 0x3, 0xff, 0x83, 0xf0, 0x0, 0xff, 0xc0,
+ 0xfe, 0x0, 0x3f, 0xf0, 0x1f, 0xc0, 0x1f, 0xfc,
+ 0x3, 0xf8, 0x7, 0xff, 0x0, 0x7f, 0x1, 0xff,
+ 0x80, 0xf, 0xe0, 0xff, 0xe0, 0x1, 0xfc, 0x3f,
+ 0xf8, 0x0, 0x3f, 0x8f, 0xfc, 0x0, 0x7, 0xf7,
+ 0xff, 0x0, 0x0, 0xff, 0xff, 0xc0, 0x0, 0x1f,
+ 0xff, 0xf0, 0x0, 0x3, 0xfb, 0xf8, 0x0, 0x0,
+ 0x7f, 0x3e, 0x0, 0x0, 0xf, 0xe3, 0x80, 0x0,
+ 0x1, 0xfc, 0x20, 0x0, 0x0, 0x3f, 0x80, 0x0,
+ 0x0, 0x7, 0xf0, 0x0, 0x0, 0x0, 0xfe, 0x0,
+ 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x3, 0xf8,
+ 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, 0xf,
+ 0xe0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0,
+ 0x3f, 0x80, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0,
+ 0x0, 0xfe, 0x0, 0x0, 0x0, 0x1f, 0xc0, 0x0,
+ 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, 0x7f, 0x0,
+ 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x1, 0xfc,
+ 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, 0x7,
+ 0xf0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0,
+ 0x1f, 0xc0, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0,
+ 0x0, 0x7f, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0,
+ 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x3f, 0x80,
+ 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0, 0x0, 0xfe,
+ 0x0, 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x3,
+ 0xf8, 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0,
+ 0xf, 0xe0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0,
+ 0x0, 0x3f, 0x80, 0x0, 0x0, 0x7, 0xf0, 0x0,
+ 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x1f, 0xc0,
+ 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, 0x7f,
+ 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x1,
+ 0xfc, 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0,
+ 0x7, 0xf0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0,
+ 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x3, 0xf8, 0x0,
+ 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, 0xf, 0xe0,
+ 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x3f,
+ 0x80, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0, 0x0,
+ 0xfe, 0x0, 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x0,
+ 0x3, 0xf8, 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0,
+ 0x0, 0xf, 0xe0, 0x0, 0x0, 0x1, 0xfc, 0x0,
+ 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, 0x7, 0xf0,
+ 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x1f,
+ 0xc0, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0,
+ 0x7f, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0,
+ 0x1, 0xfc, 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0,
+ 0x0, 0x7, 0xf0, 0x0, 0x0, 0x0, 0xfe, 0x0,
+ 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x3, 0xf8,
+ 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, 0xf,
+ 0xe0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0,
+ 0x3f, 0x80, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0,
+ 0x0, 0xfe, 0x0, 0x0, 0x0, 0x1f, 0xc0, 0x0,
+ 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, 0x7f, 0x0,
+ 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x1, 0xfc,
+ 0x0, 0x0, 0x0, 0x3f, 0x80,
+
+ /* U+0032 "2" */
+ 0x0, 0x0, 0x0, 0x7f, 0xfe, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1, 0xff, 0xff, 0xfc, 0x0, 0x0,
+ 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xf0, 0x0,
+ 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xfc,
+ 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff,
+ 0xe0, 0x0, 0x0, 0x1f, 0xff, 0xf0, 0x1, 0xff,
+ 0xfe, 0x0, 0x0, 0xf, 0xff, 0xc0, 0x0, 0x3,
+ 0xff, 0xe0, 0x0, 0x7, 0xff, 0xe0, 0x0, 0x0,
+ 0x1f, 0xfe, 0x0, 0x1, 0xff, 0xe0, 0x0, 0x0,
+ 0x0, 0xff, 0xe0, 0x0, 0x7f, 0xf0, 0x0, 0x0,
+ 0x0, 0xf, 0xfe, 0x0, 0xf, 0xfc, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0xc0, 0x0, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0xf, 0xfc, 0x0, 0xf, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0xff, 0xc0, 0x1, 0xc0, 0x0,
+ 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0, 0x10, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f,
+ 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1f, 0xf0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f,
+ 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x7f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xfc, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1, 0xff, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7, 0xfe, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1, 0xff, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7f, 0xe0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfc, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfc,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x7, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7f, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xfe, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1, 0xff, 0x80, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0xe0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7, 0xfe, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf0,
+
+ /* U+0033 "3" */
+ 0x0, 0x0, 0x0, 0x1f, 0xff, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xc0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff,
+ 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0xff,
+ 0xf8, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xe0, 0x0, 0x0, 0xff, 0xff, 0xe0, 0x0,
+ 0xff, 0xff, 0x0, 0x0, 0x3f, 0xff, 0xc0, 0x0,
+ 0x0, 0xff, 0xf8, 0x0, 0x7, 0xff, 0xe0, 0x0,
+ 0x0, 0x3, 0xff, 0xc0, 0x1, 0xff, 0xf0, 0x0,
+ 0x0, 0x0, 0xf, 0xfe, 0x0, 0x3f, 0xfc, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0xf0, 0x7, 0xff, 0x0,
+ 0x0, 0x0, 0x0, 0x1, 0xff, 0x80, 0x3f, 0xc0,
+ 0x0, 0x0, 0x0, 0x0, 0xf, 0xfc, 0x1, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xc0, 0xe,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfe, 0x0,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1, 0xff, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7, 0xfe, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0xc0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf8, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xc0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf8, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xfe, 0x0,
+ 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0x0,
+ 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xc0,
+ 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xff,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff,
+ 0xff, 0xc0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff,
+ 0xff, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xf, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xff, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xf, 0xff, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf8, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xc0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfe, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfe,
+ 0x8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
+ 0xc0, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f,
+ 0xf8, 0xf, 0x80, 0x0, 0x0, 0x0, 0x0, 0x7,
+ 0xff, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1,
+ 0xff, 0xe0, 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0,
+ 0x7f, 0xfc, 0x0, 0xff, 0xfe, 0x0, 0x0, 0x0,
+ 0x7f, 0xff, 0x80, 0xf, 0xff, 0xff, 0x80, 0x0,
+ 0xff, 0xff, 0xe0, 0x0, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xfc, 0x0, 0x1, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0x0, 0x0, 0x7, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0xf, 0xff,
+ 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x7,
+ 0xff, 0xff, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xff, 0xff, 0x80, 0x0, 0x0, 0x0,
+
+ /* U+0034 "4" */
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3, 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3, 0xfb, 0xf0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xfd, 0xf8, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfc,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xfc, 0x7e, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xfe, 0x3f, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x1f, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe,
+ 0xf, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x7f, 0x7, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0x3, 0xf0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x1, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f,
+ 0x80, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3f, 0x80, 0x7e, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x3f, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x1f,
+ 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f,
+ 0xc0, 0xf, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1f, 0xc0, 0x7, 0xe0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x3, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x1,
+ 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xe0, 0x0, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xf0, 0x0, 0x7e, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x3f, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0,
+ 0x1f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7,
+ 0xf8, 0x0, 0xf, 0xc0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x7, 0xf8, 0x0, 0x7, 0xe0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x3, 0xf0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0,
+ 0x1, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xfc, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3, 0xfc, 0x0, 0x0, 0x7e, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x3f,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0,
+ 0x0, 0x1f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x1,
+ 0xfe, 0x0, 0x0, 0xf, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xfe, 0x0, 0x0, 0x7, 0xe0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x3,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0,
+ 0x0, 0x1, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xff, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, 0x7e, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0,
+ 0x3f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80,
+ 0x0, 0x0, 0x1f, 0x80, 0x0, 0x0, 0x0, 0x0,
+ 0x3f, 0x80, 0x0, 0x0, 0xf, 0xc0, 0x0, 0x0,
+ 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x7, 0xe0,
+ 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0,
+ 0x3, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xc0,
+ 0x0, 0x0, 0x1, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x1f, 0xe0, 0x0, 0x0, 0x0, 0xfc, 0x0, 0x0,
+ 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x7e,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0,
+ 0x0, 0x3f, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0,
+ 0x0, 0x0, 0x0, 0x1f, 0x80, 0x0, 0x0, 0x0,
+ 0xf, 0xf0, 0x0, 0x0, 0x0, 0xf, 0xc0, 0x0,
+ 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x7,
+ 0xe0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0,
+ 0x0, 0x3, 0xf0, 0x0, 0x0, 0x0, 0x7, 0xf8,
+ 0x0, 0x0, 0x0, 0x1, 0xf8, 0x0, 0x0, 0x0,
+ 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0xfc, 0x0,
+ 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x7e, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0,
+ 0x0, 0x0, 0x3f, 0x0, 0x0, 0x0, 0x3, 0xfc,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x0, 0x0,
+ 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xf, 0xc0,
+ 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0,
+ 0x7, 0xe0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x3, 0xf0, 0x0, 0x0, 0x1, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xf8, 0x0, 0x0,
+ 0x0, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfc,
+ 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x7e, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0x0, 0x0, 0x0, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0x80, 0x0,
+ 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xc0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0,
+ 0x0, 0x7, 0xe0, 0x0, 0x0, 0x7f, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xf0, 0x0, 0x0, 0x3f,
+ 0x80, 0x0, 0x0, 0x0, 0x0, 0x1, 0xf8, 0x0,
+ 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xfc, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7e, 0x0, 0x0, 0x1f, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f,
+ 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0,
+
+ /* U+0035 "5" */
+ 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0,
+ 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8,
+ 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
+ 0x0, 0x7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x80, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xe0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xf8, 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xfe, 0x0, 0x7f, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0x3f, 0x8f, 0xff, 0xff, 0xff,
+ 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0xff,
+ 0xfc, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xc0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xfc, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xc0, 0x0, 0xf, 0xff, 0xf0, 0x0,
+ 0x3f, 0xff, 0xfc, 0x0, 0x1, 0xfe, 0x0, 0x0,
+ 0x0, 0x7f, 0xff, 0x80, 0x0, 0x18, 0x0, 0x0,
+ 0x0, 0x3, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3f, 0xfe, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xf8, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7, 0xff, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0xe0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfc, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xe0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xc0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
+ 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f,
+ 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7,
+ 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
+ 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0x3,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x80,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xc0,
+ 0x3f, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0xe0,
+ 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf0,
+ 0x3, 0xff, 0x80, 0x0, 0x0, 0x1, 0xff, 0xf8,
+ 0x0, 0xff, 0xfc, 0x0, 0x0, 0x3, 0xff, 0xfc,
+ 0x0, 0x3f, 0xff, 0xfc, 0x0, 0xf, 0xff, 0xfc,
+ 0x0, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
+ 0x0, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
+ 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xff, 0xfe,
+ 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff, 0xfc,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xc0,
+ 0x0, 0x0, 0x0,
+
+ /* U+0036 "6" */
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xfe, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff,
+ 0x80, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xff,
+ 0xff, 0xe0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff,
+ 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xff,
+ 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x7, 0xff,
+ 0xfc, 0x0, 0xf, 0xc0, 0x0, 0x0, 0x0, 0xff,
+ 0xfe, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0xf,
+ 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xf, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f,
+ 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xfe, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7, 0xf0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xc0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xf, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0, 0x3, 0xff,
+ 0xe0, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x1, 0xff,
+ 0xff, 0xf0, 0x0, 0x0, 0x1f, 0xc0, 0x0, 0x7f,
+ 0xff, 0xff, 0xf0, 0x0, 0x0, 0xfe, 0x0, 0xf,
+ 0xff, 0xff, 0xff, 0xf0, 0x0, 0xf, 0xf0, 0x1,
+ 0xff, 0xff, 0xff, 0xff, 0xc0, 0x0, 0x7f, 0x0,
+ 0x3f, 0xff, 0xff, 0xff, 0xff, 0x80, 0x3, 0xf8,
+ 0x3, 0xff, 0xf0, 0x1, 0xff, 0xfe, 0x0, 0x1f,
+ 0xc0, 0x7f, 0xf8, 0x0, 0x0, 0xff, 0xf8, 0x0,
+ 0xfe, 0x7, 0xfe, 0x0, 0x0, 0x1, 0xff, 0xe0,
+ 0x7, 0xf0, 0x7f, 0xc0, 0x0, 0x0, 0x3, 0xff,
+ 0x80, 0x3f, 0x87, 0xf8, 0x0, 0x0, 0x0, 0x7,
+ 0xfe, 0x1, 0xfc, 0x7f, 0x80, 0x0, 0x0, 0x0,
+ 0x1f, 0xf8, 0xf, 0xe7, 0xf8, 0x0, 0x0, 0x0,
+ 0x0, 0x7f, 0xe0, 0x7f, 0x7f, 0x0, 0x0, 0x0,
+ 0x0, 0x1, 0xff, 0x3, 0xff, 0xf0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xfc, 0x1f, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1f, 0xf0, 0xff, 0xf8, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0x8f, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x7f, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf3, 0xff,
+ 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x9f,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc,
+ 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f,
+ 0xf3, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7f, 0x9f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3, 0xfc, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1f, 0xe7, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0xbf, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3, 0xfd, 0xfe, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1f, 0xef, 0xf0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0x7f, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7, 0xfb, 0xfc, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xdf, 0xe0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf7,
+ 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f,
+ 0x9f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xfc, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1f, 0xe7, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xff, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x7, 0xf8, 0xfe, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3f, 0xc7, 0xf0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3, 0xfc, 0x3f, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1f, 0xe1, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0x7, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, 0x3f, 0xc0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc1, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x7,
+ 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0,
+ 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
+ 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xf0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7f, 0x80, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0x7, 0xfc, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0,
+ 0x0, 0x3f, 0xc0, 0x3, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x3, 0xfe, 0x0, 0x1f, 0xf0, 0x0, 0x0,
+ 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x7f, 0xc0, 0x0,
+ 0x0, 0x0, 0x3, 0xfe, 0x0, 0x1, 0xff, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x7, 0xfc,
+ 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x0, 0x3f,
+ 0xf8, 0x0, 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0,
+ 0xff, 0xe0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x0,
+ 0x3, 0xff, 0xc0, 0x0, 0x0, 0x7f, 0xf0, 0x0,
+ 0x0, 0xf, 0xff, 0x80, 0x0, 0x1f, 0xff, 0x0,
+ 0x0, 0x0, 0x1f, 0xff, 0xc0, 0xf, 0xff, 0xf0,
+ 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff, 0xff, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff,
+ 0xe0, 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xff,
+ 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff,
+ 0xff, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
+ 0xff, 0xe0, 0x0, 0x0, 0x0,
+
+ /* U+0037 "7" */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
+ 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xfc, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0,
+
+ /* U+0038 "8" */
+ 0x0, 0x0, 0x0, 0x1f, 0xff, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff, 0xff, 0x0,
+ 0x0, 0x0, 0x0, 0x7, 0xff, 0xff, 0xff, 0xfc,
+ 0x0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff, 0xff,
+ 0xf0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff,
+ 0xff, 0xc0, 0x0, 0x0, 0xf, 0xff, 0xf0, 0x1,
+ 0xff, 0xfe, 0x0, 0x0, 0x1, 0xff, 0xf0, 0x0,
+ 0x1, 0xff, 0xf0, 0x0, 0x0, 0x3f, 0xf8, 0x0,
+ 0x0, 0x3, 0xff, 0x80, 0x0, 0x7, 0xfe, 0x0,
+ 0x0, 0x0, 0xf, 0xfc, 0x0, 0x0, 0xff, 0xc0,
+ 0x0, 0x0, 0x0, 0x7f, 0xe0, 0x0, 0x1f, 0xf8,
+ 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x1, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf8, 0x0, 0x3f,
+ 0xe0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x7,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0,
+ 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xc0,
+ 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc,
+ 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f,
+ 0xe0, 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1,
+ 0xfe, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1f, 0xe0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xff, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xf0, 0x1f, 0xe0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x1, 0xfe, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xf, 0xf0, 0x1f, 0xe0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xff, 0x1, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xf, 0xf0, 0x1f, 0xe0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0x1, 0xfe, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x1f, 0xe0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x1, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x1f,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0,
+ 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe0,
+ 0xf, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe,
+ 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0, 0x3f,
+ 0xe0, 0x7, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xfc, 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0,
+ 0x7f, 0xc0, 0x7, 0xfe, 0x0, 0x0, 0x0, 0x0,
+ 0x7, 0xf8, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x0,
+ 0x0, 0xff, 0x80, 0x1, 0xff, 0x0, 0x0, 0x0,
+ 0x0, 0x1f, 0xf0, 0x0, 0x1f, 0xf8, 0x0, 0x0,
+ 0x0, 0x3, 0xfe, 0x0, 0x0, 0xff, 0xe0, 0x0,
+ 0x0, 0x0, 0x7f, 0xc0, 0x0, 0x7, 0xff, 0x0,
+ 0x0, 0x0, 0xf, 0xf8, 0x0, 0x0, 0x3f, 0xf8,
+ 0x0, 0x0, 0x1, 0xff, 0x80, 0x0, 0x1, 0xff,
+ 0xe0, 0x0, 0x0, 0x7f, 0xe0, 0x0, 0x0, 0xf,
+ 0xff, 0x80, 0x0, 0x1f, 0xfc, 0x0, 0x0, 0x0,
+ 0x7f, 0xfe, 0x0, 0x3, 0xff, 0x80, 0x0, 0x0,
+ 0x1, 0xff, 0xf8, 0x0, 0xff, 0xe0, 0x0, 0x0,
+ 0x0, 0xf, 0xff, 0xe0, 0x3f, 0xfc, 0x0, 0x0,
+ 0x0, 0x0, 0x3f, 0xff, 0x9f, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xc0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xf, 0xff, 0xfc, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xf0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xff, 0xff,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff,
+ 0xff, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff, 0xe7,
+ 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0xff, 0xf8,
+ 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x3f, 0xfe,
+ 0x0, 0x3f, 0xff, 0xc0, 0x0, 0x0, 0x7, 0xff,
+ 0x80, 0x0, 0xff, 0xfe, 0x0, 0x0, 0x1, 0xff,
+ 0xe0, 0x0, 0x3, 0xff, 0xf8, 0x0, 0x0, 0x3f,
+ 0xf8, 0x0, 0x0, 0x7, 0xff, 0xc0, 0x0, 0x7,
+ 0xfe, 0x0, 0x0, 0x0, 0x3f, 0xfe, 0x0, 0x0,
+ 0xff, 0xc0, 0x0, 0x0, 0x0, 0xff, 0xf0, 0x0,
+ 0x1f, 0xf8, 0x0, 0x0, 0x0, 0x3, 0xff, 0x80,
+ 0x3, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xfc,
+ 0x0, 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff,
+ 0xe0, 0xf, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xff, 0x0, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0,
+ 0x1f, 0xf0, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xff, 0x81, 0xfe, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xf8, 0x3f, 0xe0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7f, 0xc3, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3, 0xfc, 0x7f, 0xc0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xe7, 0xf8, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xfe, 0x7f, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0xe7, 0xf8, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xf0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xff,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1, 0xfe, 0x7f, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1f, 0xe7, 0xf8, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x1, 0xfe, 0x7f, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe7, 0xfc, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3, 0xfc, 0x3f, 0xc0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xc3, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, 0x1f,
+ 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x81,
+ 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf0,
+ 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff,
+ 0x0, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7f,
+ 0xe0, 0x7, 0xfe, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xfc, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x0, 0x1,
+ 0xff, 0x80, 0x3, 0xff, 0xc0, 0x0, 0x0, 0x0,
+ 0x7f, 0xf0, 0x0, 0x1f, 0xff, 0x0, 0x0, 0x0,
+ 0x1f, 0xfe, 0x0, 0x0, 0x7f, 0xfe, 0x0, 0x0,
+ 0xf, 0xff, 0xc0, 0x0, 0x3, 0xff, 0xfe, 0x0,
+ 0xf, 0xff, 0xf8, 0x0, 0x0, 0x1f, 0xff, 0xff,
+ 0xff, 0xff, 0xfe, 0x0, 0x0, 0x0, 0x7f, 0xff,
+ 0xff, 0xff, 0xff, 0xc0, 0x0, 0x0, 0x1, 0xff,
+ 0xff, 0xff, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x7,
+ 0xff, 0xff, 0xff, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x7, 0xff, 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x7, 0xff, 0xf8, 0x0, 0x0, 0x0,
+
+ /* U+0039 "9" */
+ 0x0, 0x0, 0x0, 0x1f, 0xfe, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xff, 0xfe, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xf, 0xff, 0xff, 0xfc, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xff, 0xff, 0xff, 0xf0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0xff, 0xff,
+ 0xc0, 0x0, 0x0, 0x0, 0x3f, 0xff, 0xff, 0xff,
+ 0xfe, 0x0, 0x0, 0x0, 0x7, 0xff, 0xf0, 0x3,
+ 0xff, 0xf8, 0x0, 0x0, 0x0, 0xff, 0xf0, 0x0,
+ 0x3, 0xff, 0xc0, 0x0, 0x0, 0x1f, 0xfc, 0x0,
+ 0x0, 0xf, 0xfe, 0x0, 0x0, 0x3, 0xff, 0x0,
+ 0x0, 0x0, 0x3f, 0xf0, 0x0, 0x0, 0x7f, 0xc0,
+ 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0xf, 0xf8,
+ 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0, 0x1, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x3f, 0xe0, 0x0, 0x3f,
+ 0xe0, 0x0, 0x0, 0x0, 0x1, 0xfe, 0x0, 0x3,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0,
+ 0x7f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80,
+ 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8,
+ 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f,
+ 0xc0, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x1,
+ 0xfc, 0x1, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1f, 0xe0, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xfe, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xf0, 0x3f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7f, 0x3, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x7, 0xf0, 0x7f, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0x87, 0xf8, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xf8, 0x7f, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3f, 0x87, 0xf8, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xfc, 0xff, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xcf, 0xf0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfc, 0xff,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xcf,
+ 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe,
+ 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xef, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xfe, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xf, 0xef, 0xf0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xfe, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xef, 0xf0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xfe, 0xff, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xff, 0xff, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0xf, 0xff, 0xf0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0xff, 0x80, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf7, 0xf8, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x7f, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf7, 0xf8,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x7f,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3f, 0xf3,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7, 0xff,
+ 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f,
+ 0xf3, 0xfe, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf,
+ 0xff, 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x1,
+ 0xff, 0xf1, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3f, 0xff, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0,
+ 0x7, 0xf7, 0xf0, 0xff, 0x80, 0x0, 0x0, 0x0,
+ 0x0, 0xfe, 0x7f, 0x7, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x1f, 0xc7, 0xf0, 0x7f, 0xe0, 0x0, 0x0,
+ 0x0, 0x3, 0xf8, 0x7f, 0x3, 0xff, 0x80, 0x0,
+ 0x0, 0x0, 0xff, 0xf, 0xf0, 0x1f, 0xfc, 0x0,
+ 0x0, 0x0, 0x1f, 0xe0, 0xff, 0x0, 0xff, 0xf0,
+ 0x0, 0x0, 0x7, 0xfc, 0xf, 0xf0, 0x7, 0xff,
+ 0xc0, 0x0, 0x3, 0xff, 0x80, 0xfe, 0x0, 0x3f,
+ 0xff, 0xc0, 0x3, 0xff, 0xf0, 0xf, 0xe0, 0x1,
+ 0xff, 0xff, 0xff, 0xff, 0xfc, 0x0, 0xfe, 0x0,
+ 0x7, 0xff, 0xff, 0xff, 0xff, 0x0, 0xf, 0xe0,
+ 0x0, 0x1f, 0xff, 0xff, 0xff, 0xe0, 0x0, 0xfe,
+ 0x0, 0x0, 0x7f, 0xff, 0xff, 0xf0, 0x0, 0xf,
+ 0xe0, 0x0, 0x0, 0xff, 0xff, 0xf8, 0x0, 0x1,
+ 0xfe, 0x0, 0x0, 0x0, 0xff, 0xf8, 0x0, 0x0,
+ 0x1f, 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x1, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3, 0xfc, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0x80, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3, 0xf8, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7f, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x7, 0xf8, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xf0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xe0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1f,
+ 0xe0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3,
+ 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x3f, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x7f, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0xf, 0xf8, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x1f, 0xf0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x3, 0xfe, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x3f, 0xc0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x7, 0xfc, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0xff, 0x80, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x1f, 0xf0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x3, 0xff, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xe0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfc, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff, 0x80,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7f, 0xf0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf, 0xfe,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3, 0xff,
+ 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xff,
+ 0xf8, 0x0, 0x0, 0x1, 0x80, 0x0, 0x0, 0xff,
+ 0xff, 0x0, 0x0, 0x0, 0x1f, 0xe0, 0x0, 0xff,
+ 0xff, 0xc0, 0x0, 0x0, 0x1, 0xff, 0xff, 0xff,
+ 0xff, 0xf0, 0x0, 0x0, 0x0, 0x1f, 0xff, 0xff,
+ 0xff, 0xfc, 0x0, 0x0, 0x0, 0x1, 0xff, 0xff,
+ 0xff, 0xff, 0x0, 0x0, 0x0, 0x0, 0x1f, 0xff,
+ 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0xff,
+ 0xff, 0xff, 0xc0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x7f, 0xff, 0x80, 0x0, 0x0, 0x0, 0x0
+};
+
+
+/*---------------------
+ * GLYPH DESCRIPTION
+ *--------------------*/
+
+static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
+ {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */,
+ {.bitmap_index = 0, .adv_w = 1370, .box_w = 69, .box_h = 110, .ofs_x = 8, .ofs_y = -1},
+ {.bitmap_index = 949, .adv_w = 1370, .box_w = 35, .box_h = 107, .ofs_x = 15, .ofs_y = 0},
+ {.bitmap_index = 1418, .adv_w = 1370, .box_w = 67, .box_h = 108, .ofs_x = 8, .ofs_y = 0},
+ {.bitmap_index = 2323, .adv_w = 1370, .box_w = 68, .box_h = 110, .ofs_x = 7, .ofs_y = -1},
+ {.bitmap_index = 3258, .adv_w = 1370, .box_w = 81, .box_h = 108, .ofs_x = 3, .ofs_y = -1},
+ {.bitmap_index = 4352, .adv_w = 1370, .box_w = 66, .box_h = 108, .ofs_x = 10, .ofs_y = -1},
+ {.bitmap_index = 5243, .adv_w = 1370, .box_w = 69, .box_h = 110, .ofs_x = 9, .ofs_y = -1},
+ {.bitmap_index = 6192, .adv_w = 1370, .box_w = 69, .box_h = 106, .ofs_x = 8, .ofs_y = 0},
+ {.bitmap_index = 7107, .adv_w = 1370, .box_w = 68, .box_h = 110, .ofs_x = 9, .ofs_y = -1},
+ {.bitmap_index = 8042, .adv_w = 1370, .box_w = 68, .box_h = 110, .ofs_x = 8, .ofs_y = -1}
+};
+
+/*---------------------
+ * CHARACTER MAPPING
+ *--------------------*/
+
+
+
+/*Collect the unicode lists and glyph_id offsets*/
+static const lv_font_fmt_txt_cmap_t cmaps[] =
+{
+ {
+ .range_start = 48, .range_length = 10, .glyph_id_start = 1,
+ .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY
+ }
+};
+
+
+
+/*--------------------
+ * ALL CUSTOM DATA
+ *--------------------*/
+
+#if LV_VERSION_CHECK(8, 0, 0)
+/*Store all the custom data of the font*/
+static lv_font_fmt_txt_glyph_cache_t cache;
+static const lv_font_fmt_txt_dsc_t font_dsc = {
+#else
+static lv_font_fmt_txt_dsc_t font_dsc = {
+#endif
+ .glyph_bitmap = glyph_bitmap,
+ .glyph_dsc = glyph_dsc,
+ .cmaps = cmaps,
+ .kern_dsc = NULL,
+ .kern_scale = 0,
+ .cmap_num = 1,
+ .bpp = 1,
+ .kern_classes = 0,
+ .bitmap_format = 0,
+#if LV_VERSION_CHECK(8, 0, 0)
+ .cache = &cache
+#endif
+};
+
+
+/*-----------------
+ * PUBLIC FONT
+ *----------------*/
+
+/*Initialize a public general font descriptor*/
+#if LV_VERSION_CHECK(8, 0, 0)
+const lv_font_t open_sans_light = {
+#else
+lv_font_t open_sans_light = {
+#endif
+ .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/
+ .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/
+ .line_height = 110, /*The maximum line height required by the font*/
+ .base_line = 1, /*Baseline measured from the bottom of the line*/
+#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0)
+ .subpx = LV_FONT_SUBPX_NONE,
+#endif
+#if LV_VERSION_CHECK(7, 4, 0)
+ .underline_position = -11,
+ .underline_thickness = 7,
+#endif
+ .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */
+};
+
+
+
+#endif /*#if OPEN_SANS_LIGHT*/
+
diff --git a/src/displayapp/fonts/open_sans_light.ttf b/src/displayapp/fonts/open_sans_light.ttf
new file mode 100644
index 00000000..6580d3a1
Binary files /dev/null and b/src/displayapp/fonts/open_sans_light.ttf differ
diff --git a/src/displayapp/lv_pinetime_theme.c b/src/displayapp/lv_pinetime_theme.c
index b003a411..1b8b1980 100644
--- a/src/displayapp/lv_pinetime_theme.c
+++ b/src/displayapp/lv_pinetime_theme.c
@@ -48,6 +48,7 @@ static lv_style_t style_sw_bg;
static lv_style_t style_sw_indic;
static lv_style_t style_sw_knob;
static lv_style_t style_arc_bg;
+static lv_style_t style_arc_knob;
static lv_style_t style_arc_indic;
static lv_style_t style_table_cell;
static lv_style_t style_pad_small;
@@ -191,6 +192,7 @@ static void basic_init(void) {
lv_style_set_text_line_space(&style_ddlist_list, LV_STATE_DEFAULT, LV_VER_RES / 25);
lv_style_set_shadow_width(&style_ddlist_list, LV_STATE_DEFAULT, LV_VER_RES / 20);
lv_style_set_shadow_color(&style_ddlist_list, LV_STATE_DEFAULT, LV_PINETIME_GRAY);
+ lv_style_set_bg_color(&style_ddlist_list, LV_STATE_DEFAULT, LV_PINETIME_GRAY);
style_init_reset(&style_ddlist_selected);
lv_style_set_bg_opa(&style_ddlist_selected, LV_STATE_DEFAULT, LV_OPA_COVER);
@@ -239,6 +241,13 @@ static void basic_init(void) {
lv_style_set_line_color(&style_arc_bg, LV_STATE_DEFAULT, LV_PINETIME_GRAY);
lv_style_set_line_width(&style_arc_bg, LV_STATE_DEFAULT, LV_DPX(25));
lv_style_set_line_rounded(&style_arc_bg, LV_STATE_DEFAULT, true);
+ lv_style_set_pad_all(&style_arc_bg, LV_STATE_DEFAULT, LV_DPX(5));
+
+ lv_style_reset(&style_arc_knob);
+ lv_style_set_radius(&style_arc_knob, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE);
+ lv_style_set_bg_opa(&style_arc_knob, LV_STATE_DEFAULT, LV_OPA_COVER);
+ lv_style_set_bg_color(&style_arc_knob, LV_STATE_DEFAULT, LV_PINETIME_LIGHT_GRAY);
+ lv_style_set_pad_all(&style_arc_knob, LV_STATE_DEFAULT, LV_DPX(5));
style_init_reset(&style_table_cell);
lv_style_set_border_color(&style_table_cell, LV_STATE_DEFAULT, LV_PINETIME_GRAY);
@@ -447,6 +456,10 @@ static void theme_apply(lv_obj_t* obj, lv_theme_style_t name) {
lv_obj_clean_style_list(obj, LV_ARC_PART_INDIC);
list = lv_obj_get_style_list(obj, LV_ARC_PART_INDIC);
_lv_style_list_add_style(list, &style_arc_indic);
+
+ lv_obj_clean_style_list(obj, LV_ARC_PART_KNOB);
+ list = lv_obj_get_style_list(obj, LV_ARC_PART_KNOB);
+ _lv_style_list_add_style(list, &style_arc_knob);
break;
case LV_THEME_SWITCH:
diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp
index d599f5cc..78c7cd9a 100644
--- a/src/displayapp/screens/ApplicationList.cpp
+++ b/src/displayapp/screens/ApplicationList.cpp
@@ -63,7 +63,7 @@ std::unique_ptr ApplicationList::CreateScreen2() {
{Symbols::paddle, Apps::Paddle},
{"2", Apps::Twos},
{"M", Apps::Motion},
- {"", Apps::None},
+ {Symbols::drum, Apps::Metronome},
{"", Apps::None},
}};
diff --git a/src/displayapp/screens/BatteryIcon.cpp b/src/displayapp/screens/BatteryIcon.cpp
index 6b54a305..bb6626a5 100644
--- a/src/displayapp/screens/BatteryIcon.cpp
+++ b/src/displayapp/screens/BatteryIcon.cpp
@@ -1,9 +1,10 @@
+#include
#include "BatteryIcon.h"
#include "Symbols.h"
using namespace Pinetime::Applications::Screens;
-const char* BatteryIcon::GetBatteryIcon(int batteryPercent) {
+const char* BatteryIcon::GetBatteryIcon(uint8_t batteryPercent) {
if (batteryPercent > 90)
return Symbols::batteryFull;
if (batteryPercent > 75)
diff --git a/src/displayapp/screens/BatteryIcon.h b/src/displayapp/screens/BatteryIcon.h
index 9c192ff7..b370b331 100644
--- a/src/displayapp/screens/BatteryIcon.h
+++ b/src/displayapp/screens/BatteryIcon.h
@@ -6,7 +6,7 @@ namespace Pinetime {
class BatteryIcon {
public:
static const char* GetUnknownIcon();
- static const char* GetBatteryIcon(int batteryPercent);
+ static const char* GetBatteryIcon(uint8_t batteryPercent);
static const char* GetPlugIcon(bool isCharging);
};
}
diff --git a/src/displayapp/screens/BatteryInfo.cpp b/src/displayapp/screens/BatteryInfo.cpp
index 1ab8b0ad..0ab47ebf 100644
--- a/src/displayapp/screens/BatteryInfo.cpp
+++ b/src/displayapp/screens/BatteryInfo.cpp
@@ -9,11 +9,6 @@ static void lv_update_task(struct _lv_task_t* task) {
user_data->UpdateScreen();
}
-static void lv_anim_task(struct _lv_task_t* task) {
- auto user_data = static_cast(task->user_data);
- user_data->UpdateAnim();
-}
-
BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Battery& batteryController)
: Screen(app), batteryController {batteryController} {
@@ -24,12 +19,12 @@ BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Cont
lv_obj_set_size(charging_bar, 200, 15);
lv_bar_set_range(charging_bar, 0, 100);
lv_obj_align(charging_bar, nullptr, LV_ALIGN_CENTER, 0, 10);
- lv_bar_set_anim_time(charging_bar, 2000);
+ lv_bar_set_anim_time(charging_bar, 1000);
lv_obj_set_style_local_radius(charging_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE);
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, lv_color_hex(0x222222));
lv_obj_set_style_local_bg_opa(charging_bar, LV_BAR_PART_BG, LV_STATE_DEFAULT, LV_OPA_100);
lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, lv_color_hex(0xFF0000));
- lv_bar_set_value(charging_bar, batteryPercent, LV_ANIM_OFF);
+ lv_bar_set_value(charging_bar, batteryPercent, LV_ANIM_ON);
status = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_static(status, "Reading Battery status");
@@ -38,24 +33,13 @@ BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Cont
percent = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_font(percent, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76);
- if (batteryPercent >= 0) {
- lv_label_set_text_fmt(percent, "%02i%%", batteryPercent);
- } else {
- lv_label_set_text(percent, "--%");
- }
+ lv_label_set_text_fmt(percent, "%02i%%", batteryPercent);
lv_label_set_align(percent, LV_LABEL_ALIGN_LEFT);
lv_obj_align(percent, nullptr, LV_ALIGN_CENTER, 0, -60);
- // hack to not use the flot functions from printf
- uint8_t batteryVoltageBytes[2];
- batteryVoltageBytes[1] = static_cast(batteryVoltage); // truncate whole numbers
- batteryVoltageBytes[0] =
- static_cast((batteryVoltage - batteryVoltageBytes[1]) * 100); // remove whole part of flt and shift 2 places over
- //
-
voltage = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(voltage, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xC6A600));
- lv_label_set_text_fmt(voltage, "%1i.%02i volts", batteryVoltageBytes[1], batteryVoltageBytes[0]);
+ lv_label_set_text_fmt(voltage, "%1i.%02i volts", batteryVoltage / 1000, batteryVoltage % 1000 / 10);
lv_label_set_align(voltage, LV_LABEL_ALIGN_CENTER);
lv_obj_align(voltage, nullptr, LV_ALIGN_CENTER, 0, 95);
@@ -65,40 +49,15 @@ BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Cont
lv_obj_set_pos(backgroundLabel, 0, 0);
lv_label_set_text_static(backgroundLabel, "");
- taskUpdate = lv_task_create(lv_update_task, 500000, LV_TASK_PRIO_LOW, this);
- taskAnim = lv_task_create(lv_anim_task, 1000, LV_TASK_PRIO_LOW, this);
+ taskUpdate = lv_task_create(lv_update_task, 5000, LV_TASK_PRIO_LOW, this);
UpdateScreen();
}
BatteryInfo::~BatteryInfo() {
lv_task_del(taskUpdate);
- lv_task_del(taskAnim);
lv_obj_clean(lv_scr_act());
}
-void BatteryInfo::UpdateAnim() {
- batteryPercent = batteryController.PercentRemaining();
-
- if (batteryPercent >= 0) {
- if (batteryController.IsCharging() and batteryPercent < 100) {
- animation += 1;
- if (animation >= 100) {
- animation = 0;
- }
-
- } else {
- if (animation > batteryPercent) {
- animation--;
- }
- if (animation < batteryPercent) {
- animation++;
- }
- }
-
- lv_bar_set_value(charging_bar, animation, LV_ANIM_OFF);
- }
-}
-
void BatteryInfo::UpdateScreen() {
batteryController.Update();
@@ -106,39 +65,27 @@ void BatteryInfo::UpdateScreen() {
batteryPercent = batteryController.PercentRemaining();
batteryVoltage = batteryController.Voltage();
- if (batteryPercent >= 0) {
- if (batteryController.IsCharging() and batteryPercent < 100) {
- 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, "Battery charging");
- } else if (batteryPercent == 100) {
- lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_BLUE);
- lv_label_set_text_static(status, "Battery is fully charged");
- } else if (batteryPercent < 10) {
- lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
- lv_label_set_text_static(status, "Battery is low");
- } else {
- lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_GREEN);
- lv_label_set_text_static(status, "Battery discharging");
- }
-
- lv_label_set_text_fmt(percent, "%02i%%", batteryPercent);
-
+ if (batteryController.IsCharging() and batteryPercent < 100) {
+ 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) {
+ lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_BLUE);
+ lv_label_set_text_static(status, "Fully charged");
+ } else if (batteryPercent < 10) {
+ lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
+ lv_label_set_text_static(status, "Battery low");
} else {
- lv_label_set_text_static(status, "Reading Battery status");
- lv_label_set_text(percent, "--%");
+ lv_obj_set_style_local_bg_color(charging_bar, LV_BAR_PART_INDIC, LV_STATE_DEFAULT, LV_COLOR_GREEN);
+ lv_label_set_text_static(status, "Discharging");
}
+ lv_label_set_text_fmt(percent, "%02i%%", batteryPercent);
+
lv_obj_align(status, charging_bar, LV_ALIGN_OUT_BOTTOM_MID, 0, 20);
- // hack to not use the flot functions from printf
- uint8_t batteryVoltageBytes[2];
- batteryVoltageBytes[1] = static_cast(batteryVoltage); // truncate whole numbers
- batteryVoltageBytes[0] =
- static_cast((batteryVoltage - batteryVoltageBytes[1]) * 100); // remove whole part of flt and shift 2 places over
- //
- lv_label_set_text_fmt(voltage, "%1i.%02i volts", batteryVoltageBytes[1], batteryVoltageBytes[0]);
+ lv_label_set_text_fmt(voltage, "%1i.%02i volts", batteryVoltage / 1000, batteryVoltage % 1000 / 10);
+ lv_bar_set_value(charging_bar, batteryPercent, LV_ANIM_ON);
}
bool BatteryInfo::Refresh() {
-
return running;
}
diff --git a/src/displayapp/screens/BatteryInfo.h b/src/displayapp/screens/BatteryInfo.h
index 8805db58..69793244 100644
--- a/src/displayapp/screens/BatteryInfo.h
+++ b/src/displayapp/screens/BatteryInfo.h
@@ -22,7 +22,6 @@ namespace Pinetime {
bool Refresh() override;
void UpdateScreen();
- void UpdateAnim();
private:
Pinetime::Controllers::Battery& batteryController;
@@ -33,11 +32,9 @@ namespace Pinetime {
lv_obj_t* status;
lv_task_t* taskUpdate;
- lv_task_t* taskAnim;
- int8_t animation = 0;
- int8_t batteryPercent = -1;
- float batteryVoltage = 0.0f;
+ uint8_t batteryPercent = 0;
+ uint16_t batteryVoltage = 0;
};
}
}
diff --git a/src/displayapp/screens/Clock.cpp b/src/displayapp/screens/Clock.cpp
index 14299840..e0684976 100644
--- a/src/displayapp/screens/Clock.cpp
+++ b/src/displayapp/screens/Clock.cpp
@@ -14,6 +14,7 @@
#include "../DisplayApp.h"
#include "WatchFaceDigital.h"
#include "WatchFaceAnalog.h"
+#include "PineTimeStyle.h"
using namespace Pinetime::Applications::Screens;
@@ -33,21 +34,20 @@ Clock::Clock(DisplayApp* app,
settingsController {settingsController},
heartRateController {heartRateController},
motionController {motionController},
- screens {app,
- settingsController.GetClockFace(),
- {
- [this]() -> std::unique_ptr {
- return WatchFaceDigitalScreen();
- },
- [this]() -> std::unique_ptr {
- return WatchFaceAnalogScreen();
- },
- // Examples for more watch faces
- //[this]() -> std::unique_ptr { return WatchFaceMinimalScreen(); },
- //[this]() -> std::unique_ptr { return WatchFaceCustomScreen(); }
- },
- Screens::ScreenListModes::LongPress} {
-
+ screen {[this, &settingsController]() {
+ switch (settingsController.GetClockFace()) {
+ case 0:
+ return WatchFaceDigitalScreen();
+ break;
+ case 1:
+ return WatchFaceAnalogScreen();
+ break;
+ case 2:
+ return PineTimeStyleScreen();
+ break;
+ }
+ return WatchFaceDigitalScreen();
+ }()} {
settingsController.SetAppMenu(0);
}
@@ -56,12 +56,12 @@ Clock::~Clock() {
}
bool Clock::Refresh() {
- screens.Refresh();
+ screen->Refresh();
return running;
}
bool Clock::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
- return screens.OnTouchEvent(event);
+ return screen->OnTouchEvent(event);
}
std::unique_ptr Clock::WatchFaceDigitalScreen() {
@@ -80,6 +80,16 @@ std::unique_ptr Clock::WatchFaceAnalogScreen() {
app, dateTimeController, batteryController, bleController, notificatioManager, settingsController);
}
+std::unique_ptr Clock::PineTimeStyleScreen() {
+ return std::make_unique(app,
+ dateTimeController,
+ batteryController,
+ bleController,
+ notificatioManager,
+ settingsController,
+ motionController);
+}
+
/*
// Examples for more watch faces
std::unique_ptr Clock::WatchFaceMinimalScreen() {
diff --git a/src/displayapp/screens/Clock.h b/src/displayapp/screens/Clock.h
index 9879985f..a48feea1 100644
--- a/src/displayapp/screens/Clock.h
+++ b/src/displayapp/screens/Clock.h
@@ -4,8 +4,8 @@
#include
#include
#include
+#include
#include "Screen.h"
-#include "ScreenList.h"
#include "components/datetime/DateTimeController.h"
namespace Pinetime {
@@ -47,9 +47,10 @@ namespace Pinetime {
Controllers::HeartRateController& heartRateController;
Controllers::MotionController& motionController;
- ScreenList<2> screens;
+ std::unique_ptr screen;
std::unique_ptr WatchFaceDigitalScreen();
std::unique_ptr WatchFaceAnalogScreen();
+ std::unique_ptr PineTimeStyleScreen();
// Examples for more watch faces
// std::unique_ptr WatchFaceMinimalScreen();
diff --git a/src/displayapp/screens/FirmwareValidation.cpp b/src/displayapp/screens/FirmwareValidation.cpp
index ad37a3df..1d05be8d 100644
--- a/src/displayapp/screens/FirmwareValidation.cpp
+++ b/src/displayapp/screens/FirmwareValidation.cpp
@@ -16,30 +16,18 @@ namespace {
FirmwareValidation::FirmwareValidation(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::FirmwareValidator& validator)
: Screen {app}, validator {validator} {
- labelVersionInfo = lv_label_create(lv_scr_act(), nullptr);
- lv_obj_align(labelVersionInfo, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0);
- lv_label_set_text(labelVersionInfo, "Version : ");
- lv_label_set_align(labelVersionInfo, LV_LABEL_ALIGN_LEFT);
-
- labelVersionValue = lv_label_create(lv_scr_act(), nullptr);
- lv_obj_align(labelVersionValue, labelVersionInfo, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
- lv_label_set_recolor(labelVersionValue, true);
- sprintf(version, "%ld.%ld.%ld", Version::Major(), Version::Minor(), Version::Patch());
- lv_label_set_text(labelVersionValue, version);
-
- labelShortRefInfo = lv_label_create(lv_scr_act(), nullptr);
- lv_obj_align(labelShortRefInfo, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 25);
- lv_label_set_text(labelShortRefInfo, "ShortRef : ");
- lv_label_set_align(labelShortRefInfo, LV_LABEL_ALIGN_LEFT);
-
- labelShortRefValue = lv_label_create(lv_scr_act(), nullptr);
- lv_obj_align(labelShortRefValue, labelShortRefInfo, LV_ALIGN_OUT_RIGHT_MID, 0, 0);
- lv_label_set_recolor(labelShortRefValue, true);
- sprintf(shortref, "%s", Version::GitCommitHash());
- lv_label_set_text(labelShortRefValue, shortref);
+ labelVersion = lv_label_create(lv_scr_act(), nullptr);
+ lv_label_set_text_fmt(labelVersion,
+ "Version : %d.%d.%d\n"
+ "ShortRef : %s",
+ Version::Major(),
+ Version::Minor(),
+ Version::Patch(),
+ Version::GitCommitHash());
+ lv_obj_align(labelVersion, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 0);
labelIsValidated = lv_label_create(lv_scr_act(), nullptr);
- lv_obj_align(labelIsValidated, nullptr, LV_ALIGN_IN_TOP_LEFT, 0, 50);
+ lv_obj_align(labelIsValidated, labelVersion, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
lv_label_set_recolor(labelIsValidated, true);
lv_label_set_long_mode(labelIsValidated, LV_LABEL_LONG_BREAK);
lv_obj_set_width(labelIsValidated, 240);
diff --git a/src/displayapp/screens/FirmwareValidation.h b/src/displayapp/screens/FirmwareValidation.h
index 303c2154..1ef5ba0a 100644
--- a/src/displayapp/screens/FirmwareValidation.h
+++ b/src/displayapp/screens/FirmwareValidation.h
@@ -23,12 +23,7 @@ namespace Pinetime {
private:
Pinetime::Controllers::FirmwareValidator& validator;
- lv_obj_t* labelVersionInfo;
- lv_obj_t* labelVersionValue;
- lv_obj_t* labelShortRefInfo;
- lv_obj_t* labelShortRefValue;
- char version[9];
- char shortref[9];
+ lv_obj_t* labelVersion;
lv_obj_t* labelIsValidated;
lv_obj_t* buttonValidate;
lv_obj_t* labelButtonValidate;
diff --git a/src/displayapp/screens/FlashLight.cpp b/src/displayapp/screens/FlashLight.cpp
index 8d647a36..63b2345e 100644
--- a/src/displayapp/screens/FlashLight.cpp
+++ b/src/displayapp/screens/FlashLight.cpp
@@ -39,14 +39,14 @@ FlashLight::FlashLight(Pinetime::Applications::DisplayApp* app,
backgroundAction->user_data = this;
lv_obj_set_event_cb(backgroundAction, event_handler);
- systemTask.PushMessage(Pinetime::System::SystemTask::Messages::DisableSleeping);
+ systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
}
FlashLight::~FlashLight() {
lv_obj_clean(lv_scr_act());
lv_obj_set_style_local_bg_color(lv_scr_act(), LV_OBJ_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
brightness.Restore();
- systemTask.PushMessage(Pinetime::System::SystemTask::Messages::EnableSleeping);
+ systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
}
void FlashLight::OnClickEvent(lv_obj_t* obj, lv_event_t event) {
diff --git a/src/displayapp/screens/HeartRate.cpp b/src/displayapp/screens/HeartRate.cpp
index 90f6bc26..5689b63e 100644
--- a/src/displayapp/screens/HeartRate.cpp
+++ b/src/displayapp/screens/HeartRate.cpp
@@ -63,12 +63,12 @@ HeartRate::HeartRate(Pinetime::Applications::DisplayApp* app,
label_startStop = lv_label_create(btn_startStop, nullptr);
UpdateStartStopButton(isHrRunning);
if (isHrRunning)
- systemTask.PushMessage(Pinetime::System::SystemTask::Messages::DisableSleeping);
+ systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
}
HeartRate::~HeartRate() {
lv_obj_clean(lv_scr_act());
- systemTask.PushMessage(Pinetime::System::SystemTask::Messages::EnableSleeping);
+ systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
}
bool HeartRate::Refresh() {
@@ -95,12 +95,12 @@ void HeartRate::OnStartStopEvent(lv_event_t event) {
if (heartRateController.State() == Controllers::HeartRateController::States::Stopped) {
heartRateController.Start();
UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped);
- systemTask.PushMessage(Pinetime::System::SystemTask::Messages::DisableSleeping);
+ systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
} else {
heartRateController.Stop();
UpdateStartStopButton(heartRateController.State() != Controllers::HeartRateController::States::Stopped);
- systemTask.PushMessage(Pinetime::System::SystemTask::Messages::EnableSleeping);
+ systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
lv_obj_set_style_local_text_color(label_hr, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
}
}
diff --git a/src/displayapp/screens/Metronome.cpp b/src/displayapp/screens/Metronome.cpp
new file mode 100644
index 00000000..7bfbccb7
--- /dev/null
+++ b/src/displayapp/screens/Metronome.cpp
@@ -0,0 +1,169 @@
+#include "Metronome.h"
+
+#include "Screen.h"
+#include "Symbols.h"
+#include "lvgl/lvgl.h"
+#include "FreeRTOSConfig.h"
+#include "task.h"
+
+#include
+#include
+
+using namespace Pinetime::Applications::Screens;
+
+namespace {
+ float calculateDelta(const TickType_t startTime, const TickType_t currentTime) {
+ TickType_t delta = 0;
+ // Take care of overflow
+ if (startTime > currentTime) {
+ delta = 0xffffffff - startTime;
+ delta += (currentTime + 1);
+ } else {
+ delta = currentTime - startTime;
+ }
+ return static_cast(delta) / static_cast(configTICK_RATE_HZ);
+ }
+
+ static void eventHandler(lv_obj_t* obj, lv_event_t event) {
+ Metronome* screen = static_cast(obj->user_data);
+ screen->OnEvent(obj, event);
+ }
+
+ lv_obj_t* createLabel(const char* name, lv_obj_t* reference, lv_align_t align, lv_font_t* font, uint8_t x = 0, uint8_t y = 0) {
+ lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_text_font(label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, font);
+ lv_obj_set_style_local_text_color(label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
+ lv_label_set_text(label, name);
+ lv_obj_align(label, reference, align, x, y);
+
+ return label;
+ }
+}
+
+Metronome::Metronome(DisplayApp* app, Controllers::MotorController& motorController, System::SystemTask& systemTask)
+ : Screen(app), running {true}, currentState {States::Stopped}, startTime {}, motorController {motorController}, systemTask {systemTask} {
+
+ bpmArc = lv_arc_create(lv_scr_act(), nullptr);
+ bpmArc->user_data = this;
+ lv_obj_set_event_cb(bpmArc, eventHandler);
+ lv_arc_set_bg_angles(bpmArc, 0, 270);
+ lv_arc_set_rotation(bpmArc, 135);
+ lv_arc_set_range(bpmArc, 40, 220);
+ lv_arc_set_value(bpmArc, bpm);
+ lv_obj_set_size(bpmArc, 210, 210);
+ lv_arc_set_adjustable(bpmArc, true);
+ lv_obj_align(bpmArc, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 7);
+
+ bpmValue = createLabel(std::to_string(lv_arc_get_value(bpmArc)).c_str(), bpmArc, LV_ALIGN_IN_TOP_MID, &jetbrains_mono_76, 0, 55);
+ bpmLegend = createLabel("bpm", bpmValue, LV_ALIGN_OUT_BOTTOM_MID, &jetbrains_mono_bold_20, 0, 0);
+
+ bpmTap = lv_btn_create(lv_scr_act(), nullptr);
+ bpmTap->user_data = this;
+ lv_obj_set_event_cb(bpmTap, eventHandler);
+ lv_obj_set_style_local_bg_opa(bpmTap, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_TRANSP);
+ lv_obj_set_height(bpmTap, 80);
+ lv_obj_align(bpmTap, bpmValue, LV_ALIGN_IN_TOP_MID, 0, 0);
+
+ bpbDropdown = lv_dropdown_create(lv_scr_act(), nullptr);
+ bpbDropdown->user_data = this;
+ lv_obj_set_event_cb(bpbDropdown, eventHandler);
+ lv_obj_set_style_local_pad_left(bpbDropdown, LV_DROPDOWN_PART_MAIN, LV_STATE_DEFAULT, 20);
+ lv_obj_set_style_local_pad_left(bpbDropdown, LV_DROPDOWN_PART_LIST, LV_STATE_DEFAULT, 20);
+ lv_obj_align(bpbDropdown, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 15, -4);
+ lv_dropdown_set_options(bpbDropdown, "1\n2\n3\n4\n5\n6\n7\n8\n9");
+ lv_dropdown_set_selected(bpbDropdown, bpb - 1);
+ bpbLegend = lv_label_create(bpbDropdown, nullptr);
+ lv_label_set_text(bpbLegend, "bpb");
+ lv_obj_align(bpbLegend, bpbDropdown, LV_ALIGN_IN_RIGHT_MID, -15, 0);
+
+ playPause = lv_btn_create(lv_scr_act(), nullptr);
+ playPause->user_data = this;
+ lv_obj_set_event_cb(playPause, eventHandler);
+ lv_obj_align(playPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -15, -10);
+ lv_obj_set_height(playPause, 39);
+ playPauseLabel = lv_label_create(playPause, nullptr);
+ lv_label_set_text(playPauseLabel, Symbols::play);
+
+ app->SetTouchMode(DisplayApp::TouchModes::Polling);
+}
+
+Metronome::~Metronome() {
+ app->SetTouchMode(DisplayApp::TouchModes::Gestures);
+ systemTask.PushMessage(System::Messages::EnableSleeping);
+ lv_obj_clean(lv_scr_act());
+}
+
+bool Metronome::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
+ return true;
+}
+
+bool Metronome::Refresh() {
+ switch (currentState) {
+ case States::Stopped: {
+ break;
+ }
+ case States::Running: {
+ if (calculateDelta(startTime, xTaskGetTickCount()) >= (60.0 / bpm)) {
+ counter--;
+ startTime -= 60.0 / bpm;
+ startTime = xTaskGetTickCount();
+ if (counter == 0) {
+ counter = bpb;
+ motorController.SetDuration(90);
+ } else {
+ motorController.SetDuration(30);
+ }
+ }
+ break;
+ }
+ }
+ return running;
+}
+
+void Metronome::OnEvent(lv_obj_t* obj, lv_event_t event) {
+ switch (event) {
+ case LV_EVENT_VALUE_CHANGED: {
+ if (obj == bpmArc) {
+ bpm = lv_arc_get_value(bpmArc);
+ lv_label_set_text_fmt(bpmValue, "%03d", bpm);
+ } else if (obj == bpbDropdown) {
+ bpb = lv_dropdown_get_selected(obj) + 1;
+ }
+ break;
+ }
+ case LV_EVENT_PRESSED: {
+ if (obj == bpmTap) {
+ float timeDelta = calculateDelta(tappedTime, xTaskGetTickCount());
+ if (tappedTime == 0 || timeDelta > 3) {
+ tappedTime = xTaskGetTickCount();
+ } else {
+ bpm = ceil(60.0 / timeDelta);
+ lv_arc_set_value(bpmArc, bpm);
+ lv_label_set_text_fmt(bpmValue, "%03d", bpm);
+ tappedTime = xTaskGetTickCount();
+ }
+ }
+ break;
+ }
+ case LV_EVENT_CLICKED: {
+ if (obj == playPause) {
+ currentState = (currentState == States::Stopped ? States::Running : States::Stopped);
+ switch (currentState) {
+ case States::Stopped: {
+ lv_label_set_text(playPauseLabel, Symbols::play);
+ systemTask.PushMessage(System::Messages::EnableSleeping);
+ break;
+ }
+ case States::Running: {
+ lv_label_set_text(playPauseLabel, Symbols::pause);
+ systemTask.PushMessage(System::Messages::DisableSleeping);
+ startTime = xTaskGetTickCount();
+ counter = 1;
+ break;
+ }
+ }
+ }
+ break;
+ }
+ }
+}
diff --git a/src/displayapp/screens/Metronome.h b/src/displayapp/screens/Metronome.h
new file mode 100644
index 00000000..3a1f1084
--- /dev/null
+++ b/src/displayapp/screens/Metronome.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include "systemtask/SystemTask.h"
+#include "components/motor/MotorController.h"
+
+#include
+
+namespace Pinetime::Applications::Screens {
+
+ class Metronome : public Screen {
+ public:
+ Metronome(DisplayApp* app, Controllers::MotorController& motorController, System::SystemTask& systemTask);
+ ~Metronome() override;
+ bool Refresh() override;
+ bool OnTouchEvent(TouchEvents event) override;
+ void OnEvent(lv_obj_t* obj, lv_event_t event);
+ enum class States { Running, Stopped };
+
+ private:
+ bool running;
+ States currentState;
+ TickType_t startTime;
+ TickType_t tappedTime = 0;
+ Controllers::MotorController& motorController;
+ System::SystemTask& systemTask;
+ uint16_t bpm = 120;
+ uint8_t bpb = 4;
+ uint8_t counter = 1;
+
+ lv_obj_t *bpmArc, *bpmTap, *bpmValue, *bpmLegend;
+ lv_obj_t *bpbDropdown, *bpbLegend;
+ lv_obj_t *playPause, *playPauseLabel;
+ };
+}
diff --git a/src/displayapp/screens/Notifications.cpp b/src/displayapp/screens/Notifications.cpp
index 1a1729ea..38b12420 100644
--- a/src/displayapp/screens/Notifications.cpp
+++ b/src/displayapp/screens/Notifications.cpp
@@ -163,10 +163,10 @@ Notifications::NotificationItem::NotificationItem(const char* title,
lv_obj_set_style_local_border_width(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
lv_obj_set_pos(container1, 0, 50);
- lv_obj_set_width(container1, 240);
- lv_obj_set_height(container1, 190);
+ lv_obj_set_size(container1, LV_HOR_RES, 190);
lv_cont_set_layout(container1, LV_LAYOUT_COLUMN_LEFT);
+ lv_cont_set_fit(container1, LV_FIT_NONE);
lv_obj_t* alert_count = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_text_fmt(alert_count, "%i/%i", notifNr, notifNb);
@@ -198,6 +198,7 @@ Notifications::NotificationItem::NotificationItem(const char* title,
lv_label_set_text(alert_subject, msg);
} break;
case Controllers::NotificationManager::Categories::IncomingCall: {
+ lv_obj_set_height(container1, 108);
lv_obj_t* alert_subject = lv_label_create(container1, nullptr);
lv_obj_set_style_local_text_color(alert_subject, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_ORANGE);
lv_label_set_long_mode(alert_subject, LV_LABEL_LONG_BREAK);
@@ -210,38 +211,29 @@ Notifications::NotificationItem::NotificationItem(const char* title,
lv_obj_set_width(alert_caller, LV_HOR_RES - 20);
lv_label_set_text(alert_caller, msg);
- lv_obj_t* callBtnContainer = lv_cont_create(container1, NULL);
- lv_obj_set_width(callBtnContainer, 240);
- lv_obj_set_height(callBtnContainer, 90);
- lv_cont_set_layout(callBtnContainer, LV_LAYOUT_ROW_MID);
-
- lv_obj_set_style_local_bg_color(callBtnContainer, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x222222));
- lv_obj_set_style_local_pad_all(callBtnContainer, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
- lv_obj_set_style_local_margin_top(callBtnContainer, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 40);
- lv_obj_set_style_local_margin_left(callBtnContainer, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, -8);
- lv_obj_set_style_local_pad_inner(callBtnContainer, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 5);
- lv_obj_set_style_local_border_width(callBtnContainer, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, 0);
-
- bt_accept = lv_btn_create(callBtnContainer, nullptr);
+ bt_accept = lv_btn_create(lv_scr_act(), nullptr);
bt_accept->user_data = this;
lv_obj_set_event_cb(bt_accept, AcceptIncomingCallEventHandler);
- lv_obj_set_size(bt_accept, (LV_HOR_RES / 3) - 5, 80);
+ lv_obj_set_size(bt_accept, 76, 76);
+ lv_obj_align(bt_accept, NULL, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
label_accept = lv_label_create(bt_accept, nullptr);
lv_label_set_text(label_accept, Symbols::phone);
lv_obj_set_style_local_bg_color(bt_accept, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
- bt_reject = lv_btn_create(callBtnContainer, nullptr);
+ bt_reject = lv_btn_create(lv_scr_act(), nullptr);
bt_reject->user_data = this;
lv_obj_set_event_cb(bt_reject, RejectIncomingCallEventHandler);
- lv_obj_set_size(bt_reject, (LV_HOR_RES / 3) - 5, 80);
+ lv_obj_set_size(bt_reject, 76, 76);
+ lv_obj_align(bt_reject, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
label_reject = lv_label_create(bt_reject, nullptr);
lv_label_set_text(label_reject, Symbols::phoneSlash);
lv_obj_set_style_local_bg_color(bt_reject, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED);
- bt_mute = lv_btn_create(callBtnContainer, nullptr);
+ bt_mute = lv_btn_create(lv_scr_act(), nullptr);
bt_mute->user_data = this;
lv_obj_set_event_cb(bt_mute, MuteIncomingCallEventHandler);
- lv_obj_set_size(bt_mute, (LV_HOR_RES / 3) - 5, 80);
+ lv_obj_set_size(bt_mute, 76, 76);
+ lv_obj_align(bt_mute, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
label_mute = lv_label_create(bt_mute, nullptr);
lv_label_set_text(label_mute, Symbols::volumMute);
lv_obj_set_style_local_bg_color(bt_mute, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
diff --git a/src/displayapp/screens/Paddle.cpp b/src/displayapp/screens/Paddle.cpp
index 161f175b..5a939ac7 100644
--- a/src/displayapp/screens/Paddle.cpp
+++ b/src/displayapp/screens/Paddle.cpp
@@ -4,98 +4,31 @@
using namespace Pinetime::Applications::Screens;
-namespace {
- const uint8_t paddle_map[] = {
- 0xfc, 0xfe, 0xfc, 0xff, /*Color of index 0*/
- 0xff, 0xff, 0xff, 0xff, /*Color of index 1*/
-
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- };
-
- const uint8_t ball_map[] = {
- 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed,
- 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed,
- 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed,
- 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed,
- 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed,
- 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed,
- 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed,
- 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed,
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed,
- 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed, 0x6f, 0xed,
- };
-}
-
Paddle::Paddle(Pinetime::Applications::DisplayApp* app, Pinetime::Components::LittleVgl& lvgl) : Screen(app), lvgl {lvgl} {
app->SetTouchMode(DisplayApp::TouchModes::Polling);
+ background = lv_obj_create(lv_scr_act(), nullptr);
+ lv_obj_set_size(background, LV_HOR_RES + 1, LV_VER_RES);
+ lv_obj_set_pos(background, -1, 0);
+ lv_obj_set_style_local_radius(background, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
+ lv_obj_set_style_local_bg_color(background, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
+ lv_obj_set_style_local_border_color(background, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
+ lv_obj_set_style_local_border_width(background, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 1);
+
points = lv_label_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_text_font(points, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42);
lv_label_set_text(points, "0000");
- lv_obj_set_style_local_text_color(points, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x444444));
- lv_obj_align(points, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0);
+ lv_obj_align(points, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 10);
- paddle.header.always_zero = 0;
- paddle.header.w = 4;
- paddle.header.h = 60;
- paddle.data_size = 68;
- paddle.header.cf = LV_IMG_CF_INDEXED_1BIT;
- paddle.data = paddle_map;
- paddle_image = lv_img_create(lv_scr_act(), nullptr);
- lv_img_set_src(paddle_image, &paddle);
+ paddle = lv_obj_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_bg_color(paddle, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
+ lv_obj_set_style_local_radius(paddle, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
+ lv_obj_set_size(paddle, 4, 60);
- ball.header.always_zero = 0;
- ball.header.w = 24;
- ball.header.h = 24;
- ball.data_size = 24 * 24 * LV_COLOR_SIZE / 8;
- ball.header.cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED;
- ball.data = ball_map;
- ball_image = lv_img_create(lv_scr_act(), nullptr);
- lv_img_set_src(ball_image, &ball);
+ ball = lv_obj_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_bg_color(ball, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
+ lv_obj_set_style_local_radius(ball, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_RADIUS_CIRCLE);
+ lv_obj_set_size(ball, ballSize, ballSize);
}
Paddle::~Paddle() {
@@ -105,41 +38,37 @@ Paddle::~Paddle() {
}
bool Paddle::Refresh() {
- if ((counter++ % 5) == 0) {
- counter = 0;
+ ballX += dx;
+ ballY += dy;
- ballX += dx;
- ballY += dy;
+ lv_obj_set_pos(ball, ballX, ballY);
- lv_obj_set_pos(ball_image, ballX, ballY);
+ // checks if it has touched the sides (floor and ceiling)
+ if (ballY <= 1 || ballY >= LV_VER_RES - ballSize - 2) {
+ dy *= -1;
+ }
- // checks if it has touched the sides (floor and ceiling)
- if (ballY <= 0 || ballY >= 215) {
- dy *= -1;
- }
+ // checks if it has touched the side (left side)
+ if (ballX >= LV_VER_RES - ballSize - 1) {
+ dx *= -1;
+ }
- // checks if it has touched the side (left side)
- if (ballX >= 215) {
- dx *= -1;
- }
-
- // checks if it is in the position of the paddle
- if (ballY <= (paddleBottomY + 16) && ballY >= (paddleTopY - 8)) {
- if (ballX >= 0 && ballX < 4) {
- lv_obj_set_pos(ball_image, 5, ballY);
+ // checks if it is in the position of the paddle
+ if (dx < 0 && ballX <= 4) {
+ if (ballX >= -ballSize / 4) {
+ if (ballY <= (paddlePos + 30 - ballSize / 4) && ballY >= (paddlePos - 30 - ballSize + ballSize / 4)) {
dx *= -1;
score++;
}
}
-
// checks if it has gone behind the paddle
- else if (ballX <= -40) {
- ballX = 107;
- ballY = 107;
+ else if (ballX <= -ballSize * 2) {
+ ballX = (LV_HOR_RES - ballSize) / 2;
+ ballY = (LV_VER_RES - ballSize) / 2;
score = 0;
}
- lv_label_set_text_fmt(points, "%04d", score);
}
+ lv_label_set_text_fmt(points, "%04d", score);
return running;
}
@@ -148,11 +77,8 @@ bool Paddle::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
}
bool Paddle::OnTouchEvent(uint16_t x, uint16_t y) {
- lv_obj_set_pos(
- paddle_image,
- 0,
- y - 30); // sets the center paddle pos. (30px offset) with the the y_coordinate of the finger and defaults the x_coordinate to 0
- paddleTopY = y - 30; // refreshes the upper extreme of the paddle
- paddleBottomY = y + 30; // refreshes the lower extreme of the paddle
+ // sets the center paddle pos. (30px offset) with the the y_coordinate of the finger
+ lv_obj_set_pos(paddle, 0, y - 30);
+ paddlePos = y;
return true;
}
diff --git a/src/displayapp/screens/Paddle.h b/src/displayapp/screens/Paddle.h
index e133244f..30ab8f94 100644
--- a/src/displayapp/screens/Paddle.h
+++ b/src/displayapp/screens/Paddle.h
@@ -24,24 +24,22 @@ namespace Pinetime {
private:
Pinetime::Components::LittleVgl& lvgl;
- int paddleBottomY = 90; // bottom extreme of the paddle
- int paddleTopY = 150; // top extreme of the paddle
+ const uint8_t ballSize = 16;
- int ballX = 107; // Initial x_coordinate for the ball (12px offset from the center to counteract the ball's 24px size)
- int ballY = 107; // Initial y_coordinate for the ball
+ uint16_t paddlePos = 30; // Paddle center
- int dx = 2; // Velocity of the ball in the x_coordinate
- int dy = 3; // Velocity of the ball in the y_coordinate
+ int16_t ballX = (LV_HOR_RES - ballSize) / 2;
+ int16_t ballY = (LV_VER_RES - ballSize) / 2;
- int counter = 0; // init Frame refresh limit counter
- int score = 0;
+ int8_t dx = 2; // Velocity of the ball in the x_coordinate
+ int8_t dy = 3; // Velocity of the ball in the y_coordinate
- lv_img_dsc_t paddle;
- lv_img_dsc_t ball;
+ uint16_t score = 0;
lv_obj_t* points;
- lv_obj_t* paddle_image; // pointer to paddle image
- lv_obj_t* ball_image; // pointer to ball image
+ lv_obj_t* paddle;
+ lv_obj_t* ball;
+ lv_obj_t* background;
};
}
}
diff --git a/src/displayapp/screens/PineTimeStyle.cpp b/src/displayapp/screens/PineTimeStyle.cpp
new file mode 100644
index 00000000..591f3a49
--- /dev/null
+++ b/src/displayapp/screens/PineTimeStyle.cpp
@@ -0,0 +1,340 @@
+/*
+ * This file is part of the Infinitime distribution (https://github.com/JF002/Infinitime).
+ * Copyright (c) 2021 Kieran Cawthray.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * PineTimeStyle watchface for Infinitime created by Kieran Cawthray
+ * Based on WatchFaceDigital
+ * Style/layout copied from TimeStyle for Pebble by Dan Tilden (github.com/tilden)
+ */
+
+#include "PineTimeStyle.h"
+#include
+#include
+#include
+#include "BatteryIcon.h"
+#include "BleIcon.h"
+#include "NotificationIcon.h"
+#include "Symbols.h"
+#include "components/battery/BatteryController.h"
+#include "components/ble/BleController.h"
+#include "components/ble/NotificationManager.h"
+#include "components/motion/MotionController.h"
+#include "components/settings/Settings.h"
+#include "../DisplayApp.h"
+
+using namespace Pinetime::Applications::Screens;
+
+PineTimeStyle::PineTimeStyle(DisplayApp* app,
+ Controllers::DateTime& dateTimeController,
+ Controllers::Battery& batteryController,
+ Controllers::Ble& bleController,
+ Controllers::NotificationManager& notificatioManager,
+ Controllers::Settings& settingsController,
+ Controllers::MotionController& motionController)
+ : Screen(app),
+ currentDateTime {{}},
+ dateTimeController {dateTimeController},
+ batteryController {batteryController},
+ bleController {bleController},
+ notificatioManager {notificatioManager},
+ settingsController {settingsController},
+ motionController {motionController} {
+
+ /* This sets the watchface number to return to after leaving the menu */
+ settingsController.SetClockFace(2);
+
+ displayedChar[0] = 0;
+ displayedChar[1] = 0;
+ displayedChar[2] = 0;
+ displayedChar[3] = 0;
+ displayedChar[4] = 0;
+
+ /* Create a 200px wide background rectangle */
+
+ 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_radius(timebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
+ lv_obj_set_size(timebar, 200, 240);
+ lv_obj_align(timebar, lv_scr_act(), LV_ALIGN_IN_TOP_LEFT, 5, 0);
+
+ /* Display the time */
+
+ 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_color(timeDD1, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080));
+ lv_label_set_text(timeDD1, "12");
+ lv_obj_align(timeDD1, timebar, LV_ALIGN_IN_TOP_MID, 5, 5);
+
+ timeDD2 = lv_label_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_text_font(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &open_sans_light);
+ lv_obj_set_style_local_text_color(timeDD2, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080));
+ lv_label_set_text(timeDD2, "34");
+ lv_obj_align(timeDD2, timebar, LV_ALIGN_IN_BOTTOM_MID, 5, -5);
+
+ timeAMPM = lv_label_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_text_color(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x008080));
+ lv_obj_set_style_local_text_line_space(timeAMPM, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, -3);
+ lv_label_set_text(timeAMPM, "");
+ lv_obj_align(timeAMPM, timebar, LV_ALIGN_IN_BOTTOM_LEFT, 2, -20);
+
+ /* Create a 40px wide bar down the right side of the screen */
+
+ 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_radius(sidebar, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
+ lv_obj_set_size(sidebar, 40, 240);
+ lv_obj_align(sidebar, lv_scr_act(), LV_ALIGN_IN_TOP_RIGHT, 0, 0);
+
+ /* Display icons */
+
+ 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_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);
+
+ 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));
+ lv_obj_align(bleIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 25);
+
+ 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(0x000000));
+ lv_obj_align(notificationIcon, sidebar, LV_ALIGN_IN_TOP_MID, 0, 40);
+
+ /* Calendar icon */
+
+ 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_radius(calendarOuter, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
+ lv_obj_set_size(calendarOuter, 34, 34);
+ lv_obj_align(calendarOuter, sidebar, LV_ALIGN_CENTER, 0, 0);
+
+ calendarInner = lv_obj_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_bg_color(calendarInner, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0xffffff));
+ lv_obj_set_style_local_radius(calendarInner, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
+ lv_obj_set_size(calendarInner, 27, 27);
+ lv_obj_align(calendarInner, calendarOuter, LV_ALIGN_CENTER, 0, 0);
+
+ calendarBar1 = lv_obj_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_bg_color(calendarBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
+ lv_obj_set_style_local_radius(calendarBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
+ lv_obj_set_size(calendarBar1, 3, 12);
+ lv_obj_align(calendarBar1, calendarOuter, LV_ALIGN_IN_TOP_MID, -6, -3);
+
+ calendarBar2 = lv_obj_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_bg_color(calendarBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
+ lv_obj_set_style_local_radius(calendarBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
+ lv_obj_set_size(calendarBar2, 3, 12);
+ lv_obj_align(calendarBar2, calendarOuter, LV_ALIGN_IN_TOP_MID, 6, -3);
+
+ calendarCrossBar1 = lv_obj_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_bg_color(calendarCrossBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
+ lv_obj_set_style_local_radius(calendarCrossBar1, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
+ lv_obj_set_size(calendarCrossBar1, 8, 3);
+ lv_obj_align(calendarCrossBar1, calendarBar1, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
+
+ calendarCrossBar2 = lv_obj_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_bg_color(calendarCrossBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
+ lv_obj_set_style_local_radius(calendarCrossBar2, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, 0);
+ lv_obj_set_size(calendarCrossBar2, 8, 3);
+ lv_obj_align(calendarCrossBar2, calendarBar2, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
+
+ /* Display date */
+
+ 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_label_set_text(dateDayOfWeek, "THU");
+ lv_obj_align(dateDayOfWeek, sidebar, LV_ALIGN_CENTER, 0, -34);
+
+ dateDay = lv_label_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_text_color(dateDay, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
+ lv_label_set_text(dateDay, "25");
+ lv_obj_align(dateDay, sidebar, LV_ALIGN_CENTER, 0, 3);
+
+ dateMonth = lv_label_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_text_color(dateMonth, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x000000));
+ lv_label_set_text(dateMonth, "MAR");
+ lv_obj_align(dateMonth, sidebar, LV_ALIGN_CENTER, 0, 32);
+
+ // Step count gauge
+ needle_colors[0] = LV_COLOR_WHITE;
+ stepGauge = lv_gauge_create(lv_scr_act(), nullptr);
+ lv_gauge_set_needle_count(stepGauge, 1, needle_colors);
+ lv_obj_set_size(stepGauge, 40, 40);
+ lv_obj_align(stepGauge, sidebar, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
+ lv_gauge_set_scale(stepGauge, 360, 11, 0);
+ lv_gauge_set_angle_offset(stepGauge, 180);
+ lv_gauge_set_critical_value(stepGauge, 100);
+ lv_gauge_set_range(stepGauge, 0, 100);
+ lv_gauge_set_value(stepGauge, 0, 0);
+
+ lv_obj_set_style_local_pad_right(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 3);
+ lv_obj_set_style_local_pad_left(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 3);
+ lv_obj_set_style_local_pad_bottom(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 3);
+ lv_obj_set_style_local_line_opa(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_COVER);
+ lv_obj_set_style_local_scale_width(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 4);
+ lv_obj_set_style_local_line_width(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, 4);
+ lv_obj_set_style_local_line_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);
+ lv_obj_set_style_local_line_opa(stepGauge, LV_GAUGE_PART_NEEDLE, LV_STATE_DEFAULT, LV_OPA_COVER);
+ lv_obj_set_style_local_line_width(stepGauge, LV_GAUGE_PART_NEEDLE, LV_STATE_DEFAULT, 4);
+ lv_obj_set_style_local_pad_inner(stepGauge, LV_GAUGE_PART_NEEDLE, LV_STATE_DEFAULT, 4);
+
+ backgroundLabel = lv_label_create(lv_scr_act(), nullptr);
+ lv_obj_set_click(backgroundLabel, true);
+ lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP);
+ lv_obj_set_size(backgroundLabel, 240, 240);
+ lv_obj_set_pos(backgroundLabel, 0, 0);
+ lv_label_set_text(backgroundLabel, "");
+}
+
+PineTimeStyle::~PineTimeStyle() {
+ lv_obj_clean(lv_scr_act());
+}
+
+bool PineTimeStyle::Refresh() {
+ 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, "");
+ }
+ }
+
+ bleState = bleController.IsConnected();
+ if (bleState.IsUpdated()) {
+ if (bleState.Get() == true) {
+ lv_label_set_text(bleIcon, BleIcon::GetIcon(true));
+ lv_obj_realign(bleIcon);
+ } else {
+ lv_label_set_text(bleIcon, BleIcon::GetIcon(false));
+ }
+ }
+
+ notificationState = notificatioManager.AreNewNotificationsAvailable();
+ if (notificationState.IsUpdated()) {
+ if (notificationState.Get() == true) {
+ lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(true));
+ lv_obj_realign(notificationIcon);
+ } else {
+ lv_label_set_text(notificationIcon, NotificationIcon::GetIcon(false));
+ }
+ }
+
+ currentDateTime = dateTimeController.CurrentDateTime();
+
+ if (currentDateTime.IsUpdated()) {
+ auto newDateTime = currentDateTime.Get();
+
+ auto dp = date::floor(newDateTime);
+ auto time = date::make_time(newDateTime - dp);
+ auto yearMonthDay = date::year_month_day(dp);
+
+ auto year = (int) yearMonthDay.year();
+ auto month = static_cast((unsigned) yearMonthDay.month());
+ auto day = (unsigned) yearMonthDay.day();
+ auto dayOfWeek = static_cast(date::weekday(yearMonthDay).iso_encoding());
+
+ int hour = time.hours().count();
+ auto minute = time.minutes().count();
+
+ char minutesChar[3];
+ sprintf(minutesChar, "%02d", static_cast(minute));
+
+ char hoursChar[3];
+ char ampmChar[5];
+
+ if (settingsController.GetClockType() == Controllers::Settings::ClockType::H24) {
+ sprintf(hoursChar, "%02d", hour);
+ } else {
+ if (hour == 0 && hour != 12) {
+ hour = 12;
+ sprintf(ampmChar, "A\nM");
+ } else if (hour == 12 && hour != 0) {
+ hour = 12;
+ sprintf(ampmChar, "P\nM");
+ } else if (hour < 12 && hour != 0) {
+ sprintf(ampmChar, "A\nM");
+ } else if (hour > 12 && hour != 0) {
+ hour = hour - 12;
+ sprintf(ampmChar, "P\nM");
+ }
+ sprintf(hoursChar, "%02d", hour);
+ }
+
+ if (hoursChar[0] != displayedChar[0] || hoursChar[1] != displayedChar[1] || minutesChar[0] != displayedChar[2] ||
+ minutesChar[1] != displayedChar[3]) {
+ displayedChar[0] = hoursChar[0];
+ displayedChar[1] = hoursChar[1];
+ displayedChar[2] = minutesChar[0];
+ displayedChar[3] = minutesChar[1];
+
+ char hourStr[3];
+ char minStr[3];
+
+ if (settingsController.GetClockType() == Controllers::Settings::ClockType::H12) {
+ lv_label_set_text(timeAMPM, ampmChar);
+ }
+
+ /* Display the time as 2 pairs of digits */
+ sprintf(hourStr, "%c%c", hoursChar[0], hoursChar[1]);
+ 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)) {
+ char dayOfWeekStr[4];
+ char dayStr[3];
+ 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_label_set_text(dateMonth, monthStr);
+
+ currentYear = year;
+ currentMonth = month;
+ currentDayOfWeek = dayOfWeek;
+ currentDay = day;
+ }
+ }
+
+ stepCount = motionController.NbSteps();
+ motionSensorOk = motionController.IsSensorOk();
+ if (stepCount.IsUpdated() || motionSensorOk.IsUpdated()) {
+ lv_gauge_set_value(stepGauge, 0, (stepCount.Get() / (settingsController.GetStepsGoal() / 100)));
+ lv_obj_realign(stepGauge);
+ if (stepCount.Get() > settingsController.GetStepsGoal()) {
+ lv_obj_set_style_local_line_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
+ lv_obj_set_style_local_scale_grad_color(stepGauge, LV_GAUGE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
+ }
+ }
+
+ return running;
+}
\ No newline at end of file
diff --git a/src/displayapp/screens/PineTimeStyle.h b/src/displayapp/screens/PineTimeStyle.h
new file mode 100644
index 00000000..3b4ded1e
--- /dev/null
+++ b/src/displayapp/screens/PineTimeStyle.h
@@ -0,0 +1,86 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include "Screen.h"
+#include "ScreenList.h"
+#include "components/datetime/DateTimeController.h"
+
+namespace Pinetime {
+ namespace Controllers {
+ class Settings;
+ class Battery;
+ class Ble;
+ class NotificationManager;
+ class HeartRateController;
+ }
+
+ namespace Applications {
+ namespace Screens {
+ class PineTimeStyle : public Screen {
+ public:
+ PineTimeStyle(DisplayApp* app,
+ Controllers::DateTime& dateTimeController,
+ Controllers::Battery& batteryController,
+ Controllers::Ble& bleController,
+ Controllers::NotificationManager& notificatioManager,
+ Controllers::Settings& settingsController,
+ Controllers::MotionController& motionController);
+ ~PineTimeStyle() override;
+
+ bool Refresh() override;
+
+ void OnObjectEvent(lv_obj_t* pObj, lv_event_t i);
+
+ private:
+ char displayedChar[5];
+
+ uint16_t currentYear = 1970;
+ Pinetime::Controllers::DateTime::Months currentMonth = Pinetime::Controllers::DateTime::Months::Unknown;
+ Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown;
+ uint8_t currentDay = 0;
+
+ DirtyValue batteryPercentRemaining {};
+ DirtyValue bleState {};
+ DirtyValue> currentDateTime {};
+ DirtyValue motionSensorOk {};
+ DirtyValue stepCount {};
+ DirtyValue notificationState {};
+
+ lv_obj_t* timebar;
+ lv_obj_t* sidebar;
+ lv_obj_t* timeDD1;
+ lv_obj_t* timeDD2;
+ lv_obj_t* timeAMPM;
+ lv_obj_t* dateDayOfWeek;
+ lv_obj_t* dateDay;
+ lv_obj_t* dateMonth;
+ 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;
+ lv_obj_t* calendarBar2;
+ lv_obj_t* calendarCrossBar1;
+ lv_obj_t* calendarCrossBar2;
+ lv_obj_t* heartbeatIcon;
+ lv_obj_t* heartbeatValue;
+ lv_obj_t* heartbeatBpm;
+ lv_obj_t* notificationIcon;
+ lv_obj_t* stepGauge;
+ lv_color_t needle_colors[1];
+
+ Controllers::DateTime& dateTimeController;
+ Controllers::Battery& batteryController;
+ Controllers::Ble& bleController;
+ Controllers::NotificationManager& notificatioManager;
+ Controllers::Settings& settingsController;
+ Controllers::MotionController& motionController;
+ };
+ }
+ }
+}
diff --git a/src/displayapp/screens/ScreenList.h b/src/displayapp/screens/ScreenList.h
index 73ea4610..ea66bfb2 100644
--- a/src/displayapp/screens/ScreenList.h
+++ b/src/displayapp/screens/ScreenList.h
@@ -15,12 +15,17 @@ namespace Pinetime {
public:
ScreenList(DisplayApp* app,
uint8_t initScreen,
- std::array()>, N>&& screens,
+ const std::array()>, N>&& screens,
ScreenListModes mode)
- : Screen(app), initScreen {initScreen}, screens {std::move(screens)}, mode {mode}, current {this->screens[initScreen]()} {
- screenIndex = initScreen;
+ : Screen(app), initScreen {initScreen}, screens {std::move(screens)}, mode {mode}, screenIndex{initScreen}, current {this->screens[initScreen]()} {
+
}
+ ScreenList(const ScreenList&) = delete;
+ ScreenList& operator=(const ScreenList&) = delete;
+ ScreenList(ScreenList&&) = delete;
+ ScreenList& operator=(ScreenList&&) = delete;
+
~ScreenList() override {
lv_obj_clean(lv_scr_act());
}
@@ -97,7 +102,7 @@ namespace Pinetime {
private:
uint8_t initScreen = 0;
- std::array()>, N> screens;
+ const std::array()>, N> screens;
ScreenListModes mode = ScreenListModes::UpDown;
uint8_t screenIndex = 0;
diff --git a/src/displayapp/screens/Steps.cpp b/src/displayapp/screens/Steps.cpp
index b485c975..6aabd30e 100644
--- a/src/displayapp/screens/Steps.cpp
+++ b/src/displayapp/screens/Steps.cpp
@@ -6,19 +6,19 @@
using namespace Pinetime::Applications::Screens;
Steps::Steps(
- Pinetime::Applications::DisplayApp *app,
+ Pinetime::Applications::DisplayApp *app,
Controllers::MotionController& motionController,
- Controllers::Settings &settingsController)
- : Screen(app),
+ Controllers::Settings &settingsController)
+ : Screen(app),
motionController{motionController},
settingsController{settingsController} {
stepsArc = lv_arc_create(lv_scr_act(), nullptr);
- lv_obj_set_style_local_bg_opa(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, LV_OPA_0);
- lv_obj_set_style_local_border_width(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, 2);
- lv_obj_set_style_local_radius(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, 0);
- lv_obj_set_style_local_line_color(stepsArc, LV_ARC_PART_INDIC, LV_STATE_DEFAULT, lv_color_hex(0x0000FF));
+ lv_obj_set_style_local_bg_opa(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, LV_OPA_0);
+ lv_obj_set_style_local_border_width(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, 2);
+ lv_obj_set_style_local_radius(stepsArc, LV_ARC_PART_BG, LV_STATE_DEFAULT, 0);
+ lv_obj_set_style_local_line_color(stepsArc, LV_ARC_PART_INDIC, LV_STATE_DEFAULT, lv_color_hex(0x0000FF));
lv_arc_set_end_angle(stepsArc, 200);
lv_obj_set_size(stepsArc, 220, 220);
lv_arc_set_range(stepsArc, 0, 500);
@@ -30,27 +30,26 @@ Steps::Steps(
lSteps = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(lSteps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x00FF00));
- lv_obj_set_style_local_text_font(lSteps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42);
- lv_label_set_text_fmt(lSteps, "%li", stepsCount);
+ lv_obj_set_style_local_text_font(lSteps, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42);
+ lv_label_set_text_fmt(lSteps, "%li", stepsCount);
lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -20);
lv_obj_t * lstepsL = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(lstepsL, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x111111));
- lv_label_set_text_static(lstepsL, "Steps");
+ lv_label_set_text_static(lstepsL, "Steps");
lv_obj_align(lstepsL, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 10);
lv_obj_t * lstepsGoal = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_color(lstepsGoal, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_CYAN);
- lv_label_set_text_fmt(lstepsGoal,"Goal\n%i", settingsController.GetStepsGoal());
+ lv_label_set_text_fmt(lstepsGoal, "Goal\n%lu", settingsController.GetStepsGoal());
lv_label_set_align(lstepsGoal, LV_LABEL_ALIGN_CENTER);
lv_obj_align(lstepsGoal, lSteps, LV_ALIGN_OUT_BOTTOM_MID, 0, 60);
- lv_obj_t * backgroundLabel = lv_label_create(lv_scr_act(), nullptr);
+ lv_obj_t* backgroundLabel = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_long_mode(backgroundLabel, LV_LABEL_LONG_CROP);
lv_obj_set_size(backgroundLabel, 240, 240);
lv_obj_set_pos(backgroundLabel, 0, 0);
lv_label_set_text_static(backgroundLabel, "");
-
}
Steps::~Steps() {
@@ -58,15 +57,13 @@ Steps::~Steps() {
}
bool Steps::Refresh() {
-
- stepsCount = motionController.NbSteps();
- lv_label_set_text_fmt(lSteps,"%li", stepsCount);
+ stepsCount = motionController.NbSteps();
+
+ lv_label_set_text_fmt(lSteps, "%li", stepsCount);
lv_obj_align(lSteps, nullptr, LV_ALIGN_CENTER, 0, -20);
-
+
lv_arc_set_value(stepsArc, int16_t(500 * stepsCount / settingsController.GetStepsGoal()));
return running;
}
-
-
diff --git a/src/displayapp/screens/StopWatch.cpp b/src/displayapp/screens/StopWatch.cpp
index d7cd20c3..f4db5d6e 100644
--- a/src/displayapp/screens/StopWatch.cpp
+++ b/src/displayapp/screens/StopWatch.cpp
@@ -45,38 +45,51 @@ static void stop_lap_event_handler(lv_obj_t* obj, lv_event_t event) {
stopWatch->stopLapBtnEventHandler(event);
}
-StopWatch::StopWatch(DisplayApp* app)
+StopWatch::StopWatch(DisplayApp* app, System::SystemTask& systemTask)
: Screen(app),
+ systemTask {systemTask},
running {true},
currentState {States::Init},
- currentEvent {Events::Stop},
startTime {},
oldTimeElapsed {},
currentTimeSeparated {},
lapBuffer {},
- lapNr {},
- lapPressed {false} {
+ lapNr {} {
time = lv_label_create(lv_scr_act(), nullptr);
lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76);
lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
lv_label_set_text(time, "00:00");
- lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -45);
+ lv_obj_align(time, lv_scr_act(), LV_ALIGN_CENTER, 0, -45);
msecTime = lv_label_create(lv_scr_act(), nullptr);
// lv_obj_set_style_local_text_font(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20);
lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
lv_label_set_text(msecTime, "00");
- lv_obj_align(msecTime, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 108, 3);
+ lv_obj_align(msecTime, lv_scr_act(), LV_ALIGN_CENTER, 0, 3);
btnPlayPause = lv_btn_create(lv_scr_act(), nullptr);
btnPlayPause->user_data = this;
lv_obj_set_event_cb(btnPlayPause, play_pause_event_handler);
- lv_obj_align(btnPlayPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_MID, 0, -10);
- lv_obj_set_height(btnPlayPause, 40);
+ lv_obj_set_height(btnPlayPause, 50);
+ lv_obj_set_width(btnPlayPause, 115);
+ lv_obj_align(btnPlayPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
txtPlayPause = lv_label_create(btnPlayPause, nullptr);
lv_label_set_text(txtPlayPause, Symbols::play);
+ btnStopLap = lv_btn_create(lv_scr_act(), nullptr);
+ btnStopLap->user_data = this;
+ lv_obj_set_event_cb(btnStopLap, stop_lap_event_handler);
+ lv_obj_set_height(btnStopLap, 50);
+ lv_obj_set_width(btnStopLap, 115);
+ lv_obj_align(btnStopLap, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
+ lv_obj_set_style_local_bg_color(btnStopLap, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x080808));
+ txtStopLap = lv_label_create(btnStopLap, nullptr);
+ lv_obj_set_style_local_text_color(txtStopLap, LV_BTN_PART_MAIN, LV_STATE_DISABLED, lv_color_hex(0x888888));
+ lv_label_set_text(txtStopLap, Symbols::stop);
+ lv_obj_set_state(btnStopLap, LV_STATE_DISABLED);
+ lv_obj_set_state(txtStopLap, LV_STATE_DISABLED);
+
lapOneText = lv_label_create(lv_scr_act(), nullptr);
// lv_obj_set_style_local_text_font(lapOneText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_bold_20);
lv_obj_set_style_local_text_color(lapOneText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
@@ -88,140 +101,103 @@ StopWatch::StopWatch(DisplayApp* app)
lv_obj_set_style_local_text_color(lapTwoText, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
lv_obj_align(lapTwoText, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 50, 55);
lv_label_set_text(lapTwoText, "");
-
- // We don't want this button in the init state
- btnStopLap = nullptr;
}
StopWatch::~StopWatch() {
+ systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
lv_obj_clean(lv_scr_act());
}
+void StopWatch::reset() {
+ currentState = States::Init;
+ oldTimeElapsed = 0;
+ lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
+ lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
+
+ lv_label_set_text(time, "00:00");
+ lv_label_set_text(msecTime, "00");
+
+ lv_label_set_text(lapOneText, "");
+ lv_label_set_text(lapTwoText, "");
+ lapBuffer.clearBuffer();
+ lapNr = 0;
+ lv_obj_set_state(btnStopLap, LV_STATE_DISABLED);
+ lv_obj_set_state(txtStopLap, LV_STATE_DISABLED);
+}
+
+void StopWatch::start() {
+ lv_obj_set_state(btnStopLap, LV_STATE_DEFAULT);
+ lv_obj_set_state(txtStopLap, LV_STATE_DEFAULT);
+ lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
+ lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
+ lv_label_set_text(txtPlayPause, Symbols::pause);
+ lv_label_set_text(txtStopLap, Symbols::lapsFlag);
+ startTime = xTaskGetTickCount();
+ currentState = States::Running;
+ systemTask.PushMessage(Pinetime::System::Messages::DisableSleeping);
+}
+
+void StopWatch::pause() {
+ startTime = 0;
+ // Store the current time elapsed in cache
+ oldTimeElapsed += timeElapsed;
+ currentState = States::Halted;
+ lv_label_set_text(txtPlayPause, Symbols::play);
+ lv_label_set_text(txtStopLap, Symbols::stop);
+ lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
+ lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
+ systemTask.PushMessage(Pinetime::System::Messages::EnableSleeping);
+}
+
bool StopWatch::Refresh() {
- // @startuml CHIP8_state
- // State "Init" as init
- // State "Running" as run
- // State "Halted" as halt
+ if (currentState == States::Running) {
+ timeElapsed = calculateDelta(startTime, xTaskGetTickCount());
+ currentTimeSeparated = convertTicksToTimeSegments((oldTimeElapsed + timeElapsed));
- // [*] --> init
- // init -> run : press play
- // run -> run : press lap
- // run --> halt : press pause
- // halt --> run : press play
- // halt --> init : press stop
- // @enduml
- // Copy paste the above plantuml text to visualize the state diagram
- switch (currentState) {
- // Init state when an user first opens the app
- // and when a stop/reset button is pressed
- case States::Init: {
- if (btnStopLap != nullptr) {
- lv_obj_del(btnStopLap);
- btnStopLap = nullptr;
- }
- // The initial default value
- lv_label_set_text(time, "00:00");
- lv_label_set_text(msecTime, "00");
-
- lv_label_set_text(lapOneText, "");
- lv_label_set_text(lapTwoText, "");
- lapBuffer.clearBuffer();
- lapNr = 0;
-
- if (currentEvent == Events::Play) {
- btnStopLap = lv_btn_create(lv_scr_act(), nullptr);
- btnStopLap->user_data = this;
- lv_obj_set_event_cb(btnStopLap, stop_lap_event_handler);
- lv_obj_align(btnStopLap, lv_scr_act(), LV_ALIGN_IN_TOP_MID, 0, 0);
- lv_obj_set_height(btnStopLap, 40);
- txtStopLap = lv_label_create(btnStopLap, nullptr);
- lv_label_set_text(txtStopLap, Symbols::lapsFlag);
-
- startTime = xTaskGetTickCount();
- currentState = States::Running;
- }
- break;
- }
- case States::Running: {
- lv_label_set_text(txtPlayPause, Symbols::pause);
- lv_label_set_text(txtStopLap, Symbols::lapsFlag);
-
- const auto timeElapsed = calculateDelta(startTime, xTaskGetTickCount());
- currentTimeSeparated = convertTicksToTimeSegments((oldTimeElapsed + timeElapsed));
-
- lv_label_set_text_fmt(time, "%02d:%02d", currentTimeSeparated.mins, currentTimeSeparated.secs);
- lv_label_set_text_fmt(msecTime, "%02d", currentTimeSeparated.hundredths);
-
- if (lapPressed == true) {
- if (lapBuffer[1]) {
- lv_label_set_text_fmt(
- lapOneText, "#%2d %2d:%02d.%02d", (lapNr - 1), lapBuffer[1]->mins, lapBuffer[1]->secs, lapBuffer[1]->hundredths);
- }
- if (lapBuffer[0]) {
- lv_label_set_text_fmt(
- lapTwoText, "#%2d %2d:%02d.%02d", lapNr, lapBuffer[0]->mins, lapBuffer[0]->secs, lapBuffer[0]->hundredths);
- }
- // Reset the bool to avoid setting the text in each cycle until there is a change
- lapPressed = false;
- }
-
- if (currentEvent == Events::Pause) {
- // Reset the start time
- startTime = 0;
- // Store the current time elapsed in cache
- oldTimeElapsed += timeElapsed;
- currentState = States::Halted;
- lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
- lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_YELLOW);
- } else {
- lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
- lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
- }
- break;
- }
- case States::Halted: {
- lv_label_set_text(txtPlayPause, Symbols::play);
- lv_label_set_text(txtStopLap, Symbols::stop);
-
- if (currentEvent == Events::Play) {
- startTime = xTaskGetTickCount();
- currentState = States::Running;
- }
- if (currentEvent == Events::Stop) {
- currentState = States::Init;
- oldTimeElapsed = 0;
- lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
- lv_obj_set_style_local_text_color(msecTime, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
- }
- break;
- }
+ lv_label_set_text_fmt(time, "%02d:%02d", currentTimeSeparated.mins, currentTimeSeparated.secs);
+ lv_label_set_text_fmt(msecTime, "%02d", currentTimeSeparated.hundredths);
}
return running;
}
void StopWatch::playPauseBtnEventHandler(lv_event_t event) {
- if (event == LV_EVENT_CLICKED) {
- if (currentState == States::Init) {
- currentEvent = Events::Play;
- } else {
- // Simple Toggle for play/pause
- currentEvent = (currentEvent == Events::Play ? Events::Pause : Events::Play);
- }
+ if (event != LV_EVENT_PRESSED) {
+ return;
+ }
+ if (currentState == States::Init) {
+ start();
+ } else if (currentState == States::Running) {
+ pause();
+ } else if (currentState == States::Halted) {
+ start();
}
}
void StopWatch::stopLapBtnEventHandler(lv_event_t event) {
- if (event == LV_EVENT_CLICKED) {
- // If running, then this button is used to save laps
- if (currentState == States::Running) {
- lapBuffer.addLaps(currentTimeSeparated);
- lapNr++;
- lapPressed = true;
-
- } else if (currentState == States::Halted) {
- currentEvent = Events::Stop;
- } else {
- // Not possible to reach here. Do nothing.
+ if (event != LV_EVENT_PRESSED) {
+ return;
+ }
+ // If running, then this button is used to save laps
+ if (currentState == States::Running) {
+ lapBuffer.addLaps(currentTimeSeparated);
+ lapNr++;
+ if (lapBuffer[1]) {
+ lv_label_set_text_fmt(
+ lapOneText, "#%2d %2d:%02d.%02d", (lapNr - 1), lapBuffer[1]->mins, lapBuffer[1]->secs, lapBuffer[1]->hundredths);
}
+ if (lapBuffer[0]) {
+ lv_label_set_text_fmt(lapTwoText, "#%2d %2d:%02d.%02d", lapNr, lapBuffer[0]->mins, lapBuffer[0]->secs, lapBuffer[0]->hundredths);
+ }
+ } else if (currentState == States::Halted) {
+ reset();
}
}
+
+bool StopWatch::OnButtonPushed() {
+ if (currentState == States::Running) {
+ pause();
+ } else {
+ running = false;
+ }
+ return true;
+}
diff --git a/src/displayapp/screens/StopWatch.h b/src/displayapp/screens/StopWatch.h
index ff604361..e132f158 100644
--- a/src/displayapp/screens/StopWatch.h
+++ b/src/displayapp/screens/StopWatch.h
@@ -8,13 +8,12 @@
#include "portmacro_cmsis.h"
#include
+#include "systemtask/SystemTask.h"
namespace Pinetime::Applications::Screens {
enum class States { Init, Running, Halted };
- enum class Events { Play, Pause, Stop };
-
struct TimeSeparated_t {
int mins;
int secs;
@@ -63,23 +62,28 @@ namespace Pinetime::Applications::Screens {
class StopWatch : public Screen {
public:
- StopWatch(DisplayApp* app);
+ StopWatch(DisplayApp* app, System::SystemTask& systemTask);
~StopWatch() override;
bool Refresh() override;
void playPauseBtnEventHandler(lv_event_t event);
void stopLapBtnEventHandler(lv_event_t event);
+ bool OnButtonPushed() override;
+
+ void reset();
+ void start();
+ void pause();
private:
+ Pinetime::System::SystemTask& systemTask;
+ TickType_t timeElapsed;
bool running;
States currentState;
- Events currentEvent;
TickType_t startTime;
TickType_t oldTimeElapsed;
TimeSeparated_t currentTimeSeparated; // Holds Mins, Secs, millisecs
LapTextBuffer_t<2> lapBuffer;
- int lapNr;
- bool lapPressed;
+ int lapNr = 0;
lv_obj_t *time, *msecTime, *btnPlayPause, *btnStopLap, *txtPlayPause, *txtStopLap;
lv_obj_t *lapOneText, *lapTwoText;
};
diff --git a/src/displayapp/screens/Symbols.h b/src/displayapp/screens/Symbols.h
index 8d55f693..c9d61541 100644
--- a/src/displayapp/screens/Symbols.h
+++ b/src/displayapp/screens/Symbols.h
@@ -40,6 +40,7 @@ namespace Pinetime {
static constexpr const char* stopWatch = "\xEF\x8B\xB2";
static constexpr const char* hourGlass = "\xEF\x89\x92";
static constexpr const char* lapsFlag = "\xEF\x80\xA4";
+ static constexpr const char* drum = "\xEF\x95\xA9";
// lv_font_sys_48.c
static constexpr const char* settings = "\xEE\xA4\x82"; // e902
diff --git a/src/displayapp/screens/SystemInfo.cpp b/src/displayapp/screens/SystemInfo.cpp
index f61d2ff1..f5bf0cc9 100644
--- a/src/displayapp/screens/SystemInfo.cpp
+++ b/src/displayapp/screens/SystemInfo.cpp
@@ -3,26 +3,42 @@
#include "../DisplayApp.h"
#include "Label.h"
#include "Version.h"
+#include "BootloaderVersion.h"
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
#include "components/brightness/BrightnessController.h"
#include "components/datetime/DateTimeController.h"
+#include "components/motion/MotionController.h"
#include "drivers/Watchdog.h"
using namespace Pinetime::Applications::Screens;
+namespace {
+ const char* ToString(const Pinetime::Controllers::MotionController::DeviceTypes deviceType) {
+ switch (deviceType) {
+ case Pinetime::Controllers::MotionController::DeviceTypes::BMA421:
+ return "BMA421";
+ case Pinetime::Controllers::MotionController::DeviceTypes::BMA425:
+ return "BMA425";
+ }
+ return "???";
+ }
+}
+
SystemInfo::SystemInfo(Pinetime::Applications::DisplayApp* app,
Pinetime::Controllers::DateTime& dateTimeController,
Pinetime::Controllers::Battery& batteryController,
Pinetime::Controllers::BrightnessController& brightnessController,
Pinetime::Controllers::Ble& bleController,
- Pinetime::Drivers::WatchdogView& watchdog)
+ Pinetime::Drivers::WatchdogView& watchdog,
+ Pinetime::Controllers::MotionController& motionController)
: Screen(app),
dateTimeController {dateTimeController},
batteryController {batteryController},
brightnessController {brightnessController},
bleController {bleController},
watchdog {watchdog},
+ motionController{motionController},
screens {app,
0,
{[this]() -> std::unique_ptr {
@@ -68,26 +84,26 @@ std::unique_ptr SystemInfo::CreateScreen1() {
lv_label_set_recolor(label, true);
lv_label_set_text_fmt(label,
"#FFFF00 InfiniTime#\n\n"
- "#444444 Version# %ld.%ld.%ld\n\n"
- "#444444 Short Ref# %s\n\n"
+ "#444444 Version# %ld.%ld.%ld\n"
+ "#444444 Short Ref# %s\n"
"#444444 Build date#\n"
"%s\n"
- "%s\n",
+ "%s\n\n"
+ "#444444 Bootloader# %s",
Version::Major(),
Version::Minor(),
Version::Patch(),
Version::GitCommitHash(),
__DATE__,
- __TIME__);
+ __TIME__,
+ BootloaderVersion::VersionString());
lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
- return std::unique_ptr(new Screens::Label(0, 5, app, label));
+ return std::make_unique(0, 5, app, label);
}
std::unique_ptr SystemInfo::CreateScreen2() {
- auto batteryPercent = static_cast(batteryController.PercentRemaining());
- float batteryVoltage = batteryController.Voltage();
-
+ auto batteryPercent = batteryController.PercentRemaining();
auto resetReason = [this]() {
switch (watchdog.ResetReason()) {
case Drivers::Watchdog::ResetReasons::Watchdog:
@@ -126,25 +142,16 @@ std::unique_ptr SystemInfo::CreateScreen2() {
uptimeSeconds = uptimeSeconds % secondsInAMinute;
// TODO handle more than 100 days of uptime
- if (batteryPercent == -1)
- batteryPercent = 0;
-
- // hack to not use the flot functions from printf
- uint8_t batteryVoltageBytes[2];
- batteryVoltageBytes[1] = static_cast(batteryVoltage); // truncate whole numbers
- batteryVoltageBytes[0] =
- static_cast((batteryVoltage - batteryVoltageBytes[1]) * 100); // remove whole part of flt and shift 2 places over
- //
-
lv_obj_t* label = lv_label_create(lv_scr_act(), nullptr);
lv_label_set_recolor(label, true);
lv_label_set_text_fmt(label,
"#444444 Date# %02d/%02d/%04d\n"
"#444444 Time# %02d:%02d:%02d\n"
"#444444 Uptime#\n %02lud %02lu:%02lu:%02lu\n"
- "#444444 Battery# %d%%/%1i.%02iv\n"
+ "#444444 Battery# %d%%/%03imV\n"
"#444444 Backlight# %s\n"
- "#444444 Last reset# %s\n",
+ "#444444 Last reset# %s\n"
+ "#444444 Accel.# %s\n",
dateTimeController.Day(),
static_cast(dateTimeController.Month()),
dateTimeController.Year(),
@@ -156,12 +163,12 @@ std::unique_ptr SystemInfo::CreateScreen2() {
uptimeMinutes,
uptimeSeconds,
batteryPercent,
- batteryVoltageBytes[1],
- batteryVoltageBytes[0],
+ batteryController.Voltage(),
brightnessController.ToString(),
- resetReason);
+ resetReason,
+ ToString(motionController.DeviceType()));
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
- return std::unique_ptr(new Screens::Label(1, 4, app, label));
+ return std::make_unique(1, 5, app, label);
}
std::unique_ptr SystemInfo::CreateScreen3() {
@@ -177,28 +184,28 @@ std::unique_ptr SystemInfo::CreateScreen3() {
"\n"
"#444444 LVGL Memory#\n"
" #444444 used# %d (%d%%)\n"
- " #444444 max used# %d\n"
+ " #444444 max used# %lu\n"
" #444444 frag# %d%%\n"
" #444444 free# %d"
"\n"
- "#444444 Steps# %li",
+ "#444444 Steps# %i",
bleAddr[5],
bleAddr[4],
bleAddr[3],
bleAddr[2],
bleAddr[1],
bleAddr[0],
- (int) mon.total_size - mon.free_size,
+ static_cast(mon.total_size - mon.free_size),
mon.used_pct,
mon.max_used,
mon.frag_pct,
- (int) mon.free_biggest_size,
+ static_cast(mon.free_biggest_size),
0);
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
- return std::unique_ptr(new Screens::Label(2, 5, app, label));
+ return std::make_unique(2, 5, app, label);
}
-bool sortById(const TaskStatus_t& lhs, const TaskStatus_t& rhs) {
+bool SystemInfo::sortById(const TaskStatus_t& lhs, const TaskStatus_t& rhs) {
return lhs.xTaskNumber < rhs.xTaskNumber;
}
@@ -229,7 +236,7 @@ std::unique_ptr SystemInfo::CreateScreen4() {
lv_table_set_cell_value(infoTask, i + 1, 2, std::to_string(tasksStatus[i].usStackHighWaterMark).c_str());
}
}
- return std::unique_ptr(new Screens::Label(3, 5, app, infoTask));
+ return std::make_unique(3, 5, app, infoTask);
}
std::unique_ptr SystemInfo::CreateScreen5() {
@@ -245,5 +252,5 @@ std::unique_ptr SystemInfo::CreateScreen5() {
"#FFFF00 JF002/InfiniTime#");
lv_label_set_align(label, LV_LABEL_ALIGN_CENTER);
lv_obj_align(label, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
- return std::unique_ptr(new Screens::Label(4, 5, app, label));
+ return std::make_unique(4, 5, app, label);
}
diff --git a/src/displayapp/screens/SystemInfo.h b/src/displayapp/screens/SystemInfo.h
index c0c65554..9d471f61 100644
--- a/src/displayapp/screens/SystemInfo.h
+++ b/src/displayapp/screens/SystemInfo.h
@@ -27,7 +27,8 @@ namespace Pinetime {
Pinetime::Controllers::Battery& batteryController,
Pinetime::Controllers::BrightnessController& brightnessController,
Pinetime::Controllers::Ble& bleController,
- Pinetime::Drivers::WatchdogView& watchdog);
+ Pinetime::Drivers::WatchdogView& watchdog,
+ Pinetime::Controllers::MotionController& motionController);
~SystemInfo() override;
bool Refresh() override;
bool OnButtonPushed() override;
@@ -41,8 +42,12 @@ namespace Pinetime {
Pinetime::Controllers::BrightnessController& brightnessController;
Pinetime::Controllers::Ble& bleController;
Pinetime::Drivers::WatchdogView& watchdog;
+ Pinetime::Controllers::MotionController& motionController;
ScreenList<5> screens;
+
+ static bool sortById(const TaskStatus_t& lhs, const TaskStatus_t& rhs);
+
std::unique_ptr CreateScreen1();
std::unique_ptr CreateScreen2();
std::unique_ptr CreateScreen3();
diff --git a/src/displayapp/screens/Tile.cpp b/src/displayapp/screens/Tile.cpp
index ec36af38..3eb127cc 100644
--- a/src/displayapp/screens/Tile.cpp
+++ b/src/displayapp/screens/Tile.cpp
@@ -107,7 +107,7 @@ Tile::Tile(uint8_t screenID,
lv_obj_set_pos(backgroundLabel, 0, 0);
lv_label_set_text_static(backgroundLabel, "");
- taskUpdate = lv_task_create(lv_update_task, 500000, LV_TASK_PRIO_MID, this);
+ taskUpdate = lv_task_create(lv_update_task, 5000, LV_TASK_PRIO_MID, this);
}
Tile::~Tile() {
diff --git a/src/displayapp/screens/Timer.cpp b/src/displayapp/screens/Timer.cpp
index 260a17ef..99e979ba 100644
--- a/src/displayapp/screens/Timer.cpp
+++ b/src/displayapp/screens/Timer.cpp
@@ -63,8 +63,8 @@ Timer::Timer(DisplayApp* app, Controllers::TimerController& timerController)
lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
uint32_t seconds = timerController.GetTimeRemaining() / 1000;
- lv_label_set_text_fmt(time, "%02d:%02d", seconds / 60, seconds % 60);
-
+ lv_label_set_text_fmt(time, "%02lu:%02lu", seconds / 60, seconds % 60);
+
lv_obj_align(time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, -20);
btnPlayPause = lv_btn_create(lv_scr_act(), nullptr);
@@ -90,7 +90,7 @@ Timer::~Timer() {
bool Timer::Refresh() {
if (timerController.IsRunning()) {
uint32_t seconds = timerController.GetTimeRemaining() / 1000;
- lv_label_set_text_fmt(time, "%02d:%02d", seconds / 60, seconds % 60);
+ lv_label_set_text_fmt(time, "%02lu:%02lu", seconds / 60, seconds % 60);
}
return running;
}
diff --git a/src/displayapp/screens/WatchFaceAnalog.cpp b/src/displayapp/screens/WatchFaceAnalog.cpp
index 02f1fc2a..f1889379 100644
--- a/src/displayapp/screens/WatchFaceAnalog.cpp
+++ b/src/displayapp/screens/WatchFaceAnalog.cpp
@@ -5,39 +5,56 @@
#include "Symbols.h"
#include "NotificationIcon.h"
-#include
-
LV_IMG_DECLARE(bg_clock);
using namespace Pinetime::Applications::Screens;
-#define HOUR_LENGTH 70
-#define MINUTE_LENGTH 90
-#define SECOND_LENGTH 110
-#define PI 3.14159265358979323846
+namespace {
-// ##
-static int16_t coordinate_x_relocate(int16_t x) {
- return ((x) + LV_HOR_RES / 2);
+constexpr auto HOUR_LENGTH = 70;
+constexpr auto MINUTE_LENGTH = 90;
+constexpr auto SECOND_LENGTH = 110;
+
+// sin(90) = 1 so the value of _lv_trigo_sin(90) is the scaling factor
+const auto LV_TRIG_SCALE = _lv_trigo_sin(90);
+
+int16_t cosine(int16_t angle) {
+ return _lv_trigo_sin(angle + 90);
}
-// ##
-static int16_t coordinate_y_relocate(int16_t y) {
- return (((y) -LV_HOR_RES / 2) < 0) ? (0 - ((y) -LV_HOR_RES / 2)) : ((y) -LV_HOR_RES / 2);
+int16_t sine(int16_t angle) {
+ return _lv_trigo_sin(angle);
}
+int16_t coordinate_x_relocate(int16_t x) {
+ return (x + LV_HOR_RES / 2);
+}
+
+int16_t coordinate_y_relocate(int16_t y) {
+ return std::abs(y - LV_HOR_RES / 2);
+}
+
+lv_point_t coordinate_relocate(int16_t radius, int16_t angle) {
+ return lv_point_t{
+ .x = coordinate_x_relocate(radius * static_cast(sine(angle)) / LV_TRIG_SCALE),
+ .y = coordinate_y_relocate(radius * static_cast(cosine(angle)) / LV_TRIG_SCALE)
+ };
+}
+
+} // namespace
+
WatchFaceAnalog::WatchFaceAnalog(Pinetime::Applications::DisplayApp* app,
Controllers::DateTime& dateTimeController,
Controllers::Battery& batteryController,
Controllers::Ble& bleController,
- Controllers::NotificationManager& notificatioManager,
+ Controllers::NotificationManager& notificationManager,
Controllers::Settings& settingsController)
: Screen(app),
currentDateTime {{}},
dateTimeController {dateTimeController},
batteryController {batteryController},
bleController {bleController},
- notificatioManager {notificatioManager},
+ notificationManager {notificationManager},
settingsController {settingsController} {
settingsController.SetClockFace(1);
@@ -123,15 +140,12 @@ void WatchFaceAnalog::UpdateClock() {
second = dateTimeController.Seconds();
if (sMinute != minute) {
- minute_point[0].x = coordinate_x_relocate(30 * sin(minute * 6 * PI / 180));
- minute_point[0].y = coordinate_y_relocate(30 * cos(minute * 6 * PI / 180));
- minute_point[1].x = coordinate_x_relocate(MINUTE_LENGTH * sin(minute * 6 * PI / 180));
- minute_point[1].y = coordinate_y_relocate(MINUTE_LENGTH * cos(minute * 6 * PI / 180));
+ auto const angle = minute * 6;
+ minute_point[0] = coordinate_relocate(30, angle);
+ minute_point[1] = coordinate_relocate(MINUTE_LENGTH, angle);
- minute_point_trace[0].x = coordinate_x_relocate(5 * sin(minute * 6 * PI / 180));
- minute_point_trace[0].y = coordinate_y_relocate(5 * cos(minute * 6 * PI / 180));
- minute_point_trace[1].x = coordinate_x_relocate(31 * sin(minute * 6 * PI / 180));
- minute_point_trace[1].y = coordinate_y_relocate(31 * cos(minute * 6 * PI / 180));
+ minute_point_trace[0] = coordinate_relocate(5, angle);
+ minute_point_trace[1] = coordinate_relocate(31, angle);
lv_line_set_points(minute_body, minute_point, 2);
lv_line_set_points(minute_body_trace, minute_point_trace, 2);
@@ -140,15 +154,13 @@ void WatchFaceAnalog::UpdateClock() {
if (sHour != hour || sMinute != minute) {
sHour = hour;
sMinute = minute;
- hour_point[0].x = coordinate_x_relocate(30 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
- hour_point[0].y = coordinate_y_relocate(30 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
- hour_point[1].x = coordinate_x_relocate(HOUR_LENGTH * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
- hour_point[1].y = coordinate_y_relocate(HOUR_LENGTH * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
+ auto const angle = (hour * 30 + minute / 2);
- hour_point_trace[0].x = coordinate_x_relocate(5 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
- hour_point_trace[0].y = coordinate_y_relocate(5 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
- hour_point_trace[1].x = coordinate_x_relocate(31 * sin((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
- hour_point_trace[1].y = coordinate_y_relocate(31 * cos((((hour > 12 ? hour - 12 : hour) * 30) + (minute * 0.5)) * PI / 180));
+ hour_point[0] = coordinate_relocate(30, angle);
+ hour_point[1] = coordinate_relocate(HOUR_LENGTH, angle);
+
+ hour_point_trace[0] = coordinate_relocate(5, angle);
+ hour_point_trace[1] = coordinate_relocate(31, angle);
lv_line_set_points(hour_body, hour_point, 2);
lv_line_set_points(hour_body_trace, hour_point_trace, 2);
@@ -156,23 +168,22 @@ void WatchFaceAnalog::UpdateClock() {
if (sSecond != second) {
sSecond = second;
- second_point[0].x = coordinate_x_relocate(20 * sin((180 + second * 6) * PI / 180));
- second_point[0].y = coordinate_y_relocate(20 * cos((180 + second * 6) * PI / 180));
- second_point[1].x = coordinate_x_relocate(SECOND_LENGTH * sin(second * 6 * PI / 180));
- second_point[1].y = coordinate_y_relocate(SECOND_LENGTH * cos(second * 6 * PI / 180));
+ auto const angle = second * 6;
+
+ second_point[0] = coordinate_relocate(-20, angle);
+ second_point[1] = coordinate_relocate(SECOND_LENGTH, angle);
lv_line_set_points(second_body, second_point, 2);
}
}
bool WatchFaceAnalog::Refresh() {
-
batteryPercentRemaining = batteryController.PercentRemaining();
if (batteryPercentRemaining.IsUpdated()) {
auto batteryPercent = batteryPercentRemaining.Get();
lv_label_set_text(batteryIcon, BatteryIcon::GetBatteryIcon(batteryPercent));
}
- notificationState = notificatioManager.AreNewNotificationsAvailable();
+ notificationState = notificationManager.AreNewNotificationsAvailable();
if (notificationState.IsUpdated()) {
if (notificationState.Get() == true)
@@ -202,4 +213,4 @@ bool WatchFaceAnalog::Refresh() {
}
return true;
-}
\ No newline at end of file
+}
diff --git a/src/displayapp/screens/WatchFaceAnalog.h b/src/displayapp/screens/WatchFaceAnalog.h
index 667f6241..ac7f0ac5 100644
--- a/src/displayapp/screens/WatchFaceAnalog.h
+++ b/src/displayapp/screens/WatchFaceAnalog.h
@@ -27,7 +27,7 @@ namespace Pinetime {
Controllers::DateTime& dateTimeController,
Controllers::Battery& batteryController,
Controllers::Ble& bleController,
- Controllers::NotificationManager& notificatioManager,
+ Controllers::NotificationManager& notificationManager,
Controllers::Settings& settingsController);
~WatchFaceAnalog() override;
@@ -48,7 +48,7 @@ namespace Pinetime {
Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown;
uint8_t currentDay = 0;
- DirtyValue batteryPercentRemaining {0};
+ DirtyValue batteryPercentRemaining {0};
DirtyValue> currentDateTime;
DirtyValue notificationState {false};
@@ -79,11 +79,11 @@ namespace Pinetime {
Controllers::DateTime& dateTimeController;
Controllers::Battery& batteryController;
Controllers::Ble& bleController;
- Controllers::NotificationManager& notificatioManager;
+ Controllers::NotificationManager& notificationManager;
Controllers::Settings& settingsController;
void UpdateClock();
};
}
}
-}
\ No newline at end of file
+}
diff --git a/src/displayapp/screens/WatchFaceDigital.h b/src/displayapp/screens/WatchFaceDigital.h
index 246efc95..76c8d3dc 100644
--- a/src/displayapp/screens/WatchFaceDigital.h
+++ b/src/displayapp/screens/WatchFaceDigital.h
@@ -45,7 +45,7 @@ namespace Pinetime {
Pinetime::Controllers::DateTime::Days currentDayOfWeek = Pinetime::Controllers::DateTime::Days::Unknown;
uint8_t currentDay = 0;
- DirtyValue batteryPercentRemaining {};
+ DirtyValue batteryPercentRemaining {};
DirtyValue bleState {};
DirtyValue> currentDateTime {};
DirtyValue motionSensorOk {};
diff --git a/src/displayapp/screens/settings/QuickSettings.cpp b/src/displayapp/screens/settings/QuickSettings.cpp
index 20d2cd22..3fb9c70b 100644
--- a/src/displayapp/screens/settings/QuickSettings.cpp
+++ b/src/displayapp/screens/settings/QuickSettings.cpp
@@ -7,12 +7,12 @@ using namespace Pinetime::Applications::Screens;
namespace {
static void ButtonEventHandler(lv_obj_t* obj, lv_event_t event) {
- QuickSettings* screen = static_cast(obj->user_data);
+ auto* screen = static_cast(obj->user_data);
screen->OnButtonEvent(obj, event);
}
static void lv_update_task(struct _lv_task_t* task) {
- auto user_data = static_cast(task->user_data);
+ auto* user_data = static_cast(task->user_data);
user_data->UpdateScreen();
}
}
@@ -110,7 +110,7 @@ QuickSettings::QuickSettings(Pinetime::Applications::DisplayApp* app,
lv_obj_set_pos(backgroundLabel, 0, 0);
lv_label_set_text_static(backgroundLabel, "");
- taskUpdate = lv_task_create(lv_update_task, 500000, LV_TASK_PRIO_MID, this);
+ taskUpdate = lv_task_create(lv_update_task, 5000, LV_TASK_PRIO_MID, this);
}
QuickSettings::~QuickSettings() {
diff --git a/src/displayapp/screens/settings/SettingSteps.cpp b/src/displayapp/screens/settings/SettingSteps.cpp
index b7c024f1..faa843e6 100644
--- a/src/displayapp/screens/settings/SettingSteps.cpp
+++ b/src/displayapp/screens/settings/SettingSteps.cpp
@@ -45,7 +45,7 @@ SettingSteps::SettingSteps(
stepValue = lv_label_create(lv_scr_act(), NULL);
lv_obj_set_style_local_text_font(stepValue, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_42);
- lv_label_set_text_fmt(stepValue,"%i", settingsController.GetStepsGoal());
+ lv_label_set_text_fmt(stepValue, "%lu", settingsController.GetStepsGoal());
lv_label_set_align(stepValue, LV_LABEL_ALIGN_CENTER);
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_CENTER, 0, -10);
@@ -81,7 +81,7 @@ void SettingSteps::UpdateSelected(lv_obj_t *object, lv_event_t event) {
value += 1000;
if ( value <= 500000 ) {
settingsController.SetStepsGoal(value);
- lv_label_set_text_fmt(stepValue,"%i", settingsController.GetStepsGoal());
+ lv_label_set_text_fmt(stepValue, "%lu", settingsController.GetStepsGoal());
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_CENTER, 0, -10);
}
}
@@ -90,7 +90,7 @@ void SettingSteps::UpdateSelected(lv_obj_t *object, lv_event_t event) {
value -= 1000;
if ( value >= 1000 ) {
settingsController.SetStepsGoal(value);
- lv_label_set_text_fmt(stepValue,"%i", settingsController.GetStepsGoal());
+ lv_label_set_text_fmt(stepValue, "%lu", settingsController.GetStepsGoal());
lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_CENTER, 0, -10);
}
}
diff --git a/src/displayapp/screens/settings/SettingWatchFace.cpp b/src/displayapp/screens/settings/SettingWatchFace.cpp
index 457cebf6..3e73489d 100644
--- a/src/displayapp/screens/settings/SettingWatchFace.cpp
+++ b/src/displayapp/screens/settings/SettingWatchFace.cpp
@@ -58,6 +58,15 @@ SettingWatchFace::SettingWatchFace(Pinetime::Applications::DisplayApp* app, Pine
lv_checkbox_set_checked(cbOption[optionsTotal], true);
}
+ optionsTotal++;
+ cbOption[optionsTotal] = lv_checkbox_create(container1, nullptr);
+ lv_checkbox_set_text_static(cbOption[optionsTotal], " PineTimeStyle");
+ cbOption[optionsTotal]->user_data = this;
+ lv_obj_set_event_cb(cbOption[optionsTotal], event_handler);
+ if (settingsController.GetClockFace() == 2) {
+ lv_checkbox_set_checked(cbOption[optionsTotal], true);
+ }
+
optionsTotal++;
}
diff --git a/src/displayapp/screens/settings/Settings.cpp b/src/displayapp/screens/settings/Settings.cpp
index 2c72c832..e63a3584 100644
--- a/src/displayapp/screens/settings/Settings.cpp
+++ b/src/displayapp/screens/settings/Settings.cpp
@@ -46,7 +46,7 @@ std::unique_ptr Settings::CreateScreen1() {
{Symbols::clock, "Watch face", Apps::SettingWatchFace},
}};
- return std::unique_ptr(new Screens::List(0, 2, app, settingsController, applications));
+ return std::make_unique(0, 2, app, settingsController, applications);
}
std::unique_ptr Settings::CreateScreen2() {
@@ -58,5 +58,5 @@ std::unique_ptr Settings::CreateScreen2() {
{Symbols::list, "About", Apps::SysInfo},
}};
- return std::unique_ptr(new Screens::List(1, 2, app, settingsController, applications));
+ return std::make_unique(1, 2, app, settingsController, applications);
}
diff --git a/src/displayapp/screens/settings/Settings.h b/src/displayapp/screens/settings/Settings.h
index 7e332dfe..711a6be6 100644
--- a/src/displayapp/screens/settings/Settings.h
+++ b/src/displayapp/screens/settings/Settings.h
@@ -16,7 +16,6 @@ namespace Pinetime {
bool Refresh() override;
- void OnButtonEvent(lv_obj_t* object, lv_event_t event);
bool OnTouchEvent(Pinetime::Applications::TouchEvents event) override;
private:
diff --git a/src/drivers/Bma421.cpp b/src/drivers/Bma421.cpp
index 925b66c7..dd284000 100644
--- a/src/drivers/Bma421.cpp
+++ b/src/drivers/Bma421.cpp
@@ -42,6 +42,12 @@ void Bma421::Init() {
if (ret != BMA4_OK)
return;
+ switch(bma.chip_id) {
+ case BMA423_CHIP_ID: deviceType = DeviceTypes::BMA421; break;
+ case BMA425_CHIP_ID: deviceType = DeviceTypes::BMA425; break;
+ default: deviceType = DeviceTypes::Unknown; break;
+ }
+
ret = bma423_write_config_file(&bma);
if (ret != BMA4_OK)
return;
@@ -103,8 +109,6 @@ Bma421::Values Bma421::Process() {
uint8_t activity = 0;
bma423_activity_output(&activity, &bma);
- NRF_LOG_INFO("MOTION : %d - %d/%d/%d", steps, data.x, data.y, data.z);
-
// X and Y axis are swapped because of the way the sensor is mounted in the PineTime
return {steps, data.y, data.x, data.z};
}
@@ -123,3 +127,6 @@ void Bma421::SoftReset() {
nrf_delay_ms(1);
}
}
+Bma421::DeviceTypes Bma421::DeviceType() const {
+ return deviceType;
+}
diff --git a/src/drivers/Bma421.h b/src/drivers/Bma421.h
index e4d925f5..ace644bd 100644
--- a/src/drivers/Bma421.h
+++ b/src/drivers/Bma421.h
@@ -6,6 +6,11 @@ namespace Pinetime {
class TwiMaster;
class Bma421 {
public:
+ enum class DeviceTypes : uint8_t {
+ Unknown,
+ BMA421,
+ BMA425
+ };
struct Values {
uint32_t steps;
int16_t x;
@@ -29,6 +34,7 @@ namespace Pinetime {
void Write(uint8_t registerAddress, const uint8_t* data, size_t size);
bool IsOk() const;
+ DeviceTypes DeviceType() const;
private:
void Reset();
@@ -38,6 +44,7 @@ namespace Pinetime {
struct bma4_dev bma;
bool isOk = false;
bool isResetOk = false;
+ DeviceTypes deviceType = DeviceTypes::Unknown;
};
}
}
\ No newline at end of file
diff --git a/src/drivers/Bma421_C/bma423.c b/src/drivers/Bma421_C/bma423.c
index 1d782705..7d6c2e0a 100644
--- a/src/drivers/Bma421_C/bma423.c
+++ b/src/drivers/Bma421_C/bma423.c
@@ -43,6 +43,521 @@
#include "bma423.h"
/**\name Feature configuration file */
+const uint8_t bma425_config_file[] = {
+ 0x80, 0x2e, 0xfd, 0x00, 0x80, 0x2e, 0xff, 0x00, 0xc8, 0x2e, 0x00, 0x2e,
+ 0x80, 0x2e, 0xfb, 0x00, 0x80, 0x2e, 0xdd, 0xb0, 0x80, 0x2e, 0xfe, 0x00,
+ 0x80, 0x2e, 0xfc, 0x00, 0x80, 0x2e, 0x0d, 0xb1, 0x50, 0x39, 0x21, 0x2e,
+ 0xb0, 0xf0, 0x10, 0x30, 0x21, 0x2e, 0x16, 0xf0, 0x80, 0x2e, 0x34, 0xb1,
+ 0x65, 0x50, 0x4f, 0x52, 0x01, 0x42, 0x3b, 0x80, 0x41, 0x30, 0x01, 0x42,
+ 0x3c, 0x80, 0x00, 0x2e, 0x01, 0x40, 0x01, 0x42, 0x21, 0x2e, 0xff, 0xaf,
+ 0xb8, 0x2e, 0x1f, 0x7f, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0xfd, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+ 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2e,
+ 0x55, 0xf0, 0xc0, 0x2e, 0x21, 0x2e, 0x55, 0xf0, 0x30, 0x50, 0x00, 0x30,
+ 0x51, 0x56, 0x05, 0x30, 0x05, 0x2c, 0xfb, 0x7f, 0x3e, 0xbe, 0xd2, 0xba,
+ 0xb2, 0xb9, 0x6c, 0x0b, 0x53, 0x0e, 0xf9, 0x2f, 0x53, 0x1a, 0x01, 0x2f,
+ 0x4d, 0x0e, 0xf5, 0x2f, 0xd2, 0x7f, 0x04, 0x30, 0x1f, 0x2c, 0xe1, 0x7f,
+ 0xc5, 0x01, 0xa3, 0x03, 0x72, 0x0e, 0x03, 0x2f, 0x72, 0x1a, 0x0f, 0x2f,
+ 0x79, 0x0f, 0x0d, 0x2f, 0xe1, 0x6f, 0x4f, 0x04, 0x5f, 0xb9, 0xb1, 0xbf,
+ 0xfa, 0x0b, 0xd2, 0x6f, 0x96, 0x06, 0xb1, 0x25, 0x51, 0xbf, 0xeb, 0x7f,
+ 0x06, 0x00, 0xb2, 0x25, 0x27, 0x03, 0xdb, 0x7f, 0xcf, 0xbf, 0x3e, 0xbf,
+ 0x01, 0xb8, 0xd2, 0xba, 0x41, 0xba, 0xb2, 0xb9, 0x07, 0x0a, 0x6e, 0x0b,
+ 0xc0, 0x90, 0xdf, 0x2f, 0x40, 0x91, 0xdd, 0x2f, 0xfb, 0x6f, 0xd0, 0x5f,
+ 0xb8, 0x2e, 0x00, 0x31, 0xc0, 0x2e, 0x21, 0x2e, 0xba, 0xf0, 0xc8, 0x2e,
+ 0xc8, 0x2e, 0xc8, 0x2e, 0xc8, 0x2e, 0xc8, 0x2e, 0xaa, 0x00, 0x05, 0x00,
+ 0xaa, 0x00, 0x05, 0x00, 0x2d, 0x01, 0xd4, 0x7b, 0x3b, 0x01, 0xdb, 0x7a,
+ 0x04, 0x00, 0x3f, 0x7b, 0xcd, 0x6c, 0xc3, 0x04, 0x85, 0x09, 0xc3, 0x04,
+ 0xec, 0xe6, 0x0c, 0x46, 0x01, 0x00, 0x27, 0x00, 0x19, 0x00, 0x96, 0x00,
+ 0xa0, 0x00, 0x01, 0x00, 0x0c, 0x00, 0xf0, 0x3c, 0x00, 0x01, 0x01, 0x00,
+ 0x03, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00,
+ 0x00, 0x00, 0x47, 0x28, 0x88, 0x00, 0x54, 0x00, 0x51, 0x00, 0x97, 0x00,
+ 0xa0, 0x00, 0x80, 0x00, 0x00, 0x40, 0xff, 0x7f, 0x00, 0x80, 0xaf, 0x00,
+ 0xff, 0x00, 0xff, 0xb7, 0x00, 0x02, 0x00, 0xb0, 0x05, 0x80, 0xb1, 0xf0,
+ 0x5e, 0xf0, 0xc0, 0x00, 0x59, 0xf0, 0x39, 0xf0, 0x57, 0x00, 0x89, 0xf0,
+ 0x54, 0x00, 0x00, 0x20, 0x82, 0x00, 0x59, 0x00, 0x5d, 0x00, 0x81, 0x00,
+ 0xff, 0xfb, 0x52, 0xf0, 0x56, 0xf0, 0x33, 0x09, 0x33, 0x07, 0x00, 0x08,
+ 0x90, 0x01, 0x00, 0xf8, 0x00, 0x01, 0x02, 0x01, 0x60, 0x00, 0x6a, 0x00,
+ 0x4c, 0x04, 0xa0, 0x00, 0xe8, 0x03, 0x81, 0x00, 0x82, 0x00, 0xeb, 0x07,
+ 0xae, 0x07, 0xaa, 0x00, 0x75, 0x00, 0xff, 0x0f, 0xdb, 0x00, 0xb6, 0x01,
+ 0x70, 0x69, 0x26, 0xd3, 0x9c, 0x07, 0xbc, 0x02, 0x1f, 0x05, 0x9d, 0x00,
+ 0xa8, 0x05, 0xee, 0x06, 0x01, 0xf0, 0xbc, 0x05, 0x37, 0x08, 0xbb, 0x06,
+ 0x37, 0xfa, 0xb2, 0x00, 0xff, 0x03, 0x98, 0x2e, 0x15, 0xb0, 0x20, 0x26,
+ 0x98, 0x2e, 0xf7, 0x00, 0x98, 0x2e, 0xc4, 0xb0, 0x10, 0x30, 0x21, 0x2e,
+ 0x59, 0xf0, 0x98, 0x2e, 0xb9, 0x00, 0x98, 0x2e, 0x7a, 0xb4, 0x98, 0x2e,
+ 0x89, 0xb4, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0x98, 0x2e, 0xa7, 0xb0,
+ 0x01, 0x2e, 0x58, 0x00, 0x00, 0xb2, 0x1a, 0x2f, 0x00, 0x30, 0x21, 0x2e,
+ 0x58, 0x00, 0x47, 0x50, 0x98, 0x2e, 0x65, 0xb0, 0x03, 0x2e, 0x1e, 0x01,
+ 0x47, 0x50, 0x02, 0x30, 0x98, 0x2e, 0x28, 0xb5, 0x03, 0x2e, 0x1f, 0x01,
+ 0x47, 0x50, 0x12, 0x30, 0x98, 0x2e, 0x28, 0xb5, 0x01, 0x2e, 0x03, 0xf0,
+ 0x0d, 0xbc, 0x0f, 0xb8, 0x00, 0x90, 0x02, 0x2f, 0x4f, 0x50, 0x21, 0x2e,
+ 0xbc, 0xf0, 0x01, 0x2e, 0x57, 0x00, 0x00, 0xb2, 0x25, 0x2f, 0x00, 0x30,
+ 0x21, 0x2e, 0x57, 0x00, 0x49, 0x50, 0x98, 0x2e, 0x65, 0xb0, 0x49, 0x50,
+ 0x98, 0x2e, 0xc1, 0xb1, 0x49, 0x50, 0x98, 0x2e, 0x34, 0xb6, 0x49, 0x50,
+ 0x4b, 0x52, 0x98, 0x2e, 0xa4, 0xb4, 0x49, 0x50, 0x4d, 0x52, 0x98, 0x2e,
+ 0xa4, 0xb4, 0x01, 0x2e, 0x1e, 0x01, 0x0f, 0xbc, 0x0f, 0xb8, 0x00, 0x90,
+ 0x4f, 0x50, 0x08, 0x2f, 0x03, 0x2e, 0x1f, 0x01, 0x9f, 0xbc, 0x9f, 0xb8,
+ 0x40, 0x90, 0x02, 0x2f, 0x21, 0x2e, 0xbc, 0xf0, 0x02, 0x2d, 0x21, 0x2e,
+ 0xba, 0xf0, 0x98, 0x2e, 0xb9, 0x00, 0xaf, 0x2d, 0x10, 0x50, 0xfb, 0x7f,
+ 0x21, 0x25, 0x98, 0x2e, 0xf4, 0x01, 0xfb, 0x6f, 0x21, 0x25, 0xf0, 0x5f,
+ 0x10, 0x25, 0x80, 0x2e, 0xbe, 0x00, 0x94, 0x01, 0xdd, 0x03, 0xc0, 0xad,
+ 0x0b, 0x2f, 0xc0, 0xa8, 0x03, 0x2f, 0xc0, 0x90, 0x07, 0x2f, 0x80, 0xa6,
+ 0x05, 0x2f, 0x40, 0xa9, 0x12, 0x2f, 0x40, 0x91, 0x01, 0x2f, 0x00, 0xab,
+ 0x0e, 0x2f, 0xc0, 0xac, 0x00, 0x30, 0x55, 0x52, 0x07, 0x2f, 0xc0, 0xa9,
+ 0x03, 0x2f, 0xc0, 0x91, 0x03, 0x2f, 0x80, 0xa7, 0x01, 0x2f, 0x40, 0xa1,
+ 0x05, 0x2f, 0xc0, 0x2e, 0x17, 0x25, 0x06, 0x25, 0xc0, 0x2e, 0xf0, 0x3f,
+ 0x53, 0x52, 0xb8, 0x2e, 0x83, 0x86, 0x01, 0x30, 0x00, 0x30, 0x94, 0x40,
+ 0x24, 0x18, 0x06, 0x00, 0x53, 0x0e, 0x4f, 0x02, 0xf9, 0x2f, 0xb8, 0x2e,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0xa8, 0x03, 0x25, 0x10, 0x2f, 0x80, 0x90,
+ 0x01, 0x2f, 0x41, 0x0e, 0x0c, 0x2f, 0xf3, 0x3f, 0x18, 0x05, 0x05, 0x30,
+ 0x5d, 0x07, 0x15, 0x0e, 0x03, 0x2f, 0x55, 0x1a, 0x02, 0x2f, 0xcc, 0x0f,
+ 0x00, 0x2f, 0x58, 0x04, 0x01, 0x25, 0xb8, 0x2e, 0xb8, 0x2e, 0x63, 0x50,
+ 0x41, 0x30, 0x02, 0x40, 0x51, 0x0a, 0x01, 0x42, 0x18, 0x82, 0x57, 0x50,
+ 0x60, 0x42, 0x70, 0x3c, 0x59, 0x54, 0x42, 0x42, 0x69, 0x82, 0x82, 0x32,
+ 0x43, 0x40, 0x18, 0x08, 0x02, 0x0a, 0x40, 0x42, 0x42, 0x80, 0x02, 0x3f,
+ 0x01, 0x40, 0x10, 0x50, 0x4a, 0x08, 0xfb, 0x7f, 0x11, 0x42, 0x0b, 0x31,
+ 0x0b, 0x42, 0x3e, 0x80, 0x31, 0x32, 0x01, 0x42, 0x00, 0x2e, 0x01, 0x2e,
+ 0x40, 0xf0, 0x13, 0x90, 0x20, 0x2f, 0x03, 0x30, 0x5d, 0x50, 0x5b, 0x54,
+ 0x14, 0x35, 0x06, 0x30, 0x61, 0x52, 0x55, 0x32, 0x1d, 0x1a, 0xe3, 0x22,
+ 0x18, 0x1a, 0x5f, 0x58, 0xe3, 0x22, 0x04, 0x30, 0xd5, 0x40, 0xb5, 0x0d,
+ 0xe1, 0xbe, 0x6f, 0xbb, 0x80, 0x91, 0xa9, 0x0d, 0x01, 0x89, 0xb5, 0x23,
+ 0x10, 0xa1, 0xf7, 0x2f, 0xda, 0x0e, 0x14, 0x35, 0xeb, 0x2f, 0x01, 0x2e,
+ 0x25, 0x00, 0x70, 0x1a, 0x00, 0x30, 0x21, 0x30, 0x02, 0x2c, 0x08, 0x22,
+ 0x30, 0x30, 0x00, 0xb2, 0x06, 0x2f, 0x21, 0x2e, 0x59, 0xf0, 0x98, 0x2e,
+ 0xb9, 0x00, 0x00, 0x2e, 0x00, 0x2e, 0xd0, 0x2e, 0xfb, 0x6f, 0xf0, 0x5f,
+ 0xb8, 0x2e, 0x70, 0x50, 0x03, 0x2e, 0x22, 0x01, 0xf1, 0x7f, 0x2a, 0x25,
+ 0xb9, 0x82, 0xe0, 0x7f, 0xdb, 0x7f, 0x00, 0x30, 0x45, 0x30, 0x32, 0x30,
+ 0x03, 0x30, 0x04, 0x30, 0xf6, 0x6f, 0xf2, 0x09, 0xfc, 0x13, 0xc2, 0xab,
+ 0xb5, 0x09, 0xc7, 0x23, 0x80, 0xb3, 0xe6, 0x6f, 0xb7, 0x01, 0x00, 0x2e,
+ 0x8b, 0x41, 0x4b, 0x42, 0x05, 0x2f, 0xc5, 0x7f, 0x05, 0x30, 0x46, 0x40,
+ 0xae, 0x05, 0xc5, 0x6f, 0x46, 0x42, 0x01, 0x80, 0x23, 0xbd, 0xd3, 0xbe,
+ 0x03, 0x89, 0x41, 0x82, 0xdf, 0x0c, 0x03, 0xa2, 0xe4, 0x2f, 0xe0, 0x6f,
+ 0x91, 0x6f, 0x11, 0x42, 0xc3, 0xb2, 0xa1, 0x6f, 0x11, 0x42, 0x00, 0x2e,
+ 0xb1, 0x6f, 0x01, 0x42, 0x06, 0x2f, 0x00, 0x32, 0x03, 0x2e, 0x59, 0xf0,
+ 0x08, 0x0a, 0x21, 0x2e, 0x59, 0xf0, 0x06, 0x2d, 0xf1, 0x3d, 0x01, 0x2e,
+ 0x59, 0xf0, 0x01, 0x08, 0x21, 0x2e, 0x59, 0xf0, 0xdb, 0x6f, 0x90, 0x5f,
+ 0xb8, 0x2e, 0x69, 0x50, 0x05, 0x2e, 0x00, 0xf0, 0x4f, 0x56, 0xd3, 0x0f,
+ 0x01, 0x40, 0xf4, 0x33, 0xcc, 0x08, 0x0d, 0x2f, 0xf4, 0x30, 0x94, 0x08,
+ 0xb9, 0x88, 0x02, 0xa3, 0x04, 0x2f, 0x67, 0x58, 0x4c, 0x0a, 0x87, 0xa2,
+ 0x05, 0x2c, 0xcb, 0x22, 0x4f, 0x54, 0x4a, 0x0a, 0xf2, 0x3b, 0xca, 0x08,
+ 0x3c, 0x80, 0x27, 0x2e, 0x59, 0xf0, 0x01, 0x40, 0x01, 0x42, 0xb8, 0x2e,
+ 0x01, 0x2e, 0xb1, 0xf0, 0x67, 0x52, 0x01, 0x0a, 0x21, 0x2e, 0xb1, 0xf0,
+ 0x01, 0x2e, 0x1e, 0x01, 0x0f, 0xbc, 0x0f, 0xb8, 0x00, 0x90, 0x4f, 0x50,
+ 0x08, 0x2f, 0x03, 0x2e, 0x1f, 0x01, 0x9f, 0xbc, 0x9f, 0xb8, 0x40, 0x90,
+ 0x02, 0x2f, 0xc0, 0x2e, 0x21, 0x2e, 0xbc, 0xf0, 0xc0, 0x2e, 0x21, 0x2e,
+ 0xba, 0xf0, 0x70, 0x50, 0xf7, 0x7f, 0x00, 0x2e, 0x0f, 0x2e, 0xb8, 0xf0,
+ 0xf8, 0xbf, 0xff, 0xbb, 0xc0, 0xb3, 0x23, 0x2f, 0xb2, 0x7f, 0x94, 0x7f,
+ 0xc6, 0x7f, 0xe5, 0x7f, 0xd3, 0x7f, 0xa1, 0x7f, 0x35, 0x30, 0x05, 0x2e,
+ 0x01, 0xf0, 0x2e, 0xbd, 0x2e, 0xbb, 0x6b, 0x58, 0x6e, 0x05, 0x47, 0x56,
+ 0x6d, 0x54, 0x11, 0x30, 0x27, 0x41, 0x06, 0x41, 0xf8, 0xbf, 0xbe, 0x0b,
+ 0xb5, 0x11, 0xd6, 0x42, 0x03, 0x89, 0x5a, 0x0e, 0xf6, 0x2f, 0x23, 0x2e,
+ 0x58, 0x00, 0x4f, 0x52, 0x23, 0x2e, 0xb8, 0xf0, 0xb2, 0x6f, 0xe5, 0x6f,
+ 0xd3, 0x6f, 0xa1, 0x6f, 0x94, 0x6f, 0xc6, 0x6f, 0xf7, 0x6f, 0x90, 0x5f,
+ 0xc8, 0x2e, 0x60, 0x50, 0xc3, 0x7f, 0xd4, 0x7f, 0xe7, 0x7f, 0xf6, 0x7f,
+ 0xb2, 0x7f, 0xa5, 0x7f, 0x36, 0x30, 0x07, 0x2e, 0x01, 0xf0, 0xbe, 0xbd,
+ 0xbe, 0xbb, 0x6f, 0x58, 0x77, 0x05, 0x49, 0x56, 0x71, 0x54, 0x27, 0x41,
+ 0x06, 0x41, 0xf8, 0xbf, 0xbe, 0x0b, 0xb5, 0x11, 0xd6, 0x42, 0x03, 0x89,
+ 0x5a, 0x0e, 0xf6, 0x2f, 0x12, 0x30, 0x25, 0x2e, 0x57, 0x00, 0x02, 0x31,
+ 0x25, 0x2e, 0xb8, 0xf0, 0xd4, 0x6f, 0xc3, 0x6f, 0xe7, 0x6f, 0xb2, 0x6f,
+ 0xa5, 0x6f, 0xf6, 0x6f, 0xa0, 0x5f, 0xc8, 0x2e, 0x1a, 0x24, 0x26, 0x00,
+ 0x80, 0x2e, 0x65, 0x01, 0x70, 0x50, 0x42, 0x8e, 0xd4, 0x7f, 0xf6, 0x7f,
+ 0x47, 0x25, 0x1a, 0x18, 0x73, 0x52, 0xf1, 0x00, 0x64, 0x25, 0x01, 0x30,
+ 0x39, 0x02, 0x94, 0x41, 0x81, 0x41, 0xe2, 0x7f, 0xbe, 0xbb, 0xbd, 0x8d,
+ 0x02, 0xbd, 0xb5, 0x7f, 0x8e, 0xb5, 0xba, 0x0a, 0xc6, 0x7f, 0xab, 0x7f,
+ 0x51, 0x25, 0x98, 0x2e, 0xd1, 0x01, 0xd5, 0x6f, 0xe2, 0x6f, 0x2a, 0x18,
+ 0x73, 0x54, 0xb2, 0x01, 0x02, 0x30, 0xc4, 0x6f, 0x7a, 0x03, 0x12, 0x41,
+ 0x74, 0x25, 0xd0, 0x7f, 0x52, 0xbc, 0xd3, 0x41, 0x6e, 0xba, 0xde, 0xb6,
+ 0x20, 0x0b, 0xc7, 0x7f, 0x91, 0x7f, 0x98, 0x2e, 0xd1, 0x01, 0xf2, 0x6f,
+ 0xd5, 0x6f, 0xca, 0x16, 0x55, 0x18, 0xdd, 0x18, 0x95, 0x6f, 0xea, 0x18,
+ 0x73, 0x5a, 0x31, 0x25, 0x75, 0x01, 0x01, 0x30, 0x20, 0x25, 0x39, 0x02,
+ 0x5e, 0xba, 0x82, 0xbc, 0x8e, 0xb6, 0x21, 0x0b, 0x98, 0x2e, 0xd1, 0x01,
+ 0xe2, 0x6f, 0xb5, 0x6f, 0x2a, 0x18, 0xe0, 0x7f, 0xf1, 0x7f, 0x04, 0x30,
+ 0x73, 0x54, 0xf2, 0x00, 0x7c, 0x02, 0x85, 0x6f, 0xd0, 0x6f, 0x0d, 0x17,
+ 0x68, 0x18, 0xe0, 0x18, 0x90, 0x6f, 0xc4, 0x6f, 0xc5, 0x18, 0xeb, 0x6f,
+ 0xb2, 0x01, 0x1b, 0x43, 0x02, 0x30, 0x7a, 0x03, 0xfb, 0x6f, 0x3d, 0x8f,
+ 0x0b, 0x43, 0x3e, 0xba, 0x12, 0xbd, 0x52, 0xbc, 0x6e, 0xbb, 0xa2, 0x0a,
+ 0x9e, 0xb5, 0xde, 0xb6, 0x30, 0x0b, 0xf7, 0x7f, 0x98, 0x2e, 0xd1, 0x01,
+ 0xf5, 0x6f, 0x31, 0x25, 0xd1, 0x6f, 0x92, 0x6f, 0xab, 0x6f, 0x50, 0x43,
+ 0x43, 0x43, 0x90, 0x5f, 0x53, 0x56, 0x80, 0x2e, 0x00, 0xb0, 0x10, 0x50,
+ 0x03, 0x40, 0x19, 0x18, 0x55, 0x56, 0x19, 0x05, 0x36, 0x25, 0xf7, 0x7f,
+ 0x4a, 0x17, 0x54, 0x18, 0xec, 0x18, 0x09, 0x17, 0x01, 0x30, 0x0c, 0x07,
+ 0xe2, 0x18, 0xde, 0x00, 0xf2, 0x6f, 0x97, 0x02, 0x51, 0x58, 0xdc, 0x00,
+ 0x91, 0x02, 0xbf, 0xb8, 0x21, 0xbd, 0x8a, 0x0a, 0xc0, 0x2e, 0x02, 0x42,
+ 0xf0, 0x5f, 0x09, 0x2e, 0x1d, 0x01, 0x05, 0x2e, 0x1d, 0x01, 0xa3, 0xbc,
+ 0x44, 0xbe, 0x90, 0x50, 0x4f, 0xb9, 0x07, 0x2e, 0x1d, 0x01, 0x4a, 0x25,
+ 0x9f, 0xb8, 0x39, 0x8f, 0xb2, 0xbd, 0xf2, 0x7f, 0xbf, 0xb9, 0xeb, 0x7f,
+ 0x8a, 0x0a, 0x37, 0x89, 0x0b, 0x30, 0x93, 0x0a, 0x8b, 0x7f, 0xcb, 0x43,
+ 0x0b, 0x43, 0x80, 0xb2, 0xd3, 0x7f, 0xc1, 0x7f, 0x90, 0x2e, 0x6c, 0xb2,
+ 0x20, 0x25, 0x01, 0x2e, 0x5f, 0x00, 0x01, 0x90, 0x0e, 0x2f, 0x75, 0x52,
+ 0x01, 0x2e, 0x5c, 0x00, 0xb4, 0x7f, 0xa2, 0x7f, 0x98, 0x2e, 0x72, 0xb2,
+ 0x00, 0x30, 0x21, 0x2e, 0x5f, 0x00, 0xc1, 0x6f, 0xd3, 0x6f, 0xa2, 0x6f,
+ 0xb4, 0x6f, 0x0b, 0x30, 0x01, 0x2e, 0x1d, 0x01, 0x06, 0xbc, 0x06, 0xbb,
+ 0x57, 0x25, 0x01, 0x2e, 0x1d, 0x01, 0x94, 0xb1, 0x05, 0xbc, 0xb6, 0x7f,
+ 0x0f, 0xbb, 0x79, 0x50, 0x80, 0xb3, 0x0f, 0x2f, 0x0d, 0x2e, 0x1d, 0x01,
+ 0x7d, 0x5e, 0xb7, 0x09, 0x2d, 0x2e, 0x1d, 0x01, 0x7f, 0x5c, 0x77, 0x5e,
+ 0x9b, 0x43, 0x9b, 0x43, 0xdb, 0x43, 0x9b, 0x43, 0x1b, 0x42, 0xcb, 0x43,
+ 0x0b, 0x42, 0x8b, 0x43, 0x40, 0xb2, 0x05, 0x2f, 0x77, 0x50, 0x00, 0x2e,
+ 0x16, 0x40, 0x0b, 0x40, 0x76, 0x7f, 0x8b, 0x7f, 0xcb, 0x0a, 0x01, 0x2e,
+ 0x5c, 0x00, 0x75, 0x52, 0x7b, 0x5c, 0x98, 0x2e, 0xbe, 0xb2, 0x90, 0x6f,
+ 0x00, 0xb2, 0x0b, 0x2f, 0xf0, 0x6f, 0x00, 0xb2, 0x08, 0x2f, 0x77, 0x58,
+ 0x79, 0x50, 0x12, 0x41, 0x12, 0x42, 0x21, 0x30, 0x04, 0x41, 0x04, 0x42,
+ 0x23, 0x2e, 0x5e, 0xf0, 0xc0, 0x6f, 0x00, 0xb2, 0x26, 0x2f, 0x74, 0x6f,
+ 0x80, 0x6f, 0x7f, 0x54, 0x88, 0xbd, 0xc8, 0xb8, 0x4b, 0x0a, 0x94, 0x42,
+ 0x91, 0x42, 0x90, 0x42, 0x88, 0xba, 0x77, 0x52, 0xf3, 0x6f, 0x54, 0x42,
+ 0x85, 0x42, 0xc0, 0x90, 0x40, 0x42, 0x15, 0x2f, 0x79, 0x52, 0x00, 0x2e,
+ 0x52, 0x40, 0x41, 0x40, 0xa2, 0x04, 0x41, 0x06, 0x40, 0xaa, 0x04, 0x2f,
+ 0x40, 0x90, 0x0b, 0x2f, 0xb1, 0x6f, 0x4a, 0x0f, 0x08, 0x2f, 0xb2, 0x6f,
+ 0x80, 0xb2, 0x05, 0x2f, 0x79, 0x54, 0x21, 0x30, 0x94, 0x42, 0x80, 0x42,
+ 0x23, 0x2e, 0x5e, 0xf0, 0xd0, 0x6f, 0x00, 0xb2, 0x13, 0x2f, 0x01, 0x2e,
+ 0x5b, 0x00, 0x09, 0x2e, 0x81, 0x00, 0x04, 0x1a, 0x0d, 0x2f, 0x81, 0x50,
+ 0x29, 0x2e, 0x5b, 0x00, 0x24, 0x42, 0x44, 0x30, 0x02, 0x40, 0x02, 0x42,
+ 0x09, 0x80, 0x00, 0x2e, 0x04, 0x42, 0x03, 0x2d, 0x10, 0x30, 0x21, 0x2e,
+ 0x5f, 0x00, 0xeb, 0x6f, 0x70, 0x5f, 0xb8, 0x2e, 0x09, 0x86, 0x51, 0x54,
+ 0xe4, 0x40, 0xc3, 0x80, 0x94, 0x04, 0xc3, 0x40, 0x13, 0x05, 0x05, 0x40,
+ 0x25, 0x05, 0x8a, 0x17, 0x73, 0x30, 0x73, 0x09, 0x8c, 0x17, 0xf3, 0x08,
+ 0xe3, 0x00, 0x4c, 0x82, 0x15, 0x01, 0xb3, 0xb5, 0x53, 0x42, 0x8b, 0x16,
+ 0x43, 0xb6, 0x52, 0x42, 0x4c, 0x17, 0x54, 0x42, 0x55, 0x42, 0x53, 0x42,
+ 0x52, 0x42, 0x54, 0x42, 0x45, 0x42, 0x6d, 0x82, 0x83, 0x54, 0x52, 0x42,
+ 0x10, 0x50, 0x85, 0x54, 0x52, 0x42, 0xfb, 0x7f, 0x22, 0x30, 0x87, 0x56,
+ 0x43, 0x42, 0x44, 0x82, 0x0b, 0x30, 0x52, 0x42, 0x5b, 0x42, 0x7c, 0x84,
+ 0x4b, 0x42, 0x35, 0x82, 0x90, 0x80, 0x8b, 0x42, 0x0b, 0x42, 0x35, 0x80,
+ 0x04, 0x30, 0x0b, 0x42, 0x37, 0x80, 0x15, 0x30, 0x60, 0x25, 0x98, 0x2e,
+ 0xb1, 0xb2, 0x8b, 0x83, 0xfb, 0x6f, 0x65, 0x42, 0xc0, 0x2e, 0x44, 0x42,
+ 0xf0, 0x5f, 0x05, 0x80, 0x02, 0x30, 0x51, 0x82, 0x02, 0x42, 0x13, 0x30,
+ 0x41, 0x40, 0x4b, 0x08, 0x89, 0x54, 0x3e, 0x80, 0x51, 0x14, 0xc0, 0x2e,
+ 0x01, 0x42, 0x00, 0x2e, 0x40, 0x51, 0xd1, 0x7f, 0x12, 0x25, 0x02, 0x30,
+ 0x42, 0x43, 0x32, 0x30, 0x82, 0x43, 0xc6, 0x7f, 0xe5, 0x7f, 0xb4, 0x7f,
+ 0xa3, 0x7f, 0x90, 0x7f, 0x8b, 0x7f, 0x98, 0x2e, 0xc6, 0x01, 0xc0, 0x7e,
+ 0x00, 0xac, 0x01, 0x2f, 0x53, 0x50, 0xc0, 0x7e, 0x00, 0x2e, 0x90, 0x6f,
+ 0x09, 0x8a, 0xd1, 0x6f, 0x75, 0x7f, 0x4c, 0x82, 0x63, 0x41, 0x65, 0x7f,
+ 0x11, 0x7f, 0x00, 0x2e, 0x64, 0x41, 0x44, 0x85, 0x52, 0x7f, 0x45, 0x7f,
+ 0x00, 0x2e, 0xa6, 0x40, 0x80, 0x40, 0x32, 0x7f, 0x82, 0x8e, 0xc2, 0x6e,
+ 0x45, 0x41, 0xf0, 0x7f, 0x27, 0x7f, 0x02, 0x7f, 0x98, 0x2e, 0x38, 0xb1,
+ 0x23, 0x6f, 0xd1, 0x6f, 0xc2, 0x40, 0xf9, 0x86, 0x23, 0x7f, 0x80, 0xb2,
+ 0xe0, 0x7e, 0x0f, 0x2f, 0x32, 0x6f, 0x64, 0x6f, 0x82, 0x40, 0xf2, 0x7f,
+ 0x50, 0x82, 0x42, 0x6f, 0x50, 0x6f, 0x73, 0x6f, 0x85, 0x40, 0xc3, 0x40,
+ 0x04, 0x41, 0x06, 0x40, 0xe2, 0x6e, 0x98, 0x2e, 0x38, 0xb1, 0xe0, 0x7e,
+ 0xf3, 0x31, 0x10, 0x6f, 0x36, 0x80, 0xe1, 0x6e, 0x02, 0x40, 0x71, 0x7f,
+ 0x51, 0x04, 0x02, 0x30, 0x40, 0xa8, 0x91, 0x04, 0x4a, 0x22, 0x89, 0x16,
+ 0x93, 0x08, 0x4a, 0x00, 0x95, 0xb4, 0x09, 0x18, 0x8e, 0x16, 0x13, 0x30,
+ 0x93, 0x08, 0x21, 0x6f, 0x60, 0x7f, 0x4d, 0x86, 0x02, 0x80, 0xb2, 0x00,
+ 0x41, 0x40, 0x21, 0xb5, 0x50, 0x7f, 0x43, 0x7f, 0x98, 0x2e, 0xa7, 0xb1,
+ 0x40, 0x6f, 0x62, 0x6f, 0x55, 0x6f, 0x13, 0x40, 0x84, 0x40, 0x01, 0x40,
+ 0x45, 0x41, 0x42, 0xbe, 0x1d, 0x18, 0x4c, 0x04, 0x31, 0x0f, 0x04, 0x8a,
+ 0xc0, 0x6f, 0x11, 0x30, 0x02, 0x2f, 0x00, 0x2e, 0x03, 0x2c, 0x01, 0x42,
+ 0x23, 0x30, 0x03, 0x42, 0x00, 0x2e, 0xd6, 0x6f, 0x44, 0x41, 0x8a, 0x87,
+ 0x76, 0x8b, 0x00, 0xb3, 0x53, 0x7f, 0x15, 0x2f, 0x04, 0x6f, 0x8b, 0x5e,
+ 0x8b, 0x8d, 0xe7, 0x01, 0xc0, 0xa5, 0x84, 0x41, 0x01, 0x2f, 0x00, 0xa1,
+ 0x03, 0x2f, 0xc0, 0xad, 0x08, 0x2f, 0x00, 0xa5, 0x06, 0x2f, 0xc6, 0x40,
+ 0x81, 0x8d, 0x07, 0x30, 0x3c, 0x05, 0xd6, 0x42, 0x04, 0x2c, 0xc4, 0x42,
+ 0x02, 0x2c, 0x07, 0x30, 0x07, 0x30, 0x86, 0x86, 0x94, 0x6f, 0xd7, 0x7e,
+ 0x0e, 0x8d, 0x00, 0x40, 0x74, 0x89, 0xc7, 0x40, 0x02, 0xb2, 0xf9, 0x29,
+ 0x45, 0x41, 0x86, 0x41, 0xbe, 0x80, 0x21, 0x41, 0x75, 0x23, 0x82, 0x40,
+ 0xc7, 0x42, 0x45, 0x7f, 0x34, 0x7f, 0x20, 0x7f, 0x98, 0x2e, 0xa7, 0xb1,
+ 0x31, 0x6f, 0x60, 0x6f, 0x24, 0x6f, 0x22, 0x40, 0x05, 0x41, 0x43, 0x40,
+ 0x13, 0x01, 0x43, 0x86, 0xac, 0x0f, 0xd1, 0x6f, 0x30, 0x7f, 0x00, 0x2f,
+ 0x44, 0x42, 0x48, 0x8a, 0x41, 0x88, 0xe1, 0x40, 0x13, 0x7f, 0x04, 0x7f,
+ 0xf5, 0x7e, 0x98, 0x2e, 0xa7, 0xb1, 0x11, 0x6f, 0x60, 0x6f, 0x34, 0x6f,
+ 0x42, 0x40, 0x03, 0x40, 0x9a, 0x04, 0x04, 0x41, 0x43, 0x82, 0xa2, 0x0e,
+ 0x03, 0x6f, 0x00, 0x2f, 0xc2, 0x42, 0x00, 0x2e, 0x41, 0x40, 0x72, 0x6f,
+ 0x98, 0x2e, 0xa7, 0xb1, 0x25, 0x6f, 0x72, 0x6f, 0x53, 0x41, 0x93, 0x0e,
+ 0xd1, 0x6f, 0x46, 0x80, 0x1b, 0x30, 0x03, 0x30, 0x0c, 0x2f, 0x04, 0x40,
+ 0x00, 0x91, 0x42, 0x42, 0x08, 0x2f, 0xf6, 0x6e, 0x44, 0x6f, 0x86, 0x41,
+ 0xb4, 0x0e, 0x03, 0x2f, 0x02, 0x88, 0xdb, 0x7e, 0x03, 0x43, 0x0b, 0x42,
+ 0x46, 0x8d, 0x44, 0x41, 0x47, 0x80, 0x05, 0x6f, 0x94, 0x0f, 0x76, 0x7f,
+ 0x60, 0x7f, 0x02, 0x2f, 0x45, 0x89, 0x42, 0x43, 0x03, 0x43, 0x49, 0x88,
+ 0xa5, 0x6f, 0x40, 0x91, 0xa4, 0x7f, 0x15, 0x30, 0xe2, 0x6f, 0xd3, 0x6e,
+ 0x03, 0x2f, 0x04, 0x30, 0x83, 0x42, 0x80, 0x2e, 0x62, 0xb4, 0x04, 0x40,
+ 0x25, 0x29, 0x04, 0x42, 0x83, 0x42, 0x45, 0x82, 0x94, 0x6f, 0x04, 0x85,
+ 0xc0, 0xb2, 0x90, 0x2e, 0x4e, 0xb4, 0x15, 0x87, 0x3c, 0x8c, 0xc4, 0x40,
+ 0x46, 0x7f, 0xc2, 0x86, 0x07, 0x40, 0x86, 0x41, 0xf4, 0xbf, 0x00, 0xb3,
+ 0x0c, 0x2f, 0x90, 0x6f, 0x16, 0x80, 0x46, 0x25, 0x00, 0x40, 0x57, 0x25,
+ 0x04, 0x18, 0xae, 0x0e, 0x10, 0x30, 0x06, 0x30, 0x75, 0x25, 0x46, 0x23,
+ 0x60, 0x6f, 0x64, 0x25, 0xc4, 0x40, 0xfa, 0x86, 0x00, 0xb3, 0x33, 0x7f,
+ 0x09, 0x2f, 0x93, 0x6f, 0xd8, 0x88, 0x53, 0x6f, 0x04, 0x41, 0xc3, 0x40,
+ 0xdc, 0x0e, 0x13, 0x30, 0x04, 0x30, 0xdc, 0x22, 0xb3, 0x25, 0x40, 0xb3,
+ 0x02, 0x2f, 0x3b, 0x25, 0xc0, 0x90, 0x05, 0x2f, 0x91, 0x6f, 0xd0, 0x6f,
+ 0x98, 0x2e, 0xb1, 0xb2, 0x4d, 0x2c, 0x04, 0x30, 0x8d, 0x88, 0x43, 0x40,
+ 0x82, 0x40, 0x54, 0x7f, 0xda, 0x0f, 0x04, 0x30, 0x08, 0x2f, 0xc1, 0x80,
+ 0x40, 0x42, 0xc2, 0x0f, 0x02, 0x2f, 0x00, 0x30, 0xc0, 0x7e, 0x1b, 0x2d,
+ 0xc0, 0x7e, 0x19, 0x2d, 0xe1, 0xbc, 0x92, 0x6f, 0x4f, 0x04, 0x90, 0x84,
+ 0x40, 0xa8, 0x21, 0x05, 0x83, 0x40, 0x4c, 0x22, 0x4b, 0x0e, 0xb6, 0x84,
+ 0x21, 0x30, 0x02, 0x2f, 0x11, 0x30, 0x04, 0x2c, 0xc1, 0x7e, 0xe3, 0x6f,
+ 0xc1, 0x7e, 0xc1, 0x42, 0x00, 0x2e, 0x00, 0x40, 0x81, 0x40, 0x04, 0xbd,
+ 0x40, 0x6f, 0x98, 0x2e, 0xa7, 0xb1, 0x50, 0x6f, 0x11, 0x30, 0x02, 0x40,
+ 0x51, 0x08, 0xc3, 0x6e, 0x03, 0x80, 0x99, 0x15, 0x0b, 0x40, 0xb1, 0x6f,
+ 0xd0, 0x6f, 0xb6, 0x7f, 0x5b, 0x7f, 0x04, 0x30, 0x59, 0x54, 0x03, 0x30,
+ 0x11, 0x2c, 0x14, 0x80, 0x55, 0x6f, 0x06, 0x40, 0x75, 0x01, 0x58, 0xbb,
+ 0x6a, 0x09, 0x05, 0x42, 0xc1, 0x86, 0x47, 0x40, 0x51, 0x25, 0xbe, 0x01,
+ 0x56, 0x43, 0x00, 0x2e, 0x46, 0x41, 0xf4, 0x03, 0xb6, 0x6f, 0x47, 0x43,
+ 0x5e, 0x0e, 0xed, 0x2f, 0x31, 0x6f, 0x60, 0x6f, 0x42, 0x40, 0x15, 0x30,
+ 0x02, 0x82, 0x95, 0x08, 0x04, 0x42, 0x52, 0x42, 0x02, 0x2c, 0x44, 0x42,
+ 0x04, 0x30, 0x3e, 0x8e, 0x91, 0x6f, 0x4f, 0x8c, 0x02, 0x40, 0x83, 0x41,
+ 0xb5, 0x8d, 0x93, 0x0e, 0xd0, 0x6f, 0x01, 0x2f, 0x98, 0x2e, 0xb1, 0xb2,
+ 0x00, 0x2e, 0xc0, 0x41, 0x81, 0x41, 0xc1, 0x0f, 0xc0, 0x6f, 0x01, 0x2f,
+ 0x04, 0x42, 0x00, 0x2e, 0x70, 0x6f, 0x3c, 0x82, 0x00, 0x40, 0x41, 0x40,
+ 0x89, 0x16, 0x95, 0x08, 0x4a, 0x00, 0x04, 0xbc, 0x91, 0xb4, 0x01, 0x0e,
+ 0xe0, 0x6f, 0x07, 0x2f, 0xa1, 0x6f, 0x00, 0x2e, 0x41, 0x40, 0x40, 0xb2,
+ 0x02, 0x2f, 0xa1, 0x6f, 0x05, 0x42, 0x44, 0x42, 0x00, 0x2e, 0x8b, 0x6f,
+ 0xc0, 0x5e, 0xb8, 0x2e, 0x10, 0x50, 0x8d, 0x52, 0x4b, 0x50, 0xfb, 0x7f,
+ 0x98, 0x2e, 0x98, 0xb4, 0x4b, 0x52, 0x45, 0x82, 0x10, 0x30, 0x50, 0x42,
+ 0x60, 0x30, 0xfb, 0x6f, 0xc0, 0x2e, 0x40, 0x42, 0xf0, 0x5f, 0x10, 0x50,
+ 0x8f, 0x52, 0x4d, 0x50, 0xfb, 0x7f, 0x98, 0x2e, 0x98, 0xb4, 0x4d, 0x52,
+ 0x45, 0x82, 0x00, 0x30, 0x50, 0x42, 0x70, 0x30, 0xfb, 0x6f, 0xc0, 0x2e,
+ 0x40, 0x42, 0xf0, 0x5f, 0x12, 0x30, 0x12, 0x42, 0x02, 0x30, 0x12, 0x42,
+ 0x12, 0x42, 0x12, 0x42, 0x02, 0x42, 0x03, 0x80, 0x41, 0x84, 0x11, 0x42,
+ 0x02, 0x42, 0xb8, 0x2e, 0x48, 0x86, 0x90, 0x50, 0xc4, 0x40, 0x42, 0x84,
+ 0xf2, 0x7f, 0x5a, 0x25, 0x02, 0x41, 0xa2, 0xbf, 0x77, 0x85, 0x06, 0x41,
+ 0xff, 0xbb, 0x87, 0x42, 0x61, 0xbf, 0x07, 0x41, 0x6f, 0xbb, 0x86, 0x7f,
+ 0x7f, 0xbb, 0x96, 0x7f, 0xfe, 0x86, 0x86, 0x40, 0x80, 0x91, 0xc3, 0x40,
+ 0xd3, 0x7f, 0xe0, 0x7f, 0x13, 0x30, 0x05, 0x2f, 0x86, 0x6f, 0x80, 0x91,
+ 0x02, 0x2f, 0x96, 0x6f, 0x80, 0xb3, 0x60, 0x2f, 0x61, 0x25, 0x57, 0x40,
+ 0xc1, 0x91, 0xc1, 0x7f, 0x0f, 0x2f, 0x01, 0x30, 0x81, 0x43, 0x00, 0x2e,
+ 0xf2, 0x6f, 0x13, 0x40, 0x93, 0x42, 0x00, 0x2e, 0x13, 0x40, 0x93, 0x42,
+ 0x00, 0x2e, 0x00, 0x40, 0x80, 0x42, 0xbd, 0x80, 0xc0, 0x2e, 0x01, 0x42,
+ 0x70, 0x5f, 0x87, 0x83, 0x7a, 0x8d, 0x45, 0x40, 0x7b, 0x82, 0x45, 0x41,
+ 0x04, 0x41, 0xd5, 0xbf, 0x43, 0xbe, 0xc3, 0xba, 0xa5, 0x7f, 0x75, 0xba,
+ 0xb6, 0x7f, 0x05, 0x30, 0x97, 0x40, 0xc0, 0xb3, 0x09, 0x2f, 0x06, 0x40,
+ 0x47, 0x40, 0xb7, 0x05, 0x07, 0x30, 0x80, 0xa9, 0xfe, 0x05, 0xb7, 0x23,
+ 0x74, 0x0f, 0x5d, 0x23, 0xb6, 0x6f, 0x41, 0x82, 0x01, 0x80, 0x56, 0x0e,
+ 0xee, 0x2f, 0x40, 0x40, 0x28, 0x1a, 0xc4, 0x6f, 0xe0, 0x6f, 0xf2, 0x6f,
+ 0x02, 0x2f, 0x03, 0x30, 0x19, 0x2c, 0x03, 0x43, 0x05, 0x41, 0x6b, 0x29,
+ 0xa6, 0x6f, 0x05, 0x43, 0x6e, 0x0e, 0x11, 0x2f, 0xd4, 0x6f, 0x00, 0xb3,
+ 0x03, 0x2f, 0x3f, 0x89, 0xdc, 0x14, 0x27, 0x2e, 0x5e, 0xf0, 0x40, 0x25,
+ 0x32, 0x25, 0x15, 0x41, 0xd5, 0x42, 0x00, 0x2e, 0x15, 0x41, 0xd5, 0x42,
+ 0x00, 0x2e, 0x04, 0x41, 0xc4, 0x42, 0x00, 0x2e, 0x00, 0x2e, 0x41, 0x40,
+ 0x40, 0x90, 0x09, 0x2f, 0x11, 0x40, 0x91, 0x42, 0x00, 0x2e, 0x11, 0x40,
+ 0x91, 0x42, 0x00, 0x2e, 0x00, 0x40, 0x02, 0x2c, 0x80, 0x42, 0x43, 0x42,
+ 0x70, 0x5f, 0xb8, 0x2e, 0xb0, 0x50, 0x3a, 0x25, 0xf5, 0x86, 0x91, 0x58,
+ 0xc4, 0x42, 0x15, 0x30, 0x93, 0x58, 0x4d, 0x09, 0x81, 0x90, 0x64, 0x7f,
+ 0xf2, 0x7f, 0xeb, 0x7f, 0x02, 0x2f, 0x40, 0xb3, 0x90, 0x2e, 0x05, 0xb6,
+ 0x15, 0x0b, 0x00, 0xb3, 0x90, 0x2e, 0x05, 0xb6, 0x9a, 0x00, 0xe3, 0x30,
+ 0xcb, 0x08, 0x81, 0x40, 0x44, 0x84, 0xb1, 0xba, 0x46, 0x86, 0x49, 0x8e,
+ 0x97, 0x5c, 0xc2, 0x7f, 0x02, 0x84, 0x07, 0x25, 0xd3, 0x7f, 0x2b, 0x2e,
+ 0xa9, 0x00, 0x84, 0x40, 0xe3, 0x41, 0xe3, 0x04, 0xc4, 0x41, 0xc3, 0x43,
+ 0x2e, 0x18, 0x95, 0x5a, 0x8b, 0x40, 0x0b, 0x42, 0xb5, 0x00, 0x99, 0x5a,
+ 0xb2, 0x7f, 0x3a, 0x80, 0x95, 0x00, 0x05, 0x40, 0x41, 0x8b, 0x05, 0x42,
+ 0x03, 0x8a, 0xa2, 0x7f, 0x43, 0x84, 0x40, 0x41, 0x7b, 0x8b, 0x85, 0x7f,
+ 0x00, 0xb2, 0xdc, 0x05, 0x91, 0x7f, 0x04, 0x2f, 0xc3, 0x6f, 0x00, 0x2e,
+ 0xc4, 0x40, 0x01, 0x89, 0xc4, 0x42, 0x47, 0x86, 0x66, 0x41, 0x75, 0x7f,
+ 0x45, 0x88, 0x42, 0x82, 0x3e, 0x0f, 0x45, 0x41, 0x34, 0x2f, 0x46, 0x40,
+ 0x3e, 0x0e, 0x26, 0x2f, 0x85, 0x40, 0xc1, 0x33, 0xa9, 0x0e, 0x01, 0x30,
+ 0x02, 0x2f, 0xc3, 0x40, 0xc0, 0xb2, 0x1b, 0x2f, 0x82, 0x34, 0xaa, 0x0e,
+ 0x31, 0x2f, 0x01, 0x41, 0x7f, 0x82, 0x43, 0xa2, 0x02, 0x30, 0x02, 0x2f,
+ 0x00, 0x2e, 0x0c, 0x2c, 0x01, 0x30, 0x00, 0xb2, 0xd0, 0x6f, 0x11, 0x30,
+ 0x01, 0x2f, 0x02, 0x42, 0x02, 0x2d, 0x01, 0x42, 0x01, 0x30, 0xc0, 0x6f,
+ 0x00, 0x2e, 0x02, 0x42, 0x3e, 0x81, 0x04, 0x86, 0x02, 0x42, 0x02, 0x43,
+ 0xc2, 0x42, 0x19, 0x2d, 0xc0, 0x33, 0x80, 0x42, 0x16, 0x2d, 0xa0, 0x6f,
+ 0x28, 0x04, 0x38, 0x1e, 0x40, 0x42, 0x11, 0x30, 0x90, 0x6f, 0x22, 0x30,
+ 0x98, 0x2e, 0x08, 0xb6, 0x0c, 0x2c, 0x01, 0x30, 0xa1, 0x6f, 0xa9, 0x00,
+ 0x90, 0x6f, 0x01, 0x82, 0xba, 0x1c, 0x42, 0x42, 0x21, 0x30, 0x12, 0x30,
+ 0x98, 0x2e, 0x08, 0xb6, 0x01, 0x30, 0x72, 0x6f, 0xd4, 0xb1, 0xf5, 0xbd,
+ 0x6b, 0xba, 0x9f, 0x5a, 0x80, 0x40, 0x05, 0x18, 0xf5, 0xbe, 0xe3, 0x0a,
+ 0xeb, 0xbb, 0x3d, 0x0b, 0x80, 0x6f, 0xe3, 0x00, 0x04, 0x40, 0x63, 0x05,
+ 0xa1, 0x58, 0x2c, 0x18, 0xf5, 0xbe, 0x83, 0x42, 0xeb, 0xbb, 0xfd, 0x0b,
+ 0xb2, 0x6f, 0x5a, 0x01, 0xdf, 0x01, 0x7d, 0x1f, 0x15, 0x42, 0x9a, 0x04,
+ 0x05, 0x40, 0x5d, 0x05, 0x2c, 0x18, 0x75, 0xbe, 0xeb, 0xba, 0x2c, 0x0b,
+ 0xdc, 0x04, 0x9a, 0x1c, 0x02, 0x42, 0x04, 0x80, 0x00, 0x2e, 0x00, 0x40,
+ 0x00, 0xb2, 0x10, 0x2f, 0xc2, 0x6f, 0xc0, 0x33, 0x82, 0x40, 0x90, 0x0e,
+ 0x0b, 0x2f, 0xd1, 0x6f, 0x7e, 0x88, 0x03, 0x81, 0x3c, 0x84, 0x0b, 0x30,
+ 0x82, 0x86, 0x4b, 0x42, 0x0b, 0x42, 0x0b, 0x43, 0x8b, 0x42, 0xcb, 0x42,
+ 0x21, 0x30, 0x42, 0xb2, 0x02, 0x30, 0x9d, 0x50, 0x02, 0x22, 0x41, 0xb2,
+ 0x9b, 0x52, 0x08, 0x22, 0xf1, 0x6f, 0x40, 0x90, 0x11, 0x30, 0x06, 0x2f,
+ 0x22, 0x30, 0x02, 0x08, 0x00, 0xb2, 0x08, 0x2f, 0x23, 0x2e, 0x5e, 0xf0,
+ 0x06, 0x2d, 0x01, 0x08, 0x00, 0xb2, 0x02, 0x2f, 0x00, 0x31, 0x21, 0x2e,
+ 0x5e, 0xf0, 0xeb, 0x6f, 0x50, 0x5f, 0xb8, 0x2e, 0x07, 0x86, 0xfc, 0x88,
+ 0xc6, 0x40, 0x05, 0x41, 0x31, 0x1a, 0x12, 0x2f, 0x80, 0x91, 0x22, 0x2f,
+ 0xc1, 0x33, 0x29, 0x0f, 0x0a, 0x2f, 0x06, 0x80, 0x00, 0x2e, 0x00, 0x40,
+ 0x00, 0xb2, 0x01, 0x2f, 0x44, 0xa9, 0x03, 0x2f, 0x00, 0x30, 0xc0, 0x42,
+ 0x00, 0x43, 0xb8, 0x2e, 0xc2, 0x42, 0x01, 0x43, 0xb8, 0x2e, 0xc1, 0x33,
+ 0xa9, 0x0e, 0x0e, 0x2f, 0x43, 0x3c, 0xeb, 0x00, 0xcc, 0xa8, 0x0a, 0x2f,
+ 0x05, 0x86, 0xc2, 0x80, 0xc3, 0x40, 0x02, 0x42, 0x3c, 0x84, 0xc1, 0x80,
+ 0x81, 0x42, 0x82, 0x84, 0xc0, 0x2e, 0x80, 0x42, 0x00, 0x2e, 0xb8, 0x2e,
+ 0x05, 0x2e, 0x20, 0x01, 0x11, 0x30, 0x20, 0x50, 0x91, 0x08, 0xf0, 0x7f,
+ 0x80, 0xb2, 0xeb, 0x7f, 0x13, 0x2f, 0x01, 0x2e, 0x74, 0x00, 0x01, 0x90,
+ 0x02, 0x30, 0xa3, 0x50, 0x03, 0x2f, 0x25, 0x2e, 0x74, 0x00, 0x98, 0x2e,
+ 0xad, 0xb7, 0xf2, 0x6f, 0xa3, 0x52, 0x98, 0x2e, 0x57, 0xb6, 0x00, 0xb2,
+ 0x06, 0x2f, 0x80, 0x30, 0x21, 0x2e, 0x5e, 0xf0, 0x03, 0x2d, 0x10, 0x30,
+ 0x21, 0x2e, 0x74, 0x00, 0xeb, 0x6f, 0xe0, 0x5f, 0xb8, 0x2e, 0x30, 0x51,
+ 0x42, 0x8a, 0xe1, 0x7f, 0x83, 0x88, 0xdb, 0x7f, 0xc5, 0x7f, 0x1a, 0x25,
+ 0x05, 0x25, 0x93, 0x40, 0x06, 0x40, 0xb3, 0x01, 0x16, 0x42, 0xcb, 0x16,
+ 0x06, 0x40, 0xf3, 0x02, 0x13, 0x42, 0x54, 0x0e, 0xf5, 0x2f, 0x04, 0x40,
+ 0x12, 0x30, 0xa2, 0x28, 0x02, 0x42, 0x88, 0xa0, 0x00, 0x30, 0x90, 0x2e,
+ 0xa9, 0xb7, 0x6d, 0x84, 0x73, 0x88, 0x92, 0x7f, 0x70, 0x7f, 0x84, 0x7f,
+ 0xa2, 0x7f, 0x70, 0x86, 0xb5, 0x7f, 0x63, 0x7f, 0x75, 0x30, 0xa5, 0x52,
+ 0xa7, 0x54, 0xbd, 0x50, 0xaf, 0x58, 0xb7, 0x6f, 0xf4, 0x7f, 0x51, 0x7f,
+ 0x00, 0x2e, 0xd6, 0x41, 0xd4, 0x41, 0xb7, 0x7f, 0xcc, 0x17, 0x7d, 0x09,
+ 0x75, 0x01, 0x06, 0x30, 0x26, 0x03, 0x4d, 0xbe, 0xd3, 0xba, 0x6c, 0x0b,
+ 0x28, 0x0e, 0x05, 0x22, 0x2a, 0x0f, 0x90, 0x22, 0xd2, 0x42, 0x43, 0x7f,
+ 0x32, 0x7f, 0x00, 0x2e, 0xa9, 0x5a, 0xab, 0x58, 0xad, 0x5c, 0xa9, 0x56,
+ 0x98, 0x2e, 0x38, 0xb1, 0x91, 0x6f, 0x32, 0x6f, 0x50, 0x42, 0x91, 0x7f,
+ 0xb3, 0x30, 0x10, 0x25, 0x98, 0x2e, 0xdb, 0xb7, 0x71, 0x6f, 0x88, 0x28,
+ 0x43, 0x6f, 0x80, 0x6f, 0x72, 0x7f, 0x58, 0x0e, 0x51, 0x6f, 0x44, 0x82,
+ 0xa7, 0x54, 0xbd, 0x50, 0x75, 0x30, 0xaf, 0x58, 0xcd, 0x2f, 0xb1, 0x6f,
+ 0x46, 0x84, 0xe1, 0x6f, 0x4e, 0x80, 0x81, 0x40, 0xb2, 0x7f, 0x90, 0x7f,
+ 0x12, 0x30, 0x98, 0x2e, 0xcc, 0xb7, 0xb1, 0x6f, 0x7c, 0x8a, 0xa2, 0x6f,
+ 0xb5, 0x7f, 0x40, 0x42, 0x98, 0x2e, 0xf4, 0x01, 0x95, 0xbc, 0x0b, 0xb9,
+ 0x51, 0x0a, 0x62, 0x6f, 0xa1, 0x7f, 0x98, 0x2e, 0xf4, 0x01, 0x95, 0xbc,
+ 0x0b, 0xb9, 0x11, 0x0a, 0xa1, 0x6f, 0x49, 0x17, 0x48, 0x18, 0x88, 0x16,
+ 0xe8, 0x18, 0xd1, 0x18, 0x27, 0x25, 0x16, 0x25, 0x80, 0x7f, 0x98, 0x2e,
+ 0xbe, 0x00, 0xb5, 0x6f, 0xe1, 0x6f, 0x43, 0x41, 0x4b, 0x84, 0x4c, 0x8c,
+ 0xb0, 0x7f, 0x62, 0x7f, 0x4a, 0x88, 0x7e, 0x8b, 0xc0, 0x90, 0x56, 0x7f,
+ 0x13, 0x2f, 0x45, 0x7f, 0x34, 0x7f, 0xb3, 0x30, 0xb1, 0x52, 0xb2, 0x6f,
+ 0x98, 0x2e, 0xdb, 0xb7, 0x71, 0x6f, 0x88, 0x0e, 0x34, 0x6f, 0x45, 0x6f,
+ 0xe1, 0x6f, 0x06, 0x2f, 0x34, 0x25, 0x1b, 0x30, 0x10, 0x6f, 0x22, 0x6f,
+ 0xdb, 0x42, 0xd0, 0x42, 0xc2, 0x42, 0x02, 0x30, 0x00, 0x6f, 0x00, 0xa8,
+ 0x90, 0x05, 0x13, 0x6f, 0x86, 0x23, 0xc0, 0xa8, 0xd3, 0x05, 0xdf, 0x23,
+ 0xb7, 0x05, 0xb3, 0x5e, 0x37, 0x0f, 0x4d, 0x8c, 0x07, 0x30, 0x19, 0x2f,
+ 0x44, 0x7f, 0x00, 0x2e, 0x24, 0x6f, 0xb3, 0x5e, 0xa7, 0x0e, 0x44, 0x6f,
+ 0x07, 0x30, 0x11, 0x2f, 0xc7, 0x5e, 0xdf, 0x00, 0xc1, 0x5e, 0x5f, 0x0e,
+ 0x02, 0x2f, 0x00, 0x2e, 0x0b, 0x2c, 0x07, 0x30, 0xc9, 0x56, 0x03, 0x00,
+ 0xc3, 0x56, 0x43, 0x0e, 0x02, 0x2f, 0x00, 0x2e, 0x03, 0x2c, 0x07, 0x30,
+ 0x82, 0x43, 0x17, 0x30, 0x41, 0x86, 0xc0, 0x91, 0x0e, 0x2f, 0xc0, 0x40,
+ 0x01, 0x90, 0x09, 0x2f, 0x80, 0x41, 0x14, 0x30, 0x04, 0x28, 0x80, 0x43,
+ 0x06, 0xa0, 0x03, 0x2f, 0xc8, 0x80, 0xbb, 0x58, 0xc2, 0x42, 0x04, 0x42,
+ 0x66, 0x2c, 0x00, 0x30, 0x90, 0x6f, 0x00, 0x2e, 0x00, 0x40, 0x00, 0xa8,
+ 0x00, 0x30, 0x5e, 0x2f, 0x00, 0x41, 0x00, 0xb2, 0x00, 0x30, 0x5a, 0x2f,
+ 0x49, 0x82, 0xb2, 0x6f, 0x43, 0x7f, 0xb5, 0x7f, 0x94, 0x7f, 0xb3, 0x30,
+ 0x41, 0x40, 0x98, 0x2e, 0xdb, 0xb7, 0x71, 0x6f, 0x88, 0x0f, 0xb5, 0x6f,
+ 0xe1, 0x6f, 0x02, 0x30, 0x00, 0x30, 0x4a, 0x2f, 0x80, 0x6f, 0xc5, 0x58,
+ 0x04, 0x00, 0xbf, 0x58, 0x44, 0x0e, 0x02, 0x2f, 0x00, 0x2e, 0x43, 0x2c,
+ 0x00, 0x30, 0xa0, 0x6f, 0xb5, 0x58, 0x84, 0x0e, 0x00, 0x30, 0x3c, 0x2f,
+ 0xb7, 0x54, 0x21, 0x6f, 0xb5, 0x7f, 0x98, 0x2e, 0xcc, 0xb7, 0x10, 0x25,
+ 0xb3, 0x30, 0x21, 0x25, 0x98, 0x2e, 0xdb, 0xb7, 0x02, 0x6f, 0xa0, 0x7f,
+ 0xb3, 0x30, 0x12, 0x25, 0x98, 0x2e, 0xdb, 0xb7, 0x12, 0x6f, 0x80, 0x7f,
+ 0xb3, 0x30, 0x12, 0x25, 0x98, 0x2e, 0xdb, 0xb7, 0x81, 0x6f, 0x88, 0x28,
+ 0x87, 0x52, 0x98, 0x2e, 0xcc, 0xb7, 0xa1, 0x6f, 0x88, 0x0f, 0xb5, 0x6f,
+ 0xe1, 0x6f, 0x02, 0x30, 0x00, 0x30, 0x1a, 0x2f, 0x44, 0x6f, 0x00, 0x2e,
+ 0x00, 0x41, 0x00, 0xb2, 0x0f, 0x2f, 0x64, 0x6f, 0x10, 0x6f, 0x04, 0x41,
+ 0x84, 0x0e, 0x00, 0x30, 0x0f, 0x2f, 0x54, 0x6f, 0x20, 0x6f, 0x04, 0x41,
+ 0x84, 0x0f, 0x00, 0x30, 0x09, 0x2f, 0x94, 0x6f, 0x10, 0x30, 0x07, 0x2c,
+ 0x02, 0x43, 0x08, 0x87, 0xb9, 0x50, 0xd0, 0x42, 0x10, 0x30, 0x00, 0x43,
+ 0xc2, 0x42, 0x0b, 0x30, 0x4b, 0x43, 0x7a, 0x8b, 0xc4, 0x6f, 0x06, 0x89,
+ 0x52, 0x43, 0x52, 0x43, 0x6c, 0x0e, 0xfb, 0x2f, 0x78, 0x85, 0x00, 0x2e,
+ 0x82, 0x40, 0x02, 0x1a, 0x02, 0x2f, 0x00, 0x2e, 0x02, 0x2c, 0x40, 0x42,
+ 0x00, 0x30, 0x00, 0x2e, 0xdb, 0x6f, 0xd0, 0x5e, 0xb8, 0x2e, 0x08, 0x82,
+ 0x02, 0x30, 0x12, 0x42, 0x08, 0x86, 0xc2, 0x88, 0x87, 0x5a, 0x12, 0x43,
+ 0x05, 0x43, 0x02, 0x8b, 0x7c, 0x8d, 0x42, 0x43, 0x14, 0x30, 0xbe, 0x8b,
+ 0x04, 0x42, 0x45, 0x81, 0x42, 0x43, 0x02, 0x42, 0x35, 0x80, 0xb9, 0x5e,
+ 0xa5, 0x5a, 0xc7, 0x42, 0x84, 0x43, 0x52, 0x43, 0x12, 0x42, 0x52, 0x43,
+ 0x12, 0x42, 0x52, 0x43, 0x52, 0x43, 0x41, 0x0e, 0xf7, 0x2f, 0xb8, 0x2e,
+ 0x0a, 0x0c, 0x55, 0x56, 0x03, 0x09, 0x0a, 0x04, 0x00, 0xb3, 0x07, 0x2f,
+ 0x88, 0x0c, 0x93, 0x08, 0x80, 0xb2, 0x03, 0x2f, 0x53, 0x50, 0xc0, 0x2e,
+ 0x40, 0xac, 0x03, 0x22, 0xb8, 0x2e, 0xff, 0x88, 0x10, 0x30, 0x4a, 0x0d,
+ 0x0a, 0x18, 0x04, 0x15, 0x4c, 0x16, 0x5f, 0xb9, 0x79, 0x08, 0x53, 0x5a,
+ 0x95, 0x00, 0x34, 0x09, 0x40, 0x90, 0x02, 0x2f, 0x00, 0x91, 0x00, 0x2f,
+ 0x00, 0x30, 0xd8, 0x00, 0xc0, 0xb2, 0x0b, 0x2f, 0xd0, 0xa0, 0x03, 0x2f,
+ 0xf0, 0x86, 0xbb, 0x11, 0x07, 0x2c, 0xce, 0x17, 0x01, 0x31, 0x4b, 0x04,
+ 0x79, 0x14, 0x33, 0x12, 0xfb, 0x11, 0x81, 0x0b, 0xce, 0x16, 0xc0, 0x2e,
+ 0x7b, 0x1a, 0x16, 0x22, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00,
+ 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00, 0x80, 0x2e, 0x18, 0x00
+};
+
const uint8_t bma423_config_file[] = {
0x80, 0x2e, 0xfe, 0x00, 0x80, 0x2e, 0xf1, 0x01, 0xc8, 0x2e, 0x00, 0x2e, 0x80, 0x2e, 0xfc, 0x00, 0x80, 0x2e, 0xfb,
0x00, 0x80, 0x2e, 0xff, 0x00, 0x80, 0x2e, 0xfd, 0x00, 0x80, 0x2e, 0x42, 0xb0, 0x50, 0x39, 0x21, 0x2e, 0xb0, 0xf0,
@@ -450,7 +965,7 @@ int8_t bma423_init(struct bma4_dev *dev)
rslt = bma4_init(dev);
if (rslt == BMA4_OK)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
/* Resolution of BMA423 sensor is 12 bit */
dev->resolution = 12;
@@ -478,7 +993,7 @@ int8_t bma423_write_config_file(struct bma4_dev *dev)
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
/* Configuration stream read/write length boundary
* check
@@ -492,7 +1007,10 @@ int8_t bma423_write_config_file(struct bma4_dev *dev)
}
/*Assign stream data */
- dev->config_file_ptr = bma423_config_file;
+ if(dev->chip_id == BMA423_CHIP_ID)
+ dev->config_file_ptr = bma423_config_file;
+ else if(dev->chip_id == BMA425_CHIP_ID)
+ dev->config_file_ptr = bma425_config_file;
rslt = bma4_write_config_file(dev);
}
else
@@ -526,7 +1044,7 @@ int8_t bma423_get_config_id(uint16_t *config_id, struct bma4_dev *dev)
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
if (rslt == BMA4_OK)
@@ -559,7 +1077,7 @@ int8_t bma423_map_interrupt(uint8_t int_line, uint16_t int_map, uint8_t enable,
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
if (int_line <= 1)
{
@@ -593,7 +1111,7 @@ int8_t bma423_read_int_status(uint16_t *int_status, struct bma4_dev *dev)
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
/* Read the interrupt status */
rslt = bma4_read_int_status(int_status, dev);
@@ -622,7 +1140,7 @@ int8_t bma423_feature_enable(uint8_t feature, uint8_t enable, struct bma4_dev *d
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
/* Read feature configuration data */
rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, len, dev);
@@ -669,7 +1187,7 @@ int8_t bma423_set_remap_axes(const struct bma423_axes_remap *remap_data, struct
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
if (rslt == BMA4_OK)
@@ -708,7 +1226,7 @@ int8_t bma423_get_remap_axes(struct bma423_axes_remap *remap_data, struct bma4_d
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
if (rslt == BMA4_OK)
@@ -997,7 +1515,7 @@ int8_t bma423_step_detector_enable(uint8_t enable, struct bma4_dev *dev)
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
if (rslt == BMA4_OK)
@@ -1034,7 +1552,7 @@ int8_t bma423_step_counter_set_watermark(uint16_t step_counter_wm, struct bma4_d
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
if (rslt == BMA4_OK)
@@ -1088,7 +1606,7 @@ int8_t bma423_step_counter_get_watermark(uint16_t *step_counter_wm, struct bma4_
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
if (rslt == BMA4_OK)
@@ -1125,7 +1643,7 @@ int8_t bma423_reset_step_counter(struct bma4_dev *dev)
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
if (rslt == BMA4_OK)
@@ -1162,7 +1680,7 @@ int8_t bma423_step_counter_output(uint32_t *step_count, struct bma4_dev *dev)
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
/* Reads the step counter output data from the
* gpio register
@@ -1200,7 +1718,7 @@ int8_t bma423_activity_output(uint8_t *activity, struct bma4_dev *dev)
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
/* Reads the activity output from the gpio register */
rslt = bma4_read_regs(BMA4_ACTIVITY_OUT_ADDR, &data, 1, dev);
@@ -1234,7 +1752,7 @@ int8_t bma423_stepcounter_get_parameter(struct bma423_stepcounter_settings *sett
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
if (rslt == BMA4_OK)
@@ -1269,7 +1787,7 @@ int8_t bma423_stepcounter_set_parameter(const struct bma423_stepcounter_settings
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
if (rslt == BMA4_OK)
@@ -1306,7 +1824,7 @@ int8_t bma423_single_tap_set_sensitivity(uint8_t sensitivity, struct bma4_dev *d
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
if (rslt == BMA4_OK)
@@ -1341,7 +1859,7 @@ int8_t bma423_double_tap_set_sensitivity(uint8_t sensitivity, struct bma4_dev *d
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
if (rslt == BMA4_OK)
@@ -1376,7 +1894,7 @@ int8_t bma423_single_tap_get_sensitivity(uint8_t *sensitivity, struct bma4_dev *
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
if (rslt == BMA4_OK)
@@ -1409,7 +1927,7 @@ int8_t bma423_double_tap_get_sensitivity(uint8_t *sensitivity, struct bma4_dev *
if (dev != NULL)
{
- if (dev->chip_id == BMA423_CHIP_ID)
+ if (dev->chip_id == BMA423_CHIP_ID || dev->chip_id == BMA425_CHIP_ID)
{
rslt = bma4_read_regs(BMA4_FEATURE_CONFIG_ADDR, feature_config, BMA423_FEATURE_SIZE, dev);
if (rslt == BMA4_OK)
diff --git a/src/drivers/Bma421_C/bma423.h b/src/drivers/Bma421_C/bma423.h
index 96e5d8e3..b58e0d21 100644
--- a/src/drivers/Bma421_C/bma423.h
+++ b/src/drivers/Bma421_C/bma423.h
@@ -52,6 +52,7 @@ extern "C" {
/**\name Chip ID of BMA423 sensor */
#define BMA423_CHIP_ID UINT8_C(0x11)
+#define BMA425_CHIP_ID UINT8_C(0x13)
/**\ Configuration ID start position of BMA423 sensor */
#define BMA423_CONFIG_ID_START_ADDR UINT8_C(66)
diff --git a/src/drivers/SpiMaster.cpp b/src/drivers/SpiMaster.cpp
index 34fcc08a..c45e1294 100644
--- a/src/drivers/SpiMaster.cpp
+++ b/src/drivers/SpiMaster.cpp
@@ -7,11 +7,14 @@
using namespace Pinetime::Drivers;
SpiMaster::SpiMaster(const SpiMaster::SpiModule spi, const SpiMaster::Parameters& params) : spi {spi}, params {params} {
- mutex = xSemaphoreCreateBinary();
- ASSERT(mutex != NULL);
}
bool SpiMaster::Init() {
+ if(mutex == nullptr) {
+ mutex = xSemaphoreCreateBinary();
+ ASSERT(mutex != nullptr);
+ }
+
/* Configure GPIO pins used for pselsck, pselmosi, pselmiso and pselss for SPI0 */
nrf_gpio_pin_set(params.pinSCK);
nrf_gpio_cfg_output(params.pinSCK);
@@ -53,6 +56,7 @@ bool SpiMaster::Init() {
break;
case BitOrder::Lsb_Msb:
regConfig = 1;
+ break;
default:
return false;
}
@@ -132,17 +136,17 @@ void SpiMaster::OnEndEvent() {
spiBaseAddress->TASKS_START = 1;
} else {
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;
if (taskToNotify != nullptr) {
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
vTaskNotifyGiveFromISR(taskToNotify, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
nrf_gpio_pin_set(this->pinCsn);
currentBufferAddr = 0;
- BaseType_t xHigherPriorityTaskWoken = pdFALSE;
- xSemaphoreGiveFromISR(mutex, &xHigherPriorityTaskWoken);
- portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+ BaseType_t xHigherPriorityTaskWoken2 = pdFALSE;
+ xSemaphoreGiveFromISR(mutex, &xHigherPriorityTaskWoken2);
+ portYIELD_FROM_ISR(xHigherPriorityTaskWoken | xHigherPriorityTaskWoken2);
}
}
diff --git a/src/drivers/SpiMaster.h b/src/drivers/SpiMaster.h
index dfc195b7..5ea624f2 100644
--- a/src/drivers/SpiMaster.h
+++ b/src/drivers/SpiMaster.h
@@ -10,7 +10,6 @@ namespace Pinetime {
namespace Drivers {
class SpiMaster {
public:
- ;
enum class SpiModule : uint8_t { SPI0, SPI1 };
enum class BitOrder : uint8_t { Msb_Lsb, Lsb_Msb };
enum class Modes : uint8_t { Mode0, Mode1, Mode2, Mode3 };
@@ -60,7 +59,7 @@ namespace Pinetime {
volatile uint32_t currentBufferAddr = 0;
volatile size_t currentBufferSize = 0;
volatile TaskHandle_t taskToNotify;
- SemaphoreHandle_t mutex;
+ SemaphoreHandle_t mutex = nullptr;
};
}
}
diff --git a/src/drivers/St7789.cpp b/src/drivers/St7789.cpp
index 39218e77..0f1dc02e 100644
--- a/src/drivers/St7789.cpp
+++ b/src/drivers/St7789.cpp
@@ -140,8 +140,9 @@ void St7789::Uninit() {
}
void St7789::DrawPixel(uint16_t x, uint16_t y, uint32_t color) {
- if ((x < 0) || (x >= Width) || (y < 0) || (y >= Height))
+ if (x >= Width || y >= Height) {
return;
+ }
SetAddrWindow(x, y, x + 1, y + 1);
diff --git a/src/drivers/TwiMaster.cpp b/src/drivers/TwiMaster.cpp
index 7b6582dd..fc9edf81 100644
--- a/src/drivers/TwiMaster.cpp
+++ b/src/drivers/TwiMaster.cpp
@@ -9,10 +9,12 @@ using namespace Pinetime::Drivers;
// TODO use DMA/IRQ
TwiMaster::TwiMaster(const Modules module, const Parameters& params) : module {module}, params {params} {
- mutex = xSemaphoreCreateBinary();
}
void TwiMaster::Init() {
+ if(mutex == nullptr)
+ mutex = xSemaphoreCreateBinary();
+
NRF_GPIO->PIN_CNF[params.pinScl] =
((uint32_t) GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) | ((uint32_t) GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
((uint32_t) GPIO_PIN_CNF_PULL_Pullup << GPIO_PIN_CNF_PULL_Pos) | ((uint32_t) GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) |
diff --git a/src/drivers/TwiMaster.h b/src/drivers/TwiMaster.h
index 1c0648a2..6175b99b 100644
--- a/src/drivers/TwiMaster.h
+++ b/src/drivers/TwiMaster.h
@@ -31,7 +31,7 @@ namespace Pinetime {
ErrorCodes Write(uint8_t deviceAddress, const uint8_t* data, size_t size, bool stop);
void FixHwFreezed();
NRF_TWIM_Type* twiBaseAddress;
- SemaphoreHandle_t mutex;
+ SemaphoreHandle_t mutex = nullptr;
const Modules module;
const Parameters params;
static constexpr uint8_t maxDataSize {16};
diff --git a/src/heartratetask/HeartRateTask.cpp b/src/heartratetask/HeartRateTask.cpp
index 36c8cc18..fddc05d7 100644
--- a/src/heartratetask/HeartRateTask.cpp
+++ b/src/heartratetask/HeartRateTask.cpp
@@ -6,12 +6,13 @@
using namespace Pinetime::Applications;
HeartRateTask::HeartRateTask(Drivers::Hrs3300& heartRateSensor, Controllers::HeartRateController& controller)
- : heartRateSensor {heartRateSensor}, controller {controller}, ppg {static_cast(heartRateSensor.ReadHrs())} {
- messageQueue = xQueueCreate(10, 1);
- controller.SetHeartRateTask(this);
+ : heartRateSensor {heartRateSensor}, controller {controller}, ppg{} {
}
void HeartRateTask::Start() {
+ messageQueue = xQueueCreate(10, 1);
+ controller.SetHeartRateTask(this);
+
if (pdPASS != xTaskCreate(HeartRateTask::Process, "Heartrate", 500, this, 0, &taskHandle))
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}
diff --git a/src/libs/littlefs b/src/libs/littlefs
new file mode 160000
index 00000000..ead50807
--- /dev/null
+++ b/src/libs/littlefs
@@ -0,0 +1 @@
+Subproject commit ead50807f1ca3fdf2da00b77a0ce02651ded2d13
diff --git a/src/libs/lv_conf.h b/src/libs/lv_conf.h
index 761baba2..65263daa 100644
--- a/src/libs/lv_conf.h
+++ b/src/libs/lv_conf.h
@@ -204,7 +204,7 @@ e.g. "stm32f769xx.h" or "stm32f429xx.h" */
/* 1: Enable file system (might be required for images */
// TODO: Enable FS
-#define LV_USE_FILESYSTEM 0
+#define LV_USE_FILESYSTEM 1
#if LV_USE_FILESYSTEM
/*Declare the type of the user data of file system drivers (can be e.g. `void *`, `int`, `struct`)*/
typedef void * lv_fs_drv_user_data_t;
@@ -236,7 +236,7 @@ typedef void * lv_fs_drv_user_data_t;
* With complex image decoders (e.g. PNG or JPG) caching can save the continuous open/decode of images.
* However the opened images might consume additional RAM.
* LV_IMG_CACHE_DEF_SIZE must be >= 1 */
-#define LV_IMG_CACHE_DEF_SIZE 1
+#define LV_IMG_CACHE_DEF_SIZE 6
/*Declare the type of the user data of image decoder (can be e.g. `void *`, `int`, `struct`)*/
typedef void* lv_img_decoder_user_data_t;
@@ -293,10 +293,10 @@ typedef void* lv_img_decoder_user_data_t;
/* 1: use a custom tick source.
* It removes the need to manually update the tick with `lv_tick_inc`) */
-#define LV_TICK_CUSTOM 0
+#define LV_TICK_CUSTOM 1
#if LV_TICK_CUSTOM == 1
-#define LV_TICK_CUSTOM_INCLUDE "Arduino.h" /*Header for the system time function*/
-#define LV_TICK_CUSTOM_SYS_TIME_EXPR (millis()) /*Expression evaluating to current system time in ms*/
+#define LV_TICK_CUSTOM_INCLUDE "FreeRTOS.h" /*Header for the system time function*/
+#define LV_TICK_CUSTOM_SYS_TIME_EXPR (xTaskGetTickCount()) /*Expression evaluating to current system time in ms*/
#endif /*LV_TICK_CUSTOM*/
typedef void* lv_disp_drv_user_data_t; /*Type of user data in the display driver*/
@@ -417,6 +417,7 @@ typedef void* lv_indev_drv_user_data_t; /*Type of user data in the in
LV_FONT_DECLARE(jetbrains_mono_extrabold_compressed) \
LV_FONT_DECLARE(jetbrains_mono_42) \
LV_FONT_DECLARE(jetbrains_mono_76) \
+ LV_FONT_DECLARE(open_sans_light) \
LV_FONT_DECLARE(lv_font_sys_48)
/* Enable it if you have fonts with a lot of characters.
@@ -758,4 +759,4 @@ typedef void* lv_obj_user_data_t;
/*--END OF LV_CONF_H--*/
-#endif /*LV_CONF_H*/
\ No newline at end of file
+#endif /*LV_CONF_H*/
diff --git a/src/main.cpp b/src/main.cpp
index 61194b95..ffbba5e7 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -28,12 +28,14 @@
#include
#include
+#include "BootloaderVersion.h"
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
#include "components/ble/NotificationManager.h"
#include "components/motor/MotorController.h"
#include "components/datetime/DateTimeController.h"
-#include "components/settings/Settings.h"
+#include "components/heartrate/HeartRateController.h"
+#include "components/fs/FS.h"
#include "drivers/Spi.h"
#include "drivers/SpiMaster.h"
#include "drivers/SpiNorFlash.h"
@@ -50,8 +52,6 @@ Pinetime::Logging::NrfLogger logger;
Pinetime::Logging::DummyLogger logger;
#endif
-#include
-
static constexpr uint8_t pinSpiSck = 2;
static constexpr uint8_t pinSpiMosi = 3;
static constexpr uint8_t pinSpiMiso = 4;
@@ -108,15 +108,61 @@ void ble_manager_set_ble_connection_callback(void (*connection)());
void ble_manager_set_ble_disconnection_callback(void (*disconnection)());
static constexpr uint8_t pinTouchIrq = 28;
static constexpr uint8_t pinPowerPresentIrq = 19;
-std::unique_ptr systemTask;
-Pinetime::Controllers::Settings settingsController {spiNorFlash};
+Pinetime::Controllers::HeartRateController heartRateController;
+Pinetime::Applications::HeartRateTask heartRateApp(heartRateSensor, heartRateController);
+Pinetime::Controllers::DateTime dateTimeController;
+Pinetime::Drivers::Watchdog watchdog;
+Pinetime::Drivers::WatchdogView watchdogView(watchdog);
+Pinetime::Controllers::NotificationManager notificationManager;
+Pinetime::Controllers::MotionController motionController;
+Pinetime::Controllers::TimerController timerController;
+
+Pinetime::Controllers::FS fs {spiNorFlash};
+Pinetime::Controllers::Settings settingsController {fs};
Pinetime::Controllers::MotorController motorController {settingsController};
+
+Pinetime::Applications::DisplayApp displayApp(lcd,
+ lvgl,
+ touchPanel,
+ batteryController,
+ bleController,
+ dateTimeController,
+ watchdogView,
+ notificationManager,
+ heartRateController,
+ settingsController,
+ motorController,
+ motionController,
+ timerController);
+
+Pinetime::System::SystemTask systemTask(spi,
+ lcd,
+ spiNorFlash,
+ twiMaster,
+ touchPanel,
+ lvgl,
+ batteryController,
+ bleController,
+ dateTimeController,
+ timerController,
+ watchdog,
+ notificationManager,
+ motorController,
+ heartRateSensor,
+ motionController,
+ motionSensor,
+ settingsController,
+ heartRateController,
+ displayApp,
+ heartRateApp,
+ fs);
+
void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
if (pin == pinTouchIrq) {
- systemTask->OnTouchEvent();
+ systemTask.OnTouchEvent();
return;
}
@@ -132,21 +178,14 @@ void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
-extern "C" {
-void vApplicationIdleHook(void) {
- if (!isFactory)
- lv_tick_inc(1);
-}
-}
-
void DebounceTimerChargeCallback(TimerHandle_t xTimer) {
xTimerStop(xTimer, 0);
- systemTask->PushMessage(Pinetime::System::SystemTask::Messages::OnChargingEvent);
+ systemTask.PushMessage(Pinetime::System::Messages::OnChargingEvent);
}
void DebounceTimerCallback(TimerHandle_t xTimer) {
xTimerStop(xTimer, 0);
- systemTask->OnButtonPushed();
+ systemTask.OnButtonPushed();
}
void SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler(void) {
@@ -264,19 +303,12 @@ int main(void) {
debounceTimer = xTimerCreate("debounceTimer", 200, pdFALSE, (void*) 0, DebounceTimerCallback);
debounceChargeTimer = xTimerCreate("debounceTimerCharge", 200, pdFALSE, (void*) 0, DebounceTimerChargeCallback);
- systemTask = std::make_unique(spi,
- lcd,
- spiNorFlash,
- twiMaster,
- touchPanel,
- lvgl,
- batteryController,
- bleController,
- motorController,
- heartRateSensor,
- motionSensor,
- settingsController);
- systemTask->Start();
+ // retrieve version stored by bootloader
+ Pinetime::BootloaderVersion::SetVersion(NRF_TIMER2->CC[0]);
+
+ lvgl.Init();
+
+ systemTask.Start();
nimble_port_init();
vTaskStartScheduler();
diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h
new file mode 100644
index 00000000..3a195e2d
--- /dev/null
+++ b/src/systemtask/Messages.h
@@ -0,0 +1,26 @@
+#pragma once
+
+namespace Pinetime {
+ namespace System {
+ enum class Messages {
+ GoToSleep,
+ GoToRunning,
+ TouchWakeUp,
+ OnNewTime,
+ OnNewNotification,
+ OnTimerDone,
+ OnNewCall,
+ BleConnected,
+ UpdateTimeOut,
+ BleFirmwareUpdateStarted,
+ BleFirmwareUpdateFinished,
+ OnTouchEvent,
+ OnButtonEvent,
+ OnDisplayTaskSleeping,
+ EnableSleeping,
+ DisableSleeping,
+ OnNewDay,
+ OnChargingEvent
+ };
+ }
+}
diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp
index 58377764..eb29638a 100644
--- a/src/systemtask/SystemTask.cpp
+++ b/src/systemtask/SystemTask.cpp
@@ -27,6 +27,12 @@
using namespace Pinetime::System;
+namespace {
+ static inline bool in_isr(void) {
+ return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0;
+ }
+}
+
void IdleTimerCallback(TimerHandle_t xTimer) {
NRF_LOG_INFO("IdleTimerCallback");
@@ -42,10 +48,19 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
Components::LittleVgl& lvgl,
Controllers::Battery& batteryController,
Controllers::Ble& bleController,
+ Controllers::DateTime& dateTimeController,
+ Controllers::TimerController& timerController,
+ Drivers::Watchdog& watchdog,
+ Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::MotorController& motorController,
Pinetime::Drivers::Hrs3300& heartRateSensor,
+ Pinetime::Controllers::MotionController& motionController,
Pinetime::Drivers::Bma421& motionSensor,
- Controllers::Settings& settingsController)
+ Controllers::Settings& settingsController,
+ Pinetime::Controllers::HeartRateController& heartRateController,
+ Pinetime::Applications::DisplayApp& displayApp,
+ Pinetime::Applications::HeartRateTask& heartRateApp,
+ Pinetime::Controllers::FS& fs)
: spi {spi},
lcd {lcd},
spiNorFlash {spiNorFlash},
@@ -53,21 +68,26 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
touchPanel {touchPanel},
lvgl {lvgl},
batteryController {batteryController},
- heartRateController {*this},
bleController {bleController},
- dateTimeController {*this},
- timerController {*this},
- watchdog {},
- watchdogView {watchdog},
+ dateTimeController {dateTimeController},
+ timerController {timerController},
+ watchdog {watchdog},
+ notificationManager{notificationManager},
motorController {motorController},
heartRateSensor {heartRateSensor},
motionSensor {motionSensor},
settingsController {settingsController},
+ heartRateController{heartRateController},
+ motionController{motionController},
+ displayApp{displayApp},
+ heartRateApp(heartRateApp),
+ fs{fs},
nimbleController(*this, bleController, dateTimeController, notificationManager, batteryController, spiNorFlash, heartRateController) {
- systemTasksMsgQueue = xQueueCreate(10, 1);
+
}
void SystemTask::Start() {
+ systemTasksMsgQueue = xQueueCreate(10, 1);
if (pdPASS != xTaskCreate(SystemTask::Process, "MAIN", 350, this, 0, &taskHandle))
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}
@@ -89,6 +109,9 @@ void SystemTask::Work() {
spi.Init();
spiNorFlash.Init();
spiNorFlash.Wakeup();
+
+ fs.Init();
+
nimbleController.Init();
nimbleController.StartAdvertising();
brightnessController.Init();
@@ -96,9 +119,11 @@ void SystemTask::Work() {
twiMaster.Init();
touchPanel.Init();
+ dateTimeController.Register(this);
batteryController.Init();
motorController.Init();
motionSensor.SoftReset();
+ timerController.Register(this);
timerController.Init();
// Reset the TWI device because the motion sensor chip most probably crashed it...
@@ -106,30 +131,17 @@ void SystemTask::Work() {
twiMaster.Init();
motionSensor.Init();
+ motionController.Init(motionSensor.DeviceType());
settingsController.Init();
- displayApp = std::make_unique(lcd,
- lvgl,
- touchPanel,
- batteryController,
- bleController,
- dateTimeController,
- watchdogView,
- *this,
- notificationManager,
- heartRateController,
- settingsController,
- motorController,
- motionController,
- timerController);
- displayApp->Start();
+ displayApp.Register(this);
+ displayApp.Start();
- displayApp->PushMessage(Pinetime::Applications::Display::Messages::UpdateBatteryLevel);
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::UpdateBatteryLevel);
heartRateSensor.Init();
heartRateSensor.Disable();
- heartRateApp = std::make_unique(heartRateSensor, heartRateController);
- heartRateApp->Start();
+ heartRateApp.Start();
nrf_gpio_cfg_sense_input(pinButton, (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pulldown, (nrf_gpio_pin_sense_t) GPIO_PIN_CNF_SENSE_High);
nrf_gpio_cfg_output(15);
@@ -208,9 +220,9 @@ void SystemTask::Work() {
spiNorFlash.Wakeup();
lcd.Wakeup();
- displayApp->PushMessage(Pinetime::Applications::Display::Messages::GoToRunning);
- displayApp->PushMessage(Pinetime::Applications::Display::Messages::UpdateBatteryLevel);
- heartRateApp->PushMessage(Pinetime::Applications::HeartRateTask::Messages::WakeUp);
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToRunning);
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::UpdateBatteryLevel);
+ heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::WakeUp);
isSleeping = false;
isWakingUp = false;
@@ -230,26 +242,26 @@ void SystemTask::Work() {
isGoingToSleep = true;
NRF_LOG_INFO("[systemtask] Going to sleep");
xTimerStop(idleTimer, 0);
- displayApp->PushMessage(Pinetime::Applications::Display::Messages::GoToSleep);
- heartRateApp->PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep);
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToSleep);
+ heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::GoToSleep);
break;
case Messages::OnNewTime:
ReloadIdleTimer();
- displayApp->PushMessage(Pinetime::Applications::Display::Messages::UpdateDateTime);
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::UpdateDateTime);
break;
case Messages::OnNewNotification:
if (isSleeping && !isWakingUp) {
GoToRunning();
}
motorController.SetDuration(35);
- displayApp->PushMessage(Pinetime::Applications::Display::Messages::NewNotification);
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::NewNotification);
break;
case Messages::OnTimerDone:
if (isSleeping && !isWakingUp) {
GoToRunning();
}
motorController.SetDuration(35);
- displayApp->PushMessage(Pinetime::Applications::Display::Messages::TimerDone);
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::TimerDone);
break;
case Messages::BleConnected:
ReloadIdleTimer();
@@ -260,7 +272,7 @@ void SystemTask::Work() {
doNotGoToSleep = true;
if (isSleeping && !isWakingUp)
GoToRunning();
- displayApp->PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted);
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::BleFirmwareUpdateStarted);
break;
case Messages::BleFirmwareUpdateFinished:
doNotGoToSleep = false;
@@ -318,6 +330,11 @@ void SystemTask::Work() {
}
}
+ if (xTaskGetTickCount() - batteryNotificationTick > batteryNotificationPeriod) {
+ nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining());
+ batteryNotificationTick = xTaskGetTickCount();
+ }
+
monitor.Process();
uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG);
dateTimeController.UpdateTime(systick_counter);
@@ -359,7 +376,7 @@ void SystemTask::OnButtonPushed() {
if (!isSleeping) {
NRF_LOG_INFO("[systemtask] Button pushed");
PushMessage(Messages::OnButtonEvent);
- displayApp->PushMessage(Pinetime::Applications::Display::Messages::ButtonPushed);
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::ButtonPushed);
} else {
if (!isWakingUp) {
NRF_LOG_INFO("[systemtask] Button pushed, waking up");
@@ -380,7 +397,7 @@ void SystemTask::OnTouchEvent() {
return;
if (!isSleeping) {
PushMessage(Messages::OnTouchEvent);
- displayApp->PushMessage(Pinetime::Applications::Display::Messages::TouchEvent);
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent);
} else if (!isWakingUp) {
if (settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::None or
settingsController.getWakeUpMode() == Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist)
@@ -389,16 +406,22 @@ void SystemTask::OnTouchEvent() {
}
}
-void SystemTask::PushMessage(SystemTask::Messages msg) {
+void SystemTask::PushMessage(System::Messages msg) {
if (msg == Messages::GoToSleep) {
isGoingToSleep = true;
}
- BaseType_t xHigherPriorityTaskWoken;
- xHigherPriorityTaskWoken = pdFALSE;
- xQueueSendFromISR(systemTasksMsgQueue, &msg, &xHigherPriorityTaskWoken);
- if (xHigherPriorityTaskWoken) {
- /* Actual macro used here is port specific. */
- // TODO: should I do something here?
+
+ if(in_isr()) {
+ BaseType_t xHigherPriorityTaskWoken;
+ xHigherPriorityTaskWoken = pdFALSE;
+ xQueueSendFromISR(systemTasksMsgQueue, &msg, &xHigherPriorityTaskWoken);
+ if (xHigherPriorityTaskWoken) {
+ /* Actual macro used here is port specific. */
+ portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
+
+ }
+ } else {
+ xQueueSend(systemTasksMsgQueue, &msg, portMAX_DELAY);
}
}
diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h
index ea41a69d..f8cf6370 100644
--- a/src/systemtask/SystemTask.h
+++ b/src/systemtask/SystemTask.h
@@ -6,7 +6,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -17,16 +16,19 @@
#include "components/ble/NotificationManager.h"
#include "components/motor/MotorController.h"
#include "components/timer/TimerController.h"
+#include "components/fs/FS.h"
+
#ifdef PINETIME_IS_RECOVERY
#include "displayapp/DisplayAppRecovery.h"
#include "displayapp/DummyLittleVgl.h"
#else
#include "components/settings/Settings.h"
#include "displayapp/DisplayApp.h"
- #include "displayapp/LittleVgl.h"
+ #include "displayapp/LittleVgl.h"
#endif
#include "drivers/Watchdog.h"
+#include "Messages.h"
namespace Pinetime {
namespace Drivers {
@@ -40,27 +42,6 @@ namespace Pinetime {
namespace System {
class SystemTask {
public:
- enum class Messages {
- GoToSleep,
- GoToRunning,
- TouchWakeUp,
- OnNewTime,
- OnNewNotification,
- OnTimerDone,
- OnNewCall,
- BleConnected,
- UpdateTimeOut,
- BleFirmwareUpdateStarted,
- BleFirmwareUpdateFinished,
- OnTouchEvent,
- OnButtonEvent,
- OnDisplayTaskSleeping,
- EnableSleeping,
- DisableSleeping,
- OnNewDay,
- OnChargingEvent
- };
-
SystemTask(Drivers::SpiMaster& spi,
Drivers::St7789& lcd,
Pinetime::Drivers::SpiNorFlash& spiNorFlash,
@@ -69,10 +50,19 @@ namespace Pinetime {
Components::LittleVgl& lvgl,
Controllers::Battery& batteryController,
Controllers::Ble& bleController,
+ Controllers::DateTime& dateTimeController,
+ Controllers::TimerController& timerController,
+ Drivers::Watchdog& watchdog,
+ Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::MotorController& motorController,
Pinetime::Drivers::Hrs3300& heartRateSensor,
+ Pinetime::Controllers::MotionController& motionController,
Pinetime::Drivers::Bma421& motionSensor,
- Controllers::Settings& settingsController);
+ Controllers::Settings& settingsController,
+ Pinetime::Controllers::HeartRateController& heartRateController,
+ Pinetime::Applications::DisplayApp& displayApp,
+ Pinetime::Applications::HeartRateTask& heartRateApp,
+ Pinetime::Controllers::FS& fs);
void Start();
void PushMessage(Messages msg);
@@ -86,6 +76,10 @@ namespace Pinetime {
return nimbleController;
};
+ bool IsSleeping() const {
+ return isSleeping;
+ }
+
private:
TaskHandle_t taskHandle;
@@ -96,27 +90,30 @@ namespace Pinetime {
Pinetime::Drivers::Cst816S& touchPanel;
Pinetime::Components::LittleVgl& lvgl;
Pinetime::Controllers::Battery& batteryController;
- std::unique_ptr displayApp;
- Pinetime::Controllers::HeartRateController heartRateController;
- std::unique_ptr heartRateApp;
+
Pinetime::Controllers::Ble& bleController;
- Pinetime::Controllers::DateTime dateTimeController;
- Pinetime::Controllers::TimerController timerController;
+ Pinetime::Controllers::DateTime& dateTimeController;
+ Pinetime::Controllers::TimerController& timerController;
QueueHandle_t systemTasksMsgQueue;
std::atomic isSleeping {false};
std::atomic isGoingToSleep {false};
std::atomic isWakingUp {false};
- Pinetime::Drivers::Watchdog watchdog;
- Pinetime::Drivers::WatchdogView watchdogView;
- Pinetime::Controllers::NotificationManager notificationManager;
+ Pinetime::Drivers::Watchdog& watchdog;
+ Pinetime::Controllers::NotificationManager& notificationManager;
Pinetime::Controllers::MotorController& motorController;
Pinetime::Drivers::Hrs3300& heartRateSensor;
Pinetime::Drivers::Bma421& motionSensor;
Pinetime::Controllers::Settings& settingsController;
- Pinetime::Controllers::NimbleController nimbleController;
+ Pinetime::Controllers::HeartRateController& heartRateController;
+
Controllers::BrightnessController brightnessController;
- Pinetime::Controllers::MotionController motionController;
+ Pinetime::Controllers::MotionController& motionController;
+
+ Pinetime::Applications::DisplayApp& displayApp;
+ Pinetime::Applications::HeartRateTask& heartRateApp;
+ Pinetime::Controllers::FS& fs;
+ Pinetime::Controllers::NimbleController nimbleController;
static constexpr uint8_t pinSpiSck = 2;
static constexpr uint8_t pinSpiMosi = 3;
@@ -138,6 +135,8 @@ namespace Pinetime {
void GoToRunning();
void UpdateMotion();
bool stepCounterMustBeReset = false;
+ static constexpr TickType_t batteryNotificationPeriod = 1000 * 60 * 10; // 1 tick ~= 1ms. 1ms * 60 * 10 = 10 minutes
+ TickType_t batteryNotificationTick = 0;
#if configUSE_TRACE_FACILITY == 1
SystemMonitor monitor;