Merge branch 'develop' of JF/PineTime into master

This commit is contained in:
JF 2021-05-21 11:38:38 +02:00 committed by Gitea
commit de69905c06
208 changed files with 11312 additions and 10738 deletions

View File

@ -21,8 +21,8 @@ AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
BinPackArguments: true
BinPackParameters: true
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
@ -52,14 +52,14 @@ BreakStringLiterals: true
ColumnLimit: 140
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 2
ContinuationIndentWidth: 2
Cpp11BracedListStyle: true
DeriveLineEnding: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ExperimentalAutoDetectBinPacking: true
FixNamespaceComments: false
ForEachMacros:
- foreach
@ -90,10 +90,6 @@ MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: All
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300

View File

@ -22,5 +22,9 @@ Checks: '*,
-hicpp-no-assembler,
-hicpp-avoid-c-arrays,
-hicpp-uppercase-literal-suffix,
-hicpp-no-array-decay,
-cert-err58-cpp,
-cert-err60-cpp'
CheckOptions:
- key: readability-function-cognitive-complexity.Threshold
value: 100

3
.gitignore vendored
View File

@ -1,4 +1,7 @@
.idea/
# Python virtual environment for DFU images
.venv/
# CMake
cmake-build-*
cmake-*

View File

@ -1,5 +1,5 @@
cmake_minimum_required(VERSION 3.10)
project(pinetime VERSION 1.0.0 LANGUAGES C CXX ASM)
project(pinetime VERSION 1.1.0 LANGUAGES C CXX ASM)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 14)
@ -55,10 +55,22 @@ if(BUILD_DFU)
set(BUILD_DFU true)
endif()
set(PROJECT_GIT_COMMIT_HASH "")
execute_process(COMMAND git rev-parse --short HEAD
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
OUTPUT_VARIABLE PROJECT_GIT_COMMIT_HASH
RESULT_VARIABLE PROJECT_GIT_COMMIT_HASH_SUCCESS)
string(STRIP ${PROJECT_GIT_COMMIT_HASH} PROJECT_GIT_COMMIT_HASH)
message("PROJECT_GIT_COMMIT_HASH_SUCCESS? " ${PROJECT_GIT_COMMIT_HASH_SUCCESS})
message("BUILD CONFIGURATION")
message("-------------------")
message(" * Version : " ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH})
message(" * Toolchain : " ${ARM_NONE_EABI_TOOLCHAIN_PATH})
message(" * GitRef(S) : " ${PROJECT_GIT_COMMIT_HASH})
message(" * NRF52 SDK : " ${NRF5_SDK_PATH})
set(PROGRAMMER "???")
if(USE_JLINK)

View File

