Merge pull request #492 from Riksu9000/new_touch_handler
New touch handler
This commit is contained in:
		
						commit
						969de9a8bc
					
				| @ -495,6 +495,8 @@ list(APPEND SOURCE_FILES | ||||
|         components/heartrate/Biquad.cpp | ||||
|         components/heartrate/Ptagc.cpp | ||||
|         components/heartrate/HeartRateController.cpp | ||||
| 
 | ||||
|         touchhandler/TouchHandler.cpp | ||||
|         ) | ||||
| 
 | ||||
| list(APPEND RECOVERY_SOURCE_FILES | ||||
| @ -552,6 +554,7 @@ list(APPEND RECOVERY_SOURCE_FILES | ||||
|         components/heartrate/Ptagc.cpp | ||||
|         components/motor/MotorController.cpp | ||||
|         components/fs/FS.cpp | ||||
|         touchhandler/TouchHandler.cpp | ||||
|         ) | ||||
| 
 | ||||
| list(APPEND RECOVERYLOADER_SOURCE_FILES | ||||
| @ -660,6 +663,7 @@ set(INCLUDE_FILES | ||||
|         components/heartrate/Ptagc.h | ||||
|         components/heartrate/HeartRateController.h | ||||
|         components/motor/MotorController.h | ||||
|         touchhandler/TouchHandler.h | ||||
|         ) | ||||
| 
 | ||||
| include_directories( | ||||
|  | ||||
| @ -53,29 +53,26 @@ namespace { | ||||
|     return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0; | ||||
|   } | ||||
| 
 | ||||
|   TouchEvents Convert(Pinetime::Drivers::Cst816S::TouchInfos info) { | ||||
|     if (info.isTouch) { | ||||
|       switch (info.gesture) { | ||||
|         case Pinetime::Drivers::Cst816S::Gestures::SingleTap: | ||||
|           return TouchEvents::Tap; | ||||
|         case Pinetime::Drivers::Cst816S::Gestures::LongPress: | ||||
|           return TouchEvents::LongTap; | ||||
|         case Pinetime::Drivers::Cst816S::Gestures::DoubleTap: | ||||
|           return TouchEvents::DoubleTap; | ||||
|         case Pinetime::Drivers::Cst816S::Gestures::SlideRight: | ||||
|           return TouchEvents::SwipeRight; | ||||
|         case Pinetime::Drivers::Cst816S::Gestures::SlideLeft: | ||||
|           return TouchEvents::SwipeLeft; | ||||
|         case Pinetime::Drivers::Cst816S::Gestures::SlideDown: | ||||
|           return TouchEvents::SwipeDown; | ||||
|         case Pinetime::Drivers::Cst816S::Gestures::SlideUp: | ||||
|           return TouchEvents::SwipeUp; | ||||
|         case Pinetime::Drivers::Cst816S::Gestures::None: | ||||
|         default: | ||||
|           return TouchEvents::None; | ||||
|       } | ||||
|   TouchEvents ConvertGesture(Pinetime::Drivers::Cst816S::Gestures gesture) { | ||||
|     switch (gesture) { | ||||
|       case Pinetime::Drivers::Cst816S::Gestures::SingleTap: | ||||
|         return TouchEvents::Tap; | ||||
|       case Pinetime::Drivers::Cst816S::Gestures::LongPress: | ||||
|         return TouchEvents::LongTap; | ||||
|       case Pinetime::Drivers::Cst816S::Gestures::DoubleTap: | ||||
|         return TouchEvents::DoubleTap; | ||||
|       case Pinetime::Drivers::Cst816S::Gestures::SlideRight: | ||||
|         return TouchEvents::SwipeRight; | ||||
|       case Pinetime::Drivers::Cst816S::Gestures::SlideLeft: | ||||
|         return TouchEvents::SwipeLeft; | ||||
|       case Pinetime::Drivers::Cst816S::Gestures::SlideDown: | ||||
|         return TouchEvents::SwipeDown; | ||||
|       case Pinetime::Drivers::Cst816S::Gestures::SlideUp: | ||||
|         return TouchEvents::SwipeUp; | ||||
|       case Pinetime::Drivers::Cst816S::Gestures::None: | ||||
|       default: | ||||
|         return TouchEvents::None; | ||||
|     } | ||||
|     return TouchEvents::None; | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @ -91,7 +88,8 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, | ||||
|                        Controllers::Settings& settingsController, | ||||
|                        Pinetime::Controllers::MotorController& motorController, | ||||
|                        Pinetime::Controllers::MotionController& motionController, | ||||
|                        Pinetime::Controllers::TimerController& timerController) | ||||
|                        Pinetime::Controllers::TimerController& timerController, | ||||
|                        Pinetime::Controllers::TouchHandler& touchHandler) | ||||
|   : lcd {lcd}, | ||||
|     lvgl {lvgl}, | ||||
|     touchPanel {touchPanel}, | ||||
| @ -104,7 +102,8 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd, | ||||
|     settingsController {settingsController}, | ||||
|     motorController {motorController}, | ||||
|     motionController {motionController}, | ||||
|     timerController {timerController} { | ||||
|     timerController {timerController}, | ||||
|     touchHandler {touchHandler} { | ||||
| } | ||||
| 
 | ||||
| void DisplayApp::Start() { | ||||
| @ -212,8 +211,7 @@ void DisplayApp::Refresh() { | ||||
|         if (state != States::Running) { | ||||
|           break; | ||||
|         } | ||||
|         auto info = touchPanel.GetTouchInfo(); | ||||
|         auto gesture = Convert(info); | ||||
|         auto gesture = ConvertGesture(touchHandler.GestureGet()); | ||||
|         if (gesture == TouchEvents::None) { | ||||
|           break; | ||||
|         } | ||||
| @ -239,11 +237,9 @@ void DisplayApp::Refresh() { | ||||
|             LoadApp(returnToApp, returnDirection); | ||||
|             brightnessController.Set(settingsController.GetBrightness()); | ||||
|             brightnessController.Backup(); | ||||
|           } else if (touchMode == TouchModes::Gestures) { | ||||
|             if (gesture == TouchEvents::Tap) { | ||||
|               lvgl.SetNewTapEvent(info.x, info.y); | ||||
|             } | ||||
|           } | ||||
|         } else { | ||||
|           touchHandler.CancelTap(); | ||||
|         } | ||||
|       } break; | ||||
|       case Messages::ButtonPushed: | ||||
| @ -273,13 +269,8 @@ void DisplayApp::Refresh() { | ||||
|     nextApp = Apps::None; | ||||
|   } | ||||
| 
 | ||||
|   if (state != States::Idle && touchMode == TouchModes::Polling) { | ||||
|     auto info = touchPanel.GetTouchInfo(); | ||||
|     if (info.action == 2) { // 2 = contact
 | ||||
|       if (!currentScreen->OnTouchEvent(info.x, info.y)) { | ||||
|         lvgl.SetNewTapEvent(info.x, info.y); | ||||
|       } | ||||
|     } | ||||
|   if (touchHandler.IsTouching()) { | ||||
|     currentScreen->OnTouchEvent(touchHandler.GetX(), touchHandler.GetY()); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| @ -302,6 +293,7 @@ void DisplayApp::ReturnApp(Apps app, DisplayApp::FullRefreshDirections direction | ||||
| } | ||||
| 
 | ||||
| void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) { | ||||
|   touchHandler.CancelTap(); | ||||
|   currentScreen.reset(nullptr); | ||||
|   SetFullRefresh(direction); | ||||
| 
 | ||||
| @ -467,10 +459,6 @@ void DisplayApp::SetFullRefresh(DisplayApp::FullRefreshDirections direction) { | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void DisplayApp::SetTouchMode(DisplayApp::TouchModes mode) { | ||||
|   touchMode = mode; | ||||
| } | ||||
| 
 | ||||
| void DisplayApp::PushMessageToSystemTask(Pinetime::System::Messages message) { | ||||
|   if (systemTask != nullptr) | ||||
|     systemTask->PushMessage(message); | ||||
|  | ||||
| @ -14,6 +14,7 @@ | ||||
| #include "components/settings/Settings.h" | ||||
| #include "displayapp/screens/Screen.h" | ||||
| #include "components/timer/TimerController.h" | ||||
| #include "touchhandler/TouchHandler.h" | ||||
| #include "Messages.h" | ||||
| 
 | ||||
| namespace Pinetime { | ||||
| @ -31,6 +32,7 @@ namespace Pinetime { | ||||
|     class NotificationManager; | ||||
|     class HeartRateController; | ||||
|     class MotionController; | ||||
|     class TouchHandler; | ||||
|   } | ||||
| 
 | ||||
|   namespace System { | ||||
| @ -41,7 +43,6 @@ namespace Pinetime { | ||||
|     public: | ||||
|       enum class States { Idle, Running }; | ||||
|       enum class FullRefreshDirections { None, Up, Down, Left, Right, LeftAnim, RightAnim }; | ||||
|       enum class TouchModes { Gestures, Polling }; | ||||
| 
 | ||||
|       DisplayApp(Drivers::St7789& lcd, | ||||
|                  Components::LittleVgl& lvgl, | ||||
| @ -55,14 +56,14 @@ namespace Pinetime { | ||||
|                  Controllers::Settings& settingsController, | ||||
|                  Pinetime::Controllers::MotorController& motorController, | ||||
|                  Pinetime::Controllers::MotionController& motionController, | ||||
|                  Pinetime::Controllers::TimerController& timerController); | ||||
|                  Pinetime::Controllers::TimerController& timerController, | ||||
|                  Pinetime::Controllers::TouchHandler& touchHandler); | ||||
|       void Start(); | ||||
|       void PushMessage(Display::Messages msg); | ||||
| 
 | ||||
|       void StartApp(Apps app, DisplayApp::FullRefreshDirections direction); | ||||
| 
 | ||||
|       void SetFullRefresh(FullRefreshDirections direction); | ||||
|       void SetTouchMode(TouchModes mode); | ||||
| 
 | ||||
|       void Register(Pinetime::System::SystemTask* systemTask); | ||||
| 
 | ||||
| @ -81,6 +82,7 @@ namespace Pinetime { | ||||
|       Pinetime::Controllers::MotorController& motorController; | ||||
|       Pinetime::Controllers::MotionController& motionController; | ||||
|       Pinetime::Controllers::TimerController& timerController; | ||||
|       Pinetime::Controllers::TouchHandler& touchHandler; | ||||
| 
 | ||||
|       Pinetime::Controllers::FirmwareValidator validator; | ||||
|       Controllers::BrightnessController brightnessController; | ||||
| @ -100,8 +102,7 @@ namespace Pinetime { | ||||
|       FullRefreshDirections returnDirection = FullRefreshDirections::None; | ||||
|       TouchEvents returnTouchEvent = TouchEvents::None; | ||||
| 
 | ||||
|       TouchModes touchMode = TouchModes::Gestures; | ||||
| 
 | ||||
|       TouchEvents GetGesture(); | ||||
|       void RunningState(); | ||||
|       void IdleState(); | ||||
|       static void Process(void* instance); | ||||
|  | ||||
| @ -166,43 +166,21 @@ void LittleVgl::FlushDisplay(const lv_area_t* area, lv_color_t* color_p) { | ||||
|   lv_disp_flush_ready(&disp_drv); | ||||
| } | ||||
| 
 | ||||
| void LittleVgl::SetNewTapEvent(uint16_t x, uint16_t y) { | ||||
| void LittleVgl::SetNewTouchPoint(uint16_t x, uint16_t y, bool contact) { | ||||
|   tap_x = x; | ||||
|   tap_y = y; | ||||
|   tapped = true; | ||||
|   tapped = contact; | ||||
| } | ||||
| 
 | ||||
| bool LittleVgl::GetTouchPadInfo(lv_indev_data_t* ptr) { | ||||
|   ptr->point.x = tap_x; | ||||
|   ptr->point.y = tap_y; | ||||
|   if (tapped) { | ||||
|     ptr->point.x = tap_x; | ||||
|     ptr->point.y = tap_y; | ||||
|     ptr->state = LV_INDEV_STATE_PR; | ||||
|     tapped = false; | ||||
|   } else { | ||||
|     ptr->state = LV_INDEV_STATE_REL; | ||||
|   } | ||||
|   return false; | ||||
|   /*
 | ||||
|   auto info = touchPanel.GetTouchInfo(); | ||||
| 
 | ||||
|   if((previousClick.x != info.x || previousClick.y != info.y) && | ||||
|           (info.gesture == Drivers::Cst816S::Gestures::SingleTap)) { | ||||
|     // TODO For an unknown reason, the first touch is taken twice into account.
 | ||||
|     // 'firstTouch' is a quite'n'dirty workaound until I find a better solution
 | ||||
|     if(firstTouch) ptr->state = LV_INDEV_STATE_REL; | ||||
|     else ptr->state = LV_INDEV_STATE_PR; | ||||
|     firstTouch = false; | ||||
|     previousClick.x = info.x; | ||||
|     previousClick.y = info.y; | ||||
|   } | ||||
|   else { | ||||
|     ptr->state = LV_INDEV_STATE_REL; | ||||
|   } | ||||
| 
 | ||||
|   ptr->point.x = info.x; | ||||
|   ptr->point.y = info.y; | ||||
|   return false; | ||||
|    */ | ||||
| } | ||||
| 
 | ||||
| void LittleVgl::InitTheme() { | ||||
|  | ||||
| @ -24,7 +24,7 @@ namespace Pinetime { | ||||
|       void FlushDisplay(const lv_area_t* area, lv_color_t* color_p); | ||||
|       bool GetTouchPadInfo(lv_indev_data_t* ptr); | ||||
|       void SetFullRefresh(FullRefreshDirections direction); | ||||
|       void SetNewTapEvent(uint16_t x, uint16_t y); | ||||
|       void SetNewTouchPoint(uint16_t x, uint16_t y, bool contact); | ||||
| 
 | ||||
|     private: | ||||
|       void InitDisplay(); | ||||
|  | ||||
| @ -68,10 +68,10 @@ bool FirmwareValidation::Refresh() { | ||||
| } | ||||
| 
 | ||||
| void FirmwareValidation::OnButtonEvent(lv_obj_t* object, lv_event_t event) { | ||||
|   if (object == buttonValidate && event == LV_EVENT_PRESSED) { | ||||
|   if (object == buttonValidate && event == LV_EVENT_CLICKED) { | ||||
|     validator.Validate(); | ||||
|     running = false; | ||||
|   } else if (object == buttonReset && event == LV_EVENT_PRESSED) { | ||||
|   } else if (object == buttonReset && event == LV_EVENT_CLICKED) { | ||||
|     validator.Reset(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -5,13 +5,10 @@ | ||||
| using namespace Pinetime::Applications::Screens; | ||||
| 
 | ||||
| InfiniPaint::InfiniPaint(Pinetime::Applications::DisplayApp* app, Pinetime::Components::LittleVgl& lvgl) : Screen(app), lvgl {lvgl} { | ||||
|   app->SetTouchMode(DisplayApp::TouchModes::Polling); | ||||
|   std::fill(b, b + bufferSize, selectColor); | ||||
| } | ||||
| 
 | ||||
| InfiniPaint::~InfiniPaint() { | ||||
|   // Reset the touchmode
 | ||||
|   app->SetTouchMode(DisplayApp::TouchModes::Gestures); | ||||
|   lv_obj_clean(lv_scr_act()); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -104,7 +104,7 @@ bool List::Refresh() { | ||||
| } | ||||
| 
 | ||||
| void List::OnButtonEvent(lv_obj_t* object, lv_event_t event) { | ||||
|   if (event == LV_EVENT_RELEASED) { | ||||
|   if (event == LV_EVENT_CLICKED) { | ||||
|     for (int i = 0; i < MAXLISTITEMS; i++) { | ||||
|       if (apps[i] != Apps::None && object == itemApps[i]) { | ||||
|         app->StartApp(apps[i], DisplayApp::FullRefreshDirections::Up); | ||||
|  | ||||
| @ -66,12 +66,9 @@ Metronome::Metronome(DisplayApp* app, Controllers::MotorController& motorControl | ||||
|   lv_obj_set_size(playPause, 115, 50); | ||||
|   lv_obj_align(playPause, lv_scr_act(), LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0); | ||||
|   lv_obj_set_style_local_value_str(playPause, LV_BTN_PART_MAIN, LV_STATE_DEFAULT, Symbols::play); | ||||
| 
 | ||||
|   app->SetTouchMode(DisplayApp::TouchModes::Polling); | ||||
| } | ||||
| 
 | ||||
| Metronome::~Metronome() { | ||||
|   app->SetTouchMode(DisplayApp::TouchModes::Gestures); | ||||
|   systemTask.PushMessage(System::Messages::EnableSleeping); | ||||
|   lv_obj_clean(lv_scr_act()); | ||||
| } | ||||
|  | ||||
| @ -5,8 +5,6 @@ | ||||
| using namespace Pinetime::Applications::Screens; | ||||
| 
 | ||||
| Paddle::Paddle(Pinetime::Applications::DisplayApp* app, Pinetime::Components::LittleVgl& lvgl) : Screen(app), lvgl {lvgl} { | ||||
|   app->SetTouchMode(DisplayApp::TouchModes::Polling); | ||||
| 
 | ||||
|   background = lv_obj_create(lv_scr_act(), nullptr); | ||||
|   lv_obj_set_size(background, LV_HOR_RES + 1, LV_VER_RES); | ||||
|   lv_obj_set_pos(background, -1, 0); | ||||
| @ -32,8 +30,6 @@ Paddle::Paddle(Pinetime::Applications::DisplayApp* app, Pinetime::Components::Li | ||||
| } | ||||
| 
 | ||||
| Paddle::~Paddle() { | ||||
|   // Reset the touchmode
 | ||||
|   app->SetTouchMode(DisplayApp::TouchModes::Gestures); | ||||
|   lv_obj_clean(lv_scr_act()); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -64,6 +64,7 @@ namespace Pinetime { | ||||
|         } | ||||
| 
 | ||||
|         /** @return false if the event hasn't been handled by the app, true if it has been handled */ | ||||
|         // Returning true will cancel lvgl tap
 | ||||
|         virtual bool OnTouchEvent(TouchEvents event) { | ||||
|           return false; | ||||
|         } | ||||
|  | ||||
| @ -110,4 +110,4 @@ namespace Pinetime { | ||||
|       }; | ||||
|     } | ||||
|   } | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -161,7 +161,7 @@ bool StopWatch::Refresh() { | ||||
| } | ||||
| 
 | ||||
| void StopWatch::playPauseBtnEventHandler(lv_event_t event) { | ||||
|   if (event != LV_EVENT_PRESSED) { | ||||
|   if (event != LV_EVENT_CLICKED) { | ||||
|     return; | ||||
|   } | ||||
|   if (currentState == States::Init) { | ||||
| @ -174,7 +174,7 @@ void StopWatch::playPauseBtnEventHandler(lv_event_t event) { | ||||
| } | ||||
| 
 | ||||
| void StopWatch::stopLapBtnEventHandler(lv_event_t event) { | ||||
|   if (event != LV_EVENT_PRESSED) { | ||||
|   if (event != LV_EVENT_CLICKED) { | ||||
|     return; | ||||
|   } | ||||
|   // If running, then this button is used to save laps
 | ||||
|  | ||||
| @ -207,7 +207,7 @@ bool SystemInfo::sortById(const TaskStatus_t& lhs, const TaskStatus_t& rhs) { | ||||
| } | ||||
| 
 | ||||
| std::unique_ptr<Screen> SystemInfo::CreateScreen4() { | ||||
|   TaskStatus_t tasksStatus[7]; | ||||
|   TaskStatus_t tasksStatus[10]; | ||||
|   lv_obj_t* infoTask = lv_table_create(lv_scr_act(), NULL); | ||||
|   lv_table_set_col_cnt(infoTask, 4); | ||||
|   lv_table_set_row_cnt(infoTask, 8); | ||||
| @ -222,9 +222,9 @@ std::unique_ptr<Screen> SystemInfo::CreateScreen4() { | ||||
|   lv_table_set_cell_value(infoTask, 0, 3, "Free"); | ||||
|   lv_table_set_col_width(infoTask, 3, 90); | ||||
| 
 | ||||
|   auto nb = uxTaskGetSystemState(tasksStatus, 7, nullptr); | ||||
|   auto nb = uxTaskGetSystemState(tasksStatus, sizeof(tasksStatus) / sizeof(tasksStatus[0]), nullptr); | ||||
|   std::sort(tasksStatus, tasksStatus + nb, sortById); | ||||
|   for (uint8_t i = 0; i < nb; i++) { | ||||
|   for (uint8_t i = 0; i < nb && i < 7; i++) { | ||||
| 
 | ||||
|     lv_table_set_cell_value(infoTask, i + 1, 0, std::to_string(tasksStatus[i].xTaskNumber).c_str()); | ||||
|     char state[2] = {0}; | ||||
|  | ||||
| @ -95,6 +95,7 @@ Tile::Tile(uint8_t screenID, | ||||
|   lv_obj_set_style_local_pad_inner(btnm1, LV_BTNMATRIX_PART_BG, LV_STATE_DEFAULT, 10); | ||||
| 
 | ||||
|   for (uint8_t i = 0; i < 6; i++) { | ||||
|     lv_btnmatrix_set_btn_ctrl(btnm1, i, LV_BTNMATRIX_CTRL_CLICK_TRIG); | ||||
|     if (applications[i].application == Apps::None) { | ||||
|       lv_btnmatrix_set_btn_ctrl(btnm1, i, LV_BTNMATRIX_CTRL_DISABLED); | ||||
|     } | ||||
|  | ||||
| @ -128,12 +128,12 @@ void QuickSettings::UpdateScreen() { | ||||
| } | ||||
| 
 | ||||
| void QuickSettings::OnButtonEvent(lv_obj_t* object, lv_event_t event) { | ||||
|   if (object == btn2 && event == LV_EVENT_PRESSED) { | ||||
|   if (object == btn2 && event == LV_EVENT_CLICKED) { | ||||
| 
 | ||||
|     running = false; | ||||
|     app->StartApp(Apps::FlashLight, DisplayApp::FullRefreshDirections::None); | ||||
| 
 | ||||
|   } else if (object == btn1 && event == LV_EVENT_PRESSED) { | ||||
|   } else if (object == btn1 && event == LV_EVENT_CLICKED) { | ||||
| 
 | ||||
|     brightness.Step(); | ||||
|     lv_label_set_text_static(btn1_lvl, brightness.GetIcon()); | ||||
| @ -150,7 +150,7 @@ void QuickSettings::OnButtonEvent(lv_obj_t* object, lv_event_t event) { | ||||
|       lv_label_set_text_static(btn3_lvl, Symbols::notificationsOff); | ||||
|     } | ||||
| 
 | ||||
|   } else if (object == btn4 && event == LV_EVENT_PRESSED) { | ||||
|   } else if (object == btn4 && event == LV_EVENT_CLICKED) { | ||||
|     running = false; | ||||
|     settingsController.SetSettingsMenu(0); | ||||
|     app->StartApp(Apps::Settings, DisplayApp::FullRefreshDirections::Up); | ||||
|  | ||||
| @ -85,7 +85,7 @@ bool SettingDisplay::Refresh() { | ||||
| } | ||||
| 
 | ||||
| void SettingDisplay::UpdateSelected(lv_obj_t* object, lv_event_t event) { | ||||
|   if (event == LV_EVENT_VALUE_CHANGED) { | ||||
|   if (event == LV_EVENT_CLICKED) { | ||||
|     for (int i = 0; i < optionsTotal; i++) { | ||||
|       if (object == cbOption[i]) { | ||||
|         lv_checkbox_set_checked(cbOption[i], true); | ||||
| @ -110,4 +110,4 @@ void SettingDisplay::UpdateSelected(lv_obj_t* object, lv_event_t event) { | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -40,38 +40,40 @@ void Cst816S::Init() { | ||||
|   */ | ||||
|   static constexpr uint8_t motionMask = 0b00000101; | ||||
|   twiMaster.Write(twiAddress, 0xEC, &motionMask, 1); | ||||
| 
 | ||||
|   /*
 | ||||
|   [7] EnTest - Interrupt pin to test, enable automatic periodic issued after a low pulse. | ||||
|   [6] EnTouch - When a touch is detected, a periodic pulsed Low. | ||||
|   [5] EnChange - Upon detecting a touch state changes, pulsed Low. | ||||
|   [4] EnMotion - When the detected gesture is pulsed Low. | ||||
|   [0] OnceWLP - Press gesture only issue a pulse signal is low. | ||||
|   */ | ||||
|   static constexpr uint8_t irqCtl = 0b01110000; | ||||
|   twiMaster.Write(twiAddress, 0xFA, &irqCtl, 1); | ||||
| } | ||||
| 
 | ||||
| Cst816S::TouchInfos Cst816S::GetTouchInfo() { | ||||
|   Cst816S::TouchInfos info; | ||||
| 
 | ||||
|   auto ret = twiMaster.Read(twiAddress, 0, touchData, sizeof(touchData)); | ||||
|   if (ret != TwiMaster::ErrorCodes::NoError) | ||||
|     return {}; | ||||
|   if (ret != TwiMaster::ErrorCodes::NoError) { | ||||
|     info.isValid = false; | ||||
|     return info; | ||||
|   } | ||||
| 
 | ||||
|   auto nbTouchPoints = touchData[2] & 0x0f; | ||||
| 
 | ||||
|   uint8_t i = 0; | ||||
| 
 | ||||
|   uint8_t pointId = (touchData[touchIdIndex + (touchStep * i)]) >> 4; | ||||
|   if (nbTouchPoints == 0 && pointId == lastTouchId) | ||||
|     return info; | ||||
| 
 | ||||
|   info.isTouch = true; | ||||
| 
 | ||||
|   auto xHigh = touchData[touchXHighIndex + (touchStep * i)] & 0x0f; | ||||
|   auto xLow = touchData[touchXLowIndex + (touchStep * i)]; | ||||
|   auto xHigh = touchData[touchXHighIndex] & 0x0f; | ||||
|   auto xLow = touchData[touchXLowIndex]; | ||||
|   uint16_t x = (xHigh << 8) | xLow; | ||||
| 
 | ||||
|   auto yHigh = touchData[touchYHighIndex + (touchStep * i)] & 0x0f; | ||||
|   auto yLow = touchData[touchYLowIndex + (touchStep * i)]; | ||||
|   auto yHigh = touchData[touchYHighIndex] & 0x0f; | ||||
|   auto yLow = touchData[touchYLowIndex]; | ||||
|   uint16_t y = (yHigh << 8) | yLow; | ||||
| 
 | ||||
|   auto action = touchData[touchEventIndex + (touchStep * i)] >> 6; /* 0 = Down, 1 = Up, 2 = contact*/ | ||||
| 
 | ||||
|   info.x = x; | ||||
|   info.y = y; | ||||
|   info.action = action; | ||||
|   info.touching = (nbTouchPoints > 0); | ||||
|   info.gesture = static_cast<Gestures>(touchData[gestureIndex]); | ||||
| 
 | ||||
|   return info; | ||||
| @ -90,4 +92,4 @@ void Cst816S::Sleep() { | ||||
| void Cst816S::Wakeup() { | ||||
|   Init(); | ||||
|   NRF_LOG_INFO("[TOUCHPANEL] Wakeup"); | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -19,12 +19,9 @@ namespace Pinetime { | ||||
|       struct TouchInfos { | ||||
|         uint16_t x = 0; | ||||
|         uint16_t y = 0; | ||||
|         uint8_t action = 0; | ||||
|         uint8_t finger = 0; | ||||
|         uint8_t pressure = 0; | ||||
|         uint8_t area = 0; | ||||
|         Gestures gesture = Gestures::None; | ||||
|         bool isTouch = false; | ||||
|         bool touching = false; | ||||
|         bool isValid = true; | ||||
|       }; | ||||
| 
 | ||||
|       Cst816S(TwiMaster& twiMaster, uint8_t twiAddress); | ||||
| @ -41,23 +38,24 @@ namespace Pinetime { | ||||
|     private: | ||||
|       static constexpr uint8_t pinIrq = 28; | ||||
|       static constexpr uint8_t pinReset = 10; | ||||
|       static constexpr uint8_t lastTouchId = 0x0f; | ||||
| 
 | ||||
|       // Unused/Unavailable commented out
 | ||||
|       static constexpr uint8_t gestureIndex = 1; | ||||
|       static constexpr uint8_t touchPointNumIndex = 2; | ||||
|       static constexpr uint8_t touchMiscIndex = 8; | ||||
|       static constexpr uint8_t touchXYIndex = 7; | ||||
|       static constexpr uint8_t touchEventIndex = 3; | ||||
|       //static constexpr uint8_t touchEventIndex = 3;
 | ||||
|       static constexpr uint8_t touchXHighIndex = 3; | ||||
|       static constexpr uint8_t touchXLowIndex = 4; | ||||
|       //static constexpr uint8_t touchIdIndex = 5;
 | ||||
|       static constexpr uint8_t touchYHighIndex = 5; | ||||
|       static constexpr uint8_t touchYLowIndex = 6; | ||||
|       static constexpr uint8_t touchIdIndex = 5; | ||||
|       static constexpr uint8_t touchStep = 6; | ||||
|       static constexpr uint8_t gestureIndex = 1; | ||||
|       //static constexpr uint8_t touchStep = 6;
 | ||||
|       //static constexpr uint8_t touchXYIndex = 7;
 | ||||
|       //static constexpr uint8_t touchMiscIndex = 8;
 | ||||
| 
 | ||||
|       uint8_t touchData[10]; | ||||
|       uint8_t touchData[7]; | ||||
|       TwiMaster& twiMaster; | ||||
|       uint8_t twiAddress; | ||||
|     }; | ||||
| 
 | ||||
|   } | ||||
| } | ||||
| } | ||||
|  | ||||
| @ -44,6 +44,7 @@ | ||||
| #include "drivers/TwiMaster.h" | ||||
| #include "drivers/Cst816s.h" | ||||
| #include "systemtask/SystemTask.h" | ||||
| #include "touchhandler/TouchHandler.h" | ||||
| 
 | ||||
| #if NRF_LOG_ENABLED | ||||
|   #include "logging/NrfLogger.h" | ||||
| @ -119,6 +120,7 @@ Pinetime::Drivers::WatchdogView watchdogView(watchdog); | ||||
| Pinetime::Controllers::NotificationManager notificationManager; | ||||
| Pinetime::Controllers::MotionController motionController; | ||||
| Pinetime::Controllers::TimerController timerController; | ||||
| Pinetime::Controllers::TouchHandler touchHandler(touchPanel, lvgl); | ||||
| 
 | ||||
| Pinetime::Controllers::FS fs {spiNorFlash}; | ||||
| Pinetime::Controllers::Settings settingsController {fs}; | ||||
| @ -137,7 +139,8 @@ Pinetime::Applications::DisplayApp displayApp(lcd, | ||||
|                                               settingsController, | ||||
|                                               motorController, | ||||
|                                               motionController, | ||||
|                                               timerController); | ||||
|                                               timerController, | ||||
|                                               touchHandler); | ||||
| 
 | ||||
| Pinetime::System::SystemTask systemTask(spi, | ||||
|                                         lcd, | ||||
| @ -159,7 +162,8 @@ Pinetime::System::SystemTask systemTask(spi, | ||||
|                                         heartRateController, | ||||
|                                         displayApp, | ||||
|                                         heartRateApp, | ||||
|                                         fs); | ||||
|                                         fs, | ||||
|                                         touchHandler); | ||||
| 
 | ||||
| void nrfx_gpiote_evt_handler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) { | ||||
|   if (pin == pinTouchIrq) { | ||||
| @ -324,6 +328,7 @@ int main(void) { | ||||
|   lvgl.Init(); | ||||
| 
 | ||||
|   systemTask.Start(); | ||||
| 
 | ||||
|   nimble_port_init(); | ||||
| 
 | ||||
|   vTaskStartScheduler(); | ||||
|  | ||||
| @ -67,7 +67,8 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi, | ||||
|                        Pinetime::Controllers::HeartRateController& heartRateController, | ||||
|                        Pinetime::Applications::DisplayApp& displayApp, | ||||
|                        Pinetime::Applications::HeartRateTask& heartRateApp, | ||||
|                        Pinetime::Controllers::FS& fs) | ||||
|                        Pinetime::Controllers::FS& fs, | ||||
|                        Pinetime::Controllers::TouchHandler& touchHandler) | ||||
|   : spi {spi}, | ||||
|     lcd {lcd}, | ||||
|     spiNorFlash {spiNorFlash}, | ||||
| @ -79,18 +80,18 @@ SystemTask::SystemTask(Drivers::SpiMaster& spi, | ||||
|     dateTimeController {dateTimeController}, | ||||
|     timerController {timerController}, | ||||
|     watchdog {watchdog}, | ||||
|     notificationManager{notificationManager}, | ||||
|     notificationManager {notificationManager}, | ||||
|     motorController {motorController}, | ||||
|     heartRateSensor {heartRateSensor}, | ||||
|     motionSensor {motionSensor}, | ||||
|     settingsController {settingsController}, | ||||
|     heartRateController{heartRateController}, | ||||
|     motionController{motionController}, | ||||
|     displayApp{displayApp}, | ||||
|     heartRateController {heartRateController}, | ||||
|     motionController {motionController}, | ||||
|     displayApp {displayApp}, | ||||
|     heartRateApp(heartRateApp), | ||||
|     fs{fs}, | ||||
|     fs {fs}, | ||||
|     touchHandler {touchHandler}, | ||||
|     nimbleController(*this, bleController, dateTimeController, notificationManager, batteryController, spiNorFlash, heartRateController) { | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| void SystemTask::Start() { | ||||
| @ -116,7 +117,7 @@ void SystemTask::Work() { | ||||
|   spi.Init(); | ||||
|   spiNorFlash.Init(); | ||||
|   spiNorFlash.Wakeup(); | ||||
|    | ||||
| 
 | ||||
|   fs.Init(); | ||||
| 
 | ||||
|   nimbleController.Init(); | ||||
| @ -241,13 +242,15 @@ void SystemTask::Work() { | ||||
|           break; | ||||
|         case Messages::TouchWakeUp: { | ||||
|           twiMaster.Wakeup(); | ||||
|           auto touchInfo = touchPanel.GetTouchInfo(); | ||||
|           twiMaster.Sleep(); | ||||
|           if (touchInfo.isTouch and ((touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap and | ||||
|                                       settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) or | ||||
|                                      (touchInfo.gesture == Pinetime::Drivers::Cst816S::Gestures::SingleTap and | ||||
|                                       settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap)))) { | ||||
|           touchHandler.GetNewTouchInfo(); | ||||
|           auto gesture = touchHandler.GestureGet(); | ||||
|           if ((gesture == Pinetime::Drivers::Cst816S::Gestures::DoubleTap && | ||||
|                settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) || | ||||
|               (gesture == Pinetime::Drivers::Cst816S::Gestures::SingleTap && | ||||
|                settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::SingleTap))) { | ||||
|             GoToRunning(); | ||||
|           } else { | ||||
|             twiMaster.Sleep(); | ||||
|           } | ||||
|         } break; | ||||
|         case Messages::GoToSleep: | ||||
| @ -294,6 +297,9 @@ void SystemTask::Work() { | ||||
|           xTimerStart(dimTimer, 0); | ||||
|           break; | ||||
|         case Messages::OnTouchEvent: | ||||
|           if (touchHandler.GetNewTouchInfo()) { | ||||
|             touchHandler.UpdateLvglTouchPoint(); | ||||
|           } | ||||
|           ReloadIdleTimer(); | ||||
|           displayApp.PushMessage(Pinetime::Applications::Display::Messages::TouchEvent); | ||||
|           break; | ||||
| @ -326,7 +332,7 @@ void SystemTask::Work() { | ||||
|           break; | ||||
|         case Messages::OnChargingEvent: | ||||
|           motorController.RunForDuration(15); | ||||
| 	  // Battery level is updated on every message - there's no need to do anything
 | ||||
|           // Battery level is updated on every message - there's no need to do anything
 | ||||
|           break; | ||||
| 
 | ||||
|         default: | ||||
| @ -424,14 +430,13 @@ void SystemTask::PushMessage(System::Messages msg) { | ||||
|     isGoingToSleep = true; | ||||
|   } | ||||
| 
 | ||||
|   if(in_isr()) { | ||||
|   if (in_isr()) { | ||||
|     BaseType_t xHigherPriorityTaskWoken; | ||||
|     xHigherPriorityTaskWoken = pdFALSE; | ||||
|     xQueueSendFromISR(systemTasksMsgQueue, &msg, &xHigherPriorityTaskWoken); | ||||
|     if (xHigherPriorityTaskWoken) { | ||||
|       /* Actual macro used here is port specific. */ | ||||
|       portYIELD_FROM_ISR(xHigherPriorityTaskWoken); | ||||
| 
 | ||||
|     } | ||||
|   } else { | ||||
|     xQueueSend(systemTasksMsgQueue, &msg, portMAX_DELAY); | ||||
|  | ||||
| @ -17,6 +17,7 @@ | ||||
| #include "components/motor/MotorController.h" | ||||
| #include "components/timer/TimerController.h" | ||||
| #include "components/fs/FS.h" | ||||
| #include "touchhandler/TouchHandler.h" | ||||
| 
 | ||||
| #ifdef PINETIME_IS_RECOVERY | ||||
|   #include "displayapp/DisplayAppRecovery.h" | ||||
| @ -24,7 +25,7 @@ | ||||
| #else | ||||
|   #include "components/settings/Settings.h" | ||||
|   #include "displayapp/DisplayApp.h" | ||||
|   #include "displayapp/LittleVgl.h"   | ||||
|   #include "displayapp/LittleVgl.h" | ||||
| #endif | ||||
| 
 | ||||
| #include "drivers/Watchdog.h" | ||||
| @ -39,6 +40,9 @@ namespace Pinetime { | ||||
|     class TwiMaster; | ||||
|     class Hrs3300; | ||||
|   } | ||||
|   namespace Controllers { | ||||
|     class TouchHandler; | ||||
|   } | ||||
|   namespace System { | ||||
|     class SystemTask { | ||||
|     public: | ||||
| @ -62,7 +66,8 @@ namespace Pinetime { | ||||
|                  Pinetime::Controllers::HeartRateController& heartRateController, | ||||
|                  Pinetime::Applications::DisplayApp& displayApp, | ||||
|                  Pinetime::Applications::HeartRateTask& heartRateApp, | ||||
|                  Pinetime::Controllers::FS& fs); | ||||
|                  Pinetime::Controllers::FS& fs, | ||||
|                  Pinetime::Controllers::TouchHandler& touchHandler); | ||||
| 
 | ||||
|       void Start(); | ||||
|       void PushMessage(Messages msg); | ||||
| @ -92,7 +97,6 @@ namespace Pinetime { | ||||
|       Pinetime::Components::LittleVgl& lvgl; | ||||
|       Pinetime::Controllers::Battery& batteryController; | ||||
| 
 | ||||
| 
 | ||||
|       Pinetime::Controllers::Ble& bleController; | ||||
|       Pinetime::Controllers::DateTime& dateTimeController; | ||||
|       Pinetime::Controllers::TimerController& timerController; | ||||
| @ -113,6 +117,7 @@ namespace Pinetime { | ||||
|       Pinetime::Applications::DisplayApp& displayApp; | ||||
|       Pinetime::Applications::HeartRateTask& heartRateApp; | ||||
|       Pinetime::Controllers::FS& fs; | ||||
|       Pinetime::Controllers::TouchHandler& touchHandler; | ||||
|       Pinetime::Controllers::NimbleController nimbleController; | ||||
| 
 | ||||
|       static constexpr uint8_t pinSpiSck = 2; | ||||
|  | ||||
							
								
								
									
										65
									
								
								src/touchhandler/TouchHandler.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/touchhandler/TouchHandler.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,65 @@ | ||||
| #include "TouchHandler.h" | ||||
| 
 | ||||
| using namespace Pinetime::Controllers; | ||||
| 
 | ||||
| TouchHandler::TouchHandler(Drivers::Cst816S& touchPanel, Components::LittleVgl& lvgl) : touchPanel {touchPanel}, lvgl {lvgl} { | ||||
| } | ||||
| 
 | ||||
| void TouchHandler::CancelTap() { | ||||
|   if (info.touching) { | ||||
|     isCancelled = true; | ||||
|     lvgl.SetNewTouchPoint(-1, -1, true); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| Pinetime::Drivers::Cst816S::Gestures TouchHandler::GestureGet() { | ||||
|   auto returnGesture = gesture; | ||||
|   gesture = Drivers::Cst816S::Gestures::None; | ||||
|   return returnGesture; | ||||
| } | ||||
| 
 | ||||
| bool TouchHandler::GetNewTouchInfo() { | ||||
|   info = touchPanel.GetTouchInfo(); | ||||
| 
 | ||||
|   if (!info.isValid) { | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   if (info.gesture != Pinetime::Drivers::Cst816S::Gestures::None) { | ||||
|     if (gestureReleased) { | ||||
|       if (info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideDown || | ||||
|           info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideLeft || | ||||
|           info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideUp || | ||||
|           info.gesture == Pinetime::Drivers::Cst816S::Gestures::SlideRight || | ||||
|           info.gesture == Pinetime::Drivers::Cst816S::Gestures::LongPress) { | ||||
|         if (info.touching) { | ||||
|           gesture = info.gesture; | ||||
|           gestureReleased = false; | ||||
|         } | ||||
|       } else { | ||||
|         gesture = info.gesture; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   if (!info.touching) { | ||||
|     gestureReleased = true; | ||||
|   } | ||||
| 
 | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| void TouchHandler::UpdateLvglTouchPoint() { | ||||
|   if (info.touching) { | ||||
|     if (!isCancelled) { | ||||
|       lvgl.SetNewTouchPoint(info.x, info.y, true); | ||||
|     } | ||||
|   } else { | ||||
|     if (isCancelled) { | ||||
|       lvgl.SetNewTouchPoint(-1, -1, false); | ||||
|       isCancelled = false; | ||||
|     } else { | ||||
|       lvgl.SetNewTouchPoint(info.x, info.y, false); | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										45
									
								
								src/touchhandler/TouchHandler.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/touchhandler/TouchHandler.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,45 @@ | ||||
| #pragma once | ||||
| #include "drivers/Cst816s.h" | ||||
| #include "systemtask/SystemTask.h" | ||||
| #include <FreeRTOS.h> | ||||
| #include <task.h> | ||||
| 
 | ||||
| namespace Pinetime { | ||||
|   namespace Components { | ||||
|     class LittleVgl; | ||||
|   } | ||||
|   namespace Drivers { | ||||
|     class Cst816S; | ||||
|   } | ||||
|   namespace System { | ||||
|     class SystemTask; | ||||
|   } | ||||
|   namespace Controllers { | ||||
|     class TouchHandler { | ||||
|       public: | ||||
|         explicit TouchHandler(Drivers::Cst816S&, Components::LittleVgl&); | ||||
|         void CancelTap(); | ||||
|         bool GetNewTouchInfo(); | ||||
|         void UpdateLvglTouchPoint(); | ||||
| 
 | ||||
|         bool IsTouching() const { | ||||
|           return info.touching; | ||||
|         } | ||||
|         uint8_t GetX() const { | ||||
|           return info.x; | ||||
|         } | ||||
|         uint8_t GetY() const { | ||||
|           return info.y; | ||||
|         } | ||||
|         Drivers::Cst816S::Gestures GestureGet(); | ||||
|       private: | ||||
| 
 | ||||
|         Pinetime::Drivers::Cst816S::TouchInfos info; | ||||
|         Pinetime::Drivers::Cst816S& touchPanel; | ||||
|         Pinetime::Components::LittleVgl& lvgl; | ||||
|         Pinetime::Drivers::Cst816S::Gestures gesture; | ||||
|         bool isCancelled = false; | ||||
|         bool gestureReleased = true; | ||||
|     }; | ||||
|   } | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 JF002
						JF002