diff --git a/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.c b/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.c index a9ea306..5995eb7 100644 --- a/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.c +++ b/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.c @@ -21,6 +21,19 @@ static int8_t _adc_offset = 0; /* Vibration motor timer */ static uint8_t _vibration_motor_timer_id = WM_TIMER_ID_INVALID; +static uint8_t _vibration_strength = 0; + +static struct vibration_pattern_conf +{ + uint16_t vibration_pattern[VIBRATION_PATTERN_SLOTS]; + uint8_t vibration_pattern_index; + bool vibration_pattern_mode; +} _vibration_pattern_conf = +{ + .vibration_pattern = {0}, /* Used to store the pattern itself */ + .vibration_pattern_index = 0, /* Used to iterate over the array */ + .vibration_pattern_mode = false, /* Value used by the timer callback to know if we are in pattern mode */ +}; /* Battery charge controller status */ static battery_controller_status_e _battery_fsm = BATTERY_CONTROLLER_STATUS_DISCHARGING; @@ -50,9 +63,40 @@ struct static void vibration_motor_timer_irq_cb(void *p) { (void)p; - tls_pwm_stop(VIBRATION_MOTOR_PWM_CHANNEL); - tls_gpio_cfg(VIBRATION_MOTOR_ENABLE, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING); - tls_gpio_write(VIBRATION_MOTOR_ENABLE, 0); + + if(!_vibration_pattern_conf.vibration_pattern_mode) + { + tls_pwm_stop(VIBRATION_MOTOR_PWM_CHANNEL); + tls_gpio_cfg(VIBRATION_MOTOR_ENABLE, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING); + tls_gpio_write(VIBRATION_MOTOR_ENABLE, 0); + } + else + { + /* Depending on the index, we may turn the vibration on or off */ + if(++_vibration_pattern_conf.vibration_pattern_index % 2 != 0) /* Odd indexes */ + { + tls_pwm_stop(VIBRATION_MOTOR_PWM_CHANNEL); + tls_gpio_cfg(VIBRATION_MOTOR_ENABLE, WM_GPIO_DIR_OUTPUT, WM_GPIO_ATTR_FLOATING); + tls_gpio_write(VIBRATION_MOTOR_ENABLE, 0); + } + else if(_vibration_pattern_conf.vibration_pattern[_vibration_pattern_conf.vibration_pattern_index]) /* We turn the vibration back on */ + { + wm_pwm0_config(VIBRATION_MOTOR_ENABLE); + tls_pwm_init(VIBRATION_MOTOR_PWM_CHANNEL, 10000, 0, 0); + tls_pwm_duty_set(VIBRATION_MOTOR_PWM_CHANNEL, _vibration_strength); + } + + /* If we are reaching the end of the pattern array, or the current pattern has a length of 0 (meaning the end), exit the function */ + if(_vibration_pattern_conf.vibration_pattern_index >= VIBRATION_PATTERN_SLOTS - 1 || !_vibration_pattern_conf.vibration_pattern[_vibration_pattern_conf.vibration_pattern_index]) + { + _vibration_pattern_conf.vibration_pattern_index = 0; + return; + } + + /* We rearm the timer for the next call */ + tls_timer_change(_vibration_motor_timer_id, _vibration_pattern_conf.vibration_pattern[_vibration_pattern_conf.vibration_pattern_index]); + tls_timer_start(_vibration_motor_timer_id); + } } #if BATTERY_CONTROLLER_STATUS_DETECTION_POLICY == POLL_POLICY && HARDWARE_PLATFORM == SMART_WATCH_PCB @@ -295,6 +339,10 @@ void watch_peripherals_vibrate(uint8_t strength, uint32_t durationMs) { /* No need to do anything if the duration is 0 or if the strength is 0 */ if(!strength || !durationMs) return; + + /* We indicate that we are not working in vibration pattern mode */ + _vibration_pattern_conf.vibration_pattern_mode = false; + /* We start the timer which will stop the vibration after durationMs time */ tls_timer_change(_vibration_motor_timer_id, durationMs); wm_pwm0_config(VIBRATION_MOTOR_ENABLE); @@ -303,6 +351,29 @@ void watch_peripherals_vibrate(uint8_t strength, uint32_t durationMs) tls_timer_start(_vibration_motor_timer_id); } +void watch_peripherals_vibrate_with_pattern(uint8_t strength, uint16_t pattern[VIBRATION_PATTERN_SLOTS]) +{ + if(!pattern || !strength) return; + if(!pattern[0]) return; + + /* We indicate that we are working in vibration pattern mode */ + _vibration_pattern_conf.vibration_pattern_mode = true; + + /* First we copy the provided pattern in our local array */ + memcpy(_vibration_pattern_conf.vibration_pattern, pattern, sizeof _vibration_pattern_conf.vibration_pattern); + /* We reset the iterator index */ + _vibration_pattern_conf.vibration_pattern_index = 0; + _vibration_strength = strength; + /* We start the timer and the vibration */ + tls_timer_change(_vibration_motor_timer_id, _vibration_pattern_conf.vibration_pattern[_vibration_pattern_conf.vibration_pattern_index]); + + wm_pwm0_config(VIBRATION_MOTOR_ENABLE); + tls_pwm_init(VIBRATION_MOTOR_PWM_CHANNEL, 10000, 0, 0); + tls_pwm_duty_set(VIBRATION_MOTOR_PWM_CHANNEL, strength); + + tls_timer_start(_vibration_motor_timer_id); +} + void watch_peripherals_set_brightness(uint8_t brightness) { extern LCDConfig_t LCDConfig; diff --git a/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.h b/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.h index d45a0e7..9f4f454 100644 --- a/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.h +++ b/src/W800_SDK_v1.00.10/app/app_drivers/watch_peripherals/watch_peripherals.h @@ -8,6 +8,8 @@ #include "wm_type_def.h" #include "QMC5883L.h" +#define VIBRATION_PATTERN_SLOTS (8) + typedef enum battery_unit { battery_unit_mv = 0, @@ -83,6 +85,15 @@ battery_controller_status_e watch_peripherals_get_battery_controller_status(void */ void watch_peripherals_vibrate(uint8_t strength, uint32_t durationMs); +/** + * @brief Triggers the vibration motor to vibrate with the specified pattern. + * + * @param strength the vibration strength from 0 to 255 (the same is used for every vibrations) + * @param pattern the vibration pattern : a pointer to an array of size @ref VIBRATION_PATTERN_SLOTS. + * The first duration is the on duration, the second is the off duration and so on. + */ +void watch_peripherals_vibrate_with_pattern(uint8_t strength, uint16_t pattern[VIBRATION_PATTERN_SLOTS]); + /** * @brief Sets the brightness of the LCD display *