Skip to content

Commit 18e3cc7

Browse files
committed
Merge remote-tracking branch 'upstream/develop' into pts-settings
2 parents 85d494a + 4a5b5f9 commit 18e3cc7

26 files changed

Lines changed: 516 additions & 63 deletions

.clang-tidy

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
Checks: '*,
22
-altera-unroll-loops,
33
-llvmlibc-callee-namespace,
4+
-llvmlibc-restrict-system-libc-headers,
45
-llvm-header-guard,
56
-llvm-namespace-comment,
67
-google-build-using-namespace,
@@ -9,6 +10,7 @@ Checks: '*,
910
-fuchsia-statically-constructed-objects,
1011
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
1112
-cppcoreguidelines-pro-bounds-constant-array-index,
13+
-cppcoreguidelines-pro-type-static-cast-downcast,
1214
-cppcoreguidelines-pro-type-union-access,
1315
-cppcoreguidelines-pro-type-cstyle-cast,
1416
-cppcoreguidelines-pro-type-vararg,

doc/MotionService.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Motion Service
2+
## Introduction
3+
The motion service exposes step count and raw X/Y/Z motion value as READ and NOTIFY characteristics.
4+
5+
## Service
6+
The service UUID is **00020000-78fc-48fe-8e23-433b3a1942d0**
7+
8+
## Characteristics
9+
### Step count (UUID 00020001-78fc-48fe-8e23-433b3a1942d0)
10+
The current number of steps represented as a single `uint32_t` (4 bytes) value.
11+
12+
### Raw motion values (UUID 00020002-78fc-48fe-8e23-433b3a1942d0)
13+
The current raw motion values. This is a 3 `int16_t` array:
14+
15+
- [0] : X
16+
- [1] : Y
17+
- [2] : Z

doc/ble.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,19 @@ When the service does not exist in the BLE specification, InfiniTime implements
6565
The following custom services are implemented in InfiniTime:
6666

6767
- Since InfiniTime 0.8:
68-
```
69-
* Music Service : 00000000-78fc-48fe-8e23-433b3a1942d0
70-
```
71-
68+
* Music Service : 00000000-78fc-48fe-8e23-433b3a1942d0
69+
70+
7271
- Since InfiniTime 0.11:
73-
```
74-
* Navigation Service : 00010000-78fc-48fe-8e23-433b3a1942d0
75-
```
72+
* [Navigation Service](NavigationService.md) : 00010000-78fc-48fe-8e23-433b3a1942d0
73+
74+
75+
- Since InfiniTime 0.13
76+
* Call characteristic (extension to the Alert Notification Service): 00020001-78fc-48fe-8e23-433b3a1942d0
77+
78+
79+
- Since InfiniTime 1.7:
80+
* [Motion Service](MotionService.md) : 00030000-78fc-48fe-8e23-433b3a1942d0
7681

7782
---
7883

