led_softblink.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /* Copyright (c) 2015 Nordic Semiconductor. All Rights Reserved.
  2. *
  3. * The information contained herein is property of Nordic Semiconductor ASA.
  4. * Terms and conditions of usage are described in detail in NORDIC
  5. * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
  6. *
  7. * Licensees are granted free, non-transferable use of the information. NO
  8. * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
  9. * the file.
  10. *
  11. */
  12. #include <string.h>
  13. #include "led_softblink.h"
  14. #include "nrf_gpio.h"
  15. #include "app_timer.h"
  16. #include "nrf_assert.h"
  17. #include "low_power_pwm.h"
  18. /* Period for LED softblink PWM. */
  19. #define PWM_PERIOD UINT8_MAX
  20. /**@bref Structure to handle timer time-outs
  21. *
  22. */
  23. typedef struct
  24. {
  25. bool leds_is_on; /**< Flag for indicating if LEDs are on. */
  26. bool is_counting_up; /**< Flag for indicating if counter is incrementing or decrementing. */
  27. nrf_drv_state_t led_sb_state; /**< Indicates current state of instance. */
  28. uint16_t duty_cycle; /**< Current pulse width. */
  29. uint32_t bit_mask; /**< Mask of used pins. */
  30. led_sb_init_params_t params; /**< Structure holding initialization parameters. */
  31. low_power_pwm_config_t pwm_config; /**< Structure holding parameters for initializing low level layer. */
  32. low_power_pwm_t pwm_instance; /**< Structure holding low-power PWM instance parameters. */
  33. }led_sb_context_t;
  34. static led_sb_context_t m_led_sb = {0};
  35. /**@brief Timer event handler for softblink.
  36. *
  37. * @param[in] p_context General purpose pointer. Will be passed to the time-out handler
  38. * when the timer expires.
  39. *
  40. */
  41. static void led_softblink_on_timeout(void * p_context)
  42. {
  43. static int32_t pause_ticks;
  44. ASSERT(m_led_sb.led_sb_state != NRF_DRV_STATE_UNINITIALIZED);
  45. ret_code_t err_code;
  46. if(pause_ticks <= 0)
  47. {
  48. if (m_led_sb.is_counting_up)
  49. {
  50. if (m_led_sb.duty_cycle >= (m_led_sb.params.duty_cycle_max - m_led_sb.params.duty_cycle_step))
  51. {
  52. // Max PWM duty cycle is reached, start decrementing.
  53. m_led_sb.is_counting_up = false;
  54. m_led_sb.duty_cycle = m_led_sb.params.duty_cycle_max;
  55. pause_ticks = m_led_sb.params.on_time_ticks ? m_led_sb.params.on_time_ticks + APP_TIMER_MIN_TIMEOUT_TICKS : 0;
  56. }
  57. else
  58. {
  59. m_led_sb.duty_cycle += m_led_sb.params.duty_cycle_step;
  60. }
  61. }
  62. else
  63. {
  64. if (m_led_sb.duty_cycle <= (m_led_sb.params.duty_cycle_min + m_led_sb.params.duty_cycle_step))
  65. {
  66. // Min PWM duty cycle is reached, start incrementing.
  67. m_led_sb.is_counting_up = true;
  68. m_led_sb.duty_cycle = m_led_sb.params.duty_cycle_min;
  69. pause_ticks = m_led_sb.params.off_time_ticks ? m_led_sb.params.off_time_ticks + APP_TIMER_MIN_TIMEOUT_TICKS : 0;
  70. }
  71. else
  72. {
  73. m_led_sb.duty_cycle -= m_led_sb.params.duty_cycle_step;
  74. }
  75. }
  76. }
  77. else
  78. {
  79. pause_ticks -= PWM_PERIOD;
  80. }
  81. err_code = low_power_pwm_duty_set(&m_led_sb.pwm_instance, m_led_sb.duty_cycle);
  82. APP_ERROR_CHECK(err_code);
  83. }
  84. ret_code_t led_softblink_init(led_sb_init_params_t * p_init_params)
  85. {
  86. ret_code_t err_code;
  87. ASSERT(m_led_sb.led_sb_state == NRF_DRV_STATE_UNINITIALIZED);
  88. ASSERT(p_init_params);
  89. if ( (p_init_params->duty_cycle_max == 0) ||
  90. (p_init_params->duty_cycle_max <= p_init_params->duty_cycle_min) ||
  91. (p_init_params->duty_cycle_step == 0) ||
  92. (p_init_params->leds_pin_bm == 0))
  93. {
  94. return NRF_ERROR_INVALID_PARAM;
  95. }
  96. memset(&m_led_sb, 0, sizeof(led_sb_context_t));
  97. memcpy(&m_led_sb.params, p_init_params, sizeof(led_sb_init_params_t));
  98. m_led_sb.is_counting_up = true;
  99. m_led_sb.duty_cycle = p_init_params->duty_cycle_min + p_init_params->duty_cycle_step;
  100. m_led_sb.leds_is_on = false;
  101. m_led_sb.bit_mask = p_init_params->leds_pin_bm;
  102. APP_TIMER_DEF(led_softblink_timer);
  103. m_led_sb.pwm_config.active_high = m_led_sb.params.active_high;
  104. m_led_sb.pwm_config.bit_mask = p_init_params->leds_pin_bm;
  105. m_led_sb.pwm_config.period = PWM_PERIOD;
  106. m_led_sb.pwm_config.p_timer_id = &led_softblink_timer;
  107. err_code = low_power_pwm_init( &m_led_sb.pwm_instance, &m_led_sb.pwm_config, led_softblink_on_timeout);
  108. if (err_code == NRF_SUCCESS)
  109. {
  110. m_led_sb.led_sb_state = NRF_DRV_STATE_INITIALIZED;
  111. }
  112. else
  113. {
  114. return err_code;
  115. }
  116. err_code = low_power_pwm_duty_set( &m_led_sb.pwm_instance, p_init_params->duty_cycle_min + p_init_params->duty_cycle_step);
  117. return err_code;
  118. }
  119. ret_code_t led_softblink_start(uint32_t leds_pin_bit_mask)
  120. {
  121. ret_code_t err_code;
  122. ASSERT(m_led_sb.led_sb_state == NRF_DRV_STATE_INITIALIZED);
  123. err_code = low_power_pwm_start(&m_led_sb.pwm_instance, leds_pin_bit_mask);
  124. return err_code;
  125. }
  126. ret_code_t led_softblink_stop(void)
  127. {
  128. ret_code_t err_code;
  129. err_code = low_power_pwm_stop(&m_led_sb.pwm_instance);
  130. return err_code;
  131. }
  132. void led_softblink_off_time_set(uint32_t off_time_ticks)
  133. {
  134. ASSERT(m_led_sb.led_sb_state != NRF_DRV_STATE_UNINITIALIZED);
  135. m_led_sb.params.off_time_ticks = off_time_ticks;
  136. }
  137. void led_softblink_on_time_set(uint32_t on_time_ticks)
  138. {
  139. ASSERT(m_led_sb.led_sb_state != NRF_DRV_STATE_UNINITIALIZED);
  140. m_led_sb.params.on_time_ticks = on_time_ticks;
  141. }
  142. ret_code_t led_softblink_uninit(void)
  143. {
  144. ASSERT(m_led_sb.led_sb_state != NRF_DRV_STATE_UNINITIALIZED);
  145. ret_code_t err_code;
  146. err_code = led_softblink_stop();
  147. if (err_code == NRF_SUCCESS)
  148. {
  149. m_led_sb.led_sb_state = NRF_DRV_STATE_UNINITIALIZED;
  150. }
  151. else
  152. {
  153. return err_code;
  154. }
  155. memset(&m_led_sb, 0, sizeof(m_led_sb));
  156. return NRF_SUCCESS;
  157. }