diff --git a/src/components/motor/MotorController.cpp b/src/components/motor/MotorController.cpp index 4e392416..96963381 100644 --- a/src/components/motor/MotorController.cpp +++ b/src/components/motor/MotorController.cpp @@ -5,14 +5,58 @@ using namespace Pinetime::Controllers; +namespace { + TimerHandle_t vibTimer; + + void PatternStep(TimerHandle_t xTimer) { + /* Vibration pattern format: + * { + * durationOfVibration, + * durationOfPause, + * durationOfVibration, + * durationOfPause, + * ..., + * durationOfVibration, + * zeroTerminator + * } + * + * Patterns can be any length + * The pattern must end with a duration of vibration and a terminator. + */ + + static constexpr uint8_t vibrationPattern[] = {30, 150, 30, 150, 30, 0}; + + static size_t patternPosition = 0; + if (vibrationPattern[patternPosition] != 0 && xTimerChangePeriod(vibTimer, vibrationPattern[patternPosition] << 1, 0) == pdPASS && + xTimerStart(vibTimer, 0) == pdPASS) { + if (patternPosition % 2 == 0) { + nrf_gpio_pin_clear(Pinetime::PinMap::Motor); + } else { + nrf_gpio_pin_set(Pinetime::PinMap::Motor); + } + patternPosition++; + } else { + patternPosition = 0; + nrf_gpio_pin_set(Pinetime::PinMap::Motor); + auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); + motorController->PatternFinished(); + } + } +} + void MotorController::Init() { nrf_gpio_cfg_output(PinMap::Motor); nrf_gpio_pin_set(PinMap::Motor); + vibTimer = xTimerCreate("vibration", 1, pdFALSE, this, PatternStep); shortVib = xTimerCreate("shortVib", 1, pdFALSE, nullptr, StopMotor); longVib = xTimerCreate("longVib", pdMS_TO_TICKS(1000), pdTRUE, this, Ring); } +void MotorController::PatternFinished() { + patternPlaying = false; +} + void MotorController::Ring(TimerHandle_t xTimer) { auto* motorController = static_cast(pvTimerGetTimerID(xTimer)); motorController->RunForDuration(50); @@ -24,6 +68,15 @@ void MotorController::RunForDuration(uint8_t motorDuration) { } } +bool MotorController::StartPattern() { + if (!patternPlaying) { + patternPlaying = true; + PatternStep(vibTimer); + return true; + } + return false; +} + void MotorController::StartRinging() { RunForDuration(50); xTimerStart(longVib, 0); diff --git a/src/components/motor/MotorController.h b/src/components/motor/MotorController.h index 6dea6d1f..2f6ca59b 100644 --- a/src/components/motor/MotorController.h +++ b/src/components/motor/MotorController.h @@ -15,10 +15,13 @@ namespace Pinetime { void RunForDuration(uint8_t motorDuration); void StartRinging(); void StopRinging(); + void PatternFinished(); + bool StartPattern(); private: static void Ring(TimerHandle_t xTimer); static void StopMotor(TimerHandle_t xTimer); + bool patternPlaying; TimerHandle_t shortVib; TimerHandle_t longVib; };