@ -24,8 +24,7 @@ The goal of this project is to design an open-source firmware for the Pinetime s
## Overview
![Pinetime screens](images/0.14.0/collage1.png "PinetimeScreens")
![Pinetime screens](images/0.14.0/collage2.png "PinetimeScreens")
![Pinetime screens](images/1.0.0/collage.png "PinetimeScreens")
As of now, here is the list of achievements of this project:
@ -37,10 +36,15 @@ As of now, here is the list of achievements of this project:
- Heart rate measurements
- Step counting
- Wake-up on wrist rotation
- Quick actions
* Disable vibration on notification
* Brightness settings
* Flashlight
* Settings
- 2 watch faces:
* Digital
* Analog
- Multiple 'apps' :
* Clock (displays the date, time, battery level, ble connection status, heart rate)
* System info (displays various info : BLE MAC, build date/time, uptime, version,...)
* Brightess (allows the user to configure the brightness of the display)
* Music (control the playback of the music on your phone)
* Heart rate (controls the heart rate sensor and display current heartbeat)
* Navigation (displays navigation instructions coming from the companion app)
@ -48,21 +52,31 @@ As of now, here is the list of achievements of this project:
* Paddle (single player pong-like game)
* Two (2048 clone game)
* Stopwatch (with all the necessary functions such as play, pause, lap, stop)
* Motion sensor and step counter (displays the number of steps and the state of the motion sensor in real-time)
- User settings:
* Display timeout
* Wake-up condition
* Time format (12/24h)
* Default watch face
* Battery status
* Firmware validation
* System information
- Supported by 3 companion apps (development is in progress):
* [Gadgetbridge](https://codeberg.org/Freeyourgadget/Gadgetbridge/) (on Android)
* [Amazfish](https://openrepos.net/content/piggz/amazfish) (on SailfishOS and Linux)
* [Siglo](https://github.com/alexr4535/siglo) (on Linux)
* **[Experimental]** [WebBLEWatch](https://hubmartin.github.io/WebBLEWatch/) Synchronize time directly from your web browser. [video](https://youtu.be/IakiuhVDdrY)
- **[Experimental]** OTA (Over-the-air) update via BLE
- **[Experimental]** Bootloader based on [MCUBoot](https://juullabs-oss.github.io/mcuboot/)
- OTA (Over-the-air) update via BLE
- [Bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader) based on [MCUBoot](https://juullabs-oss.github.io/mcuboot/)
## Documentation
### Getting started
- [Flash, upgrade (OTA), time synchronization,...](doc/gettingStarted/gettingStarted.md)
- [Getting started with InfiniTime 1.0 (quick user guide, update bootloader and InfiniTime,...)](doc/gettingStarted/gettingStarted-1.0.md)
- [Flash, upgrade (OTA), time synchronization,...](doc/gettingStarted/ota-gadgetbridge-nrfconnect.md)
### Develop
- [Generate the fonts and symbols](src/displayapp/fonts/Readme.md)
- [Generate the fonts and symbols](src/displayapp/fonts/README.md)
- [Creating a stopwatch in Pinetime(article)](https://pankajraghav.com/2021/04/03/PINETIME-STOPCLOCK.html)
### Build, flash and debug

View File

@ -3,6 +3,7 @@
To build this project, you'll need:
- A cross-compiler : [ARM-GCC (9-2020-q2-update)](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads/9-2020-q2-update)
- The NRF52 SDK 15.3.0 : [nRF-SDK v15.3.0](https://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v15.x.x/nRF5_SDK_15.3.0_59ac345.zip)
- The `cbor` and `intelhex` modules for Python 3
- A reasonably recent version of CMake (I use 3.16.5)
## Build steps

View File

@ -8,20 +8,51 @@ As the documentation is part of the source code, you can submit your improvement
## Fix bugs, add functionalities and improve the code
You want to fix a bug, add a cool new functionality or improve the code? See *How to submit a pull request below*.
## Spread the word
Pinetime is a cool open source project that deserves to be know. Talk about it around you, on social networks, on your blog,... and let people know that we are working on an open-source firmware for a smartwatch!
The Pinetime is a cool open source project that deserves to be known. Talk about it around you, on social networks, on your blog,... and let people know that we are working on an open-source firmware for a smartwatch!
# How to submit a pull request ?
## TL;DR
- Create a branch from develop;
- Work on a single subject in this branch. Create multiple branches/pulls-requests if you want to work on multiple subjects (bugs, features,...);
- Test your modifications on the actual hardware;
- Check the code formatting against our coding conventions and [clang-format](../.clang-format) and [clang-tidy](../.clang-tidy);
- Clean your code and remove files that are not needed;
- Write documentation related to your new feature is applicable;
- Create the pull-request and write a great description about it : what does your PR do, why, how,... Add pictures and video if possible;
- Wait for someone to review your PR and take part in the review process;
- Your PR will eventually be merged :)
Your contribution is more than welcome!
If you want to fix a bug, add a functionality or improve the code, you'll first need to create a branch from the **develop** branch (see [this page about the branching model](./branches.md)). This branch is called a feature branch, and you should choose a name that explains what you are working on (ex: "add-doc-about-contributions"). In this branch, try to focus on only one topic, bug or feature. For example, if you created this branch to work on the UI of a specific application, do not commit modifications about the SPI driver. If you want to work on multiple topics, create one branch per topic.
If you want to fix a bug, add a functionality or improve the code, you'll first need to create a branch from the **develop** branch (see [this page about the branching model](./branches.md)). This branch is called a feature branch, and you should choose a name that explains what you are working on (ex: "add-doc-about-contributions"). In this branch, **focus on only one topic, bug or feature**. For example, if you created this branch to work on the UI of a specific application, do not commit modifications about the SPI driver. If you want to work on multiple topics, create one branch per topic.
When your feature branch is ready, make sure it actually works and do not forget to write documentation about it if necessary.
When your feature branch is ready, **make sure it actually works** and **do not forget to write documentation** about it if it's relevant.
Then, you can submit a pull-request for review. Try to describe your pull request as much as possible: what did you do in this branch, how does it work, how is it designed, are there any limitations,... This will help the contributors to understand and review your code easily.
I **strongly discourage to create a PR containing modifications that haven't been tested**. If, for any reason, you cannot test your modifications but want to publish them anyway, **please mention it in the description**. This way, other contributors might be willing to test it and provide feedback about your code.
Other contributors can post comments about the pull request, maybe ask for more info or adjustements in the code.
Also, before submitting your PR, check the coding style of your code against the **coding conventions** detailed below. This project also provides [clang-format](../.clang-format) and [clang-tidy](../.clang-tidy) configuration files. You can use them to ensure correct formatting of your code.
Once the pull request is reviewed an accepted, it'll be merge in **develop** and will be released in the next release version of the firmware.
Do not forget to check the files you are going to commit and remove those who are not necessary (config files from your IDE, for example). Remove old comments, commented code,...
Then, you can submit a pull-request for review. Try to **describe your pull request as much as possible**: what did you do in this branch, how does it work, how is it designed, are there any limitations,... This will help the contributors to understand and review your code easily. You can add pictures and video to the description so that contributors will have a quick overview of your work.
Other contributors can post comments about the pull request, maybe ask for more info or adjustments in the code.
Once the pull request is reviewed and accepted, it'll be merge in **develop** and will be released in the next release version of the firmware.
## Why all these rules?
Reviewing pull-requests is a **very time consuming task** for the creator of this project ([JF002](https://github.com/JF002)) and for other contributors who take the time to review them. Every little thing you do to make their lives easier will **increase the chances your PR will be merge quickly**.
When reviewing PR, the author and contributors will first look at the **description**. If it's easy to understand what the PR does, why the modification is needed or interesting and how it's done, a good part of the work is already done : we understand the PR and its context.
Then, reviewing **a few files that were modified for a single purpose** is a lot more easier than to review 30 files modified for many reasons (bug fix, UI improvements, typos in doc,...), even if all these changes make sense. Also, it's possible that we agree on some modification but not on some other, and we won't be able to merge the PR because of the changes that are not accepted.
We do our best to keep the code as consistent as possible, and that mean we pay attention to the **formatting** of the code. If the code formatting is not consistent with our code base, we'll ask you to review it, which will take more time.
The last step of the review consists in **testing** the modification. If it doesn't work out of the box, we'll ask your to review your code and to ensure that it works as expected.
It's totally normal for a PR to need some more work even after it was created, that's why we review them. But every round trip takes time, and it's good practice to try to reduce them as much as possible by following those simple rules.
# Coding convention
## Language
@ -32,7 +63,7 @@ It's OK to include C code if this code comes from another library like FreeRTOS,
## Coding style
The most important rule to follow is to try to keep the code as easy to read and maintain as possible.
- **Identation** : 2 spaces, no tabulation
- **Indentation** : 2 spaces, no tabulation
- **Opening brace** at the end of the line
- **Naming** : Choose self-describing variable name
- **class** : PascalCase

Binary file not shown.

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 KiB

View File

@ -0,0 +1,112 @@
# Getting started with InfiniTime 1.0
On April 22 2021, InfiniTime and Pine64 [announced the release of InfiniTime 1.0](https://www.pine64.org/2021/04/22/its-time-infinitime-1-0/) and the availability of PineTime smartwatches as *enthusiast grade end-user product*. This page aims to guide you with your first step with your new PineTime.
## Firmware, InfiniTime, Bootloader, Recovery firmware, OTA, DFU... What is it?
You might have already seen these words by reading the announcement, release notes, or [the wiki guide](https://wiki.pine64.org/wiki/Upgrade_PineTime_to_InfiniTime_1.0.0) and, you may find them misleading if you're not familiar with the project.
Basically, a **firmware** is just a software running on the embedded hardware of a device, the PineTime in this case.
**InfiniTime** is based on 3 distinct **firmwares**:
- **[InfiniTime](https://github.com/JF002/InfiniTime)** itself, this is the *application firmware* running on the PineTime. This is the main firmware which provides most of the functionalities you'll use on a daily basis : bluetooth low-energy (BLE) connectivity, applications, watchfaces,...
- **[The bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader)** is responsible for safely applying **updates** of the *application firmware*, reverting them in case of issues and load the recovery firmware when requested.
- **The recovery firmware** is a specific *application firmware* than can be loaded by the bootloader on user request. This firmware can be useful in case of serious issue, when the main application firmware cannot perform an OTA update correctly. Currently, this recovery firmware is based on [InfiniTime 0.14.1](https://github.com/JF002/InfiniTime/releases/tag/0.14.1).
**OTA** and **DFU** refer to the update of the firmware over BLE (**B**luetooth **L**ow **E**nergy). **OTA** means **O**ver **T**he **A**ir, this is a functionality that allows the user to update the firmware how their device using a wireless communication like BLE. When we talk about **DFU** (**D**igital **F**irmware **U**pdate), we refer to the file format and protocol used to send the update of the firmware to the watch over-the-air. InfiniTime implement the (legacy) DFU protocol from Nordic Semiconductor (NRF).
## How to check the version of InfiniTime and the bootloader?
Since September 2020, all PineTimes (devkits or sealed) are flashed using the **[first iteration of the bootloader](https://github.com/lupyuen/pinetime-rust-mynewt/releases/tag/v4.1.7)** and **[InfiniTime 0.7.1](https://github.com/JF002/InfiniTime/releases/tag/0.7.1)**. There was no recovery firmware at that time.
The bootloader only runs when the watch starts (from an empty battery, for example) or after a reset (after a succesful OTA or a manual reset - long push on the button).
You can recognize this first iteration of the bootloader with it greenish **PINETIME** logo.
![Old bootloader logo](oldbootloaderlogo.jpg)
You can check the version of InfiniTime by opening the app *SystemInfo*. For version < 1.0:
![InfiniTime 0.7.1 Application menu](appmenu-071.jpg)
![InfiniTime 0.7.1 version](version-071.jpg)
And for version >= 1.0 :
![InfiniTime 1.0 version](version-1.0.jpg)
PineTime shipped from June 2020 (to be confirmed) will be flashed with the [new version of the bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader/releases/tag/1.0.0), the [recovery firmware](https://github.com/JF002/InfiniTime/releases/tag/0.14.1) and [InfiniTime 1.0](https://github.com/JF002/InfiniTime/releases/tag/1.0.0).
The bootloader is easily recognizable with it white pine cone that is progressively drawn in green. It also displays its own version on the bottom (1.0.0 as of now).
![Bootloader 1.0](bootloader-1.0.jpg)
## How to update your PineTime?
To update your PineTime, you can use one of the compatible companion applications. Here are the main ones:
- **[Amazfish](https://github.com/piggz/harbour-amazfish)** (Desktop Linux, mobile Linux, SailfishOS, runs on the PinebookPro and the Pinephone)
- **[Gadgetbridge](https://www.gadgetbridge.org/)** (Android)
- **[Siglo](https://github.com/alexr4535/siglo)** (Linux, GTK based)
- **NRFConnect** (closed source, Android & iOS).
See [this page](ota-gadgetbridge-nrfconnect.md) for more info about the OTA procedure using Gadgetbrige and NRFCOnnect.
### From InfiniTime 0.7.1 / old bootloader
If your PineTime is currently running InfiniTime 0.7.1 and the old bootloader, we strongly recommend you update them to more recent version (Bootloader 1.0.0 and InfiniTime 1.0.0 as of now). We also recommend you install the recovery firmware once the bootloader is up-do-date.
Using the companion app of your choice, you'll need to apply the OTA procedure for these 3 firmwares in this sequence (failing to follow this specific order might temporarily or permanently brick your device):
1. Flash the latest version of InfiniTime. The file to upload is named **pinetime-mcuboot-app-dfu-x.y.z.zip**. Here is the link to [InfiniTime 1.0](https://github.com/JF002/InfiniTime/releases/download/1.0.0/pinetime-mcuboot-app-dfu-1.0.0.zip).
2. Update the bootloader by applying the OTA procedure with the file named [**reloader-mcuboot.zip** from the repo of the bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader/releases/download/1.0.0/reloader-mcuboot.zip).
3. Install the recovery firmware by applying the OTA procedure with the file named [**pinetime-mcuboot-recovery-loader-dfu-0.14.1.zip** from the version 0.14.1 of InfiniTime](https://github.com/JF002/InfiniTime/releases/download/0.14.1/pinetime-mcuboot-recovery-loader-dfu-0.14.1.zip).
You'll find more info about this process in [this wiki page](https://wiki.pine64.org/wiki/Upgrade_PineTime_to_InfiniTime_1.0.0). You can also see the procedure in video [here](https://video.codingfield.com/videos/watch/831077c5-16f3-47b4-9b2b-c4bbfecc6529) and [here (from Amazfish)](https://video.codingfield.com/videos/watch/f7bffb3d-a6a1-43c4-8f01-f4aeff4adf9e)
### From version > 1.0
If you are already running the new "1.0.0" bootloader, all you have to do is update your version of InfiniTime when it'll be available. We'll write specific instructions when (if) we release a new version of the bootloader.
### Firmware validation
The bootloader requires a (manual) validation of the firmware. If the watch reset with an updated firmware that was not validated, the bootloader will consider it as non-functionning and will revert to the previous version of the firmware. This is a safety feature to prevent bricking your device with a faulty firmware.
You can validate your updated firmware on InfiniTime >= 1.0 by following this simple procedure:
- From the watchface, swipe **right** to display the *Quick Actions menu*
- Open the **Settings** app by tapping the *gear* icon on the bottom right
- Swipe down and tap on the entry named **Firmware**
- This app shows the version that is currently running. If it's not validated yet, it displays 2 buttons:
- **Validate** to validate your firmware
- **Reset** to reset the watch and revert to the previously running version of the firmware
## InfiniTime 1.0 quick user guide
### Setting the time
By default, InfiniTime starts on the digital watchface. It'll probably display the epoch time (1 Jan 1970, 00:00). The time will be automatically synchronized once you connect on of the companion app to your PineTime using BLE connectivity. InfiniTime does not provide any way to manually set the time for now.
### Navigation in the menu
![Quick actions](quickactions.jpg)
![Settings](settings.jpg)
![Application menu](appmenu.jpg)
- Swipe **down** to display the notification panel. Notification sent by your companion app will be displayed in this panel.
- Swipe **up** to display the application menus. Apps (stopwatch, music, step, games,...) can be started from this menu.
- Swipe **right** to display the Quick Actions menu. This menu allows you to
- Set the brightness of the display
- Start the **flashlight** app
- Enable/disable vibrations on notifications (Do Not Disturb mode)
- Enter the **settings** menu
- Settings
- Display timeout
- Wake up event (Tap, wrist rotation)
- Time format (12/24H)
- Default watchface (digital / analog)
- Battery info
- Firmware validation
- About (system info, firmware version,...)
### Bootloader
Most of the time, the bootloader just runs without your intervention (update and load the firmware).
However, you can enable 2 functionalities using the push button:
- Push the button until the pine cone is drawn in **blue** to force the rollback of the previous version of the firmware, even if you've already validated the updated one
- Push the button until the pine cone is drawn in **red** to load the recovery firmware. This recovery firmware only provides BLE connectivity and OTA functionality.
More info about the bootloader in [its project page](https://github.com/JF002/pinetime-mcuboot-bootloader/blob/master/README.md).

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

View File

@ -19,8 +19,11 @@ RUN apt-get update -qq \
libffi-dev \
libssl-dev \
python3-dev \
git \
&& rm -rf /var/cache/apt/* /var/lib/apt/lists/*;
# Git needed for PROJECT_GIT_COMMIT_HASH variable setting
# Needs to be installed as root
RUN pip3 install adafruit-nrfutil
RUN pip3 install -Iv cryptography==3.3

View File

@ -19,8 +19,11 @@ RUN apt-get update -qq \
libssl-dev \
python3-dev \
python \
git \
&& rm -rf /var/cache/apt/* /var/lib/apt/lists/*;
# Git needed for PROJECT_GIT_COMMIT_HASH variable setting
RUN pip3 install adafruit-nrfutil
RUN pip3 install -Iv cryptography==3.3

BIN
images/1.0.0/collage.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@ -406,6 +406,8 @@ list(APPEND SOURCE_FILES
displayapp/screens/FlashLight.cpp
displayapp/screens/List.cpp
displayapp/screens/BatteryInfo.cpp
displayapp/screens/Steps.cpp
displayapp/screens/Timer.cpp
## Settings
displayapp/screens/settings/QuickSettings.cpp
@ -414,6 +416,7 @@ list(APPEND SOURCE_FILES
displayapp/screens/settings/SettingTimeFormat.cpp
displayapp/screens/settings/SettingWakeUp.cpp
displayapp/screens/settings/SettingDisplay.cpp
displayapp/screens/settings/SettingSteps.cpp
## Watch faces
displayapp/icons/bg_clock.c
@ -457,6 +460,7 @@ list(APPEND SOURCE_FILES
components/firmwarevalidator/FirmwareValidator.cpp
components/motor/MotorController.cpp
components/settings/Settings.cpp
components/timer/TimerController.cpp
drivers/Cst816s.cpp
FreeRTOS/port.c
FreeRTOS/port_cmsis_systick.c
@ -466,6 +470,7 @@ list(APPEND SOURCE_FILES
displayapp/fonts/jetbrains_mono_extrabold_compressed.c
displayapp/fonts/jetbrains_mono_bold_20.c
displayapp/fonts/jetbrains_mono_76.c
displayapp/fonts/jetbrains_mono_42.c
displayapp/fonts/lv_font_sys_48.c
displayapp/lv_pinetime_theme.c
@ -517,6 +522,7 @@ list(APPEND RECOVERY_SOURCE_FILES
components/ble/HeartRateService.cpp
components/firmwarevalidator/FirmwareValidator.cpp
components/settings/Settings.cpp
components/timer/TimerController.cpp
drivers/Cst816s.cpp
FreeRTOS/port.c
FreeRTOS/port_cmsis_systick.c
@ -587,6 +593,7 @@ set(INCLUDE_FILES
displayapp/screens/Notifications.h
displayapp/screens/HeartRate.h
displayapp/screens/Motion.h
displayapp/screens/Timer.h
drivers/St7789.h
drivers/SpiNorFlash.h
drivers/SpiMaster.h
@ -616,6 +623,7 @@ set(INCLUDE_FILES
components/ble/BleClient.h
components/ble/HeartRateService.h
components/settings/Settings.h
components/timer/TimerController.h
drivers/Cst816s.h
FreeRTOS/portmacro.h
FreeRTOS/portmacro_cmsis.h

View File

@ -26,7 +26,6 @@
* 1 tab == 4 spaces!
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
@ -103,7 +102,6 @@
/* Tickless idle/low power functionality. */
/* Define to trap errors during development. */
#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER)
#define configASSERT(x) ASSERT(x)
@ -140,7 +138,6 @@ INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
PRIORITY THAN THIS! (higher priorities are lower numeric values. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY _PRIO_APP_HIGH
/* Interrupt priorities used by the kernel port layer itself. These are generic
to all Cortex-M ports, and do not rely on any particular library functions. */
#define configKERNEL_INTERRUPT_PRIORITY configLIBRARY_LOWEST_INTERRUPT_PRIORITY
@ -154,7 +151,6 @@ standard names - or at least those used in the unmodified vector table. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
/*-----------------------------------------------------------
* Settings that are generated automatically
* basing on the settings above
@ -198,9 +194,9 @@ standard names - or at least those used in the unmodified vector table. */
* one or more RTC ticks are lost. The tick interrupt inside RTOS will detect this and make a correction needed. This is needed
* for the RTOS internal timers to be more accurate.
* 1. The auto correction for RTOS tick is disabled even though few RTC tick interrupts were lost. This feature is desirable when debugging
* the RTOS application and stepping though the code. After stepping when the application is continued in debug mode, the auto-corrections of
* RTOS tick might cause asserts. Setting configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG to 1 will make RTC and RTOS go out of sync but could be
* convenient for debugging.
* the RTOS application and stepping though the code. After stepping when the application is continued in debug mode, the
* auto-corrections of RTOS tick might cause asserts. Setting configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG to 1 will make RTC and RTOS go
* out of sync but could be convenient for debugging.
*/
#define configUSE_DISABLE_TICK_AUTO_CORRECTION_DEBUG 0

View File

@ -8,11 +8,13 @@ namespace Pinetime {
static constexpr uint32_t Major() {return major;}
static constexpr uint32_t Minor() {return minor;}
static constexpr uint32_t Patch() {return patch;}
static constexpr const char* GitCommitHash() {return commitHash;}
static constexpr const char* VersionString() {return versionString;}
private:
static constexpr uint32_t major = @PROJECT_VERSION_MAJOR@;
static constexpr uint32_t minor = @PROJECT_VERSION_MINOR@;
static constexpr uint32_t patch = @PROJECT_VERSION_PATCH@;
static constexpr const char* commitHash = "@PROJECT_GIT_COMMIT_HASH@";
static constexpr const char* versionString = "@PROJECT_VERSION_MAJOR@.@PROJECT_VERSION_MINOR@.@PROJECT_VERSION_PATCH@";
};
}

View File

@ -15,7 +15,6 @@ Battery::Battery() {
void Battery::Init() {
nrf_gpio_cfg_input(chargingPin, (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pullup);
nrf_gpio_cfg_input(powerPresentPin, (nrf_gpio_pin_pull_t)GPIO_PIN_CNF_PULL_Pullup);
}
void Battery::Update() {
@ -23,14 +22,14 @@ void Battery::Update() {
isCharging = !nrf_gpio_pin_read(chargingPin);
isPowerPresent = !nrf_gpio_pin_read(powerPresentPin);
if ( isReading ) return;
if (isReading)
return;
// Non blocking read
samples = 0;
isReading = true;
SaadcInit();
nrfx_saadc_sample();
}
void Battery::adcCallbackStatic(nrfx_saadc_evt_t const* event) {
@ -41,8 +40,7 @@ void Battery::SaadcInit() {
nrfx_saadc_config_t adcConfig = NRFX_SAADC_DEFAULT_CONFIG;
APP_ERROR_CHECK(nrfx_saadc_init(&adcConfig, adcCallbackStatic));
nrf_saadc_channel_config_t adcChannelConfig = {
.resistor_p = NRF_SAADC_RESISTOR_DISABLED,
nrf_saadc_channel_config_t adcChannelConfig = {.resistor_p = NRF_SAADC_RESISTOR_DISABLED,
.resistor_n = NRF_SAADC_RESISTOR_DISABLED,
.gain = NRF_SAADC_GAIN1_5,
.reference = NRF_SAADC_REFERENCE_INTERNAL,
@ -50,11 +48,9 @@ void Battery::SaadcInit() {
.mode = NRF_SAADC_MODE_SINGLE_ENDED,
.burst = NRF_SAADC_BURST_ENABLED,
.pin_p = batteryVoltageAdcInput,
.pin_n = NRF_SAADC_INPUT_DISABLED
};
.pin_n = NRF_SAADC_INPUT_DISABLED};
APP_ERROR_CHECK(nrfx_saadc_channel_init(0, &adcChannelConfig));
APP_ERROR_CHECK(nrfx_saadc_buffer_convert(&saadc_value, 1));
}
void Battery::SaadcEventHandler(nrfx_saadc_evt_t const* p_event) {
@ -85,4 +81,3 @@ void Battery::SaadcEventHandler(nrfx_saadc_evt_t const * p_event) {
}
}
}

View File

@ -11,10 +11,10 @@ namespace Pinetime {
out the sensor values. The total capacity of the CircBuffer
is given as the template parameter N.
*/
template <int N>
class CircBuffer {
template <int N> class CircBuffer {
public:
CircBuffer() : arr{}, sz{}, cap{N}, head{} {}
CircBuffer() : arr {}, sz {}, cap {N}, head {} {
}
/**
insert member function overwrites the next data to the current
HEAD and moves the HEAD to the newly inserted value.
@ -41,18 +41,25 @@ namespace Pinetime {
class Battery {
public:
Battery();
void Init();
void Update();
int PercentRemaining() const { return percentRemainingBuffer.GetAverage(); }
int PercentRemaining() const {
return percentRemainingBuffer.GetAverage();
}
float Voltage() const { return voltage; }
float Voltage() const {
return voltage;
}
bool IsCharging() const { return isCharging; }
bool IsPowerPresent() const { return isPowerPresent; }
bool IsCharging() const {
return isCharging;
}
bool IsPowerPresent() const {
return isPowerPresent;
}
private:
static Battery* instance;

View File

@ -12,50 +12,42 @@ constexpr ble_uuid16_t AlertNotificationClient::unreadAlertStatusUuid;
constexpr ble_uuid16_t AlertNotificationClient::controlPointUuid;
namespace {
int
OnDiscoveryEventCallback(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service,
void *arg) {
int OnDiscoveryEventCallback(uint16_t conn_handle, const struct ble_gatt_error* error, const struct ble_gatt_svc* service, void* arg) {
auto client = static_cast<AlertNotificationClient*>(arg);
return client->OnDiscoveryEvent(conn_handle, error, service);
}
int OnAlertNotificationCharacteristicDiscoveredCallback(uint16_t conn_handle, const struct ble_gatt_error *error,
const struct ble_gatt_chr *chr, void *arg) {
int OnAlertNotificationCharacteristicDiscoveredCallback(uint16_t conn_handle,
const struct ble_gatt_error* error,
const struct ble_gatt_chr* chr,
void* arg) {
auto client = static_cast<AlertNotificationClient*>(arg);
return client->OnCharacteristicsDiscoveryEvent(conn_handle, error, chr);
}
int OnAlertNotificationDescriptorDiscoveryEventCallback(uint16_t conn_handle,
const struct ble_gatt_error *error,
uint16_t chr_val_handle,
const struct ble_gatt_dsc *dsc,
void *arg) {
int OnAlertNotificationDescriptorDiscoveryEventCallback(
uint16_t conn_handle, const struct ble_gatt_error* error, uint16_t chr_val_handle, const struct ble_gatt_dsc* dsc, void* arg) {
auto client = static_cast<AlertNotificationClient*>(arg);
return client->OnDescriptorDiscoveryEventCallback(conn_handle, error, chr_val_handle, dsc);
}
int NewAlertSubcribeCallback(uint16_t conn_handle,
const struct ble_gatt_error *error,
struct ble_gatt_attr *attr,
void *arg) {
int NewAlertSubcribeCallback(uint16_t conn_handle, const struct ble_gatt_error* error, struct ble_gatt_attr* attr, void* arg) {
auto client = static_cast<AlertNotificationClient*>(arg);
return client->OnNewAlertSubcribe(conn_handle, error, attr);
}
}
AlertNotificationClient::AlertNotificationClient(Pinetime::System::SystemTask& systemTask,
Pinetime::Controllers::NotificationManager &notificationManager) :
systemTask{systemTask}, notificationManager{notificationManager} {
Pinetime::Controllers::NotificationManager& notificationManager)
: systemTask {systemTask}, notificationManager {notificationManager} {
}
bool AlertNotificationClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error,
const ble_gatt_svc *service) {
bool AlertNotificationClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_svc* service) {
if (service == nullptr && error->status == BLE_HS_EDONE) {
if (isDiscovered) {
NRF_LOG_INFO("ANS Discovery found, starting characteristics discovery");
ble_gattc_disc_all_chrs(connectionHandle, ansStartHandle, ansEndHandle,
OnAlertNotificationCharacteristicDiscoveredCallback, this);
ble_gattc_disc_all_chrs(connectionHandle, ansStartHandle, ansEndHandle, OnAlertNotificationCharacteristicDiscoveredCallback, this);
} else {
NRF_LOG_INFO("ANS not found");
onServiceDiscovered(connectionHandle);
@ -72,7 +64,8 @@ bool AlertNotificationClient::OnDiscoveryEvent(uint16_t connectionHandle, const
return false;
}
int AlertNotificationClient::OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error,
int AlertNotificationClient::OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle,
const ble_gatt_error* error,
const ble_gatt_chr* characteristic) {
if (error->status != 0 && error->status != BLE_HS_EDONE) {
NRF_LOG_INFO("ANS Characteristic discovery ERROR");
@ -83,41 +76,34 @@ int AlertNotificationClient::OnCharacteristicsDiscoveryEvent(uint16_t connection
if (characteristic == nullptr && error->status == BLE_HS_EDONE) {
NRF_LOG_INFO("ANS Characteristic discovery complete");
if (isCharacteristicDiscovered) {
ble_gattc_disc_all_dscs(connectionHandle,
newAlertHandle, ansEndHandle,
OnAlertNotificationDescriptorDiscoveryEventCallback, this);
ble_gattc_disc_all_dscs(connectionHandle, newAlertHandle, ansEndHandle, OnAlertNotificationDescriptorDiscoveryEventCallback, this);
} else
onServiceDiscovered(connectionHandle);
} else {
if (characteristic != nullptr &&
ble_uuid_cmp(((ble_uuid_t *) &supportedNewAlertCategoryUuid), &characteristic->uuid.u) == 0) {
if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &supportedNewAlertCategoryUuid), &characteristic->uuid.u) == 0) {
NRF_LOG_INFO("ANS Characteristic discovered : supportedNewAlertCategoryUuid");
supportedNewAlertCategoryHandle = characteristic->val_handle;
} else if (characteristic != nullptr &&
ble_uuid_cmp(((ble_uuid_t *) &supportedUnreadAlertCategoryUuid), &characteristic->uuid.u) == 0) {
} else if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &supportedUnreadAlertCategoryUuid), &characteristic->uuid.u) == 0) {
NRF_LOG_INFO("ANS Characteristic discovered : supportedUnreadAlertCategoryUuid");
supportedUnreadAlertCategoryHandle = characteristic->val_handle;
} else if (characteristic != nullptr &&
ble_uuid_cmp(((ble_uuid_t *) &newAlertUuid), &characteristic->uuid.u) == 0) {
} else if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &newAlertUuid), &characteristic->uuid.u) == 0) {
NRF_LOG_INFO("ANS Characteristic discovered : newAlertUuid");
newAlertHandle = characteristic->val_handle;
newAlertDefHandle = characteristic->def_handle;
isCharacteristicDiscovered = true;
} else if (characteristic != nullptr &&
ble_uuid_cmp(((ble_uuid_t *) &unreadAlertStatusUuid), &characteristic->uuid.u) == 0) {
} else if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &unreadAlertStatusUuid), &characteristic->uuid.u) == 0) {
NRF_LOG_INFO("ANS Characteristic discovered : unreadAlertStatusUuid");
unreadAlertStatusHandle = characteristic->val_handle;
} else if (characteristic != nullptr &&
ble_uuid_cmp(((ble_uuid_t *) &controlPointUuid), &characteristic->uuid.u) == 0) {
} else if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &controlPointUuid), &characteristic->uuid.u) == 0) {
NRF_LOG_INFO("ANS Characteristic discovered : controlPointUuid");
controlPointHandle = characteristic->val_handle;
} else NRF_LOG_INFO("ANS Characteristic discovered : 0x%x", characteristic->val_handle);
} else
NRF_LOG_INFO("ANS Characteristic discovered : 0x%x", characteristic->val_handle);
}
return 0;
}
int AlertNotificationClient::OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error *error,
ble_gatt_attr *attribute) {
int AlertNotificationClient::OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* attribute) {
if (error->status == 0) {
NRF_LOG_INFO("ANS New alert subscribe OK");
} else {
@ -128,12 +114,12 @@ int AlertNotificationClient::OnNewAlertSubcribe(uint16_t connectionHandle, const
return 0;
}
int AlertNotificationClient::OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle, const ble_gatt_error *error,
int AlertNotificationClient::OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle,
const ble_gatt_error* error,
uint16_t characteristicValueHandle,
const ble_gatt_dsc* descriptor) {
if (error->status == 0) {
if (characteristicValueHandle == newAlertHandle &&
ble_uuid_cmp(((ble_uuid_t *) &newAlertUuid), &descriptor->uuid.u)) {
if (characteristicValueHandle == newAlertHandle && ble_uuid_cmp(((ble_uuid_t*) &newAlertUuid), &descriptor->uuid.u)) {
if (newAlertDescriptorHandle == 0) {
NRF_LOG_INFO("ANS Descriptor discovered : %d", descriptor->handle);
newAlertDescriptorHandle = descriptor->handle;
@ -160,7 +146,8 @@ void AlertNotificationClient::OnNotification(ble_gap_event *event) {
// Ignore notifications with empty message
const auto packetLen = OS_MBUF_PKTLEN(event->notify_rx.om);
if(packetLen <= headerSize) return;
if (packetLen <= headerSize)
return;
size_t bufferSize = std::min(packetLen + stringTerminatorSize, maxBufferSize);
auto messageSize = std::min(maxMessageSize, (bufferSize - headerSize));

View File

@ -24,11 +24,12 @@ namespace Pinetime {
Pinetime::Controllers::NotificationManager& notificationManager);
bool OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_svc* service);
int OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error,
const ble_gatt_chr *characteristic);
int OnCharacteristicsDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic);
int OnNewAlertSubcribe(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* attribute);
int OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle, const ble_gatt_error *error,
uint16_t characteristicValueHandle, const ble_gatt_dsc *descriptor);
int OnDescriptorDiscoveryEventCallback(uint16_t connectionHandle,
const ble_gatt_error* error,
uint16_t characteristicValueHandle,
const ble_gatt_dsc* descriptor);
void OnNotification(ble_gap_event* event);
void Reset();
void Discover(uint16_t connectionHandle, std::function<void(uint16_t)> lambda) override;
@ -41,30 +42,13 @@ namespace Pinetime {
static constexpr uint16_t unreadAlertStatusId = 0x2a45;
static constexpr uint16_t controlPointId = 0x2a44;
static constexpr ble_uuid16_t ansServiceUuid{
.u {.type = BLE_UUID_TYPE_16},
.value = ansServiceId
};
static constexpr ble_uuid16_t supportedNewAlertCategoryUuid{
.u {.type = BLE_UUID_TYPE_16},
.value = supportedNewAlertCategoryId
};
static constexpr ble_uuid16_t supportedUnreadAlertCategoryUuid{
.u {.type = BLE_UUID_TYPE_16},
.value = supportedUnreadAlertCategoryId
};
static constexpr ble_uuid16_t newAlertUuid{
.u {.type = BLE_UUID_TYPE_16},
.value = newAlertId
};
static constexpr ble_uuid16_t unreadAlertStatusUuid{
.u {.type = BLE_UUID_TYPE_16},
.value = unreadAlertStatusId
};
static constexpr ble_uuid16_t controlPointUuid{
.u {.type = BLE_UUID_TYPE_16},
.value = controlPointId
};
static constexpr ble_uuid16_t ansServiceUuid {.u {.type = BLE_UUID_TYPE_16}, .value = ansServiceId};
static constexpr ble_uuid16_t supportedNewAlertCategoryUuid {.u {.type = BLE_UUID_TYPE_16}, .value = supportedNewAlertCategoryId};
static constexpr ble_uuid16_t supportedUnreadAlertCategoryUuid {.u {.type = BLE_UUID_TYPE_16},
.value = supportedUnreadAlertCategoryId};
static constexpr ble_uuid16_t newAlertUuid {.u {.type = BLE_UUID_TYPE_16}, .value = newAlertId};
static constexpr ble_uuid16_t unreadAlertStatusUuid {.u {.type = BLE_UUID_TYPE_16}, .value = unreadAlertStatusId};
static constexpr ble_uuid16_t controlPointUuid {.u {.type = BLE_UUID_TYPE_16}, .value = controlPointId};
uint16_t ansStartHandle = 0;
uint16_t ansEndHandle = 0;

View File

@ -11,7 +11,6 @@ constexpr ble_uuid16_t AlertNotificationService::ansUuid;
constexpr ble_uuid16_t AlertNotificationService::ansCharUuid;
constexpr ble_uuid128_t AlertNotificationService::notificationEventUuid;
int AlertNotificationCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
auto anService = static_cast<AlertNotificationService*>(arg);
return anService->OnAlert(conn_handle, attr_handle, ctxt);
@ -27,39 +26,28 @@ void AlertNotificationService::Init() {
}
AlertNotificationService::AlertNotificationService(System::SystemTask& systemTask, NotificationManager& notificationManager)
: characteristicDefinition{
{
.uuid = (ble_uuid_t *) &ansCharUuid,
: characteristicDefinition {{.uuid = (ble_uuid_t*) &ansCharUuid,
.access_cb = AlertNotificationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE
},
{
.uuid = (ble_uuid_t *) &notificationEventUuid,
.flags = BLE_GATT_CHR_F_WRITE},
{.uuid = (ble_uuid_t*) &notificationEventUuid,
.access_cb = AlertNotificationCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_NOTIFY,
.val_handle = &eventHandle
},
{
0
}
},
.val_handle = &eventHandle},
{0}},
serviceDefinition {
{
/* Device Information Service */
{/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t*) &ansUuid,
.characteristics = characteristicDefinition
.characteristics = characteristicDefinition},
{0},
},
{
0
},
}, systemTask{systemTask}, notificationManager{notificationManager} {
systemTask {systemTask},
notificationManager {notificationManager} {
}
int AlertNotificationService::OnAlert(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt) {
int AlertNotificationService::OnAlert(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) {
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
constexpr size_t stringTerminatorSize = 1; // end of string '\0'
constexpr size_t headerSize = 3;
@ -68,7 +56,8 @@ int AlertNotificationService::OnAlert(uint16_t conn_handle, uint16_t attr_handle
// Ignore notifications with empty message
const auto packetLen = OS_MBUF_PKTLEN(ctxt->om);
if(packetLen <= headerSize) return 0;
if (packetLen <= headerSize)
return 0;
size_t bufferSize = std::min(packetLen + stringTerminatorSize, maxBufferSize);
auto messageSize = std::min(maxMessageSize, (bufferSize - headerSize));

View File

@ -8,7 +8,8 @@
#undef min
// 00020001-78fc-48fe-8e23-433b3a1942d0
#define NOTIFICATION_EVENT_SERVICE_UUID_BASE {0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x01, 0x00, 0x02, 0x00}
#define NOTIFICATION_EVENT_SERVICE_UUID_BASE \
{ 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x01, 0x00, 0x02, 0x00 }
namespace Pinetime {
@ -20,22 +21,16 @@ namespace Pinetime {
class AlertNotificationService {
public:
AlertNotificationService(Pinetime::System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager &notificationManager);
AlertNotificationService(Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::NotificationManager& notificationManager);
void Init();
int OnAlert(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt);
int OnAlert(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt);
void AcceptIncomingCall();
void RejectIncomingCall();
void MuteIncomingCall();
enum class IncomingCallResponses : uint8_t {
Reject = 0x00,
Answer = 0x01,
Mute = 0x02
};
enum class IncomingCallResponses : uint8_t { Reject = 0x00, Answer = 0x01, Mute = 0x02 };
private:
enum class Categories : uint8_t {
@ -55,20 +50,11 @@ namespace Pinetime {
static constexpr uint16_t ansId {0x1811};
static constexpr uint16_t ansCharId {0x2a46};
static constexpr ble_uuid16_t ansUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = ansId
};
static constexpr ble_uuid16_t ansUuid {.u {.type = BLE_UUID_TYPE_16}, .value = ansId};
static constexpr ble_uuid16_t ansCharUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = ansCharId
};
static constexpr ble_uuid16_t ansCharUuid {.u {.type = BLE_UUID_TYPE_16}, .value = ansCharId};
static constexpr ble_uuid128_t notificationEventUuid {
.u { .type = BLE_UUID_TYPE_128 },
.value = NOTIFICATION_EVENT_SERVICE_UUID_BASE
};
static constexpr ble_uuid128_t notificationEventUuid {.u {.type = BLE_UUID_TYPE_128}, .value = NOTIFICATION_EVENT_SERVICE_UUID_BASE};
struct ble_gatt_chr_def characteristicDefinition[3];
struct ble_gatt_svc_def serviceDefinition[2];

View File

@ -7,39 +7,26 @@ using namespace Pinetime::Controllers;
constexpr ble_uuid16_t BatteryInformationService::batteryInformationServiceUuid;
constexpr ble_uuid16_t BatteryInformationService::batteryLevelUuid;
int BatteryInformationServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
auto* batteryInformationService = static_cast<BatteryInformationService*>(arg);
return batteryInformationService->OnBatteryServiceRequested(conn_handle, attr_handle, ctxt);
}
BatteryInformationService::BatteryInformationService(Controllers::Battery& batteryController) :
batteryController{batteryController},
characteristicDefinition{
{
.uuid = (ble_uuid_t *) &batteryLevelUuid,
BatteryInformationService::BatteryInformationService(Controllers::Battery& batteryController)
: batteryController {batteryController},
characteristicDefinition {{.uuid = (ble_uuid_t*) &batteryLevelUuid,
.access_cb = BatteryInformationServiceCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
.val_handle = &batteryLevelHandle
},
{
0
}
},
.val_handle = &batteryLevelHandle},
{0}},
serviceDefinition {
{
/* Device Information Service */
{/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t*) &batteryInformationServiceUuid,
.characteristics = characteristicDefinition
},
{
0
},
.characteristics = characteristicDefinition},
{0},
} {
}
void BatteryInformationService::Init() {
@ -51,7 +38,8 @@ void BatteryInformationService::Init() {
ASSERT(res == 0);
}
int BatteryInformationService::OnBatteryServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle,
int BatteryInformationService::OnBatteryServiceRequested(uint16_t connectionHandle,
uint16_t attributeHandle,
ble_gatt_access_ctxt* context) {
if (attributeHandle == batteryLevelHandle) {
NRF_LOG_INFO("BATTERY : handle = %d", batteryLevelHandle);

View File

@ -16,29 +16,21 @@ namespace Pinetime {
BatteryInformationService(Controllers::Battery& batteryController);
void Init();
int
OnBatteryServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt *context);
int OnBatteryServiceRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context);
private:
Controllers::Battery& batteryController;
static constexpr uint16_t batteryInformationServiceId {0x180F};
static constexpr uint16_t batteryLevelId {0x2A19};
static constexpr ble_uuid16_t batteryInformationServiceUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = batteryInformationServiceId
};
static constexpr ble_uuid16_t batteryInformationServiceUuid {.u {.type = BLE_UUID_TYPE_16}, .value = batteryInformationServiceId};
static constexpr ble_uuid16_t batteryLevelUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = batteryLevelId
};
static constexpr ble_uuid16_t batteryLevelUuid {.u {.type = BLE_UUID_TYPE_16}, .value = batteryLevelId};
struct ble_gatt_chr_def characteristicDefinition[3];
struct ble_gatt_svc_def serviceDefinition[2];
uint16_t batteryLevelHandle;
};
}
}

View File

@ -25,5 +25,3 @@ void Ble::FirmwareUpdateTotalBytes(uint32_t totalBytes) {
void Ble::FirmwareUpdateCurrentBytes(uint32_t currentBytes) {
firmwareUpdateCurrentBytes = currentBytes;
}

View File

@ -12,7 +12,9 @@ namespace Pinetime {
enum class AddressTypes { Public, Random };
Ble() = default;
bool IsConnected() const {return isConnected;}
bool IsConnected() const {
return isConnected;
}
void Connect();
void Disconnect();
@ -20,16 +22,33 @@ namespace Pinetime {
void StopFirmwareUpdate();
void FirmwareUpdateTotalBytes(uint32_t totalBytes);
void FirmwareUpdateCurrentBytes(uint32_t currentBytes);
void State(FirmwareUpdateStates state) { firmwareUpdateState = state; }
void State(FirmwareUpdateStates state) {
firmwareUpdateState = state;
}
bool IsFirmwareUpdating() const { return isFirmwareUpdating; }
uint32_t FirmwareUpdateTotalBytes() const { return firmwareUpdateTotalBytes; }
uint32_t FirmwareUpdateCurrentBytes() const { return firmwareUpdateCurrentBytes; }
FirmwareUpdateStates State() const { return firmwareUpdateState; }
bool IsFirmwareUpdating() const {
return isFirmwareUpdating;
}
uint32_t FirmwareUpdateTotalBytes() const {
return firmwareUpdateTotalBytes;
}
uint32_t FirmwareUpdateCurrentBytes() const {
return firmwareUpdateCurrentBytes;
}
FirmwareUpdateStates State() const {
return firmwareUpdateState;
}
void Address(BleAddress&& addr) {
address = addr;
}
const BleAddress& Address() const {
return address;
}
void AddressType(AddressTypes t) {
addressType = t;
}
void Address(BleAddress&& addr) { address = addr; }
const BleAddress& Address() const { return address; }
void AddressType(AddressTypes t) { addressType = t;}
private:
bool isConnected = false;
bool isFirmwareUpdating = false;
@ -38,7 +57,6 @@ namespace Pinetime {
FirmwareUpdateStates firmwareUpdateState = FirmwareUpdateStates::Idle;
BleAddress address;
AddressTypes addressType;
};
}
}

View File

@ -14,8 +14,10 @@ namespace {
return client->OnDiscoveryEvent(conn_handle, error, service);
}
int OnCurrentTimeCharacteristicDiscoveredCallback(uint16_t conn_handle, const struct ble_gatt_error *error,
const struct ble_gatt_chr *chr, void *arg) {
int OnCurrentTimeCharacteristicDiscoveredCallback(uint16_t conn_handle,
const struct ble_gatt_error* error,
const struct ble_gatt_chr* chr,
void* arg) {
auto client = static_cast<CurrentTimeClient*>(arg);
return client->OnCharacteristicDiscoveryEvent(conn_handle, error, chr);
}
@ -27,21 +29,17 @@ namespace {
}
CurrentTimeClient::CurrentTimeClient(DateTime& dateTimeController) : dateTimeController {dateTimeController} {
}
void CurrentTimeClient::Init() {
}
bool CurrentTimeClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error,
const ble_gatt_svc *service) {
bool CurrentTimeClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_svc* service) {
if (service == nullptr && error->status == BLE_HS_EDONE) {
if (isDiscovered) {
NRF_LOG_INFO("CTS found, starting characteristics discovery");
ble_gattc_disc_all_chrs(connectionHandle, ctsStartHandle, ctsEndHandle,
OnCurrentTimeCharacteristicDiscoveredCallback, this);
ble_gattc_disc_all_chrs(connectionHandle, ctsStartHandle, ctsEndHandle, OnCurrentTimeCharacteristicDiscoveredCallback, this);
} else {
NRF_LOG_INFO("CTS not found");
onServiceDiscovered(connectionHandle);
@ -59,7 +57,8 @@ bool CurrentTimeClient::OnDiscoveryEvent(uint16_t connectionHandle, const ble_ga
return false;
}
int CurrentTimeClient::OnCharacteristicDiscoveryEvent(uint16_t conn_handle, const ble_gatt_error *error,
int CurrentTimeClient::OnCharacteristicDiscoveryEvent(uint16_t conn_handle,
const ble_gatt_error* error,
const ble_gatt_chr* characteristic) {
if (characteristic == nullptr && error->status == BLE_HS_EDONE) {
if (isCharacteristicDiscovered) {
@ -73,8 +72,7 @@ int CurrentTimeClient::OnCharacteristicDiscoveryEvent(uint16_t conn_handle, cons
return 0;
}
if (characteristic != nullptr &&
ble_uuid_cmp(((ble_uuid_t *) &currentTimeCharacteristicUuid), &characteristic->uuid.u) == 0) {
if (characteristic != nullptr && ble_uuid_cmp(((ble_uuid_t*) &currentTimeCharacteristicUuid), &characteristic->uuid.u) == 0) {
NRF_LOG_INFO("CTS Characteristic discovered : 0x%x", characteristic->val_handle);
isCharacteristicDiscovered = true;
currentTimeHandle = characteristic->val_handle;
@ -82,17 +80,15 @@ int CurrentTimeClient::OnCharacteristicDiscoveryEvent(uint16_t conn_handle, cons
return 0;
}
int CurrentTimeClient::OnCurrentTimeReadResult(uint16_t conn_handle, const ble_gatt_error *error,
const ble_gatt_attr *attribute) {
int CurrentTimeClient::OnCurrentTimeReadResult(uint16_t conn_handle, const ble_gatt_error* error, const ble_gatt_attr* attribute) {
if (error->status == 0) {
// TODO check that attribute->handle equals the handle discovered in OnCharacteristicDiscoveryEvent
CtsData result;
os_mbuf_copydata(attribute->om, 0, sizeof(CtsData), &result);
NRF_LOG_INFO("Received data: %d-%d-%d %d:%d:%d", result.year,
result.month, result.dayofmonth,
result.hour, result.minute, result.second);
dateTimeController.SetTime(result.year, result.month, result.dayofmonth,
0, result.hour, result.minute, result.second, nrf_rtc_counter_get(portNRF_RTC_REG));
NRF_LOG_INFO(
"Received data: %d-%d-%d %d:%d:%d", result.year, result.month, result.dayofmonth, result.hour, result.minute, result.second);
dateTimeController.SetTime(
result.year, result.month, result.dayofmonth, 0, result.hour, result.minute, result.second, nrf_rtc_counter_get(portNRF_RTC_REG));
} else {
NRF_LOG_INFO("Error retrieving current time: %d", error->status);
}

View File

@ -17,11 +17,14 @@ namespace Pinetime {
void Init();
void Reset();
bool OnDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_svc* service);
int OnCharacteristicDiscoveryEvent(uint16_t conn_handle, const ble_gatt_error *error,
const ble_gatt_chr *characteristic);
int OnCharacteristicDiscoveryEvent(uint16_t conn_handle, const ble_gatt_error* error, const ble_gatt_chr* characteristic);
int OnCurrentTimeReadResult(uint16_t conn_handle, const ble_gatt_error* error, const ble_gatt_attr* attribute);
static constexpr const ble_uuid16_t* Uuid() { return &CurrentTimeClient::ctsServiceUuid; }
static constexpr const ble_uuid16_t* CurrentTimeCharacteristicUuid() { return &CurrentTimeClient::currentTimeCharacteristicUuid; }
static constexpr const ble_uuid16_t* Uuid() {
return &CurrentTimeClient::ctsServiceUuid;
}
static constexpr const ble_uuid16_t* CurrentTimeCharacteristicUuid() {
return &CurrentTimeClient::currentTimeCharacteristicUuid;
}
void Discover(uint16_t connectionHandle, std::function<void(uint16_t)> lambda) override;
private:
@ -39,14 +42,8 @@ namespace Pinetime {
static constexpr uint16_t ctsServiceId {0x1805};
static constexpr uint16_t currentTimeCharacteristicId {0x2a2b};
static constexpr ble_uuid16_t ctsServiceUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = ctsServiceId
};
static constexpr ble_uuid16_t currentTimeCharacteristicUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = currentTimeCharacteristicId
};
static constexpr ble_uuid16_t ctsServiceUuid {.u {.type = BLE_UUID_TYPE_16}, .value = ctsServiceId};
static constexpr ble_uuid16_t currentTimeCharacteristicUuid {.u {.type = BLE_UUID_TYPE_16}, .value = currentTimeCharacteristicId};
DateTime& dateTimeController;
bool isDiscovered = false;

View File

@ -7,7 +7,6 @@ using namespace Pinetime::Controllers;
constexpr ble_uuid16_t CurrentTimeService::ctsUuid;
constexpr ble_uuid16_t CurrentTimeService::ctChrUuid;
int CTSCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
auto cts = static_cast<CurrentTimeService*>(arg);
return cts->OnTimeAccessed(conn_handle, attr_handle, ctxt);
@ -22,9 +21,7 @@ void CurrentTimeService::Init() {
ASSERT(res == 0);
}
int CurrentTimeService::OnTimeAccessed(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt) {
int CurrentTimeService::OnTimeAccessed(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) {
NRF_LOG_INFO("Setting time...");
@ -32,12 +29,11 @@ int CurrentTimeService::OnTimeAccessed(uint16_t conn_handle, uint16_t attr_handl
CtsData result;
os_mbuf_copydata(ctxt->om, 0, sizeof(CtsData), &result);
NRF_LOG_INFO("Received data: %d-%d-%d %d:%d:%d", result.year,
result.month, result.dayofmonth,
result.hour, result.minute, result.second);
NRF_LOG_INFO(
"Received data: %d-%d-%d %d:%d:%d", result.year, result.month, result.dayofmonth, result.hour, result.minute, result.second);
m_dateTimeController.SetTime(result.year, result.month, result.dayofmonth,
0, result.hour, result.minute, result.second, nrf_rtc_counter_get(portNRF_RTC_REG));
m_dateTimeController.SetTime(
result.year, result.month, result.dayofmonth, 0, result.hour, result.minute, result.second, nrf_rtc_counter_get(portNRF_RTC_REG));
} else if (ctxt->op == BLE_GATT_ACCESS_OP_READ_CHR) {
CtsData currentDateTime;
@ -49,39 +45,26 @@ int CurrentTimeService::OnTimeAccessed(uint16_t conn_handle, uint16_t attr_handl
currentDateTime.second = m_dateTimeController.Seconds();
currentDateTime.millis = 0;
int res = os_mbuf_append(ctxt->om, &currentDateTime, sizeof(CtsData));
return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
return 0;
}
CurrentTimeService::CurrentTimeService(DateTime &dateTimeController) :
characteristicDefinition{
{
.uuid = (ble_uuid_t *) &ctChrUuid,
CurrentTimeService::CurrentTimeService(DateTime& dateTimeController)
: characteristicDefinition {{.uuid = (ble_uuid_t*) &ctChrUuid,
.access_cb = CTSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
},
{
0
}
},
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ},
{0}},
serviceDefinition {
{
/* Device Information Service */
{/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t*) &ctsUuid,
.characteristics = characteristicDefinition
.characteristics = characteristicDefinition},
{0},
},
{
0
},
}, m_dateTimeController{dateTimeController} {
m_dateTimeController {dateTimeController} {
}

View File

@ -16,22 +16,15 @@ namespace Pinetime {
CurrentTimeService(DateTime& dateTimeController);
void Init();
int OnTimeAccessed(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt);
int OnTimeAccessed(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt);
private:
static constexpr uint16_t ctsId {0x1805};
static constexpr uint16_t ctsCharId {0x2a2b};
static constexpr ble_uuid16_t ctsUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = ctsId
};
static constexpr ble_uuid16_t ctsUuid {.u {.type = BLE_UUID_TYPE_16}, .value = ctsId};
static constexpr ble_uuid16_t ctChrUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = ctsCharId
};
static constexpr ble_uuid16_t ctChrUuid {.u {.type = BLE_UUID_TYPE_16}, .value = ctsCharId};
struct ble_gatt_chr_def characteristicDefinition[2];
struct ble_gatt_svc_def serviceDefinition[2];

View File

@ -10,7 +10,6 @@ constexpr ble_uuid16_t DeviceInformationService::deviceInfoUuid;
constexpr ble_uuid16_t DeviceInformationService::hwRevisionUuid;
constexpr ble_uuid16_t DeviceInformationService::swRevisionUuid;
int DeviceInformationCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
auto deviceInformationService = static_cast<DeviceInformationService*>(arg);
return deviceInformationService->OnDeviceInfoRequested(conn_handle, attr_handle, ctxt);
@ -25,9 +24,7 @@ void DeviceInformationService::Init() {
ASSERT(res == 0);
}
int DeviceInformationService::OnDeviceInfoRequested(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt) {
int DeviceInformationService::OnDeviceInfoRequested(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) {
const char* str;
switch (ble_uuid_u16(ctxt->chr->uuid)) {
@ -57,9 +54,8 @@ int DeviceInformationService::OnDeviceInfoRequested(uint16_t conn_handle, uint16
return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES;
}
DeviceInformationService::DeviceInformationService() :
characteristicDefinition{
{
DeviceInformationService::DeviceInformationService()
: characteristicDefinition {{
.uuid = (ble_uuid_t*) &manufacturerNameUuid,
.access_cb = DeviceInformationCallback,
.arg = this,
@ -95,22 +91,12 @@ DeviceInformationService::DeviceInformationService() :
.arg = this,
.flags = BLE_GATT_CHR_F_READ,
},
{
0
}
},
{0}},
serviceDefinition {
{
/* Device Information Service */
{/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t*) &deviceInfoUuid,
.characteristics = characteristicDefinition
},
{
0
},
.characteristics = characteristicDefinition},
{0},
} {
}
{
}

View File

@ -13,8 +13,7 @@ namespace Pinetime {
DeviceInformationService();
void Init();
int OnDeviceInfoRequested(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt);
int OnDeviceInfoRequested(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt);
private:
static constexpr uint16_t deviceInfoId {0x180a};
@ -32,46 +31,22 @@ namespace Pinetime {
static constexpr const char* fwRevision = Version::VersionString();
static constexpr const char* swRevision = "InfiniTime";
static constexpr ble_uuid16_t deviceInfoUuid {.u {.type = BLE_UUID_TYPE_16}, .value = deviceInfoId};
static constexpr ble_uuid16_t deviceInfoUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = deviceInfoId
};
static constexpr ble_uuid16_t manufacturerNameUuid {.u {.type = BLE_UUID_TYPE_16}, .value = manufacturerNameId};
static constexpr ble_uuid16_t manufacturerNameUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = manufacturerNameId
};
static constexpr ble_uuid16_t modelNumberUuid {.u {.type = BLE_UUID_TYPE_16}, .value = modelNumberId};
static constexpr ble_uuid16_t modelNumberUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = modelNumberId
};
static constexpr ble_uuid16_t serialNumberUuid {.u {.type = BLE_UUID_TYPE_16}, .value = serialNumberId};
static constexpr ble_uuid16_t serialNumberUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = serialNumberId
};
static constexpr ble_uuid16_t fwRevisionUuid {.u {.type = BLE_UUID_TYPE_16}, .value = fwRevisionId};
static constexpr ble_uuid16_t fwRevisionUuid {
.u { .type = BLE_UUID_TYPE_16 },
.value = fwRevisionId
};
static constexpr ble_uuid16_t hwRevisionUuid {.u {.type = BLE_UUID_TYPE_16}, .value = hwRevisionId};
static constexpr ble_uuid16_t hwRevisionUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = hwRevisionId
};
static constexpr ble_uuid16_t swRevisionUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = swRevisionId
};
static constexpr ble_uuid16_t swRevisionUuid {.u {.type = BLE_UUID_TYPE_16}, .value = swRevisionId};
struct ble_gatt_chr_def characteristicDefinition[7];
struct ble_gatt_svc_def serviceDefinition[2];
};
}
}

View File

@ -11,8 +11,7 @@ constexpr ble_uuid128_t DfuService::controlPointCharacteristicUuid;
constexpr ble_uuid128_t DfuService::revisionCharacteristicUuid;
constexpr ble_uuid128_t DfuService::packetCharacteristicUuid;
int DfuServiceCallback(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt, void *arg) {
int DfuServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
auto dfuService = static_cast<DfuService*>(arg);
return dfuService->OnServiceData(conn_handle, attr_handle, ctxt);
}
@ -27,13 +26,13 @@ void TimeoutTimerCallback(TimerHandle_t xTimer) {
dfuService->OnTimeout();
}
DfuService::DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Controllers::Ble &bleController,
Pinetime::Drivers::SpiNorFlash &spiNorFlash) :
systemTask{systemTask},
DfuService::DfuService(Pinetime::System::SystemTask& systemTask,
Pinetime::Controllers::Ble& bleController,
Pinetime::Drivers::SpiNorFlash& spiNorFlash)
: systemTask {systemTask},
bleController {bleController},
dfuImage {spiNorFlash},
characteristicDefinition{
{
characteristicDefinition {{
.uuid = (ble_uuid_t*) &packetCharacteristicUuid,
.access_cb = DfuServiceCallback,
.arg = this,
@ -55,21 +54,15 @@ DfuService::DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Contr
.val_handle = &revision,
},
{
0
}
{0}
},
serviceDefinition {
{
/* Device Information Service */
{/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t*) &serviceUuid,
.characteristics = characteristicDefinition
},
{
0
},
.characteristics = characteristicDefinition},
{0},
} {
timeoutTimer = xTimerCreate("notificationTimer", 10000, pdFALSE, this, TimeoutTimerCallback);
}
@ -88,26 +81,25 @@ int DfuService::OnServiceData(uint16_t connectionHandle, uint16_t attributeHandl
xTimerStart(timeoutTimer, 0);
}
ble_gatts_find_chr((ble_uuid_t *) &serviceUuid, (ble_uuid_t *) &packetCharacteristicUuid, nullptr,
&packetCharacteristicHandle);
ble_gatts_find_chr((ble_uuid_t *) &serviceUuid, (ble_uuid_t *) &controlPointCharacteristicUuid, nullptr,
&controlPointCharacteristicHandle);
ble_gatts_find_chr((ble_uuid_t *) &serviceUuid, (ble_uuid_t *) &revisionCharacteristicUuid, nullptr,
&revisionCharacteristicHandle);
ble_gatts_find_chr((ble_uuid_t*) &serviceUuid, (ble_uuid_t*) &packetCharacteristicUuid, nullptr, &packetCharacteristicHandle);
ble_gatts_find_chr((ble_uuid_t*) &serviceUuid, (ble_uuid_t*) &controlPointCharacteristicUuid, nullptr, &controlPointCharacteristicHandle);
ble_gatts_find_chr((ble_uuid_t*) &serviceUuid, (ble_uuid_t*) &revisionCharacteristicUuid, nullptr, &revisionCharacteristicHandle);
if (attributeHandle == packetCharacteristicHandle) {
if (context->op == BLE_GATT_ACCESS_OP_WRITE_CHR)
return WritePacketHandler(connectionHandle, context->om);
else return 0;
else
return 0;
} else if (attributeHandle == controlPointCharacteristicHandle) {
if (context->op == BLE_GATT_ACCESS_OP_WRITE_CHR)
return ControlPointHandler(connectionHandle, context->om);
else return 0;
else
return 0;
} else if (attributeHandle == revisionCharacteristicHandle) {
if (context->op == BLE_GATT_ACCESS_OP_READ_CHR)
return SendDfuRevision(context->om);
else return 0;
else
return 0;
} else {
NRF_LOG_INFO("[DFU] Unknown Characteristic : %d", attributeHandle);
return 0;
@ -126,8 +118,8 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) {
bootloaderSize = om->om_data[4] + (om->om_data[5] << 8) + (om->om_data[6] << 16) + (om->om_data[7] << 24);
applicationSize = om->om_data[8] + (om->om_data[9] << 8) + (om->om_data[10] << 16) + (om->om_data[11] << 24);
bleController.FirmwareUpdateTotalBytes(applicationSize);
NRF_LOG_INFO("[DFU] -> Start data received : SD size : %d, BT size : %d, app size : %d", softdeviceSize,
bootloaderSize, applicationSize);
NRF_LOG_INFO(
"[DFU] -> Start data received : SD size : %d, BT size : %d, app size : %d", softdeviceSize, bootloaderSize, applicationSize);
dfuImage.Erase();
@ -139,19 +131,22 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) {
case States::Init: {
uint16_t deviceType = om->om_data[0] + (om->om_data[1] << 8);
uint16_t deviceRevision = om->om_data[2] + (om->om_data[3] << 8);
uint32_t applicationVersion =
om->om_data[4] + (om->om_data[5] << 8) + (om->om_data[6] << 16) + (om->om_data[7] << 24);
uint32_t applicationVersion = om->om_data[4] + (om->om_data[5] << 8) + (om->om_data[6] << 16) + (om->om_data[7] << 24);
uint16_t softdeviceArrayLength = om->om_data[8] + (om->om_data[9] << 8);
uint16_t sd[softdeviceArrayLength];
for (int i = 0; i < softdeviceArrayLength; i++) {
sd[i] = om->om_data[10 + (i * 2)] + (om->om_data[10 + (i * 2) + 1] << 8);
}
expectedCrc =
om->om_data[10 + (softdeviceArrayLength * 2)] + (om->om_data[10 + (softdeviceArrayLength * 2) + 1] << 8);
expectedCrc = om->om_data[10 + (softdeviceArrayLength * 2)] + (om->om_data[10 + (softdeviceArrayLength * 2) + 1] << 8);
NRF_LOG_INFO(
"[DFU] -> Init data received : deviceType = %d, deviceRevision = %d, applicationVersion = %d, nb SD = %d, First SD = %d, CRC = %u",
deviceType, deviceRevision, applicationVersion, softdeviceArrayLength, sd[0], expectedCrc);
deviceType,
deviceRevision,
applicationVersion,
softdeviceArrayLength,
sd[0],
expectedCrc);
return 0;
}
@ -164,8 +159,10 @@ int DfuService::WritePacketHandler(uint16_t connectionHandle, os_mbuf *om) {
if ((nbPacketReceived % nbPacketsToNotify) == 0 && bytesReceived != applicationSize) {
uint8_t data[5] {static_cast<uint8_t>(Opcodes::PacketReceiptNotification),
(uint8_t) (bytesReceived & 0x000000FFu), (uint8_t) (bytesReceived >> 8u),
(uint8_t) (bytesReceived >> 16u), (uint8_t) (bytesReceived >> 24u)};
(uint8_t) (bytesReceived & 0x000000FFu),
(uint8_t) (bytesReceived >> 8u),
(uint8_t) (bytesReceived >> 16u),
(uint8_t) (bytesReceived >> 24u)};
NRF_LOG_INFO("[DFU] -> Send packet notification: %d bytes received", bytesReceived);
notificationManager.Send(connectionHandle, controlPointCharacteristicHandle, data, 5);
}
@ -214,8 +211,7 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) {
NRF_LOG_INFO("[DFU] -> Start DFU, mode %d not supported!", imageType);
return 0;
}
}
break;
} break;
case Opcodes::InitDFUParameters: {
if (state != States::Init) {
NRF_LOG_INFO("[DFU] -> Init DFU requested, but we are not in Init state");
@ -225,11 +221,9 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) {
NRF_LOG_INFO("[DFU] -> Init DFU parameters %s", isInitComplete ? " complete" : " not complete");
if (isInitComplete) {
uint8_t data[3] {
static_cast<uint8_t>(Opcodes::Response),
uint8_t data[3] {static_cast<uint8_t>(Opcodes::Response),
static_cast<uint8_t>(Opcodes::InitDFUParameters),
(isInitComplete ? uint8_t{1} : uint8_t{0})
};
(isInitComplete ? uint8_t {1} : uint8_t {0})};
notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
return 0;
}
@ -262,21 +256,17 @@ int DfuService::ControlPointHandler(uint16_t connectionHandle, os_mbuf *om) {
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Validated);
NRF_LOG_INFO("Image OK");
uint8_t data[3] {
static_cast<uint8_t>(Opcodes::Response),
uint8_t data[3] {static_cast<uint8_t>(Opcodes::Response),
static_cast<uint8_t>(Opcodes::ValidateFirmware),
static_cast<uint8_t>(ErrorCodes::NoError)
};
static_cast<uint8_t>(ErrorCodes::NoError)};
notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
} else {
bleController.State(Pinetime::Controllers::Ble::FirmwareUpdateStates::Error);
NRF_LOG_INFO("Image Error : bad CRC");
uint8_t data[3] {
static_cast<uint8_t>(Opcodes::Response),
uint8_t data[3] {static_cast<uint8_t>(Opcodes::Response),
static_cast<uint8_t>(Opcodes::ValidateFirmware),
static_cast<uint8_t>(ErrorCodes::CrcError)
};
static_cast<uint8_t>(ErrorCodes::CrcError)};
notificationManager.AsyncSend(connectionHandle, controlPointCharacteristicHandle, data, 3);
}
@ -354,7 +344,8 @@ void DfuService::NotificationManager::Reset() {
}
void DfuService::DfuImage::Init(size_t chunkSize, size_t totalSize, uint16_t expectedCrc) {
if(chunkSize != 20) return;
if (chunkSize != 20)
return;
this->chunkSize = chunkSize;
this->totalSize = totalSize;
this->expectedCrc = expectedCrc;
@ -362,7 +353,8 @@ void DfuService::DfuImage::Init(size_t chunkSize, size_t totalSize, uint16_t exp
}
void DfuService::DfuImage::Append(uint8_t* data, size_t size) {
if(!ready) return;
if (!ready)
return;
ASSERT(size <= 20);
std::memcpy(tempBuffer + bufferWriteIndex, data, size);
@ -383,7 +375,8 @@ void DfuService::DfuImage::Append(uint8_t *data, size_t size) {
}
void DfuService::DfuImage::WriteMagicNumber() {
uint32_t magic[4] = { // TODO When this variable is a static constexpr, the values written to the memory are not correct. Why?
uint32_t magic[4] = {
// TODO When this variable is a static constexpr, the values written to the memory are not correct. Why?
0xf395c277,
0x7fefd260,
0x0f505235,
@ -436,6 +429,7 @@ uint16_t DfuService::DfuImage::ComputeCrc(uint8_t const *p_data, uint32_t size,
}
bool DfuService::DfuImage::IsComplete() {
if(!ready) return false;
if (!ready)
return false;
return totalWriteIndex == totalSize;
}

View File

@ -21,7 +21,8 @@ namespace Pinetime {
class DfuService {
public:
DfuService(Pinetime::System::SystemTask &systemTask, Pinetime::Controllers::Ble &bleController,
DfuService(Pinetime::System::SystemTask& systemTask,
Pinetime::Controllers::Ble& bleController,
Pinetime::Drivers::SpiNorFlash& spiNorFlash);
void Init();
int OnServiceData(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context);
@ -33,19 +34,22 @@ namespace Pinetime {
NotificationManager();
bool AsyncSend(uint16_t connection, uint16_t charactHandle, uint8_t* data, size_t size);
void Send(uint16_t connection, uint16_t characteristicHandle, const uint8_t* data, const size_t s);
private:
TimerHandle_t timer;
uint16_t connectionHandle = 0;
uint16_t characteristicHandle = 0;
size_t size = 0;
uint8_t buffer[10];
public:
void OnNotificationTimer();
void Reset();
};
class DfuImage {
public:
DfuImage(Pinetime::Drivers::SpiNorFlash& spiNorFlash) : spiNorFlash{spiNorFlash} {}
DfuImage(Pinetime::Drivers::SpiNorFlash& spiNorFlash) : spiNorFlash {spiNorFlash} {
}
void Init(size_t chunkSize, size_t totalSize, uint16_t expectedCrc);
void Erase();
void Append(uint8_t* data, size_t size);
@ -67,7 +71,6 @@ namespace Pinetime {
void WriteMagicNumber();
uint16_t ComputeCrc(uint8_t const* p_data, uint32_t size, uint16_t const* p_crc);
};
private:
@ -85,27 +88,19 @@ namespace Pinetime {
static constexpr ble_uuid128_t serviceUuid {
.u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00}
};
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00}};
static constexpr ble_uuid128_t packetCharacteristicUuid {
.u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
0xDE, 0xEF, 0x12, 0x12, 0x32, 0x15, 0x00, 0x00}
};
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x32, 0x15, 0x00, 0x00}};
static constexpr ble_uuid128_t controlPointCharacteristicUuid {
.u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
0xDE, 0xEF, 0x12, 0x12, 0x31, 0x15, 0x00, 0x00}
};
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x31, 0x15, 0x00, 0x00}};
static constexpr ble_uuid128_t revisionCharacteristicUuid {
.u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
0xDE, 0xEF, 0x12, 0x12, 0x34, 0x15, 0x00, 0x00}
};
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x34, 0x15, 0x00, 0x00}};
struct ble_gatt_chr_def characteristicDefinition[4];
struct ble_gatt_svc_def serviceDefinition[2];
@ -113,9 +108,7 @@ namespace Pinetime {
uint16_t controlPointCharacteristicHandle;
uint16_t revisionCharacteristicHandle;
enum class States : uint8_t {
Idle, Init, Start, Data, Validate, Validated
};
enum class States : uint8_t { Idle, Init, Start, Data, Validate, Validated };
States state = States::Idle;
enum class ImageTypes : uint8_t {

View File

@ -15,31 +15,21 @@ namespace {
}
// TODO Refactoring - remove dependency to SystemTask
HeartRateService::HeartRateService(Pinetime::System::SystemTask &system, Controllers::HeartRateController& heartRateController) :
system{system},
HeartRateService::HeartRateService(Pinetime::System::SystemTask& system, Controllers::HeartRateController& heartRateController)
: system {system},
heartRateController {heartRateController},
characteristicDefinition{
{
.uuid = (ble_uuid_t *) &heartRateMeasurementUuid,
characteristicDefinition {{.uuid = (ble_uuid_t*) &heartRateMeasurementUuid,
.access_cb = HeartRateServiceServiceCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
.val_handle = &heartRateMeasurementHandle
},
{
0
}
},
.val_handle = &heartRateMeasurementHandle},
{0}},
serviceDefinition {
{
/* Device Information Service */
{/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t*) &heartRateServiceUuid,
.characteristics = characteristicDefinition
},
{
0
},
.characteristics = characteristicDefinition},
{0},
} {
// TODO refactor to prevent this loop dependency (service depends on controller and controller depends on service)
heartRateController.SetService(this);
@ -54,8 +44,7 @@ void HeartRateService::Init() {
ASSERT(res == 0);
}
int HeartRateService::OnHeartRateRequested(uint16_t connectionHandle, uint16_t attributeHandle,
ble_gatt_access_ctxt *context) {
int HeartRateService::OnHeartRateRequested(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context) {
if (attributeHandle == heartRateMeasurementHandle) {
NRF_LOG_INFO("HEARTRATE : handle = %d", heartRateMeasurementHandle);
uint8_t buffer[2] = {0, heartRateController.HeartRate()}; // [0] = flags, [1] = hr value

View File

@ -24,21 +24,14 @@ namespace Pinetime {
static constexpr uint16_t heartRateServiceId {0x180D};
static constexpr uint16_t heartRateMeasurementId {0x2A37};
static constexpr ble_uuid16_t heartRateServiceUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = heartRateServiceId
};
static constexpr ble_uuid16_t heartRateServiceUuid {.u {.type = BLE_UUID_TYPE_16}, .value = heartRateServiceId};
static constexpr ble_uuid16_t heartRateMeasurementUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = heartRateMeasurementId
};
static constexpr ble_uuid16_t heartRateMeasurementUuid {.u {.type = BLE_UUID_TYPE_16}, .value = heartRateMeasurementId};
struct ble_gatt_chr_def characteristicDefinition[3];
struct ble_gatt_svc_def serviceDefinition[2];
uint16_t heartRateMeasurementHandle;
};
}
}

View File

@ -16,42 +16,35 @@ namespace {
const char* ToString(ImmediateAlertService::Levels level) {
switch (level) {
case ImmediateAlertService::Levels::NoAlert: return "Alert : None";
case ImmediateAlertService::Levels::HighAlert: return "Alert : High";
case ImmediateAlertService::Levels::MildAlert: return "Alert : Mild";
default: return "";
case ImmediateAlertService::Levels::NoAlert:
return "Alert : None";
case ImmediateAlertService::Levels::HighAlert:
return "Alert : High";
case ImmediateAlertService::Levels::MildAlert:
return "Alert : Mild";
default:
return "";
}
}
}
ImmediateAlertService::ImmediateAlertService(Pinetime::System::SystemTask& systemTask,
Pinetime::Controllers::NotificationManager &notificationManager) :
systemTask{systemTask},
Pinetime::Controllers::NotificationManager& notificationManager)
: systemTask {systemTask},
notificationManager {notificationManager},
characteristicDefinition{
{
.uuid = (ble_uuid_t *) &alertLevelUuid,
characteristicDefinition {{.uuid = (ble_uuid_t*) &alertLevelUuid,
.access_cb = AlertLevelCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE_NO_RSP,
.val_handle = &alertLevelHandle
},
{
0
}
},
.val_handle = &alertLevelHandle},
{0}},
serviceDefinition {
{
/* Device Information Service */
{/* Device Information Service */
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t*) &immediateAlertServiceUuid,
.characteristics = characteristicDefinition
},
{
0
},
.characteristics = characteristicDefinition},
{0},
} {
}
void ImmediateAlertService::Init() {

View File

@ -13,14 +13,9 @@ namespace Pinetime {
class NotificationManager;
class ImmediateAlertService {
public:
enum class Levels : uint8_t {
NoAlert = 0,
MildAlert = 1,
HighAlert = 2
};
enum class Levels : uint8_t { NoAlert = 0, MildAlert = 1, HighAlert = 2 };
ImmediateAlertService(Pinetime::System::SystemTask &systemTask,
Pinetime::Controllers::NotificationManager &notificationManager);
ImmediateAlertService(Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::NotificationManager& notificationManager);
void Init();
int OnAlertLevelChanged(uint16_t connectionHandle, uint16_t attributeHandle, ble_gatt_access_ctxt* context);
@ -31,15 +26,9 @@ namespace Pinetime {
static constexpr uint16_t immediateAlertServiceId {0x1802};
static constexpr uint16_t alertLevelId {0x2A06};
static constexpr ble_uuid16_t immediateAlertServiceUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = immediateAlertServiceId
};
static constexpr ble_uuid16_t immediateAlertServiceUuid {.u {.type = BLE_UUID_TYPE_16}, .value = immediateAlertServiceId};
static constexpr ble_uuid16_t alertLevelUuid {
.u {.type = BLE_UUID_TYPE_16},
.value = alertLevelId
};
static constexpr ble_uuid16_t alertLevelUuid {.u {.type = BLE_UUID_TYPE_16}, .value = alertLevelId};
struct ble_gatt_chr_def characteristicDefinition[3];
struct ble_gatt_svc_def serviceDefinition[2];

View File

@ -91,75 +91,44 @@ Pinetime::Controllers::MusicService::MusicService(Pinetime::System::SystemTask &
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_NOTIFY,
.val_handle = &eventHandle
};
characteristicDefinition[1] = {.uuid = (ble_uuid_t *) (&msStatusCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[2] = {.uuid = (ble_uuid_t *) (&msTrackCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[3] = {.uuid = (ble_uuid_t *) (&msArtistCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[4] = {.uuid = (ble_uuid_t *) (&msAlbumCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[5] = {.uuid = (ble_uuid_t *) (&msPositionCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
.val_handle = &eventHandle};
characteristicDefinition[1] = {
.uuid = (ble_uuid_t*) (&msStatusCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[2] = {
.uuid = (ble_uuid_t*) (&msTrackCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[3] = {
.uuid = (ble_uuid_t*) (&msArtistCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[4] = {
.uuid = (ble_uuid_t*) (&msAlbumCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[5] = {
.uuid = (ble_uuid_t*) (&msPositionCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[6] = {.uuid = (ble_uuid_t*) (&msTotalLengthCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[7] = {.uuid = (ble_uuid_t*) (&msTotalLengthCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[8] = {.uuid = (ble_uuid_t*) (&msTrackNumberCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[9] = {.uuid = (ble_uuid_t*) (&msTrackTotalCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[10] = {.uuid = (ble_uuid_t*) (&msPlaybackSpeedCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[11] = {.uuid = (ble_uuid_t *) (&msRepeatCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[12] = {.uuid = (ble_uuid_t *) (&msShuffleCharUuid),
.access_cb = MSCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[11] = {
.uuid = (ble_uuid_t*) (&msRepeatCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[12] = {
.uuid = (ble_uuid_t*) (&msShuffleCharUuid), .access_cb = MSCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[13] = {0};
serviceDefinition[0] = {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t *) &msUuid,
.characteristics = characteristicDefinition
};
serviceDefinition[0] = {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = (ble_uuid_t*) &msUuid, .characteristics = characteristicDefinition};
serviceDefinition[1] = {0};
artistName = "Waiting for";
@ -182,8 +151,7 @@ void Pinetime::Controllers::MusicService::Init() {
ASSERT(res == 0);
}
int Pinetime::Controllers::MusicService::OnCommand(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt) {
int Pinetime::Controllers::MusicService::OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) {
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
size_t notifSize = OS_MBUF_PKTLEN(ctxt->om);
@ -257,4 +225,3 @@ int Pinetime::Controllers::MusicService::getProgress() {
int Pinetime::Controllers::MusicService::getTrackLength() {
return trackLength;
}

View File

@ -27,7 +27,8 @@
#undef min
// 00000000-78fc-48fe-8e23-433b3a1942d0
#define MUSIC_SERVICE_UUID_BASE {0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00}
#define MUSIC_SERVICE_UUID_BASE \
{ 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00 }
namespace Pinetime {
namespace System {
@ -41,8 +42,7 @@ namespace Pinetime {
void Init();
int OnCommand(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt);
int OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt);
void event(char event);
@ -68,10 +68,8 @@ namespace Pinetime {
static const char EVENT_MUSIC_VOLUP = 0x05;
static const char EVENT_MUSIC_VOLDOWN = 0x06;
enum MusicStatus {
NotPlaying = 0x00,
Playing = 0x01
};
enum MusicStatus { NotPlaying = 0x00, Playing = 0x01 };
private:
static constexpr uint8_t msId[2] = {0x00, 0x00};
static constexpr uint8_t msEventCharId[2] = {0x01, 0x00};
@ -87,59 +85,20 @@ namespace Pinetime {
static constexpr uint8_t msRepeatCharId[2] = {0x0b, 0x00};
static constexpr uint8_t msShuffleCharId[2] = {0x0c, 0x00};
ble_uuid128_t msUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msEventCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msStatusCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msArtistCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msTrackCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msAlbumCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msPositionCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msTotalLengthCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msTrackNumberCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msTrackTotalCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msPlaybackSpeedCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msRepeatCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msShuffleCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = MUSIC_SERVICE_UUID_BASE
};
ble_uuid128_t msEventCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msStatusCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msArtistCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msTrackCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msAlbumCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msPositionCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msTotalLengthCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msTrackNumberCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msTrackTotalCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msPlaybackSpeedCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msRepeatCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
ble_uuid128_t msShuffleCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = MUSIC_SERVICE_UUID_BASE};
struct ble_gatt_chr_def characteristicDefinition[14];
struct ble_gatt_svc_def serviceDefinition[2];
@ -166,4 +125,3 @@ namespace Pinetime {
};
}
}

View File

@ -49,35 +49,25 @@ Pinetime::Controllers::NavigationService::NavigationService(Pinetime::System::Sy
navProgressCharUuid.value[14] = navId[0];
navProgressCharUuid.value[15] = navId[1];
characteristicDefinition[0] = {.uuid = (ble_uuid_t *) (&navFlagCharUuid),
.access_cb = NAVCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
characteristicDefinition[0] = {
.uuid = (ble_uuid_t*) (&navFlagCharUuid), .access_cb = NAVCallback, .arg = this, .flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[1] = {.uuid = (ble_uuid_t*) (&navNarrativeCharUuid),
.access_cb = NAVCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[2] = {.uuid = (ble_uuid_t*) (&navManDistCharUuid),
.access_cb = NAVCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[3] = {.uuid = (ble_uuid_t*) (&navProgressCharUuid),
.access_cb = NAVCallback,
.arg = this,
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ
};
.flags = BLE_GATT_CHR_F_WRITE | BLE_GATT_CHR_F_READ};
characteristicDefinition[4] = {0};
serviceDefinition[0] = {
.type = BLE_GATT_SVC_TYPE_PRIMARY,
.uuid = (ble_uuid_t *) &navUuid,
.characteristics = characteristicDefinition
};
serviceDefinition[0] = {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = (ble_uuid_t*) &navUuid, .characteristics = characteristicDefinition};
serviceDefinition[1] = {0};
m_progress = 0;
@ -92,8 +82,7 @@ void Pinetime::Controllers::NavigationService::Init() {
ASSERT(res == 0);
}
int Pinetime::Controllers::NavigationService::OnCommand(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt) {
int Pinetime::Controllers::NavigationService::OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt) {
if (ctxt->op == BLE_GATT_ACCESS_OP_WRITE_CHR) {
size_t notifSize = OS_MBUF_PKTLEN(ctxt->om);
@ -114,23 +103,18 @@ int Pinetime::Controllers::NavigationService::OnCommand(uint16_t conn_handle, ui
return 0;
}
std::string Pinetime::Controllers::NavigationService::getFlag()
{
std::string Pinetime::Controllers::NavigationService::getFlag() {
return m_flag;
}
std::string Pinetime::Controllers::NavigationService::getNarrative()
{
std::string Pinetime::Controllers::NavigationService::getNarrative() {
return m_narrative;
}
std::string Pinetime::Controllers::NavigationService::getManDist()
{
std::string Pinetime::Controllers::NavigationService::getManDist() {
return m_manDist;
}
int Pinetime::Controllers::NavigationService::getProgress()
{
int Pinetime::Controllers::NavigationService::getProgress() {
return m_progress;
}

View File

@ -27,7 +27,8 @@
#undef min
// c7e60000-78fc-48fe-8e23-433b3a1942d0
#define NAVIGATION_SERVICE_UUID_BASE {0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00}
#define NAVIGATION_SERVICE_UUID_BASE \
{ 0xd0, 0x42, 0x19, 0x3a, 0x3b, 0x43, 0x23, 0x8e, 0xfe, 0x48, 0xfc, 0x78, 0x00, 0x00, 0x00, 0x00 }
namespace Pinetime {
namespace System {
@ -41,8 +42,7 @@ namespace Pinetime {
void Init();
int OnCommand(uint16_t conn_handle, uint16_t attr_handle,
struct ble_gatt_access_ctxt *ctxt);
int OnCommand(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt);
std::string getFlag();
@ -59,27 +59,12 @@ namespace Pinetime {
static constexpr uint8_t navManDistCharId[2] = {0x03, 0x00};
static constexpr uint8_t navProgressCharId[2] = {0x04, 0x00};
ble_uuid128_t navUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = NAVIGATION_SERVICE_UUID_BASE
};
ble_uuid128_t navUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE};
ble_uuid128_t navFlagCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = NAVIGATION_SERVICE_UUID_BASE
};
ble_uuid128_t navNarrativeCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = NAVIGATION_SERVICE_UUID_BASE
};
ble_uuid128_t navManDistCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = NAVIGATION_SERVICE_UUID_BASE
};
ble_uuid128_t navProgressCharUuid{
.u = {.type = BLE_UUID_TYPE_128},
.value = NAVIGATION_SERVICE_UUID_BASE
};
ble_uuid128_t navFlagCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE};
ble_uuid128_t navNarrativeCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE};
ble_uuid128_t navManDistCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE};
ble_uuid128_t navProgressCharUuid {.u = {.type = BLE_UUID_TYPE_128}, .value = NAVIGATION_SERVICE_UUID_BASE};
struct ble_gatt_chr_def characteristicDefinition[5];
struct ble_gatt_svc_def serviceDefinition[2];
@ -93,4 +78,3 @@ namespace Pinetime {
};
}
}

View File

@ -23,8 +23,8 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Controllers::Battery& batteryController,
Pinetime::Drivers::SpiNorFlash& spiNorFlash,
Controllers::HeartRateController& heartRateController) :
systemTask{systemTask},
Controllers::HeartRateController& heartRateController)
: systemTask {systemTask},
bleController {bleController},
dateTimeController {dateTimeController},
notificationManager {notificationManager},
@ -48,7 +48,8 @@ int GAPEventCallback(struct ble_gap_event *event, void *arg) {
}
void NimbleController::Init() {
while (!ble_hs_synced()) {}
while (!ble_hs_synced()) {
}
ble_svc_gap_init();
ble_svc_gatt_init();
@ -81,7 +82,8 @@ void NimbleController::Init() {
}
void NimbleController::StartAdvertising() {
if(bleController.IsConnected() || ble_gap_conn_active() || ble_gap_adv_active()) return;
if (bleController.IsConnected() || ble_gap_conn_active() || ble_gap_adv_active())
return;
ble_svc_gap_device_name_set(deviceName);
@ -101,8 +103,7 @@ void NimbleController::StartAdvertising() {
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
fields.flags = BLE_HS_ADV_F_DISC_GEN |
BLE_HS_ADV_F_BREDR_UNSUP;
fields.flags = BLE_HS_ADV_F_DISC_GEN | BLE_HS_ADV_F_BREDR_UNSUP;
// fields.uuids128 = BLE_UUID128(BLE_UUID128_DECLARE(
// 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
// 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff));
@ -121,8 +122,7 @@ void NimbleController::StartAdvertising() {
ble_gap_adv_rsp_set_fields(&rsp_fields);
// ASSERT(res == 0);
ble_gap_adv_start(addrType, NULL, 180000,
&adv_params, GAPEventCallback, this);
ble_gap_adv_start(addrType, NULL, 180000, &adv_params, GAPEventCallback, this);
// ASSERT(res == 0);// TODO I've disabled these ASSERT as they sometime asserts and reset the mcu.
// For now, the advertising is restarted as soon as it ends. There may be a race condition
// that prevent the advertising from restarting reliably.
@ -141,8 +141,7 @@ int NimbleController::OnGAPEvent(ble_gap_event *event) {
NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_CONNECT");
/* A new connection was established or a connection attempt failed. */
NRF_LOG_INFO("connection %s; status=%d ", event->connect.status == 0 ? "established" : "failed",
event->connect.status);
NRF_LOG_INFO("connection %s; status=%d ", event->connect.status == 0 ? "established" : "failed", event->connect.status);
if (event->connect.status != 0) {
/* Connection failed; resume advertising. */
@ -154,8 +153,7 @@ int NimbleController::OnGAPEvent(ble_gap_event *event) {
connectionHandle = event->connect.conn_handle;
// Service discovery is deffered via systemtask
}
}
break;
} break;
case BLE_GAP_EVENT_DISCONNECT:
NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_DISCONNECT");
NRF_LOG_INFO("disconnect; reason=%d", event->disconnect.reason);
@ -187,10 +185,7 @@ int NimbleController::OnGAPEvent(ble_gap_event *event) {
event->subscribe.prev_indicate);
return 0;
case BLE_GAP_EVENT_MTU:
NRF_LOG_INFO("mtu update event; conn_handle=%d cid=%d mtu=%d\n",
event->mtu.conn_handle,
event->mtu.channel_id,
event->mtu.value);
NRF_LOG_INFO("mtu update event; conn_handle=%d cid=%d mtu=%d\n", event->mtu.conn_handle, event->mtu.channel_id, event->mtu.value);
return 0;
case BLE_GAP_EVENT_REPEAT_PAIRING: {
@ -216,9 +211,7 @@ int NimbleController::OnGAPEvent(ble_gap_event *event) {
NRF_LOG_INFO("received %s; conn_handle=%d attr_handle=%d "
"attr_len=%d",
event->notify_rx.indication ?
"indication" :
"notification",
event->notify_rx.indication ? "indication" : "notification",
event->notify_rx.conn_handle,
event->notify_rx.attr_handle,
notifSize);
@ -239,8 +232,6 @@ void NimbleController::StartDiscovery() {
serviceDiscovery.StartDiscovery(connectionHandle);
}
uint16_t NimbleController::connHandle() {
return connectionHandle;
}

View File

@ -37,28 +37,37 @@ namespace Pinetime {
class NimbleController {
public:
NimbleController(Pinetime::System::SystemTask& systemTask, Pinetime::Controllers::Ble& bleController,
DateTime& dateTimeController, Pinetime::Controllers::NotificationManager& notificationManager,
Controllers::Battery& batteryController, Pinetime::Drivers::SpiNorFlash& spiNorFlash,
NimbleController(Pinetime::System::SystemTask& systemTask,
Pinetime::Controllers::Ble& bleController,
DateTime& dateTimeController,
Pinetime::Controllers::NotificationManager& notificationManager,
Controllers::Battery& batteryController,
Pinetime::Drivers::SpiNorFlash& spiNorFlash,
Controllers::HeartRateController& heartRateController);
void Init();
void StartAdvertising();
int OnGAPEvent(ble_gap_event* event);
int OnDiscoveryEvent(uint16_t i, const ble_gatt_error* pError, const ble_gatt_svc* pSvc);
int OnCTSCharacteristicDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error,
const ble_gatt_chr *characteristic);
int OnANSCharacteristicDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error *error,
const ble_gatt_chr *characteristic);
int OnCTSCharacteristicDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic);
int OnANSCharacteristicDiscoveryEvent(uint16_t connectionHandle, const ble_gatt_error* error, const ble_gatt_chr* characteristic);
int OnCurrentTimeReadResult(uint16_t connectionHandle, const ble_gatt_error* error, ble_gatt_attr* attribute);
int OnANSDescriptorDiscoveryEventCallback(uint16_t connectionHandle, const ble_gatt_error *error,
uint16_t characteristicValueHandle, const ble_gatt_dsc *descriptor);
int OnANSDescriptorDiscoveryEventCallback(uint16_t connectionHandle,
const ble_gatt_error* error,
uint16_t characteristicValueHandle,
const ble_gatt_dsc* descriptor);
void StartDiscovery();
Pinetime::Controllers::MusicService& music() {return musicService;};
Pinetime::Controllers::NavigationService& navigation() {return navService;};
Pinetime::Controllers::AlertNotificationService& alertService() {return anService;};
Pinetime::Controllers::MusicService& music() {
return musicService;
};
Pinetime::Controllers::NavigationService& navigation() {
return navService;
};
Pinetime::Controllers::AlertNotificationService& alertService() {
return anService;
};
uint16_t connHandle();
@ -87,9 +96,7 @@ namespace Pinetime {
ble_uuid128_t dfuServiceUuid {
.u {.type = BLE_UUID_TYPE_128},
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15,
0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00}
};
.value = {0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, 0xDE, 0xEF, 0x12, 0x12, 0x30, 0x15, 0x00, 0x00}};
ServiceDiscovery serviceDiscovery;
};

View File

@ -6,7 +6,6 @@ using namespace Pinetime::Controllers;
constexpr uint8_t NotificationManager::MessageSize;
void NotificationManager::Push(NotificationManager::Notification&& notif) {
notif.id = GetNextId();
notif.valid = true;
@ -14,7 +13,8 @@ void NotificationManager::Push(NotificationManager::Notification &&notif) {
writeIndex = (writeIndex + 1 < TotalNbNotifications) ? writeIndex + 1 : 0;
if (!empty)
readIndex = (readIndex + 1 < TotalNbNotifications) ? readIndex + 1 : 0;
else empty = false;
else
empty = false;
newNotification = true;
}
@ -30,8 +30,11 @@ NotificationManager::Notification::Id NotificationManager::GetNextId() {
}
NotificationManager::Notification NotificationManager::GetNext(NotificationManager::Notification::Id id) {
auto currentIterator = std::find_if(notifications.begin(), notifications.end(), [id](const Notification& n){return n.valid && n.id == id;});
if(currentIterator == notifications.end() || currentIterator->id != id) return Notification{};
auto currentIterator = std::find_if(notifications.begin(), notifications.end(), [id](const Notification& n) {
return n.valid && n.id == id;
});
if (currentIterator == notifications.end() || currentIterator->id != id)
return Notification {};
auto& lastNotification = notifications[readIndex];
@ -42,15 +45,19 @@ NotificationManager::Notification NotificationManager::GetNext(NotificationManag
else
result = *(currentIterator + 1);
if(result.id <= id) return {};
if (result.id <= id)
return {};
result.index = (lastNotification.id - result.id) + 1;
return result;
}
NotificationManager::Notification NotificationManager::GetPrevious(NotificationManager::Notification::Id id) {
auto currentIterator = std::find_if(notifications.begin(), notifications.end(), [id](const Notification& n){return n.valid && n.id == id;});
if(currentIterator == notifications.end() || currentIterator->id != id) return Notification{};
auto currentIterator = std::find_if(notifications.begin(), notifications.end(), [id](const Notification& n) {
return n.valid && n.id == id;
});
if (currentIterator == notifications.end() || currentIterator->id != id)
return Notification {};
auto& lastNotification = notifications[readIndex];
@ -61,7 +68,8 @@ NotificationManager::Notification NotificationManager::GetPrevious(NotificationM
else
result = *(currentIterator - 1);
if(result.id >= id) return {};
if (result.id >= id)
return {};
result.index = (lastNotification.id - result.id) + 1;
return result;
@ -84,7 +92,9 @@ bool NotificationManager::ClearNewNotificationFlag() {
}
size_t NotificationManager::NbNotifications() const {
return std::count_if(notifications.begin(), notifications.end(), [](const Notification& n){ return n.valid;});
return std::count_if(notifications.begin(), notifications.end(), [](const Notification& n) {
return n.valid;
});
}
const char* NotificationManager::Notification::Message() const {

View File

@ -9,7 +9,19 @@ namespace Pinetime {
namespace Controllers {
class NotificationManager {
public:
enum class Categories {Unknown, SimpleAlert, Email, News, IncomingCall, MissedCall, Sms, VoiceMail, Schedule, HighProriotyAlert, InstantMessage };
enum class Categories {
Unknown,
SimpleAlert,
Email,
News,
IncomingCall,
MissedCall,
Sms,
VoiceMail,
Schedule,
HighProriotyAlert,
InstantMessage
};
static constexpr uint8_t MessageSize {100};
struct Notification {
@ -35,7 +47,9 @@ namespace Pinetime {
bool IsVibrationEnabled();
void ToggleVibrations();
static constexpr size_t MaximumMessageSize() { return MessageSize; };
static constexpr size_t MaximumMessageSize() {
return MessageSize;
};
size_t NbNotifications() const;
private:

View File

@ -5,7 +5,6 @@
using namespace Pinetime::Controllers;
ServiceDiscovery::ServiceDiscovery(std::array<BleClient*, 2>&& clients) : clients {clients} {
}
void ServiceDiscovery::StartDiscovery(uint16_t connectionHandle) {

View File

@ -13,7 +13,6 @@ namespace Pinetime {
void StartDiscovery(uint16_t connectionHandle);
private:
BleClient** clientIterator;
std::array<BleClient*, 2> clients;

View File

@ -4,7 +4,6 @@
using namespace Pinetime::Controllers;
void BrightnessController::Init() {
nrf_gpio_cfg_output(pinLcdBacklight1);
nrf_gpio_cfg_output(pinLcdBacklight2);
@ -41,19 +40,33 @@ void BrightnessController::Set(BrightnessController::Levels level) {
void BrightnessController::Lower() {
switch (level) {
case Levels::High: Set(Levels::Medium); break;
case Levels::Medium: Set(Levels::Low); break;
case Levels::Low: Set(Levels::Off); break;
default: break;
case Levels::High:
Set(Levels::Medium);
break;
case Levels::Medium:
Set(Levels::Low);
break;
case Levels::Low:
Set(Levels::Off);
break;
default:
break;
}
}
void BrightnessController::Higher() {
switch (level) {
case Levels::Off: Set(Levels::Low); break;
case Levels::Low: Set(Levels::Medium); break;
case Levels::Medium: Set(Levels::High); break;
default: break;
case Levels::Off:
Set(Levels::Low);
break;
case Levels::Low:
Set(Levels::Medium);
break;
case Levels::Medium:
Set(Levels::High);
break;
default:
break;
}
}
@ -71,28 +84,43 @@ void BrightnessController::Restore() {
void BrightnessController::Step() {
switch (level) {
case Levels::Low: Set(Levels::Medium); break;
case Levels::Medium: Set(Levels::High); break;
case Levels::High: Set(Levels::Low); break;
default: break;
case Levels::Low:
Set(Levels::Medium);
break;
case Levels::Medium:
Set(Levels::High);
break;
case Levels::High:
Set(Levels::Low);
break;
default:
break;
}
}
const char* BrightnessController::GetIcon() {
switch (level) {
case Levels::Medium: return Applications::Screens::Symbols::brightnessMedium;
case Levels::High: return Applications::Screens::Symbols::brightnessHigh;
default: break;
case Levels::Medium:
return Applications::Screens::Symbols::brightnessMedium;
case Levels::High:
return Applications::Screens::Symbols::brightnessHigh;
default:
break;
}
return Applications::Screens::Symbols::brightnessLow;
}
const char* BrightnessController::ToString() {
switch (level) {
case Levels::Off: return "Off";
case Levels::Low: return "Low";
case Levels::Medium: return "Medium";
case Levels::High: return "High";
default : return "???";
case Levels::Off:
return "Off";
case Levels::Low:
return "Low";
case Levels::Medium:
return "Medium";
case Levels::High:
return "High";
default:
return "???";
}
}

View File

@ -6,13 +6,12 @@
using namespace Pinetime::Controllers;
DateTime::DateTime(System::SystemTask& systemTask) : systemTask {systemTask} {
}
void DateTime::SetTime(uint16_t year, uint8_t month, uint8_t day, uint8_t dayOfWeek, uint8_t hour, uint8_t minute,
uint8_t second, uint32_t systickCounter) {
std::tm tm = { /* .tm_sec = */ second,
void DateTime::SetTime(
uint16_t year, uint8_t month, uint8_t day, uint8_t dayOfWeek, uint8_t hour, uint8_t minute, uint8_t second, uint32_t systickCounter) {
std::tm tm = {
/* .tm_sec = */ second,
/* .tm_min = */ minute,
/* .tm_hour = */ hour,
/* .tm_mday = */ day,
@ -105,95 +104,17 @@ const char *DateTime::DayOfWeekShortToStringLow() {
return DateTime::DaysStringShortLow[(uint8_t) dayOfWeek];
}
char const* DateTime::DaysStringLow[] = {"--", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
char const *DateTime::DaysStringLow[] = {
"--",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
};
char const* DateTime::DaysStringShortLow[] = {"--", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
char const *DateTime::DaysStringShortLow[] = {
"--",
"Mon",
"Tue",
"Wed",
"Thu",
"Fri",
"Sat",
"Sun"
};
char const* DateTime::DaysStringShort[] = {"--", "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
char const *DateTime::DaysStringShort[] = {
"--",
"MON",
"TUE",
"WED",
"THU",
"FRI",
"SAT",
"SUN"
};
char const* DateTime::DaysString[] = {"--", "MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"};
char const *DateTime::DaysString[] = {
"--",
"MONDAY",
"TUESDAY",
"WEDNESDAY",
"THURSDAY",
"FRIDAY",
"SATURDAY",
"SUNDAY"
};
char const* DateTime::MonthsString[] = {"--", "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"};
char const *DateTime::MonthsString[] = {
"--",
"JAN",
"FEB",
"MAR",
"APR",
"MAY",
"JUN",
"JUL",
"AUG",
"SEP",
"OCT",
"NOV",
"DEC"
};
char const *DateTime::MonthsStringLow[] = {
"--",
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
char const* DateTime::MonthsStringLow[] = {"--", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
char const* DateTime::MonthsLow[] = {
"--",
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
"--", "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};

View File

@ -11,19 +11,54 @@ namespace Pinetime {
class DateTime {
public:
enum class Days : uint8_t { Unknown, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday };
enum class Months : uint8_t {Unknown, January, February, March, April, May, June, July, August, September, October, November, December};
enum class Months : uint8_t {
Unknown,
January,
February,
March,
April,
May,
June,
July,
August,
September,
October,
November,
December
};
DateTime(System::SystemTask& systemTask);
void SetTime(uint16_t year, uint8_t month, uint8_t day, uint8_t dayOfWeek, uint8_t hour, uint8_t minute, uint8_t second, uint32_t systickCounter);
void SetTime(uint16_t year,
uint8_t month,
uint8_t day,
uint8_t dayOfWeek,
uint8_t hour,
uint8_t minute,
uint8_t second,
uint32_t systickCounter);
void UpdateTime(uint32_t systickCounter);
uint16_t Year() const { return year; }
Months Month() const { return month; }
uint8_t Day() const { return day; }
Days DayOfWeek() const { return dayOfWeek; }
uint8_t Hours() const { return hour; }
uint8_t Minutes() const { return minute; }
uint8_t Seconds() const { return second; }
uint16_t Year() const {
return year;
}
Months Month() const {
return month;
}
uint8_t Day() const {
return day;
}
Days DayOfWeek() const {
return dayOfWeek;
}
uint8_t Hours() const {
return hour;
}
uint8_t Minutes() const {
return minute;
}
uint8_t Seconds() const {
return second;
}
const char* MonthShortToString();
const char* MonthShortToStringLow();
@ -33,8 +68,13 @@ namespace Pinetime {
const char* DayOfWeekToStringLow();
const char* DayOfWeekShortToStringLow();
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> CurrentDateTime() const { return currentDateTime; }
std::chrono::seconds Uptime() const { return uptime; }
std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> CurrentDateTime() const {
return currentDateTime;
}
std::chrono::seconds Uptime() const {
return uptime;
}
private:
System::SystemTask& systemTask;
uint16_t year = 0;
@ -58,7 +98,6 @@ namespace Pinetime {
static char const* MonthsString[];
static char const* MonthsStringLow[];
static char const* MonthsLow[];
};
}
}

View File

@ -10,6 +10,7 @@ namespace Pinetime {
bool IsValidated() const;
void Reset();
private:
static constexpr uint32_t validBitAdress {0x7BFE8};
static constexpr uint32_t validBitValue {1};

View File

@ -6,7 +6,6 @@ Gfx::Gfx(Pinetime::Drivers::St7789 &lcd) : lcd{lcd} {
}
void Gfx::Init() {
}
void Gfx::ClearScreen() {
@ -20,7 +19,6 @@ void Gfx::ClearScreen() {
lcd.DrawBuffer(0, 0, width, height, reinterpret_cast<const uint8_t*>(buffer), width * 2);
WaitTransferFinished();
}
void Gfx::FillRectangle(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint16_t color) {
@ -101,8 +99,7 @@ void Gfx::DrawChar(const FONT_INFO *font, uint8_t c, uint8_t *x, uint8_t y, uint
for (uint8_t k = 0; k < 8; k++) {
if ((1 << (7 - k)) & font->data[font->charInfo[char_idx].offset + j]) {
buffer[(j * 8) + k] = color;
}
else {
} else {
buffer[(j * 8) + k] = bg;
}
}
@ -142,7 +139,8 @@ void Gfx::SetBackgroundColor(uint16_t color) {
}
bool Gfx::GetNextBuffer(uint8_t** data, size_t& size) {
if(!state.busy) return false;
if (!state.busy)
return false;
state.remainingIterations--;
if (state.remainingIterations == 0) {
state.busy = false;
@ -162,8 +160,7 @@ bool Gfx::GetNextBuffer(uint8_t **data, size_t &size) {
for (uint8_t k = 0; k < 8; k++) {
if ((1 << (7 - k)) & state.font->data[state.font->charInfo[char_idx].offset + ((state.currentIteration + 1) * bytes_in_line) + j]) {
buffer[(j * 8) + k] = state.color;
}
else {
} else {
buffer[(j * 8) + k] = bg;
}
}

View File

@ -23,20 +23,19 @@ namespace Pinetime {
void SetScrollArea(uint16_t topFixedLines, uint16_t scrollLines, uint16_t bottomFixedLines);
void SetScrollStartLine(uint16_t line);
void Sleep();
void Wakeup();
bool GetNextBuffer(uint8_t** buffer, size_t& size) override;
void pixel_draw(uint8_t x, uint8_t y, uint16_t color);
private:
static constexpr uint8_t width = 240;
static constexpr uint8_t height = 240;
enum class Action { None, FillRectangle, DrawChar };
struct State {
State() : busy{false}, action{Action::None}, remainingIterations{0}, currentIteration{0} {}
State() : busy {false}, action {Action::None}, remainingIterations {0}, currentIteration {0} {
}
volatile bool busy;
volatile Action action;
volatile uint16_t remainingIterations;

View File

@ -10,7 +10,6 @@ using namespace Pinetime::Controllers;
/** Original implementation from wasp-os : https://github.com/daniel-thompson/wasp-os/blob/master/wasp/ppg.py */
Biquad::Biquad(float b0, float b1, float b2, float a1, float a2) : b0 {b0}, b1 {b1}, b2 {b2}, a1 {a1}, a2 {a2} {
}
float Biquad::Step(float x) {

View File

@ -5,10 +5,8 @@
using namespace Pinetime::Controllers;
HeartRateController::HeartRateController(Pinetime::System::SystemTask& systemTask) : systemTask {systemTask} {
}
void HeartRateController::Update(HeartRateController::States newState, uint8_t heartRate) {
this->state = newState;
if (this->heartRate != heartRate) {
@ -38,4 +36,3 @@ void HeartRateController::SetHeartRateTask(Pinetime::Applications::HeartRateTask
void HeartRateController::SetService(Pinetime::Controllers::HeartRateService* service) {
this->service = service;
}

View File

@ -22,8 +22,12 @@ namespace Pinetime {
void Update(States newState, uint8_t heartRate);
void SetHeartRateTask(Applications::HeartRateTask* task);
States State() const { return state; }
uint8_t HeartRate() const { return heartRate; }
States State() const {
return state;
}
uint8_t HeartRate() const {
return heartRate;
}
void SetService(Pinetime::Controllers::HeartRateService* service);

View File

@ -11,7 +11,7 @@ using namespace Pinetime::Controllers;
/** Original implementation from wasp-os : https://github.com/daniel-thompson/wasp-os/blob/master/wasp/ppg.py */
namespace {
int Compare(int* d1, int* d2, size_t count) {
int Compare(int8_t* d1, int8_t* d2, size_t count) {
int e = 0;
for (size_t i = 0; i < count; i++) {
auto d = d1[i] - d2[i];
@ -20,11 +20,11 @@ namespace {
return e;
}
int CompareShift(int* d, int shift, size_t count) {
int CompareShift(int8_t* d, int shift, size_t count) {
return Compare(d + shift, d, count - shift);
}
int Trough(int* d, size_t size, float mn, float mx) {
int Trough(int8_t* d, size_t size, uint8_t mn, uint8_t mx) {
auto z2 = CompareShift(d, mn - 2, size);
auto z1 = CompareShift(d, mn - 1, size);
for (int i = mn; i < mx + 1; i++) {
@ -38,20 +38,20 @@ namespace {
}
}
Ppg::Ppg(float spl) : offset{spl},
Ppg::Ppg(float spl)
: offset {spl},
hpf {0.87033078, -1.74066156, 0.87033078, -1.72377617, 0.75754694},
agc {20, 0.971, 2},
lpf {0.11595249, 0.23190498, 0.11595249, -0.72168143, 0.18549138} {
}
int Ppg::Preprocess(float spl) {
int8_t Ppg::Preprocess(float spl) {
spl -= offset;
spl = hpf.Step(spl);
spl = agc.Step(spl);
spl = lpf.Step(spl);
auto spl_int = static_cast<int>(spl);
auto spl_int = static_cast<int8_t>(spl);
if (dataIndex < 200)
data[dataIndex++] = spl_int;

View File

@ -10,21 +10,20 @@ namespace Pinetime {
public:
explicit Ppg(float spl);
int Preprocess(float spl);
int8_t Preprocess(float spl);
float HeartRate();
void SetOffset(uint16_t i);
void Reset();
private:
std::array<int, 200> data;
std::array<int8_t, 200> data;
size_t dataIndex = 0;
float offset;
Biquad hpf;
Ptagc agc;
Biquad lpf;
float ProcessHeartRate();
};
}

View File

@ -11,7 +11,6 @@ using namespace Pinetime::Controllers;
/** Original implementation from wasp-os : https://github.com/daniel-thompson/wasp-os/blob/master/wasp/ppg.py */
Ptagc::Ptagc(float start, float decay, float threshold) : peak {start}, decay {decay}, boost {1.0f / decay}, threshold {threshold} {
}
float Ptagc::Step(float spl) {

View File

@ -12,7 +12,6 @@ namespace Pinetime {
float decay;
float boost;
float threshold;
};
}
}

View File

@ -8,14 +8,24 @@ namespace Pinetime {
public:
void Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps);
uint16_t X() const { return x; }
uint16_t Y() const { return y; }
uint16_t Z() const { return z; }
uint32_t NbSteps() const { return nbSteps; }
int16_t X() const {
return x;
}
int16_t Y() const {
return y;
}
int16_t Z() const {
return z;
}
uint32_t NbSteps() const {
return nbSteps;
}
bool ShouldWakeUp(bool isSleeping);
void IsSensorOk(bool isOk);
bool IsSensorOk() const { return isSensorOk; }
bool IsSensorOk() const {
return isSensorOk;
}
private:
uint32_t nbSteps;

View File

@ -7,18 +7,19 @@ APP_TIMER_DEF(vibTimer);
using namespace Pinetime::Controllers;
MotorController::MotorController( Controllers::Settings &settingsController ) : settingsController{settingsController} {}
MotorController::MotorController(Controllers::Settings& settingsController) : settingsController {settingsController} {
}
void MotorController::Init() {
nrf_gpio_cfg_output(pinMotor);
nrf_gpio_pin_set(pinMotor);
app_timer_init();
app_timer_create(&vibTimer, APP_TIMER_MODE_SINGLE_SHOT, vibrate);
}
void MotorController::SetDuration(uint8_t motorDuration) {
if ( settingsController.GetVibrationStatus() == Controllers::Settings::Vibration::OFF ) return;
if (settingsController.GetVibrationStatus() == Controllers::Settings::Vibration::OFF)
return;
nrf_gpio_pin_clear(pinMotor);
/* Start timer for motorDuration miliseconds and timer triggers vibrate() when it finishes*/

View File

@ -3,7 +3,6 @@
using namespace Pinetime::Tools;
RleDecoder::RleDecoder(const uint8_t* buffer, size_t size) : buffer {buffer}, size {size} {
}
RleDecoder::RleDecoder(const uint8_t* buffer, size_t size, uint16_t foregroundColor, uint16_t backgroundColor) : RleDecoder {buffer, size} {
@ -11,7 +10,6 @@ RleDecoder::RleDecoder(const uint8_t *buffer, size_t size, uint16_t foregroundCo
this->backgroundColor = backgroundColor;
}
void RleDecoder::DecodeNext(uint8_t* output, size_t maxBytes) {
for (; encodedBufferIndex < size; encodedBufferIndex++) {
uint8_t rl = buffer[encodedBufferIndex] - processedCount;
@ -36,4 +34,3 @@ void RleDecoder::DecodeNext(uint8_t *output, size_t maxBytes) {
color = backgroundColor;
}
}

View File

@ -11,14 +11,13 @@ struct SettingsHeader {
#define HEADER_SIZE sizeof(SettingsHeader)
Settings::Settings( Pinetime::Drivers::SpiNorFlash &spiNorFlash ) : spiNorFlash{spiNorFlash} {}
Settings::Settings(Pinetime::Drivers::SpiNorFlash& spiNorFlash) : spiNorFlash {spiNorFlash} {
}
void Settings::Init() {
// Load default settings from Flash
LoadSettingsFromFlash();
}
void Settings::SaveSettings() {
@ -30,7 +29,6 @@ void Settings::SaveSettings() {
settingsChanged = false;
}
bool Settings::FindHeader() {
SettingsHeader settingsHeader;
uint8_t bufferHead[sizeof(settingsHeader)];
@ -66,7 +64,6 @@ void Settings::SetHeader( bool state ) {
std::memcpy(bufferHead, &settingsHeader, sizeof(settingsHeader));
spiNorFlash.Write(settingsBaseAddr + (settingsFlashBlock * 0x1000), bufferHead, sizeof(settingsHeader));
}
void Settings::SaveSettingsData() {
@ -89,7 +86,6 @@ void Settings::LoadSettingsFromFlash() {
// never used :)
ReadSettingsData();
}
}
void Settings::SaveSettingsToFlash() {
@ -106,7 +102,8 @@ void Settings::SaveSettingsToFlash() {
}
settingsFlashBlock++;
if ( settingsFlashBlock > 9 ) settingsFlashBlock = 0;
if (settingsFlashBlock > 9)
settingsFlashBlock = 0;
EraseBlock();
SetHeader(true);

View File

@ -19,49 +19,82 @@ namespace Pinetime {
void SaveSettings();
void SetClockFace(uint8_t face) {
if ( face != settings.clockFace ) settingsChanged = true;
if (face != settings.clockFace)
settingsChanged = true;
settings.clockFace = face;
};
uint8_t GetClockFace() const { return settings.clockFace; };
uint8_t GetClockFace() const {
return settings.clockFace;
};
void SetAppMenu( uint8_t menu ) { appMenu = menu; };
uint8_t GetAppMenu() { return appMenu; };
void SetAppMenu(uint8_t menu) {
appMenu = menu;
};
uint8_t GetAppMenu() {
return appMenu;
};
void SetSettingsMenu( uint8_t menu ) { settingsMenu = menu; };
uint8_t GetSettingsMenu() const { return settingsMenu; };
void SetSettingsMenu(uint8_t menu) {
settingsMenu = menu;
};
uint8_t GetSettingsMenu() const {
return settingsMenu;
};
void SetClockType(ClockType clocktype) {
if ( clocktype != settings.clockType ) settingsChanged = true;
if (clocktype != settings.clockType)
settingsChanged = true;
settings.clockType = clocktype;
};
ClockType GetClockType() const { return settings.clockType; };
ClockType GetClockType() const {
return settings.clockType;
};
void SetVibrationStatus(Vibration status) {
if ( status != settings.vibrationStatus ) settingsChanged = true;
if (status != settings.vibrationStatus)
settingsChanged = true;
settings.vibrationStatus = status;
};
Vibration GetVibrationStatus() const { return settings.vibrationStatus; };
Vibration GetVibrationStatus() const {
return settings.vibrationStatus;
};
void SetScreenTimeOut(uint32_t timeout) {
if ( timeout != settings.screenTimeOut ) settingsChanged = true;
if (timeout != settings.screenTimeOut)
settingsChanged = true;
settings.screenTimeOut = timeout;
};
uint32_t GetScreenTimeOut() const { return settings.screenTimeOut; };
uint32_t GetScreenTimeOut() const {
return settings.screenTimeOut;
};
void setWakeUpMode(WakeUpMode wakeUp) {
if ( wakeUp != settings.wakeUpMode ) settingsChanged = true;
if (wakeUp != settings.wakeUpMode)
settingsChanged = true;
settings.wakeUpMode = wakeUp;
};
WakeUpMode getWakeUpMode() const { return settings.wakeUpMode; };
WakeUpMode getWakeUpMode() const {
return settings.wakeUpMode;
};
void SetBrightness(Controllers::BrightnessController::Levels level) {
if ( level != settings.brightLevel ) settingsChanged = true;
if (level != settings.brightLevel)
settingsChanged = true;
settings.brightLevel = level;
};
Controllers::BrightnessController::Levels GetBrightness() const { return settings.brightLevel; };
Controllers::BrightnessController::Levels GetBrightness() const {
return settings.brightLevel;
};
void SetStepsGoal( uint32_t goal ) {
if ( goal != settings.stepsGoal )
settingsChanged = true;
settings.stepsGoal = goal;
};
uint32_t GetStepsGoal() const { return settings.stepsGoal; };
private:
Pinetime::Drivers::SpiNorFlash& spiNorFlash;
struct SettingsData {
@ -70,13 +103,12 @@ namespace Pinetime {
uint8_t clockFace = 0;
uint32_t stepsGoal = 1000;
uint32_t stepsGoal = 10000;
uint32_t screenTimeOut = 15000;
WakeUpMode wakeUpMode = WakeUpMode::None;
Controllers::BrightnessController::Levels brightLevel = Controllers::BrightnessController::Levels::Medium;
};
SettingsData settings;
@ -99,7 +131,6 @@ namespace Pinetime {
void SaveSettingsData();
void LoadSettingsFromFlash();
void SaveSettingsToFlash();
};
}
}

View File

@ -0,0 +1,64 @@
//
// Created by florian on 16.05.21.
//
#include "TimerController.h"
#include "systemtask/SystemTask.h"
#include "app_timer.h"
#include "task.h"
using namespace Pinetime::Controllers;
APP_TIMER_DEF(timerAppTimer);
TimerController::TimerController(System::SystemTask& systemTask) : systemTask{systemTask} {
}
void TimerController::Init() {
app_timer_create(&timerAppTimer, APP_TIMER_MODE_SINGLE_SHOT, timerEnd);
}
void TimerController::StartTimer(uint32_t duration) {
app_timer_stop(timerAppTimer);
auto currentTicks = xTaskGetTickCount();
app_timer_start(timerAppTimer, APP_TIMER_TICKS(duration), this);
endTicks = currentTicks + APP_TIMER_TICKS(duration);
timerRunning = true;
}
uint32_t TimerController::GetTimeRemaining() {
if (!timerRunning) {
return 0;
}
auto currentTicks = xTaskGetTickCount();
TickType_t deltaTicks = 0;
if (currentTicks > endTicks) {
deltaTicks = 0xffffffff - currentTicks;
deltaTicks += (endTicks + 1);
} else {
deltaTicks = endTicks - currentTicks;
}
return (static_cast<TickType_t>(deltaTicks) / static_cast<TickType_t>(configTICK_RATE_HZ)) * 1000;
}
void TimerController::timerEnd(void* p_context) {
auto* controller = static_cast<Controllers::TimerController*> (p_context);
controller->timerRunning = false;
controller->systemTask.PushMessage(System::SystemTask::Messages::OnTimerDone);
}
void TimerController::StopTimer() {
app_timer_stop(timerAppTimer);
timerRunning = false;
}
bool TimerController::IsRunning() {
return timerRunning;
}

View File

@ -0,0 +1,36 @@
#pragma once
#include <cstdint>
#include "app_timer.h"
#include "portmacro_cmsis.h"
namespace Pinetime {
namespace System {
class SystemTask;
}
namespace Controllers {
class TimerController {
public:
TimerController(Pinetime::System::SystemTask& systemTask);
void Init();
void StartTimer(uint32_t duration);
void StopTimer();
uint32_t GetTimeRemaining();
bool IsRunning();
private:
System::SystemTask& systemTask;
static void timerEnd(void* p_context);
TickType_t endTicks;
bool timerRunning = false;
};
}
}

View File

@ -3,9 +3,33 @@
namespace Pinetime {
namespace Applications {
enum class Apps {
None, Launcher, Clock, SysInfo, FirmwareUpdate, FirmwareValidation, NotificationsPreview, Notifications, FlashLight, BatteryInfo,
Music, Paint, Paddle, Twos, HeartRate, Navigation, StopWatch, Motion,
QuickSettings, Settings, SettingWatchFace, SettingTimeFormat, SettingDisplay, SettingWakeUp
None,
Launcher,
Clock,
SysInfo,
FirmwareUpdate,
FirmwareValidation,
NotificationsPreview,
Notifications,
Timer,
FlashLight,
BatteryInfo,
Music,
Paint,
Paddle,
Twos,
HeartRate,
Navigation,
StopWatch,
Motion,
Steps,
QuickSettings,
Settings,
SettingWatchFace,
SettingTimeFormat,
SettingDisplay,
SettingWakeUp,
SettingSteps
};
}
}

View File

@ -2,11 +2,13 @@
#include <libraries/log/nrf_log.h>
#include <displayapp/screens/HeartRate.h>
#include <displayapp/screens/Motion.h>
#include <displayapp/screens/Timer.h>
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
#include "components/datetime/DateTimeController.h"
#include "components/ble/NotificationManager.h"
#include "components/motion/MotionController.h"
#include "components/motor/MotorController.h"
#include "displayapp/screens/ApplicationList.h"
#include "displayapp/screens/Brightness.h"
#include "displayapp/screens/Clock.h"
@ -24,6 +26,7 @@
#include "displayapp/screens/Twos.h"
#include "displayapp/screens/FlashLight.h"
#include "displayapp/screens/BatteryInfo.h"
#include "displayapp/screens/Steps.h"
#include "drivers/Cst816s.h"
#include "drivers/St7789.h"
@ -36,19 +39,26 @@
#include "displayapp/screens/settings/SettingTimeFormat.h"
#include "displayapp/screens/settings/SettingWakeUp.h"
#include "displayapp/screens/settings/SettingDisplay.h"
#include "displayapp/screens/settings/SettingSteps.h"
using namespace Pinetime::Applications;
using namespace Pinetime::Applications::Display;
DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Drivers::Cst816S &touchPanel,
Controllers::Battery &batteryController, Controllers::Ble &bleController,
Controllers::DateTime &dateTimeController, Drivers::WatchdogView &watchdog,
DisplayApp::DisplayApp(Drivers::St7789& lcd,
Components::LittleVgl& lvgl,
Drivers::Cst816S& touchPanel,
Controllers::Battery& batteryController,
Controllers::Ble& bleController,
Controllers::DateTime& dateTimeController,
Drivers::WatchdogView& watchdog,
System::SystemTask& systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
Controllers::Settings& settingsController,
Pinetime::Controllers::MotionController& motionController) :
lcd{lcd},
Pinetime::Controllers::MotorController& motorController,
Pinetime::Controllers::MotionController& motionController,
Pinetime::Controllers::TimerController& timerController)
: lcd {lcd},
lvgl {lvgl},
touchPanel {touchPanel},
batteryController {batteryController},
@ -59,16 +69,19 @@ DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Driver
notificationManager {notificationManager},
heartRateController {heartRateController},
settingsController {settingsController},
motionController{motionController} {
motorController {motorController},
motionController {motionController},
timerController {timerController} {
msgQueue = xQueueCreate(queueSize, itemSize);
// Start clock when smartwatch boots
LoadApp(Apps::Clock, DisplayApp::FullRefreshDirections::None);
}
void DisplayApp::Start() {
if (pdPASS != xTaskCreate(DisplayApp::Process, "displayapp", 800, this, 0, &taskHandle))
if (pdPASS != xTaskCreate(DisplayApp::Process, "displayapp", 800, this, 0, &taskHandle)) {
APP_ERROR_HANDLER(NRF_ERROR_NO_MEM);
}
}
void DisplayApp::Process(void* instance) {
auto* app = static_cast<DisplayApp*>(instance);
@ -78,7 +91,7 @@ void DisplayApp::Process(void *instance) {
// Send a dummy notification to unlock the lvgl display driver for the first iteration
xTaskNotifyGive(xTaskGetCurrentTaskHandle());
while (1) {
while (true) {
app->Refresh();
}
}
@ -129,7 +142,8 @@ void DisplayApp::Refresh() {
systemTask.PushMessage(System::SystemTask::Messages::UpdateTimeOut);
break;
case Messages::UpdateBleConnection:
// clockScreen.SetBleConnectionState(bleController.IsConnected() ? Screens::Clock::BleConnectionStates::Connected : Screens::Clock::BleConnectionStates::NotConnected);
// clockScreen.SetBleConnectionState(bleController.IsConnected() ? Screens::Clock::BleConnectionStates::Connected :
// Screens::Clock::BleConnectionStates::NotConnected);
break;
case Messages::UpdateBatteryLevel:
batteryController.Update();
@ -137,8 +151,17 @@ void DisplayApp::Refresh() {
case Messages::NewNotification:
LoadApp(Apps::NotificationsPreview, DisplayApp::FullRefreshDirections::Down);
break;
case Messages::TimerDone:
if (currentApp == Apps::Timer) {
auto *timer = dynamic_cast<Screens::Timer*>(currentScreen.get());
timer->setDone();
} else {
LoadApp(Apps::Timer, DisplayApp::FullRefreshDirections::Down);
}
break;
case Messages::TouchEvent: {
if (state != States::Running) break;
if (state != States::Running)
break;
auto gesture = OnTouchEvent();
if (!currentScreen->OnTouchEvent(gesture)) {
if (currentApp == Apps::Clock) {
@ -162,8 +185,7 @@ void DisplayApp::Refresh() {
LoadApp(returnToApp, returnDirection);
}
}
}
break;
} break;
case Messages::ButtonPushed:
if (currentApp == Apps::Clock) {
systemTask.PushMessage(System::SystemTask::Messages::GoToSleep);
@ -205,7 +227,7 @@ void DisplayApp::StartApp(Apps app, DisplayApp::FullRefreshDirections direction)
LoadApp(app, direction);
}
void DisplayApp::returnApp(Apps app, DisplayApp::FullRefreshDirections direction, TouchEvents touchEvent) {
void DisplayApp::ReturnApp(Apps app, DisplayApp::FullRefreshDirections direction, TouchEvents touchEvent) {
returnToApp = app;
returnDirection = direction;
returnTouchEvent = touchEvent;
@ -216,73 +238,91 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
SetFullRefresh(direction);
// default return to launcher
returnApp(Apps::Launcher, FullRefreshDirections::Down, TouchEvents::SwipeDown);
ReturnApp(Apps::Launcher, FullRefreshDirections::Down, TouchEvents::SwipeDown);
switch (app) {
case Apps::Launcher:
currentScreen = std::make_unique<Screens::ApplicationList>(this, settingsController, batteryController, dateTimeController);
returnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::SwipeDown);
ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
case Apps::None:
case Apps::Clock:
currentScreen = std::make_unique<Screens::Clock>(this, dateTimeController, batteryController, bleController, notificationManager, settingsController, heartRateController, motionController);
currentScreen = std::make_unique<Screens::Clock>(this,
dateTimeController,
batteryController,
bleController,
notificationManager,
settingsController,
heartRateController,
motionController);
break;
case Apps::FirmwareValidation:
currentScreen = std::make_unique<Screens::FirmwareValidation>(this, validator);
returnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
case Apps::FirmwareUpdate:
currentScreen = std::make_unique<Screens::FirmwareUpdate>(this, bleController);
break;
case Apps::Notifications:
currentScreen = std::make_unique<Screens::Notifications>(this, notificationManager, systemTask.nimble().alertService(), Screens::Notifications::Modes::Normal);
returnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp);
currentScreen = std::make_unique<Screens::Notifications>(
this, notificationManager, systemTask.nimble().alertService(), Screens::Notifications::Modes::Normal);
ReturnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp);
break;
case Apps::NotificationsPreview:
currentScreen = std::make_unique<Screens::Notifications>(this, notificationManager, systemTask.nimble().alertService(), Screens::Notifications::Modes::Preview);
returnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp);
currentScreen = std::make_unique<Screens::Notifications>(
this, notificationManager, systemTask.nimble().alertService(), Screens::Notifications::Modes::Preview);
ReturnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp);
break;
case Apps::Timer:
currentScreen = std::make_unique<Screens::Timer>(this, timerController);
break;
// Settings
case Apps::QuickSettings:
currentScreen = std::make_unique<Screens::QuickSettings>(this, batteryController, dateTimeController, brightnessController, settingsController);
returnApp(Apps::Clock, FullRefreshDirections::LeftAnim, TouchEvents::SwipeLeft);
currentScreen = std::make_unique<Screens::QuickSettings>(
this, batteryController, dateTimeController, brightnessController, motorController, settingsController);
ReturnApp(Apps::Clock, FullRefreshDirections::LeftAnim, TouchEvents::SwipeLeft);
break;
case Apps::Settings:
currentScreen = std::make_unique<Screens::Settings>(this, settingsController);
returnApp(Apps::QuickSettings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
ReturnApp(Apps::QuickSettings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
case Apps::SettingWatchFace:
currentScreen = std::make_unique<Screens::SettingWatchFace>(this, settingsController);
returnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
case Apps::SettingTimeFormat:
currentScreen = std::make_unique<Screens::SettingTimeFormat>(this, settingsController);
returnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
case Apps::SettingWakeUp:
currentScreen = std::make_unique<Screens::SettingWakeUp>(this, settingsController);
returnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
case Apps::SettingDisplay:
currentScreen = std::make_unique<Screens::SettingDisplay>(this, settingsController);
returnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
case Apps::SettingSteps:
currentScreen = std::make_unique<Screens::SettingSteps>(this, settingsController);
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
case Apps::BatteryInfo:
currentScreen = std::make_unique<Screens::BatteryInfo>(this, batteryController);
returnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
case Apps::SysInfo:
currentScreen = std::make_unique<Screens::SystemInfo>(this, dateTimeController, batteryController, brightnessController, bleController, watchdog);
returnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
currentScreen =
std::make_unique<Screens::SystemInfo>(this, dateTimeController, batteryController, brightnessController, bleController, watchdog);
ReturnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);
break;
//
case Apps::FlashLight:
currentScreen = std::make_unique<Screens::FlashLight>(this, systemTask, brightnessController);
returnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None);
ReturnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None);
break;
case Apps::StopWatch:
currentScreen = std::make_unique<Screens::StopWatch>(this);
@ -308,12 +348,14 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
case Apps::Motion:
currentScreen = std::make_unique<Screens::Motion>(this, motionController);
break;
case Apps::Steps:
currentScreen = std::make_unique<Screens::Steps>(this, motionController, settingsController);
break;
}
currentApp = app;
}
void DisplayApp::IdleState() {
}
void DisplayApp::PushMessage(Messages msg) {
@ -331,8 +373,9 @@ TouchEvents DisplayApp::OnTouchEvent() {
if (info.isTouch) {
switch (info.gesture) {
case Pinetime::Drivers::Cst816S::Gestures::SingleTap:
if(touchMode == TouchModes::Gestures)
if (touchMode == TouchModes::Gestures) {
lvgl.SetNewTapEvent(info.x, info.y);
}
return TouchEvents::Tap;
case Pinetime::Drivers::Cst816S::Gestures::LongPress:
return TouchEvents::LongTap;
@ -374,11 +417,11 @@ void DisplayApp::SetFullRefresh(DisplayApp::FullRefreshDirections direction) {
case DisplayApp::FullRefreshDirections::RightAnim:
lvgl.SetFullRefresh(Components::LittleVgl::FullRefreshDirections::RightAnim);
break;
default: break;
default:
break;
}
}
void DisplayApp::SetTouchMode(DisplayApp::TouchModes mode) {
touchMode = mode;
}

View File

@ -8,9 +8,11 @@
#include "LittleVgl.h"
#include "TouchEvents.h"
#include "components/brightness/BrightnessController.h"
#include "components/motor/MotorController.h"
#include "components/firmwarevalidator/FirmwareValidator.h"
#include "components/settings/Settings.h"
#include "displayapp/screens/Screen.h"
#include "components/timer/TimerController.h"
#include "Messages.h"
namespace Pinetime {
@ -40,15 +42,20 @@ namespace Pinetime {
enum class FullRefreshDirections { None, Up, Down, Left, Right, LeftAnim, RightAnim };
enum class TouchModes { Gestures, Polling };
DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Drivers::Cst816S &,
Controllers::Battery &batteryController, Controllers::Ble &bleController,
Controllers::DateTime &dateTimeController, Drivers::WatchdogView &watchdog,
DisplayApp(Drivers::St7789& lcd,
Components::LittleVgl& lvgl,
Drivers::Cst816S&,
Controllers::Battery& batteryController,
Controllers::Ble& bleController,
Controllers::DateTime& dateTimeController,
Drivers::WatchdogView& watchdog,
System::SystemTask& systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
Controllers::Settings& settingsController,
Pinetime::Controllers::MotionController& motionController
);
Pinetime::Controllers::MotorController& motorController,
Pinetime::Controllers::MotionController& motionController,
Pinetime::Controllers::TimerController& timerController);
void Start();
void PushMessage(Display::Messages msg);
@ -58,7 +65,6 @@ namespace Pinetime {
void SetTouchMode(TouchModes mode);
private:
Pinetime::Drivers::St7789& lcd;
Pinetime::Components::LittleVgl& lvgl;
Pinetime::Drivers::Cst816S& touchPanel;
@ -70,7 +76,9 @@ namespace Pinetime {
Pinetime::Controllers::NotificationManager& notificationManager;
Pinetime::Controllers::HeartRateController& heartRateController;
Pinetime::Controllers::Settings& settingsController;
Pinetime::Controllers::MotorController& motorController;
Pinetime::Controllers::MotionController& motionController;
Pinetime::Controllers::TimerController& timerController;
Pinetime::Controllers::FirmwareValidator validator;
Controllers::BrightnessController brightnessController;
@ -98,11 +106,8 @@ namespace Pinetime {
static void Process(void* instance);
void InitHw();
void Refresh();
void returnApp(Apps app, DisplayApp::FullRefreshDirections direction, TouchEvents touchEvent);
void ReturnApp(Apps app, DisplayApp::FullRefreshDirections direction, TouchEvents touchEvent);
void LoadApp(Apps app, DisplayApp::FullRefreshDirections direction);
};
}
}

View File

@ -7,17 +7,21 @@
using namespace Pinetime::Applications;
DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Drivers::Cst816S &touchPanel,
Controllers::Battery &batteryController, Controllers::Ble &bleController,
Controllers::DateTime &dateTimeController, Drivers::WatchdogView &watchdog,
DisplayApp::DisplayApp(Drivers::St7789& lcd,
Components::LittleVgl& lvgl,
Drivers::Cst816S& touchPanel,
Controllers::Battery& batteryController,
Controllers::Ble& bleController,
Controllers::DateTime& dateTimeController,
Drivers::WatchdogView& watchdog,
System::SystemTask& systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
Pinetime::Controllers::Settings& settingsController,
Pinetime::Controllers::MotionController& motionController):
lcd{lcd}, bleController{bleController} {
Pinetime::Controllers::MotorController& motorController,
Pinetime::Controllers::MotionController& motionController)
: lcd {lcd}, bleController {bleController} {
msgQueue = xQueueCreate(queueSize, itemSize);
}
void DisplayApp::Start() {
@ -33,7 +37,7 @@ void DisplayApp::Process(void *instance) {
xTaskNotifyGive(xTaskGetCurrentTaskHandle());
app->InitHw();
while (1) {
while (true) {
app->Refresh();
}
}
@ -47,10 +51,11 @@ void DisplayApp::Refresh() {
if (xQueueReceive(msgQueue, &msg, 200)) {
switch (msg) {
case Display::Messages::UpdateBleConnection:
if (bleController.IsConnected())
if (bleController.IsConnected()) {
DisplayLogo(colorBlue);
else
} else {
DisplayLogo(colorWhite);
}
break;
case Display::Messages::BleFirmwareUpdateStarted:
DisplayLogo(colorGreen);
@ -61,8 +66,9 @@ void DisplayApp::Refresh() {
}
if (bleController.IsFirmwareUpdating()) {
uint8_t percent = (static_cast<float>(bleController.FirmwareUpdateCurrentBytes()) /
static_cast<float>(bleController.FirmwareUpdateTotalBytes())) * 100.0f;
uint8_t percent =
(static_cast<float>(bleController.FirmwareUpdateCurrentBytes()) / static_cast<float>(bleController.FirmwareUpdateTotalBytes())) *
100.0f;
switch (bleController.State()) {
case Controllers::Ble::FirmwareUpdateStates::Running:
DisplayOtaProgress(percent, colorWhite);

View File

@ -17,6 +17,7 @@
#include <drivers/Watchdog.h>
#include <components/heartrate/HeartRateController.h>
#include <components/motion/MotionController.h>
#include <components/motor/MotorController.h>
#include <components/settings/Settings.h>
#include "TouchEvents.h"
#include "Apps.h"
@ -30,13 +31,18 @@ namespace Pinetime {
namespace Applications {
class DisplayApp {
public:
DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Drivers::Cst816S &,
Controllers::Battery &batteryController, Controllers::Ble &bleController,
Controllers::DateTime &dateTimeController, Drivers::WatchdogView &watchdog,
DisplayApp(Drivers::St7789& lcd,
Components::LittleVgl& lvgl,
Drivers::Cst816S&,
Controllers::Battery& batteryController,
Controllers::Ble& bleController,
Controllers::DateTime& dateTimeController,
Drivers::WatchdogView& watchdog,
System::SystemTask& systemTask,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::HeartRateController& heartRateController,
Pinetime::Controllers::Settings& settingsController,
Pinetime::Controllers::MotorController& motorController,
Pinetime::Controllers::MotionController& motionController);
void Start();
void PushMessage(Pinetime::Applications::Display::Messages msg);
@ -66,10 +72,6 @@ namespace Pinetime {
static constexpr uint16_t colorRedSwapped = 0x00ff;
static constexpr uint16_t colorBlack = 0x0000;
uint8_t displayBuffer[displayWidth * bytesPerPixel];
};
}
}

View File

@ -11,20 +11,23 @@ namespace Pinetime {
class LittleVgl {
public:
enum class FullRefreshDirections { None, Up, Down };
LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::Cst816S& touchPanel) {}
LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::Cst816S& touchPanel) {
}
LittleVgl(const LittleVgl&) = delete;
LittleVgl& operator=(const LittleVgl&) = delete;
LittleVgl(LittleVgl&&) = delete;
LittleVgl& operator=(LittleVgl&&) = delete;
void FlushDisplay(const lv_area_t * area, lv_color_t * color_p) {}
bool GetTouchPadInfo(lv_indev_data_t *ptr) {return false;}
void SetFullRefresh(FullRefreshDirections direction) {}
void SetNewTapEvent(uint16_t x, uint16_t y) {}
void FlushDisplay(const lv_area_t* area, lv_color_t* color_p) {
}
bool GetTouchPadInfo(lv_indev_data_t* ptr) {
return false;
}
void SetFullRefresh(FullRefreshDirections direction) {
}
void SetNewTapEvent(uint16_t x, uint16_t y) {
}
};
}
}

View File

@ -21,7 +21,8 @@ bool touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) {
return lvgl->GetTouchPadInfo(data);
}
LittleVgl::LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::Cst816S& touchPanel) : lcd{lcd}, touchPanel{touchPanel}, previousClick{0,0} {
LittleVgl::LittleVgl(Pinetime::Drivers::St7789& lcd, Pinetime::Drivers::Cst816S& touchPanel)
: lcd {lcd}, touchPanel {touchPanel}, previousClick {0, 0} {
lv_init();
InitTheme();
InitDisplay();
@ -203,13 +204,7 @@ bool LittleVgl::GetTouchPadInfo(lv_indev_data_t *ptr) {
void LittleVgl::InitTheme() {
lv_theme_t* th = lv_pinetime_theme_init(
LV_COLOR_WHITE, LV_COLOR_SILVER,
0,
&jetbrains_mono_bold_20,
&jetbrains_mono_bold_20,
&jetbrains_mono_bold_20,
&jetbrains_mono_bold_20);
LV_COLOR_WHITE, LV_COLOR_SILVER, 0, &jetbrains_mono_bold_20, &jetbrains_mono_bold_20, &jetbrains_mono_bold_20, &jetbrains_mono_bold_20);
lv_theme_set_act(th);
}

View File

@ -29,11 +29,9 @@ namespace Pinetime {
void InitTouchpad();
void InitTheme();
Pinetime::Drivers::St7789& lcd;
Pinetime::Drivers::Cst816S& touchPanel;
lv_disp_buf_t disp_buf_2;
lv_color_t buf2_1[LV_HOR_RES_MAX * 4];
lv_color_t buf2_2[LV_HOR_RES_MAX * 4];
@ -45,7 +43,9 @@ namespace Pinetime {
static constexpr uint8_t nbWriteLines = 4;
static constexpr uint16_t totalNbLines = 320;
static constexpr uint16_t visibleNbLines = 240;
static constexpr uint8_t MaxScrollOffset() { return LV_VER_RES_MAX - nbWriteLines; }
static constexpr uint8_t MaxScrollOffset() {
return LV_VER_RES_MAX - nbWriteLines;
}
FullRefreshDirections scrollDirection = FullRefreshDirections::None;
uint16_t writeOffset = 0;
uint16_t scrollOffset = 0;
@ -56,4 +56,3 @@ namespace Pinetime {
};
}
}

View File

@ -3,8 +3,17 @@ namespace Pinetime {
namespace Applications {
namespace Display {
enum class Messages : uint8_t {
GoToSleep, GoToRunning, UpdateDateTime, UpdateBleConnection, UpdateBatteryLevel, TouchEvent, ButtonPushed,
NewNotification, BleFirmwareUpdateStarted, UpdateTimeOut
GoToSleep,
GoToRunning,
UpdateDateTime,
UpdateBleConnection,
UpdateBatteryLevel,
TouchEvent,
ButtonPushed,
NewNotification,
TimerDone,
BleFirmwareUpdateStarted,
UpdateTimeOut
};
}
}

View File

@ -0,0 +1,44 @@
# Fonts
* [Jetbrains Mono](https://www.jetbrains.com/fr-fr/lp/mono/)
* [Awesome font from LVGL](https://lvgl.io/assets/others/FontAwesome5-Solid+Brands+Regular.woff)
## Generate the fonts:
* Open the [LVGL font converter](https://lvgl.io/tools/fontconverter)
* Name : jetbrains_mono_bold_20
* Size : 20
* Bpp : 1 bit-per-pixel
* Do not enable font compression and horizontal subpixel hinting
* Load the file `JetBrainsMono-Bold.tff` and specify the following range : `0x20-0x7f, 0x410-0x44f`
* Add a 2nd font, load the file `FontAwesome5-Solid+Brands+Regular.woff` and specify the following
range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024, 0xf252`
* Click on Convert, and download the file `jetbrains_mono_bold_20.c` and copy it in `src/DisplayApp/Fonts`
Add new symbols:
* Browse the [cheatsheet](https://fontawesome.com/cheatsheet/free/solid) and find your new symbols
* For each symbol, add its hex code (0xf641 for the 'Ad' icon, for example) to the *Range* list (Remember to keep this
readme updated with newest range list)
* Convert this hex value into a UTF-8 code
using [this site](http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=f185&mode=hex)
* Define the new symbols in `src/displayapp/screens/Symbols.h`:
```
static constexpr const char* newSymbol = "\xEF\x86\x85";
```
#### Navigation font
To create the navigtion.ttf I use the web app [icomoon](https://icomoon.io/app)
this app can import the svg files from the folder *src/displayapp/icons/navigation/unique* and creat a ttf file the
project for the site is *lv_font_navi_80.json* you can import it to add or remove icons
You can also use the online LVGL tool to create the .c
ttf file : navigation.ttf name : lv_font_navi_80 size : 80px Bpp : 2 bit-per-pixel range : 0xe900-0xe929
$lv_font_conv --font navigation.ttf -r '0xe900-0xe929' --size 80 --format lvgl --bpp 2 --no-prefilter -o
lv_font_navi_80.c
#### I use the method above to create the other ttf

View File

@ -1,41 +0,0 @@
#Fonts
* [Jetbrains Mono](https://www.jetbrains.com/fr-fr/lp/mono/)
* [Awesome font from LVGL](https://lvgl.io/assets/others/FontAwesome5-Solid+Brands+Regular.woff)
## Generate the fonts:
* Open the [LVGL font converter](https://lvgl.io/tools/fontconverter)
* Name : jetbrains_mono_bold_20
* Size : 20
* Bpp : 1 bit-per-pixel
* Do not enable font compression and horizontal subpixel hinting
* Load the file `JetBrainsMono-Bold.tff` and specify the following range : `0x20-0x7f, 0x410-0x44f`
* Add a 2nd font, load the file `FontAwesome5-Solid+Brands+Regular.woff` and specify the following range : `0xf293, 0xf294, 0xf244, 0xf240, 0xf242, 0xf243, 0xf241, 0xf54b, 0xf21e, 0xf1e6, 0xf54b, 0xf017, 0xf129, 0xf03a, 0xf185, 0xf560, 0xf001, 0xf3fd, 0xf069, 0xf1fc, 0xf45d, 0xf59f, 0xf5a0, 0xf029, 0xf027, 0xf028, 0xf6a9, 0xf04b, 0xf04c, 0xf048, 0xf051, 0xf095, 0xf3dd, 0xf04d, 0xf2f2, 0xf024`
* Click on Convert, and download the file `jetbrains_mono_bold_20.c` and copy it in `src/DisplayApp/Fonts`
Add new symbols:
* Browse the [cheatsheet](https://fontawesome.com/cheatsheet/free/solid) and find your new symbols
* For each symbol, add its hex code (0xf641 for the 'Ad' icon, for example) to the *Range* list (Remember to keep this readme updated with newest range list)
* Convert this hex value into a UTF-8 code using [this site](http://www.ltg.ed.ac.uk/~richard/utf-8.cgi?input=f185&mode=hex)
* Define the new symbols in `src/DisplayApp/Screens/Symbols.h`:
```
static constex char* newSymbol = "\xEF\x86\x85";
```
#### Navigation font
To create the navigtion.ttf I use the web app [icomoon](https://icomoon.io/app)
this app can import the svg files from the folder *src/displayapp/icons/navigation/unique* and creat a ttf file
the project for the site is *lv_font_navi_80.json* you can import it to add or remove icons
You can also use the online LVGL tool to create the .c
ttf file : navigation.ttf
name : lv_font_navi_80
size : 80px
Bpp : 2 bit-per-pixel
range : 0xe900-0xe929
$lv_font_conv --font navigation.ttf -r '0xe900-0xe929' --size 80 --format lvgl --bpp 2 --no-prefilter -o lv_font_navi_80.c
#### I use the method above to create the other ttf

View File

@ -0,0 +1,258 @@
/*******************************************************************************
* Size: 42 px
* Bpp: 1
* Opts:
******************************************************************************/
#ifdef LV_LVGL_H_INCLUDE_SIMPLE
#include "lvgl.h"
#else
#include "lvgl/lvgl.h"
#endif
#ifndef JETBRAINS_MONO_42
#define JETBRAINS_MONO_42 1
#endif
#if JETBRAINS_MONO_42
/*-----------------
* BITMAPS
*----------------*/
/*Store the image of the glyphs*/
static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = {
/* U+0025 "%" */
0x1f, 0x80, 0x7, 0x3f, 0xc0, 0xe, 0x7f, 0xe0,
0x1c, 0xf0, 0xf0, 0x1c, 0xe0, 0x70, 0x38, 0xe0,
0x70, 0x70, 0xe0, 0x70, 0x70, 0xe0, 0x70, 0xe0,
0xe0, 0x71, 0xc0, 0xe0, 0x71, 0xc0, 0xf0, 0xf3,
0x80, 0x7f, 0xe7, 0x0, 0x3f, 0xc7, 0x0, 0x1f,
0x8e, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x3c, 0x0,
0x0, 0x38, 0x0, 0x0, 0x71, 0xf8, 0x0, 0xe3,
0xfc, 0x0, 0xe7, 0xfe, 0x1, 0xcf, 0xf, 0x3,
0x8e, 0x7, 0x3, 0x8e, 0x7, 0x7, 0xe, 0x7,
0xe, 0xe, 0x7, 0xe, 0xe, 0x7, 0x1c, 0xe,
0x7, 0x38, 0xf, 0xf, 0x38, 0x7, 0xfe, 0x70,
0x3, 0xfc, 0xe0, 0x1, 0xf8,
/* U+0030 "0" */
0x3, 0xf8, 0x1, 0xff, 0xc0, 0xff, 0xfe, 0x1f,
0x7, 0xc7, 0xc0, 0x7c, 0xf0, 0x7, 0xbc, 0x0,
0x7f, 0x80, 0xf, 0xf0, 0x1, 0xfe, 0x0, 0x3f,
0xc0, 0x7, 0xf8, 0x0, 0xff, 0xe, 0x1f, 0xe3,
0xe3, 0xfc, 0x7c, 0x7f, 0x8f, 0x8f, 0xf0, 0xe1,
0xfe, 0x0, 0x3f, 0xc0, 0x7, 0xf8, 0x0, 0xff,
0x0, 0x1f, 0xe0, 0x3, 0xfc, 0x0, 0x7f, 0x80,
0xf, 0xf0, 0x1, 0xef, 0x0, 0x79, 0xf0, 0x1f,
0x1f, 0x7, 0xc3, 0xff, 0xf8, 0x1f, 0xfc, 0x0,
0xfe, 0x0,
/* U+0031 "1" */
0x3, 0xf0, 0x0, 0xfe, 0x0, 0x3f, 0xc0, 0x1f,
0xf8, 0x7, 0xcf, 0x1, 0xf1, 0xe0, 0x3c, 0x3c,
0x7, 0x7, 0x80, 0x80, 0xf0, 0x0, 0x1e, 0x0,
0x3, 0xc0, 0x0, 0x78, 0x0, 0xf, 0x0, 0x1,
0xe0, 0x0, 0x3c, 0x0, 0x7, 0x80, 0x0, 0xf0,
0x0, 0x1e, 0x0, 0x3, 0xc0, 0x0, 0x78, 0x0,
0xf, 0x0, 0x1, 0xe0, 0x0, 0x3c, 0x0, 0x7,
0x80, 0x0, 0xf0, 0x0, 0x1e, 0x0, 0x3, 0xc0,
0x0, 0x78, 0xf, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf8,
/* U+0032 "2" */
0x3, 0xf8, 0x1, 0xff, 0xc0, 0x7f, 0xfe, 0x1f,
0x7, 0xc7, 0xc0, 0x3c, 0xf0, 0x7, 0xbc, 0x0,
0x7f, 0x80, 0xf, 0xf0, 0x1, 0xe0, 0x0, 0x3c,
0x0, 0x7, 0x80, 0x1, 0xf0, 0x0, 0x3c, 0x0,
0xf, 0x80, 0x1, 0xe0, 0x0, 0x7c, 0x0, 0x1f,
0x0, 0x7, 0xc0, 0x1, 0xf0, 0x0, 0x7e, 0x0,
0xf, 0x80, 0x3, 0xe0, 0x0, 0xf8, 0x0, 0x3e,
0x0, 0xf, 0x80, 0x3, 0xe0, 0x0, 0xf8, 0x0,
0x3e, 0x0, 0x7, 0xff, 0xfe, 0xff, 0xff, 0xdf,
0xff, 0xf8,
/* U+0033 "3" */
0x7f, 0xff, 0x8f, 0xff, 0xf1, 0xff, 0xfe, 0x0,
0x3, 0xc0, 0x0, 0xf0, 0x0, 0x3c, 0x0, 0xf,
0x0, 0x3, 0xc0, 0x0, 0xf0, 0x0, 0x3e, 0x0,
0x7, 0x80, 0x1, 0xfe, 0x0, 0x3f, 0xf0, 0x7,
0xff, 0x0, 0x3, 0xf0, 0x0, 0x1e, 0x0, 0x3,
0xc0, 0x0, 0x3c, 0x0, 0x7, 0x80, 0x0, 0xf0,
0x0, 0x1e, 0x0, 0x3, 0xfc, 0x0, 0x7f, 0x80,
0xf, 0xf0, 0x1, 0xef, 0x0, 0x79, 0xf0, 0x1f,
0x1f, 0x7, 0xc3, 0xff, 0xf0, 0x1f, 0xfc, 0x0,
0xfe, 0x0,
/* U+0034 "4" */
0x0, 0x1e, 0x0, 0xf, 0x80, 0x3, 0xc0, 0x1,
0xe0, 0x0, 0x78, 0x0, 0x3c, 0x0, 0x1f, 0x0,
0x7, 0x80, 0x3, 0xc0, 0x1, 0xf0, 0x0, 0x78,
0x0, 0x3e, 0x0, 0xf, 0x0, 0x7, 0x80, 0xf3,
0xe0, 0x3c, 0xf0, 0xf, 0x7c, 0x3, 0xde, 0x0,
0xff, 0x0, 0x3f, 0xc0, 0xf, 0xf0, 0x3, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0, 0x3,
0xc0, 0x0, 0xf0, 0x0, 0x3c, 0x0, 0xf, 0x0,
0x3, 0xc0, 0x0, 0xf0, 0x0, 0x3c,
/* U+0035 "5" */
0x7f, 0xff, 0x9f, 0xff, 0xe7, 0xff, 0xf9, 0xe0,
0x0, 0x78, 0x0, 0x1e, 0x0, 0x7, 0x80, 0x1,
0xe0, 0x0, 0x78, 0x0, 0x1e, 0x0, 0x7, 0x8f,
0x81, 0xef, 0xf8, 0x7f, 0xff, 0x1f, 0x87, 0xe7,
0xc0, 0x79, 0xe0, 0x1f, 0x0, 0x3, 0xc0, 0x0,
0xf0, 0x0, 0x3c, 0x0, 0xf, 0x0, 0x3, 0xc0,
0x0, 0xf0, 0x0, 0x3c, 0x0, 0xf, 0xf0, 0x3,
0xde, 0x1, 0xe7, 0x80, 0x78, 0xf8, 0x7e, 0x3f,
0xff, 0x3, 0xff, 0x80, 0x3f, 0x0,
/* U+0036 "6" */
0x0, 0x3c, 0x0, 0x7, 0x80, 0x0, 0x78, 0x0,
0xf, 0x0, 0x1, 0xe0, 0x0, 0x1e, 0x0, 0x3,
0xc0, 0x0, 0x3c, 0x0, 0x7, 0x80, 0x0, 0x70,
0x0, 0xf, 0x0, 0x1, 0xe7, 0xc0, 0x1f, 0xff,
0x3, 0xff, 0xfc, 0x3f, 0xf, 0xc7, 0xc0, 0x3e,
0x78, 0x1, 0xe7, 0x80, 0x1f, 0xf0, 0x0, 0xff,
0x0, 0xf, 0xf0, 0x0, 0xff, 0x0, 0xf, 0xf0,
0x0, 0xff, 0x0, 0xf, 0xf8, 0x1, 0xe7, 0x80,
0x1e, 0x7c, 0x3, 0xe3, 0xf0, 0xfc, 0x1f, 0xff,
0x80, 0xff, 0xf0, 0x1, 0xf8, 0x0,
/* U+0037 "7" */
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x0, 0x1e, 0xf0, 0x1, 0xef, 0x0, 0x1e, 0xf0,
0x3, 0xcf, 0x0, 0x3c, 0x0, 0x3, 0x80, 0x0,
0x78, 0x0, 0x7, 0x80, 0x0, 0xf0, 0x0, 0xf,
0x0, 0x0, 0xf0, 0x0, 0x1e, 0x0, 0x1, 0xe0,
0x0, 0x3c, 0x0, 0x3, 0xc0, 0x0, 0x3c, 0x0,
0x7, 0x80, 0x0, 0x78, 0x0, 0x7, 0x80, 0x0,
0xf0, 0x0, 0xf, 0x0, 0x1, 0xe0, 0x0, 0x1e,
0x0, 0x1, 0xe0, 0x0, 0x3c, 0x0, 0x3, 0xc0,
0x0, 0x7c, 0x0, 0x7, 0x80, 0x0,
/* U+0038 "8" */
0x1, 0xf8, 0x0, 0xff, 0xf0, 0x1f, 0xff, 0x83,
0xf0, 0xfc, 0x3c, 0x3, 0xc7, 0xc0, 0x3e, 0x78,
0x1, 0xe7, 0x80, 0x1e, 0x78, 0x1, 0xe7, 0x80,
0x1e, 0x3c, 0x3, 0xc3, 0xe0, 0x7c, 0x1f, 0xf,
0x80, 0xff, 0xf0, 0x3, 0xfc, 0x0, 0x7f, 0xe0,
0xf, 0xff, 0x3, 0xe0, 0x7c, 0x3c, 0x3, 0xc7,
0x80, 0x1e, 0xf0, 0x0, 0xff, 0x0, 0xf, 0xf0,
0x0, 0xff, 0x0, 0xf, 0xf0, 0x0, 0xff, 0x80,
0x1f, 0x7c, 0x3, 0xe7, 0xe0, 0x7e, 0x3f, 0xff,
0xc0, 0xff, 0xf0, 0x3, 0xfc, 0x0,
/* U+0039 "9" */
0x3, 0xf8, 0x0, 0xff, 0xf0, 0x1f, 0xff, 0x83,
0xe0, 0xfc, 0x7c, 0x3, 0xe7, 0x80, 0x1e, 0xf8,
0x1, 0xff, 0x0, 0xf, 0xf0, 0x0, 0xff, 0x0,
0xf, 0xf0, 0x0, 0xff, 0x0, 0xf, 0xf8, 0x1,
0xf7, 0x80, 0x1e, 0x7c, 0x3, 0xe3, 0xe0, 0x7e,
0x3f, 0xff, 0xc1, 0xff, 0xfc, 0x7, 0xe7, 0x80,
0x0, 0xf8, 0x0, 0xf, 0x0, 0x1, 0xe0, 0x0,
0x1e, 0x0, 0x3, 0xc0, 0x0, 0x3c, 0x0, 0x7,
0x80, 0x0, 0xf8, 0x0, 0xf, 0x0, 0x1, 0xe0,
0x0, 0x1e, 0x0, 0x3, 0xc0, 0x0,
/* U+003A ":" */
0x7d, 0xff, 0xff, 0xff, 0xef, 0x80, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1,
0xf7, 0xff, 0xff, 0xff, 0xbe
};
/*---------------------
* GLYPH DESCRIPTION
*--------------------*/
static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */,
{.bitmap_index = 0, .adv_w = 403, .box_w = 24, .box_h = 31, .ofs_x = 1, .ofs_y = 0},
{.bitmap_index = 93, .adv_w = 403, .box_w = 19, .box_h = 31, .ofs_x = 3, .ofs_y = 0},
{.bitmap_index = 167, .adv_w = 403, .box_w = 19, .box_h = 31, .ofs_x = 4, .ofs_y = 0},
{.bitmap_index = 241, .adv_w = 403, .box_w = 19, .box_h = 31, .ofs_x = 3, .ofs_y = 0},
{.bitmap_index = 315, .adv_w = 403, .box_w = 19, .box_h = 31, .ofs_x = 3, .ofs_y = 0},
{.bitmap_index = 389, .adv_w = 403, .box_w = 18, .box_h = 31, .ofs_x = 3, .ofs_y = 0},
{.bitmap_index = 459, .adv_w = 403, .box_w = 18, .box_h = 31, .ofs_x = 3, .ofs_y = 0},
{.bitmap_index = 529, .adv_w = 403, .box_w = 20, .box_h = 31, .ofs_x = 3, .ofs_y = 0},
{.bitmap_index = 607, .adv_w = 403, .box_w = 20, .box_h = 31, .ofs_x = 3, .ofs_y = 0},
{.bitmap_index = 685, .adv_w = 403, .box_w = 20, .box_h = 31, .ofs_x = 3, .ofs_y = 0},
{.bitmap_index = 763, .adv_w = 403, .box_w = 20, .box_h = 31, .ofs_x = 3, .ofs_y = 0},
{.bitmap_index = 841, .adv_w = 403, .box_w = 7, .box_h = 24, .ofs_x = 9, .ofs_y = 0}
};
/*---------------------
* CHARACTER MAPPING
*--------------------*/
/*Collect the unicode lists and glyph_id offsets*/
static const lv_font_fmt_txt_cmap_t cmaps[] =
{
{
.range_start = 37, .range_length = 1, .glyph_id_start = 1,
.unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY
},
{
.range_start = 48, .range_length = 11, .glyph_id_start = 2,
.unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY
}
};
/*--------------------
* ALL CUSTOM DATA
*--------------------*/
#if LV_VERSION_CHECK(8, 0, 0)
/*Store all the custom data of the font*/
static lv_font_fmt_txt_glyph_cache_t cache;
static const lv_font_fmt_txt_dsc_t font_dsc = {
#else
static lv_font_fmt_txt_dsc_t font_dsc = {
#endif
.glyph_bitmap = glyph_bitmap,
.glyph_dsc = glyph_dsc,
.cmaps = cmaps,
.kern_dsc = NULL,
.kern_scale = 0,
.cmap_num = 2,
.bpp = 1,
.kern_classes = 0,
.bitmap_format = 0,
#if LV_VERSION_CHECK(8, 0, 0)
.cache = &cache
#endif
};
/*-----------------
* PUBLIC FONT
*----------------*/
/*Initialize a public general font descriptor*/
#if LV_VERSION_CHECK(8, 0, 0)
const lv_font_t jetbrains_mono_42 = {
#else
lv_font_t jetbrains_mono_42 = {
#endif
.get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/
.get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/
.line_height = 31, /*The maximum line height required by the font*/
.base_line = 0, /*Baseline measured from the bottom of the line*/
#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0)
.subpx = LV_FONT_SUBPX_NONE,
#endif
#if LV_VERSION_CHECK(7, 4, 0)
.underline_position = -7,
.underline_thickness = 2,
#endif
.dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */
};
#endif /*#if JETBRAINS_MONO_42*/

View File

@ -900,6 +900,13 @@ static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = {
0x7, 0xe0, 0x0, 0x7, 0xf0, 0x0, 0x3, 0xff,
0xff, 0xff, 0xcf, 0xff, 0xff, 0xe0,
/* U+F252 "" */
0xff, 0xff, 0xff, 0xfd, 0x80, 0x33, 0x80, 0xe7,
0xff, 0xc7, 0xff, 0xf, 0xfe, 0xf, 0xf8, 0xf,
0xe0, 0xf, 0x80, 0x7f, 0xc0, 0xe3, 0x83, 0x83,
0x86, 0x3, 0x1f, 0xff, 0x3f, 0xfe, 0x7f, 0xfd,
0xff, 0xff, 0xff, 0xf8,
/* U+F293 "" */
0x7, 0xe0, 0x3f, 0xe0, 0xfb, 0xe3, 0xf3, 0xe7,
0xe3, 0xdf, 0xd3, 0xf9, 0xb3, 0xf9, 0x4f, 0xf8,
@ -1184,17 +1191,18 @@ static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = {
{.bitmap_index = 3380, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1},
{.bitmap_index = 3418, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1},
{.bitmap_index = 3456, .adv_w = 400, .box_w = 25, .box_h = 12, .ofs_x = 0, .ofs_y = 1},
{.bitmap_index = 3494, .adv_w = 280, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = -3},
{.bitmap_index = 3532, .adv_w = 200, .box_w = 11, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
{.bitmap_index = 3561, .adv_w = 280, .box_w = 16, .box_h = 19, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 3599, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
{.bitmap_index = 3665, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
{.bitmap_index = 3714, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3764, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3824, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
{.bitmap_index = 3877, .adv_w = 360, .box_w = 22, .box_h = 20, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3932, .adv_w = 360, .box_w = 22, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3985, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0}
{.bitmap_index = 3494, .adv_w = 240, .box_w = 15, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3530, .adv_w = 280, .box_w = 15, .box_h = 20, .ofs_x = 1, .ofs_y = -3},
{.bitmap_index = 3568, .adv_w = 200, .box_w = 11, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
{.bitmap_index = 3597, .adv_w = 280, .box_w = 16, .box_h = 19, .ofs_x = 1, .ofs_y = -2},
{.bitmap_index = 3635, .adv_w = 400, .box_w = 25, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
{.bitmap_index = 3701, .adv_w = 360, .box_w = 23, .box_h = 17, .ofs_x = 0, .ofs_y = -1},
{.bitmap_index = 3750, .adv_w = 320, .box_w = 20, .box_h = 20, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3800, .adv_w = 400, .box_w = 25, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3860, .adv_w = 320, .box_w = 20, .box_h = 21, .ofs_x = 0, .ofs_y = -3},
{.bitmap_index = 3913, .adv_w = 360, .box_w = 22, .box_h = 20, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 3968, .adv_w = 360, .box_w = 22, .box_h = 19, .ofs_x = 0, .ofs_y = -2},
{.bitmap_index = 4021, .adv_w = 320, .box_w = 20, .box_h = 15, .ofs_x = 0, .ofs_y = 0}
};
/*---------------------
@ -1205,8 +1213,8 @@ static const uint16_t unicode_list_2[] = {
0x0, 0x16, 0x23, 0x26, 0x27, 0x28, 0x39, 0x47,
0x4a, 0x4b, 0x4c, 0x50, 0x68, 0x94, 0x128, 0x184,
0x1e5, 0x1fb, 0x21d, 0x23f, 0x240, 0x241, 0x242, 0x243,
0x292, 0x293, 0x2f1, 0x3dc, 0x3fc, 0x45c, 0x54a, 0x55f,
0x59e, 0x59f, 0x6a8
0x251, 0x292, 0x293, 0x2f1, 0x3dc, 0x3fc, 0x45c, 0x54a,
0x55f, 0x59e, 0x59f, 0x6a8
};
/*Collect the unicode lists and glyph_id offsets*/
@ -1222,7 +1230,7 @@ static const lv_font_fmt_txt_cmap_t cmaps[] =
},
{
.range_start = 61441, .range_length = 1705, .glyph_id_start = 160,
.unicode_list = unicode_list_2, .glyph_id_ofs_list = NULL, .list_length = 35, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
.unicode_list = unicode_list_2, .glyph_id_ofs_list = NULL, .list_length = 36, .type = LV_FONT_FMT_TXT_CMAP_SPARSE_TINY
}
};

View File

@ -67,15 +67,14 @@ static bool inited;
* STATIC FUNCTIONS
**********************/
static void style_init_reset(lv_style_t * style)
{
if(inited) lv_style_reset(style);
else lv_style_init(style);
static void style_init_reset(lv_style_t* style) {
if (inited)
lv_style_reset(style);
else
lv_style_init(style);
}
static void basic_init(void)
{
static void basic_init(void) {
style_init_reset(&style_pad);
lv_style_set_pad_top(&style_pad, LV_STATE_DEFAULT, LV_VER_RES / 30);
@ -103,7 +102,6 @@ static void basic_init(void)
lv_style_set_border_color(&style_box_border, LV_STATE_DEFAULT, LV_PINETIME_GRAY);
lv_style_set_text_color(&style_box, LV_STATE_DEFAULT, LV_PINETIME_BLUE);
style_init_reset(&style_title);
lv_style_set_text_color(&style_title, LV_STATE_DEFAULT, LV_PINETIME_WHITE);
lv_style_set_text_font(&style_title, LV_STATE_DEFAULT, theme.font_subtitle);
@ -301,10 +299,8 @@ static void basic_init(void)
lv_style_set_pad_right(&style_cb_bullet, LV_STATE_DEFAULT, LV_DPX(8));
lv_style_set_pad_top(&style_cb_bullet, LV_STATE_DEFAULT, LV_DPX(8));
lv_style_set_pad_bottom(&style_cb_bullet, LV_STATE_DEFAULT, LV_DPX(8));
}
/**********************
* GLOBAL FUNCTIONS
**********************/
@ -320,10 +316,13 @@ static void basic_init(void)
* @param font_title pointer to a extra large font
* @return a pointer to reference this theme later
*/
lv_theme_t * lv_pinetime_theme_init(lv_color_t color_primary, lv_color_t color_secondary, uint32_t flags,
const lv_font_t * font_small, const lv_font_t * font_normal, const lv_font_t * font_subtitle,
const lv_font_t * font_title)
{
lv_theme_t* lv_pinetime_theme_init(lv_color_t color_primary,
lv_color_t color_secondary,
uint32_t flags,
const lv_font_t* font_small,
const lv_font_t* font_normal,
const lv_font_t* font_subtitle,
const lv_font_t* font_title) {
theme.color_primary = color_primary;
theme.color_secondary = color_secondary;
theme.font_small = font_small;
@ -341,9 +340,7 @@ lv_theme_t * lv_pinetime_theme_init(lv_color_t color_primary, lv_color_t color_s
return &theme;
}
static void theme_apply(lv_obj_t * obj, lv_theme_style_t name)
{
static void theme_apply(lv_obj_t* obj, lv_theme_style_t name) {
lv_style_list_t* list;
/*To avoid warnings*/
@ -442,7 +439,6 @@ static void theme_apply(lv_obj_t * obj, lv_theme_style_t name)
_lv_style_list_add_style(list, &style_list_btn);
break;
case LV_THEME_ARC:
lv_obj_clean_style_list(obj, LV_ARC_PART_BG);
list = lv_obj_get_style_list(obj, LV_ARC_PART_BG);
@ -453,7 +449,6 @@ static void theme_apply(lv_obj_t * obj, lv_theme_style_t name)
_lv_style_list_add_style(list, &style_arc_indic);
break;
case LV_THEME_SWITCH:
lv_obj_clean_style_list(obj, LV_SWITCH_PART_BG);
list = lv_obj_get_style_list(obj, LV_SWITCH_PART_BG);
@ -526,15 +521,11 @@ static void theme_apply(lv_obj_t * obj, lv_theme_style_t name)
_lv_style_list_add_style(list, &style_cb_bullet);
break;
default:
break;
}
lv_obj_refresh_style(obj, LV_OBJ_PART_ALL, LV_STYLE_PROP_ALL);
}
/**********************

View File

@ -31,12 +31,10 @@ extern "C" {
* TYPEDEFS
**********************/
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Initialize the default
* @param color_primary the primary color of the theme
@ -48,8 +46,12 @@ extern "C" {
* @param font_title pointer to a extra large font
* @return a pointer to reference this theme later
*/
lv_theme_t * lv_pinetime_theme_init(lv_color_t color_primary, lv_color_t color_secondary, uint32_t flags,
const lv_font_t * font_small, const lv_font_t * font_normal, const lv_font_t * font_subtitle,
lv_theme_t* lv_pinetime_theme_init(lv_color_t color_primary,
lv_color_t color_secondary,
uint32_t flags,
const lv_font_t* font_small,
const lv_font_t* font_normal,
const lv_font_t* font_subtitle,
const lv_font_t* font_title);
/**********************
* MACROS

View File

@ -11,21 +11,24 @@ using namespace Pinetime::Applications::Screens;
ApplicationList::ApplicationList(Pinetime::Applications::DisplayApp* app,
Pinetime::Controllers::Settings& settingsController,
Pinetime::Controllers::Battery& batteryController,
Controllers::DateTime& dateTimeController) :
Screen(app),
Controllers::DateTime& dateTimeController)
: Screen(app),
settingsController {settingsController},
batteryController {batteryController},
dateTimeController {dateTimeController},
screens {app,
settingsController.GetAppMenu(),
{
[this]() -> std::unique_ptr<Screen> { return CreateScreen1(); },
[this]() -> std::unique_ptr<Screen> { return CreateScreen2(); },
[this]() -> std::unique_ptr<Screen> {
return CreateScreen1();
},
[this]() -> std::unique_ptr<Screen> {
return CreateScreen2();
},
//[this]() -> std::unique_ptr<Screen> { return CreateScreen3(); }
},
Screens::ScreenListModes::UpDown
} {}
Screens::ScreenListModes::UpDown} {
}
ApplicationList::~ApplicationList() {
lv_obj_clean(lv_scr_act());
@ -42,31 +45,27 @@ bool ApplicationList::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
}
std::unique_ptr<Screen> ApplicationList::CreateScreen1() {
std::array<Screens::Tile::Applications, 6> applications {
{
std::array<Screens::Tile::Applications, 6> applications {{
{Symbols::stopWatch, Apps::StopWatch},
{Symbols::music, Apps::Music},
{Symbols::map, Apps::Navigation},
{Symbols::shoe, Apps::Motion},
{Symbols::shoe, Apps::Steps},
{Symbols::heartBeat, Apps::HeartRate},
{"", Apps::None},
}
};
{Symbols::hourGlass, Apps::Timer},
}};
return std::make_unique<Screens::Tile>(0, 2, app, settingsController, batteryController, dateTimeController, applications);
}
std::unique_ptr<Screen> ApplicationList::CreateScreen2() {
std::array<Screens::Tile::Applications, 6> applications {
{
std::array<Screens::Tile::Applications, 6> applications {{
{Symbols::paintbrush, Apps::Paint},
{Symbols::paddle, Apps::Paddle},
{"2", Apps::Twos},
{"M", Apps::Motion},
{"", Apps::None},
{"", Apps::None},
{"", Apps::None},
}
};
}};
return std::make_unique<Screens::Tile>(1, 2, app, settingsController, batteryController, dateTimeController, applications);
}
@ -84,4 +83,3 @@ std::unique_ptr<Screen> ApplicationList::CreateScreen2() {
return std::make_unique<Screens::Tile>(2, 3, app, settingsController, batteryController, dateTimeController, applications);
}*/

View File

@ -20,8 +20,8 @@ namespace Pinetime {
~ApplicationList() override;
bool Refresh() override;
bool OnTouchEvent(TouchEvents event) override;
private:
private:
Controllers::Settings& settingsController;
Pinetime::Controllers::Battery& batteryController;
Controllers::DateTime& dateTimeController;

View File

@ -4,10 +4,14 @@
using namespace Pinetime::Applications::Screens;
const char* BatteryIcon::GetBatteryIcon(int batteryPercent) {
if(batteryPercent > 90) return Symbols::batteryFull;
if(batteryPercent > 75) return Symbols::batteryThreeQuarter;
if(batteryPercent > 50) return Symbols::batteryHalf;
if(batteryPercent > 25) return Symbols::batteryOneQuarter;
if (batteryPercent > 90)
return Symbols::batteryFull;
if (batteryPercent > 75)
return Symbols::batteryThreeQuarter;
if (batteryPercent > 50)
return Symbols::batteryHalf;
if (batteryPercent > 25)
return Symbols::batteryOneQuarter;
return Symbols::batteryEmpty;
}
@ -18,5 +22,6 @@ const char* BatteryIcon::GetUnknownIcon() {
const char* BatteryIcon::GetPlugIcon(bool isCharging) {
if (isCharging)
return Symbols::plug;
else return "";
else
return "";
}

View File

@ -14,12 +14,8 @@ static void lv_anim_task(struct _lv_task_t *task) {
user_data->UpdateAnim();
}
BatteryInfo::BatteryInfo(
Pinetime::Applications::DisplayApp *app,
Pinetime::Controllers::Battery& batteryController) :
Screen(app),
batteryController{batteryController}
{
BatteryInfo::BatteryInfo(Pinetime::Applications::DisplayApp* app, Pinetime::Controllers::Battery& batteryController)
: Screen(app), batteryController {batteryController} {
batteryPercent = batteryController.PercentRemaining();
batteryVoltage = batteryController.Voltage();
@ -53,7 +49,8 @@ BatteryInfo::BatteryInfo(
// hack to not use the flot functions from printf
uint8_t batteryVoltageBytes[2];
batteryVoltageBytes[1] = static_cast<uint8_t>(batteryVoltage); // truncate whole numbers
batteryVoltageBytes[0] = static_cast<uint8_t>((batteryVoltage - batteryVoltageBytes[1]) * 100); //remove whole part of flt and shift 2 places over
batteryVoltageBytes[0] =
static_cast<uint8_t>((batteryVoltage - batteryVoltageBytes[1]) * 100); // remove whole part of flt and shift 2 places over
//
voltage = lv_label_create(lv_scr_act(), nullptr);
@ -73,7 +70,6 @@ BatteryInfo::BatteryInfo(
UpdateScreen();
}
BatteryInfo::~BatteryInfo() {
lv_task_del(taskUpdate);
lv_task_del(taskAnim);
@ -136,14 +132,13 @@ void BatteryInfo::UpdateScreen() {
// hack to not use the flot functions from printf
uint8_t batteryVoltageBytes[2];
batteryVoltageBytes[1] = static_cast<uint8_t>(batteryVoltage); // truncate whole numbers
batteryVoltageBytes[0] = static_cast<uint8_t>((batteryVoltage - batteryVoltageBytes[1]) * 100); //remove whole part of flt and shift 2 places over
batteryVoltageBytes[0] =
static_cast<uint8_t>((batteryVoltage - batteryVoltageBytes[1]) * 100); // remove whole part of flt and shift 2 places over
//
lv_label_set_text_fmt(voltage, "%1i.%02i volts", batteryVoltageBytes[1], batteryVoltageBytes[0]);
}
bool BatteryInfo::Refresh() {
return running;
}

View File

@ -6,7 +6,6 @@
#include "Screen.h"
#include <lvgl/lvgl.h>
namespace Pinetime {
namespace Controllers {
class Battery;
@ -17,18 +16,15 @@ namespace Pinetime {
class BatteryInfo : public Screen {
public:
BatteryInfo(DisplayApp* app,
Pinetime::Controllers::Battery& batteryController);
BatteryInfo(DisplayApp* app, Pinetime::Controllers::Battery& batteryController);
~BatteryInfo() override;
bool Refresh() override;
void UpdateScreen();
void UpdateAnim();
private:
Pinetime::Controllers::Battery& batteryController;
lv_obj_t* voltage;
@ -42,7 +38,6 @@ namespace Pinetime {
int8_t animation = 0;
int8_t batteryPercent = -1;
float batteryVoltage = 0.0f;
};
}
}

View File

@ -3,6 +3,8 @@
using namespace Pinetime::Applications::Screens;
const char* BleIcon::GetIcon(bool isConnected) {
if(isConnected) return Symbols::bluetooth;
else return "";
if (isConnected)
return Symbols::bluetooth;
else
return "";
}

View File

@ -10,7 +10,8 @@ void slider_event_cb(lv_obj_t * slider, lv_event_t event) {
}
}
Brightness::Brightness(Pinetime::Applications::DisplayApp *app, Controllers::BrightnessController& brightness) : Screen(app), brightness{brightness} {
Brightness::Brightness(Pinetime::Applications::DisplayApp* app, Controllers::BrightnessController& brightness)
: Screen(app), brightness {brightness} {
slider = lv_slider_create(lv_scr_act(), nullptr);
lv_obj_set_user_data(slider, this);
lv_obj_set_width(slider, LV_DPI * 2);
@ -35,11 +36,16 @@ bool Brightness::Refresh() {
const char* Brightness::LevelToString(Pinetime::Controllers::BrightnessController::Levels level) {
switch (level) {
case Pinetime::Controllers::BrightnessController::Levels::Off: return "Off";
case Pinetime::Controllers::BrightnessController::Levels::Low: return "Low";
case Pinetime::Controllers::BrightnessController::Levels::Medium: return "Medium";
case Pinetime::Controllers::BrightnessController::Levels::High: return "High";
default : return "???";
case Pinetime::Controllers::BrightnessController::Levels::Off:
return "Off";
case Pinetime::Controllers::BrightnessController::Levels::Low:
return "Low";
case Pinetime::Controllers::BrightnessController::Levels::Medium:
return "Medium";
case Pinetime::Controllers::BrightnessController::Levels::High:
return "High";
default:
return "???";
}
}
@ -49,20 +55,31 @@ void Brightness::OnValueChanged() {
void Brightness::SetValue(uint8_t value) {
switch (value) {
case 0: brightness.Set(Controllers::BrightnessController::Levels::Low); break;
case 1: brightness.Set(Controllers::BrightnessController::Levels::Medium); break;
case 2: brightness.Set(Controllers::BrightnessController::Levels::High); break;
case 0:
brightness.Set(Controllers::BrightnessController::Levels::Low);
break;
case 1:
brightness.Set(Controllers::BrightnessController::Levels::Medium);
break;
case 2:
brightness.Set(Controllers::BrightnessController::Levels::High);
break;
}
lv_label_set_text(slider_label, LevelToString(brightness.Level()));
}
uint8_t Brightness::LevelToInt(Pinetime::Controllers::BrightnessController::Levels level) {
switch (level) {
case Pinetime::Controllers::BrightnessController::Levels::Off: return 0;
case Pinetime::Controllers::BrightnessController::Levels::Low: return 0;
case Pinetime::Controllers::BrightnessController::Levels::Medium: return 1;
case Pinetime::Controllers::BrightnessController::Levels::High: return 2;
default : return 0;
case Pinetime::Controllers::BrightnessController::Levels::Off:
return 0;
case Pinetime::Controllers::BrightnessController::Levels::Low:
return 0;
case Pinetime::Controllers::BrightnessController::Levels::Medium:
return 1;
case Pinetime::Controllers::BrightnessController::Levels::High:
return 2;
default:
return 0;
}
}

View File

@ -17,8 +17,8 @@ namespace Pinetime {
bool OnTouchEvent(TouchEvents event) override;
void OnValueChanged();
private:
private:
Controllers::BrightnessController& brightness;
lv_obj_t* slider_label;

View File

@ -15,7 +15,6 @@
#include "WatchFaceDigital.h"
#include "WatchFaceAnalog.h"
using namespace Pinetime::Applications::Screens;
Clock::Clock(DisplayApp* app,
@ -25,33 +24,37 @@ Clock::Clock(DisplayApp* app,
Controllers::NotificationManager& notificatioManager,
Controllers::Settings& settingsController,
Controllers::HeartRateController& heartRateController,
Controllers::MotionController& motionController) : Screen(app),
dateTimeController{dateTimeController}, batteryController{batteryController},
bleController{bleController}, notificatioManager{notificatioManager},
Controllers::MotionController& motionController)
: Screen(app),
dateTimeController {dateTimeController},
batteryController {batteryController},
bleController {bleController},
notificatioManager {notificatioManager},
settingsController {settingsController},
heartRateController {heartRateController},
motionController {motionController},
screens {app,
settingsController.GetClockFace(),
{
[this]() -> std::unique_ptr<Screen> { return WatchFaceDigitalScreen(); },
[this]() -> std::unique_ptr<Screen> { return WatchFaceAnalogScreen(); },
[this]() -> std::unique_ptr<Screen> {
return WatchFaceDigitalScreen();
},
[this]() -> std::unique_ptr<Screen> {
return WatchFaceAnalogScreen();
},
// Examples for more watch faces
//[this]() -> std::unique_ptr<Screen> { return WatchFaceMinimalScreen(); },
//[this]() -> std::unique_ptr<Screen> { return WatchFaceCustomScreen(); }
},
Screens::ScreenListModes::LongPress
} {
Screens::ScreenListModes::LongPress} {
settingsController.SetAppMenu(0);
}
Clock::~Clock() {
lv_obj_clean(lv_scr_act());
}
bool Clock::Refresh() {
screens.Refresh();
return running;
@ -62,20 +65,30 @@ bool Clock::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
}
std::unique_ptr<Screen> Clock::WatchFaceDigitalScreen() {
return std::make_unique<Screens::WatchFaceDigital>(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController, heartRateController, motionController);
return std::make_unique<Screens::WatchFaceDigital>(app,
dateTimeController,
batteryController,
bleController,
notificatioManager,
settingsController,
heartRateController,
motionController);
}
std::unique_ptr<Screen> Clock::WatchFaceAnalogScreen() {
return std::make_unique<Screens::WatchFaceAnalog>(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController);
return std::make_unique<Screens::WatchFaceAnalog>(
app, dateTimeController, batteryController, bleController, notificatioManager, settingsController);
}
/*
// Examples for more watch faces
std::unique_ptr<Screen> Clock::WatchFaceMinimalScreen() {
return std::make_unique<Screens::WatchFaceMinimal>(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController);
return std::make_unique<Screens::WatchFaceMinimal>(app, dateTimeController, batteryController, bleController, notificatioManager,
settingsController);
}
std::unique_ptr<Screen> Clock::WatchFaceCustomScreen() {
return std::make_unique<Screens::WatchFaceCustom>(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController);
return std::make_unique<Screens::WatchFaceCustom>(app, dateTimeController, batteryController, bleController, notificatioManager,
settingsController);
}
*/

View File

@ -39,7 +39,6 @@ namespace Pinetime {
bool OnTouchEvent(TouchEvents event) override;
private:
Controllers::DateTime& dateTimeController;
Controllers::Battery& batteryController;
Controllers::Ble& bleController;
@ -48,7 +47,6 @@ namespace Pinetime {
Controllers::HeartRateController& heartRateController;
Controllers::MotionController& motionController;
ScreenList<2> screens;
std::unique_ptr<Screen> WatchFaceDigitalScreen();
std::unique_ptr<Screen> WatchFaceAnalogScreen();
@ -56,9 +54,6 @@ namespace Pinetime {
// Examples for more watch faces
// std::unique_ptr<Screen> WatchFaceMinimalScreen();
// std::unique_ptr<Screen> WatchFaceCustomScreen();
};
}
}

Some files were not shown because too many files have changed in this diff Show More