<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.pine64.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Electr0lyte</id>
	<title>PINE64 - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.pine64.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Electr0lyte"/>
	<link rel="alternate" type="text/html" href="https://wiki.pine64.org/wiki/Special:Contributions/Electr0lyte"/>
	<updated>2026-05-25T17:44:33Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Development&amp;diff=9805</id>
		<title>PineTime Development</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Development&amp;diff=9805"/>
		<updated>2021-04-10T15:05:17Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Available firmware and projects */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Reprogramming ==&lt;br /&gt;
&lt;br /&gt;
[[PineTime devkit wiring|Wire it up]] and then [[Reprogramming the PineTime| flash something]].&lt;br /&gt;
&lt;br /&gt;
== Available firmware and projects ==&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
!&lt;br /&gt;
! Project Homepage&lt;br /&gt;
! Project Source&lt;br /&gt;
! PineTime Implementations&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! FreeRTOS&lt;br /&gt;
|https://www.freertos.org&lt;br /&gt;
| https://sourceforge.net/projects/freertos/&lt;br /&gt;
|&lt;br /&gt;
{|&lt;br /&gt;
|[[InfiniTime]] (GitHub: [https://github.com/JF002/Pinetime JF002/Pinetime])&lt;br /&gt;
|-&lt;br /&gt;
|[https://github.com/kaythe/pinetime-os kaythe/pinetime-os]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Zephyr&lt;br /&gt;
| https://www.zephyrproject.org&lt;br /&gt;
| https://github.com/zephyrproject-rtos/zephyr&lt;br /&gt;
|&lt;br /&gt;
{|&lt;br /&gt;
|[https://github.com/najnesnaj/pinetime-zephyr najnesnaj/pinetime-zephyr]&lt;br /&gt;
|- &lt;br /&gt;
|[https://github.com/SuperPrower/pinetime_zephyr_sample_fw SuperPrower/pinetime_zephyr_sample_fw]&lt;br /&gt;
|-&lt;br /&gt;
|[https://github.com/Dejvino/pinetime-hermes-firmware Dejvino/pinetime-hermes-firmware]&lt;br /&gt;
|-&lt;br /&gt;
|[https://github.com/endian-albin/pinetime-hypnos endian-albin/pinetime-hypnos]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! mynewt&lt;br /&gt;
| https://mynewt.apache.org/about/&lt;br /&gt;
| https://github.com/apache/mynewt-core&lt;br /&gt;
|&lt;br /&gt;
{|&lt;br /&gt;
|[https://github.com/lupyuen/pinetime-rust-mynewt lupyuen/pinetime-rust-mynewt]&lt;br /&gt;
|-&lt;br /&gt;
|[https://gitlab.com/caspermeijn/klok caspermeijn/klok]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! MbedOS&lt;br /&gt;
| https://os.mbed.com&lt;br /&gt;
| https://github.com/ARMmbed/mbed-os&lt;br /&gt;
|&lt;br /&gt;
{|&lt;br /&gt;
|[https://github.com/sethitow/mbed-pinetime sethitow/mbed-pinetime]&lt;br /&gt;
|-&lt;br /&gt;
|[https://github.com/geoffrey-vl/mbed-pinetime geoffrey.vl/mbed-pinetime]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! RIOT&lt;br /&gt;
| http://riot-os.org/&lt;br /&gt;
| https://github.com/RIOT-OS/RIOT/&lt;br /&gt;
| [https://github.com/bosmoment/PineTime-apps bosmoment/PineTime-apps]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! TinyGo&lt;br /&gt;
| https://tinygo.org&lt;br /&gt;
| https://github.com/tinygo-org/tinygo&lt;br /&gt;
| [https://github.com/aykevl/go-smartwatch aykevl/go-smartwatch]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! wasp-os (MicroPython)&lt;br /&gt;
| https://wasp-os.readthedocs.io/&lt;br /&gt;
| https://github.com/daniel-thompson/wasp-os&lt;br /&gt;
| [https://wasp-os.readthedocs.io/en/latest/install.html#pine64-pinetime-developer-edition WaspOS PineTime install guide]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! wasp-os Companion app for Linux&lt;br /&gt;
| [https://gitlab.com/arteeh/wasp-companion arteeh/wasp-companion]&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Rust + RTFM&lt;br /&gt;
| https://rtfm.rs/&lt;br /&gt;
| [https://github.com/rtfm-rs/cortex-m-rtfm rtfm-rs/cortex-m-rtfm]&lt;br /&gt;
| https://github.com/dbrgn/pinetime-rtfm/&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Bare Metal&lt;br /&gt;
| &lt;br /&gt;
|&lt;br /&gt;
{|&lt;br /&gt;
|https://github.com/xriss/timecake&lt;br /&gt;
|-&lt;br /&gt;
|https://github.com/Arc13/Pyrus&lt;br /&gt;
|}&lt;br /&gt;
|&lt;br /&gt;
{|&lt;br /&gt;
|[https://github.com/xriss/timecake xriss/timecake]&lt;br /&gt;
|-&lt;br /&gt;
|[https://github.com/Arc13/Pyrus Arc13/Pyrus]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! AdaFruit bootloader&lt;br /&gt;
|&lt;br /&gt;
| https://github.com/adafruit/Adafruit_nRF52_Bootloader&lt;br /&gt;
| [https://github.com/daniel-thompson/wasp-bootloader daniel-thompson/wasp-bootloader]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Useful drivers&lt;br /&gt;
|&lt;br /&gt;
| https://github.com/sethitow/mbed-pinetime&lt;br /&gt;
| [https://github.com/sethitow/mbed-pinetime/tree/master/drivers https://github.com/sethitow/mbed-pinetime]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! UI concepts and drawings&lt;br /&gt;
| [https://gitlab.com/arteeh/pinetime-os arteeh/pinetime-os]&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Flashing app for Linux&lt;br /&gt;
| [https://gitlab.com/arteeh/pinetime-flasher arteeh/pinetime-flasher]&lt;br /&gt;
[https://github.com/alexr4535/siglo alexr4535/siglo]&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Android companion app&lt;br /&gt;
| https://gadgetbridge.org/&lt;br /&gt;
| https://codeberg.org/Freeyourgadget/Gadgetbridge&lt;br /&gt;
| [https://github.com/JF002/Pinetime InfiniTime] [https://codeberg.org/Freeyourgadget/Gadgetbridge/commit/9b8f4d329e49cafdfe0497ed38a715faa9f844c6 initial support added]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Arduino&lt;br /&gt;
| https://youtu.be/4aFDjymXjOw&lt;br /&gt;
| https://github.com/atc1441/ATCwatch&lt;br /&gt;
| https://github.com/atc1441/ATCwatch&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! OTA Update Flasher / DaFlasher&lt;br /&gt;
| https://youtu.be/gUVEz-pxhgg&lt;br /&gt;
| https://github.com/atc1441/DaFlasherFiles&lt;br /&gt;
| https://github.com/atc1441/DaFlasherFiles&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! Flashing app for Windows&lt;br /&gt;
| [https://github.com/ZephyrLabs/PinetimeFlasher ZephyrLabs/PinetimeFlasher]&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Manuals ===&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/JF002/Pinetime InfiniTime installation]&lt;br /&gt;
* [https://github.com/najnesnaj/pinetime-zephyr Zephyr installation] Beginner manual which explains how to install Zephyr (by najnesnaj).&lt;br /&gt;
* [https://wasp-os.readthedocs.io/en/latest/ Wasp-OS installation] Full manual with install instructions and an application writer's guide.&lt;br /&gt;
&lt;br /&gt;
== How to write battery friendly software? ==&lt;br /&gt;
&lt;br /&gt;
The key to save battery is to enable only what you need when you need it. nRF52832 has a lot of functionalities allowing you to draw as little current as possible. Here are some tips and tricks:&lt;br /&gt;
&lt;br /&gt;
* Disable / shutdown / put in sleep mode '''all devices around the MCU''' (display controller, touch controller, external memory,...). &lt;br /&gt;
* Disable all '''peripheral inside the MCU''' when you don't need them (SPI, TWI(I²C),...). The power management of the NRF52832 is very smart and will completely shut down (power off and disable the clock) the peripheral when the software disables it.&lt;br /&gt;
* Put the MCU to sleep as soon and as often as possible. If you are not using a RTOS, this is done by calling ''WFE'' (wait for event) instruction. Most of the time, RTOS implement this functionality. For example, FreeRTOS calls it the ''tickless mode'' : it puts the CPU in sleep mode when no task is planned for execution for more than a specified time, and wakes up as soon as an event is detected or when a task is ready to run.&lt;br /&gt;
* Do not use logging (JLink RTT, SWO, semihosting,...), it uses a lot of power.&lt;br /&gt;
* Ensure that the debug circuitry of the MCU is not enabled when you measuring the battery life. The debug peripheral is enabled as soon as you connect a debugger to the device, and '''is not automatically disabled''', even if you disconnect the debugger you will have to wait for the battery to go flat to disable to port. The software running in the NRF52832 cannot disable the debug peripheral. How to disable the debug circuitry:&lt;br /&gt;
  - using ''nrfjprog --reset''&lt;br /&gt;
  - using JLinkExe : issue the command ''writeDP 1 0''&lt;br /&gt;
&lt;br /&gt;
  or with OpenOCD&lt;br /&gt;
  - issue the command ''halt''&lt;br /&gt;
  - issue the command ''flash fillw 0x10001208 0xFFFFFF00 0x01''&lt;br /&gt;
  - issue the command ''reset''&lt;br /&gt;
&lt;br /&gt;
  you can check if the debug port is enabled using the following code&lt;br /&gt;
  DWT-&amp;gt;CYCCNT ? &amp;quot;NO&amp;quot;:&amp;quot;YES&amp;quot;&lt;br /&gt;
* Read [https://infocenter.nordicsemi.com/pdf/nRF52832_Rev_2_Errata_v1.1.pdf the errata sheet of the MCU] and apply workarounds if they apply to your software.&lt;br /&gt;
&lt;br /&gt;
== Wishlist ==&lt;br /&gt;
&lt;br /&gt;
In order to keep track of features and changes to the hardware people would like to see, check out this article: [[PineTime Hardware Wishlist]]&lt;br /&gt;
&lt;br /&gt;
== Compatibility with other projects ==&lt;br /&gt;
&lt;br /&gt;
Different firmware running using different bootloaders and Bluetooth stacks on the nRF52832 have different requirements on how they should be initialised and what should be placed where in the internal flash.&lt;br /&gt;
&lt;br /&gt;
To keep track of what, how and why things work like they do across the different projects, check out the [[PineTime SD MCUBoot|PineTime SoftDevice and MCUBoot compatibility]] article.&lt;br /&gt;
&lt;br /&gt;
== Compatibility with companions apps and Bluetooth communication ==&lt;br /&gt;
&lt;br /&gt;
There are a lot of different firmware running on the Pinetime that implement different BLE APIs (time synchronization, notifications, ...). Companion apps must be able to differentiate between different firmware and forks of the same firmware. See [[PineTime Bluetooth]].&lt;br /&gt;
&lt;br /&gt;
== PineTime equivalents and jailbreaking ==&lt;br /&gt;
&lt;br /&gt;
This page contains a list of PineTime-like smartwatches that might be &amp;quot;jailbreakable&amp;quot; or a good source for ideas for the PineTime: [[PineTime Equivalents]]&lt;br /&gt;
&lt;br /&gt;
[[Category:PineTime]]&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime&amp;diff=8927</id>
		<title>PineTime</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime&amp;diff=8927"/>
		<updated>2021-01-08T06:12:52Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: link the watch face repository to main page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Frequently asked questions ==&lt;br /&gt;
&lt;br /&gt;
'''Read these first!'''&lt;br /&gt;
&lt;br /&gt;
* [[Frequently asked questions about the PineTime| Frequently Asked Questions about the devkit]]&lt;br /&gt;
* [[Reprogramming the PineTime|Reprogramming the PineTime (development kit)]]&lt;br /&gt;
&lt;br /&gt;
== Default OS ==&lt;br /&gt;
&lt;br /&gt;
The current default operating system on the PineTime is called [[InfiniTime]], you can find more information about the firmware on its GitHub page. First devkits shipped with a proprietary custom firmware.&lt;br /&gt;
&lt;br /&gt;
== Short overview ==&lt;br /&gt;
'''Dimensions:''' 37.5 x 40 x 11mm &amp;lt;br&amp;gt;&lt;br /&gt;
'''Weight:''' 38 grams &amp;lt;br&amp;gt;&lt;br /&gt;
'''IP Rating:''' IP67 (waterproof to 1 meter (sealed edition!)) &amp;lt;br&amp;gt;&lt;br /&gt;
'''Display:'''&lt;br /&gt;
: '''Size:''' 1.3 inches (33mm) diagonal&lt;br /&gt;
: '''Type:''' IPS capacitive touchscreen, RGB 65K colors&lt;br /&gt;
: '''Display Controller:''' ST7789&lt;br /&gt;
: '''Resolution:''' 240x240 pixels &amp;lt;br&amp;gt;&lt;br /&gt;
'''System on Chip:''' Nordic Semiconductor nRF52832 &amp;lt;br&amp;gt;&lt;br /&gt;
'''Flash:''' 512KB with additional 4MB SPI NOR &amp;lt;br&amp;gt;&lt;br /&gt;
'''RAM:''' 64KB &amp;lt;br&amp;gt;&lt;br /&gt;
'''Bluetooth:''' [[PineTime_Bluetooth|5.0 (including Bluetooth Low Energy)]] &amp;lt;br&amp;gt;&lt;br /&gt;
'''Sensors:''' Accelerometer, Heart rate sensor &amp;lt;br&amp;gt;&lt;br /&gt;
'''Feedback:''' Vibration motor &amp;lt;br&amp;gt;&lt;br /&gt;
'''Battery:''' 170-180mAh LiPo&lt;br /&gt;
&lt;br /&gt;
= Community =&lt;br /&gt;
* [https://forum.pine64.org/forumdisplay.php?fid=134 PineTime forum]&lt;br /&gt;
* [https://app.element.io/#/room/#pinetime:matrix.org Matrix Channel] (No login required to read)&lt;br /&gt;
* IRC Server: [ircs://irc.pine64.org#pinetime irc.pine64.org] Channel: PineTime&lt;br /&gt;
* [https://t.me/pinetime Telegram group]&lt;br /&gt;
* [https://discordapp.com/invite/DgB7kzr Discord server invite link]&lt;br /&gt;
&lt;br /&gt;
== Development efforts ==&lt;br /&gt;
&lt;br /&gt;
To read more about development on the PineTime, the projects available and more technical details, check out [[PineTime Development]]&lt;br /&gt;
&lt;br /&gt;
== Useful articles and blog posts == &lt;br /&gt;
&lt;br /&gt;
If you want to dive in to the ecosystem, here's a short list of various articles and blog posts that can help you set up your soft- or hardware development environment.&lt;br /&gt;
&lt;br /&gt;
* [https://medium.com/swlh/sneak-peek-of-pinetime-smart-watch-and-why-its-perfect-for-teaching-iot-81b74161c159 Sneak Peek of PineTime Smart Watch… And why it’s perfect for teaching IoT]&lt;br /&gt;
&lt;br /&gt;
* [https://medium.com/@ly.lee/building-a-rust-driver-for-pinetimes-touch-controller-cbc1a5d5d3e9 Building a Rust Driver for PineTime’s Touch Controller]&lt;br /&gt;
&lt;br /&gt;
* [https://medium.com/@ly.lee/porting-druid-rust-widgets-to-pinetime-smart-watch-7e1d5a5d977a Porting (druid) Rust Widgets to PineTime Smart Watch]&lt;br /&gt;
&lt;br /&gt;
* [https://medium.com/@ly.lee/optimising-pinetimes-display-driver-with-rust-and-mynewt-3ba269ea2f5c Optimising PineTime’s Display Driver with Rust and Mynewt]&lt;br /&gt;
&lt;br /&gt;
* [https://www.zephyrproject.org/getting-started-with-zephyr-rtos-on-nordic-nrf52832-hackable/ Getting Started with Zephyr RTOS on Nordic nRF52832 hackaBLE]&lt;br /&gt;
&lt;br /&gt;
* [https://blog.aegrel.ee/absniffer-cmsis-dap-sniffer.html Removing the lock and installing another firmware on the nRF52832 using CMSIS-DAP dongle on Linux]&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/JF002/nrf52-baseproject/wiki/Build,-program-and-debug-NRF52-project-with-JLink,-CMake-and-CLion Build, program and debug NRF52 project with JLink, CMake and CLion]&lt;br /&gt;
&lt;br /&gt;
* [https://www.nrbtech.io/blog/2020/1/4/using-clion-for-nordic-nrf52-projects Using CLion for Nordic nRF52 projects]&lt;br /&gt;
&lt;br /&gt;
* [https://dev.to/aaronc81/flashing-your-pinetime-using-an-st-link-and-openocd-54dd Flashing your PineTime using an ST-Link and OpenOCD]&lt;br /&gt;
&lt;br /&gt;
* [https://zephyrlabs.github.io/Watchfaces/ Zephyrlabs: just a bunch of watchfaces made for the pinetime]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
=== Display ===&lt;br /&gt;
&lt;br /&gt;
Note: The factory-default software on the PineTime does not auto-detect the display being disconnected when it has already booted. That can cause garbled output, to fix it just restart the PineTime.&lt;br /&gt;
&lt;br /&gt;
The display is driven using the ST7789 display controller. Use the following pins to drive the screen:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! PineTime pin&lt;br /&gt;
! ST7789 pin&lt;br /&gt;
|-&lt;br /&gt;
| LCD_SCK (P0.02)&lt;br /&gt;
| SPI clock&lt;br /&gt;
|-&lt;br /&gt;
| LCD_SDI (P0.03)&lt;br /&gt;
| SPI MOSI&lt;br /&gt;
|-&lt;br /&gt;
| LCD_RS (P0.18)&lt;br /&gt;
| Command/Data pin (CD)&lt;br /&gt;
|-&lt;br /&gt;
| LCD_CS (P0.25)&lt;br /&gt;
| Chip select&lt;br /&gt;
|-&lt;br /&gt;
| LCD_RESET (P0.26)&lt;br /&gt;
| Display reset&lt;br /&gt;
|-&lt;br /&gt;
| LCD_BACKLIGHT_{LOW,MID,HIGH}&lt;br /&gt;
| Backlight (active low)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
&lt;br /&gt;
* Chip select must be held low while driving the display. It must be high when using other SPI devices on the same bus (such as external flash storage) so that the display controller won't respond to the wrong commands.&lt;br /&gt;
* SPI must be used in mode 3. Mode 0 (the default) won't work.&lt;br /&gt;
* LCD_DISPLAY_* is used to enable the backlight. Set at least one to low to see anything on the screen.&lt;br /&gt;
* Use SPI at 8MHz (the fastest clock available on the nRF52832) because otherwise refreshing will be super slow.&lt;br /&gt;
&lt;br /&gt;
'''References''':&lt;br /&gt;
&lt;br /&gt;
[https://github.com/adafruit/Adafruit-ST7735-Library/ Adafruit ST7789 driver in cpp]&lt;br /&gt;
&lt;br /&gt;
=== Battery measurement ===&lt;br /&gt;
&lt;br /&gt;
Reading whether the PineTime has power attached is easy: simply read the charge indication pin (P0.12). When it is high it is running on battery, when it is low it is charging.&lt;br /&gt;
&lt;br /&gt;
Reading the battery voltage is a bit harder. For that you can use the battery voltage pin on P0.31 (AIN7). The returned value is 12 bits, which means it is 0..4095. You can get the measured voltage with the following formula, assuming a reference voltage of 3.3V (this is configurable in the ADC):&lt;br /&gt;
&lt;br /&gt;
 adcVoltage = adcValue / (4095 / 3.3)&lt;br /&gt;
&lt;br /&gt;
The measured voltage is actually half of the actual battery voltage, because the ADC is connected between a voltage divider where both resistors are 1MΩ. This can be corrected by multiplying the value:&lt;br /&gt;
&lt;br /&gt;
 batteryVoltage = adcValue * 2 / (4095 / 3.3)&lt;br /&gt;
&lt;br /&gt;
It's often better to avoid floating point values on embedded systems and in this case there is no reason to use float at all, we can just represent the value in millivolts. Therefore the formula can be simplified to:&lt;br /&gt;
&lt;br /&gt;
 batteryVoltage = adcValue * 2000 / (4095 / 3.3)&lt;br /&gt;
 batteryVoltage = adcValue * 2000 / 1241&lt;br /&gt;
&lt;br /&gt;
Converting this voltage to an estimated capacity in percent requires a more complicated algorithm, because Lithium-ion batteries have a non-linear discharge curve.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Button ===&lt;br /&gt;
&lt;br /&gt;
The button on the side of the PineTime is disabled by default. To enable it, drive the button out pin (P0.15) high.&lt;br /&gt;
&lt;br /&gt;
While enabled, the button in pin (P0.13) will be high when the button is pressed, and low when it is not pressed.&lt;br /&gt;
&lt;br /&gt;
=== Touch panel ===&lt;br /&gt;
&lt;br /&gt;
The touch panel is controlled by a Hynitron CST816S chips. Unfortunately, there is not much information about this chip on the internet apart from the datasheet below and a [https://github.com/lupyuen/hynitron_i2c_cst0xxse/ reference driver]. This is enough to implement a basic driver, but crucial information needed to implement advanced functionalities are missing (I²C protocol and registers, timings, power modes,...).&lt;br /&gt;
&lt;br /&gt;
==== Pins ====&lt;br /&gt;
&lt;br /&gt;
* P0.10 : Reset&lt;br /&gt;
* P0.28 : Interrupt (signal to the CPU when a touch event is detected)&lt;br /&gt;
* P0.06 : I²C SDA&lt;br /&gt;
* P0.07 : I²C SCL&lt;br /&gt;
&lt;br /&gt;
==== I²C ====&lt;br /&gt;
&lt;br /&gt;
* Device address : 0x15&lt;br /&gt;
* Frequency : from 10Khz to 400Khz&lt;br /&gt;
&lt;br /&gt;
'''NOTE : ''' The controller go to sleep when no event is detected. In sleep mode, the controller does not communicate on the I²C bus (it appears disconnected). So, for the communication to work, you need to tap on the screen so that the chip wakes-up.&lt;br /&gt;
&lt;br /&gt;
==== Touch events ====&lt;br /&gt;
&lt;br /&gt;
Touch information is available from the 63 first registers of the controller. Remember: the device is in sleep mode when no touch event is detected. It means that you can read the register only when the touch controller detected an event. You can use the ''Interrupt'' pin to detect such event in the software. &lt;br /&gt;
&lt;br /&gt;
These 63 bytes contain up to 10 touch point (X, Y, event type, pressure,...) : &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Byte&lt;br /&gt;
! Bit7&lt;br /&gt;
! Bit6&lt;br /&gt;
! Bit5&lt;br /&gt;
! Bit4&lt;br /&gt;
! Bit3&lt;br /&gt;
! Bit2&lt;br /&gt;
! Bit1&lt;br /&gt;
! Bit0&lt;br /&gt;
|-&lt;br /&gt;
|0&lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;|?&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;|GestureID : (Gesture code ,&lt;br /&gt;
&lt;br /&gt;
0x00: no gesture,&lt;br /&gt;
&lt;br /&gt;
0x01: Slide down,&lt;br /&gt;
&lt;br /&gt;
0x02: Slide up,&lt;br /&gt;
&lt;br /&gt;
0x03: Slide left,&lt;br /&gt;
&lt;br /&gt;
0x04: Slide right,&lt;br /&gt;
&lt;br /&gt;
0x05: Single click,&lt;br /&gt;
&lt;br /&gt;
0x0B: Double click,&lt;br /&gt;
&lt;br /&gt;
0x0C: Long press) &lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|colspan=&amp;quot;4&amp;quot;|? &lt;br /&gt;
|colspan=&amp;quot;4&amp;quot;|Number of touch points &lt;br /&gt;
|-&lt;br /&gt;
|3&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|Event (0 = Down, 1 = Up, 2 = Contact)&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|?&lt;br /&gt;
|colspan=&amp;quot;4&amp;quot;|X (MSB) coordinate&lt;br /&gt;
|-&lt;br /&gt;
|4&lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;|X (LSB) coordinate&lt;br /&gt;
|-&lt;br /&gt;
|5&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|?&lt;br /&gt;
|colspan=&amp;quot;2&amp;quot;|Touch ID&lt;br /&gt;
|colspan=&amp;quot;4&amp;quot;|Y (MSB) coordinate&lt;br /&gt;
|-&lt;br /&gt;
|6&lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;|Y (LSB) coordinate&lt;br /&gt;
|-&lt;br /&gt;
|7&lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;|Pressure (?)&lt;br /&gt;
|-&lt;br /&gt;
|8&lt;br /&gt;
|colspan=&amp;quot;8&amp;quot;|Miscellaneous (?)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Bytes 3 to 8 are repeated 10 times (10*6 + 3 = 63 bytes).&lt;br /&gt;
&lt;br /&gt;
'''NOTES'''&lt;br /&gt;
&lt;br /&gt;
* The touch controller seems to report only 1 touch point&lt;br /&gt;
* Fields X, Y, Number of touch points and touch ID are updated. The others are always 0.&lt;br /&gt;
&lt;br /&gt;
==== Registers ====&lt;br /&gt;
&lt;br /&gt;
The reference driver specifies some registers and value, but there is no information about them: &lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
&lt;br /&gt;
!Register&lt;br /&gt;
!Address&lt;br /&gt;
!Description&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_INT_CNT&lt;br /&gt;
|0x8F&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_FLOW_WORK_CNT&lt;br /&gt;
|0x91&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_WORKMODE &lt;br /&gt;
|0x00&lt;br /&gt;
|0 = WORK, 0x40 = FACTORY&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_CHIP_ID&lt;br /&gt;
|0xA3&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_CHIP_ID2&lt;br /&gt;
|0x9F&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_POWER_MODE&lt;br /&gt;
|0xA5&lt;br /&gt;
|0x03 = SLEEP (reset the touchpanel using the reset pin before using this register : pin_low, delay 5ms, pin_high, delay 50ms then write 3 to register 0xA5)&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_FW_VER&lt;br /&gt;
|0xA6&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_VENDOR_ID&lt;br /&gt;
|0xA8&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_LCD_BUSY_NUM&lt;br /&gt;
|0xAB&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_FACE_DEC_MODE_EN&lt;br /&gt;
|0xB0&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_GLOVE_MODE_EN&lt;br /&gt;
|0xC0&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_COVER_MODE_EN&lt;br /&gt;
|0xC1&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_CHARGER_MODE_EN&lt;br /&gt;
|0x8B&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_GESTURE_EN&lt;br /&gt;
|0xD0&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_GESTURE_OUTPUT_ADDRESS&lt;br /&gt;
|0xD3&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|HYN_REG_ESD_SATURATE 0xED&lt;br /&gt;
|0xED&lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''WARNING : ''' &amp;lt;del&amp;gt;Writing the SLEEP command (write 0x05 in HYN_REG_POWER_MODE) seems to freeze the controller (it returns only static values) until the battery is totally drained and the whole system reset. Analysis and debugging is more than welcome!&amp;lt;/del&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===Accelerometer===&lt;br /&gt;
The on board accelerometer is Bosch BMA421, connected to the I2C bus.&lt;br /&gt;
&lt;br /&gt;
==== Pins ====&lt;br /&gt;
&lt;br /&gt;
* P0.06 : I²C SDA&lt;br /&gt;
* P0.07 : I²C SCL&lt;br /&gt;
* P0.08 : Interrupt&lt;br /&gt;
&lt;br /&gt;
I2C Device address : 0x18&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Datasheets and Schematics ==&lt;br /&gt;
&lt;br /&gt;
=== Schematics ===&lt;br /&gt;
* [https://files.pine64.org/doc/PineTime/PineTime%20Schematic-V1.0a-20191103.pdf PineTime Schematic ver1.0a]&lt;br /&gt;
* [https://files.pine64.org/doc/PineTime/PineTime%20Port%20Assignment%20rev1.0.pdf PineTime GPIO Port Assignment ver1.0]&lt;br /&gt;
&lt;br /&gt;
Note: The part number for the SPI FLASH in the schematic diagram is not correct, the PineTime features a larger external FLASH device, see below.&lt;br /&gt;
&lt;br /&gt;
=== Chip Datasheets ===&lt;br /&gt;
* NORDIC nRF52832 information:&lt;br /&gt;
** [https://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf nRF52832 Product Brief]&lt;br /&gt;
** [https://infocenter.nordicsemi.com/pdf/nRF52832_PS_v1.1.pdf nRF52832 Product Specification v1.1]&lt;br /&gt;
* ARMv7-M information:&lt;br /&gt;
** [https://static.docs.arm.com/ddi0403/eb/DDI0403E_B_armv7m_arm.pdf ARMv7-M Architecture Reference Manual]&lt;br /&gt;
&lt;br /&gt;
=== Component Datasheets ===&lt;br /&gt;
* PMU (Power Management Unit) information:&lt;br /&gt;
** [https://files.pine64.org/doc/datasheet/pinetime/SGM40561.pdf SGMicro SGM40561 Single Cell Charger Datasheet]&lt;br /&gt;
** [https://files.pine64.org/doc/datasheet/pinetime/SGMICRO-SGM2036.pdf SGMicro SGM2036 3.3V Low Power Low Dropout RF Linear Regulator Datasheet]&lt;br /&gt;
* SPI Flash information:&lt;br /&gt;
** [https://www.elnec.com/en/device/XTX/XT25F32B+%28QuadSPI%29+%5BSOP8-200%5D/ XTX XT25F32B 32Mb(4MB) SPI NOR Flash] (data sheets for this part are hard to find but it acts similar to other QuadSPI SPI NOR Flash such as [https://www.macronix.com/Lists/Datasheet/Attachments/7426/MX25L3233F,%203V,%2032Mb,%20v1.6.pdf Macronix 32Mb(4MB) SPI NOR Flash])&lt;br /&gt;
** [https://datasheet.lcsc.com/szlcsc/2005251035_XTX-XT25F32BSOIGU-S_C558851.pdf XTX XT25F32B]&lt;br /&gt;
** IDs for XT25F32B are: manufacturer (0x0b), device (0x15), memory type (0x40), density (0x16)&lt;br /&gt;
* LCD Panel:&lt;br /&gt;
** [https://files.pine64.org/doc/datasheet/pinetime/PineTime%20LCD%20Panel.jpg 1.3&amp;quot; 240x240 IPS LCD Panel Specification for PineTime]&lt;br /&gt;
** [https://wiki.pine64.org/images/5/54/ST7789V_v1.6.pdf 11.6&amp;quot; Sitronix LCD Driver/Controller Datasheet]&lt;br /&gt;
* Touchpad information:&lt;br /&gt;
** [https://files.pine64.org/doc/datasheet/pinetime/PineTime%20Touch%20Panel.jpg Touchpad Specification for PineTimel]&lt;br /&gt;
** [https://files.pine64.org/doc/datasheet/pinetime/CST816S数据手册V1.1.pdf 11.6&amp;quot; Hynitron CST816S Capacitive Touch Controller Datasheet in Chinese]&lt;br /&gt;
** [https://wiki.pine64.org/images/2/2f/CST816S.zip Touch Controller Datasheet en]&lt;br /&gt;
* Sensor:&lt;br /&gt;
** [https://files.pine64.org/doc/datasheet/pinetime/BST-BMA421-FL000.pdf BOSCH BMA421 Triaxial VAcceleration Sensor Product Brief]&lt;br /&gt;
** [https://wiki.pine64.org/images/c/cc/Bst-bma400-ds000.pdf BOSCH BMA400 3-axes ultra-low power accelerometer datasheet]&lt;br /&gt;
** [https://files.pine64.org/doc/datasheet/pinetime/HRS3300%20Heart%20Rate%20Sensor.pdf TianYiHeXin HRS3300 PPG Heart Rate Sensor Data Sheet]&lt;br /&gt;
&lt;br /&gt;
[[Category:PineTime]]&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=7335</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=7335"/>
		<updated>2020-09-27T06:51:57Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Creating an Object from the Array */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
[[File:LVGL coord system.png|200px|thumb|right|LVGL coord system]]&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
this image can show you how to decide label placement for lv_obj_set_pos(...)&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be using the flash directly, we need to be considerate about flash memory usage.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
gives you the number of KB the image used in storage...&lt;br /&gt;
&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total storage used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the flash storage with consideration, when using other apps as well, excess usage of storage &lt;br /&gt;
 might mean the Firmware will not compile... the limit to storage to about 400Kb for the user, the &lt;br /&gt;
 firmware size must not exceed that...&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
The LVGL library has a feature that allows you to flip the two bytes of the pixel, so if the two parts were, ...0xB4,0xF5,... ,it will change it to become, ...0xF5,0xB4,...&lt;br /&gt;
&lt;br /&gt;
The reason for this is to allow the use of 8-bit SPI interfaces, but we do not require it, and if set with  wrong parameter we could get problems with the color...&lt;br /&gt;
&lt;br /&gt;
To make sure you are ready for the next step, make sure that inside your lvgl configuration file (located at '''src/libs/lv_conf.h''')&lt;br /&gt;
&lt;br /&gt;
this parameter, &lt;br /&gt;
 '''#define LV_COLOR_16_SWAP   1'''&lt;br /&gt;
is set to &amp;quot;1&amp;quot; as seen...&lt;br /&gt;
&lt;br /&gt;
 NOTE: if you haven't modified it or tampered with it with your Github fork, you shouldn't have a problem &lt;br /&gt;
 as it is correct by default, and you can skip these steps&lt;br /&gt;
&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
To include the Icon, first Identify the Array you need to copy to the source (clock.cpp)&lt;br /&gt;
&lt;br /&gt;
The one we require from it is the data below the tag that looks like,&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
 /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
from this copy the Data from the array alone...&lt;br /&gt;
I.e this part,&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00&lt;br /&gt;
&lt;br /&gt;
(Make sure to not include the comma at the end or the #endif as the entire part is going to substitute a new array)&lt;br /&gt;
&lt;br /&gt;
In clock.cpp, just below the header files and the Task creation part (I.e event_handler...),&lt;br /&gt;
&lt;br /&gt;
 static void event_handler(lv_obj_t * obj, lv_event_t event) {&lt;br /&gt;
 Clock* screen = static_cast&amp;lt;Clock *&amp;gt;(obj-&amp;gt;user_data);&lt;br /&gt;
 screen-&amp;gt;OnObjectEvent(obj, event);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
create a name for the label with,&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;; // remember to replace &amp;lt;name&amp;gt; with the actual name you gave to your image while converting !&lt;br /&gt;
&lt;br /&gt;
then below it create a array to hold the data with,&lt;br /&gt;
 const uint8_t &amp;lt;name&amp;gt;_map[] = {}; // paste the array you copied from the conversion file we specified above...&lt;br /&gt;
&lt;br /&gt;
so your  array is something like,&lt;br /&gt;
&lt;br /&gt;
 const uint8_t &amp;lt;name&amp;gt;_map[] = {0x00,0x00,0x00...&lt;br /&gt;
 ...0x00,0x00,0x00};&lt;br /&gt;
&lt;br /&gt;
so your Entire top region of declaration looks like,&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
 #include &amp;lt;libs/date/includes/date/date.h&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
 using namespace Pinetime::Applications::Screens;&lt;br /&gt;
 extern lv_font_t jetbrains_mono_extrabold_compressed;&lt;br /&gt;
 extern lv_font_t jetbrains_mono_bold_20;&lt;br /&gt;
 extern lv_style_t* LabelBigStyle;&lt;br /&gt;
 '''   '''&lt;br /&gt;
 static void event_handler(lv_obj_t * obj, lv_event_t event) {&lt;br /&gt;
  Clock* screen = static_cast&amp;lt;Clock *&amp;gt;(obj-&amp;gt;user_data);&lt;br /&gt;
  screen-&amp;gt;OnObjectEvent(obj, event);&lt;br /&gt;
 }&lt;br /&gt;
 '''   '''&lt;br /&gt;
 '''//Declare the descriptor here'''&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;;&lt;br /&gt;
 '''//place the Image data here&lt;br /&gt;
 const uint8_t &amp;lt;name&amp;gt;_map[] = {0x00,0x00,0x00...&lt;br /&gt;
 ...0x00,0x00,0x00&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 '''note: Declaring variables outside a function like we did above is known as global scope declaration, this means the variable can be used by not just one function but the Entire code...'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then inside the &lt;br /&gt;
 Clock::Clock(DisplayApp* app,...){... &lt;br /&gt;
region, (the watchface function)&lt;br /&gt;
You need to place a particular set of lines which LVGL uses to define the object declare the array as an Icon/Image, You can place this set of lines above label_time...&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.always_zero = 0; //Initialization&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.w = &amp;lt;picture_X&amp;gt;;                     // Setting the Width (or) Horizontal length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.h = &amp;lt;picture_Y&amp;gt;;                     // Setting the Height (or) vertical length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.data_size = &amp;lt;Hr_length&amp;gt; * &amp;lt;Vr_length&amp;gt; * LV_COLOR_SIZE / 8; //Allocation of memory for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.cf = LV_IMG_CF_TRUE_COLOR; // Sets the color scheme for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.data = &amp;lt;name&amp;gt;_map;                // Maps the Image data to the Array&lt;br /&gt;
  lv_obj_t *img_src = lv_img_create(lv_scr_act(), NULL);  // Create an image object&lt;br /&gt;
  lv_img_set_src(img_src, &amp;amp;&amp;lt;name&amp;gt;);        // Set the created file as image (&amp;lt;name&amp;gt;)&lt;br /&gt;
  &lt;br /&gt;
again, make sure to replace &amp;lt;name&amp;gt; with the name you gave it during conversion!&lt;br /&gt;
&lt;br /&gt;
Now that we have bought in the image data, we need to set the position, you can place this just below the lines we wrote for bringing in the image, It can be done with either,&lt;br /&gt;
 lv_obj_set_pos(img_src, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); // &amp;lt;x_pos&amp;gt;, &amp;lt;y_pos&amp;gt; are the coordinates of the cartesian plane&lt;br /&gt;
or,&lt;br /&gt;
 lv_obj_align(img_src, lv_scr_act(), LV_ALIGN_&amp;lt;parameter&amp;gt;, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); &lt;br /&gt;
&lt;br /&gt;
If done correctly, you will now have a beautiful little Icon/Image in your Watch face,&lt;br /&gt;
Make sure that your Watch face can accommodate the Image by pushing the other labels farther away creating space for it...&lt;br /&gt;
&lt;br /&gt;
We have provided a small template you can use for adding even a large image comfortably&lt;br /&gt;
&lt;br /&gt;
If you have succeeded with this, you have completed part 3 of the tutorial.&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=7334</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=7334"/>
		<updated>2020-09-27T06:50:49Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Creating an Object from the Array */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
[[File:LVGL coord system.png|200px|thumb|right|LVGL coord system]]&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
this image can show you how to decide label placement for lv_obj_set_pos(...)&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be using the flash directly, we need to be considerate about flash memory usage.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
gives you the number of KB the image used in storage...&lt;br /&gt;
&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total storage used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the flash storage with consideration, when using other apps as well, excess usage of storage &lt;br /&gt;
 might mean the Firmware will not compile... the limit to storage to about 400Kb for the user, the &lt;br /&gt;
 firmware size must not exceed that...&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
The LVGL library has a feature that allows you to flip the two bytes of the pixel, so if the two parts were, ...0xB4,0xF5,... ,it will change it to become, ...0xF5,0xB4,...&lt;br /&gt;
&lt;br /&gt;
The reason for this is to allow the use of 8-bit SPI interfaces, but we do not require it, and if set with  wrong parameter we could get problems with the color...&lt;br /&gt;
&lt;br /&gt;
To make sure you are ready for the next step, make sure that inside your lvgl configuration file (located at '''src/libs/lv_conf.h''')&lt;br /&gt;
&lt;br /&gt;
this parameter, &lt;br /&gt;
 '''#define LV_COLOR_16_SWAP   1'''&lt;br /&gt;
is set to &amp;quot;1&amp;quot; as seen...&lt;br /&gt;
&lt;br /&gt;
 NOTE: if you haven't modified it or tampered with it with your Github fork, you shouldn't have a problem &lt;br /&gt;
 as it is correct by default, and you can skip these steps&lt;br /&gt;
&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
To include the Icon, first Identify the Array you need to copy to the source (clock.cpp)&lt;br /&gt;
&lt;br /&gt;
The one we require from it is the data below the tag that looks like,&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
 /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
from this copy the Data from the array alone...&lt;br /&gt;
I.e this part,&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00&lt;br /&gt;
&lt;br /&gt;
(Make sure to not include the comma at the end or the #endif as the entire part is going to substitute a new array)&lt;br /&gt;
&lt;br /&gt;
In clock.cpp, just below the header files and the Task creation part (I.e event_handler...),&lt;br /&gt;
&lt;br /&gt;
 static void event_handler(lv_obj_t * obj, lv_event_t event) {&lt;br /&gt;
 Clock* screen = static_cast&amp;lt;Clock *&amp;gt;(obj-&amp;gt;user_data);&lt;br /&gt;
 screen-&amp;gt;OnObjectEvent(obj, event);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
create a name for the label with,&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;; // remember to replace &amp;lt;name&amp;gt; with the actual name you gave to your image while converting !&lt;br /&gt;
&lt;br /&gt;
then below it create a array to hold the data with,&lt;br /&gt;
 const uint8_t &amp;lt;name&amp;gt;_map[] = {}; // paste the array you copied from the conversion file we specified above...&lt;br /&gt;
&lt;br /&gt;
so your  array is something like,&lt;br /&gt;
&lt;br /&gt;
 const uint8_t &amp;lt;name&amp;gt;_map[] = {0x00,0x00,0x00...&lt;br /&gt;
 ...0x00,0x00,0x00};&lt;br /&gt;
&lt;br /&gt;
so your Entire top region of declaration looks like,&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
 #include &amp;lt;libs/date/includes/date/date.h&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
 using namespace Pinetime::Applications::Screens;&lt;br /&gt;
 extern lv_font_t jetbrains_mono_extrabold_compressed;&lt;br /&gt;
 extern lv_font_t jetbrains_mono_bold_20;&lt;br /&gt;
 extern lv_style_t* LabelBigStyle;&lt;br /&gt;
 '''   '''&lt;br /&gt;
 static void event_handler(lv_obj_t * obj, lv_event_t event) {&lt;br /&gt;
  Clock* screen = static_cast&amp;lt;Clock *&amp;gt;(obj-&amp;gt;user_data);&lt;br /&gt;
  screen-&amp;gt;OnObjectEvent(obj, event);&lt;br /&gt;
 }&lt;br /&gt;
 '''   '''&lt;br /&gt;
 '''//Declare the descriptor here'''&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;;&lt;br /&gt;
 '''//place the Image data here&lt;br /&gt;
 const uint8_t bitmap_map[] = {0x00,0x00,0x00...&lt;br /&gt;
 ...0x00,0x00,0x00&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 '''note: Declaring variables outside a function like we did above is known as global scope declaration, this means the variable can be used by not just one function but the Entire code...'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then inside the &lt;br /&gt;
 Clock::Clock(DisplayApp* app,...){... &lt;br /&gt;
region, (the watchface function)&lt;br /&gt;
You need to place a particular set of lines which LVGL uses to define the object declare the array as an Icon/Image, You can place this set of lines above label_time...&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.always_zero = 0; //Initialization&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.w = &amp;lt;picture_X&amp;gt;;                     // Setting the Width (or) Horizontal length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.h = &amp;lt;picture_Y&amp;gt;;                     // Setting the Height (or) vertical length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.data_size = &amp;lt;Hr_length&amp;gt; * &amp;lt;Vr_length&amp;gt; * LV_COLOR_SIZE / 8; //Allocation of memory for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.cf = LV_IMG_CF_TRUE_COLOR; // Sets the color scheme for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.data = &amp;lt;name&amp;gt;_map;                // Maps the Image data to the Array&lt;br /&gt;
  lv_obj_t *img_src = lv_img_create(lv_scr_act(), NULL);  // Create an image object&lt;br /&gt;
  lv_img_set_src(img_src, &amp;amp;&amp;lt;name&amp;gt;);        // Set the created file as image (&amp;lt;name&amp;gt;)&lt;br /&gt;
  &lt;br /&gt;
again, make sure to replace &amp;lt;name&amp;gt; with the name you gave it during conversion!&lt;br /&gt;
&lt;br /&gt;
Now that we have bought in the image data, we need to set the position, you can place this just below the lines we wrote for bringing in the image, It can be done with either,&lt;br /&gt;
 lv_obj_set_pos(img_src, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); // &amp;lt;x_pos&amp;gt;, &amp;lt;y_pos&amp;gt; are the coordinates of the cartesian plane&lt;br /&gt;
or,&lt;br /&gt;
 lv_obj_align(img_src, lv_scr_act(), LV_ALIGN_&amp;lt;parameter&amp;gt;, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); &lt;br /&gt;
&lt;br /&gt;
If done correctly, you will now have a beautiful little Icon/Image in your Watch face,&lt;br /&gt;
Make sure that your Watch face can accommodate the Image by pushing the other labels farther away creating space for it...&lt;br /&gt;
&lt;br /&gt;
We have provided a small template you can use for adding even a large image comfortably&lt;br /&gt;
&lt;br /&gt;
If you have succeeded with this, you have completed part 3 of the tutorial.&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=7333</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=7333"/>
		<updated>2020-09-27T06:48:51Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Creating an Object from the Array */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
[[File:LVGL coord system.png|200px|thumb|right|LVGL coord system]]&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
this image can show you how to decide label placement for lv_obj_set_pos(...)&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be using the flash directly, we need to be considerate about flash memory usage.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
gives you the number of KB the image used in storage...&lt;br /&gt;
&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total storage used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the flash storage with consideration, when using other apps as well, excess usage of storage &lt;br /&gt;
 might mean the Firmware will not compile... the limit to storage to about 400Kb for the user, the &lt;br /&gt;
 firmware size must not exceed that...&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
The LVGL library has a feature that allows you to flip the two bytes of the pixel, so if the two parts were, ...0xB4,0xF5,... ,it will change it to become, ...0xF5,0xB4,...&lt;br /&gt;
&lt;br /&gt;
The reason for this is to allow the use of 8-bit SPI interfaces, but we do not require it, and if set with  wrong parameter we could get problems with the color...&lt;br /&gt;
&lt;br /&gt;
To make sure you are ready for the next step, make sure that inside your lvgl configuration file (located at '''src/libs/lv_conf.h''')&lt;br /&gt;
&lt;br /&gt;
this parameter, &lt;br /&gt;
 '''#define LV_COLOR_16_SWAP   1'''&lt;br /&gt;
is set to &amp;quot;1&amp;quot; as seen...&lt;br /&gt;
&lt;br /&gt;
 NOTE: if you haven't modified it or tampered with it with your Github fork, you shouldn't have a problem &lt;br /&gt;
 as it is correct by default, and you can skip these steps&lt;br /&gt;
&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
To include the Icon, first Identify the Array you need to copy to the source (clock.cpp)&lt;br /&gt;
&lt;br /&gt;
The one we require from it is the data below the tag that looks like,&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
 /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
from this copy the Data from the array alone...&lt;br /&gt;
I.e this part,&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00&lt;br /&gt;
&lt;br /&gt;
(Make sure to not include the comma at the end or the #endif as the entire part is going to substitute a new array)&lt;br /&gt;
&lt;br /&gt;
In clock.cpp, just below the header files and the Task creation part (I.e event_handler...),&lt;br /&gt;
&lt;br /&gt;
 static void event_handler(lv_obj_t * obj, lv_event_t event) {&lt;br /&gt;
 Clock* screen = static_cast&amp;lt;Clock *&amp;gt;(obj-&amp;gt;user_data);&lt;br /&gt;
 screen-&amp;gt;OnObjectEvent(obj, event);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
create a name for the label with,&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;; // remember to replace &amp;lt;name&amp;gt; with the actual name you gave to your image while converting !&lt;br /&gt;
&lt;br /&gt;
then below it create a array to hold the data with,&lt;br /&gt;
 const uint8_t bitmap_map[] = { &amp;lt;data&amp;gt; }; // paste the array you copied from the conversion file we specified above...&lt;br /&gt;
&lt;br /&gt;
so your Entire top region of declaration looks like,&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
 #include &amp;lt;libs/date/includes/date/date.h&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
 using namespace Pinetime::Applications::Screens;&lt;br /&gt;
 extern lv_font_t jetbrains_mono_extrabold_compressed;&lt;br /&gt;
 extern lv_font_t jetbrains_mono_bold_20;&lt;br /&gt;
 extern lv_style_t* LabelBigStyle;&lt;br /&gt;
 '''   '''&lt;br /&gt;
 static void event_handler(lv_obj_t * obj, lv_event_t event) {&lt;br /&gt;
  Clock* screen = static_cast&amp;lt;Clock *&amp;gt;(obj-&amp;gt;user_data);&lt;br /&gt;
  screen-&amp;gt;OnObjectEvent(obj, event);&lt;br /&gt;
 }&lt;br /&gt;
 '''   '''&lt;br /&gt;
 '''//Declare the descriptor here'''&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;;&lt;br /&gt;
 '''//place the Image data here&lt;br /&gt;
 const uint8_t bitmap_map[] = {0x00,0x00,0x00...&lt;br /&gt;
 ...0x00,0x00,0x00&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 '''note: Declaring variables outside a function like we did above is known as global scope declaration, this means the variable can be used by not just one function but the Entire code...'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then inside the &lt;br /&gt;
 Clock::Clock(DisplayApp* app,...){... &lt;br /&gt;
region, (the watchface function)&lt;br /&gt;
You need to place a particular set of lines which LVGL uses to define the object declare the array as an Icon/Image, You can place this set of lines above label_time...&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.always_zero = 0; //Initialization&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.w = &amp;lt;picture_X&amp;gt;;                     // Setting the Width (or) Horizontal length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.h = &amp;lt;picture_Y&amp;gt;;                     // Setting the Height (or) vertical length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.data_size = &amp;lt;Hr_length&amp;gt; * &amp;lt;Vr_length&amp;gt; * LV_COLOR_SIZE / 8; //Allocation of memory for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.cf = LV_IMG_CF_TRUE_COLOR; // Sets the color scheme for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.data = &amp;lt;name&amp;gt;_map;                // Maps the Image data to the Array&lt;br /&gt;
  lv_obj_t *img_src = lv_img_create(lv_scr_act(), NULL);  // Create an image object&lt;br /&gt;
  lv_img_set_src(img_src, &amp;amp;&amp;lt;name&amp;gt;);        // Set the created file as image (&amp;lt;name&amp;gt;)&lt;br /&gt;
  &lt;br /&gt;
again, make sure to replace &amp;lt;name&amp;gt; with the name you gave it during conversion!&lt;br /&gt;
&lt;br /&gt;
Now that we have bought in the image data, we need to set the position, you can place this just below the lines we wrote for bringing in the image, It can be done with either,&lt;br /&gt;
 lv_obj_set_pos(img_src, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); // &amp;lt;x_pos&amp;gt;, &amp;lt;y_pos&amp;gt; are the coordinates of the cartesian plane&lt;br /&gt;
or,&lt;br /&gt;
 lv_obj_align(img_src, lv_scr_act(), LV_ALIGN_&amp;lt;parameter&amp;gt;, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); &lt;br /&gt;
&lt;br /&gt;
If done correctly, you will now have a beautiful little Icon/Image in your Watch face,&lt;br /&gt;
Make sure that your Watch face can accommodate the Image by pushing the other labels farther away creating space for it...&lt;br /&gt;
&lt;br /&gt;
We have provided a small template you can use for adding even a large image comfortably&lt;br /&gt;
&lt;br /&gt;
If you have succeeded with this, you have completed part 3 of the tutorial.&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=7332</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=7332"/>
		<updated>2020-09-27T06:47:24Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Creating an Object from the Array */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
[[File:LVGL coord system.png|200px|thumb|right|LVGL coord system]]&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
this image can show you how to decide label placement for lv_obj_set_pos(...)&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be using the flash directly, we need to be considerate about flash memory usage.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
gives you the number of KB the image used in storage...&lt;br /&gt;
&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total storage used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the flash storage with consideration, when using other apps as well, excess usage of storage &lt;br /&gt;
 might mean the Firmware will not compile... the limit to storage to about 400Kb for the user, the &lt;br /&gt;
 firmware size must not exceed that...&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
The LVGL library has a feature that allows you to flip the two bytes of the pixel, so if the two parts were, ...0xB4,0xF5,... ,it will change it to become, ...0xF5,0xB4,...&lt;br /&gt;
&lt;br /&gt;
The reason for this is to allow the use of 8-bit SPI interfaces, but we do not require it, and if set with  wrong parameter we could get problems with the color...&lt;br /&gt;
&lt;br /&gt;
To make sure you are ready for the next step, make sure that inside your lvgl configuration file (located at '''src/libs/lv_conf.h''')&lt;br /&gt;
&lt;br /&gt;
this parameter, &lt;br /&gt;
 '''#define LV_COLOR_16_SWAP   1'''&lt;br /&gt;
is set to &amp;quot;1&amp;quot; as seen...&lt;br /&gt;
&lt;br /&gt;
 NOTE: if you haven't modified it or tampered with it with your Github fork, you shouldn't have a problem &lt;br /&gt;
 as it is correct by default, and you can skip these steps&lt;br /&gt;
&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
To include the Icon, first Identify the Array you need to copy to the source (clock.cpp)&lt;br /&gt;
&lt;br /&gt;
The one we require from it is the data below the tag that looks like,&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
 /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
from this copy the Data from the array alone...&lt;br /&gt;
I.e this part,&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00&lt;br /&gt;
&lt;br /&gt;
(Make sure to not include the comma at the end or the #endif as the entire part is going to substitute a new array)&lt;br /&gt;
&lt;br /&gt;
In clock.cpp, just below the header files and the Task creation part (I.e event_handler...),&lt;br /&gt;
&lt;br /&gt;
 static void event_handler(lv_obj_t * obj, lv_event_t event) {&lt;br /&gt;
 Clock* screen = static_cast&amp;lt;Clock *&amp;gt;(obj-&amp;gt;user_data);&lt;br /&gt;
 screen-&amp;gt;OnObjectEvent(obj, event);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
create a name for the label with,&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;; // remember to replace &amp;lt;name&amp;gt; with the actual name you gave to your image while converting !&lt;br /&gt;
&lt;br /&gt;
then below it create a array to hold the data with,&lt;br /&gt;
 const uint8_t bitmap_map[] = {&amp;lt;data&amp;gt;}; // paste the array you copied from the conversion file we specified above...&lt;br /&gt;
&lt;br /&gt;
so your Entire top region of declaration looks like,&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;cstdio&amp;gt;&lt;br /&gt;
 #include &amp;lt;libs/date/includes/date/date.h&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
 using namespace Pinetime::Applications::Screens;&lt;br /&gt;
 extern lv_font_t jetbrains_mono_extrabold_compressed;&lt;br /&gt;
 extern lv_font_t jetbrains_mono_bold_20;&lt;br /&gt;
 extern lv_style_t* LabelBigStyle;&lt;br /&gt;
 '''   '''&lt;br /&gt;
 static void event_handler(lv_obj_t * obj, lv_event_t event) {&lt;br /&gt;
  Clock* screen = static_cast&amp;lt;Clock *&amp;gt;(obj-&amp;gt;user_data);&lt;br /&gt;
  screen-&amp;gt;OnObjectEvent(obj, event);&lt;br /&gt;
 }&lt;br /&gt;
 '''   '''&lt;br /&gt;
 '''//Declare the descriptor here'''&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;;&lt;br /&gt;
 '''//place the Image data here&lt;br /&gt;
 const uint8_t bitmap_map[] = {0x00,0x00,0x00...&lt;br /&gt;
 ...0x00,0x00,0x00&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 '''note: Declaring variables outside a function like we did above is known as global scope declaration, this means the variable can be used by not just one function but the Entire code...'''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then inside the &lt;br /&gt;
 Clock::Clock(DisplayApp* app,...){... &lt;br /&gt;
region, (the watchface function)&lt;br /&gt;
You need to place a particular set of lines which LVGL uses to define the object declare the array as an Icon/Image, You can place this set of lines above label_time...&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.always_zero = 0; //Initialization&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.w = &amp;lt;picture_X&amp;gt;;                     // Setting the Width (or) Horizontal length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.h = &amp;lt;picture_Y&amp;gt;;                     // Setting the Height (or) vertical length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.data_size = &amp;lt;Hr_length&amp;gt; * &amp;lt;Vr_length&amp;gt; * LV_COLOR_SIZE / 8; //Allocation of memory for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.cf = LV_IMG_CF_TRUE_COLOR; // Sets the color scheme for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.data = &amp;lt;name&amp;gt;_map;                // Maps the Image data to the Array&lt;br /&gt;
  lv_obj_t *img_src = lv_img_create(lv_scr_act(), NULL);  // Create an image object&lt;br /&gt;
  lv_img_set_src(img_src, &amp;amp;&amp;lt;name&amp;gt;);        // Set the created file as image (&amp;lt;name&amp;gt;)&lt;br /&gt;
  &lt;br /&gt;
again, make sure to replace &amp;lt;name&amp;gt; with the name you gave it during conversion!&lt;br /&gt;
&lt;br /&gt;
Now that we have bought in the image data, we need to set the position, you can place this just below the lines we wrote for bringing in the image, It can be done with either,&lt;br /&gt;
 lv_obj_set_pos(img_src, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); // &amp;lt;x_pos&amp;gt;, &amp;lt;y_pos&amp;gt; are the coordinates of the cartesian plane&lt;br /&gt;
or,&lt;br /&gt;
 lv_obj_align(img_src, lv_scr_act(), LV_ALIGN_&amp;lt;parameter&amp;gt;, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); &lt;br /&gt;
&lt;br /&gt;
If done correctly, you will now have a beautiful little Icon/Image in your Watch face,&lt;br /&gt;
Make sure that your Watch face can accommodate the Image by pushing the other labels farther away creating space for it...&lt;br /&gt;
&lt;br /&gt;
We have provided a small template you can use for adding even a large image comfortably&lt;br /&gt;
&lt;br /&gt;
If you have succeeded with this, you have completed part 3 of the tutorial.&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=7331</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=7331"/>
		<updated>2020-09-27T03:55:48Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Creating an Object from the Array */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
[[File:LVGL coord system.png|200px|thumb|right|LVGL coord system]]&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
this image can show you how to decide label placement for lv_obj_set_pos(...)&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be using the flash directly, we need to be considerate about flash memory usage.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
gives you the number of KB the image used in storage...&lt;br /&gt;
&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total storage used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the flash storage with consideration, when using other apps as well, excess usage of storage &lt;br /&gt;
 might mean the Firmware will not compile... the limit to storage to about 400Kb for the user, the &lt;br /&gt;
 firmware size must not exceed that...&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
The LVGL library has a feature that allows you to flip the two bytes of the pixel, so if the two parts were, ...0xB4,0xF5,... ,it will change it to become, ...0xF5,0xB4,...&lt;br /&gt;
&lt;br /&gt;
The reason for this is to allow the use of 8-bit SPI interfaces, but we do not require it, and if set with  wrong parameter we could get problems with the color...&lt;br /&gt;
&lt;br /&gt;
To make sure you are ready for the next step, make sure that inside your lvgl configuration file (located at '''src/libs/lv_conf.h''')&lt;br /&gt;
&lt;br /&gt;
this parameter, &lt;br /&gt;
 '''#define LV_COLOR_16_SWAP   1'''&lt;br /&gt;
is set to &amp;quot;1&amp;quot; as seen...&lt;br /&gt;
&lt;br /&gt;
 NOTE: if you haven't modified it or tampered with it with your Github fork, you shouldn't have a problem &lt;br /&gt;
 as it is correct by default, and you can skip these steps&lt;br /&gt;
&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
To include the Icon, first Identify the Array you need to copy to the source (clock.cpp)&lt;br /&gt;
&lt;br /&gt;
The one we require from it is the data below the tag that looks like,&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
 /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
from this copy the Data from the array alone...&lt;br /&gt;
I.e this part,&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00&lt;br /&gt;
&lt;br /&gt;
(Make sure to not include the comma at the end or the #endif as the entire part is going to substitute a new array)&lt;br /&gt;
&lt;br /&gt;
In clock.cpp, just below the header files and the Task creation part (I.e event_handler...),&lt;br /&gt;
create a name for the label with,&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;; // remember to replace &amp;lt;name&amp;gt; with the actual name you gave to your image while converting !&lt;br /&gt;
&lt;br /&gt;
then below it create a array to hold the data with,&lt;br /&gt;
 const uint8_t bitmap_map[] = {&amp;lt;data&amp;gt;}; // paste the array you copied from the conversion file we specified above...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then inside the Clock::Clock(DisplayApp* app,...){... region, &lt;br /&gt;
You need to place a particular set of lines which LVGL uses to define the object declare the array as an Icon/Image, You can place this set of lines above label_time...&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.always_zero = 0; //Initialization&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.w = &amp;lt;picture_X&amp;gt;;                     // Setting the Width (or) Horizontal length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.h = &amp;lt;picture_Y&amp;gt;;                     // Setting the Height (or) vertical length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.data_size = &amp;lt;Hr_length&amp;gt; * &amp;lt;Vr_length&amp;gt; * LV_COLOR_SIZE / 8; //Allocation of memory for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.cf = LV_IMG_CF_TRUE_COLOR; // Sets the color scheme for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.data = &amp;lt;name&amp;gt;_map;                // Maps the Image data to the Array&lt;br /&gt;
  lv_obj_t *img_src = lv_img_create(lv_scr_act(), NULL);  // Create an image object&lt;br /&gt;
  lv_img_set_src(img_src, &amp;amp;&amp;lt;name&amp;gt;);        // Set the created file as image (&amp;lt;name&amp;gt;)&lt;br /&gt;
  &lt;br /&gt;
again, make sure to replace &amp;lt;name&amp;gt; with the name you gave it during conversion!&lt;br /&gt;
&lt;br /&gt;
Now that we have bought in the image data, we need to set the position, you can place this just below the lines we wrote for bringing in the image, It can be done with either,&lt;br /&gt;
 lv_obj_set_pos(img_src, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); // &amp;lt;x_pos&amp;gt;, &amp;lt;y_pos&amp;gt; are the coordinates of the cartesian plane&lt;br /&gt;
or,&lt;br /&gt;
 lv_obj_align(img_src, lv_scr_act(), LV_ALIGN_&amp;lt;parameter&amp;gt;, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); &lt;br /&gt;
&lt;br /&gt;
If done correctly, you will now have a beautiful little Icon/Image in your Watch face,&lt;br /&gt;
Make sure that your Watch face can accommodate the Image by pushing the other labels farther away creating space for it...&lt;br /&gt;
&lt;br /&gt;
We have provided a small template you can use for adding even a large image comfortably&lt;br /&gt;
&lt;br /&gt;
If you have succeeded with this, you have completed part 3 of the tutorial.&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=7273</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=7273"/>
		<updated>2020-09-23T15:01:53Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Label positioning */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
[[File:LVGL coord system.png|200px|thumb|right|LVGL coord system]]&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
this image can show you how to decide label placement for lv_obj_set_pos(...)&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be using the flash directly, we need to be considerate about flash memory usage.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
gives you the number of KB the image used in storage...&lt;br /&gt;
&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total storage used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the flash storage with consideration, when using other apps as well, excess usage of storage &lt;br /&gt;
 might mean the Firmware will not compile... the limit to storage to about 400Kb for the user, the &lt;br /&gt;
 firmware size must not exceed that...&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
The LVGL library has a feature that allows you to flip the two bytes of the pixel, so if the two parts were, ...0xB4,0xF5,... ,it will change it to become, ...0xF5,0xB4,...&lt;br /&gt;
&lt;br /&gt;
The reason for this is to allow the use of 8-bit SPI interfaces, but we do not require it, and if set with  wrong parameter we could get problems with the color...&lt;br /&gt;
&lt;br /&gt;
To make sure you are ready for the next step, make sure that inside your lvgl configuration file (located at '''src/libs/lv_conf.h''')&lt;br /&gt;
&lt;br /&gt;
this parameter, &lt;br /&gt;
 '''#define LV_COLOR_16_SWAP   1'''&lt;br /&gt;
is set to &amp;quot;1&amp;quot; as seen...&lt;br /&gt;
&lt;br /&gt;
 NOTE: if you haven't modified it or tampered with it with your Github fork, you shouldn't have a problem &lt;br /&gt;
 as it is correct by default, and you can skip these steps&lt;br /&gt;
&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
To include the Icon, first Identify the Array you need to copy to the source (clock.cpp)&lt;br /&gt;
&lt;br /&gt;
The one we require from it is the data below the tag that looks like,&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
 /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
from this copy the Data from the array alone...&lt;br /&gt;
I.e this part,&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00&lt;br /&gt;
&lt;br /&gt;
(Make sure to not include the comma at the end or the #endif as the entire part is going to substitute a new array)&lt;br /&gt;
&lt;br /&gt;
In clock.cpp, just below the header files and the Task creation part (I.e event_handler...),&lt;br /&gt;
create a name for the label with,&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;; // remember to replace &amp;lt;name&amp;gt; with the actual name you gave to your image while converting !&lt;br /&gt;
&lt;br /&gt;
then below it create a array to hold the data with,&lt;br /&gt;
 const uint8_t bitmap_map[] = {&amp;lt;data&amp;gt;}; // paste the array you copied from the conversion file we specified above...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then inside the Clock::Clock(DisplayApp* app,...){... region, &lt;br /&gt;
You need to place a particular set of lines which LVGL uses to define the object declare the array as an Icon/Image, You can place this set of lines above label_time...&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.always_zero = 0; //Initialization&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.w = &amp;lt;picture_X&amp;gt;;                     // Setting the Width (or) Horizontal length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.h = &amp;lt;picture_Y&amp;gt;;                     // Setting the Height (or) vertical length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.data_size = &amp;lt;Hr_length&amp;gt; * &amp;lt;Vr_length&amp;gt; * LV_COLOR_SIZE / 8; //Allocation of memory for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.cf = LV_IMG_CF_TRUE_COLOR; // Sets the color scheme for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.data = &amp;lt;name&amp;gt;_map;                // Maps the Image data to the Array&lt;br /&gt;
  lv_obj_t *img_src = lv_img_create(lv_scr_act(), NULL);  // Create an image object&lt;br /&gt;
  lv_img_set_src(img_src, &amp;amp;&amp;lt;name&amp;gt;);        // Set the created file as image (&amp;lt;name&amp;gt;)&lt;br /&gt;
  &lt;br /&gt;
again, make sure to replace &amp;lt;name&amp;gt; with the name you gave it during conversion!&lt;br /&gt;
&lt;br /&gt;
Now that we have bought in the image data, we need to set the position, you can place this just below the lines we wrote for bringing in the image, It can be done with either,&lt;br /&gt;
 lv_obj_set_pos(img_src, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); // &amp;lt;x_pos&amp;gt;, &amp;lt;y_pos&amp;gt; are the coordinates of the cartesian plane&lt;br /&gt;
or,&lt;br /&gt;
 lv_obj_align(img_src, lv_scr_act(), LV_ALIGN_&amp;lt;parameter&amp;gt;, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); &lt;br /&gt;
&lt;br /&gt;
If done correctly, you will now have a beautiful little Icon/Image in your Watch face,&lt;br /&gt;
Make sure that your Watch face can accommodate the Image by pushing the other labels farther away creating space for it...&lt;br /&gt;
&lt;br /&gt;
We have provided a small template you can use for adding even a large image comfortably&lt;br /&gt;
&lt;br /&gt;
If you have succeeded with this, you have completed part 3 of the tutorial.&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=File:LVGL_coord_system.png&amp;diff=7272</id>
		<title>File:LVGL coord system.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=File:LVGL_coord_system.png&amp;diff=7272"/>
		<updated>2020-09-23T14:54:37Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: This displays the coordiniate system used by the lv_set_pos(...) function in LVGL&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
This displays the coordiniate system used by the lv_set_pos(...) function in LVGL&lt;br /&gt;
== Licensing ==&lt;br /&gt;
{{GPL|GPL}}&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6671</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6671"/>
		<updated>2020-08-18T08:46:43Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Image size considerations */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be using the flash directly, we need to be considerate about flash memory usage.&lt;br /&gt;
 &lt;br /&gt;
&amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
gives you the number of KB the image used in storage...&lt;br /&gt;
&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total storage used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the flash storage with consideration, when using other apps as well, excess usage of storage &lt;br /&gt;
 might mean the Firmware will not compile... the limit to storage to about 400Kb for the user, the &lt;br /&gt;
 firmware size must not exceed that...&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
The LVGL library has a feature that allows you to flip the two bytes of the pixel, so if the two parts were, ...0xB4,0xF5,... ,it will change it to become, ...0xF5,0xB4,...&lt;br /&gt;
&lt;br /&gt;
The reason for this is to allow the use of 8-bit SPI interfaces, but we do not require it, and if set with  wrong parameter we could get problems with the color...&lt;br /&gt;
&lt;br /&gt;
To make sure you are ready for the next step, make sure that inside your lvgl configuration file (located at '''src/libs/lv_conf.h''')&lt;br /&gt;
&lt;br /&gt;
this parameter, &lt;br /&gt;
 '''#define LV_COLOR_16_SWAP   1'''&lt;br /&gt;
is set to &amp;quot;1&amp;quot; as seen...&lt;br /&gt;
&lt;br /&gt;
 NOTE: if you haven't modified it or tampered with it with your Github fork, you shouldn't have a problem &lt;br /&gt;
 as it is correct by default, and you can skip these steps&lt;br /&gt;
&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
To include the Icon, first Identify the Array you need to copy to the source (clock.cpp)&lt;br /&gt;
&lt;br /&gt;
The one we require from it is the data below the tag that looks like,&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
 /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
from this copy the Data from the array alone...&lt;br /&gt;
I.e this part,&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00&lt;br /&gt;
&lt;br /&gt;
(Make sure to not include the comma at the end or the #endif as the entire part is going to substitute a new array)&lt;br /&gt;
&lt;br /&gt;
In clock.cpp, just below the header files and the Task creation part (I.e event_handler...),&lt;br /&gt;
create a name for the label with,&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;; // remember to replace &amp;lt;name&amp;gt; with the actual name you gave to your image while converting !&lt;br /&gt;
&lt;br /&gt;
then below it create a array to hold the data with,&lt;br /&gt;
 const uint8_t bitmap_map[] = {&amp;lt;data&amp;gt;}; // paste the array you copied from the conversion file we specified above...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then inside the Clock::Clock(DisplayApp* app,...){... region, &lt;br /&gt;
You need to place a particular set of lines which LVGL uses to define the object declare the array as an Icon/Image, You can place this set of lines above label_time...&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.always_zero = 0; //Initialization&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.w = &amp;lt;picture_X&amp;gt;;                     // Setting the Width (or) Horizontal length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.h = &amp;lt;picture_Y&amp;gt;;                     // Setting the Height (or) vertical length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.data_size = &amp;lt;Hr_length&amp;gt; * &amp;lt;Vr_length&amp;gt; * LV_COLOR_SIZE / 8; //Allocation of memory for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.cf = LV_IMG_CF_TRUE_COLOR; // Sets the color scheme for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.data = &amp;lt;name&amp;gt;_map;                // Maps the Image data to the Array&lt;br /&gt;
  lv_obj_t *img_src = lv_img_create(lv_scr_act(), NULL);  // Create an image object&lt;br /&gt;
  lv_img_set_src(img_src, &amp;amp;&amp;lt;name&amp;gt;);        // Set the created file as image (&amp;lt;name&amp;gt;)&lt;br /&gt;
  &lt;br /&gt;
again, make sure to replace &amp;lt;name&amp;gt; with the name you gave it during conversion!&lt;br /&gt;
&lt;br /&gt;
Now that we have bought in the image data, we need to set the position, you can place this just below the lines we wrote for bringing in the image, It can be done with either,&lt;br /&gt;
 lv_obj_set_pos(img_src, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); // &amp;lt;x_pos&amp;gt;, &amp;lt;y_pos&amp;gt; are the coordinates of the cartesian plane&lt;br /&gt;
or,&lt;br /&gt;
 lv_obj_align(img_src, lv_scr_act(), LV_ALIGN_&amp;lt;parameter&amp;gt;, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); &lt;br /&gt;
&lt;br /&gt;
If done correctly, you will now have a beautiful little Icon/Image in your Watch face,&lt;br /&gt;
Make sure that your Watch face can accommodate the Image by pushing the other labels farther away creating space for it...&lt;br /&gt;
&lt;br /&gt;
We have provided a small template you can use for adding even a large image comfortably&lt;br /&gt;
&lt;br /&gt;
If you have succeeded with this, you have completed part 3 of the tutorial.&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6668</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6668"/>
		<updated>2020-08-18T03:57:24Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Creating an Object from the Array */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be written from internal Flash to the RAM, we need to be considerate as to use less RAM as we are capped at 64KB maximum...&lt;br /&gt;
for testing we did not exceed more than 30% of the 64KB which is about 19.2KB...&lt;br /&gt;
&lt;br /&gt;
You can calculate the RAM usage of your images with a simple formula..&lt;br /&gt;
 &amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
give you the number of KB the image uses...&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total RAM used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the RAM sparingly, too much and the RAM overflow could cause the MCU to crash... you have been warned !!!&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
The LVGL library has a feature that allows you to flip the two bytes of the pixel, so if the two parts were, ...0xB4,0xF5,... ,it will change it to become, ...0xF5,0xB4,...&lt;br /&gt;
&lt;br /&gt;
The reason for this is to allow the use of 8-bit SPI interfaces, but we do not require it, and if set with  wrong parameter we could get problems with the color...&lt;br /&gt;
&lt;br /&gt;
To make sure you are ready for the next step, make sure that inside your lvgl configuration file (located at '''src/libs/lv_conf.h''')&lt;br /&gt;
&lt;br /&gt;
this parameter, &lt;br /&gt;
 '''#define LV_COLOR_16_SWAP   1'''&lt;br /&gt;
is set to &amp;quot;1&amp;quot; as seen...&lt;br /&gt;
&lt;br /&gt;
 NOTE: if you haven't modified it or tampered with it with your Github fork, you shouldn't have a problem &lt;br /&gt;
 as it is correct by default, and you can skip these steps&lt;br /&gt;
&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
To include the Icon, first Identify the Array you need to copy to the source (clock.cpp)&lt;br /&gt;
&lt;br /&gt;
The one we require from it is the data below the tag that looks like,&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
 /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
from this copy the Data from the array alone...&lt;br /&gt;
I.e this part,&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00&lt;br /&gt;
&lt;br /&gt;
(Make sure to not include the comma at the end or the #endif as the entire part is going to substitute a new array)&lt;br /&gt;
&lt;br /&gt;
In clock.cpp, just below the header files and the Task creation part (I.e event_handler...),&lt;br /&gt;
create a name for the label with,&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;; // remember to replace &amp;lt;name&amp;gt; with the actual name you gave to your image while converting !&lt;br /&gt;
&lt;br /&gt;
then below it create a array to hold the data with,&lt;br /&gt;
 const uint8_t bitmap_map[] = {&amp;lt;data&amp;gt;}; // paste the array you copied from the conversion file we specified above...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then inside the Clock::Clock(DisplayApp* app,...){... region, &lt;br /&gt;
You need to place a particular set of lines which LVGL uses to define the object declare the array as an Icon/Image, You can place this set of lines above label_time...&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.always_zero = 0; //Initialization&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.w = &amp;lt;picture_X&amp;gt;;                     // Setting the Width (or) Horizontal length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.h = &amp;lt;picture_Y&amp;gt;;                     // Setting the Height (or) vertical length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.data_size = &amp;lt;Hr_length&amp;gt; * &amp;lt;Vr_length&amp;gt; * LV_COLOR_SIZE / 8; //Allocation of memory for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.cf = LV_IMG_CF_TRUE_COLOR; // Sets the color scheme for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.data = &amp;lt;name&amp;gt;_map;                // Maps the Image data to the Array&lt;br /&gt;
  lv_obj_t *img_src = lv_img_create(lv_scr_act(), NULL);  // Create an image object&lt;br /&gt;
  lv_img_set_src(img_src, &amp;amp;&amp;lt;name&amp;gt;);        // Set the created file as image (&amp;lt;name&amp;gt;)&lt;br /&gt;
  &lt;br /&gt;
again, make sure to replace &amp;lt;name&amp;gt; with the name you gave it during conversion!&lt;br /&gt;
&lt;br /&gt;
Now that we have bought in the image data, we need to set the position, you can place this just below the lines we wrote for bringing in the image, It can be done with either,&lt;br /&gt;
 lv_obj_set_pos(img_src, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); // &amp;lt;x_pos&amp;gt;, &amp;lt;y_pos&amp;gt; are the coordinates of the cartesian plane&lt;br /&gt;
or,&lt;br /&gt;
 lv_obj_align(img_src, lv_scr_act(), LV_ALIGN_&amp;lt;parameter&amp;gt;, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); &lt;br /&gt;
&lt;br /&gt;
If done correctly, you will now have a beautiful little Icon/Image in your Watch face,&lt;br /&gt;
Make sure that your Watch face can accommodate the Image by pushing the other labels farther away creating space for it...&lt;br /&gt;
&lt;br /&gt;
We have provided a small template you can use for adding even a large image comfortably&lt;br /&gt;
&lt;br /&gt;
If you have succeeded with this, you have completed part 3 of the tutorial.&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6667</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6667"/>
		<updated>2020-08-18T03:57:05Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Flipping the bytes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be written from internal Flash to the RAM, we need to be considerate as to use less RAM as we are capped at 64KB maximum...&lt;br /&gt;
for testing we did not exceed more than 30% of the 64KB which is about 19.2KB...&lt;br /&gt;
&lt;br /&gt;
You can calculate the RAM usage of your images with a simple formula..&lt;br /&gt;
 &amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
give you the number of KB the image uses...&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total RAM used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the RAM sparingly, too much and the RAM overflow could cause the MCU to crash... you have been warned !!!&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
The LVGL library has a feature that allows you to flip the two bytes of the pixel, so if the two parts were, ...0xB4,0xF5,... ,it will change it to become, ...0xF5,0xB4,...&lt;br /&gt;
&lt;br /&gt;
The reason for this is to allow the use of 8-bit SPI interfaces, but we do not require it, and if set with  wrong parameter we could get problems with the color...&lt;br /&gt;
&lt;br /&gt;
To make sure you are ready for the next step, make sure that inside your lvgl configuration file (located at '''src/libs/lv_conf.h''')&lt;br /&gt;
&lt;br /&gt;
this parameter, &lt;br /&gt;
 '''#define LV_COLOR_16_SWAP   1'''&lt;br /&gt;
is set to &amp;quot;1&amp;quot; as seen...&lt;br /&gt;
&lt;br /&gt;
 NOTE: if you haven't modified it or tampered with it with your Github fork, you shouldn't have a problem &lt;br /&gt;
 as it is correct by default, and you can skip these steps&lt;br /&gt;
&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
To include the Icon, first Identify the Array you need to copy to the source (clock.cpp)&lt;br /&gt;
&lt;br /&gt;
The one we require from it is the data below the tag that looks like,&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
 /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
from this copy the Data from the array alone...&lt;br /&gt;
I.e this part,&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00&lt;br /&gt;
&lt;br /&gt;
(Make sure to not include the comma at the end or the #endif as the entire part is going to substitute a new array)&lt;br /&gt;
&lt;br /&gt;
In clock.cpp, just below the header files and the Task creation part (I.e event_handler...),&lt;br /&gt;
create a name for the label with,&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;; // remember to replace &amp;lt;name&amp;gt; with the actual name you gave to your image while converting !&lt;br /&gt;
&lt;br /&gt;
then below it create a array to hold the data with,&lt;br /&gt;
 const uint8_t bitmap_map[] = {&amp;lt;data&amp;gt;}; // paste the array you copied from the conversion file we specified above...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then inside the Clock::Clock(DisplayApp* app,...){... region, &lt;br /&gt;
You need to place a particular set of lines which LVGL uses to define the object declare the array as an Icon/Image, You can place this set of lines above label_time...&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.always_zero = 0; //Initialization&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.w = &amp;lt;picture_X&amp;gt;;                     // Setting the Width (or) Horizontal length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.h = &amp;lt;picture_Y&amp;gt;;                     // Setting the Height (or) vertical length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.data_size = &amp;lt;Hr_length&amp;gt; * &amp;lt;Vr_length&amp;gt; * LV_COLOR_SIZE / 8; //Allocation of memory for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.cf = LV_IMG_CF_TRUE_COLOR; // Sets the color scheme for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.data = &amp;lt;name&amp;gt;_map;                // Maps the Image data to the Array&lt;br /&gt;
  lv_obj_t *img_src = lv_img_create(lv_scr_act(), NULL);  // Create an image object&lt;br /&gt;
  lv_img_set_src(img_src, &amp;amp;&amp;lt;name&amp;gt;);        // Set the created file as image (&amp;lt;name&amp;gt;)&lt;br /&gt;
  &lt;br /&gt;
again, make sure to replace &amp;lt;name&amp;gt; with the name you gave it during conversion!&lt;br /&gt;
&lt;br /&gt;
Now that we have bought in the image data, we need to set the position, you can place this just below the lines we wrote for bringing in the image, It can be done with either,&lt;br /&gt;
 lv_obj_set_pos(img_src, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); // &amp;lt;x_pos&amp;gt;, &amp;lt;y_pos&amp;gt; are the coordinates of the cartesian plane&lt;br /&gt;
or,&lt;br /&gt;
 lv_obj_align(img_src, lv_scr_act(), LV_ALIGN_&amp;lt;parameter&amp;gt;, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); &lt;br /&gt;
&lt;br /&gt;
If done correctly, you will now have a beautiful little Icon/Image in your Watch face,&lt;br /&gt;
Make sure that your Watch face can accommodate the Image by pushing the other labels farther away creating space for it...&lt;br /&gt;
&lt;br /&gt;
We have provided a small template you can use for adding even a large image comfortably&lt;br /&gt;
&lt;br /&gt;
If you have succeeded with this, you have completed part 3 of the tutorial.&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6661</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6661"/>
		<updated>2020-08-17T09:16:52Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* RAM vs ROM */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be written from internal Flash to the RAM, we need to be considerate as to use less RAM as we are capped at 64KB maximum...&lt;br /&gt;
for testing we did not exceed more than 30% of the 64KB which is about 19.2KB...&lt;br /&gt;
&lt;br /&gt;
You can calculate the RAM usage of your images with a simple formula..&lt;br /&gt;
 &amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
give you the number of KB the image uses...&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total RAM used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the RAM sparingly, too much and the RAM overflow could cause the MCU to crash... you have been warned !!!&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
The LVGL library has a feature that allows you to flip the two bytes of the pixel, so if the two parts were, ...0xB4,0xF5,... ,it will change it to become, ...0xF5,0xB4,...&lt;br /&gt;
&lt;br /&gt;
The reason for this is to allow the use of 8-bit SPI interfaces, but we do not require it, and if set with  wrong parameter we could get problems with the color...&lt;br /&gt;
&lt;br /&gt;
To make sure you are ready for the next step, make sure that inside your lvgl configuration file (located at '''src/libs/lv_conf.h''')&lt;br /&gt;
&lt;br /&gt;
this parameter, &lt;br /&gt;
 '''#define LV_COLOR_16_SWAP   0'''&lt;br /&gt;
is set to &amp;quot;0&amp;quot; as seen...&lt;br /&gt;
&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
To include the Icon, first Identify the Array you need to copy to the source (clock.cpp)&lt;br /&gt;
&lt;br /&gt;
The one we require from it is the data below the tag that looks like,&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
 /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
from this copy the Data from the array alone...&lt;br /&gt;
I.e this part,&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00&lt;br /&gt;
&lt;br /&gt;
(Make sure to not include the comma at the end or the #endif as the entire part is going to substitute a new array)&lt;br /&gt;
&lt;br /&gt;
In clock.cpp, just below the header files and the Task creation part (I.e event_handler...),&lt;br /&gt;
create a name for the label with,&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;; // remember to replace &amp;lt;name&amp;gt; with the actual name you gave to your image while converting !&lt;br /&gt;
&lt;br /&gt;
then below it create a array to hold the data with,&lt;br /&gt;
 const uint8_t bitmap_map[] = {&amp;lt;data&amp;gt;}; // paste the array you copied from the conversion file we specified above...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then inside the Clock::Clock(DisplayApp* app,...){... region, &lt;br /&gt;
You need to place a particular set of lines which LVGL uses to define the object declare the array as an Icon/Image, You can place this set of lines above label_time...&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.always_zero = 0; //Initialization&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.w = &amp;lt;picture_X&amp;gt;;                     // Setting the Width (or) Horizontal length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.h = &amp;lt;picture_Y&amp;gt;;                     // Setting the Height (or) vertical length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.data_size = &amp;lt;Hr_length&amp;gt; * &amp;lt;Vr_length&amp;gt; * LV_COLOR_SIZE / 8; //Allocation of memory for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.cf = LV_IMG_CF_TRUE_COLOR; // Sets the color scheme for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.data = &amp;lt;name&amp;gt;_map;                // Maps the Image data to the Array&lt;br /&gt;
  lv_obj_t *img_src = lv_img_create(lv_scr_act(), NULL);  // Create an image object&lt;br /&gt;
  lv_img_set_src(img_src, &amp;amp;&amp;lt;name&amp;gt;);        // Set the created file as image (&amp;lt;name&amp;gt;)&lt;br /&gt;
  &lt;br /&gt;
again, make sure to replace &amp;lt;name&amp;gt; with the name you gave it during conversion!&lt;br /&gt;
&lt;br /&gt;
Now that we have bought in the image data, we need to set the position, you can place this just below the lines we wrote for bringing in the image, It can be done with either,&lt;br /&gt;
 lv_obj_set_pos(img_src, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); // &amp;lt;x_pos&amp;gt;, &amp;lt;y_pos&amp;gt; are the coordinates of the cartesian plane&lt;br /&gt;
or,&lt;br /&gt;
 lv_obj_align(img_src, lv_scr_act(), LV_ALIGN_&amp;lt;parameter&amp;gt;, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); &lt;br /&gt;
&lt;br /&gt;
If done correctly, you will now have a beautiful little Icon/Image in your Watch face,&lt;br /&gt;
Make sure that your Watch face can accommodate the Image by pushing the other labels farther away creating space for it...&lt;br /&gt;
&lt;br /&gt;
We have provided a small template you can use for adding even a large image comfortably&lt;br /&gt;
&lt;br /&gt;
If you have succeeded with this, you have completed part 3 of the tutorial.&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6658</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6658"/>
		<updated>2020-08-17T08:17:10Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Creating an Object from the Array */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be written from internal Flash to the RAM, we need to be considerate as to use less RAM as we are capped at 64KB maximum...&lt;br /&gt;
for testing we did not exceed more than 30% of the 64KB which is about 19.2KB...&lt;br /&gt;
&lt;br /&gt;
You can calculate the RAM usage of your images with a simple formula..&lt;br /&gt;
 &amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
give you the number of KB the image uses...&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total RAM used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the RAM sparingly, too much and the RAM overflow could cause the MCU to crash... you have been warned !!!&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
The LVGL library has a feature that allows you to flip the two bytes of the pixel, so if the two parts were, ...0xB4,0xF5,... ,it will change it to become, ...0xF5,0xB4,...&lt;br /&gt;
&lt;br /&gt;
The reason for this is to allow the use of 8-bit SPI interfaces, but we do not require it, and if set with  wrong parameter we could get problems with the color...&lt;br /&gt;
&lt;br /&gt;
To make sure you are ready for the next step, make sure that inside your lvgl configuration file (located at '''src/libs/lv_conf.h''')&lt;br /&gt;
&lt;br /&gt;
this parameter, &lt;br /&gt;
 '''#define LV_COLOR_16_SWAP   0'''&lt;br /&gt;
is set to &amp;quot;0&amp;quot; as seen...&lt;br /&gt;
&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
To include the Icon, first Identify the Array you need to copy to the source (clock.cpp)&lt;br /&gt;
&lt;br /&gt;
The one we require from it is the data below the tag that looks like,&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
 /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
from this copy the Data from the array alone...&lt;br /&gt;
I.e this part,&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00&lt;br /&gt;
&lt;br /&gt;
(Make sure to not include the comma at the end or the #endif as the entire part is going to substitute a new array)&lt;br /&gt;
&lt;br /&gt;
In clock.cpp, just below the header files and the Task creation part (I.e event_handler...),&lt;br /&gt;
create a name for the label with,&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;; // remember to replace &amp;lt;name&amp;gt; with the actual name you gave to your image while converting !&lt;br /&gt;
&lt;br /&gt;
then below it create a array to hold the data with,&lt;br /&gt;
 const uint8_t bitmap_map[] = {&amp;lt;data&amp;gt;}; // paste the array you copied from the conversion file we specified above...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then inside the Clock::Clock(DisplayApp* app,...){... region, &lt;br /&gt;
You need to place a particular set of lines which LVGL uses to define the object declare the array as an Icon/Image, You can place this set of lines above label_time...&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.always_zero = 0; //Initialization&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.w = &amp;lt;picture_X&amp;gt;;                     // Setting the Width (or) Horizontal length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.h = &amp;lt;picture_Y&amp;gt;;                     // Setting the Height (or) vertical length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.data_size = &amp;lt;Hr_length&amp;gt; * &amp;lt;Vr_length&amp;gt; * LV_COLOR_SIZE / 8; //Allocation of memory for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.cf = LV_IMG_CF_TRUE_COLOR; // Sets the color scheme for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.data = &amp;lt;name&amp;gt;_map;                // Maps the Image data to the Array&lt;br /&gt;
  lv_obj_t *img_src = lv_img_create(lv_scr_act(), NULL);  // Create an image object&lt;br /&gt;
  lv_img_set_src(img_src, &amp;amp;&amp;lt;name&amp;gt;);        // Set the created file as image (&amp;lt;name&amp;gt;)&lt;br /&gt;
  &lt;br /&gt;
again, make sure to replace &amp;lt;name&amp;gt; with the name you gave it during conversion!&lt;br /&gt;
&lt;br /&gt;
Now that we have bought in the image data, we need to set the position, you can place this just below the lines we wrote for bringing in the image, It can be done with either,&lt;br /&gt;
 lv_obj_set_pos(img_src, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); // &amp;lt;x_pos&amp;gt;, &amp;lt;y_pos&amp;gt; are the coordinates of the cartesian plane&lt;br /&gt;
or,&lt;br /&gt;
 lv_obj_align(img_src, lv_scr_act(), LV_ALIGN_&amp;lt;parameter&amp;gt;, &amp;lt;x_pos, &amp;lt;y_pos&amp;gt;); &lt;br /&gt;
&lt;br /&gt;
If done correctly, you will now have a beautiful little Icon/Image in your Watch face,&lt;br /&gt;
Make sure that your Watch face can accommodate the Image by pushing the other labels farther away creating space for it...&lt;br /&gt;
&lt;br /&gt;
We have provided a small template you can use for adding even a large image comfortably&lt;br /&gt;
&lt;br /&gt;
If you have succeeded with this, you have completed part 3 of the tutorial.&lt;br /&gt;
&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6657</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6657"/>
		<updated>2020-08-17T08:02:12Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Creating an Object from the Array */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be written from internal Flash to the RAM, we need to be considerate as to use less RAM as we are capped at 64KB maximum...&lt;br /&gt;
for testing we did not exceed more than 30% of the 64KB which is about 19.2KB...&lt;br /&gt;
&lt;br /&gt;
You can calculate the RAM usage of your images with a simple formula..&lt;br /&gt;
 &amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
give you the number of KB the image uses...&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total RAM used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the RAM sparingly, too much and the RAM overflow could cause the MCU to crash... you have been warned !!!&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
The LVGL library has a feature that allows you to flip the two bytes of the pixel, so if the two parts were, ...0xB4,0xF5,... ,it will change it to become, ...0xF5,0xB4,...&lt;br /&gt;
&lt;br /&gt;
The reason for this is to allow the use of 8-bit SPI interfaces, but we do not require it, and if set with  wrong parameter we could get problems with the color...&lt;br /&gt;
&lt;br /&gt;
To make sure you are ready for the next step, make sure that inside your lvgl configuration file (located at '''src/libs/lv_conf.h''')&lt;br /&gt;
&lt;br /&gt;
this parameter, &lt;br /&gt;
 '''#define LV_COLOR_16_SWAP   0'''&lt;br /&gt;
is set to &amp;quot;0&amp;quot; as seen...&lt;br /&gt;
&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
To include the Icon, first Identify the Array you need to copy to the source (clock.cpp)&lt;br /&gt;
&lt;br /&gt;
The one we require from it is the data below the tag that looks like,&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
 /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
from this copy the Data from the array alone...&lt;br /&gt;
I.e this part,&lt;br /&gt;
 0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00&lt;br /&gt;
&lt;br /&gt;
(Make sure to not include the comma at the end or the #endif as the entire part is going to substitute a new array)&lt;br /&gt;
&lt;br /&gt;
In clock.cpp, just below the header files and the Task creation part (I.e event_handler...),&lt;br /&gt;
create a name for the label with,&lt;br /&gt;
 static lv_img_dsc_t &amp;lt;name&amp;gt;; // remember to replace &amp;lt;name&amp;gt; with the actual name you gave to your image while converting !&lt;br /&gt;
&lt;br /&gt;
then below it create a array to hold the data with,&lt;br /&gt;
 const uint8_t bitmap_map[] = {&amp;lt;data&amp;gt;}; // paste the array you copied from the conversion file we specified above...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then inside the Clock::Clock(DisplayApp* app,...){... region, &lt;br /&gt;
You need to place a particular set of lines which LVGL uses to define the object declare the array as an Icon/Image, You can place this set of lines above label_time...&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.always_zero = 0; //Initialization&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.w = &amp;lt;Hr_length&amp;gt;;                     // Setting the Width (or) Horizontal length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.h = &amp;lt;Vr_length&amp;gt;;                     // Setting the Height (or) vertical length of the image (number of px)&lt;br /&gt;
  &amp;lt;name&amp;gt;.data_size = &amp;lt;Hr_length&amp;gt; * &amp;lt;Vr_length&amp;gt; * LV_COLOR_SIZE / 8; //Allocation of memory for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.header.cf = LV_IMG_CF_TRUE_COLOR; // Sets the color scheme for the image&lt;br /&gt;
  &amp;lt;name&amp;gt;.data = &amp;lt;name&amp;gt;_map;                // Maps the Image data to the Array&lt;br /&gt;
  lv_obj_t *img_src = lv_img_create(lv_scr_act(), NULL);  // Create an image object&lt;br /&gt;
  lv_img_set_src(img_src, &amp;amp;&amp;lt;name&amp;gt;);        // Set the created file as image (&amp;lt;name&amp;gt;)&lt;br /&gt;
  &lt;br /&gt;
again, make sure to replace &amp;lt;name&amp;gt; with the name you gave it during conversion!&lt;br /&gt;
&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6655</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6655"/>
		<updated>2020-08-17T06:31:46Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Flipping the bytes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be written from internal Flash to the RAM, we need to be considerate as to use less RAM as we are capped at 64KB maximum...&lt;br /&gt;
for testing we did not exceed more than 30% of the 64KB which is about 19.2KB...&lt;br /&gt;
&lt;br /&gt;
You can calculate the RAM usage of your images with a simple formula..&lt;br /&gt;
 &amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
give you the number of KB the image uses...&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total RAM used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the RAM sparingly, too much and the RAM overflow could cause the MCU to crash... you have been warned !!!&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
The LVGL library has a feature that allows you to flip the two bytes of the pixel, so if the two parts were, ...0xB4,0xF5,... ,it will change it to become, ...0xF5,0xB4,...&lt;br /&gt;
&lt;br /&gt;
The reason for this is to allow the use of 8-bit SPI interfaces, but we do not require it, and if set with  wrong parameter we could get problems with the color...&lt;br /&gt;
&lt;br /&gt;
To make sure you are ready for the next step, make sure that inside your lvgl configuration file (located at '''src/libs/lv_conf.h''')&lt;br /&gt;
&lt;br /&gt;
this parameter, &lt;br /&gt;
 '''#define LV_COLOR_16_SWAP   0'''&lt;br /&gt;
is set to &amp;quot;0&amp;quot; as seen...&lt;br /&gt;
&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6654</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6654"/>
		<updated>2020-08-17T06:31:12Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Flipping the bytes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be written from internal Flash to the RAM, we need to be considerate as to use less RAM as we are capped at 64KB maximum...&lt;br /&gt;
for testing we did not exceed more than 30% of the 64KB which is about 19.2KB...&lt;br /&gt;
&lt;br /&gt;
You can calculate the RAM usage of your images with a simple formula..&lt;br /&gt;
 &amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
give you the number of KB the image uses...&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total RAM used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the RAM sparingly, too much and the RAM overflow could cause the MCU to crash... you have been warned !!!&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
The LVGL library has a feature that allows you to flip the two bytes of the pixel, so if the two parts were, ...0xB4,0xF5,... ,it will change it to become, ...0xF5,0xB4,...&lt;br /&gt;
&lt;br /&gt;
The reason for this is to allow the use of 8-bit SPI interfaces, but we do not require it, and if set with  wrong parameter we could get problems with the color...&lt;br /&gt;
&lt;br /&gt;
To make sure you are ready for the next step, make sure that inside your lvgl configuration file (located at src/libs/lv_conf.h)&lt;br /&gt;
&lt;br /&gt;
this parameter, &lt;br /&gt;
 #define LV_COLOR_16_SWAP   0&lt;br /&gt;
is set to &amp;quot;0&amp;quot; as seen...&lt;br /&gt;
&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6651</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6651"/>
		<updated>2020-08-17T06:04:48Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Preparing the image for inclusion as an icon */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be written from internal Flash to the RAM, we need to be considerate as to use less RAM as we are capped at 64KB maximum...&lt;br /&gt;
for testing we did not exceed more than 30% of the 64KB which is about 19.2KB...&lt;br /&gt;
&lt;br /&gt;
You can calculate the RAM usage of your images with a simple formula..&lt;br /&gt;
 &amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
give you the number of KB the image uses...&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total RAM used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the RAM sparingly, too much and the RAM overflow could cause the MCU to crash... you have been warned !!!&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
&lt;br /&gt;
Once you have your obtained your C array from the LVGL converter, you can take a look inside it to see all the different formats of your image, &lt;br /&gt;
try using something like Notepad++ or any of your favorite text editors to peek inside of it,&lt;br /&gt;
 &lt;br /&gt;
there will be 4 sets of Arrays inside it that look like,&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 1 || LV_COLOR_DEPTH == 8&lt;br /&gt;
  /*Pixel format: Red: 3 bit, Green: 3 bit, Blue: 2 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP == 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 16 &amp;amp;&amp;amp; LV_COLOR_16_SWAP != 0&lt;br /&gt;
  /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit BUT the 2 bytes are swapped*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0x00, &lt;br /&gt;
 #endif&lt;br /&gt;
&lt;br /&gt;
 #if LV_COLOR_DEPTH == 32&lt;br /&gt;
  /*Pixel format: Fix 0xFF: 8 bit, Red: 8 bit, Green: 8 bit, Blue: 8 bit*/&lt;br /&gt;
  0x00, 0x00, 0x00,...&lt;br /&gt;
 ...0x00, 0x00, 0xff, &lt;br /&gt;
 #endif&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
And another small bit of info we will need for later that looks like,&lt;br /&gt;
&lt;br /&gt;
 const lv_img_dsc_t bitmap = {&lt;br /&gt;
  .header.always_zero = 0,&lt;br /&gt;
  .header.w = 40,&lt;br /&gt;
  .header.h = 40,&lt;br /&gt;
  .data_size = 1600 * LV_COLOR_SIZE / 8,&lt;br /&gt;
  .header.cf = LV_IMG_CF_TRUE_COLOR,&lt;br /&gt;
  .data = bitmap_map,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 NOTE: There are some header files at the top, which we can ignore...&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
&lt;br /&gt;
The Pinetime uses a display that uses a 16 bit color space, also known as RGB565.&lt;br /&gt;
&lt;br /&gt;
These 16 bit are assigned to RGB as 5 bits each for Red and Blue and 6 bits for Green, so 5+6+5=16 bits are required, so each pixel's color occupies 2 bytes of data,&lt;br /&gt;
and since 2&amp;lt;sup&amp;gt;16&amp;lt;/sup&amp;gt; is equal to 65,536 it allows us to view 65,536 or 65k colors&lt;br /&gt;
&lt;br /&gt;
The way it packs these bits is by converting the bits into 2x  4+4 bit hex-code, so for example,&lt;br /&gt;
 &lt;br /&gt;
if the color of a pixel in Binary is '''10110100 01011111''' (this color is approximately Lavender purple)&lt;br /&gt;
 &lt;br /&gt;
It is split as '''1011''' &amp;amp; '''0100''' for the first byte and '''0101''' &amp;amp; '''1111''' for the second byte&lt;br /&gt;
and so, converting the binary into Hex-code,&lt;br /&gt;
&lt;br /&gt;
the two parts are '''0xB4''' and '''0xF5'''&lt;br /&gt;
&lt;br /&gt;
These two parts in conjunction are used for determining the color of one pixel...&lt;br /&gt;
&lt;br /&gt;
also from the binary, it is observed that,&lt;br /&gt;
&lt;br /&gt;
The bits '''10110''' is used for Red, '''100010''' is used for green, and '''11111''' is used for blue.&lt;br /&gt;
&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===Creating an Object from the Array===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6613</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6613"/>
		<updated>2020-08-15T15:36:08Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Using icons */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
The LVGL library allows for the use of widgets known as &amp;quot;Images&amp;quot;, In short it allows you to use small Icons like pictures with a small dedicated function,&lt;br /&gt;
However when this was attempted the first time we stumbled on some problems as LVGL v6 (used on the pinetime) is not much documented as the latest release (v7 as of August 2020) &lt;br /&gt;
but also the existing code was only documented for C not C++, after some painful attempts we were able to translate it into C++, &lt;br /&gt;
&lt;br /&gt;
To bring images into Clock.cpp&lt;br /&gt;
you will need to do the following,&lt;br /&gt;
&lt;br /&gt;
1. Have a small image that cannot exceed a maximum size of 240px x 240px (pinetime max resolution)&lt;br /&gt;
&lt;br /&gt;
2. Use this Image converter (Thanks to LVGL) https://lvgl.io/tools/imageconverter&lt;br /&gt;
to convert your image to a C array and having the Color format as &amp;quot;True color&amp;quot; and the output format as &amp;quot;C array&amp;quot;&lt;br /&gt;
make sure to use something simple as the name we will be using &amp;quot;bitmap&amp;quot; as the name, but will also be referred as &amp;lt;name&amp;gt; for simplicity&lt;br /&gt;
&lt;br /&gt;
 Note: for example we shall use &amp;lt;name&amp;gt; = bitmap, but any simple word can be used, as long as it does not cause problems with system variables&lt;br /&gt;
&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
since the image will be written from internal Flash to the RAM, we need to be considerate as to use less RAM as we are capped at 64KB maximum...&lt;br /&gt;
for testing we did not exceed more than 30% of the 64KB which is about 19.2KB...&lt;br /&gt;
&lt;br /&gt;
You can calculate the RAM usage of your images with a simple formula..&lt;br /&gt;
 &amp;lt;picture_X&amp;gt; x &amp;lt;picture_Y&amp;gt; x 2 &lt;br /&gt;
give you the number of KB the image uses...&lt;br /&gt;
where, &amp;lt;picture_X&amp;gt; &amp;lt;picture_Y&amp;gt; are the dimensions of the image horizontally and vertically&lt;br /&gt;
&lt;br /&gt;
for example,&lt;br /&gt;
 if &amp;lt;picture_X&amp;gt;=80px &amp;lt;picture_Y&amp;gt;=64px&lt;br /&gt;
then,&lt;br /&gt;
 total RAM used = 80 x 60 x 2 = 10.24KB &lt;br /&gt;
&lt;br /&gt;
 please use the RAM sparingly, too much and the RAM overflow could cause the MCU to crash... you have been warned !!!&lt;br /&gt;
&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
&lt;br /&gt;
A holistic guide on how to install different firmware using various hardware programmers is available here: [[Reprogramming the PineTime]]. There's also the possibility of using OTA updating. ''//TODO: add that to the article!''&lt;br /&gt;
&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=User:Electr0lyte&amp;diff=6612</id>
		<title>User:Electr0lyte</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=User:Electr0lyte&amp;diff=6612"/>
		<updated>2020-08-15T15:07:29Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: Basic Info&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Computer and Embedded electronics Enthusiast (⌐■_■)&lt;br /&gt;
&lt;br /&gt;
Follow me on twitter, https://twitter.com/SravanSenthiln1&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6601</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6601"/>
		<updated>2020-08-14T15:35:14Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Label positioning */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position of labels..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6600</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6600"/>
		<updated>2020-08-14T15:34:09Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Label positioning */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
now let's try something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
&lt;br /&gt;
you can alternatively swap the whole line to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6599</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6599"/>
		<updated>2020-08-14T15:30:54Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Label positioning */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and '''&amp;lt;text/obj&amp;gt;''' is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
here is something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
you can alternatively change it to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6598</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6598"/>
		<updated>2020-08-14T15:29:22Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Label positioning */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
'''&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;''' are the cartesian coordinates, '''&amp;lt;location parameter&amp;gt;''' is replaced by '''LV_ALIGN_&amp;lt;preset&amp;gt;''',&lt;br /&gt;
there will be a picture showing the presets below, and &amp;lt;text/obj&amp;gt; is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
here is something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
you can alternatively change it to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6597</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6597"/>
		<updated>2020-08-14T15:28:26Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Modifying label data */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt; are the cartesian coordinates, &amp;lt;location parameter&amp;gt; is replaced by LV_ALIGN_&amp;lt;preset&amp;gt;,&lt;br /&gt;
there will be a picture showing the presets below, and &amp;lt;text/obj&amp;gt; is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
here is something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
you can alternatively change it to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6596</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6596"/>
		<updated>2020-08-14T15:11:34Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Label positioning */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top left corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt; are the cartesian coordinates, &amp;lt;location parameter&amp;gt; is replaced by LV_ALIGN_&amp;lt;preset&amp;gt;,&lt;br /&gt;
there will be a picture showing the presets below, and &amp;lt;text/obj&amp;gt; is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here is a small example.&lt;br /&gt;
&lt;br /&gt;
Take the Label that tells the date,&lt;br /&gt;
In the source file (clock.cpp) it is this line,&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 60);&lt;br /&gt;
by increasing the Value of the Y coordinate (60) to a higher value, we can bring the position of the Date downwards a bit away from the Time, and toward the Heartbeat count in the bottom row&lt;br /&gt;
here I will increase it to 80, so it becomes..&lt;br /&gt;
 lv_obj_align(label_date, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 80);&lt;br /&gt;
&lt;br /&gt;
and now we have made some space up top..&lt;br /&gt;
&lt;br /&gt;
here is something a bit complex,&lt;br /&gt;
&lt;br /&gt;
Take the position argument for the label that tells you time...&lt;br /&gt;
here, in the source file (clock.cpp),&lt;br /&gt;
 lv_obj_align(label_time, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this line determines the position of the Label telling time, as seen in the image...&lt;br /&gt;
&lt;br /&gt;
we modifying this, by changing the origin &amp;lt;preset&amp;gt; parameter (here it is LV_ALIGN_IN_LEFT_MID) to LV_ALIGN_IN_TOP_LEFT&lt;br /&gt;
you can alternatively change it to,&lt;br /&gt;
 lv_obj_set_pos(label_time, 0, 0);&lt;br /&gt;
&lt;br /&gt;
this makes the Time label/obj. to go to the top left corner...&lt;br /&gt;
&lt;br /&gt;
but I will do something a little extra,&lt;br /&gt;
I will modify the label that store the data and Time format,&lt;br /&gt;
i.e this line,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c:%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
by removing the &amp;quot;:&amp;quot; colon in between the numbers, and replacing it with a Newline symbol &amp;quot;\n&amp;quot;&lt;br /&gt;
I change it to become,&lt;br /&gt;
 sprintf(timeStr, &amp;quot;%c%c\n%c%c&amp;quot;, hoursChar[0],hoursChar[1],minutesChar[0], minutesChar[1]);&lt;br /&gt;
&lt;br /&gt;
this gives it a nice wrapped text format in the top corner, and gives us some space to play with in the side, for things like Pictures and icons, which we will do next..&lt;br /&gt;
&lt;br /&gt;
If you have been able to do these things, you now have completed the 2nd part of the tutorial, and now know how to change and modify the position..&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6594</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6594"/>
		<updated>2020-08-14T14:37:45Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Label positioning */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
and the top right corner is the Cartesian origin, aka coordinates (0,0)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt; are the cartesian coordinates, &amp;lt;location parameter&amp;gt; is replaced by LV_ALIGN_&amp;lt;preset&amp;gt;,&lt;br /&gt;
there will be a picture showing the presets below, and &amp;lt;text/obj&amp;gt; is your text label...&lt;br /&gt;
&lt;br /&gt;
here, LV_ALIGN_&amp;lt;preset&amp;gt; sets the cartesian origin...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6578</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6578"/>
		<updated>2020-08-14T06:53:04Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Label positioning */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
&lt;br /&gt;
The locational placement in LVGL is done on a cartesian plane,&lt;br /&gt;
where each object can have dynamic origin placement, and the Y-axis is inverted...&lt;br /&gt;
So going down is done with a positive Y-axis value and not negative as the it is by de-facto...&lt;br /&gt;
&lt;br /&gt;
The position of the various objects in clock.cpp are set by the line,&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
we use another function, that is more advanced that gives the positional alignment based on preset locations...&lt;br /&gt;
 lv_obj_align(&amp;lt;text/obj&amp;gt;, &amp;lt;image/obj&amp;gt;, &amp;lt;location_parameter&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
the &amp;quot;&amp;lt;image/obj&amp;gt;&amp;quot; data is used for putting text beside other picture icons , and so if using only text based labels, we can substitute it with,&lt;br /&gt;
 lv_scr_act() (or) NULL&lt;br /&gt;
&lt;br /&gt;
&amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt; are the cartesian coordinates, &amp;lt;location parameter&amp;gt; is replaced by LV_ALIGN_&amp;lt;preset&amp;gt;,&lt;br /&gt;
there will be a picture showing the presets below, and &amp;lt;text/obj&amp;gt; is your text label...&lt;br /&gt;
&lt;br /&gt;
Label positioning based on alignment is both a simple and complicated thing to understand, so here I have given something you can refer to while modifying the position of the various labels and objects...&lt;br /&gt;
&lt;br /&gt;
you can also refer here for LVGL's documentation of coordinate system https://docs.lvgl.io/v6/en/html/object-types/obj.html#coordinates&lt;br /&gt;
&lt;br /&gt;
It is however recommended that you use the first method to set the location&lt;br /&gt;
 lv_obj_set_pos(&amp;lt;obj&amp;gt;, &amp;lt;new_x&amp;gt;, &amp;lt;new_y&amp;gt;)&lt;br /&gt;
as it is simple and easier for beginners&lt;br /&gt;
&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6555</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6555"/>
		<updated>2020-08-13T09:27:53Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Modifying label data */  (completed)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek), and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
It is because the system gives the date/ time as numbers (Monday-1, Tuesday-2 Wednesday-3 for the days, and 1-January, 2-February, 3-March ),&lt;br /&gt;
and so a function along with a C array is used to assign these numbers to Days/Months in text form as it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
while doing so, we can even make the months use small letters as said before..&lt;br /&gt;
&lt;br /&gt;
so the source file (clock.cpp) becomes,&lt;br /&gt;
&lt;br /&gt;
(for the days of the week)&lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;mon.&amp;quot;,&lt;br /&gt;
        &amp;quot;tue.&amp;quot;,&lt;br /&gt;
        &amp;quot;wed.&amp;quot;,&lt;br /&gt;
        &amp;quot;thu.&amp;quot;,&lt;br /&gt;
        &amp;quot;fri.&amp;quot;,&lt;br /&gt;
        &amp;quot;sat.&amp;quot;,&lt;br /&gt;
        &amp;quot;sun.&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and&lt;br /&gt;
&lt;br /&gt;
(for the months of the year)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;jan&amp;quot;,&lt;br /&gt;
        &amp;quot;feb&amp;quot;,&lt;br /&gt;
        &amp;quot;mar&amp;quot;,&lt;br /&gt;
        &amp;quot;apr&amp;quot;,&lt;br /&gt;
        &amp;quot;may&amp;quot;,&lt;br /&gt;
        &amp;quot;jun&amp;quot;,&lt;br /&gt;
        &amp;quot;jul&amp;quot;,&lt;br /&gt;
        &amp;quot;aug&amp;quot;,&lt;br /&gt;
        &amp;quot;sep&amp;quot;,&lt;br /&gt;
        &amp;quot;oct&amp;quot;,&lt;br /&gt;
        &amp;quot;nov&amp;quot;,&lt;br /&gt;
        &amp;quot;dec&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
which means now our original date, saturday 11/7/2020 will become...&lt;br /&gt;
 sat. 11 jul, 2020&lt;br /&gt;
&lt;br /&gt;
you now know how to change the data present in a label object, and the format of it..,&lt;br /&gt;
 &lt;br /&gt;
Here is a fun idea you can try: you can even replace the days with whatever thing that tells you (or) reminds you the day of the week &lt;br /&gt;
(like the food served in the cafe, Monday/taco, Tuesday/burger, Wednesday/pasta etc.) &lt;br /&gt;
 &lt;br /&gt;
 NOTE: when making the custom array, don't forget to leave a empty &amp;quot;&amp;quot; as the first element of the array,&lt;br /&gt;
 This is because the date is given by the system in a natural numbers format (1,2,3...) rather than a zero-starting format (0,1,2,3...), which the C array uses to index...&lt;br /&gt;
 so the C array indexes the days as &amp;quot;&amp;quot;-0, &amp;quot;Monday&amp;quot;-1, &amp;quot;Tuesday&amp;quot;-2 etc. and the months as &amp;quot;&amp;quot;-0, &amp;quot;January&amp;quot;-1, &amp;quot;February&amp;quot;-2 etc.)&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6554</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6554"/>
		<updated>2020-08-13T07:59:29Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: label modification&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
Now, &lt;br /&gt;
if the date was a saturday 11/7/2020, you can observe that the date looks like &lt;br /&gt;
 SATURDAY 11 JUL 2020&lt;br /&gt;
as seen in the above image (the one where we changed BPM to LOVE)&lt;br /&gt;
&lt;br /&gt;
by modifying the format of the variables, we can change how those words are arranged, and add some extra characters if we like... &lt;br /&gt;
 (there is a catch to the list of characters you can use however, but it will be discussed later...)&lt;br /&gt;
&lt;br /&gt;
For example,&lt;br /&gt;
&lt;br /&gt;
We modifying the format by adding a comma... &amp;quot;,&amp;quot; in between the second &amp;quot;%s&amp;quot; and &amp;quot;%d&amp;quot; like this,&lt;br /&gt;
 &amp;quot;%s %d %s, %d&amp;quot;&lt;br /&gt;
and changing that in the line...&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s, %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
&lt;br /&gt;
we can make the date become...&lt;br /&gt;
 SATURDAY 11 JUL, 2020&lt;br /&gt;
&lt;br /&gt;
which means we now were able to modify how the text got display to make it a bit more nice...&lt;br /&gt;
&lt;br /&gt;
but if you haven't noticed, the line containing the date is already full, meaning we will get some problems while displaying the date and causing it to wrap around,&lt;br /&gt;
making a single character go to the next line and look more like,&lt;br /&gt;
&lt;br /&gt;
 SATURDAY 11 JUL, 202&lt;br /&gt;
 0&lt;br /&gt;
&lt;br /&gt;
so why don't we shorten the characters present in the date from being &amp;quot;SATURDAY&amp;quot; to simply just &amp;quot;sat.&amp;quot; (It will have the small period at the end, and is only 3 characters long) &lt;br /&gt;
I will also convert the months of the year from Capital to small letters ... &lt;br /&gt;
&lt;br /&gt;
for that look into the part where the days of the week of are stored as text,&lt;br /&gt;
and also while looking at it, we can solve another question, why was their two variables in the date format that looked like, DayOfWeekToString(dayOfWeek) ,and MonthToString(month) ?&lt;br /&gt;
&lt;br /&gt;
well it is because the system gives the dates as numbers... and here in the watchface, we assign those numbers to strings showing the actual &amp;quot;day&amp;quot; and &amp;quot;month&amp;quot;&lt;br /&gt;
so it is easier to read...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
this is the Array containing the day of the week, (as text) &lt;br /&gt;
 char const *Clock::DaysString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;MONDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;TUESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;WEDNESDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;THURSDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;FRIDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SATURDAY&amp;quot;,&lt;br /&gt;
        &amp;quot;SUNDAY&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
and this Array stores the months of the year, (as text)&lt;br /&gt;
 char const *Clock::MonthsString[] = {&lt;br /&gt;
        &amp;quot;&amp;quot;,&lt;br /&gt;
        &amp;quot;JAN&amp;quot;,&lt;br /&gt;
        &amp;quot;FEB&amp;quot;,&lt;br /&gt;
        &amp;quot;MAR&amp;quot;,&lt;br /&gt;
        &amp;quot;APR&amp;quot;,&lt;br /&gt;
        &amp;quot;MAY&amp;quot;,&lt;br /&gt;
        &amp;quot;JUN&amp;quot;,&lt;br /&gt;
        &amp;quot;JUL&amp;quot;,&lt;br /&gt;
        &amp;quot;AUG&amp;quot;,&lt;br /&gt;
        &amp;quot;SEP&amp;quot;,&lt;br /&gt;
        &amp;quot;OCT&amp;quot;,&lt;br /&gt;
        &amp;quot;NOV&amp;quot;,&lt;br /&gt;
        &amp;quot;DEC&amp;quot;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
here we can see that the days are stored in a full format as &amp;quot;SUNDAY&amp;quot;, &amp;quot;MONDAY&amp;quot;, &amp;quot;TUESDAY&amp;quot; etc.&lt;br /&gt;
we can change all of them to a shorter format like &amp;quot;sun.&amp;quot;, &amp;quot;mon.&amp;quot;, &amp;quot;tue.&amp;quot;, to make it short and nice...&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6542</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6542"/>
		<updated>2020-08-12T09:48:26Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: modification of label data (not finished)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now take for in instance the days of the week that we have on the bottom line with the date...&lt;br /&gt;
&lt;br /&gt;
they are stored a &amp;quot;C array&amp;quot; which is basically multiple words separated by commas..&lt;br /&gt;
the date is in a format of '''&amp;lt;day of the week&amp;gt; &amp;lt;day&amp;gt; &amp;lt;Month&amp;gt; &amp;lt;year&amp;gt;&lt;br /&gt;
&lt;br /&gt;
which in the source file is expressed as,&lt;br /&gt;
 sprintf(dateStr, &amp;quot;%s %d %s %d&amp;quot;, DayOfWeekToString(dayOfWeek), day, MonthToString(month), year);&lt;br /&gt;
 lv_label_set_text(label_date, dateStr);&lt;br /&gt;
&lt;br /&gt;
here, &lt;br /&gt;
 %s %d %s %d &lt;br /&gt;
stores the print format of the variables, and&lt;br /&gt;
&lt;br /&gt;
 DayOfWeekToString(dayOfWeek), day, MonthToString(month), year  &lt;br /&gt;
are the variables themselves...&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6541</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6541"/>
		<updated>2020-08-12T06:15:11Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Modifying label data */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:PineTimeCustom-1.png|right|200px]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface! Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6540</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6540"/>
		<updated>2020-08-12T06:06:27Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Modifying label data */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:https://wiki.pine64.org/images/6/67/PineTimeCustom-1.png]]&lt;br /&gt;
&lt;br /&gt;
If we take a look at the source file of the watchface, (a.k.a the clock.cpp file)&lt;br /&gt;
we can observe that these particular lines are what attributes to the word &amp;quot;BPM being displayed...&lt;br /&gt;
 heartbeatBpm = lv_label_create(lv_scr_act(), NULL);&lt;br /&gt;
 lv_label_set_text(heartbeatBpm, &amp;quot;BPM&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
we can modify the text inside the quotes and replace the word 'BPM' between those quotes to something like 'LOVE'&lt;br /&gt;
and the result after compiling the firmware again with the changes and flashing it to the watch would be that the text changes on the watch face and displays 'LOVE' inplace of 'BPM'...&lt;br /&gt;
&lt;br /&gt;
If this happened correctly, then you have successfully made a custom new watchface. Now we can do something a bit more complex...&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6539</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6539"/>
		<updated>2020-08-12T05:54:06Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Overview */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The main file we need to focus on is the '''clock.cpp''' file, it is what contains most of the data attributed to what we see on the watchface, including The time/day characters, the battery and bluetooth icons, and also pedometer count...&lt;br /&gt;
&lt;br /&gt;
so everything we will be doing in the basic modifications is purely messing with this single file.&lt;br /&gt;
&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:https://wiki.pine64.org/images/6/67/PineTimeCustom-1.png]]&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6538</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6538"/>
		<updated>2020-08-12T05:28:48Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: adding image&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:https://wiki.pine64.org/images/6/67/PineTimeCustom-1.png]]&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6537</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6537"/>
		<updated>2020-08-12T05:27:57Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: adding image&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:https://wiki.pine64.org/images/6/67/PineTimeCustom-1.png|200px|thumb|left|alt text]]&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6536</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6536"/>
		<updated>2020-08-12T05:26:50Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: adding image&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[file:https://wiki.pine64.org/images/6/67/PineTimeCustom-1.png]]&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6535</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6535"/>
		<updated>2020-08-12T05:21:47Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Modifying label data */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
[[https://wiki.pine64.org/images/6/67/PineTimeCustom-1.png]]&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=File:PineTimeCustom-1.png&amp;diff=6534</id>
		<title>File:PineTimeCustom-1.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=File:PineTimeCustom-1.png&amp;diff=6534"/>
		<updated>2020-08-12T05:17:02Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: picture (1) in the pinetime custom tutorial&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Summary ==&lt;br /&gt;
picture (1) in the pinetime custom tutorial&lt;br /&gt;
== Licensing ==&lt;br /&gt;
{{subst:Unknown_copyright}}&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6533</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6533"/>
		<updated>2020-08-12T05:14:01Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* Modifying label data */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
let's observe something small like the word &amp;quot;BPM&amp;quot; near the bottom of the watch face...&lt;br /&gt;
&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6531</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6531"/>
		<updated>2020-08-12T05:09:37Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: /* What are labels? */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
Labels are considered as &amp;quot;elemental&amp;quot; parts that make up a screen's Text-based UI by the LVGL library...&lt;br /&gt;
Each label is also considered as an &amp;quot;object&amp;quot; or &amp;quot;obj&amp;quot; and can be manipulated, by changing the data attributed with the &amp;quot;obj&amp;quot;, for example, position, internal data like the strings/text etc.&lt;br /&gt;
when can change what the label shows and where it shows it...&lt;br /&gt;
&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6488</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6488"/>
		<updated>2020-08-10T09:19:55Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Using icons==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion as an icon==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bytes===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6487</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6487"/>
		<updated>2020-08-10T09:17:10Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
==Labels==&lt;br /&gt;
===What are labels?===&lt;br /&gt;
===Modifying label data===&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Choosing the image to be included==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bits===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6486</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6486"/>
		<updated>2020-08-10T09:15:40Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things we went through while creating some custom Watchfaces, so consider this as a log of experiments of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
==Labels==&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Choosing the image to be included==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bits===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6485</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6485"/>
		<updated>2020-08-10T09:14:57Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=PineTime Custom Watchface Tutorial=&lt;br /&gt;
&lt;br /&gt;
This is a tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development...&lt;br /&gt;
&lt;br /&gt;
We will explain some of the things I went through while creating some custom Watchfaces, so consider this as a log of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as it will be dynamically updated...&lt;br /&gt;
&lt;br /&gt;
==What you need to start==&lt;br /&gt;
The entire building process will be done by GitHub, so all you need is a device which can give you a Github Web Client, a PC or tablet to give you enough screen space to review your code and a steady internet connection.&lt;br /&gt;
&lt;br /&gt;
Since the compiling and file management is done by Github online, you have nothing else to worry about other than working with the files that display the watch face.&lt;br /&gt;
&lt;br /&gt;
So with those things settled, let's start with the basics of a watchface.&lt;br /&gt;
&lt;br /&gt;
Please remember that this is a wiki, so you can make an account and help us improve this page.&lt;br /&gt;
&lt;br /&gt;
Please make sure not to unilaterally remove info though, but offer an alternative. If it is indeed a better way, in time your alternative will grow into the main text, and the latter info will be pruned.&lt;br /&gt;
&lt;br /&gt;
==Overview==&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is made with a programming language named '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
Basic knowledge of C/C++ is required to to understand the advanced watch faces as that requires more complex code, but you can still do a some cool things without much knowledge of C++ programming, just some small edits to existing programs.&lt;br /&gt;
&lt;br /&gt;
InfiniTime uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brain of the watch.&lt;br /&gt;
&lt;br /&gt;
To get the watchface to work there are these basic steps. We will go over each step separately, so don't be daunted, all will become clear soon.&lt;br /&gt;
&lt;br /&gt;
For now we will, modify the the existing watchface, change the positioning of the text labels, add an icon to an existing watchface, and later on we will do a full watchface.&lt;br /&gt;
==Labels==&lt;br /&gt;
===Label positioning===&lt;br /&gt;
==Choosing the image to be included==&lt;br /&gt;
===Image size considerations===&lt;br /&gt;
==Preparing the image for inclusion==&lt;br /&gt;
===RGB565 image format===&lt;br /&gt;
===Flipping the bits===&lt;br /&gt;
===RAM vs ROM===&lt;br /&gt;
=Using git to work on the firmware=&lt;br /&gt;
===Cloning the repository===&lt;br /&gt;
===Changing the code to add the image===&lt;br /&gt;
===Compiling the firmware===&lt;br /&gt;
==Testing the firmware==&lt;br /&gt;
===Installing the new firmware===&lt;br /&gt;
===Activating the firmware===&lt;br /&gt;
===How to troubleshoot===&lt;br /&gt;
==Conclusions==&lt;br /&gt;
==Next steps==&lt;br /&gt;
==More in-depth documentation==&lt;br /&gt;
==Thanks for the help==&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6483</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6483"/>
		<updated>2020-08-10T06:34:27Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hi, this is a simple tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development..&lt;br /&gt;
&lt;br /&gt;
I will explain some of the things I went through while creating some custom Watchfaces, so consider this as a log of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as I keep updating it...&lt;br /&gt;
&lt;br /&gt;
==What you need to start:==&lt;br /&gt;
&lt;br /&gt;
The entire building process will be done on the cloud, so all you need is a device which can give you a Github Web Client, and a proper internet connection...&lt;br /&gt;
&lt;br /&gt;
Try using a device like a PC or tablet to give you enough screen space to review your code...&lt;br /&gt;
&lt;br /&gt;
since the compiling and file management is done in Github itself, you have nothing else to worry about other than working with the file that displays the watch face&lt;br /&gt;
&lt;br /&gt;
So with those things in mind, let's start with the basics of the watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The basics==&lt;br /&gt;
&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is comprised of code made with the common programming language known as '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;br /&gt;
&lt;br /&gt;
basic knowledge of C/C++ is required to to understand the advanced watch faces where we will work with more complex code...&lt;br /&gt;
&lt;br /&gt;
but you can still do a few things without the knowledge of C++ programming, and just your brain...&lt;br /&gt;
&lt;br /&gt;
The firmware uses the '''LVGL''':[https://lvgl.io] graphics library to provide users with a simple and clean UI without overpowering the Nordic '''nRF52832''':[http://files.pine64.org/doc/datasheet/pinetime/nRF52832%20product%20brief.pdf] microcontroller which is the brains of the operation inside the watch...&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6481</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6481"/>
		<updated>2020-08-10T06:19:31Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hi, this is a simple tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development..&lt;br /&gt;
&lt;br /&gt;
I will explain some of the things I went through while creating some custom Watchfaces, so consider this as a log of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as I keep updating it...&lt;br /&gt;
&lt;br /&gt;
==What you need to start:==&lt;br /&gt;
&lt;br /&gt;
The entire building process will be done on the cloud, so all you need is a device which can give you a Github Web Client, and a proper internet connection...&lt;br /&gt;
&lt;br /&gt;
Try using a device like a PC or tablet to give you enough screen space to review your code...&lt;br /&gt;
&lt;br /&gt;
So with those things in mind, let's start with the basics of the watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The basics==&lt;br /&gt;
&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is comprised of basic code made with the common programming language known as '''C++''':[https://en.wikipedia.org/wiki/C%2B%2B]&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6480</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6480"/>
		<updated>2020-08-10T06:19:11Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hi, this is a simple tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development..&lt;br /&gt;
&lt;br /&gt;
I will explain some of the things I went through while creating some custom Watchfaces, so consider this as a log of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as I keep updating it...&lt;br /&gt;
&lt;br /&gt;
==What you need to start:==&lt;br /&gt;
&lt;br /&gt;
The entire building process will be done on the cloud, so all you need is a device which can give you a Github Web Client, and a proper internet connection...&lt;br /&gt;
&lt;br /&gt;
Try using a device like a PC or tablet to give you enough screen space to review your code...&lt;br /&gt;
&lt;br /&gt;
So with those things in mind, let's start with the basics of the watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The basics==&lt;br /&gt;
&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is comprised of basic code made with the common programming language known as ```C++```:[https://en.wikipedia.org/wiki/C%2B%2B]&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6479</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6479"/>
		<updated>2020-08-10T06:12:47Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hi, this is a simple tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development..&lt;br /&gt;
&lt;br /&gt;
I will explain some of the things I went through while creating some custom Watchfaces, so consider this as a log of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as I keep updating it...&lt;br /&gt;
&lt;br /&gt;
==What you need to start:==&lt;br /&gt;
&lt;br /&gt;
The entire building process will be done on the cloud, so all you need is a device which can give you a Github Web Client, and a proper internet connection...&lt;br /&gt;
&lt;br /&gt;
Try using a device like a PC or tablet to give you enough screen space to review your code...&lt;br /&gt;
&lt;br /&gt;
So with those things in mind, let's start with the basics of the watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The basics==&lt;br /&gt;
&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is comprised of basic code made with the common programming language known as '''C++''' :[https://en.wikipedia.org/wiki/C%2B%2B]&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
	<entry>
		<id>https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6478</id>
		<title>PineTime Custom Watchface Tutorial</title>
		<link rel="alternate" type="text/html" href="https://wiki.pine64.org/index.php?title=PineTime_Custom_Watchface_Tutorial&amp;diff=6478"/>
		<updated>2020-08-10T06:04:44Z</updated>

		<summary type="html">&lt;p&gt;Electr0lyte: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hi, this is a simple tutorial to help new users create custom watchfaces based on the InfiniTime Firmware for Pinetime made by user JF002, thanks to him for its development..&lt;br /&gt;
&lt;br /&gt;
I will explain some of the things I went through while creating some custom Watchfaces, so consider this as a log of sorts..&lt;br /&gt;
&lt;br /&gt;
So stay tuned to it as I keep updating it...&lt;br /&gt;
&lt;br /&gt;
==What you need to start:==&lt;br /&gt;
&lt;br /&gt;
The entire building process will be done on the cloud, so all you need is a device which can give you a Github Web Client, and a proper internet connection...&lt;br /&gt;
&lt;br /&gt;
Try using a device like a PC or tablet to give you enough screen space to review your code...&lt;br /&gt;
&lt;br /&gt;
So with those things in mind, let's start with the basics of the watchface.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==The basics==&lt;br /&gt;
&lt;br /&gt;
The Firmware (also called InfiniTime) we will be working with is comprised of basic code made with the common programming language known as &amp;quot;C++&amp;quot;&lt;/div&gt;</summary>
		<author><name>Electr0lyte</name></author>
	</entry>
</feed>