diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b02675df0..7ead035fee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,3 +12,7 @@ So we only actually use two levels of version numbers for PineTimeSD and ignore - Starts heart rate sensor automatically on start-up - V230.0.3 - Changed device name back to InfiniTime so that GadgetBridge detects it to update firmware + V230.0.4 + - Added OSD alarm Status to watch face + V230.0.5 + - Added fault detection to OSD alarm status. diff --git a/CMakeLists.txt b/CMakeLists.txt index e7e308a15f..3fc9ef0ca5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.10) set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose Debug or Release") -project(pinetime VERSION 230.0.3 LANGUAGES C CXX ASM) +project(pinetime VERSION 230.0.5 LANGUAGES C CXX ASM) set(CMAKE_C_STANDARD 99) set(CMAKE_CXX_STANDARD 20) diff --git a/src/components/ble/MotionService.cpp b/src/components/ble/MotionService.cpp index 70e22e5078..b24a08d016 100644 --- a/src/components/ble/MotionService.cpp +++ b/src/components/ble/MotionService.cpp @@ -20,11 +20,13 @@ namespace { constexpr ble_uuid128_t motionServiceUuid {BaseUuid()}; constexpr ble_uuid128_t stepCountCharUuid {CharUuid(0x01, 0x00)}; constexpr ble_uuid128_t motionValuesCharUuid {CharUuid(0x02, 0x00)}; + constexpr ble_uuid128_t osdStatusCharUuid {CharUuid(0x78, 0x00)}; // 0x78 is 120 for OSD int MotionServiceCallback(uint16_t /*conn_handle*/, uint16_t attr_handle, struct ble_gatt_access_ctxt* ctxt, void* arg) { auto* motionService = static_cast(arg); return motionService->OnStepCountRequested(attr_handle, ctxt); } + } // TODO Refactoring - remove dependency to SystemTask @@ -41,6 +43,12 @@ MotionService::MotionService(NimbleController& nimble, Controllers::MotionContro .arg = this, .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_NOTIFY, .val_handle = &motionValuesHandle}, + {.uuid = &osdStatusCharUuid.u, + .access_cb = MotionServiceCallback, + .arg = this, + .flags = BLE_GATT_CHR_F_READ | BLE_GATT_CHR_F_WRITE, + .val_handle = &osdStatusHandle}, + {0}}, serviceDefinition { {.type = BLE_GATT_SVC_TYPE_PRIMARY, .uuid = &motionServiceUuid.u, .characteristics = characteristicDefinition}, @@ -76,6 +84,12 @@ int MotionService::OnStepCountRequested(uint16_t attributeHandle, ble_gatt_acces res = os_mbuf_append(context->om, this->data, 3 * 3 * sizeof(int16_t)); } return (res == 0) ? 0 : BLE_ATT_ERR_INSUFFICIENT_RES; + } else if (attributeHandle == osdStatusHandle) { + int8_t statusVal = -1; + res = os_mbuf_copydata(context->om, 0, 1, &statusVal); + motionController.osdStatus = statusVal; + motionController.osdStatusTime = xTaskGetTickCount(); + return res; } return 0; } diff --git a/src/components/ble/MotionService.h b/src/components/ble/MotionService.h index 5f4f5192f1..aae4f7f716 100644 --- a/src/components/ble/MotionService.h +++ b/src/components/ble/MotionService.h @@ -30,13 +30,14 @@ namespace Pinetime { NimbleController& nimble; Controllers::MotionController& motionController; - struct ble_gatt_chr_def characteristicDefinition[3]; + struct ble_gatt_chr_def characteristicDefinition[4]; struct ble_gatt_svc_def serviceDefinition[2]; int16_t *data; int16_t nData; uint16_t stepCountHandle; uint16_t motionValuesHandle; + uint16_t osdStatusHandle; std::atomic_bool stepCountNoficationEnabled {false}; std::atomic_bool motionValuesNoficationEnabled {false}; diff --git a/src/components/motion/MotionController.cpp b/src/components/motion/MotionController.cpp index 39c8e08794..f4e3d85335 100644 --- a/src/components/motion/MotionController.cpp +++ b/src/components/motion/MotionController.cpp @@ -68,6 +68,15 @@ void MotionController::Update(int16_t *fifo, uint16_t nFifo, uint32_t nbSteps) currentTripSteps += deltaSteps; } this->nbSteps = nbSteps; + +} + +void MotionController::CheckOsdTimeout() { + // If the OSD status has not been updated by the phone within 30 seconds, + // show a fault condition. This is called from WatchFaceOsd every update. + if ((xTaskGetTickCount() - osdStatusTime) > FAULT_TIMEOUT_TICKS) { + osdStatus = ALARM_STATE_NETFAULT; + } } MotionController::AccelStats MotionController::GetAccelStats() const { @@ -148,6 +157,8 @@ void MotionController::Init(Pinetime::Drivers::Bma421::DeviceTypes types) { this->deviceType = DeviceTypes::Unknown; break; } + osdStatus = 0x81; + osdStatusTime = xTaskGetTickCount(); } void MotionController::SetService(Pinetime::Controllers::MotionService* service) { diff --git a/src/components/motion/MotionController.h b/src/components/motion/MotionController.h index 1a3073fe60..99fa4f6a97 100644 --- a/src/components/motion/MotionController.h +++ b/src/components/motion/MotionController.h @@ -60,10 +60,12 @@ namespace Pinetime { void SetService(Pinetime::Controllers::MotionService* service); - Pinetime::Controllers::MotionService* GetService() const; + int8_t osdStatus; + uint32_t osdStatusTime; + void CheckOsdTimeout(); private: uint32_t nbSteps = 0; @@ -94,6 +96,8 @@ namespace Pinetime { Utility::CircularBuffer yHistory = {}; Utility::CircularBuffer zHistory = {}; int32_t accumulatedSpeed = 0; + static constexpr uint32_t FAULT_TIMEOUT_TICKS = 30000; + static constexpr uint8_t ALARM_STATE_NETFAULT = 7; DeviceTypes deviceType = DeviceTypes::Unknown; Pinetime::Controllers::MotionService* service = nullptr; diff --git a/src/displayapp/screens/WatchFaceOsd.cpp b/src/displayapp/screens/WatchFaceOsd.cpp index 8cea0b4e98..fe60b6ff25 100644 --- a/src/displayapp/screens/WatchFaceOsd.cpp +++ b/src/displayapp/screens/WatchFaceOsd.cpp @@ -74,6 +74,14 @@ WatchFaceOsd::WatchFaceOsd(Controllers::DateTime& dateTimeController, lv_label_set_text_static(stepIcon, Symbols::shoe); lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0); + label_osdStatus = lv_label_create(lv_scr_act(), nullptr); + lv_obj_set_style_local_text_color(label_osdStatus, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT, lv_color_hex(0x999999)); + //lv_obj_align(label_title, lv_scr_act(), LV_ALIGN_CENTER, 0, -50); + lv_obj_set_pos(label_osdStatus,5,50); + lv_label_set_text_static(label_osdStatus,"OsdStatus"); + + + taskRefresh = lv_task_create(RefreshTaskCallback, LV_DISP_DEF_REFR_PERIOD, LV_TASK_PRIO_MID, this); Refresh(); } @@ -159,4 +167,21 @@ void WatchFaceOsd::Refresh() { lv_obj_realign(stepValue); lv_obj_realign(stepIcon); } + + motionController.CheckOsdTimeout(); + lv_label_set_text_fmt(label_osdStatus,"%3d: %s", + (xTaskGetTickCount() - motionController.osdStatusTime)/1024, + //motionController.osdStatus, + status2Str(motionController.osdStatus)); + } + +const char* WatchFaceOsd::status2Str(int8_t osdStatus) { + if (osdStatus >= NSTATUSSTRS) + osdStatus = -1; + if (osdStatus < -1) + osdStatus = -1; + + return(statusStrs[osdStatus+1]); +} + diff --git a/src/displayapp/screens/WatchFaceOsd.h b/src/displayapp/screens/WatchFaceOsd.h index 23b5f84be6..ed8845bcfa 100644 --- a/src/displayapp/screens/WatchFaceOsd.h +++ b/src/displayapp/screens/WatchFaceOsd.h @@ -62,6 +62,7 @@ namespace Pinetime { lv_obj_t* stepValue; lv_obj_t* notificationIcon; lv_obj_t* label_title; + lv_obj_t* label_osdStatus; Controllers::DateTime& dateTimeController; Controllers::NotificationManager& notificationManager; @@ -71,6 +72,15 @@ namespace Pinetime { lv_task_t* taskRefresh; Widgets::StatusIcons statusIcons; + + // Strings to convert osdStatus value to text. Add 1 onto status value to map + // correctly onto statusStrs[]; (-1=undefined, 0=ok etc); + // FIXME - we should really have an OsdController and OsdService to do this, + // but there is a lot less code to piggy back on MotionController. + #define NSTATUSSTRS 9 + const char *statusStrs[NSTATUSSTRS] = { "NOT STARTED", "0-OK", "1-WARNING", "2-**ALARM**", "3-FALL", "4-FAULT", "5-", "6-","7-ERR:COMMS"}; + + const char* status2Str(int8_t osdStatus); }; }