summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt17
-rw-r--r--src/components/alarm/AlarmController.cpp114
-rw-r--r--src/components/alarm/AlarmController.h68
-rw-r--r--src/components/battery/BatteryController.cpp16
-rw-r--r--src/components/battery/BatteryController.h9
-rw-r--r--src/components/ble/NimbleController.cpp125
-rw-r--r--src/components/ble/NimbleController.h7
-rw-r--r--src/components/brightness/BrightnessController.cpp32
-rw-r--r--src/components/brightness/BrightnessController.h3
-rw-r--r--src/components/datetime/DateTimeController.cpp7
-rw-r--r--src/components/datetime/DateTimeController.h1
-rw-r--r--src/components/motor/MotorController.cpp11
-rw-r--r--src/components/motor/MotorController.h2
-rw-r--r--src/components/settings/Settings.h2
-rw-r--r--src/displayapp/Apps.h1
-rw-r--r--src/displayapp/DisplayApp.cpp19
-rw-r--r--src/displayapp/DisplayApp.h4
-rw-r--r--src/displayapp/DisplayAppRecovery.cpp2
-rw-r--r--src/displayapp/DisplayAppRecovery.h34
-rw-r--r--src/displayapp/Messages.h4
-rw-r--r--src/displayapp/screens/Alarm.cpp254
-rw-r--r--src/displayapp/screens/Alarm.h54
-rw-r--r--src/displayapp/screens/ApplicationList.cpp2
-rw-r--r--src/displayapp/screens/BatteryInfo.cpp2
-rw-r--r--src/displayapp/screens/Metronome.cpp2
-rw-r--r--src/displayapp/screens/Notifications.cpp2
-rw-r--r--src/displayapp/screens/Notifications.h8
-rw-r--r--src/displayapp/screens/settings/Settings.cpp4
-rw-r--r--src/drivers/Cst816s.cpp13
-rw-r--r--src/drivers/Cst816s.h3
-rw-r--r--src/drivers/PinMap.h38
-rw-r--r--src/main.cpp70
-rw-r--r--src/recoveryLoader.cpp19
-rw-r--r--src/systemtask/Messages.h6
-rw-r--r--src/systemtask/SystemTask.cpp76
-rw-r--r--src/systemtask/SystemTask.h20
36 files changed, 837 insertions, 214 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index a7242903..37ee0848 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -92,6 +92,9 @@ set(SDK_SOURCE_FILES
set(TINYCRYPT_SRC
libs/mynewt-nimble/ext/tinycrypt/src/aes_encrypt.c
libs/mynewt-nimble/ext/tinycrypt/src/utils.c
+ libs/mynewt-nimble/ext/tinycrypt/src/cmac_mode.c
+ libs/mynewt-nimble/ext/tinycrypt/src/ecc.c
+ libs/mynewt-nimble/ext/tinycrypt/src/ecc_dh.c
)
set(NIMBLE_SRC
@@ -104,6 +107,10 @@ set(NIMBLE_SRC
libs/mynewt-nimble/nimble/host/src/ble_l2cap.c
libs/mynewt-nimble/nimble/host/src/ble_hs_mbuf.c
libs/mynewt-nimble/nimble/host/src/ble_sm.c
+ libs/mynewt-nimble/nimble/host/src/ble_sm_cmd.c
+ libs/mynewt-nimble/nimble/host/src/ble_sm_lgcy.c
+ libs/mynewt-nimble/nimble/host/src/ble_sm_alg.c
+ libs/mynewt-nimble/nimble/host/src/ble_sm_sc.c
libs/mynewt-nimble/nimble/host/src/ble_gap.c
libs/mynewt-nimble/nimble/host/src/ble_gatts.c
libs/mynewt-nimble/nimble/host/src/ble_gattc.c
@@ -127,10 +134,6 @@ set(NIMBLE_SRC
libs/mynewt-nimble/nimble/host/src/ble_hs_atomic.c
libs/mynewt-nimble/nimble/host/src/ble_hs_adv.c
libs/mynewt-nimble/nimble/host/src/ble_hs_flow.c
- libs/mynewt-nimble/nimble/host/src/ble_sm.c
- libs/mynewt-nimble/nimble/host/src/ble_sm_cmd.c
- libs/mynewt-nimble/nimble/host/src/ble_sm_lgcy.c
- libs/mynewt-nimble/nimble/host/src/ble_sm_alg.c
libs/mynewt-nimble/nimble/host/src/ble_hs_mqueue.c
libs/mynewt-nimble/nimble/host/src/ble_hs_stop.c
libs/mynewt-nimble/nimble/host/src/ble_hs_startup.c
@@ -418,6 +421,7 @@ list(APPEND SOURCE_FILES
displayapp/screens/BatteryInfo.cpp
displayapp/screens/Steps.cpp
displayapp/screens/Timer.cpp
+ displayapp/screens/Alarm.cpp
displayapp/Colors.cpp
## Settings
@@ -474,6 +478,7 @@ list(APPEND SOURCE_FILES
components/motor/MotorController.cpp
components/settings/Settings.cpp
components/timer/TimerController.cpp
+ components/alarm/AlarmController.cpp
components/fs/FS.cpp
drivers/Cst816s.cpp
FreeRTOS/port.c
@@ -540,6 +545,7 @@ list(APPEND RECOVERY_SOURCE_FILES
components/firmwarevalidator/FirmwareValidator.cpp
components/settings/Settings.cpp
components/timer/TimerController.cpp
+ components/alarm/AlarmController.cpp
drivers/Cst816s.cpp
FreeRTOS/port.c
FreeRTOS/port_cmsis_systick.c
@@ -612,6 +618,7 @@ set(INCLUDE_FILES
displayapp/screens/Metronome.h
displayapp/screens/Motion.h
displayapp/screens/Timer.h
+ displayapp/screens/Alarm.h
displayapp/Colors.h
drivers/St7789.h
drivers/SpiNorFlash.h
@@ -621,6 +628,7 @@ set(INCLUDE_FILES
drivers/DebugPins.h
drivers/InternalFlash.h
drivers/Hrs3300.h
+ drivers/PinMap.h
drivers/Bma421.h
drivers/Bma421_C/bma4.c
drivers/Bma421_C/bma423.c
@@ -643,6 +651,7 @@ set(INCLUDE_FILES
components/ble/HeartRateService.h
components/settings/Settings.h
components/timer/TimerController.h
+ components/alarm/AlarmController.h
drivers/Cst816s.h
FreeRTOS/portmacro.h
FreeRTOS/portmacro_cmsis.h
diff --git a/src/components/alarm/AlarmController.cpp b/src/components/alarm/AlarmController.cpp
new file mode 100644
index 00000000..67ca05a9
--- /dev/null
+++ b/src/components/alarm/AlarmController.cpp
@@ -0,0 +1,114 @@
+/* Copyright (C) 2021 mruss77, Florian
+
+ This file is part of InfiniTime.
+
+ InfiniTime is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ InfiniTime is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#include "AlarmController.h"
+#include "systemtask/SystemTask.h"
+#include "app_timer.h"
+#include "task.h"
+#include <chrono>
+
+using namespace Pinetime::Controllers;
+using namespace std::chrono_literals;
+
+AlarmController::AlarmController(Controllers::DateTime& dateTimeController) : dateTimeController {dateTimeController} {
+}
+
+APP_TIMER_DEF(alarmAppTimer);
+
+namespace {
+ void SetOffAlarm(void* p_context) {
+ auto* controller = static_cast<Pinetime::Controllers::AlarmController*>(p_context);
+ if (controller != nullptr) {
+ controller->SetOffAlarmNow();
+ }
+ }
+}
+
+void AlarmController::Init(System::SystemTask* systemTask) {
+ app_timer_create(&alarmAppTimer, APP_TIMER_MODE_SINGLE_SHOT, SetOffAlarm);
+ this->systemTask = systemTask;
+}
+
+void AlarmController::SetAlarmTime(uint8_t alarmHr, uint8_t alarmMin) {
+ hours = alarmHr;
+ minutes = alarmMin;
+}
+
+void AlarmController::ScheduleAlarm() {
+ // Determine the next time the alarm needs to go off and set the app_timer
+ app_timer_stop(alarmAppTimer);
+
+ auto now = dateTimeController.CurrentDateTime();
+ alarmTime = now;
+ time_t ttAlarmTime = std::chrono::system_clock::to_time_t(alarmTime);
+ tm* tmAlarmTime = std::localtime(&ttAlarmTime);
+
+ // If the time being set has already passed today,the alarm should be set for tomorrow
+ if (hours < dateTimeController.Hours() || (hours == dateTimeController.Hours() && minutes <= dateTimeController.Minutes())) {
+ tmAlarmTime->tm_mday += 1;
+ // tm_wday doesn't update automatically
+ tmAlarmTime->tm_wday = (tmAlarmTime->tm_wday + 1) % 7;
+ }
+
+ tmAlarmTime->tm_hour = hours;
+ tmAlarmTime->tm_min = minutes;
+ tmAlarmTime->tm_sec = 0;
+
+ // if alarm is in weekday-only mode, make sure it shifts to the next weekday
+ if (recurrence == RecurType::Weekdays) {
+ if (tmAlarmTime->tm_wday == 0) { // Sunday, shift 1 day
+ tmAlarmTime->tm_mday += 1;
+ } else if (tmAlarmTime->tm_wday == 6) { // Saturday, shift 2 days
+ tmAlarmTime->tm_mday += 2;
+ }
+ }
+ tmAlarmTime->tm_isdst = -1; // use system timezone setting to determine DST
+
+ // now can convert back to a time_point
+ alarmTime = std::chrono::system_clock::from_time_t(std::mktime(tmAlarmTime));
+ auto mSecToAlarm = std::chrono::duration_cast<std::chrono::milliseconds>(alarmTime - now).count();
+ app_timer_start(alarmAppTimer, APP_TIMER_TICKS(mSecToAlarm), this);
+
+ state = AlarmState::Set;
+}
+
+uint32_t AlarmController::SecondsToAlarm() {
+ return std::chrono::duration_cast<std::chrono::seconds>(alarmTime - dateTimeController.CurrentDateTime()).count();
+}
+
+void AlarmController::DisableAlarm() {
+ app_timer_stop(alarmAppTimer);
+ state = AlarmState::Not_Set;
+}
+
+void AlarmController::SetOffAlarmNow() {
+ state = AlarmState::Alerting;
+ systemTask->PushMessage(System::Messages::SetOffAlarm);
+}
+
+void AlarmController::StopAlerting() {
+ systemTask->PushMessage(System::Messages::StopRinging);
+
+ // Alarm state is off unless this is a recurring alarm
+ if (recurrence == RecurType::None) {
+ state = AlarmState::Not_Set;
+ } else {
+ state = AlarmState::Set;
+ // set next instance
+ ScheduleAlarm();
+ }
+}
diff --git a/src/components/alarm/AlarmController.h b/src/components/alarm/AlarmController.h
new file mode 100644
index 00000000..bf85d431
--- /dev/null
+++ b/src/components/alarm/AlarmController.h
@@ -0,0 +1,68 @@
+/* Copyright (C) 2021 mruss77, Florian
+
+ This file is part of InfiniTime.
+
+ InfiniTime is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ InfiniTime is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#pragma once
+
+#include <cstdint>
+#include "app_timer.h"
+#include "components/datetime/DateTimeController.h"
+
+namespace Pinetime {
+ namespace System {
+ class SystemTask;
+ }
+ namespace Controllers {
+ class AlarmController {
+ public:
+ AlarmController(Controllers::DateTime& dateTimeController);
+
+ void Init(System::SystemTask* systemTask);
+ void SetAlarmTime(uint8_t alarmHr, uint8_t alarmMin);
+ void ScheduleAlarm();
+ void DisableAlarm();
+ void SetOffAlarmNow();
+ uint32_t SecondsToAlarm();
+ void StopAlerting();
+ enum class AlarmState { Not_Set, Set, Alerting };
+ enum class RecurType { None, Daily, Weekdays };
+ uint8_t Hours() const {
+ return hours;
+ }
+ uint8_t Minutes() const {
+ return minutes;
+ }
+ AlarmState State() const {
+ return state;
+ }
+ RecurType Recurrence() const {
+ return recurrence;
+ }
+ void SetRecurrence(RecurType recurType) {
+ recurrence = recurType;
+ }
+
+ private:
+ Controllers::DateTime& dateTimeController;
+ System::SystemTask* systemTask = nullptr;
+ uint8_t hours = 7;
+ uint8_t minutes = 0;
+ std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> alarmTime;
+ AlarmState state = AlarmState::Not_Set;
+ RecurType recurrence = RecurType::None;
+ };
+ }
+}
diff --git a/src/components/battery/BatteryController.cpp b/src/components/battery/BatteryController.cpp
index 619e227c..d2ddae74 100644
--- a/src/components/battery/BatteryController.cpp
+++ b/src/components/battery/BatteryController.cpp
@@ -1,4 +1,5 @@
#include "BatteryController.h"
+#include "drivers/PinMap.h"
#include <hal/nrf_gpio.h>
#include <nrfx_saadc.h>
#include <algorithm>
@@ -9,15 +10,12 @@ Battery* Battery::instance = nullptr;
Battery::Battery() {
instance = this;
-}
-
-void Battery::Init() {
- nrf_gpio_cfg_input(chargingPin, static_cast<nrf_gpio_pin_pull_t> GPIO_PIN_CNF_PULL_Pullup);
+ nrf_gpio_cfg_input(PinMap::Charging, static_cast<nrf_gpio_pin_pull_t> GPIO_PIN_CNF_PULL_Disabled);
}
void Battery::Update() {
- isCharging = !nrf_gpio_pin_read(chargingPin);
- isPowerPresent = !nrf_gpio_pin_read(powerPresentPin);
+ isCharging = !nrf_gpio_pin_read(PinMap::Charging);
+ isPowerPresent = !nrf_gpio_pin_read(PinMap::PowerPresent);
if (isPowerPresent && !isCharging) {
isFull = true;
@@ -81,5 +79,11 @@ void Battery::SaadcEventHandler(nrfx_saadc_evt_t const* p_event) {
nrfx_saadc_uninit();
isReading = false;
+
+ systemTask->PushMessage(System::Messages::BatteryMeasurementDone);
}
}
+
+void Battery::Register(Pinetime::System::SystemTask* systemTask) {
+ this->systemTask = systemTask;
+}
diff --git a/src/components/battery/BatteryController.h b/src/components/battery/BatteryController.h
index b66da5e4..c78ffb3f 100644
--- a/src/components/battery/BatteryController.h
+++ b/src/components/battery/BatteryController.h
@@ -1,8 +1,7 @@
#pragma once
#include <cstdint>
#include <drivers/include/nrfx_saadc.h>
-#include <array>
-#include <numeric>
+#include <systemtask/SystemTask.h>
namespace Pinetime {
namespace Controllers {
@@ -11,8 +10,8 @@ namespace Pinetime {
public:
Battery();
- void Init();
void Update();
+ void Register(System::SystemTask* systemTask);
uint8_t PercentRemaining() const {
return percentRemaining;
@@ -36,8 +35,6 @@ namespace Pinetime {
static Battery* instance;
nrf_saadc_value_t saadc_value;
- static constexpr uint32_t chargingPin = 12;
- static constexpr uint32_t powerPresentPin = 19;
static constexpr nrf_saadc_input_t batteryVoltageAdcInput = NRF_SAADC_INPUT_AIN7;
uint16_t voltage = 0;
uint8_t percentRemaining = 0;
@@ -52,6 +49,8 @@ namespace Pinetime {
static void AdcCallbackStatic(nrfx_saadc_evt_t const* event);
bool isReading = false;
+
+ Pinetime::System::SystemTask* systemTask = nullptr;
};
}
}
diff --git a/src/components/ble/NimbleController.cpp b/src/components/ble/NimbleController.cpp
index 5eb227bf..879421e7 100644
--- a/src/components/ble/NimbleController.cpp
+++ b/src/components/ble/NimbleController.cpp
@@ -42,6 +42,19 @@ NimbleController::NimbleController(Pinetime::System::SystemTask& systemTask,
serviceDiscovery({&currentTimeClient, &alertNotificationClient}) {
}
+void nimble_on_reset(int reason) {
+ NRF_LOG_INFO("Resetting state; reason=%d\n", reason);
+}
+
+void nimble_on_sync(void) {
+ int rc;
+
+ rc = ble_hs_util_ensure_addr(0);
+ ASSERT(rc == 0);
+
+ nptr->StartAdvertising();
+}
+
int GAPEventCallback(struct ble_gap_event* event, void* arg) {
auto nimbleController = static_cast<NimbleController*>(arg);
return nimbleController->OnGAPEvent(event);
@@ -51,6 +64,10 @@ void NimbleController::Init() {
while (!ble_hs_synced()) {
}
+ nptr = this;
+ ble_hs_cfg.reset_cb = nimble_on_reset;
+ ble_hs_cfg.sync_cb = nimble_on_sync;
+
ble_svc_gap_init();
ble_svc_gatt_init();
@@ -64,28 +81,31 @@ void NimbleController::Init() {
batteryInformationService.Init();
immediateAlertService.Init();
heartRateService.Init();
- int res;
- res = ble_hs_util_ensure_addr(0);
- ASSERT(res == 0);
- res = ble_hs_id_infer_auto(0, &addrType);
- ASSERT(res == 0);
- res = ble_svc_gap_device_name_set(deviceName);
- ASSERT(res == 0);
+
+ int rc;
+ rc = ble_hs_util_ensure_addr(0);
+ ASSERT(rc == 0);
+ rc = ble_hs_id_infer_auto(0, &addrType);
+ ASSERT(rc == 0);
+ rc = ble_svc_gap_device_name_set(deviceName);
+ ASSERT(rc == 0);
+ rc = ble_svc_gap_device_appearance_set(0xC2);
+ ASSERT(rc == 0);
Pinetime::Controllers::Ble::BleAddress address;
- res = ble_hs_id_copy_addr(addrType, address.data(), nullptr);
- ASSERT(res == 0);
+ rc = ble_hs_id_copy_addr(addrType, address.data(), nullptr);
+ ASSERT(rc == 0);
bleController.AddressType((addrType == 0) ? Ble::AddressTypes::Public : Ble::AddressTypes::Random);
bleController.Address(std::move(address));
- res = ble_gatts_start();
- ASSERT(res == 0);
+ rc = ble_gatts_start();
+ ASSERT(rc == 0);
+
+ if (!ble_gap_adv_active() && !bleController.IsConnected())
+ StartAdvertising();
}
void NimbleController::StartAdvertising() {
- if (bleController.IsConnected() || ble_gap_conn_active() || ble_gap_adv_active())
- return;
-
- ble_svc_gap_device_name_set(deviceName);
+ int rc;
/* set adv parameters */
struct ble_gap_adv_params adv_params;
@@ -102,11 +122,17 @@ void NimbleController::StartAdvertising() {
adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
+ /* fast advertise for 30 sec */
+ if (fastAdvCount < 15) {
+ adv_params.itvl_min = 32;
+ adv_params.itvl_max = 47;
+ fastAdvCount++;
+ } else {
+ adv_params.itvl_min = 1636;
+ adv_params.itvl_max = 1651;
+ }
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));
fields.uuids128 = &dfuServiceUuid;
fields.num_uuids128 = 1;
fields.uuids128_is_complete = 1;
@@ -116,28 +142,25 @@ void NimbleController::StartAdvertising() {
rsp_fields.name_len = strlen(deviceName);
rsp_fields.name_is_complete = 1;
- ble_gap_adv_set_fields(&fields);
- // ASSERT(res == 0); // TODO this one sometimes fails with error 22 (notsync)
+ rc = ble_gap_adv_set_fields(&fields);
+ ASSERT(rc == 0);
- ble_gap_adv_rsp_set_fields(&rsp_fields);
- // ASSERT(res == 0);
+ rc = ble_gap_adv_rsp_set_fields(&rsp_fields);
+ ASSERT(rc == 0);
- 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.
- // I remove the assert to prevent this uncesseray crash, but in the long term, the management of
- // the advertising should be improve (better error handling, and advertise for 3 minutes after
- // the application has been woken up, for example.
+ rc = ble_gap_adv_start(addrType, NULL, 2000, &adv_params, GAPEventCallback, this);
+ ASSERT(rc == 0);
}
int NimbleController::OnGAPEvent(ble_gap_event* event) {
switch (event->type) {
case BLE_GAP_EVENT_ADV_COMPLETE:
NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_ADV_COMPLETE");
- NRF_LOG_INFO("advertise complete; reason=%dn status=%d", event->adv_complete.reason, event->connect.status);
+ NRF_LOG_INFO("reason=%d; status=%d", event->adv_complete.reason, event->connect.status);
+ StartAdvertising();
break;
- case BLE_GAP_EVENT_CONNECT: {
+
+ case BLE_GAP_EVENT_CONNECT:
NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_CONNECT");
/* A new connection was established or a connection attempt failed. */
@@ -145,35 +168,44 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) {
if (event->connect.status != 0) {
/* Connection failed; resume advertising. */
- StartAdvertising();
+ currentTimeClient.Reset();
+ alertNotificationClient.Reset();
+ connectionHandle = BLE_HS_CONN_HANDLE_NONE;
bleController.Disconnect();
+ fastAdvCount = 0;
+ StartAdvertising();
} else {
+ connectionHandle = event->connect.conn_handle;
bleController.Connect();
systemTask.PushMessage(Pinetime::System::Messages::BleConnected);
- connectionHandle = event->connect.conn_handle;
- // Service discovery is deffered via systemtask
+ // Service discovery is deferred 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);
+ NRF_LOG_INFO("disconnect reason=%d", event->disconnect.reason);
/* Connection terminated; resume advertising. */
currentTimeClient.Reset();
alertNotificationClient.Reset();
connectionHandle = BLE_HS_CONN_HANDLE_NONE;
bleController.Disconnect();
+ fastAdvCount = 0;
StartAdvertising();
break;
+
case BLE_GAP_EVENT_CONN_UPDATE:
NRF_LOG_INFO("Advertising event : BLE_GAP_EVENT_CONN_UPDATE");
/* The central has updated the connection parameters. */
- NRF_LOG_INFO("connection updated; status=%d ", event->conn_update.status);
+ NRF_LOG_INFO("update status=%d ", event->conn_update.status);
break;
+
case BLE_GAP_EVENT_ENC_CHANGE:
/* Encryption has been enabled or disabled for this connection. */
NRF_LOG_INFO("encryption change event; status=%d ", event->enc_change.status);
- return 0;
+ break;
+
case BLE_GAP_EVENT_SUBSCRIBE:
NRF_LOG_INFO("subscribe event; conn_handle=%d attr_handle=%d "
"reason=%d prevn=%d curn=%d previ=%d curi=???\n",
@@ -183,10 +215,12 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) {
event->subscribe.prev_notify,
event->subscribe.cur_notify,
event->subscribe.prev_indicate);
- return 0;
+ break;
+
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);
- return 0;
+ 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);
+ break;
case BLE_GAP_EVENT_REPEAT_PAIRING: {
/* We already have a bond with the peer, but it is attempting to
@@ -217,8 +251,7 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) {
notifSize);
alertNotificationClient.OnNotification(event);
- return 0;
- }
+ } break;
/* Attribute data is contained in event->notify_rx.attr_data. */
default:
@@ -229,7 +262,9 @@ int NimbleController::OnGAPEvent(ble_gap_event* event) {
}
void NimbleController::StartDiscovery() {
- serviceDiscovery.StartDiscovery(connectionHandle);
+ if (connectionHandle != BLE_HS_CONN_HANDLE_NONE) {
+ serviceDiscovery.StartDiscovery(connectionHandle);
+ }
}
uint16_t NimbleController::connHandle() {
@@ -237,7 +272,7 @@ uint16_t NimbleController::connHandle() {
}
void NimbleController::NotifyBatteryLevel(uint8_t level) {
- if(connectionHandle != BLE_HS_CONN_HANDLE_NONE) {
+ if (connectionHandle != BLE_HS_CONN_HANDLE_NONE) {
batteryInformationService.NotifyBatteryLevel(connectionHandle, level);
}
}
diff --git a/src/components/ble/NimbleController.h b/src/components/ble/NimbleController.h
index 0cfe983c..473bb1af 100644
--- a/src/components/ble/NimbleController.h
+++ b/src/components/ble/NimbleController.h
@@ -72,6 +72,10 @@ namespace Pinetime {
uint16_t connHandle();
void NotifyBatteryLevel(uint8_t level);
+ void RestartFastAdv() {
+ fastAdvCount = 0;
+ }
+
private:
static constexpr const char* deviceName = "InfiniTime";
Pinetime::System::SystemTask& systemTask;
@@ -94,6 +98,7 @@ namespace Pinetime {
uint8_t addrType; // 1 = Random, 0 = PUBLIC
uint16_t connectionHandle = BLE_HS_CONN_HANDLE_NONE;
+ uint8_t fastAdvCount = 0;
ble_uuid128_t dfuServiceUuid {
.u {.type = BLE_UUID_TYPE_128},
@@ -101,5 +106,7 @@ namespace Pinetime {
ServiceDiscovery serviceDiscovery;
};
+
+ static NimbleController* nptr;
}
}
diff --git a/src/components/brightness/BrightnessController.cpp b/src/components/brightness/BrightnessController.cpp
index 8ad987d1..6c524679 100644
--- a/src/components/brightness/BrightnessController.cpp
+++ b/src/components/brightness/BrightnessController.cpp
@@ -1,13 +1,13 @@
#include "BrightnessController.h"
#include <hal/nrf_gpio.h>
#include "displayapp/screens/Symbols.h"
-
+#include "drivers/PinMap.h"
using namespace Pinetime::Controllers;
void BrightnessController::Init() {
- nrf_gpio_cfg_output(pinLcdBacklight1);
- nrf_gpio_cfg_output(pinLcdBacklight2);
- nrf_gpio_cfg_output(pinLcdBacklight3);
+ nrf_gpio_cfg_output(PinMap::LcdBacklightLow);
+ nrf_gpio_cfg_output(PinMap::LcdBacklightMedium);
+ nrf_gpio_cfg_output(PinMap::LcdBacklightHigh);
Set(level);
}
@@ -16,24 +16,24 @@ void BrightnessController::Set(BrightnessController::Levels level) {
switch (level) {
default:
case Levels::High:
- nrf_gpio_pin_clear(pinLcdBacklight1);
- nrf_gpio_pin_clear(pinLcdBacklight2);
- nrf_gpio_pin_clear(pinLcdBacklight3);
+ nrf_gpio_pin_clear(PinMap::LcdBacklightLow);
+ nrf_gpio_pin_clear(PinMap::LcdBacklightMedium);
+ nrf_gpio_pin_clear(PinMap::LcdBacklightHigh);
break;
case Levels::Medium:
- nrf_gpio_pin_clear(pinLcdBacklight1);
- nrf_gpio_pin_clear(pinLcdBacklight2);
- nrf_gpio_pin_set(pinLcdBacklight3);
+ nrf_gpio_pin_clear(PinMap::LcdBacklightLow);
+ nrf_gpio_pin_clear(PinMap::LcdBacklightMedium);
+ nrf_gpio_pin_set(PinMap::LcdBacklightHigh);
break;
case Levels::Low:
- nrf_gpio_pin_clear(pinLcdBacklight1);
- nrf_gpio_pin_set(pinLcdBacklight2);
- nrf_gpio_pin_set(pinLcdBacklight3);
+ nrf_gpio_pin_clear(PinMap::LcdBacklightLow);
+ nrf_gpio_pin_set(PinMap::LcdBacklightMedium);
+ nrf_gpio_pin_set(PinMap::LcdBacklightHigh);
break;
case Levels::Off:
- nrf_gpio_pin_set(pinLcdBacklight1);
- nrf_gpio_pin_set(pinLcdBacklight2);
- nrf_gpio_pin_set(pinLcdBacklight3);
+ nrf_gpio_pin_set(PinMap::LcdBacklightLow);
+ nrf_gpio_pin_set(PinMap::LcdBacklightMedium);
+ nrf_gpio_pin_set(PinMap::LcdBacklightHigh);
break;
}
}
diff --git a/src/components/brightness/BrightnessController.h b/src/components/brightness/BrightnessController.h
index c47158a9..0d7ac2ff 100644
--- a/src/components/brightness/BrightnessController.h
+++ b/src/components/brightness/BrightnessController.h
@@ -22,9 +22,6 @@ namespace Pinetime {
const char* ToString();
private:
- static constexpr uint8_t pinLcdBacklight1 = 14;
- static constexpr uint8_t pinLcdBacklight2 = 22;
- static constexpr uint8_t pinLcdBacklight3 = 23;
Levels level = Levels::High;
Levels backupLevel = Levels::High;
};
diff --git a/src/components/datetime/DateTimeController.cpp b/src/components/datetime/DateTimeController.cpp
index d6aa83c8..0756d38d 100644
--- a/src/components/datetime/DateTimeController.cpp
+++ b/src/components/datetime/DateTimeController.cpp
@@ -5,6 +5,11 @@
using namespace Pinetime::Controllers;
+void DateTime::SetCurrentTime(std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> t) {
+ this->currentDateTime = t;
+ UpdateTime(previousSystickCounter); // Update internal state without updating the time
+}
+
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 = {
@@ -67,7 +72,7 @@ void DateTime::UpdateTime(uint32_t systickCounter) {
// Notify new day to SystemTask
if (hour == 0 and not isMidnightAlreadyNotified) {
isMidnightAlreadyNotified = true;
- if(systemTask != nullptr)
+ if (systemTask != nullptr)
systemTask->PushMessage(System::Messages::OnNewDay);
} else if (hour != 0) {
isMidnightAlreadyNotified = false;
diff --git a/src/components/datetime/DateTimeController.h b/src/components/datetime/DateTimeController.h
index 265d6e9d..061c303f 100644
--- a/src/components/datetime/DateTimeController.h
+++ b/src/components/datetime/DateTimeController.h
@@ -74,6 +74,7 @@ namespace Pinetime {
}
void Register(System::SystemTask* systemTask);
+ void SetCurrentTime(std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> t);
private:
uint16_t year = 0;
diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp
index b25e6bc8..42057a86 100644
--- a/src/components/motor/MotorController.cpp
+++ b/src/components/motor/MotorController.cpp
@@ -2,6 +2,7 @@
#include <hal/nrf_gpio.h>
#include "systemtask/SystemTask.h"
#include "app_timer.h"
+#include "drivers/PinMap.h"
APP_TIMER_DEF(shortVibTimer);
APP_TIMER_DEF(longVibTimer);
@@ -12,8 +13,8 @@ MotorController::MotorController(Controllers::Settings& settingsController) : se
}
void MotorController::Init() {
- nrf_gpio_cfg_output(pinMotor);
- nrf_gpio_pin_set(pinMotor);
+ nrf_gpio_cfg_output(PinMap::Motor);
+ nrf_gpio_pin_set(PinMap::Motor);
app_timer_init();
app_timer_create(&shortVibTimer, APP_TIMER_MODE_SINGLE_SHOT, StopMotor);
@@ -30,7 +31,7 @@ void MotorController::RunForDuration(uint8_t motorDuration) {
return;
}
- nrf_gpio_pin_clear(pinMotor);
+ nrf_gpio_pin_clear(PinMap::Motor);
app_timer_start(shortVibTimer, APP_TIMER_TICKS(motorDuration), nullptr);
}
@@ -44,9 +45,9 @@ void MotorController::StartRinging() {
void MotorController::StopRinging() {
app_timer_stop(longVibTimer);
- nrf_gpio_pin_set(pinMotor);
+ nrf_gpio_pin_set(PinMap::Motor);
}
void MotorController::StopMotor(void* p_context) {
- nrf_gpio_pin_set(pinMotor);
+ nrf_gpio_pin_set(PinMap::Motor);
}
diff --git a/src/components/motor/MotorController.h b/src/components/motor/MotorController.h
index d2c9fe5f..cf78088e 100644
--- a/src/components/motor/MotorController.h
+++ b/src/components/motor/MotorController.h
@@ -1,12 +1,10 @@
#pragma once
#include <cstdint>
-#include "app_timer.h"
#include "components/settings/Settings.h"
namespace Pinetime {
namespace Controllers {
- static constexpr uint8_t pinMotor = 16;
class MotorController {
public:
diff --git a/src/components/settings/Settings.h b/src/components/settings/Settings.h
index a294ab78..a54ba976 100644
--- a/src/components/settings/Settings.h
+++ b/src/components/settings/Settings.h
@@ -114,7 +114,7 @@ namespace Pinetime {
};
void setWakeUpMode(WakeUpMode wakeUp, bool enabled) {
- if (!isWakeUpModeOn(wakeUp)) {
+ if (enabled != isWakeUpModeOn(wakeUp)) {
settingsChanged = true;
}
settings.wakeUpMode.set(static_cast<size_t>(wakeUp), enabled);
diff --git a/src/displayapp/Apps.h b/src/displayapp/Apps.h
index dd51fdb4..e3aca8cf 100644
--- a/src/displayapp/Apps.h
+++ b/src/displayapp/Apps.h
@@ -12,6 +12,7 @@ namespace Pinetime {
NotificationsPreview,
Notifications,
Timer,
+ Alarm,
FlashLight,
BatteryInfo,
Music,
diff --git a/src/displayapp/DisplayApp.cpp b/src/displayapp/DisplayApp.cpp
index d6100ece..9d473101 100644
--- a/src/displayapp/DisplayApp.cpp
+++ b/src/displayapp/DisplayApp.cpp
@@ -3,6 +3,7 @@
#include <displayapp/screens/HeartRate.h>
#include <displayapp/screens/Motion.h>
#include <displayapp/screens/Timer.h>
+#include <displayapp/screens/Alarm.h>
#include "components/battery/BatteryController.h"
#include "components/ble/BleController.h"
#include "components/datetime/DateTimeController.h"
@@ -90,6 +91,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
Pinetime::Controllers::MotorController& motorController,
Pinetime::Controllers::MotionController& motionController,
Pinetime::Controllers::TimerController& timerController,
+ Pinetime::Controllers::AlarmController& alarmController,
Pinetime::Controllers::TouchHandler& touchHandler)
: lcd {lcd},
lvgl {lvgl},
@@ -104,6 +106,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
motorController {motorController},
motionController {motionController},
timerController {timerController},
+ alarmController {alarmController},
touchHandler {touchHandler} {
}
@@ -136,9 +139,6 @@ void DisplayApp::InitHw() {
brightnessController.Set(settingsController.GetBrightness());
}
-uint32_t acc = 0;
-uint32_t count = 0;
-bool toggle = true;
void DisplayApp::Refresh() {
TickType_t queueTimeout;
TickType_t delta;
@@ -194,9 +194,6 @@ void DisplayApp::Refresh() {
// clockScreen.SetBleConnectionState(bleController.IsConnected() ? Screens::Clock::BleConnectionStates::Connected :
// Screens::Clock::BleConnectionStates::NotConnected);
break;
- case Messages::UpdateBatteryLevel:
- batteryController.Update();
- break;
case Messages::NewNotification:
LoadApp(Apps::NotificationsPreview, DisplayApp::FullRefreshDirections::Down);
break;
@@ -208,6 +205,13 @@ void DisplayApp::Refresh() {
LoadApp(Apps::Timer, DisplayApp::FullRefreshDirections::Down);
}
break;
+ case Messages::AlarmTriggered:
+ if (currentApp == Apps::Alarm) {
+ auto* alarm = static_cast<Screens::Alarm*>(currentScreen.get());
+ alarm->SetAlerting();
+ } else {
+ LoadApp(Apps::Alarm, DisplayApp::FullRefreshDirections::None);
+ }
case Messages::TouchEvent: {
if (state != States::Running) {
break;
@@ -340,6 +344,9 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction)
case Apps::Timer:
currentScreen = std::make_unique<Screens::Timer>(this, timerController);
break;
+ case Apps::Alarm:
+ currentScreen = std::make_unique<Screens::Alarm>(this, alarmController);
+ break;
// Settings
case Apps::QuickSettings:
diff --git a/src/displayapp/DisplayApp.h b/src/displayapp/DisplayApp.h
index 96951d1c..4254523a 100644
--- a/src/displayapp/DisplayApp.h
+++ b/src/displayapp/DisplayApp.h
@@ -14,7 +14,9 @@
#include "components/settings/Settings.h"
#include "displayapp/screens/Screen.h"
#include "components/timer/TimerController.h"
+#include "components/alarm/AlarmController.h"
#include "touchhandler/TouchHandler.h"
+
#include "Messages.h"
namespace Pinetime {
@@ -57,6 +59,7 @@ namespace Pinetime {
Pinetime::Controllers::MotorController& motorController,
Pinetime::Controllers::MotionController& motionController,
Pinetime::Controllers::TimerController& timerController,
+ Pinetime::Controllers::AlarmController& alarmController,
Pinetime::Controllers::TouchHandler& touchHandler);
void Start();
void PushMessage(Display::Messages msg);
@@ -82,6 +85,7 @@ namespace Pinetime {
Pinetime::Controllers::MotorController& motorController;
Pinetime::Controllers::MotionController& motionController;
Pinetime::Controllers::TimerController& timerController;
+ Pinetime::Controllers::AlarmController& alarmController;
Pinetime::Controllers::TouchHandler& touchHandler;
Pinetime::Controllers::FirmwareValidator validator;
diff --git a/src/displayapp/DisplayAppRecovery.cpp b/src/displayapp/DisplayAppRecovery.cpp
index 17612ef0..a42d81a2 100644
--- a/src/displayapp/DisplayAppRecovery.cpp
+++ b/src/displayapp/DisplayAppRecovery.cpp
@@ -5,6 +5,7 @@
#include <components/rle/RleDecoder.h>
#include <touchhandler/TouchHandler.h>
#include "displayapp/icons/infinitime/infinitime-nb.c"
+#include "components/ble/BleController.h"
using namespace Pinetime::Applications;
@@ -21,6 +22,7 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
Pinetime::Controllers::MotorController& motorController,
Pinetime::Controllers::MotionController& motionController,
Pinetime::Controllers::TimerController& timerController,
+ Pinetime::Controllers::AlarmController& alarmController,
Pinetime::Controllers::TouchHandler& touchHandler)
: lcd {lcd}, bleController {bleController} {
diff --git a/src/displayapp/DisplayAppRecovery.h b/src/displayapp/DisplayAppRecovery.h
index 8b2bc7f5..425e0aca 100644
--- a/src/displayapp/DisplayAppRecovery.h
+++ b/src/displayapp/DisplayAppRecovery.h
@@ -6,32 +6,39 @@
#include <bits/unique_ptr.h>
#include <queue.h>
#include "components/gfx/Gfx.h"
-#include "components/battery/BatteryController.h"
-#include "components/brightness/BrightnessController.h"
-#include "components/ble/BleController.h"
-#include "components/datetime/DateTimeController.h"
-#include "components/ble/NotificationManager.h"
-#include "components/firmwarevalidator/FirmwareValidator.h"
#include "drivers/Cst816s.h"
#include <date/date.h>
#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"
#include "Messages.h"
#include "DummyLittleVgl.h"
-#include "components/timer/TimerController.h"
namespace Pinetime {
- namespace System {
- class SystemTask;
- };
+ namespace Drivers {
+ class St7789;
+ class Cst816S;
+ class WatchdogView;
+ }
namespace Controllers {
+ class Settings;
+ class Battery;
+ class Ble;
+ class DateTime;
+ class NotificationManager;
+ class HeartRateController;
+ class MotionController;
class TouchHandler;
+ class MotorController;
+ class TimerController;
+ class AlarmController;
}
+
+ namespace System {
+ class SystemTask;
+ };
+
namespace Applications {
class DisplayApp {
public:
@@ -48,6 +55,7 @@ namespace Pinetime {
Pinetime::Controllers::MotorController& motorController,
Pinetime::Controllers::MotionController& motionController,
Pinetime::Controllers::TimerController& timerController,
+ Pinetime::Controllers::AlarmController& alarmController,
Pinetime::Controllers::TouchHandler& touchHandler);
void Start();
void PushMessage(Pinetime::Applications::Display::Messages msg);
diff --git a/src/displayapp/Messages.h b/src/displayapp/Messages.h
index 322505e6..d48b646f 100644
--- a/src/displayapp/Messages.h
+++ b/src/displayapp/Messages.h
@@ -7,7 +7,6 @@ namespace Pinetime {
GoToRunning,
UpdateDateTime,
UpdateBleConnection,
- UpdateBatteryLevel,
TouchEvent,
ButtonPushed,
NewNotification,
@@ -15,7 +14,8 @@ namespace Pinetime {
BleFirmwareUpdateStarted,
UpdateTimeOut,
DimScreen,
- RestoreBrightness
+ RestoreBrightness,
+ AlarmTriggered
};
}
}
diff --git a/src/displayapp/screens/Alarm.cpp b/src/displayapp/screens/Alarm.cpp
new file mode 100644
index 00000000..959cb0b2
--- /dev/null
+++ b/src/displayapp/screens/Alarm.cpp
@@ -0,0 +1,254 @@
+/* Copyright (C) 2021 mruss77, Florian
+
+ This file is part of InfiniTime.
+
+ InfiniTime is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ InfiniTime is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#include "Alarm.h"
+#include "Screen.h"
+#include "Symbols.h"
+
+using namespace Pinetime::Applications::Screens;
+using Pinetime::Controllers::AlarmController;
+
+static void btnEventHandler(lv_obj_t* obj, lv_event_t event) {
+ Alarm* screen = static_cast<Alarm*>(obj->user_data);
+ screen->OnButtonEvent(obj, event);
+}
+
+Alarm::Alarm(DisplayApp* app, Controllers::AlarmController& alarmController)
+ : Screen(app), running {true}, alarmController {alarmController} {
+
+ time = lv_label_create(lv_scr_act(), nullptr);
+ lv_obj_set_style_local_text_font(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, &jetbrains_mono_76);
+ lv_obj_set_style_local_text_color(time, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
+
+ alarmHours = alarmController.Hours();
+ alarmMinutes = alarmController.Minutes();
+ lv_label_set_text_fmt(time, "%02lu:%02lu", alarmHours, alarmMinutes);
+
+ lv_obj_align(time, lv_scr_act(), LV_ALIGN_CENTER, 0, -25);
+
+ btnHoursUp = lv_btn_create(lv_scr_act(), nullptr);
+ btnHoursUp->user_data = this;
+ lv_obj_set_event_cb(btnHoursUp, btnEventHandler);
+ lv_obj_set_size(btnHoursUp, 60, 40);
+ lv_obj_align(btnHoursUp, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 20, -85);
+ txtHrUp = lv_label_create(btnHoursUp, nullptr);
+ lv_label_set_text_static(txtHrUp, "+");
+
+ btnHoursDown = lv_btn_create(lv_scr_act(), nullptr);
+ btnHoursDown->user_data = this;
+ lv_obj_set_event_cb(btnHoursDown, btnEventHandler);
+ lv_obj_set_size(btnHoursDown, 60, 40);
+ lv_obj_align(btnHoursDown, lv_scr_act(), LV_ALIGN_IN_LEFT_MID, 20, 35);
+ txtHrDown = lv_label_create(btnHoursDown, nullptr);
+ lv_label_set_text_static(txtHrDown, "-");
+
+ btnMinutesUp = lv_btn_create(lv_scr_act(), nullptr);
+ btnMinutesUp->user_data = this;
+ lv_obj_set_event_cb(btnMinutesUp, btnEventHandler);
+ lv_obj_set_size(btnMinutesUp, 60, 40);
+ lv_obj_align(btnMinutesUp, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -20, -85);
+ txtMinUp = lv_label_create(btnMinutesUp, nullptr);
+ lv_label_set_text_static(txtMinUp, "+");
+
+ btnMinutesDown = lv_btn_create(lv_scr_act(), nullptr);
+ btnMinutesDown->user_data = this;
+ lv_obj_set_event_cb(btnMinutesDown, btnEventHandler);
+ lv_obj_set_size(btnMinutesDown, 60, 40);
+ lv_obj_align(btnMinutesDown, lv_scr_act(), LV_ALIGN_IN_RIGHT_MID, -20, 35);
+ txtMinDown = lv_label_create(btnMinutesDown, nullptr);
+ lv_label_set_text_static(txtMinDown, "-");
+
+ btnEnable = lv_btn_create(lv_scr_act(), nullptr);
+ btnEnable->user_data = this;
+ lv_obj_set_event_cb(btnEnable, btnEventHandler);
+ lv_obj_set_size(btnEnable, 115, 50);
+ lv_obj_align(btnEnable, lv_scr_act(), LV_ALIGN_IN_BOTTOM_LEFT, 0, 0);
+ txtEnable = lv_label_create(btnEnable, nullptr);
+ SetEnableButtonState();
+
+ btnRecur = lv_btn_create(lv_scr_act(), nullptr);
+ btnRecur->user_data = this;
+ lv_obj_set_event_cb(btnRecur, btnEventHandler);
+ lv_obj_set_size(btnRecur, 115, 50);
+ lv_obj_align(btnRecur, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
+ txtRecur = lv_label_create(btnRecur, nullptr);
+ SetRecurButtonState();
+
+ btnInfo = lv_btn_create(lv_scr_act(), nullptr);
+ btnInfo->user_data = this;
+ lv_obj_set_event_cb(btnInfo, btnEventHandler);
+ lv_obj_set_size(btnInfo, 50, 40);
+ lv_obj_align(btnInfo, lv_scr_act(), LV_ALIGN_CENTER, 0, -85);
+ txtInfo = lv_label_create(btnInfo, nullptr);
+ lv_label_set_text_static(txtInfo, "i");
+}
+
+Alarm::~Alarm() {
+ lv_obj_clean(lv_scr_act());
+}
+
+void Alarm::OnButtonEvent(lv_obj_t* obj, lv_event_t event) {
+ using Pinetime::Controllers::AlarmController;
+ if (event == LV_EVENT_CLICKED) {
+ if (obj == btnEnable) {
+ if (alarmController.State() == AlarmController::AlarmState::Alerting) {
+ alarmController.StopAlerting();
+ } else if (alarmController.State() == AlarmController::AlarmState::Set) {
+ alarmController.DisableAlarm();
+ } else {
+ alarmController.ScheduleAlarm();
+ }
+ SetEnableButtonState();
+ return;
+ }
+ if (obj == btnInfo) {
+ ShowInfo();
+ return;
+ }
+ if (obj == btnMessage) {
+ lv_obj_del(txtMessage);
+ lv_obj_del(btnMessage);
+ txtMessage = nullptr;
+ btnMessage = nullptr;
+ return;
+ }
+ // If any other button was pressed, disable the alarm
+ // this is to make it clear that the alarm won't be set until it is turned back on
+ if (alarmController.State() == AlarmController::AlarmState::Set) {
+ alarmController.DisableAlarm();
+ SetEnableButtonState();
+ }
+ if (obj == btnMinutesUp) {
+ if (alarmMinutes >= 59) {
+ alarmMinutes = 0;
+ } else {
+ alarmMinutes++;
+ }
+ UpdateAlarmTime();
+ return;
+ }
+ if (obj == btnMinutesDown) {
+ if (alarmMinutes == 0) {
+ alarmMinutes = 59;
+ } else {
+ alarmMinutes--;
+ }
+ UpdateAlarmTime();
+ return;
+ }
+ if (obj == btnHoursUp) {
+ if (alarmHours >= 23) {
+ alarmHours = 0;
+ } else {
+ alarmHours++;
+ }
+ UpdateAlarmTime();
+ return;
+ }
+ if (obj == btnHoursDown) {
+ if (alarmHours == 0) {
+ alarmHours = 23;
+ } else {
+ alarmHours--;
+ }
+ UpdateAlarmTime();
+ return;
+ }
+ if (obj == btnRecur) {
+ ToggleRecurrence();
+ }
+ }
+}
+
+void Alarm::UpdateAlarmTime() {
+ lv_label_set_text_fmt(time, "%02d:%02d", alarmHours, alarmMinutes);
+ alarmController.SetAlarmTime(alarmHours, alarmMinutes);
+}
+
+void Alarm::SetAlerting() {
+ SetEnableButtonState();
+}
+
+void Alarm::SetEnableButtonState() {
+ switch (alarmController.State()) {
+ case AlarmController::AlarmState::Set:
+ lv_label_set_text(txtEnable, "ON");
+ lv_obj_set_style_local_bg_color(btnEnable, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GREEN);
+ break;
+ case AlarmController::AlarmState::Not_Set:
+ lv_label_set_text(txtEnable, "OFF");
+ lv_obj_set_style_local_bg_color(btnEnable, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_GRAY);
+ break;
+ case AlarmController::AlarmState::Alerting:
+ lv_label_set_text(txtEnable, Symbols::stop);
+ lv_obj_set_style_local_bg_color(btnEnable, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_RED);
+ }
+}
+
+void Alarm::ShowInfo() {
+ btnMessage = lv_btn_create(lv_scr_act(), nullptr);
+ btnMessage->user_data = this;
+ lv_obj_set_event_cb(btnMessage, btnEventHandler);
+ lv_obj_set_height(btnMessage, 200);
+ lv_obj_set_width(btnMessage, 150);
+ lv_obj_align(btnMessage, lv_scr_act(), LV_ALIGN_CENTER, 0, 0);
+ txtMessage = lv_label_create(btnMessage, nullptr);
+ lv_obj_set_style_local_bg_color(btnMessage, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_NAVY);
+
+ if (alarmController.State() == AlarmController::AlarmState::Set) {
+ auto timeToAlarm = alarmController.SecondsToAlarm();
+
+ auto daysToAlarm = timeToAlarm / 86400;
+ auto hrsToAlarm = (timeToAlarm % 86400) / 3600;
+ auto minToAlarm = (timeToAlarm % 3600) / 60;
+ auto secToAlarm = timeToAlarm % 60;
+
+ lv_label_set_text_fmt(
+ txtMessage, "Time to\nalarm:\n%2d Days\n%2d Hours\n%2d Minutes\n%2d Seconds", daysToAlarm, hrsToAlarm, minToAlarm, secToAlarm);
+ } else {
+ lv_label_set_text(txtMessage, "Alarm\nis not\nset.");
+ }
+}
+
+void Alarm::SetRecurButtonState() {
+ using Pinetime::Controllers::AlarmController;
+ switch (alarmController.Recurrence()) {
+ case AlarmController::RecurType::None:
+ lv_label_set_text(txtRecur, "ONCE");
+ break;
+ case AlarmController::RecurType::Daily:
+ lv_label_set_text(txtRecur, "DAILY");
+ break;
+ case AlarmController::RecurType::Weekdays:
+ lv_label_set_text(txtRecur, "MON-FRI");
+ }
+}
+
+void Alarm::ToggleRecurrence() {
+ using Pinetime::Controllers::AlarmController;
+ switch (alarmController.Recurrence()) {
+ case AlarmController::RecurType::None:
+ alarmController.SetRecurrence(AlarmController::RecurType::Daily);
+ break;
+ case AlarmController::RecurType::Daily:
+ alarmController.SetRecurrence(AlarmController::RecurType::Weekdays);
+ break;
+ case AlarmController::RecurType::Weekdays:
+ alarmController.SetRecurrence(AlarmController::RecurType::None);
+ }
+ SetRecurButtonState();
+}
diff --git a/src/displayapp/screens/Alarm.h b/src/displayapp/screens/Alarm.h
new file mode 100644
index 00000000..abf97eba
--- /dev/null
+++ b/src/displayapp/screens/Alarm.h
@@ -0,0 +1,54 @@
+/* Copyright (C) 2021 mruss77, Florian
+
+ This file is part of InfiniTime.
+
+ InfiniTime is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published
+ by the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ InfiniTime is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+#pragma once
+
+#include "Screen.h"
+#include "systemtask/SystemTask.h"
+#include "../LittleVgl.h"
+#include "components/alarm/AlarmController.h"
+
+namespace Pinetime {
+ namespace Applications {
+ namespace Screens {
+ class Alarm : public Screen {
+ public:
+ Alarm(DisplayApp* app, Controllers::AlarmController& alarmController);
+ ~Alarm() override;
+ void SetAlerting();
+ void OnButtonEvent(lv_obj_t* obj, lv_event_t event);
+
+ private:
+ bool running;
+ uint8_t alarmHours;
+ uint8_t alarmMinutes;
+ Controllers::AlarmController& alarmController;
+
+ lv_obj_t *time, *btnEnable, *txtEnable, *btnMinutesUp, *btnMinutesDown, *btnHoursUp, *btnHoursDown, *txtMinUp, *txtMinDown,
+ *txtHrUp, *txtHrDown, *btnRecur, *txtRecur, *btnMessage, *txtMessage, *btnInfo, *txtInfo;
+
+ enum class EnableButtonState { On, Off, Alerting };
+ void SetEnableButtonState();
+ void SetRecurButtonState();
+ void SetAlarm();
+ void ShowInfo();
+ void ToggleRecurrence();
+ void UpdateAlarmTime();
+ };
+ };
+ };
+}
diff --git a/src/displayapp/screens/ApplicationList.cpp b/src/displayapp/screens/ApplicationList.cpp
index 6e7bbb74..5c582f60 100644
--- a/src/displayapp/screens/ApplicationList.cpp
+++ b/src/displayapp/screens/ApplicationList.cpp
@@ -58,7 +58,7 @@ std::unique_ptr<Screen> ApplicationList::CreateScreen2() {
{"2", Apps::Twos},
{Symbols::chartLine, Apps::Motion},
{Symbols::drum, Apps::Metronome},
- {"", Apps::None},
+ {Symbols::clock, Apps::Alarm},
}};
return std::make_unique<Screens::Tile>(1, 2, app, settingsController, batteryController, dateTimeController, applications);
diff --git a/src/displayapp/screens/BatteryInfo.cpp b/src/displayapp/screens/BatteryInfo.cpp
index 25fd1efa..44ea7f51 100644
--- a/src/displayapp/screens/BatteryInfo.cpp
+++ b/src/displayapp/screens/BatteryInfo.cpp
@@ -55,8 +55,6 @@ BatteryInfo::~BatteryInfo() {
void BatteryInfo::Refresh() {
- batteryController.Update();
-
batteryPercent = batteryController.PercentRemaining();
batteryVoltage = batteryController.Voltage();
diff --git a/src/displayapp/screens/Metronome.cpp b/src/displayapp/screens/Metronome.cpp
index 884a4a51..52cb8519 100644
--- a/src/displayapp/screens/Metronome.cpp
+++ b/src/displayapp/screens/Metronome.cpp
@@ -78,7 +78,7 @@ Metronome::~Metronome() {
void Metronome::Refresh() {
if (metronomeStarted) {
- if (xTaskGetTickCount() - startTime > 60 * configTICK_RATE_HZ / bpm) {
+ if (xTaskGetTickCount() - startTime > 60u * configTICK_RATE_HZ / static_cast<uint16_t>(bpm)) {
startTime += 60 * configTICK_RATE_HZ / bpm;
counter--;
if (counter == 0) {
diff --git a/src/displayapp/screens/Notifications.cpp b/src/displayapp/screens/Notifications.cpp
index 22eb290e..417dff00 100644
--- a/src/displayapp/screens/Notifications.cpp
+++ b/src/displayapp/screens/Notifications.cpp
@@ -152,7 +152,7 @@ Notifications::NotificationItem::NotificationItem(const char* title,
uint8_t notifNb,
Modes mode,
Pinetime::Controllers::AlertNotificationService& alertNotificationService)
- : notifNr {notifNr}, notifNb {notifNb}, mode {mode}, alertNotificationService {alertNotificationService} {
+ : mode {mode}, alertNotificationService {alertNotificationService} {
lv_obj_t* container1 = lv_cont_create(lv_scr_act(), NULL);
lv_obj_set_style_local_bg_color(container1, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x222222));
diff --git a/src/displayapp/screens/Notifications.h b/src/displayapp/screens/Notifications.h
index f6f8b4c3..0b5271e7 100644
--- a/src/displayapp/screens/Notifications.h
+++ b/src/displayapp/screens/Notifications.h
@@ -43,21 +43,13 @@ namespace Pinetime {
void OnCallButtonEvent(lv_obj_t*, lv_event_t event);
private:
- uint8_t notifNr = 0;
- uint8_t notifNb = 0;
- char pageText[4];
-
lv_obj_t* container1;
- lv_obj_t* t1;
- lv_obj_t* l1;
- lv_obj_t* l2;
lv_obj_t* bt_accept;
lv_obj_t* bt_mute;
lv_obj_t* bt_reject;
lv_obj_t* label_accept;
lv_obj_t* label_mute;
lv_obj_t* label_reject;
- lv_obj_t* bottomPlaceholder;
Modes mode;
Pinetime::Controllers::AlertNotificationService& alertNotificationService;
bool running = true;
diff --git a/src/displayapp/screens/settings/Settings.cpp b/src/displayapp/screens/settings/Settings.cpp
index f82b03c1..e3319f03 100644
--- a/src/displayapp/screens/settings/Settings.cpp
+++ b/src/displayapp/screens/settings/Settings.cpp
@@ -50,8 +50,8 @@ std::unique_ptr<Screen> Settings::CreateScreen2() {
std::array<Screens::List::Applications, 4> applications {{
{Symbols::shoe, "Steps", Apps::SettingSteps},
{Symbols::batteryHalf, "Battery", Apps::BatteryInfo},
+ {Symbols::paintbrush, "PTS Colors", Apps::SettingPineTimeStyle},
{Symbols::check, "Firmware", Apps::FirmwareValidation},
- {Symbols::list, "About", Apps::SysInfo},
}};
return std::make_unique<Screens::List>(1, 3, app, settingsController, applications);
@@ -60,7 +60,7 @@ std::unique_ptr<Screen> Settings::CreateScreen2() {
std::unique_ptr<Screen> Settings::CreateScreen3() {
std::array<Screens::List::Applications, 4> applications {{
- {Symbols::paintbrush, "PTS Colors", Apps::SettingPineTimeStyle},
+ {Symbols::list, "About", Apps::SysInfo},
{Symbols::none, "None", Apps::None},
{Symbols::none, "None", Apps::None},
{Symbols::none, "None", Apps::None},
diff --git a/src/drivers/Cst816s.cpp b/src/drivers/Cst816s.cpp
index b8f8e45d..1ff163b0 100644
--- a/src/drivers/Cst816s.cpp
+++ b/src/drivers/Cst816s.cpp
@@ -3,6 +3,7 @@
#include <legacy/nrf_drv_gpiote.h>
#include <nrfx_log.h>
#include <task.h>
+#include "drivers/PinMap.h"
using namespace Pinetime::Drivers;
@@ -18,12 +19,12 @@ Cst816S::Cst816S(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster {twiMaste
}
void Cst816S::Init() {
- nrf_gpio_cfg_output(pinReset);
- nrf_gpio_pin_set(pinReset);
+ nrf_gpio_cfg_output(PinMap::Cst816sReset);
+ nrf_gpio_pin_set(PinMap::Cst816sReset);
vTaskDelay(50);
- nrf_gpio_pin_clear(pinReset);
+ nrf_gpio_pin_clear(PinMap::Cst816sReset);
vTaskDelay(5);
- nrf_gpio_pin_set(pinReset);
+ nrf_gpio_pin_set(PinMap::Cst816sReset);
vTaskDelay(50);
// Wake the touchpanel up
@@ -80,9 +81,9 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() {
}
void Cst816S::Sleep() {
- nrf_gpio_pin_clear(pinReset);
+ nrf_gpio_pin_clear(PinMap::Cst816sReset);
vTaskDelay(5);
- nrf_gpio_pin_set(pinReset);
+ nrf_gpio_pin_set(PinMap::Cst816sReset);
vTaskDelay(50);
static constexpr uint8_t sleepValue = 0x03;
twiMaster.Write(twiAddress, 0xA5, &sleepValue, 1);
diff --git a/src/drivers/Cst816s.h b/src/drivers/Cst816s.h
index d4c17bb8..7b46c5d5 100644
--- a/src/drivers/Cst816s.h
+++ b/src/drivers/Cst816s.h
@@ -36,9 +36,6 @@ namespace Pinetime {
void Wakeup();
private:
- static constexpr uint8_t pinIrq = 28;
- static constexpr uint8_t pinReset = 10;
-
// Unused/Unavailable commented out
static constexpr uint8_t gestureIndex = 1;
static constexpr uint8_t touchPointNumIndex = 2;
diff --git a/src/drivers/PinMap.h b/src/drivers/PinMap.h
new file mode 100644
index 00000000..57964020
--- /dev/null
+++ b/src/drivers/PinMap.h
@@ -0,0 +1,38 @@
+#pragma once
+
+namespace Pinetime {
+ namespace PinMap {
+
+ #ifdef WATCH_P8
+ // COLMI P8
+ static constexpr uint8_t Charging = 19;
+ static constexpr uint8_t Cst816sReset = 13;
+ static constexpr uint8_t Button = 17;
+ #else
+ // Pinetime
+ static constexpr uint8_t Charging = 12;
+ static constexpr uint8_t Cst816sReset = 10;
+ static constexpr uint8_t Button = 13;
+ #endif
+
+ static constexpr uint8_t Cst816sIrq = 28;
+ static constexpr uint8_t PowerPresent = 19;
+
+ static constexpr uint8_t Motor = 16;
+
+ static constexpr uint8_t LcdBacklightLow = 14;
+ static constexpr uint8_t LcdBacklightMedium = 22;
+ static constexpr uint8_t LcdBacklightHigh = 23;
+
+ static constexpr uint8_t SpiSck = 2;
+ static constexpr uint8_t SpiMosi = 3;
+ static constexpr uint8_t SpiMiso = 4;
+
+ static constexpr uint8_t SpiFlashCsn = 5;
+ static constexpr uint8_t SpiLcdCsn = 25;
+ static constexpr uint8_t LcdDataCommand = 18;
+
+ static constexpr uint8_t TwiScl = 7;
+ static constexpr uint8_t TwiSda = 6;
+ }
+}
diff --git a/src/main.cpp b/src/main.cpp
index 79e2ad86..e14d03a2 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -43,7 +43,9 @@
#include "drivers/St7789.h"
#include "drivers/TwiMaster.h"
#include "drivers/Cst816s.h"
+#include "drivers/PinMap.h"
#include "systemtask/SystemTask.h"
+#include "drivers/PinMap.h"
#include "touchhandler/TouchHandler.h"
#if NRF_LOG_ENABLED
@@ -54,14 +56,6 @@ Pinetime::Logging::NrfLogger logger;
Pinetime::Logging::DummyLogger logger;
#endif
-static constexpr uint8_t pinSpiSck = 2;
-static constexpr uint8_t pinSpiMosi = 3;
-static constexpr uint8_t pinSpiMiso = 4;
-static constexpr uint8_t pinSpiFlashCsn = 5;
-static constexpr uint8_t pinLcdCsn = 25;
-static constexpr uint8_t pinLcdDataCommand = 18;
-static constexpr uint8_t pinTwiScl = 7;
-static constexpr uint8_t pinTwiSda = 6;
static constexpr uint8_t touchPanelTwiAddress = 0x15;
static constexpr uint8_t motionSensorTwiAddress = 0x18;
static constexpr uint8_t heartRateSensorTwiAddress = 0x44;
@@ -70,33 +64,30 @@ Pinetime::Drivers::SpiMaster spi {Pinetime::Drivers::SpiMaster::SpiModule::SPI0,
{Pinetime::Drivers::SpiMaster::BitOrder::Msb_Lsb,
Pinetime::Drivers::SpiMaster::Modes::Mode3,
Pinetime::Drivers::SpiMaster::Frequencies::Freq8Mhz,
- pinSpiSck,
- pinSpiMosi,
- pinSpiMiso}};
+ Pinetime::PinMap::SpiSck,
+ Pinetime::PinMap::SpiMosi,
+ Pinetime::PinMap::SpiMiso}};
-Pinetime::Drivers::Spi lcdSpi {spi, pinLcdCsn};
-Pinetime::Drivers::St7789 lcd {lcdSpi, pinLcdDataCommand};
+Pinetime::Drivers::Spi lcdSpi {spi, Pinetime::PinMap::SpiLcdCsn};
+Pinetime::Drivers::St7789 lcd {lcdSpi, Pinetime::PinMap::LcdDataCommand};
-Pinetime::Drivers::Spi flashSpi {spi, pinSpiFlashCsn};
+Pinetime::Drivers::Spi flashSpi {spi, Pinetime::PinMap::SpiFlashCsn};
Pinetime::Drivers::SpiNorFlash spiNorFlash {flashSpi};
// The TWI device should work @ up to 400Khz but there is a HW bug which prevent it from
// respecting correct timings. According to erratas heet, this magic value makes it run
// at ~390Khz with correct timings.
static constexpr uint32_t MaxTwiFrequencyWithoutHardwareBug {0x06200000};
-Pinetime::Drivers::TwiMaster twiMaster {NRF_TWIM1, MaxTwiFrequencyWithoutHardwareBug, pinTwiSda, pinTwiScl};
+Pinetime::Drivers::TwiMaster twiMaster {NRF_TWIM1, MaxTwiFrequencyWithoutHardwareBug, Pinetime::PinMap::TwiSda, Pinetime::PinMap::TwiScl};
Pinetime::Drivers::Cst816S touchPanel {twiMaster, touchPanelTwiAddress};
#ifdef PINETIME_IS_RECOVERY
-static constexpr bool isFactory = true;
#include "displayapp/DummyLittleVgl.h"
#include "displayapp/DisplayAppRecovery.h"
-Pinetime::Components::LittleVgl lvgl {lcd, touchPanel};
#else
-static constexpr bool isFactory = false;
#include "displayapp/LittleVgl.h"
#include "displayapp/DisplayApp.h"
-Pinetime::Components::LittleVgl lvgl {lcd, touchPanel};
#endif
+Pinetime::Components::LittleVgl lvgl {lcd, touchPanel};
Pinetime::Drivers::Bma421 motionSensor {twiMaster, motionSensorTwiAddress};
Pinetime::Drivers::Hrs3300 heartRateSensor {twiMaster, heartRateSensorTwiAddress};
@@ -105,10 +96,8 @@ TimerHandle_t debounceTimer;
TimerHandle_t debounceChargeTimer;
Pinetime::Controllers::Battery batteryController;
Pinetime::Controllers::Ble bleController;
-void ble_manager_set_ble_connection_callback(void (*connection)());
-void ble_manager_set_ble_disconnection_callback(void (*disconnection)());
-static constexpr uint8_t pinTouchIrq = 28;
-static constexpr uint8_t pinPowerPresentIrq = 19;
+static constexpr uint8_t pinTouchIrq = Pinetime::PinMap::Cst816sIrq;
+static constexpr uint8_t pinPowerPresentIrq = Pinetime::PinMap::PowerPresent;
Pinetime::Controllers::HeartRateController heartRateController;
Pinetime::Applications::HeartRateTask heartRateApp(heartRateSensor, heartRateController);
@@ -119,13 +108,13 @@ Pinetime::Drivers::WatchdogView watchdogView(watchdog);
Pinetime::Controllers::NotificationManager notificationManager;
Pinetime::Controllers::MotionController motionController;
Pinetime::Controllers::TimerController timerController;
+Pinetime::Controllers::AlarmController alarmController {dateTimeController};
Pinetime::Controllers::TouchHandler touchHandler(touchPanel, lvgl);
Pinetime::Controllers::FS fs {spiNorFlash};
Pinetime::Controllers::Settings settingsController {fs};
Pinetime::Controllers::MotorController motorController {settingsController};
-
Pinetime::Applications::DisplayApp displayApp(lcd,
lvgl,
touchPanel,
@@ -139,6 +128,7 @@ Pinetime::Applications::DisplayApp displayApp(lcd,
motorController,
motionController,
timerController,
+ alarmController,
touchHandler);
Pinetime::System::SystemTask systemTask(spi,
@@ -151,6 +141,7 @@ Pinetime::System::SystemTask systemTask(spi,
bleController,
dateTimeController,
timerController,
+ alarmController,
watchdog,
notificationManager,
motorController,
@@ -164,15 +155,25 @@ Pinetime::System::SystemTask systemTask(spi,
fs,
touchHandler);
+/* Variable Declarations for variables in noinit SRAM
+ Increment NoInit_MagicValue upon adding variables to this area
+*/
+extern uint32_t __start_noinit_data;
+extern uint32_t __stop_noinit_data;
+static constexpr uint32_t NoInit_MagicValue = 0xDEAD0000;
+uint32_t NoInit_MagicWord __attribute__((section(".noinit")));
+std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> NoInit_BackUpTime __attribute__((section(".noinit")));
+
+
void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) {
- if (pin == pinTouchIrq) {
+ if (pin == Pinetime::PinMap::Cst816sIrq) {
systemTask.OnTouchEvent();
return;
}
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
- if (pin == pinPowerPresentIrq and action == NRF_GPIOTE_POLARITY_TOGGLE) {
+ if (pin == Pinetime::PinMap::PowerPresent and action == NRF_GPIOTE_POLARITY_TOGGLE) {
xTimerStartFromISR(debounceChargeTimer, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
return;
@@ -305,18 +306,18 @@ int main(void) {
nrf_drv_clock_init();
// Unblock i2c?
- nrf_gpio_cfg(pinTwiScl,
+ nrf_gpio_cfg(Pinetime::PinMap::TwiScl,
NRF_GPIO_PIN_DIR_OUTPUT,
NRF_GPIO_PIN_INPUT_DISCONNECT,
NRF_GPIO_PIN_NOPULL,
NRF_GPIO_PIN_S0D1,
NRF_GPIO_PIN_NOSENSE);
- nrf_gpio_pin_set(pinTwiScl);
+ nrf_gpio_pin_set(Pinetime::PinMap::TwiScl);
for (uint8_t i = 0; i < 16; i++) {
- nrf_gpio_pin_toggle(pinTwiScl);
+ nrf_gpio_pin_toggle(Pinetime::PinMap::TwiScl);
nrf_delay_us(5);
}
- nrf_gpio_cfg_default(pinTwiScl);
+ nrf_gpio_cfg_default(Pinetime::PinMap::TwiScl);
debounceTimer = xTimerCreate("debounceTimer", 200, pdFALSE, (void*) 0, DebounceTimerCallback);
debounceChargeTimer = xTimerCreate("debounceTimerCharge", 200, pdFALSE, (void*) 0, DebounceTimerChargeCallback);
@@ -324,6 +325,15 @@ int main(void) {
// retrieve version stored by bootloader
Pinetime::BootloaderVersion::SetVersion(NRF_TIMER2->CC[0]);
+
+ if (NoInit_MagicWord == NoInit_MagicValue) {
+ dateTimeController.SetCurrentTime(NoInit_BackUpTime);
+ } else {
+ //Clear Memory to known state
+ memset(&__start_noinit_data,0,(uintptr_t)&__stop_noinit_data-(uintptr_t)&__start_noinit_data);
+ NoInit_MagicWord = NoInit_MagicValue;
+ }
+
lvgl.Init();
systemTask.Start();
diff --git a/src/recoveryLoader.cpp b/src/recoveryLoader.cpp
index 9818179d..acec14c8 100644
--- a/src/recoveryLoader.cpp
+++ b/src/recoveryLoader.cpp
@@ -15,6 +15,7 @@
#include <components/brightness/BrightnessController.h>
#include <algorithm>
#include "recoveryImage.h"
+#include "drivers/PinMap.h"
#include "displayapp/icons/infinitime/infinitime-nb.c"
#include "components/rle/RleDecoder.h"
@@ -27,12 +28,6 @@ Pinetime::Logging::NrfLogger logger;
Pinetime::Logging::DummyLogger logger;
#endif
-static constexpr uint8_t pinSpiSck = 2;
-static constexpr uint8_t pinSpiMosi = 3;
-static constexpr uint8_t pinSpiMiso = 4;
-static constexpr uint8_t pinSpiFlashCsn = 5;
-static constexpr uint8_t pinLcdCsn = 25;
-static constexpr uint8_t pinLcdDataCommand = 18;
static constexpr uint8_t displayWidth = 240;
static constexpr uint8_t displayHeight = 240;
@@ -45,14 +40,14 @@ Pinetime::Drivers::SpiMaster spi {Pinetime::Drivers::SpiMaster::SpiModule::SPI0,
{Pinetime::Drivers::SpiMaster::BitOrder::Msb_Lsb,
Pinetime::Drivers::SpiMaster::Modes::Mode3,
Pinetime::Drivers::SpiMaster::Frequencies::Freq8Mhz,
- pinSpiSck,
- pinSpiMosi,
- pinSpiMiso}};
-Pinetime::Drivers::Spi flashSpi {spi, pinSpiFlashCsn};
+ Pinetime::PinMap::SpiSck,
+ Pinetime::PinMap::SpiMosi,
+ Pinetime::PinMap::SpiMiso}};
+Pinetime::Drivers::Spi flashSpi {spi, Pinetime::PinMap::SpiFlashCsn};
Pinetime::Drivers::SpiNorFlash spiNorFlash {flashSpi};
-Pinetime::Drivers::Spi lcdSpi {spi, pinLcdCsn};
-Pinetime::Drivers::St7789 lcd {lcdSpi, pinLcdDataCommand};
+Pinetime::Drivers::Spi lcdSpi {spi, Pinetime::PinMap::SpiLcdCsn};
+Pinetime::Drivers::St7789 lcd {lcdSpi, Pinetime::PinMap::LcdDataCommand};
Pinetime::Components::Gfx gfx {lcd};
Pinetime::Controllers::BrightnessController brightnessController;
diff --git a/src/systemtask/Messages.h b/src/systemtask/Messages.h
index 3a195e2d..bd1de234 100644
--- a/src/systemtask/Messages.h
+++ b/src/systemtask/Messages.h
@@ -20,7 +20,11 @@ namespace Pinetime {
EnableSleeping,
DisableSleeping,
OnNewDay,
- OnChargingEvent
+ OnChargingEvent,
+ SetOffAlarm,
+ StopRinging,
+ MeasureBatteryTimerExpired,
+ BatteryMeasurementDone,
};
}
}
diff --git a/src/systemtask/SystemTask.cpp b/src/systemtask/SystemTask.cpp
index 0617b0ce..529d2863 100644
--- a/src/systemtask/SystemTask.cpp
+++ b/src/systemtask/SystemTask.cpp
@@ -21,8 +21,10 @@
#include "drivers/SpiNorFlash.h"
#include "drivers/TwiMaster.h"
#include "drivers/Hrs3300.h"
+#include "drivers/PinMap.h"
#include "main.h"
+
#include <memory>
using namespace Pinetime::System;
@@ -47,6 +49,11 @@ void IdleTimerCallback(TimerHandle_t xTimer) {
sysTask->OnIdle();
}
+void MeasureBatteryTimerCallback(TimerHandle_t xTimer) {
+ auto* sysTask = static_cast<SystemTask*>(pvTimerGetTimerID(xTimer));
+ sysTask->PushMessage(Pinetime::System::Messages::MeasureBatteryTimerExpired);
+}
+
SystemTask::SystemTask(Drivers::SpiMaster& spi,
Drivers::St7789& lcd,
Pinetime::Drivers::SpiNorFlash& spiNorFlash,
@@ -57,6 +64,7 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
Controllers::Ble& bleController,
Controllers::DateTime& dateTimeController,
Controllers::TimerController& timerController,
+ Controllers::AlarmController& alarmController,
Drivers::Watchdog& watchdog,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::MotorController& motorController,
@@ -79,6 +87,7 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi,
bleController {bleController},
dateTimeController {dateTimeController},
timerController {timerController},
+ alarmController {alarmController},
watchdog {watchdog},
notificationManager {notificationManager},
motorController {motorController},
@@ -121,17 +130,18 @@ void SystemTask::Work() {
fs.Init();
nimbleController.Init();
- nimbleController.StartAdvertising();
lcd.Init();
twiMaster.Init();
touchPanel.Init();
dateTimeController.Register(this);
- batteryController.Init();
+ batteryController.Register(this);
+ batteryController.Update();
motorController.Init();
motionSensor.SoftReset();
timerController.Register(this);
timerController.Init();
+ alarmController.Init(this);
// Reset the TWI device because the motion sensor chip most probably crashed it...
twiMaster.Sleep();
@@ -144,13 +154,11 @@ void SystemTask::Work() {
displayApp.Register(this);
displayApp.Start();
- displayApp.PushMessage(Pinetime::Applications::Display::Messages::UpdateBatteryLevel);
-
heartRateSensor.Init();
heartRateSensor.Disable();
heartRateApp.Start();
- nrf_gpio_cfg_sense_input(pinButton, (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pulldown, (nrf_gpio_pin_sense_t) GPIO_PIN_CNF_SENSE_High);
+ nrf_gpio_cfg_sense_input(PinMap::Button, (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pulldown, (nrf_gpio_pin_sense_t) GPIO_PIN_CNF_SENSE_High);
nrf_gpio_cfg_output(15);
nrf_gpio_pin_set(15);
@@ -161,9 +169,9 @@ void SystemTask::Work() {
pinConfig.sense = (nrf_gpiote_polarity_t) NRF_GPIOTE_POLARITY_HITOLO;
pinConfig.pull = (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pulldown;
- nrfx_gpiote_in_init(pinButton, &pinConfig, nrfx_gpiote_evt_handler);
+ nrfx_gpiote_in_init(PinMap::Button, &pinConfig, nrfx_gpiote_evt_handler);
- nrf_gpio_cfg_sense_input(pinTouchIrq, (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pullup, (nrf_gpio_pin_sense_t) GPIO_PIN_CNF_SENSE_Low);
+ nrf_gpio_cfg_sense_input(PinMap::Cst816sIrq, (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pullup, (nrf_gpio_pin_sense_t) GPIO_PIN_CNF_SENSE_Low);
pinConfig.skip_gpio_setup = true;
pinConfig.hi_accuracy = false;
@@ -171,24 +179,26 @@ void SystemTask::Work() {
pinConfig.sense = (nrf_gpiote_polarity_t) NRF_GPIOTE_POLARITY_HITOLO;
pinConfig.pull = (nrf_gpio_pin_pull_t) GPIO_PIN_CNF_PULL_Pullup;
- nrfx_gpiote_in_init(pinTouchIrq, &pinConfig, nrfx_gpiote_evt_handler);
+ nrfx_gpiote_in_init(PinMap::Cst816sIrq, &pinConfig, nrfx_gpiote_evt_handler);
pinConfig.sense = NRF_GPIOTE_POLARITY_TOGGLE;
pinConfig.pull = NRF_GPIO_PIN_NOPULL;
pinConfig.is_watcher = false;
pinConfig.hi_accuracy = false;
pinConfig.skip_gpio_setup = true;
- nrfx_gpiote_in_init(pinPowerPresentIrq, &pinConfig, nrfx_gpiote_evt_handler);
+ nrfx_gpiote_in_init(PinMap::PowerPresent, &pinConfig, nrfx_gpiote_evt_handler);
- if (nrf_gpio_pin_read(pinPowerPresentIrq)) {
- nrf_gpio_cfg_sense_input(pinPowerPresentIrq, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);
+ if (nrf_gpio_pin_read(PinMap::PowerPresent)) {
+ nrf_gpio_cfg_sense_input(PinMap::PowerPresent, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);
} else {
- nrf_gpio_cfg_sense_input(pinPowerPresentIrq, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH);
+ nrf_gpio_cfg_sense_input(PinMap::PowerPresent, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_HIGH);
}
idleTimer = xTimerCreate("idleTimer", pdMS_TO_TICKS(2000), pdFALSE, this, IdleTimerCallback);
dimTimer = xTimerCreate("dimTimer", pdMS_TO_TICKS(settingsController.GetScreenTimeOut() - 2000), pdFALSE, this, DimTimerCallback);
+ measureBatteryTimer = xTimerCreate("measureBattery", batteryMeasurementPeriod, pdTRUE, this, MeasureBatteryTimerCallback);
xTimerStart(dimTimer, 0);
+ xTimerStart(measureBatteryTimer, portMAX_DELAY);
// Suppress endless loop diagnostic
#pragma clang diagnostic push
@@ -198,11 +208,6 @@ void SystemTask::Work() {
uint8_t msg;
if (xQueueReceive(systemTasksMsgQueue, &msg, 100)) {
-
- batteryController.Update();
- // the battery does not emit events when changing charge levels, so we piggyback
- // on any system event to read and update the current values
-
Messages message = static_cast<Messages>(msg);
switch (message) {
case Messages::EnableSleeping:
@@ -226,15 +231,16 @@ void SystemTask::Work() {
touchPanel.Wakeup();
}
- nimbleController.StartAdvertising();
xTimerStart(dimTimer, 0);
spiNorFlash.Wakeup();
lcd.Wakeup();
displayApp.PushMessage(Pinetime::Applications::Display::Messages::GoToRunning);
- displayApp.PushMessage(Pinetime::Applications::Display::Messages::UpdateBatteryLevel);
heartRateApp.PushMessage(Pinetime::Applications::HeartRateTask::Messages::WakeUp);
+ if (!bleController.IsConnected())
+ nimbleController.RestartFastAdv();
+
isSleeping = false;
isWakingUp = false;
isDimmed = false;
@@ -275,6 +281,16 @@ void SystemTask::Work() {
motorController.RunForDuration(35);
displayApp.PushMessage(Pinetime::Applications::Display::Messages::TimerDone);
break;
+ case Messages::SetOffAlarm:
+ if (isSleeping && !isWakingUp) {
+ GoToRunning();
+ }
+ motorController.StartRinging();
+ displayApp.PushMessage(Pinetime::Applications::Display::Messages::AlarmTriggered);
+ break;
+ case Messages::StopRinging:
+ motorController.StopRinging();
+ break;
case Messages::BleConnected:
ReloadIdleTimer();
isBleDiscoveryTimerRunning = true;
@@ -327,8 +343,18 @@ void SystemTask::Work() {
stepCounterMustBeReset = true;
break;
case Messages::OnChargingEvent:
+ batteryController.Update();
motorController.RunForDuration(15);
- // Battery level is updated on every message - there's no need to do anything
+ break;
+ case Messages::MeasureBatteryTimerExpired:
+ sendBatteryNotification = true;
+ batteryController.Update();
+ break;
+ case Messages::BatteryMeasurementDone:
+ if (sendBatteryNotification) {
+ sendBatteryNotification = false;
+ nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining());
+ }
break;
default:
@@ -340,22 +366,18 @@ void SystemTask::Work() {
if (bleDiscoveryTimer == 0) {
isBleDiscoveryTimerRunning = false;
// Services discovery is deffered from 3 seconds to avoid the conflicts between the host communicating with the
- // tharget and vice-versa. I'm not sure if this is the right way to handle this...
+ // target and vice-versa. I'm not sure if this is the right way to handle this...
nimbleController.StartDiscovery();
} else {
bleDiscoveryTimer--;
}
}
- if (xTaskGetTickCount() - batteryNotificationTick > batteryNotificationPeriod) {
- nimbleController.NotifyBatteryLevel(batteryController.PercentRemaining());
- batteryNotificationTick = xTaskGetTickCount();
- }
-
monitor.Process();
uint32_t systick_counter = nrf_rtc_counter_get(portNRF_RTC_REG);
dateTimeController.UpdateTime(systick_counter);
- if (!nrf_gpio_pin_read(pinButton))
+ NoInit_BackUpTime = dateTimeController.CurrentDateTime();
+ if (!nrf_gpio_pin_read(PinMap::Button))
watchdog.Kick();
}
// Clear diagnostic suppression
diff --git a/src/systemtask/SystemTask.h b/src/systemtask/SystemTask.h
index 0266ba8a..1fcfeb8a 100644
--- a/src/systemtask/SystemTask.h
+++ b/src/systemtask/SystemTask.h
@@ -8,6 +8,7 @@
#include <heartratetask/HeartRateTask.h>
#include <components/settings/Settings.h>
#include <drivers/Bma421.h>
+#include <drivers/PinMap.h>
#include <components/motion/MotionController.h>
#include "SystemMonitor.h"
@@ -16,6 +17,7 @@
#include "components/ble/NotificationManager.h"
#include "components/motor/MotorController.h"
#include "components/timer/TimerController.h"
+#include "components/alarm/AlarmController.h"
#include "components/fs/FS.h"
#include "touchhandler/TouchHandler.h"
@@ -31,6 +33,7 @@
#include "drivers/Watchdog.h"
#include "Messages.h"
+extern std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> NoInit_BackUpTime;
namespace Pinetime {
namespace Drivers {
class Cst816S;
@@ -56,6 +59,7 @@ namespace Pinetime {
Controllers::Ble& bleController,
Controllers::DateTime& dateTimeController,
Controllers::TimerController& timerController,
+ Controllers::AlarmController& alarmController,
Drivers::Watchdog& watchdog,
Pinetime::Controllers::NotificationManager& notificationManager,
Pinetime::Controllers::MotorController& motorController,
@@ -100,6 +104,7 @@ namespace Pinetime {
Pinetime::Controllers::Ble& bleController;
Pinetime::Controllers::DateTime& dateTimeController;
Pinetime::Controllers::TimerController& timerController;
+ Pinetime::Controllers::AlarmController& alarmController;
QueueHandle_t systemTasksMsgQueue;
std::atomic<bool> isSleeping {false};
std::atomic<bool> isGoingToSleep {false};
@@ -120,15 +125,6 @@ namespace Pinetime {
Pinetime::Controllers::TouchHandler& touchHandler;
Pinetime::Controllers::NimbleController nimbleController;
- static constexpr uint8_t pinSpiSck = 2;
- static constexpr uint8_t pinSpiMosi = 3;
- static constexpr uint8_t pinSpiMiso = 4;
- static constexpr uint8_t pinSpiCsn = 25;
- static constexpr uint8_t pinLcdDataCommand = 18;
- static constexpr uint8_t pinButton = 13;
- static constexpr uint8_t pinTouchIrq = 28;
- static constexpr uint8_t pinPowerPresentIrq = 19;
-
static void Process(void* instance);
void Work();
void ReloadIdleTimer();
@@ -136,13 +132,15 @@ namespace Pinetime {
uint8_t bleDiscoveryTimer = 0;
TimerHandle_t dimTimer;
TimerHandle_t idleTimer;
+ TimerHandle_t measureBatteryTimer;
+ bool sendBatteryNotification = false;
bool doNotGoToSleep = false;
void GoToRunning();
void UpdateMotion();
bool stepCounterMustBeReset = false;
- static constexpr TickType_t batteryNotificationPeriod = 1000 * 60 * 10; // 1 tick ~= 1ms. 1ms * 60 * 10 = 10 minutes
- TickType_t batteryNotificationTick = 0;
+ static constexpr TickType_t batteryMeasurementPeriod = pdMS_TO_TICKS(10 * 60 * 1000);
+ TickType_t lastBatteryNotificationTime = 0;
#if configUSE_TRACE_FACILITY == 1
SystemMonitor<FreeRtosMonitor> monitor;