Merge branch 'develop' into update_touch_driver
This commit is contained in:
		
						commit
						d2d97319e0
					
				@ -496,6 +496,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
 | 
			
		||||
@ -553,6 +555,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
 | 
			
		||||
@ -661,6 +664,7 @@ set(INCLUDE_FILES
 | 
			
		||||
        components/heartrate/Ptagc.h
 | 
			
		||||
        components/heartrate/HeartRateController.h
 | 
			
		||||
        components/motor/MotorController.h
 | 
			
		||||
        touchhandler/TouchHandler.h
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
include_directories(
 | 
			
		||||
@ -840,7 +844,7 @@ target_compile_options(${EXECUTABLE_NAME} PUBLIC
 | 
			
		||||
 | 
			
		||||
set_target_properties(${EXECUTABLE_NAME} PROPERTIES
 | 
			
		||||
        SUFFIX ".out"
 | 
			
		||||
        LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_FILE_NAME}.map"
 | 
			
		||||
        LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections -Wl,--print-memory-usage --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_FILE_NAME}.map"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
add_custom_command(TARGET ${EXECUTABLE_NAME}
 | 
			
		||||
@ -870,7 +874,7 @@ target_compile_options(${EXECUTABLE_MCUBOOT_NAME} PUBLIC
 | 
			
		||||
 | 
			
		||||
set_target_properties(${EXECUTABLE_MCUBOOT_NAME} PROPERTIES
 | 
			
		||||
        SUFFIX ".out"
 | 
			
		||||
        LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT_MCUBOOT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_MCUBOOT_FILE_NAME}.map"
 | 
			
		||||
        LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT_MCUBOOT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections -Wl,--print-memory-usage --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_MCUBOOT_FILE_NAME}.map"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
add_custom_command(TARGET ${EXECUTABLE_MCUBOOT_NAME}
 | 
			
		||||
@ -907,7 +911,7 @@ target_compile_options(${EXECUTABLE_RECOVERY_NAME} PUBLIC
 | 
			
		||||
 | 
			
		||||
set_target_properties(${EXECUTABLE_RECOVERY_NAME} PROPERTIES
 | 
			
		||||
        SUFFIX ".out"
 | 
			
		||||
        LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_RECOVERY_FILE_NAME}.map"
 | 
			
		||||
        LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections -Wl,--print-memory-usage --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_RECOVERY_FILE_NAME}.map"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
add_custom_command(TARGET ${EXECUTABLE_RECOVERY_NAME}
 | 
			
		||||
@ -937,7 +941,7 @@ target_compile_options(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PUBLIC
 | 
			
		||||
 | 
			
		||||
set_target_properties(${EXECUTABLE_RECOVERY_MCUBOOT_NAME} PROPERTIES
 | 
			
		||||
        SUFFIX ".out"
 | 
			
		||||
        LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_GRAPHICS_FILE_NAME}.map"
 | 
			
		||||
        LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections -Wl,--print-memory-usage --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_GRAPHICS_FILE_NAME}.map"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
add_custom_command(TARGET ${EXECUTABLE_RECOVERY_MCUBOOT_NAME}
 | 
			
		||||
@ -978,7 +982,7 @@ add_dependencies(${EXECUTABLE_RECOVERYLOADER_NAME} ${EXECUTABLE_RECOVERY_MCUBOOT
 | 
			
		||||
 | 
			
		||||
set_target_properties(${EXECUTABLE_RECOVERYLOADER_NAME} PROPERTIES
 | 
			
		||||
        SUFFIX ".out"
 | 
			
		||||
        LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_RECOVERYLOADER_FILE_NAME}.map"
 | 
			
		||||
        LINK_FLAGS "-mthumb -mabi=aapcs -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections -Wl,--print-memory-usage --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_RECOVERYLOADER_FILE_NAME}.map"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
add_custom_command(TARGET ${EXECUTABLE_RECOVERYLOADER_NAME}
 | 
			
		||||
@ -1011,7 +1015,7 @@ add_dependencies(${EXECUTABLE_MCUBOOT_RECOVERYLOADER_NAME} ${EXECUTABLE_RECOVERY
 | 
			
		||||
 | 
			
		||||
set_target_properties(${EXECUTABLE_MCUBOOT_RECOVERYLOADER_NAME} PROPERTIES
 | 
			
		||||
        SUFFIX ".out"
 | 
			
		||||
        LINK_FLAGS "-mthumb -mabi=aapcs -std=gnu++98 -std=c99 -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT_MCUBOOT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_MCUBOOT_RECOVERYLOADER_FILE_NAME}.map"
 | 
			
		||||
        LINK_FLAGS "-mthumb -mabi=aapcs -std=gnu++98 -std=c99 -L ${NRF5_SDK_PATH}/modules/nrfx/mdk -T${NRF5_LINKER_SCRIPT_MCUBOOT} -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Wl,--gc-sections -Wl,--print-memory-usage --specs=nano.specs -lc -lnosys -lm -Wl,-Map=${EXECUTABLE_MCUBOOT_RECOVERYLOADER_FILE_NAME}.map"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
add_custom_command(TARGET ${EXECUTABLE_MCUBOOT_RECOVERYLOADER_NAME}
 | 
			
		||||
 | 
			
		||||
@ -54,29 +54,26 @@ namespace {
 | 
			
		||||
    return (SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  TouchEvents Convert(Pinetime::Drivers::Cst816S::TouchInfos info) {
 | 
			
		||||
    if (info.isValid) {
 | 
			
		||||
      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;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -92,7 +89,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},
 | 
			
		||||
@ -105,7 +103,8 @@ DisplayApp::DisplayApp(Drivers::St7789& lcd,
 | 
			
		||||
    settingsController {settingsController},
 | 
			
		||||
    motorController {motorController},
 | 
			
		||||
    motionController {motionController},
 | 
			
		||||
    timerController {timerController} {
 | 
			
		||||
    timerController {timerController},
 | 
			
		||||
    touchHandler {touchHandler} {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DisplayApp::Start(System::BootErrors error) {
 | 
			
		||||
@ -218,8 +217,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;
 | 
			
		||||
        }
 | 
			
		||||
@ -245,11 +243,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:
 | 
			
		||||
@ -279,13 +275,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());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -308,6 +299,7 @@ void DisplayApp::ReturnApp(Apps app, DisplayApp::FullRefreshDirections direction
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void DisplayApp::LoadApp(Apps app, DisplayApp::FullRefreshDirections direction) {
 | 
			
		||||
  touchHandler.CancelTap();
 | 
			
		||||
  currentScreen.reset(nullptr);
 | 
			
		||||
  SetFullRefresh(direction);
 | 
			
		||||
 | 
			
		||||
@ -478,10 +470,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"
 | 
			
		||||
#include "BootErrors.h"
 | 
			
		||||
 | 
			
		||||
@ -32,6 +33,7 @@ namespace Pinetime {
 | 
			
		||||
    class NotificationManager;
 | 
			
		||||
    class HeartRateController;
 | 
			
		||||
    class MotionController;
 | 
			
		||||
    class TouchHandler;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  namespace System {
 | 
			
		||||
@ -42,7 +44,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,
 | 
			
		||||
@ -56,14 +57,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(System::BootErrors error);
 | 
			
		||||
      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);
 | 
			
		||||
 | 
			
		||||
@ -82,6 +83,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;
 | 
			
		||||
@ -101,8 +103,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);
 | 
			
		||||
 | 
			
		||||
@ -3,6 +3,7 @@
 | 
			
		||||
#include <task.h>
 | 
			
		||||
#include <libraries/log/nrf_log.h>
 | 
			
		||||
#include <components/rle/RleDecoder.h>
 | 
			
		||||
#include <touchhandler/TouchHandler.h>
 | 
			
		||||
#include "displayapp/icons/infinitime/infinitime-nb.c"
 | 
			
		||||
 | 
			
		||||
using namespace Pinetime::Applications;
 | 
			
		||||
@ -19,7 +20,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}, bleController {bleController} {
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -29,6 +29,9 @@ namespace Pinetime {
 | 
			
		||||
  namespace System {
 | 
			
		||||
    class SystemTask;
 | 
			
		||||
  };
 | 
			
		||||
  namespace Controllers {
 | 
			
		||||
    class TouchHandler;
 | 
			
		||||
  }
 | 
			
		||||
  namespace Applications {
 | 
			
		||||
    class DisplayApp {
 | 
			
		||||
    public:
 | 
			
		||||
@ -44,7 +47,8 @@ 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(Pinetime::Applications::Display::Messages msg);
 | 
			
		||||
      void Register(Pinetime::System::SystemTask* systemTask);
 | 
			
		||||
 | 
			
		||||
@ -32,6 +32,9 @@ namespace Pinetime {
 | 
			
		||||
      }
 | 
			
		||||
      void SetNewTapEvent(uint16_t x, uint16_t y) {
 | 
			
		||||
      }
 | 
			
		||||
      void SetNewTouchPoint(uint16_t x, uint16_t y, bool contact) {
 | 
			
		||||
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -292,7 +292,7 @@ bool Music::OnTouchEvent(Pinetime::Applications::TouchEvents event) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
    default: {
 | 
			
		||||
      return true;
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -213,7 +213,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);
 | 
			
		||||
@ -228,9 +228,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) {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -41,6 +41,16 @@ bool 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);
 | 
			
		||||
 | 
			
		||||
  // There's mixed information about which register contains which information
 | 
			
		||||
  if (twiMaster.Read(twiAddress, 0xA7, &chipId, 1) == TwiMaster::ErrorCodes::TransactionFailed) {
 | 
			
		||||
    chipId = 0xFF;
 | 
			
		||||
@ -78,11 +88,8 @@ Cst816S::TouchInfos Cst816S::GetTouchInfo() {
 | 
			
		||||
  auto yLow = touchData[touchYLowIndex];
 | 
			
		||||
  uint16_t y = (yHigh << 8) | yLow;
 | 
			
		||||
 | 
			
		||||
  auto action = touchData[touchEventIndex] >> 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]);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -19,9 +19,8 @@ namespace Pinetime {
 | 
			
		||||
      struct TouchInfos {
 | 
			
		||||
        uint16_t x = 0;
 | 
			
		||||
        uint16_t y = 0;
 | 
			
		||||
        uint8_t action = 0;
 | 
			
		||||
        bool touching = false;
 | 
			
		||||
        Gestures gesture = Gestures::None;
 | 
			
		||||
        bool touching = false;
 | 
			
		||||
        bool isValid = true;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
@ -52,7 +51,7 @@ namespace Pinetime {
 | 
			
		||||
      // Unused/Unavailable commented out
 | 
			
		||||
      static constexpr uint8_t gestureIndex = 1;
 | 
			
		||||
      static constexpr uint8_t touchPointNumIndex = 2;
 | 
			
		||||
      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;
 | 
			
		||||
 | 
			
		||||
@ -8,45 +8,39 @@ 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} {
 | 
			
		||||
TwiMaster::TwiMaster(NRF_TWIM_Type* module, uint32_t frequency, uint8_t pinSda, uint8_t pinScl)
 | 
			
		||||
  : module {module}, frequency {frequency}, pinSda {pinSda}, pinScl {pinScl} {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TwiMaster::ConfigurePins() const {
 | 
			
		||||
  NRF_GPIO->PIN_CNF[pinScl] =
 | 
			
		||||
    (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
 | 
			
		||||
    (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
 | 
			
		||||
    (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
 | 
			
		||||
    (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) |
 | 
			
		||||
    (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
 | 
			
		||||
 | 
			
		||||
  NRF_GPIO->PIN_CNF[pinSda] =
 | 
			
		||||
    (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos) |
 | 
			
		||||
    (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) |
 | 
			
		||||
    (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos) |
 | 
			
		||||
    (GPIO_PIN_CNF_DRIVE_S0D1 << GPIO_PIN_CNF_DRIVE_Pos) |
 | 
			
		||||
    (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TwiMaster::Init() {
 | 
			
		||||
  if(mutex == nullptr)
 | 
			
		||||
  if (mutex == nullptr) {
 | 
			
		||||
    mutex = xSemaphoreCreateBinary();
 | 
			
		||||
  
 | 
			
		||||
  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;
 | 
			
		||||
  }
 | 
			
		||||
  ConfigurePins();
 | 
			
		||||
 | 
			
		||||
  twiBaseAddress->PSEL.SCL = params.pinScl;
 | 
			
		||||
  twiBaseAddress->PSEL.SDA = params.pinSda;
 | 
			
		||||
  twiBaseAddress = module;
 | 
			
		||||
 | 
			
		||||
  twiBaseAddress->FREQUENCY = frequency;
 | 
			
		||||
 | 
			
		||||
  twiBaseAddress->PSEL.SCL = pinScl;
 | 
			
		||||
  twiBaseAddress->PSEL.SDA = pinSda;
 | 
			
		||||
  twiBaseAddress->EVENTS_LASTRX = 0;
 | 
			
		||||
  twiBaseAddress->EVENTS_STOPPED = 0;
 | 
			
		||||
  twiBaseAddress->EVENTS_LASTTX = 0;
 | 
			
		||||
@ -57,19 +51,15 @@ void TwiMaster::Init() {
 | 
			
		||||
 | 
			
		||||
  twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos);
 | 
			
		||||
 | 
			
		||||
  /* // IRQ
 | 
			
		||||
     NVIC_ClearPendingIRQ(_IRQn);
 | 
			
		||||
     NVIC_SetPriority(_IRQn, 2);
 | 
			
		||||
     NVIC_EnableIRQ(_IRQn);
 | 
			
		||||
   */
 | 
			
		||||
 | 
			
		||||
  xSemaphoreGive(mutex);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* data, size_t size) {
 | 
			
		||||
  xSemaphoreTake(mutex, portMAX_DELAY);
 | 
			
		||||
  Wakeup();
 | 
			
		||||
  auto ret = Write(deviceAddress, ®isterAddress, 1, false);
 | 
			
		||||
  ret = Read(deviceAddress, data, size, true);
 | 
			
		||||
  Sleep();
 | 
			
		||||
  xSemaphoreGive(mutex);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
@ -77,9 +67,11 @@ TwiMaster::ErrorCodes TwiMaster::Read(uint8_t deviceAddress, uint8_t registerAdd
 | 
			
		||||
TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, uint8_t registerAddress, const uint8_t* data, size_t size) {
 | 
			
		||||
  ASSERT(size <= maxDataSize);
 | 
			
		||||
  xSemaphoreTake(mutex, portMAX_DELAY);
 | 
			
		||||
  Wakeup();
 | 
			
		||||
  internalBuffer[0] = registerAddress;
 | 
			
		||||
  std::memcpy(internalBuffer + 1, data, size);
 | 
			
		||||
  auto ret = Write(deviceAddress, internalBuffer, size + 1, true);
 | 
			
		||||
  Sleep();
 | 
			
		||||
  xSemaphoreGive(mutex);
 | 
			
		||||
  return ret;
 | 
			
		||||
}
 | 
			
		||||
@ -170,17 +162,11 @@ TwiMaster::ErrorCodes TwiMaster::Write(uint8_t deviceAddress, const uint8_t* dat
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TwiMaster::Sleep() {
 | 
			
		||||
  while (twiBaseAddress->ENABLE != 0) {
 | 
			
		||||
    twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos);
 | 
			
		||||
  }
 | 
			
		||||
  nrf_gpio_cfg_default(6);
 | 
			
		||||
  nrf_gpio_cfg_default(7);
 | 
			
		||||
  NRF_LOG_INFO("[TWIMASTER] Sleep");
 | 
			
		||||
  twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Disabled << TWIM_ENABLE_ENABLE_Pos);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void TwiMaster::Wakeup() {
 | 
			
		||||
  Init();
 | 
			
		||||
  NRF_LOG_INFO("[TWIMASTER] Wakeup");
 | 
			
		||||
  twiBaseAddress->ENABLE = (TWIM_ENABLE_ENABLE_Enabled << TWIM_ENABLE_ENABLE_Pos);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Sometimes, the TWIM device just freeze and never set the event EVENTS_LASTTX.
 | 
			
		||||
@ -190,20 +176,10 @@ void TwiMaster::Wakeup() {
 | 
			
		||||
 * */
 | 
			
		||||
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);
 | 
			
		||||
  Sleep();
 | 
			
		||||
 | 
			
		||||
  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;
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -8,16 +8,9 @@ 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;
 | 
			
		||||
        uint8_t pinSda;
 | 
			
		||||
        uint8_t pinScl;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      TwiMaster(const Modules module, const Parameters& params);
 | 
			
		||||
      TwiMaster(NRF_TWIM_Type* module, uint32_t frequency, uint8_t pinSda, uint8_t pinScl);
 | 
			
		||||
 | 
			
		||||
      void Init();
 | 
			
		||||
      ErrorCodes Read(uint8_t deviceAddress, uint8_t registerAddress, uint8_t* buffer, size_t size);
 | 
			
		||||
@ -30,10 +23,14 @@ namespace Pinetime {
 | 
			
		||||
      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();
 | 
			
		||||
      void ConfigurePins() const;
 | 
			
		||||
 | 
			
		||||
      NRF_TWIM_Type* twiBaseAddress;
 | 
			
		||||
      SemaphoreHandle_t mutex = nullptr;
 | 
			
		||||
      const Modules module;
 | 
			
		||||
      const Parameters params;
 | 
			
		||||
      NRF_TWIM_Type* module;
 | 
			
		||||
      uint32_t frequency;
 | 
			
		||||
      uint8_t pinSda;
 | 
			
		||||
      uint8_t pinScl;
 | 
			
		||||
      static constexpr uint8_t maxDataSize {16};
 | 
			
		||||
      static constexpr uint8_t registerSize {1};
 | 
			
		||||
      uint8_t internalBuffer[maxDataSize + registerSize];
 | 
			
		||||
@ -41,4 +38,4 @@ namespace Pinetime {
 | 
			
		||||
      static constexpr uint32_t HwFreezedDelay {161000};
 | 
			
		||||
    };
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								src/main.cpp
									
									
									
									
									
								
							@ -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"
 | 
			
		||||
@ -83,8 +84,7 @@ Pinetime::Drivers::SpiNorFlash spiNorFlash {flashSpi};
 | 
			
		||||
// respecting correct timings. According to erratas heet, this magic value makes it run
 | 
			
		||||
// at ~390Khz with correct timings.
 | 
			
		||||
static constexpr uint32_t MaxTwiFrequencyWithoutHardwareBug {0x06200000};
 | 
			
		||||
Pinetime::Drivers::TwiMaster twiMaster {Pinetime::Drivers::TwiMaster::Modules::TWIM1,
 | 
			
		||||
                                        Pinetime::Drivers::TwiMaster::Parameters {MaxTwiFrequencyWithoutHardwareBug, pinTwiSda, pinTwiScl}};
 | 
			
		||||
Pinetime::Drivers::TwiMaster twiMaster {NRF_TWIM1, MaxTwiFrequencyWithoutHardwareBug, pinTwiSda, pinTwiScl};
 | 
			
		||||
Pinetime::Drivers::Cst816S touchPanel {twiMaster, touchPanelTwiAddress};
 | 
			
		||||
#ifdef PINETIME_IS_RECOVERY
 | 
			
		||||
static constexpr bool isFactory = true;
 | 
			
		||||
@ -119,6 +119,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 +138,8 @@ Pinetime::Applications::DisplayApp displayApp(lcd,
 | 
			
		||||
                                              settingsController,
 | 
			
		||||
                                              motorController,
 | 
			
		||||
                                              motionController,
 | 
			
		||||
                                              timerController);
 | 
			
		||||
                                              timerController,
 | 
			
		||||
                                              touchHandler);
 | 
			
		||||
 | 
			
		||||
Pinetime::System::SystemTask systemTask(spi,
 | 
			
		||||
                                        lcd,
 | 
			
		||||
@ -159,7 +161,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 +327,7 @@ int main(void) {
 | 
			
		||||
  lvgl.Init();
 | 
			
		||||
 | 
			
		||||
  systemTask.Start();
 | 
			
		||||
 | 
			
		||||
  nimble_port_init();
 | 
			
		||||
 | 
			
		||||
  vTaskStartScheduler();
 | 
			
		||||
 | 
			
		||||
@ -68,7 +68,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},
 | 
			
		||||
@ -80,18 +81,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() {
 | 
			
		||||
@ -119,7 +120,7 @@ void SystemTask::Work() {
 | 
			
		||||
  spi.Init();
 | 
			
		||||
  spiNorFlash.Init();
 | 
			
		||||
  spiNorFlash.Wakeup();
 | 
			
		||||
  
 | 
			
		||||
 | 
			
		||||
  fs.Init();
 | 
			
		||||
 | 
			
		||||
  nimbleController.Init();
 | 
			
		||||
@ -224,7 +225,6 @@ void SystemTask::Work() {
 | 
			
		||||
          break;
 | 
			
		||||
        case Messages::GoToRunning:
 | 
			
		||||
          spi.Wakeup();
 | 
			
		||||
          twiMaster.Wakeup();
 | 
			
		||||
 | 
			
		||||
          // Double Tap needs the touch screen to be in normal mode
 | 
			
		||||
          if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
 | 
			
		||||
@ -245,9 +245,7 @@ void SystemTask::Work() {
 | 
			
		||||
          isDimmed = false;
 | 
			
		||||
          break;
 | 
			
		||||
        case Messages::TouchWakeUp: {
 | 
			
		||||
          twiMaster.Wakeup();
 | 
			
		||||
          auto touchInfo = touchPanel.GetTouchInfo();
 | 
			
		||||
          twiMaster.Sleep();
 | 
			
		||||
          if (touchInfo.isValid 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
 | 
			
		||||
@ -299,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;
 | 
			
		||||
@ -319,7 +320,6 @@ void SystemTask::Work() {
 | 
			
		||||
          if (!settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::DoubleTap)) {
 | 
			
		||||
            touchPanel.Sleep();
 | 
			
		||||
          }
 | 
			
		||||
          twiMaster.Sleep();
 | 
			
		||||
 | 
			
		||||
          isSleeping = true;
 | 
			
		||||
          isGoingToSleep = false;
 | 
			
		||||
@ -331,7 +331,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:
 | 
			
		||||
@ -371,17 +371,12 @@ void SystemTask::UpdateMotion() {
 | 
			
		||||
  if (isSleeping && !settingsController.isWakeUpModeOn(Pinetime::Controllers::Settings::WakeUpMode::RaiseWrist))
 | 
			
		||||
    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);
 | 
			
		||||
@ -429,14 +424,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