gpio_led.cc 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. #include "gpio_led.h"
  2. #include "application.h"
  3. #include "device_state.h"
  4. #include <esp_log.h>
  5. #define TAG "GpioLed"
  6. #define DEFAULT_BRIGHTNESS 50
  7. #define HIGH_BRIGHTNESS 100
  8. #define LOW_BRIGHTNESS 10
  9. #define IDLE_BRIGHTNESS 5
  10. #define SPEAKING_BRIGHTNESS 75
  11. #define UPGRADING_BRIGHTNESS 25
  12. #define ACTIVATING_BRIGHTNESS 35
  13. #define BLINK_INFINITE -1
  14. // GPIO_LED
  15. #define LEDC_LS_TIMER LEDC_TIMER_1
  16. #define LEDC_LS_MODE LEDC_LOW_SPEED_MODE
  17. #define LEDC_LS_CH0_CHANNEL LEDC_CHANNEL_0
  18. #define LEDC_DUTY (8191)
  19. #define LEDC_FADE_TIME (1000)
  20. // GPIO_LED
  21. GpioLed::GpioLed(gpio_num_t gpio)
  22. : GpioLed(gpio, 0, LEDC_LS_TIMER, LEDC_LS_CH0_CHANNEL) {
  23. }
  24. GpioLed::GpioLed(gpio_num_t gpio, int output_invert)
  25. : GpioLed(gpio, output_invert, LEDC_LS_TIMER, LEDC_LS_CH0_CHANNEL) {
  26. }
  27. GpioLed::GpioLed(gpio_num_t gpio, int output_invert, ledc_timer_t timer_num, ledc_channel_t channel) {
  28. // If the gpio is not connected, you should use NoLed class
  29. assert(gpio != GPIO_NUM_NC);
  30. /*
  31. * Prepare and set configuration of timers
  32. * that will be used by LED Controller
  33. */
  34. ledc_timer_config_t ledc_timer = {};
  35. ledc_timer.duty_resolution = LEDC_TIMER_13_BIT; // resolution of PWM duty
  36. ledc_timer.freq_hz = 4000; // frequency of PWM signal
  37. ledc_timer.speed_mode = LEDC_LS_MODE; // timer mode
  38. ledc_timer.timer_num = timer_num; // timer index
  39. ledc_timer.clk_cfg = LEDC_AUTO_CLK; // Auto select the source clock
  40. ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));
  41. ledc_channel_.channel = channel,
  42. ledc_channel_.duty = 0,
  43. ledc_channel_.gpio_num = gpio,
  44. ledc_channel_.speed_mode = LEDC_LS_MODE,
  45. ledc_channel_.hpoint = 0,
  46. ledc_channel_.timer_sel = timer_num,
  47. ledc_channel_.flags.output_invert = output_invert & 0x01,
  48. // Set LED Controller with previously prepared configuration
  49. ledc_channel_config(&ledc_channel_);
  50. // Initialize fade service.
  51. ledc_fade_func_install(0);
  52. // When the callback registered by ledc_cb_degister is called, run led ->OnFadeEnd()
  53. ledc_cbs_t ledc_callbacks = {
  54. .fade_cb = FadeCallback
  55. };
  56. ledc_cb_register(ledc_channel_.speed_mode, ledc_channel_.channel, &ledc_callbacks, this);
  57. esp_timer_create_args_t blink_timer_args = {
  58. .callback = [](void *arg) {
  59. auto led = static_cast<GpioLed*>(arg);
  60. led->OnBlinkTimer();
  61. },
  62. .arg = this,
  63. .dispatch_method = ESP_TIMER_TASK,
  64. .name = "Blink Timer",
  65. .skip_unhandled_events = false,
  66. };
  67. ESP_ERROR_CHECK(esp_timer_create(&blink_timer_args, &blink_timer_));
  68. ledc_initialized_ = true;
  69. }
  70. GpioLed::~GpioLed() {
  71. esp_timer_stop(blink_timer_);
  72. if (ledc_initialized_) {
  73. ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel);
  74. ledc_fade_func_uninstall();
  75. }
  76. }
  77. void GpioLed::SetBrightness(uint8_t brightness) {
  78. if (brightness == 100) {
  79. duty_ = LEDC_DUTY;
  80. } else {
  81. duty_ = brightness * LEDC_DUTY / 100;
  82. }
  83. }
  84. void GpioLed::TurnOn() {
  85. if (!ledc_initialized_) {
  86. return;
  87. }
  88. std::lock_guard<std::mutex> lock(mutex_);
  89. esp_timer_stop(blink_timer_);
  90. ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel);
  91. ledc_set_duty(ledc_channel_.speed_mode, ledc_channel_.channel, duty_);
  92. ledc_update_duty(ledc_channel_.speed_mode, ledc_channel_.channel);
  93. }
  94. void GpioLed::TurnOff() {
  95. if (!ledc_initialized_) {
  96. return;
  97. }
  98. std::lock_guard<std::mutex> lock(mutex_);
  99. esp_timer_stop(blink_timer_);
  100. ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel);
  101. ledc_set_duty(ledc_channel_.speed_mode, ledc_channel_.channel, 0);
  102. ledc_update_duty(ledc_channel_.speed_mode, ledc_channel_.channel);
  103. }
  104. void GpioLed::BlinkOnce() {
  105. Blink(1, 100);
  106. }
  107. void GpioLed::Blink(int times, int interval_ms) {
  108. StartBlinkTask(times, interval_ms);
  109. }
  110. void GpioLed::StartContinuousBlink(int interval_ms) {
  111. StartBlinkTask(BLINK_INFINITE, interval_ms);
  112. }
  113. void GpioLed::StartBlinkTask(int times, int interval_ms) {
  114. if (!ledc_initialized_) {
  115. return;
  116. }
  117. std::lock_guard<std::mutex> lock(mutex_);
  118. esp_timer_stop(blink_timer_);
  119. ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel);
  120. blink_counter_ = times * 2;
  121. blink_interval_ms_ = interval_ms;
  122. esp_timer_start_periodic(blink_timer_, interval_ms * 1000);
  123. }
  124. void GpioLed::OnBlinkTimer() {
  125. std::lock_guard<std::mutex> lock(mutex_);
  126. blink_counter_--;
  127. if (blink_counter_ & 1) {
  128. ledc_set_duty(ledc_channel_.speed_mode, ledc_channel_.channel, duty_);
  129. } else {
  130. ledc_set_duty(ledc_channel_.speed_mode, ledc_channel_.channel, 0);
  131. if (blink_counter_ == 0) {
  132. esp_timer_stop(blink_timer_);
  133. }
  134. }
  135. ledc_update_duty(ledc_channel_.speed_mode, ledc_channel_.channel);
  136. }
  137. void GpioLed::StartFadeTask() {
  138. if (!ledc_initialized_) {
  139. return;
  140. }
  141. std::lock_guard<std::mutex> lock(mutex_);
  142. esp_timer_stop(blink_timer_);
  143. ledc_fade_stop(ledc_channel_.speed_mode, ledc_channel_.channel);
  144. fade_up_ = true;
  145. ledc_set_fade_with_time(ledc_channel_.speed_mode,
  146. ledc_channel_.channel, LEDC_DUTY, LEDC_FADE_TIME);
  147. ledc_fade_start(ledc_channel_.speed_mode,
  148. ledc_channel_.channel, LEDC_FADE_NO_WAIT);
  149. }
  150. void GpioLed::OnFadeEnd() {
  151. std::lock_guard<std::mutex> lock(mutex_);
  152. fade_up_ = !fade_up_;
  153. ledc_set_fade_with_time(ledc_channel_.speed_mode,
  154. ledc_channel_.channel, fade_up_ ? LEDC_DUTY : 0, LEDC_FADE_TIME);
  155. ledc_fade_start(ledc_channel_.speed_mode,
  156. ledc_channel_.channel, LEDC_FADE_NO_WAIT);
  157. }
  158. bool IRAM_ATTR GpioLed::FadeCallback(const ledc_cb_param_t *param, void *user_arg) {
  159. if (param->event == LEDC_FADE_END_EVT) {
  160. auto led = static_cast<GpioLed*>(user_arg);
  161. led->OnFadeEnd();
  162. }
  163. return true;
  164. }
  165. void GpioLed::OnStateChanged() {
  166. auto& app = Application::GetInstance();
  167. auto device_state = app.GetDeviceState();
  168. switch (device_state) {
  169. case kDeviceStateStarting:
  170. SetBrightness(DEFAULT_BRIGHTNESS);
  171. StartContinuousBlink(100);
  172. break;
  173. case kDeviceStateWifiConfiguring:
  174. SetBrightness(DEFAULT_BRIGHTNESS);
  175. StartContinuousBlink(500);
  176. break;
  177. case kDeviceStateIdle:
  178. SetBrightness(IDLE_BRIGHTNESS);
  179. TurnOn();
  180. // TurnOff();
  181. break;
  182. case kDeviceStateConnecting:
  183. SetBrightness(DEFAULT_BRIGHTNESS);
  184. TurnOn();
  185. break;
  186. case kDeviceStateListening:
  187. case kDeviceStateAudioTesting:
  188. if (app.IsVoiceDetected()) {
  189. SetBrightness(HIGH_BRIGHTNESS);
  190. } else {
  191. SetBrightness(LOW_BRIGHTNESS);
  192. }
  193. // TurnOn();
  194. StartFadeTask();
  195. break;
  196. case kDeviceStateSpeaking:
  197. SetBrightness(SPEAKING_BRIGHTNESS);
  198. TurnOn();
  199. break;
  200. case kDeviceStateUpgrading:
  201. SetBrightness(UPGRADING_BRIGHTNESS);
  202. StartContinuousBlink(100);
  203. break;
  204. case kDeviceStateActivating:
  205. SetBrightness(ACTIVATING_BRIGHTNESS);
  206. StartContinuousBlink(500);
  207. break;
  208. default:
  209. ESP_LOGE(TAG, "Unknown gpio led event: %d", device_state);
  210. return;
  211. }
  212. }