Merge branch 'motion-sensor' into develop
This commit is contained in:
		
						commit
						eb769fb60e
					
				| @ -1,5 +1,5 @@ | ||||
| cmake_minimum_required(VERSION 3.10) | ||||
| project(pinetime VERSION 0.15.0 LANGUAGES C CXX ASM) | ||||
| project(pinetime VERSION 0.16.0 LANGUAGES C CXX ASM) | ||||
| 
 | ||||
| set(CMAKE_C_STANDARD 99) | ||||
| set(CMAKE_CXX_STANDARD 14) | ||||
|  | ||||
| @ -34,6 +34,9 @@ As of now, here is the list of achievements of this project: | ||||
|  - Rich user interface via display, touchscreen and pushbutton | ||||
|  - Time synchronization via BLE | ||||
|  - Notification via BLE | ||||
|  - Heart rate measurements | ||||
|  - Step counting | ||||
|  - Wake-up on wrist rotation | ||||
|  - Multiple 'apps' :  | ||||
|     * Clock (displays the date, time, battery level, ble connection status, heart rate) | ||||
|     * System info (displays various info : BLE MAC, build date/time, uptime, version,...) | ||||
|  | ||||
| @ -83,7 +83,7 @@ set(SDK_SOURCE_FILES | ||||
|         "${NRF5_SDK_PATH}/external/fprintf/nrf_fprintf_format.c" | ||||
| 
 | ||||
|         # TWI | ||||
|         "${NRF5_SDK_PATH}/modules/nrfx/drivers/src/nrfx_twi.c" | ||||
|         "${NRF5_SDK_PATH}/modules/nrfx/drivers/src/nrfx_twim.c" | ||||
| 
 | ||||
|         # GPIOTE | ||||
|         "${NRF5_SDK_PATH}/components/libraries/gpiote/app_gpiote.c" | ||||
| @ -396,11 +396,13 @@ list(APPEND SOURCE_FILES | ||||
|         displayapp/screens/FirmwareUpdate.cpp | ||||
|         displayapp/screens/Music.cpp | ||||
|         displayapp/screens/Navigation.cpp | ||||
|         displayapp/screens/Motion.cpp | ||||
|         displayapp/screens/FirmwareValidation.cpp | ||||
|         displayapp/screens/ApplicationList.cpp | ||||
|         displayapp/screens/Notifications.cpp | ||||
|         displayapp/screens/Twos.cpp | ||||
|         displayapp/screens/HeartRate.cpp | ||||
|         displayapp/screens/Motion.cpp | ||||
|         displayapp/screens/FlashLight.cpp | ||||
|         displayapp/screens/List.cpp | ||||
|         displayapp/screens/BatteryInfo.cpp | ||||
| @ -429,11 +431,15 @@ list(APPEND SOURCE_FILES | ||||
|         drivers/DebugPins.cpp | ||||
|         drivers/InternalFlash.cpp | ||||
|         drivers/Hrs3300.cpp | ||||
|         drivers/Bma421.cpp | ||||
|         drivers/Bma421_C/bma4.c | ||||
|         drivers/Bma421_C/bma423.c | ||||
|         components/battery/BatteryController.cpp | ||||
|         components/ble/BleController.cpp | ||||
|         components/ble/NotificationManager.cpp | ||||
|         components/datetime/DateTimeController.cpp | ||||
|         components/brightness/BrightnessController.cpp | ||||
|         components/motion/MotionController.cpp | ||||
|         components/ble/NimbleController.cpp | ||||
|         components/ble/DeviceInformationService.cpp | ||||
|         components/ble/CurrentTimeClient.cpp | ||||
| @ -487,11 +493,15 @@ list(APPEND RECOVERY_SOURCE_FILES | ||||
|         drivers/DebugPins.cpp | ||||
|         drivers/InternalFlash.cpp | ||||
|         drivers/Hrs3300.cpp | ||||
|         drivers/Bma421.cpp | ||||
|         drivers/Bma421_C/bma4.c | ||||
|         drivers/Bma421_C/bma423.c | ||||
|         components/battery/BatteryController.cpp | ||||
|         components/ble/BleController.cpp | ||||
|         components/ble/NotificationManager.cpp | ||||
|         components/datetime/DateTimeController.cpp | ||||
|         components/brightness/BrightnessController.cpp | ||||
|         components/motion/MotionController.cpp | ||||
|         components/ble/NimbleController.cpp | ||||
|         components/ble/DeviceInformationService.cpp | ||||
|         components/ble/CurrentTimeClient.cpp | ||||
| @ -576,6 +586,7 @@ set(INCLUDE_FILES | ||||
|         displayapp/Apps.h | ||||
|         displayapp/screens/Notifications.h | ||||
|         displayapp/screens/HeartRate.h | ||||
|         displayapp/screens/Motion.h | ||||
|         drivers/St7789.h | ||||
|         drivers/SpiNorFlash.h | ||||
|         drivers/SpiMaster.h | ||||
| @ -584,11 +595,15 @@ set(INCLUDE_FILES | ||||
|         drivers/DebugPins.h | ||||
|         drivers/InternalFlash.h | ||||
|         drivers/Hrs3300.h | ||||
|         drivers/Bma421.h | ||||
|         drivers/Bma421_C/bma4.c | ||||
|         drivers/Bma421_C/bma423.c | ||||
|         components/battery/BatteryController.h | ||||
|         components/ble/BleController.h | ||||
|         components/ble/NotificationManager.h | ||||
|         components/datetime/DateTimeController.h | ||||
|         components/brightness/BrightnessController.h | ||||
|         components/motion/MotionController.h | ||||
|         components/ble/NimbleController.h | ||||
|         components/ble/DeviceInformationService.h | ||||
|         components/ble/CurrentTimeClient.h | ||||
|  | ||||
| @ -1,9 +1,14 @@ | ||||
| #include "DateTimeController.h" | ||||
| #include <date/date.h> | ||||
| #include <libraries/log/nrf_log.h> | ||||
| #include <systemtask/SystemTask.h> | ||||
| 
 | ||||
| using namespace Pinetime::Controllers; | ||||
| 
 | ||||
| DateTime::DateTime(System::SystemTask& systemTask) : systemTask{systemTask} { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void DateTime::SetTime(uint16_t year, uint8_t month, uint8_t day, uint8_t dayOfWeek, uint8_t hour, uint8_t minute, | ||||
|                        uint8_t second, uint32_t systickCounter) { | ||||
| @ -62,6 +67,14 @@ void DateTime::UpdateTime(uint32_t systickCounter) { | ||||
|   hour = time.hours().count(); | ||||
|   minute = time.minutes().count(); | ||||
|   second = time.seconds().count(); | ||||
| 
 | ||||
|   // Notify new day to SystemTask
 | ||||
|   if(hour == 0 and not isMidnightAlreadyNotified) { | ||||
|     isMidnightAlreadyNotified = true; | ||||
|     systemTask.PushMessage(System::SystemTask::Messages::OnNewDay); | ||||
|   } else if (hour != 0) { | ||||
|     isMidnightAlreadyNotified = false; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| const char *DateTime::MonthShortToString() { | ||||
|  | ||||
| @ -4,12 +4,17 @@ | ||||
| #include <chrono> | ||||
| 
 | ||||
| namespace Pinetime { | ||||
|   namespace System { | ||||
|     class SystemTask; | ||||
|   } | ||||
|   namespace Controllers { | ||||
|     class DateTime { | ||||
|       public: | ||||
|         enum class Days : uint8_t {Unknown, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday}; | ||||
|         enum class Months : uint8_t {Unknown, January, February, March, April, May, June, July, August, September, October, November, December}; | ||||
| 
 | ||||
|         DateTime(System::SystemTask& systemTask); | ||||
| 
 | ||||
|         void SetTime(uint16_t year, uint8_t month, uint8_t day, uint8_t dayOfWeek, uint8_t hour, uint8_t minute, uint8_t second, uint32_t systickCounter); | ||||
|         void UpdateTime(uint32_t systickCounter); | ||||
|         uint16_t Year() const { return year; } | ||||
| @ -31,6 +36,7 @@ namespace Pinetime { | ||||
|         std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> CurrentDateTime() const { return currentDateTime; } | ||||
|         std::chrono::seconds Uptime() const { return uptime; } | ||||
|       private: | ||||
|         System::SystemTask& systemTask; | ||||
|         uint16_t year = 0; | ||||
|         Months month = Months::Unknown; | ||||
|         uint8_t day = 0; | ||||
| @ -43,6 +49,8 @@ namespace Pinetime { | ||||
|         std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> currentDateTime; | ||||
|         std::chrono::seconds uptime {0}; | ||||
| 
 | ||||
|         bool isMidnightAlreadyNotified = false; | ||||
| 
 | ||||
|         static char const *DaysString[]; | ||||
|         static char const *DaysStringShort[]; | ||||
|         static char const *DaysStringLow[]; | ||||
|  | ||||
							
								
								
									
										36
									
								
								src/components/motion/MotionController.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/components/motion/MotionController.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| #include "MotionController.h" | ||||
| 
 | ||||
| using namespace Pinetime::Controllers; | ||||
| 
 | ||||
| void MotionController::Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps) { | ||||
|   this->x = x; | ||||
|   this->y = y; | ||||
|   this->z = z; | ||||
|   this->nbSteps = nbSteps; | ||||
| } | ||||
| 
 | ||||
| bool MotionController::ShouldWakeUp(bool isSleeping) { | ||||
|   if ((x + 335) <= 670 && z < 0) { | ||||
|     if (not isSleeping) { | ||||
|       if (y <= 0) { | ||||
|         return false; | ||||
|       } else { | ||||
|         lastYForWakeUp = 0; | ||||
|         return false; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     if (y >= 0) { | ||||
|       lastYForWakeUp = 0; | ||||
|       return false; | ||||
|     } | ||||
|     if (y + 230 < lastYForWakeUp) { | ||||
|       lastYForWakeUp = y; | ||||
|       return true; | ||||
|     } | ||||
|   } | ||||
|   return false; | ||||
| } | ||||
| void MotionController::IsSensorOk(bool isOk) { | ||||
|   isSensorOk = isOk; | ||||
| } | ||||
							
								
								
									
										29
									
								
								src/components/motion/MotionController.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/components/motion/MotionController.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <cstdint> | ||||
| 
 | ||||
| namespace Pinetime { | ||||
|   namespace Controllers { | ||||
|     class MotionController { | ||||
|     public: | ||||
|       void Update(int16_t x, int16_t y, int16_t z, uint32_t nbSteps); | ||||
| 
 | ||||
|       uint16_t X() const { return x; } | ||||
|       uint16_t Y() const { return y; } | ||||
|       uint16_t Z() const { return z; } | ||||
|       uint32_t NbSteps() const { return nbSteps; } | ||||
|       bool ShouldWakeUp(bool isSleeping); | ||||
| 
 | ||||
|       void IsSensorOk(bool isOk); | ||||
|       bool IsSensorOk() const { return isSensorOk; } | ||||
| 
 | ||||
|     private: | ||||
|       uint32_t nbSteps; | ||||
|       int16_t x; | ||||
|       int16_t y; | ||||
|       int16_t z; | ||||
|       int16_t lastYForWakeUp = 0; | ||||
|       bool isSensorOk = false; | ||||
|     }; | ||||
|   } | ||||
| } | ||||
| @ -2,9 +2,9 @@ | ||||
| 
 | ||||
| namespace Pinetime { | ||||
|   namespace Applications { | ||||
|     enum class Apps {  | ||||
|     enum class Apps { | ||||
|       None, Launcher, Clock, SysInfo, FirmwareUpdate, FirmwareValidation, NotificationsPreview, Notifications, FlashLight, BatteryInfo, | ||||
|       Music, Paint, Paddle, Twos, HeartRate, Navigation, StopWatch, | ||||
|       Music, Paint, Paddle, Twos, HeartRate, Navigation, StopWatch, Motion, | ||||
|       QuickSettings, Settings, SettingWatchFace, SettingTimeFormat, SettingDisplay, SettingWakeUp | ||||
|     }; | ||||
|   } | ||||
|  | ||||
| @ -1,10 +1,12 @@ | ||||
| #include "DisplayApp.h" | ||||
| #include <libraries/log/nrf_log.h> | ||||
| #include <displayapp/screens/HeartRate.h> | ||||
| #include <displayapp/screens/Motion.h> | ||||
| #include "components/battery/BatteryController.h" | ||||
| #include "components/ble/BleController.h" | ||||
| #include "components/datetime/DateTimeController.h" | ||||
| #include "components/ble/NotificationManager.h" | ||||
| #include "components/motion/MotionController.h" | ||||
| #include "displayapp/screens/ApplicationList.h" | ||||
| #include "displayapp/screens/Brightness.h" | ||||
| #include "displayapp/screens/Clock.h" | ||||
| @ -43,7 +45,8 @@ DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Driver | ||||
|                        System::SystemTask &systemTask, | ||||
|                        Pinetime::Controllers::NotificationManager& notificationManager, | ||||
|                        Pinetime::Controllers::HeartRateController& heartRateController, | ||||
|                        Controllers::Settings &settingsController) : | ||||
|                        Controllers::Settings &settingsController, | ||||
|                        Pinetime::Controllers::MotionController& motionController) : | ||||
|         lcd{lcd}, | ||||
|         lvgl{lvgl}, | ||||
|         touchPanel{touchPanel}, | ||||
| @ -54,7 +57,8 @@ DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Driver | ||||
|         systemTask{systemTask}, | ||||
|         notificationManager{notificationManager}, | ||||
|         heartRateController{heartRateController}, | ||||
|         settingsController{settingsController} { | ||||
|         settingsController{settingsController}, | ||||
|         motionController{motionController} { | ||||
|   msgQueue = xQueueCreate(queueSize, itemSize); | ||||
|   // Start clock when smartwatch boots
 | ||||
|   LoadApp( Apps::Clock, DisplayApp::FullRefreshDirections::None ); | ||||
| @ -174,7 +178,7 @@ void DisplayApp::Refresh() { | ||||
|         break; | ||||
|        case Messages::UpdateDateTime: | ||||
|        // Added to remove warning
 | ||||
|        // What should happen here? 
 | ||||
|        // What should happen here?
 | ||||
|        break; | ||||
|     } | ||||
|   } | ||||
| @ -220,7 +224,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) | ||||
|       break; | ||||
|     case Apps::None: | ||||
|     case Apps::Clock: | ||||
|       currentScreen = std::make_unique<Screens::Clock>(this, dateTimeController, batteryController, bleController, notificationManager, settingsController, heartRateController);  | ||||
|       currentScreen = std::make_unique<Screens::Clock>(this, dateTimeController, batteryController, bleController, notificationManager, settingsController, heartRateController, motionController); | ||||
|       break; | ||||
| 
 | ||||
|     case Apps::FirmwareValidation: | ||||
| @ -232,7 +236,7 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) | ||||
|       break; | ||||
| 
 | ||||
|     case Apps::Notifications: | ||||
|       currentScreen = std::make_unique<Screens::Notifications>(this, notificationManager, systemTask.nimble().alertService(), Screens::Notifications::Modes::Normal);  | ||||
|       currentScreen = std::make_unique<Screens::Notifications>(this, notificationManager, systemTask.nimble().alertService(), Screens::Notifications::Modes::Normal); | ||||
|       returnApp(Apps::Clock, FullRefreshDirections::Up, TouchEvents::SwipeUp); | ||||
|       break; | ||||
|     case Apps::NotificationsPreview: | ||||
| @ -245,37 +249,37 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) | ||||
|       currentScreen = std::make_unique<Screens::QuickSettings>(this, batteryController, dateTimeController, brightnessController, settingsController); | ||||
|       returnApp(Apps::Clock, FullRefreshDirections::LeftAnim, TouchEvents::SwipeLeft); | ||||
|       break; | ||||
|     case Apps::Settings:  | ||||
|     case Apps::Settings: | ||||
|       currentScreen = std::make_unique<Screens::Settings>(this, settingsController); | ||||
|       returnApp(Apps::QuickSettings, FullRefreshDirections::Down, TouchEvents::SwipeDown); | ||||
|       break; | ||||
|     case Apps::SettingWatchFace:  | ||||
|     case Apps::SettingWatchFace: | ||||
|       currentScreen = std::make_unique<Screens::SettingWatchFace>(this, settingsController); | ||||
|       returnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); | ||||
|       break; | ||||
|     case Apps::SettingTimeFormat:  | ||||
|     case Apps::SettingTimeFormat: | ||||
|       currentScreen = std::make_unique<Screens::SettingTimeFormat>(this, settingsController); | ||||
|       returnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); | ||||
|       break; | ||||
|     case Apps::SettingWakeUp:  | ||||
|     case Apps::SettingWakeUp: | ||||
|       currentScreen = std::make_unique<Screens::SettingWakeUp>(this, settingsController); | ||||
|       returnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); | ||||
|       break; | ||||
|     case Apps::SettingDisplay:  | ||||
|     case Apps::SettingDisplay: | ||||
|       currentScreen = std::make_unique<Screens::SettingDisplay>(this, settingsController); | ||||
|       returnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); | ||||
|       break; | ||||
|     case Apps::BatteryInfo: | ||||
|       currentScreen = std::make_unique<Screens::BatteryInfo>(this, batteryController); | ||||
|       returnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown);       | ||||
|       returnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); | ||||
|       break; | ||||
|     case Apps::SysInfo: | ||||
|       currentScreen = std::make_unique<Screens::SystemInfo>(this, dateTimeController, batteryController, brightnessController, bleController, watchdog); | ||||
|       returnApp(Apps::Settings, FullRefreshDirections::Down, TouchEvents::SwipeDown); | ||||
|       break; | ||||
|     //
 | ||||
|      | ||||
|     case Apps::FlashLight:  | ||||
| 
 | ||||
|     case Apps::FlashLight: | ||||
|       currentScreen = std::make_unique<Screens::FlashLight>(this, systemTask, brightnessController); | ||||
|       returnApp(Apps::Clock, FullRefreshDirections::Down, TouchEvents::None); | ||||
|       break; | ||||
| @ -283,23 +287,27 @@ void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) | ||||
|       currentScreen = std::make_unique<Screens::StopWatch>(this); | ||||
|       break; | ||||
|     case Apps::Twos: | ||||
|       currentScreen = std::make_unique<Screens::Twos>(this);  | ||||
|       currentScreen = std::make_unique<Screens::Twos>(this); | ||||
|       break; | ||||
|     case Apps::Paint: | ||||
|       currentScreen = std::make_unique<Screens::InfiniPaint>(this, lvgl);  | ||||
|       currentScreen = std::make_unique<Screens::InfiniPaint>(this, lvgl); | ||||
|       break; | ||||
|     case Apps::Paddle: | ||||
|       currentScreen = std::make_unique<Screens::Paddle>(this, lvgl);  | ||||
|       currentScreen = std::make_unique<Screens::Paddle>(this, lvgl); | ||||
|       break; | ||||
|     case Apps::Music: | ||||
|       currentScreen = std::make_unique<Screens::Music>(this, systemTask.nimble().music());  | ||||
|       currentScreen = std::make_unique<Screens::Music>(this, systemTask.nimble().music()); | ||||
|       break; | ||||
|     case Apps::Navigation: | ||||
|       currentScreen = std::make_unique<Screens::Navigation>(this, systemTask.nimble().navigation());  | ||||
|       currentScreen = std::make_unique<Screens::Navigation>(this, systemTask.nimble().navigation()); | ||||
|       break; | ||||
|     case Apps::HeartRate: | ||||
|       currentScreen = std::make_unique<Screens::HeartRate>(this, heartRateController, systemTask);  | ||||
|       currentScreen = std::make_unique<Screens::HeartRate>(this, heartRateController, systemTask); | ||||
|       break; | ||||
|     case Apps::Motion: | ||||
|       currentScreen = std::make_unique<Screens::Motion>(this, motionController); | ||||
|       break; | ||||
| 
 | ||||
|   } | ||||
|   currentApp = app; | ||||
| } | ||||
|  | ||||
| @ -27,6 +27,7 @@ namespace Pinetime { | ||||
|     class DateTime; | ||||
|     class NotificationManager; | ||||
|     class HeartRateController; | ||||
|     class MotionController; | ||||
|   } | ||||
| 
 | ||||
|   namespace System { | ||||
| @ -45,7 +46,8 @@ namespace Pinetime { | ||||
|                    System::SystemTask &systemTask, | ||||
|                    Pinetime::Controllers::NotificationManager& notificationManager, | ||||
|                    Pinetime::Controllers::HeartRateController& heartRateController, | ||||
|                    Controllers::Settings &settingsController | ||||
|                    Controllers::Settings &settingsController, | ||||
|                    Pinetime::Controllers::MotionController& motionController | ||||
|                    ); | ||||
|         void Start(); | ||||
|         void PushMessage(Display::Messages msg); | ||||
| @ -68,7 +70,8 @@ namespace Pinetime { | ||||
|         Pinetime::Controllers::NotificationManager& notificationManager; | ||||
|         Pinetime::Controllers::HeartRateController& heartRateController; | ||||
|         Pinetime::Controllers::Settings& settingsController; | ||||
|          | ||||
|         Pinetime::Controllers::MotionController& motionController; | ||||
| 
 | ||||
|         Pinetime::Controllers::FirmwareValidator validator; | ||||
|         Controllers::BrightnessController brightnessController; | ||||
| 
 | ||||
|  | ||||
| @ -13,7 +13,8 @@ DisplayApp::DisplayApp(Drivers::St7789 &lcd, Components::LittleVgl &lvgl, Driver | ||||
|                        System::SystemTask &systemTask, | ||||
|                        Pinetime::Controllers::NotificationManager& notificationManager, | ||||
|                        Pinetime::Controllers::HeartRateController& heartRateController, | ||||
|                        Pinetime::Controllers::Settings& settingsController): | ||||
|                        Pinetime::Controllers::Settings& settingsController, | ||||
|                        Pinetime::Controllers::MotionController& motionController): | ||||
|     lcd{lcd}, bleController{bleController} { | ||||
|   msgQueue = xQueueCreate(queueSize, itemSize); | ||||
| 
 | ||||
|  | ||||
| @ -16,6 +16,7 @@ | ||||
| #include <date/date.h> | ||||
| #include <drivers/Watchdog.h> | ||||
| #include <components/heartrate/HeartRateController.h> | ||||
| #include <components/motion/MotionController.h> | ||||
| #include <components/settings/Settings.h> | ||||
| #include "TouchEvents.h" | ||||
| #include "Apps.h" | ||||
| @ -35,7 +36,8 @@ namespace Pinetime { | ||||
|                  System::SystemTask &systemTask, | ||||
|                  Pinetime::Controllers::NotificationManager& notificationManager, | ||||
|                  Pinetime::Controllers::HeartRateController& heartRateController, | ||||
|                  Pinetime::Controllers::Settings& settingsController); | ||||
|                  Pinetime::Controllers::Settings& settingsController, | ||||
|                  Pinetime::Controllers::MotionController& motionController); | ||||
|       void Start(); | ||||
|       void PushMessage(Pinetime::Applications::Display::Messages msg); | ||||
| 
 | ||||
|  | ||||
| @ -53,6 +53,7 @@ static lv_style_t style_table_cell; | ||||
| static lv_style_t style_pad_small; | ||||
| static lv_style_t style_bg_grad; | ||||
| static lv_style_t style_lmeter; | ||||
| static lv_style_t style_chart_serie; | ||||
| static lv_style_t style_cb_bg; | ||||
| static lv_style_t style_cb_bullet; | ||||
| 
 | ||||
| @ -277,6 +278,12 @@ static void basic_init(void) | ||||
|     lv_style_set_line_width(&style_lmeter, LV_STATE_DEFAULT, LV_DPX(10)); | ||||
|     lv_style_set_scale_end_line_width(&style_lmeter, LV_STATE_DEFAULT, LV_DPX(7)); | ||||
| 
 | ||||
|     style_init_reset(&style_chart_serie); | ||||
|     lv_style_set_line_color(&style_chart_serie, LV_STATE_DEFAULT, LV_PINETIME_WHITE); | ||||
|     lv_style_set_line_width(&style_chart_serie, LV_STATE_DEFAULT, 4); | ||||
|     lv_style_set_size(&style_chart_serie, LV_STATE_DEFAULT, 4); | ||||
|     lv_style_set_bg_opa(&style_chart_serie, LV_STATE_DEFAULT, 0); | ||||
| 
 | ||||
|     lv_style_reset(&style_cb_bg); | ||||
|     lv_style_set_radius(&style_cb_bg, LV_STATE_DEFAULT, LV_DPX(4)); | ||||
|     lv_style_set_pad_inner(&style_cb_bg, LV_STATE_DEFAULT, LV_DPX(10)); | ||||
| @ -500,7 +507,14 @@ static void theme_apply(lv_obj_t * obj, lv_theme_style_t name) | ||||
|             _lv_style_list_add_style(list, &style_bg); | ||||
|             _lv_style_list_add_style(list, &style_lmeter); | ||||
|             break; | ||||
|              | ||||
| 
 | ||||
|         case LV_THEME_CHART: | ||||
|           lv_obj_clean_style_list(obj, LV_CHART_PART_SERIES); | ||||
|           list = lv_obj_get_style_list(obj, LV_CHART_PART_SERIES); | ||||
|           _lv_style_list_add_style(list, &style_btn); | ||||
|           _lv_style_list_add_style(list, &style_chart_serie); | ||||
|           break; | ||||
| 
 | ||||
|         case LV_THEME_CHECKBOX: | ||||
|             list = lv_obj_get_style_list(obj, LV_CHECKBOX_PART_BG); | ||||
|             _lv_style_list_add_style(list, &style_cb_bg); | ||||
|  | ||||
| @ -16,7 +16,7 @@ ApplicationList::ApplicationList(Pinetime::Applications::DisplayApp *app, | ||||
|         settingsController{settingsController}, | ||||
|         batteryController{batteryController}, | ||||
|         dateTimeController{dateTimeController}, | ||||
|         screens{app,  | ||||
|         screens{app, | ||||
|           settingsController.GetAppMenu(), | ||||
|           { | ||||
|                 [this]() -> std::unique_ptr<Screen> { return CreateScreen1(); }, | ||||
| @ -47,7 +47,7 @@ std::unique_ptr<Screen> ApplicationList::CreateScreen1() { | ||||
|             {Symbols::stopWatch,    Apps::StopWatch}, | ||||
|             {Symbols::music,        Apps::Music}, | ||||
|             {Symbols::map,          Apps::Navigation}, | ||||
|             {Symbols::shoe,         Apps::Clock}, | ||||
|             {Symbols::shoe,         Apps::Motion}, | ||||
|             {Symbols::heartBeat,    Apps::HeartRate}, | ||||
|             {"",                    Apps::None}, | ||||
|           } | ||||
|  | ||||
| @ -8,6 +8,7 @@ | ||||
| #include "NotificationIcon.h" | ||||
| #include "Symbols.h" | ||||
| #include "components/battery/BatteryController.h" | ||||
| #include "components/motion/MotionController.h" | ||||
| #include "components/ble/BleController.h" | ||||
| #include "components/ble/NotificationManager.h" | ||||
| #include "../DisplayApp.h" | ||||
| @ -23,12 +24,14 @@ Clock::Clock(DisplayApp* app, | ||||
|         Controllers::Ble& bleController, | ||||
|         Controllers::NotificationManager& notificatioManager, | ||||
|         Controllers::Settings &settingsController, | ||||
|         Controllers::HeartRateController& heartRateController) : Screen(app), | ||||
|         Controllers::HeartRateController& heartRateController, | ||||
|         Controllers::MotionController& motionController) : Screen(app), | ||||
|         dateTimeController{dateTimeController}, batteryController{batteryController}, | ||||
|         bleController{bleController}, notificatioManager{notificatioManager}, | ||||
|         settingsController{settingsController}, | ||||
|         heartRateController{heartRateController}, | ||||
|         screens{app,  | ||||
|         motionController{motionController}, | ||||
|         screens{app, | ||||
|           settingsController.GetClockFace(), | ||||
|           { | ||||
|                 [this]() -> std::unique_ptr<Screen> { return WatchFaceDigitalScreen(); }, | ||||
| @ -59,7 +62,7 @@ bool Clock::OnTouchEvent(Pinetime::Applications::TouchEvents event) { | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<Screen> Clock::WatchFaceDigitalScreen() {   | ||||
|   return std::make_unique<Screens::WatchFaceDigital>(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController, heartRateController); | ||||
|   return std::make_unique<Screens::WatchFaceDigital>(app, dateTimeController, batteryController, bleController, notificatioManager, settingsController, heartRateController, motionController); | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<Screen> Clock::WatchFaceAnalogScreen() {   | ||||
|  | ||||
| @ -17,6 +17,7 @@ namespace Pinetime { | ||||
|     class Battery; | ||||
|     class Ble; | ||||
|     class NotificationManager; | ||||
|     class MotionController; | ||||
|   } | ||||
| 
 | ||||
|   namespace Applications { | ||||
| @ -29,7 +30,8 @@ namespace Pinetime { | ||||
|                   Controllers::Ble& bleController, | ||||
|                   Controllers::NotificationManager& notificatioManager, | ||||
|                   Controllers::Settings &settingsController, | ||||
|                   Controllers::HeartRateController& heartRateController); | ||||
|                   Controllers::HeartRateController& heartRateController, | ||||
|                   Controllers::MotionController& motionController); | ||||
|           ~Clock() override; | ||||
| 
 | ||||
|           bool Refresh() override; | ||||
| @ -44,6 +46,7 @@ namespace Pinetime { | ||||
|           Controllers::NotificationManager& notificatioManager; | ||||
|           Controllers::Settings& settingsController; | ||||
|           Controllers::HeartRateController& heartRateController; | ||||
|           Controllers::MotionController& motionController; | ||||
| 
 | ||||
| 
 | ||||
|           ScreenList<2> screens; | ||||
|  | ||||
							
								
								
									
										59
									
								
								src/displayapp/screens/Motion.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								src/displayapp/screens/Motion.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| #include <libs/lvgl/lvgl.h> | ||||
| #include "Motion.h" | ||||
| #include "../DisplayApp.h" | ||||
| 
 | ||||
| using namespace Pinetime::Applications::Screens; | ||||
| extern lv_font_t jetbrains_mono_extrabold_compressed; | ||||
| extern lv_font_t jetbrains_mono_bold_20; | ||||
| 
 | ||||
| 
 | ||||
| Motion::Motion(Pinetime::Applications::DisplayApp *app, Controllers::MotionController& motionController) : Screen(app), motionController{motionController} { | ||||
|   chart = lv_chart_create(lv_scr_act(), NULL); | ||||
|   lv_obj_set_size(chart, 240, 240); | ||||
|   lv_obj_align(chart, NULL, LV_ALIGN_IN_TOP_MID, 0, 0); | ||||
|   lv_chart_set_type(chart, LV_CHART_TYPE_LINE);   /*Show lines and points too*/ | ||||
|   //lv_chart_set_series_opa(chart, LV_OPA_70);                            /*Opacity of the data series*/
 | ||||
|   //lv_chart_set_series_width(chart, 4);                                  /*Line width and point radious*/
 | ||||
| 
 | ||||
|   lv_chart_set_range(chart, -1100, 1100); | ||||
|   lv_chart_set_update_mode(chart, LV_CHART_UPDATE_MODE_SHIFT); | ||||
|   lv_chart_set_point_count(chart, 10); | ||||
| 
 | ||||
|   /*Add 3 data series*/ | ||||
|   ser1 = lv_chart_add_series(chart, LV_COLOR_RED); | ||||
|   ser2 = lv_chart_add_series(chart, LV_COLOR_GREEN); | ||||
|   ser3 = lv_chart_add_series(chart, LV_COLOR_YELLOW); | ||||
| 
 | ||||
|   lv_chart_init_points(chart, ser1, 0); | ||||
|   lv_chart_init_points(chart, ser2, 0); | ||||
|   lv_chart_init_points(chart, ser3, 0); | ||||
|   lv_chart_refresh(chart); /*Required after direct set*/ | ||||
| 
 | ||||
|   labelStep = lv_label_create(lv_scr_act(), NULL); | ||||
|   lv_obj_align(labelStep, chart, LV_ALIGN_IN_BOTTOM_LEFT, 0, 0); | ||||
|   lv_label_set_text(labelStep, "Steps: "); | ||||
| 
 | ||||
|   labelStepValue = lv_label_create(lv_scr_act(), NULL); | ||||
|   lv_obj_align(labelStepValue, labelStep, LV_ALIGN_OUT_RIGHT_MID, 0, 0); | ||||
|   lv_label_set_text(labelStepValue, "-"); | ||||
| } | ||||
| 
 | ||||
| Motion::~Motion() { | ||||
|   lv_obj_clean(lv_scr_act()); | ||||
| } | ||||
| 
 | ||||
| bool Motion::Refresh() { | ||||
|   lv_chart_set_next(chart, ser1, motionController.X()); | ||||
|   lv_chart_set_next(chart, ser2, motionController.Y()); | ||||
|   lv_chart_set_next(chart, ser3, motionController.Z()); | ||||
| 
 | ||||
|   snprintf(nbStepsBuffer, nbStepsBufferSize, "%lu", motionController.NbSteps()); | ||||
|   lv_label_set_text(labelStepValue, nbStepsBuffer); | ||||
| 
 | ||||
|   return running; | ||||
| } | ||||
| 
 | ||||
| bool Motion::OnButtonPushed() { | ||||
|   running = false; | ||||
|   return true; | ||||
| } | ||||
							
								
								
									
										39
									
								
								src/displayapp/screens/Motion.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/displayapp/screens/Motion.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,39 @@ | ||||
| #pragma once | ||||
| 
 | ||||
| #include <cstdint> | ||||
| #include <chrono> | ||||
| #include "Screen.h" | ||||
| #include <bits/unique_ptr.h> | ||||
| #include <libs/lvgl/src/lv_core/lv_style.h> | ||||
| #include <libs/lvgl/src/lv_core/lv_obj.h> | ||||
| #include <components/motion/MotionController.h> | ||||
| 
 | ||||
| namespace Pinetime { | ||||
|   namespace Applications { | ||||
|     namespace Screens { | ||||
| 
 | ||||
|       class Motion : public Screen{ | ||||
|       public: | ||||
|         Motion(DisplayApp* app, Controllers::MotionController& motionController); | ||||
|         ~Motion() override; | ||||
| 
 | ||||
|         bool Refresh() override; | ||||
|         bool OnButtonPushed() override; | ||||
| 
 | ||||
|       private: | ||||
|         Controllers::MotionController& motionController; | ||||
|         lv_obj_t * chart; | ||||
|         lv_chart_series_t * ser1; | ||||
|         lv_chart_series_t * ser2; | ||||
|         lv_chart_series_t * ser3; | ||||
| 
 | ||||
|         lv_obj_t* labelStep; | ||||
|         lv_obj_t* labelStepValue; | ||||
|         static constexpr uint8_t nbStepsBufferSize = 9; | ||||
|         char nbStepsBuffer[nbStepsBufferSize+1]; | ||||
|         bool running = true; | ||||
| 
 | ||||
|       }; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @ -11,6 +11,7 @@ | ||||
| #include "components/ble/BleController.h" | ||||
| #include "components/ble/NotificationManager.h" | ||||
| #include "components/heartrate/HeartRateController.h" | ||||
| #include "components/motion/MotionController.h" | ||||
| #include "components/settings/Settings.h" | ||||
| #include "../DisplayApp.h" | ||||
| 
 | ||||
| @ -23,11 +24,13 @@ WatchFaceDigital::WatchFaceDigital(DisplayApp* app, | ||||
|         Controllers::Ble& bleController, | ||||
|         Controllers::NotificationManager& notificatioManager, | ||||
|         Controllers::Settings &settingsController, | ||||
|         Controllers::HeartRateController& heartRateController): Screen(app), currentDateTime{{}}, | ||||
|         Controllers::HeartRateController& heartRateController, | ||||
|         Controllers::MotionController& motionController) : Screen(app), currentDateTime{{}}, | ||||
|                                            dateTimeController{dateTimeController}, batteryController{batteryController}, | ||||
|                                            bleController{bleController}, notificatioManager{notificatioManager}, | ||||
|                                            settingsController{settingsController}, | ||||
|                                            heartRateController{heartRateController} { | ||||
|                                            heartRateController{heartRateController}, | ||||
|                                            motionController{motionController} { | ||||
|   settingsController.SetClockFace(0); | ||||
| 
 | ||||
|   displayedChar[0] = 0; | ||||
| @ -236,10 +239,14 @@ bool WatchFaceDigital::Refresh() { | ||||
|     lv_obj_align(heartbeatBpm, heartbeatValue, LV_ALIGN_OUT_RIGHT_MID, 5, 0); | ||||
|   } | ||||
| 
 | ||||
|   // TODO stepCount = stepController.GetValue();
 | ||||
|   if(stepCount.IsUpdated()) { | ||||
|   stepCount = motionController.NbSteps(); | ||||
|   motionSensorOk = motionController.IsSensorOk(); | ||||
|   if(stepCount.IsUpdated() || motionSensorOk.IsUpdated()) { | ||||
|     char stepBuffer[5]; | ||||
|     sprintf(stepBuffer, "%lu", stepCount.Get()); | ||||
|     if(motionSensorOk.Get()) | ||||
|       sprintf(stepBuffer, "%lu", stepCount.Get()); | ||||
|     else | ||||
|       sprintf(stepBuffer, "---", stepCount.Get()); | ||||
|     lv_label_set_text(stepValue, stepBuffer); | ||||
|     lv_obj_align(stepValue, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, -5, -2); | ||||
|     lv_obj_align(stepIcon, stepValue, LV_ALIGN_OUT_LEFT_MID, -5, 0); | ||||
|  | ||||
| @ -15,6 +15,7 @@ namespace Pinetime { | ||||
|     class Ble; | ||||
|     class NotificationManager; | ||||
|     class HeartRateController; | ||||
|     class MotionController; | ||||
|   } | ||||
| 
 | ||||
|   namespace Applications { | ||||
| @ -28,7 +29,8 @@ namespace Pinetime { | ||||
|                   Controllers::Ble& bleController, | ||||
|                   Controllers::NotificationManager& notificatioManager, | ||||
|                   Controllers::Settings &settingsController, | ||||
|                   Controllers::HeartRateController& heartRateController); | ||||
|                   Controllers::HeartRateController& heartRateController, | ||||
|                   Controllers::MotionController& motionController); | ||||
|           ~WatchFaceDigital() override; | ||||
| 
 | ||||
|           bool Refresh() override; | ||||
| @ -48,6 +50,7 @@ namespace Pinetime { | ||||
|           DirtyValue<int> batteryPercentRemaining  {}; | ||||
|           DirtyValue<bool> bleState {}; | ||||
|           DirtyValue<std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>> currentDateTime{}; | ||||
|           DirtyValue<bool> motionSensorOk  {}; | ||||
|           DirtyValue<uint32_t> stepCount  {}; | ||||
|           DirtyValue<uint8_t> heartbeat  {}; | ||||
|           DirtyValue<bool> heartbeatRunning  {}; | ||||
| @ -73,6 +76,7 @@ namespace Pinetime { | ||||
|           Controllers::NotificationManager& notificatioManager; | ||||
|           Controllers::Settings& settingsController; | ||||
|           Controllers::HeartRateController& heartRateController; | ||||
|           Controllers::MotionController& motionController; | ||||
| 
 | ||||
|            | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										116
									
								
								src/drivers/Bma421.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								src/drivers/Bma421.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,116 @@ | ||||
| #include <libraries/delay/nrf_delay.h> | ||||
| #include <libraries/log/nrf_log.h> | ||||
| #include "Bma421.h" | ||||
| #include "TwiMaster.h" | ||||
| #include <drivers/Bma421_C/bma423.h> | ||||
| 
 | ||||
| using namespace Pinetime::Drivers; | ||||
| 
 | ||||
| namespace { | ||||
|   int8_t user_i2c_read(uint8_t reg_addr, uint8_t* reg_data, uint32_t length, void* intf_ptr) { | ||||
|     auto bma421 = static_cast<Bma421*>(intf_ptr); | ||||
|     bma421->Read(reg_addr, reg_data, length); | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   int8_t user_i2c_write(uint8_t reg_addr, const uint8_t* reg_data, uint32_t length, void* intf_ptr) { | ||||
|     auto bma421 = static_cast<Bma421*>(intf_ptr); | ||||
|     bma421->Write(reg_addr, reg_data, length); | ||||
|     return 0; | ||||
|   } | ||||
| 
 | ||||
|   void user_delay(uint32_t period_us, void* intf_ptr) { | ||||
|     nrf_delay_us(period_us); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| Bma421::Bma421(TwiMaster& twiMaster, uint8_t twiAddress) : twiMaster{twiMaster}, deviceAddress{twiAddress} { | ||||
|   bma.intf = BMA4_I2C_INTF; | ||||
|   bma.bus_read = user_i2c_read; | ||||
|   bma.bus_write = user_i2c_write; | ||||
|   bma.variant = BMA42X_VARIANT; | ||||
|   bma.intf_ptr = this; | ||||
|   bma.delay_us = user_delay; | ||||
|   bma.read_write_len = 8; | ||||
| } | ||||
| 
 | ||||
| void Bma421::Init() { | ||||
|   if(not isResetOk) return; // Call SoftReset (and reset TWI device) first!
 | ||||
| 
 | ||||
|   auto ret = bma423_init(&bma); | ||||
|   if(ret != BMA4_OK) return; | ||||
| 
 | ||||
|   ret = bma423_write_config_file(&bma); | ||||
|   if(ret != BMA4_OK) return; | ||||
| 
 | ||||
|   ret = bma4_set_interrupt_mode(BMA4_LATCH_MODE, &bma); | ||||
|   if(ret != BMA4_OK) return; | ||||
| 
 | ||||
|   ret = bma423_feature_enable(BMA423_STEP_CNTR, 1, &bma); | ||||
|   if(ret != BMA4_OK) return; | ||||
| 
 | ||||
|   ret = bma423_step_detector_enable(0, &bma); | ||||
|   if(ret != BMA4_OK) return; | ||||
| 
 | ||||
|   ret = bma4_set_accel_enable(1, &bma); | ||||
|   if(ret != BMA4_OK) return; | ||||
| 
 | ||||
|   struct bma4_accel_config accel_conf; | ||||
|   accel_conf.odr = BMA4_OUTPUT_DATA_RATE_100HZ; | ||||
|   accel_conf.range = BMA4_ACCEL_RANGE_2G; | ||||
|   accel_conf.bandwidth = BMA4_ACCEL_NORMAL_AVG4; | ||||
|   accel_conf.perf_mode = BMA4_CIC_AVG_MODE; | ||||
|   ret = bma4_set_accel_config(&accel_conf, &bma); | ||||
|   if(ret != BMA4_OK) return; | ||||
| 
 | ||||
|   isOk = true; | ||||
| } | ||||
| 
 | ||||
| void Bma421::Reset() { | ||||
|   uint8_t data = 0xb6; | ||||
|   twiMaster.Write(deviceAddress, 0x7E, &data, 1); | ||||
| } | ||||
| 
 | ||||
| void Bma421::Read(uint8_t registerAddress, uint8_t *buffer, size_t size) { | ||||
|   twiMaster.Read(deviceAddress, registerAddress, buffer, size); | ||||
| } | ||||
| 
 | ||||
| void Bma421::Write(uint8_t registerAddress, const uint8_t *data, size_t size) { | ||||
|   twiMaster.Write(deviceAddress, registerAddress, data, size); | ||||
| } | ||||
| 
 | ||||
| Bma421::Values Bma421::Process() { | ||||
|   if(not isOk) return {}; | ||||
|   struct bma4_accel data; | ||||
|   bma4_read_accel_xyz(&data, &bma); | ||||
| 
 | ||||
|   uint32_t steps = 0; | ||||
|   bma423_step_counter_output(&steps, &bma); | ||||
| 
 | ||||
|   int32_t temperature; | ||||
|   bma4_get_temperature(&temperature, BMA4_DEG, &bma); | ||||
|   temperature = temperature / 1000; | ||||
| 
 | ||||
|   uint8_t activity = 0; | ||||
|   bma423_activity_output(&activity, &bma); | ||||
| 
 | ||||
|   NRF_LOG_INFO("MOTION : %d - %d/%d/%d", steps, data.x, data.y, data.z); | ||||
| 
 | ||||
|   // X and Y axis are swapped because of the way the sensor is mounted in the PineTime
 | ||||
|   return {steps, data.y, data.x, data.z}; | ||||
| } | ||||
| bool Bma421::IsOk() const { | ||||
|   return isOk; | ||||
| } | ||||
| 
 | ||||
| void Bma421::ResetStepCounter() { | ||||
|   bma423_reset_step_counter(&bma); | ||||
| } | ||||
| 
 | ||||
| void Bma421::SoftReset() { | ||||
|   auto ret = bma4_soft_reset(&bma); | ||||
|   if(ret == BMA4_OK) { | ||||
|     isResetOk = true; | ||||
|     nrf_delay_ms(1); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										43
									
								
								src/drivers/Bma421.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/drivers/Bma421.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,43 @@ | ||||
| #pragma once | ||||
| #include <drivers/Bma421_C/bma4_defs.h> | ||||
| 
 | ||||
| namespace Pinetime { | ||||
|   namespace Drivers { | ||||
|     class TwiMaster; | ||||
|     class Bma421 { | ||||
|     public: | ||||
|       struct Values { | ||||
|         uint32_t steps; | ||||
|         int16_t x; | ||||
|         int16_t y; | ||||
|         int16_t z; | ||||
|       }; | ||||
|       Bma421(TwiMaster& twiMaster, uint8_t twiAddress); | ||||
|       Bma421(const Bma421&) = delete; | ||||
|       Bma421& operator=(const Bma421&) = delete; | ||||
|       Bma421(Bma421&&) = delete; | ||||
|       Bma421& operator=(Bma421&&) = delete; | ||||
| 
 | ||||
|       /// The chip freezes the TWI bus after the softreset operation. Softreset is separated from the
 | ||||
|       /// Init() method to allow the caller to uninit and then reinit the TWI device after the softreset.
 | ||||
|       void SoftReset(); | ||||
|       void Init(); | ||||
|       Values Process(); | ||||
|       void ResetStepCounter(); | ||||
| 
 | ||||
|       void Read(uint8_t registerAddress, uint8_t *buffer, size_t size); | ||||
|       void Write(uint8_t registerAddress, const uint8_t *data, size_t size); | ||||
| 
 | ||||
|       bool IsOk() const; | ||||
| 
 | ||||
|     private: | ||||
|       void Reset(); | ||||
| 
 | ||||
|       TwiMaster& twiMaster; | ||||
|       uint8_t deviceAddress = 0x18; | ||||
|       struct bma4_dev bma; | ||||
|       bool isOk = false; | ||||
|       bool isResetOk = false; | ||||
|     }; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										5689
									
								
								src/drivers/Bma421_C/bma4.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5689
									
								
								src/drivers/Bma421_C/bma4.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2281
									
								
								src/drivers/Bma421_C/bma4.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2281
									
								
								src/drivers/Bma421_C/bma4.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1688
									
								
								src/drivers/Bma421_C/bma423.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1688
									
								
								src/drivers/Bma421_C/bma423.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1115
									
								
								src/drivers/Bma421_C/bma423.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1115
									
								
								src/drivers/Bma421_C/bma423.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1144
									
								
								src/drivers/Bma421_C/bma4_defs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1144
									
								
								src/drivers/Bma421_C/bma4_defs.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -2,196 +2,77 @@ | ||||
| #include <cstring> | ||||
| #include <hal/nrf_gpio.h> | ||||
| #include <nrfx_log.h> | ||||
| 
 | ||||
| #include <nrfx_twim.h> | ||||
| #include <nrf_drv_twi.h> | ||||
| using namespace Pinetime::Drivers; | ||||
| 
 | ||||
| // TODO use shortcut to automatically send STOP when receive LastTX, for example
 | ||||
| // TODO use DMA/IRQ
 | ||||
| 
 | ||||
| TwiMaster::TwiMaster(const Modules module, const Parameters& params) : module{module}, params{params} { | ||||
|   mutex = xSemaphoreCreateBinary(); | ||||
|   ASSERT(mutex != NULL); | ||||
| TwiMaster::TwiMaster(const Modules module, const Parameters& params) : module{module}, params{params}, mutex{xSemaphoreCreateBinary()} { | ||||
|   ASSERT(mutex != nullptr); | ||||
|   switch(module) { | ||||
|     case Modules::TWIM1: | ||||
|     default: | ||||
|       twim = NRFX_TWIM_INSTANCE(1); | ||||
|       break; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void TwiMaster::Init() { | ||||
|   NRF_GPIO->PIN_CNF[params.pinScl] = ((uint32_t)GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos) | ||||
|                                      | ((uint32_t)GPIO_PIN_CNF_INPUT_Connect    << GPIO_PIN_CNF_INPUT_Pos) | ||||
|                                      | ((uint32_t)GPIO_PIN_CNF_PULL_Pullup      << GPIO_PIN_CNF_PULL_Pos) | ||||
|                                      | ((uint32_t)GPIO_PIN_CNF_DRIVE_S0D1       << GPIO_PIN_CNF_DRIVE_Pos) | ||||
|                                      | ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled   << GPIO_PIN_CNF_SENSE_Pos); | ||||
| 
 | ||||
|   NRF_GPIO->PIN_CNF[params.pinSda] = ((uint32_t)GPIO_PIN_CNF_DIR_Input        << GPIO_PIN_CNF_DIR_Pos) | ||||
|                                      | ((uint32_t)GPIO_PIN_CNF_INPUT_Connect    << GPIO_PIN_CNF_INPUT_Pos) | ||||
|                                      | ((uint32_t)GPIO_PIN_CNF_PULL_Pullup      << GPIO_PIN_CNF_PULL_Pos) | ||||
|                                      | ((uint32_t)GPIO_PIN_CNF_DRIVE_S0D1       << GPIO_PIN_CNF_DRIVE_Pos) | ||||
|                                      | ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled   << GPIO_PIN_CNF_SENSE_Pos); | ||||
| 
 | ||||
|   switch(module) { | ||||
|     case Modules::TWIM1: twiBaseAddress = NRF_TWIM1; break; | ||||
|     default: | ||||
|       return; | ||||
|   } | ||||
| 
 | ||||
|   switch(static_cast<Frequencies>(params.frequency)) { | ||||
|     case Frequencies::Khz100 : twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K100; break; | ||||
|     case Frequencies::Khz250 : twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K250; break; | ||||
|     case Frequencies::Khz400 : twiBaseAddress->FREQUENCY = TWIM_FREQUENCY_FREQUENCY_K400; break; | ||||
|   } | ||||
| 
 | ||||
|   twiBaseAddress->PSEL.SCL = params.pinScl; | ||||
|   twiBaseAddress->PSEL.SDA = params.pinSda; | ||||
|   twiBaseAddress->EVENTS_LASTRX = 0; | ||||
|   twiBaseAddress->EVENTS_STOPPED = 0; | ||||
|   twiBaseAddress->EVENTS_LASTTX = 0; | ||||
|   twiBaseAddress->EVENTS_ERROR = 0; | ||||
|   twiBaseAddress->EVENTS_RXSTARTED = 0; | ||||
|   twiBaseAddress->EVENTS_SUSPENDED = 0; | ||||
|   twiBaseAddress->EVENTS_TXSTARTED = 0; | ||||
| 
 | ||||
|   twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos); | ||||
| 
 | ||||
| 
 | ||||
|   /* // IRQ
 | ||||
|      NVIC_ClearPendingIRQ(_IRQn); | ||||
|      NVIC_SetPriority(_IRQn, 2); | ||||
|      NVIC_EnableIRQ(_IRQn); | ||||
|    */ | ||||
|   nrfx_twim_config_t config; | ||||
|   config.frequency = static_cast<nrf_twim_frequency_t>(params.frequency); | ||||
|   config.hold_bus_uninit = false; | ||||
|   config.interrupt_priority = 0; | ||||
|   config.scl = params.pinScl; | ||||
|   config.sda = params.pinSda; | ||||
|   nrfx_twim_init(&twim, | ||||
|                  &config, | ||||
|                  nullptr, | ||||
|                  nullptr); | ||||
|   nrfx_twim_enable(&twim); | ||||
| 
 | ||||
|   xSemaphoreGive(mutex); | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data, size_t size) { | ||||
|   xSemaphoreTake(mutex, portMAX_DELAY);   | ||||
|   auto ret = ReadWithRetry(deviceAddress, registerAddress, data, size); | ||||
|   xSemaphoreTake(mutex, portMAX_DELAY); | ||||
|   TwiMaster::ErrorCodes ret; | ||||
| 
 | ||||
|   auto err = nrfx_twim_tx(&twim, deviceAddress, ®isterAddress, 1, false); | ||||
|   if(err != 0) { | ||||
|     return TwiMaster::ErrorCodes::TransactionFailed; | ||||
|   } | ||||
| 
 | ||||
|   err = nrfx_twim_rx(&twim, deviceAddress, data, size); | ||||
|   if(err != 0) { | ||||
|     return TwiMaster::ErrorCodes::TransactionFailed; | ||||
|   } | ||||
|   xSemaphoreGive(mutex); | ||||
| 
 | ||||
|   return ret; | ||||
|   return TwiMaster::ErrorCodes::NoError; | ||||
| } | ||||
| 
 | ||||
| TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t *data, size_t size) { | ||||
|   ASSERT(size <= maxDataSize); | ||||
|   xSemaphoreTake(mutex, portMAX_DELAY); | ||||
| 
 | ||||
|   auto ret = WriteWithRetry(deviceAddress, registerAddress, data, size); | ||||
|   xSemaphoreGive(mutex); | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| /* Execute a read transaction (composed of a write and a read operation). If one of these opeartion fails,
 | ||||
|  * it's retried once. If it fails again, an error is returned */ | ||||
| TwiMaster::ErrorCodes TwiMaster::ReadWithRetry(uint8_t deviceAddress, uint8_t registerAddress, uint8_t *data, size_t size) { | ||||
|   TwiMaster::ErrorCodes ret; | ||||
|   ret = Write(deviceAddress, ®isterAddress, 1, false); | ||||
|   if(ret != ErrorCodes::NoError) | ||||
|     ret = Write(deviceAddress, ®isterAddress, 1, false); | ||||
| 
 | ||||
|   if(ret != ErrorCodes::NoError) return ret; | ||||
| 
 | ||||
|   ret = Read(deviceAddress, data, size, true); | ||||
|   if(ret != ErrorCodes::NoError) | ||||
|     ret = Read(deviceAddress, data, size, true); | ||||
| 
 | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| /* Execute a write transaction. If it fails, it is retried once. If it fails again, an error is returned. */ | ||||
| TwiMaster::ErrorCodes TwiMaster::WriteWithRetry(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t *data, size_t size) { | ||||
|   internalBuffer[0] = registerAddress; | ||||
|   std::memcpy(internalBuffer+1, data, size); | ||||
|   auto ret = Write(deviceAddress, internalBuffer, size+1, true); | ||||
|   if(ret != ErrorCodes::NoError) | ||||
|     ret = Write(deviceAddress, internalBuffer, size+1, true); | ||||
| 
 | ||||
|   return ret; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t *buffer, size_t size, bool stop) { | ||||
|   twiBaseAddress->ADDRESS = deviceAddress; | ||||
|   twiBaseAddress->TASKS_RESUME = 0x1UL; | ||||
|   twiBaseAddress->RXD.PTR = (uint32_t)buffer; | ||||
|   twiBaseAddress->RXD.MAXCNT = size; | ||||
| 
 | ||||
|   twiBaseAddress->TASKS_STARTRX = 1; | ||||
| 
 | ||||
|   while(!twiBaseAddress->EVENTS_RXSTARTED && !twiBaseAddress->EVENTS_ERROR); | ||||
|   twiBaseAddress->EVENTS_RXSTARTED = 0x0UL; | ||||
| 
 | ||||
|   txStartedCycleCount = DWT->CYCCNT; | ||||
|   uint32_t currentCycleCount; | ||||
|   while(!twiBaseAddress->EVENTS_LASTRX && !twiBaseAddress->EVENTS_ERROR) { | ||||
|     currentCycleCount = DWT->CYCCNT; | ||||
|     if ((currentCycleCount-txStartedCycleCount) > HwFreezedDelay) { | ||||
|       FixHwFreezed(); | ||||
|       return ErrorCodes::TransactionFailed; | ||||
|     } | ||||
|   } | ||||
|   twiBaseAddress->EVENTS_LASTRX = 0x0UL; | ||||
| 
 | ||||
|   if (stop || twiBaseAddress->EVENTS_ERROR) { | ||||
|     twiBaseAddress->TASKS_STOP = 0x1UL; | ||||
|     while(!twiBaseAddress->EVENTS_STOPPED); | ||||
|     twiBaseAddress->EVENTS_STOPPED = 0x0UL; | ||||
|   } | ||||
|   else { | ||||
|     twiBaseAddress->TASKS_SUSPEND = 0x1UL; | ||||
|     while(!twiBaseAddress->EVENTS_SUSPENDED); | ||||
|     twiBaseAddress->EVENTS_SUSPENDED = 0x0UL; | ||||
|   auto err = nrfx_twim_tx(&twim, deviceAddress, internalBuffer , size+1, false); | ||||
|   if(err != 0){ | ||||
|     return TwiMaster::ErrorCodes::TransactionFailed; | ||||
|   } | ||||
| 
 | ||||
|   if (twiBaseAddress->EVENTS_ERROR) { | ||||
|     twiBaseAddress->EVENTS_ERROR = 0x0UL; | ||||
|   } | ||||
|   return ErrorCodes::NoError; | ||||
| } | ||||
| 
 | ||||
| TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, const uint8_t *data, size_t size, bool stop) { | ||||
|   twiBaseAddress->ADDRESS = deviceAddress; | ||||
|   twiBaseAddress->TASKS_RESUME = 0x1UL; | ||||
|   twiBaseAddress->TXD.PTR = (uint32_t)data; | ||||
|   twiBaseAddress->TXD.MAXCNT = size; | ||||
| 
 | ||||
|   twiBaseAddress->TASKS_STARTTX = 1; | ||||
| 
 | ||||
|   while(!twiBaseAddress->EVENTS_TXSTARTED && !twiBaseAddress->EVENTS_ERROR); | ||||
|   twiBaseAddress->EVENTS_TXSTARTED = 0x0UL; | ||||
| 
 | ||||
|   txStartedCycleCount = DWT->CYCCNT; | ||||
|   uint32_t currentCycleCount; | ||||
|   while(!twiBaseAddress->EVENTS_LASTTX && !twiBaseAddress->EVENTS_ERROR) { | ||||
|     currentCycleCount = DWT->CYCCNT; | ||||
|     if ((currentCycleCount-txStartedCycleCount) > HwFreezedDelay) { | ||||
|       FixHwFreezed(); | ||||
|       return ErrorCodes::TransactionFailed; | ||||
|     } | ||||
|   } | ||||
|   twiBaseAddress->EVENTS_LASTTX = 0x0UL; | ||||
| 
 | ||||
|   if (stop || twiBaseAddress->EVENTS_ERROR) { | ||||
|     twiBaseAddress->TASKS_STOP = 0x1UL; | ||||
|     while(!twiBaseAddress->EVENTS_STOPPED); | ||||
|     twiBaseAddress->EVENTS_STOPPED = 0x0UL; | ||||
|   } | ||||
|   else { | ||||
|     twiBaseAddress->TASKS_SUSPEND = 0x1UL; | ||||
|     while(!twiBaseAddress->EVENTS_SUSPENDED); | ||||
|     twiBaseAddress->EVENTS_SUSPENDED = 0x0UL; | ||||
|   } | ||||
| 
 | ||||
|   if (twiBaseAddress->EVENTS_ERROR) { | ||||
|     twiBaseAddress->EVENTS_ERROR = 0x0UL; | ||||
|     uint32_t error = twiBaseAddress->ERRORSRC; | ||||
|     twiBaseAddress->ERRORSRC = error; | ||||
|   } | ||||
| 
 | ||||
|   return ErrorCodes::NoError; | ||||
|   xSemaphoreGive(mutex); | ||||
|   return TwiMaster::ErrorCodes::NoError; | ||||
| } | ||||
| 
 | ||||
| void TwiMaster::Sleep() { | ||||
|   while(twiBaseAddress->ENABLE != 0) { | ||||
|     twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos); | ||||
|   } | ||||
|   nrfx_twim_disable(&twim); | ||||
|   nrfx_twim_uninit(&twim); | ||||
| 
 | ||||
|   nrf_gpio_cfg_default(6); | ||||
|   nrf_gpio_cfg_default(7); | ||||
|   NRF_LOG_INFO("[TWIMASTER] Sleep"); | ||||
| @ -201,30 +82,3 @@ void TwiMaster::Wakeup() { | ||||
|   Init(); | ||||
|   NRF_LOG_INFO("[TWIMASTER] Wakeup"); | ||||
| } | ||||
| 
 | ||||
| /* Sometimes, the TWIM device just freeze and never set the event EVENTS_LASTTX.
 | ||||
|  * This method disable and re-enable the peripheral so that it works again. | ||||
|  * This is just a workaround, and it would be better if we could find a way to prevent | ||||
|  * this issue from happening. | ||||
|  * */ | ||||
| void TwiMaster::FixHwFreezed() { | ||||
|   NRF_LOG_INFO("I2C device frozen, reinitializing it!"); | ||||
|   // Disable I²C
 | ||||
|   uint32_t twi_state = NRF_TWI1->ENABLE; | ||||
|   twiBaseAddress->ENABLE = TWIM_ENABLE_ENABLE_Disabled << TWI_ENABLE_ENABLE_Pos; | ||||
| 
 | ||||
|   NRF_GPIO->PIN_CNF[params.pinScl] = ((uint32_t)GPIO_PIN_CNF_DIR_Input      << GPIO_PIN_CNF_DIR_Pos) | ||||
|                          | ((uint32_t)GPIO_PIN_CNF_INPUT_Connect    << GPIO_PIN_CNF_INPUT_Pos) | ||||
|                          | ((uint32_t)GPIO_PIN_CNF_PULL_Pullup      << GPIO_PIN_CNF_PULL_Pos) | ||||
|                          | ((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1       << GPIO_PIN_CNF_DRIVE_Pos) | ||||
|                          | ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled   << GPIO_PIN_CNF_SENSE_Pos); | ||||
| 
 | ||||
|   NRF_GPIO->PIN_CNF[params.pinSda] = ((uint32_t)GPIO_PIN_CNF_DIR_Input        << GPIO_PIN_CNF_DIR_Pos) | ||||
|                          | ((uint32_t)GPIO_PIN_CNF_INPUT_Connect    << GPIO_PIN_CNF_INPUT_Pos) | ||||
|                          | ((uint32_t)GPIO_PIN_CNF_PULL_Pullup      << GPIO_PIN_CNF_PULL_Pos) | ||||
|                          | ((uint32_t)GPIO_PIN_CNF_DRIVE_S0S1       << GPIO_PIN_CNF_DRIVE_Pos) | ||||
|                          | ((uint32_t)GPIO_PIN_CNF_SENSE_Disabled   << GPIO_PIN_CNF_SENSE_Pos); | ||||
| 
 | ||||
|   // Re-enable I²C
 | ||||
|   twiBaseAddress->ENABLE = twi_state; | ||||
| } | ||||
|  | ||||
| @ -3,13 +3,13 @@ | ||||
| #include <semphr.h> | ||||
| #include <drivers/include/nrfx_twi.h> // NRF_TWIM_Type | ||||
| #include <cstdint> | ||||
| #include <nrfx_twim.h> | ||||
| 
 | ||||
| namespace Pinetime { | ||||
|   namespace Drivers { | ||||
|     class TwiMaster { | ||||
|       public: | ||||
|         enum class Modules { TWIM1 }; | ||||
|         enum class Frequencies {Khz100, Khz250, Khz400}; | ||||
|         enum class ErrorCodes {NoError, TransactionFailed}; | ||||
|         struct Parameters { | ||||
|           uint32_t frequency; | ||||
| @ -27,21 +27,13 @@ namespace Pinetime { | ||||
|         void Wakeup(); | ||||
| 
 | ||||
|       private: | ||||
|         ErrorCodes ReadWithRetry(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, size_t size); | ||||
|         ErrorCodes WriteWithRetry(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t* data, size_t size); | ||||
| 
 | ||||
|         ErrorCodes Read(uint8_t deviceAddress, uint8_t* buffer, size_t size, bool stop); | ||||
|         ErrorCodes Write(uint8_t deviceAddress, const uint8_t* data, size_t size, bool stop); | ||||
|         void FixHwFreezed(); | ||||
|         NRF_TWIM_Type* twiBaseAddress; | ||||
|         SemaphoreHandle_t mutex; | ||||
|         nrfx_twim_t twim; | ||||
|         const Modules module; | ||||
|         const Parameters params; | ||||
|         SemaphoreHandle_t mutex; | ||||
|         static constexpr uint8_t maxDataSize{8}; | ||||
|         static constexpr uint8_t registerSize{1}; | ||||
|         uint8_t internalBuffer[maxDataSize + registerSize]; | ||||
|         uint32_t txStartedCycleCount = 0; | ||||
|         static constexpr uint32_t HwFreezedDelay{161000}; | ||||
|     }; | ||||
|   } | ||||
| } | ||||
| @ -26,6 +26,7 @@ | ||||
| #include <task.h> | ||||
| #include <timers.h> | ||||
| #include <drivers/Hrs3300.h> | ||||
| #include <drivers/Bma421.h> | ||||
| 
 | ||||
| #include "components/battery/BatteryController.h" | ||||
| #include "components/ble/BleController.h" | ||||
| @ -60,6 +61,7 @@ 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; | ||||
| 
 | ||||
| Pinetime::Drivers::SpiMaster spi{Pinetime::Drivers::SpiMaster::SpiModule::SPI0, { | ||||
| @ -98,14 +100,13 @@ static constexpr bool isFactory = false; | ||||
| Pinetime::Components::LittleVgl lvgl {lcd, touchPanel}; | ||||
| #endif | ||||
| 
 | ||||
| 
 | ||||
| Pinetime::Drivers::Bma421 motionSensor{twiMaster, motionSensorTwiAddress}; | ||||
| Pinetime::Drivers::Hrs3300 heartRateSensor {twiMaster, heartRateSensorTwiAddress}; | ||||
| 
 | ||||
| 
 | ||||
| TimerHandle_t debounceTimer; | ||||
| Pinetime::Controllers::Battery batteryController; | ||||
| Pinetime::Controllers::Ble bleController; | ||||
| Pinetime::Controllers::DateTime dateTimeController; | ||||
| void ble_manager_set_ble_connection_callback(void (*connection)()); | ||||
| void ble_manager_set_ble_disconnection_callback(void (*disconnection)()); | ||||
| static constexpr uint8_t pinTouchIrq = 28; | ||||
| @ -257,7 +258,7 @@ int main(void) { | ||||
|   debounceTimer = xTimerCreate ("debounceTimer", 200, pdFALSE, (void *) 0, DebounceTimerCallback); | ||||
| 
 | ||||
|   systemTask = std::make_unique<Pinetime::System::SystemTask>(spi, lcd, spiNorFlash, twiMaster, touchPanel, lvgl, batteryController, bleController, | ||||
|                                                     dateTimeController, motorController, heartRateSensor, settingsController); | ||||
|                                                     motorController, heartRateSensor, motionSensor, settingsController); | ||||
|   systemTask->Start(); | ||||
|   nimble_port_init(); | ||||
| 
 | ||||
|  | ||||
| @ -4992,7 +4992,7 @@ | ||||
| // <e> NRFX_TWIM_ENABLED - nrfx_twim - TWIM peripheral driver
 | ||||
| //==========================================================
 | ||||
| #ifndef NRFX_TWIM_ENABLED | ||||
| #define NRFX_TWIM_ENABLED 0 | ||||
| #define NRFX_TWIM_ENABLED 1 | ||||
| #endif | ||||
| // <q> NRFX_TWIM0_ENABLED  - Enable TWIM0 instance
 | ||||
| 
 | ||||
| @ -5005,7 +5005,7 @@ | ||||
| 
 | ||||
| 
 | ||||
| #ifndef NRFX_TWIM1_ENABLED | ||||
| #define NRFX_TWIM1_ENABLED 0 | ||||
| #define NRFX_TWIM1_ENABLED 1 | ||||
| #endif | ||||
| 
 | ||||
| // <o> NRFX_TWIM_DEFAULT_CONFIG_FREQUENCY  - Frequency
 | ||||
|  | ||||
| @ -40,16 +40,16 @@ SystemTask::SystemTask(Drivers::SpiMaster &spi, Drivers::St7789 &lcd, | ||||
|                        Drivers::TwiMaster& twiMaster, Drivers::Cst816S &touchPanel, | ||||
|                        Components::LittleVgl &lvgl, | ||||
|                        Controllers::Battery &batteryController, Controllers::Ble &bleController, | ||||
|                        Controllers::DateTime &dateTimeController, | ||||
|                        Pinetime::Controllers::MotorController& motorController, | ||||
|                        Pinetime::Drivers::Hrs3300& heartRateSensor, | ||||
|                        Pinetime::Drivers::Bma421& motionSensor, | ||||
|                        Controllers::Settings &settingsController) : | ||||
|                        spi{spi}, lcd{lcd}, spiNorFlash{spiNorFlash}, | ||||
|                        twiMaster{twiMaster}, touchPanel{touchPanel}, lvgl{lvgl}, batteryController{batteryController}, | ||||
|                        heartRateController{*this}, | ||||
|                        bleController{bleController}, dateTimeController{dateTimeController}, | ||||
|                        bleController{bleController}, dateTimeController{*this}, | ||||
|                        watchdog{}, watchdogView{watchdog}, | ||||
|                        motorController{motorController}, heartRateSensor{heartRateSensor}, | ||||
|                        motorController{motorController}, heartRateSensor{heartRateSensor}, motionSensor{motionSensor}, | ||||
|                        settingsController{settingsController}, | ||||
|                        nimbleController(*this, bleController,dateTimeController, notificationManager, batteryController, spiNorFlash, heartRateController) { | ||||
|   systemTasksMsgQueue = xQueueCreate(10, 1); | ||||
| @ -84,13 +84,18 @@ void SystemTask::Work() { | ||||
|   touchPanel.Init(); | ||||
|   batteryController.Init(); | ||||
|   motorController.Init(); | ||||
|   motionSensor.SoftReset(); | ||||
| 
 | ||||
|   // Reset the TWI device because the motion sensor chip most probably crashed it...
 | ||||
|   twiMaster.Sleep(); | ||||
|   twiMaster.Init(); | ||||
| 
 | ||||
|   motionSensor.Init(); | ||||
|   settingsController.Init(); | ||||
| 
 | ||||
| 
 | ||||
|   displayApp =  std::make_unique<Pinetime::Applications::DisplayApp>(lcd, lvgl, touchPanel, batteryController, bleController, | ||||
|                                                           dateTimeController, watchdogView, *this, notificationManager, | ||||
|                                                           heartRateController, settingsController); | ||||
|                                                           heartRateController, settingsController, motionController); | ||||
|   displayApp->Start(); | ||||
| 
 | ||||
|   batteryController.Update(); | ||||
| @ -132,8 +137,10 @@ void SystemTask::Work() { | ||||
|   #pragma clang diagnostic push | ||||
|   #pragma ide diagnostic ignored "EndlessLoop" | ||||
|   while(true) { | ||||
|     UpdateMotion(); | ||||
| 
 | ||||
|     uint8_t msg; | ||||
|     if (xQueueReceive(systemTasksMsgQueue, &msg, isSleeping ? 2500 : 1000)) { | ||||
|     if (xQueueReceive(systemTasksMsgQueue, &msg, 100)) { | ||||
|       batteryController.Update(); | ||||
|       Messages message = static_cast<Messages >(msg); | ||||
|       switch(message) { | ||||
| @ -148,10 +155,10 @@ void SystemTask::Work() { | ||||
|         break; | ||||
|         case Messages::GoToRunning: | ||||
|           spi.Wakeup(); | ||||
|           twiMaster.Wakeup(); | ||||
| 
 | ||||
|           // Double Tap needs the touch screen to be in normal mode
 | ||||
|           if ( settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::DoubleTap ) { | ||||
|             twiMaster.Wakeup(); | ||||
|             touchPanel.Wakeup(); | ||||
|           } | ||||
| 
 | ||||
| @ -168,7 +175,9 @@ void SystemTask::Work() { | ||||
|           isWakingUp = false; | ||||
|           break; | ||||
|         case Messages::TouchWakeUp: { | ||||
|           twiMaster.Wakeup(); | ||||
|           auto touchInfo = touchPanel.GetTouchInfo(); | ||||
|           twiMaster.Sleep(); | ||||
|           if( touchInfo.isTouch and  | ||||
|               ( | ||||
|                 ( touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap and  | ||||
| @ -232,12 +241,17 @@ void SystemTask::Work() { | ||||
|           // Double Tap needs the touch screen to be in normal mode
 | ||||
|           if ( settingsController.getWakeUpMode() != Pinetime::Controllers::Settings::WakeUpMode::DoubleTap ) { | ||||
|             touchPanel.Sleep(); | ||||
|             twiMaster.Sleep(); | ||||
|           } | ||||
|           twiMaster.Sleep(); | ||||
|            | ||||
|           isSleeping = true; | ||||
|           isGoingToSleep = false; | ||||
|           break; | ||||
|         case Messages::OnNewDay: | ||||
|           // We might be sleeping (with TWI device disabled.
 | ||||
|           // Remember we'll have to reset the counter next time we're awake
 | ||||
|           stepCounterMustBeReset = true; | ||||
|           break; | ||||
|         default: break; | ||||
|       } | ||||
|     } | ||||
| @ -262,6 +276,30 @@ void SystemTask::Work() { | ||||
|   // Clear diagnostic suppression
 | ||||
|   #pragma clang diagnostic pop | ||||
| } | ||||
| void SystemTask::UpdateMotion() { | ||||
|   if(isGoingToSleep or isWakingUp) return; | ||||
| 
 | ||||
|   if(isSleeping) | ||||
|     twiMaster.Wakeup(); | ||||
| 
 | ||||
|   if(stepCounterMustBeReset) { | ||||
|     motionSensor.ResetStepCounter(); | ||||
|     stepCounterMustBeReset = false; | ||||
|   } | ||||
| 
 | ||||
|   auto motionValues = motionSensor.Process(); | ||||
|   if(isSleeping) | ||||
|     twiMaster.Sleep(); | ||||
| 
 | ||||
|   motionController.IsSensorOk(motionSensor.IsOk()); | ||||
|   motionController.Update(motionValues.x, | ||||
|                           motionValues.y, | ||||
|                           motionValues.z, | ||||
|                           motionValues.steps); | ||||
|   if (motionController.ShouldWakeUp(isSleeping)) { | ||||
|     GoToRunning(); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void SystemTask::OnButtonPushed() { | ||||
|   if(isGoingToSleep) return; | ||||
| @ -279,6 +317,7 @@ void SystemTask::OnButtonPushed() { | ||||
| } | ||||
| 
 | ||||
| void SystemTask::GoToRunning() { | ||||
|   if(isGoingToSleep or (not isSleeping) or isWakingUp) return; | ||||
|   isWakingUp = true; | ||||
|   PushMessage(Messages::GoToRunning); | ||||
| } | ||||
|  | ||||
| @ -8,6 +8,8 @@ | ||||
| #include <heartratetask/HeartRateTask.h> | ||||
| #include <components/heartrate/HeartRateController.h> | ||||
| #include <components/settings/Settings.h> | ||||
| #include <drivers/Bma421.h> | ||||
| #include <components/motion/MotionController.h> | ||||
| 
 | ||||
| #include "SystemMonitor.h" | ||||
| #include "components/battery/BatteryController.h" | ||||
| @ -38,7 +40,8 @@ namespace Pinetime { | ||||
|     class SystemTask { | ||||
|       public: | ||||
|         enum class Messages {GoToSleep, GoToRunning, TouchWakeUp, OnNewTime, OnNewNotification, OnNewCall, BleConnected, UpdateTimeOut, | ||||
|             BleFirmwareUpdateStarted, BleFirmwareUpdateFinished, OnTouchEvent, OnButtonEvent, OnDisplayTaskSleeping, EnableSleeping, DisableSleeping | ||||
|             BleFirmwareUpdateStarted, BleFirmwareUpdateFinished, OnTouchEvent, OnButtonEvent, OnDisplayTaskSleeping, EnableSleeping, DisableSleeping, | ||||
|             OnNewDay | ||||
|         }; | ||||
| 
 | ||||
|         SystemTask(Drivers::SpiMaster &spi, Drivers::St7789 &lcd, | ||||
| @ -46,9 +49,9 @@ namespace Pinetime { | ||||
|                    Drivers::TwiMaster& twiMaster, Drivers::Cst816S &touchPanel, | ||||
|                    Components::LittleVgl &lvgl, | ||||
|                    Controllers::Battery &batteryController, Controllers::Ble &bleController, | ||||
|                    Controllers::DateTime &dateTimeController, | ||||
|                    Pinetime::Controllers::MotorController& motorController, | ||||
|                    Pinetime::Drivers::Hrs3300& heartRateSensor, | ||||
|                    Pinetime::Drivers::Bma421& motionSensor, | ||||
|                    Controllers::Settings &settingsController); | ||||
| 
 | ||||
| 
 | ||||
| @ -77,7 +80,7 @@ namespace Pinetime { | ||||
|         std::unique_ptr<Pinetime::Applications::HeartRateTask> heartRateApp; | ||||
| 
 | ||||
|         Pinetime::Controllers::Ble& bleController; | ||||
|         Pinetime::Controllers::DateTime& dateTimeController; | ||||
|         Pinetime::Controllers::DateTime dateTimeController; | ||||
|         QueueHandle_t systemTasksMsgQueue; | ||||
|         std::atomic<bool> isSleeping{false}; | ||||
|         std::atomic<bool> isGoingToSleep{false}; | ||||
| @ -87,9 +90,11 @@ namespace Pinetime { | ||||
|         Pinetime::Controllers::NotificationManager notificationManager; | ||||
|         Pinetime::Controllers::MotorController& motorController; | ||||
|         Pinetime::Drivers::Hrs3300& heartRateSensor; | ||||
|         Pinetime::Drivers::Bma421& motionSensor; | ||||
|         Pinetime::Controllers::Settings& settingsController; | ||||
|         Pinetime::Controllers::NimbleController nimbleController; | ||||
|         Controllers::BrightnessController brightnessController; | ||||
|         Pinetime::Controllers::MotionController motionController; | ||||
| 
 | ||||
|         static constexpr uint8_t pinSpiSck = 2; | ||||
|         static constexpr uint8_t pinSpiMosi = 3; | ||||
| @ -108,6 +113,8 @@ namespace Pinetime { | ||||
|         bool doNotGoToSleep = false; | ||||
| 
 | ||||
|         void GoToRunning(); | ||||
|         void UpdateMotion(); | ||||
|         bool stepCounterMustBeReset = false; | ||||
| 
 | ||||
| #if configUSE_TRACE_FACILITY == 1 | ||||
|         SystemMonitor<FreeRtosMonitor> monitor; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user