doc/buildAndProgram.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,3 +231,33 @@ Loading section .sec7, size 0xdf08 lma 0x40000
231231
Start address 0x0, load size 314200
232232
Transfer rate: 45 KB/sec, 969 bytes/write.
233233
```
234+
235+
### How to generate files needed by the factory
236+
These files are needed by the Pine64 factory to flash InfiniTime as the default firmware on the PineTimes.
237+
238+
Two files are needed: an **HEX (.hex)** file that contains the content of the internal flash memory (bootloader + InfiniTime) and a **binary (.bin)** file that contains the content of the external flash memory (recovery firmware).
239+
240+
#### merged-internal.hex
241+
First, convert the bootloader to hex:
242+
```
243+
<ARM TOOLCHAIN>/bin/arm-none-eabi-objcopy -I binary -O ihex ./bootloader.bin ./bootloader.hex
244+
```
245+
where `bootloader.bin` is the [last stable version](https://github.com/JF002/pinetime-mcuboot-bootloader/releases) of the [bootloader](https://github.com/JF002/pinetime-mcuboot-bootloader).
246+
247+
Then, convert the MCUBoot image of InfiniTime:
248+
```
249+
<ARM TOOLCHAIN>/bin/arm-none-eabi-objcopy -I binary -O ihex --change-addresses 0x8000 ./pinetime-mcuboot-app-image-1.6.0.bin ./pinetime-mcuboot-app-image-1.6.0.hex
250+
```
251+
where `pinetime-mcuboot-app-image-1.6.0.bin` is [the bin of the last MCUBoot image](https://github.com/InfiniTimeOrg/InfiniTime/releases) of [InfiniTime](https://github.com/InfiniTimeOrg/InfiniTime).
252+
253+
Pay attention to the parameter `--change-addresses 0x8000`. It's needed to ensure the image will be flashed at the offset expected by the bootloader (0x8000).
254+
255+
Finally, merge them together with **mergehex**:
256+
```
257+
/opt/mergehex/mergehex -m ./bootloader.hex ./pinetime-mcuboot-app-image-1.6.0.hex -o merged-internal.hex
258+
```
259+
260+
This file must be flashed at offset **0x00** of the internal memory of the NRF52832.
261+
262+
#### spinor.bin
263+
This file is the MCUBoot image of the last stable version of the recovery firmware. It must be flashed at offset **0x00** of the external SPINOR flash memory.

doc/gettingStarted/gettingStarted-1.0.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ Basically, a **firmware** is just a software running on the embedded hardware of
1212
- **[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.
1313
- **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/InfiniTimeOrg/InfiniTime/releases/tag/0.14.1).
1414

15-
**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).
15+
**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**evice **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).
1616

1717
## How to check the version of InfiniTime and the bootloader?
1818

src/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,7 @@ list(APPEND SOURCE_FILES
476476
components/ble/ImmediateAlertService.cpp
477477
components/ble/ServiceDiscovery.cpp
478478
components/ble/HeartRateService.cpp
479+
components/ble/MotionService.cpp
479480
components/firmwarevalidator/FirmwareValidator.cpp
480481
components/motor/MotorController.cpp
481482
components/settings/Settings.cpp
@@ -505,6 +506,7 @@ list(APPEND SOURCE_FILES
505506
components/heartrate/Ptagc.cpp
506507
components/heartrate/HeartRateController.cpp
507508

509+
buttonhandler/ButtonHandler.cpp
508510
touchhandler/TouchHandler.cpp
509511
)
510512

@@ -544,6 +546,7 @@ list(APPEND RECOVERY_SOURCE_FILES
544546
components/ble/ServiceDiscovery.cpp
545547
components/ble/NavigationService.cpp
546548
components/ble/HeartRateService.cpp
549+
components/ble/MotionService.cpp
547550
components/firmwarevalidator/FirmwareValidator.cpp
548551
components/settings/Settings.cpp
549552
components/timer/TimerController.cpp
@@ -564,6 +567,7 @@ list(APPEND RECOVERY_SOURCE_FILES
564567
components/heartrate/Ptagc.cpp
565568
components/motor/MotorController.cpp
566569
components/fs/FS.cpp
570+
buttonhandler/ButtonHandler.cpp
567571
touchhandler/TouchHandler.cpp
568572
)
569573

@@ -651,6 +655,7 @@ set(INCLUDE_FILES
651655
components/ble/ServiceDiscovery.h
652656
components/ble/BleClient.h
653657
components/ble/HeartRateService.h
658+
components/ble/MotionService.h
654659
components/settings/Settings.h
655660
components/timer/TimerController.h
656661
components/alarm/AlarmController.h
@@ -677,6 +682,7 @@ set(INCLUDE_FILES
677682
components/heartrate/Ptagc.h
678683
components/heartrate/HeartRateController.h
679684
components/motor/MotorController.h
685+
buttonhandler/ButtonHandler.h
680686
touchhandler/TouchHandler.h
681687
)
682688

src/buttonhandler/ButtonActions.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#pragma once
2+
3+
namespace Pinetime {
4+
namespace Controllers {
5+
enum class ButtonActions { None, Click, DoubleClick, LongPress, LongerPress };
6+
}
7+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
#include "ButtonHandler.h"
2+
3+
using namespace Pinetime::Controllers;
4+
5+
void ButtonTimerCallback(TimerHandle_t xTimer) {
6+
auto* sysTask = static_cast<Pinetime::System::SystemTask*>(pvTimerGetTimerID(xTimer));
7+
sysTask->PushMessage(Pinetime::System::Messages::HandleButtonTimerEvent);
8+
}
9+
10+
void ButtonHandler::Init(Pinetime::System::SystemTask* systemTask) {
11+
buttonTimer = xTimerCreate("buttonTimer", 0, pdFALSE, systemTask, ButtonTimerCallback);
12+
}
13+
14+
ButtonActions ButtonHandler::HandleEvent(Events event) {
15+
static constexpr TickType_t doubleClickTime = pdMS_TO_TICKS(200);
16+
static constexpr TickType_t longPressTime = pdMS_TO_TICKS(400);
17+
static constexpr TickType_t longerPressTime = pdMS_TO_TICKS(2000);
18+
19+
if (event == Events::Press) {
20+
buttonPressed = true;
21+
} else if (event == Events::Release) {
22+
releaseTime = xTaskGetTickCount();
23+
buttonPressed = false;
24+
}
25+
26+
switch (state) {
27+
case States::Idle:
28+
if (event == Events::Press) {
29+
xTimerChangePeriod(buttonTimer, doubleClickTime, 0);
30+
xTimerStart(buttonTimer, 0);
31+
state = States::Pressed;
32+
}
33+
break;
34+
case States::Pressed:
35+
if (event == Events::Press) {
36+
if (xTaskGetTickCount() - releaseTime < doubleClickTime) {
37+
xTimerStop(buttonTimer, 0);
38+
state = States::Idle;
39+
return ButtonActions::DoubleClick;
40+
}
41+
} else if (event == Events::Release) {
42+
xTimerChangePeriod(buttonTimer, doubleClickTime, 0);
43+
xTimerStart(buttonTimer, 0);
44+
} else if (event == Events::Timer) {
45+
if (buttonPressed) {
46+
xTimerChangePeriod(buttonTimer, longPressTime - doubleClickTime, 0);
47+
xTimerStart(buttonTimer, 0);
48+
state = States::Holding;
49+
} else {
50+
state = States::Idle;
51+
return ButtonActions::Click;
52+
}
53+
}
54+
break;
55+
case States::Holding:
56+
if (event == Events::Release) {
57+
xTimerStop(buttonTimer, 0);
58+
state = States::Idle;
59+
return ButtonActions::Click;
60+
} else if (event == Events::Timer) {
61+
xTimerChangePeriod(buttonTimer, longerPressTime - longPressTime - doubleClickTime, 0);
62+
xTimerStart(buttonTimer, 0);
63+
state = States::LongHeld;
64+
return ButtonActions::LongPress;
65+
}
66+
break;
67+
case States::LongHeld:
68+
if (event == Events::Release) {
69+
xTimerStop(buttonTimer, 0);
70+
state = States::Idle;
71+
} else if (event == Events::Timer) {
72+
state = States::Idle;
73+
return ButtonActions::LongerPress;
74+
}
75+
break;
76+
}
77+
return ButtonActions::None;
78+
}

src/buttonhandler/ButtonHandler.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#include "ButtonActions.h"
4+
#include "systemtask/SystemTask.h"
5+
#include <FreeRTOS.h>
6+
#include <timers.h>
7+
8+
namespace Pinetime {
9+
namespace Controllers {
10+
class ButtonHandler {
11+
public:
12+
enum class Events : uint8_t { Press, Release, Timer };
13+
void Init(Pinetime::System::SystemTask* systemTask);
14+
ButtonActions HandleEvent(Events event);
15+
16+
private:
17+
enum class States : uint8_t { Idle, Pressed, Holding, LongHeld };
18+
TickType_t releaseTime = 0;
19+
TimerHandle_t buttonTimer;
20+
bool buttonPressed = false;
21+
States state = States::Idle;
22+
};
23+
}
24+
}

src/components/ble/HeartRateService.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ constexpr ble_uuid16_t HeartRateService::heartRateServiceUuid;
88
constexpr ble_uuid16_t HeartRateService::heartRateMeasurementUuid;
99

1010
namespace {
11-
int HeartRateServiceServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
11+
int HeartRateServiceCallback(uint16_t conn_handle, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) {
1212
auto* heartRateService = static_cast<HeartRateService*>(arg);
1313
return heartRateService->OnHeartRateRequested(conn_handle, attr_handle, ctxt);
1414
}
@@ -19,7 +19,7 @@ HeartRateService::HeartRateService(Pinetime::System::SystemTask& system, Control
1919
: system {system},
2020
heartRateController {heartRateController},
2121
characteristicDefinition {{.uuid = &heartRateMeasurementUuid.u,
22-
.access_cb = HeartRateServiceServiceCallback,
22+
.access_cb = HeartRateServiceCallback,
2323
.arg = this,
2424
.flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY,
2525
.val_handle = &heartRateMeasurementHandle},
@@ -56,6 +56,8 @@ int HeartRateService::OnHeartRateRequested(uint16_t connectionHandle, uint16_t a
5656
}
5757

5858
void HeartRateService::OnNewHeartRateValue(uint8_t heartRateValue) {
59+
if(!heartRateMeasurementNotificationEnable) return;
60+
5961
uint8_t buffer[2] = {0, heartRateController.HeartRate()}; // [0] = flags, [1] = hr value
6062
auto* om = ble_hs_mbuf_from_flat(buffer, 2);
6163

@@ -67,3 +69,13 @@ void HeartRateService::OnNewHeartRateValue(uint8_t heartRateValue) {
6769

6870
ble_gattc_notify_custom(connectionHandle, heartRateMeasurementHandle, om);
6971
}
72+
73+
void HeartRateService::SubscribeNotification(uint16_t connectionHandle, uint16_t attributeHandle) {
74+
if(attributeHandle == heartRateMeasurementHandle)
75+
heartRateMeasurementNotificationEnable = true;
76+
}
77+
78+
void HeartRateService::UnsubscribeNotification(uint16_t connectionHandle, uint16_t attributeHandle) {
79+
if(attributeHandle == heartRateMeasurementHandle)
80+
heartRateMeasurementNotificationEnable = false;
81+
}

0 commit comments

Comments
 (0)