LEDWidget.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  1. /*
  2. *
  3. * Copyright (c) 2021 Project CHIP Authors
  4. * Copyright (c) 2019 Google LLC.
  5. * Copyright 2021, Cypress Semiconductor Corporation (an Infineon company)
  6. * All rights reserved.
  7. *
  8. * Licensed under the Apache License, Version 2.0 (the "License");
  9. * you may not use this file except in compliance with the License.
  10. * You may obtain a copy of the License at
  11. *
  12. * http://www.apache.org/licenses/LICENSE-2.0
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. */
  20. #include "LEDWidget.h"
  21. #include "cybsp.h"
  22. #include "cyhal.h"
  23. #include <platform/CHIPDeviceLayer.h>
  24. /*******************************************************************************
  25. * Macro Definitions
  26. *******************************************************************************/
  27. /* Allowed TCPWM compare value for maximum brightness */
  28. #define LED_MAX_BRIGHTNESS (100u)
  29. /* Allowed TCPWM compare value for minimum brightness*/
  30. #define LED_MIN_BRIGHTNESS (1u)
  31. #define PWM_LED_FREQ_HZ (1000000u) /* in Hz */
  32. /* subtracting from 100 since the LED is connected in active low configuration */
  33. #define GET_DUTY_CYCLE(x) (100 - x)
  34. // PWM period in micro seconds
  35. #define CY_RGB_LED_PWM_PERIOD_US (255u)
  36. // Clock instance
  37. static cyhal_clock_t clk_pwm;
  38. void LEDWidget::Init(int ledNum)
  39. {
  40. mLastChangeTimeMS = 0;
  41. mBlinkOnTimeMS = 0;
  42. mBlinkOffTimeMS = 0;
  43. mLedNum = ledNum;
  44. mState = 0;
  45. mbrightness = LED_MAX_BRIGHTNESS;
  46. if (CY_RSLT_SUCCESS != cyhal_pwm_init(&pwm_led, (cyhal_gpio_t) ledNum, NULL))
  47. {
  48. printf("LED PWM Init failed!");
  49. }
  50. if (CY_RSLT_SUCCESS != cyhal_pwm_set_duty_cycle(&pwm_led, GET_DUTY_CYCLE(LED_MAX_BRIGHTNESS), PWM_LED_FREQ_HZ))
  51. {
  52. printf("PWM failed to set dutycycle!");
  53. }
  54. }
  55. void LEDWidget::Invert(void)
  56. {
  57. Set(!mState);
  58. }
  59. void LEDWidget::Set(bool state)
  60. {
  61. mLastChangeTimeMS = mBlinkOnTimeMS = mBlinkOffTimeMS = 0;
  62. DoSet(state);
  63. }
  64. bool LEDWidget::Get()
  65. {
  66. return mState;
  67. }
  68. void LEDWidget::Blink(uint32_t changeRateMS)
  69. {
  70. Blink(changeRateMS, changeRateMS);
  71. }
  72. void LEDWidget::Blink(uint32_t onTimeMS, uint32_t offTimeMS)
  73. {
  74. mBlinkOnTimeMS = onTimeMS;
  75. mBlinkOffTimeMS = offTimeMS;
  76. Animate();
  77. }
  78. void LEDWidget::Animate()
  79. {
  80. if (mBlinkOnTimeMS != 0 && mBlinkOffTimeMS != 0)
  81. {
  82. uint64_t nowMS = chip::System::SystemClock().GetMonotonicMilliseconds64().count();
  83. uint64_t stateDurMS = mState ? mBlinkOnTimeMS : mBlinkOffTimeMS;
  84. uint64_t nextChangeTimeMS = mLastChangeTimeMS + stateDurMS;
  85. if (nextChangeTimeMS < nowMS)
  86. {
  87. DoSet(!mState);
  88. mLastChangeTimeMS = nowMS;
  89. }
  90. }
  91. }
  92. void LEDWidget::DoSet(bool state)
  93. {
  94. if (mState != state)
  95. {
  96. (state) ? PWM_start() : PWM_stop();
  97. }
  98. mState = state;
  99. }
  100. void LEDWidget::RGB_init()
  101. {
  102. cy_rslt_t result = CY_RSLT_SUCCESS;
  103. // Allocate and assign the clock for TCPWMs for RGB LED control
  104. result = cyhal_clock_allocate(&clk_pwm, CYHAL_CLOCK_BLOCK_PERIPHERAL_16BIT);
  105. if (result == CY_RSLT_SUCCESS)
  106. {
  107. result = cyhal_clock_set_frequency(&clk_pwm, PWM_LED_FREQ_HZ, NULL);
  108. }
  109. if (result == CY_RSLT_SUCCESS)
  110. {
  111. result = cyhal_clock_set_enabled(&clk_pwm, true, true);
  112. }
  113. if (CY_RSLT_SUCCESS != cyhal_pwm_init(&pwm_red, CYBSP_LED_RGB_RED, &clk_pwm))
  114. {
  115. printf("PWM Init failed for RBG Red LED!");
  116. }
  117. if (CY_RSLT_SUCCESS != cyhal_pwm_init(&pwm_green, CYBSP_LED_RGB_GREEN, &clk_pwm))
  118. {
  119. printf("PWM Init failed for RBG Green LED!");
  120. }
  121. if (CY_RSLT_SUCCESS != cyhal_pwm_init(&pwm_blue, CYBSP_LED_RGB_BLUE, &clk_pwm))
  122. {
  123. printf("PWM Init failed for RBG blue LED!");
  124. }
  125. if (CY_RSLT_SUCCESS != cyhal_pwm_set_duty_cycle(&pwm_red, GET_DUTY_CYCLE(LED_MAX_BRIGHTNESS), PWM_LED_FREQ_HZ))
  126. {
  127. printf("PWM failed to set dutycycle for RBG Red LED!");
  128. }
  129. if (CY_RSLT_SUCCESS != cyhal_pwm_set_duty_cycle(&pwm_green, GET_DUTY_CYCLE(LED_MAX_BRIGHTNESS), PWM_LED_FREQ_HZ))
  130. {
  131. printf("PWM failed to set dutycycle for RBG Green LED!");
  132. }
  133. if (CY_RSLT_SUCCESS != cyhal_pwm_set_duty_cycle(&pwm_blue, GET_DUTY_CYCLE(LED_MAX_BRIGHTNESS), PWM_LED_FREQ_HZ))
  134. {
  135. printf("PWM failed to set dutycycle for RBG Blue LED!");
  136. }
  137. mState = 0;
  138. mbrightness = LED_MAX_BRIGHTNESS;
  139. mHue = 0;
  140. mSaturation = 0;
  141. }
  142. void LEDWidget::PWM_start()
  143. {
  144. if (!mState)
  145. {
  146. /* Start PWM to turn the LED on */
  147. if (CY_RSLT_SUCCESS != cyhal_pwm_start(&pwm_led))
  148. {
  149. printf("PWM failed to start!");
  150. }
  151. mState = 1;
  152. }
  153. }
  154. void LEDWidget::PWM_stop()
  155. {
  156. if (mState)
  157. {
  158. /* Stop PWM to turn the LED off */
  159. if (CY_RSLT_SUCCESS != cyhal_pwm_stop(&pwm_led))
  160. {
  161. printf("PWM failed to stop!");
  162. }
  163. mState = 0;
  164. }
  165. }
  166. void LEDWidget::RGB_set(bool state)
  167. {
  168. if (mState != state)
  169. {
  170. if (state)
  171. {
  172. if (CY_RSLT_SUCCESS != cyhal_pwm_start(&pwm_red))
  173. {
  174. printf("PWM failed to start!");
  175. }
  176. if (CY_RSLT_SUCCESS != cyhal_pwm_start(&pwm_green))
  177. {
  178. printf("PWM failed to start!");
  179. }
  180. if (CY_RSLT_SUCCESS != cyhal_pwm_start(&pwm_blue))
  181. {
  182. printf("PWM failed to start!");
  183. }
  184. mState = 1;
  185. }
  186. else
  187. {
  188. if (CY_RSLT_SUCCESS != cyhal_pwm_stop(&pwm_red))
  189. {
  190. printf("PWM failed to start!");
  191. }
  192. if (CY_RSLT_SUCCESS != cyhal_pwm_stop(&pwm_green))
  193. {
  194. printf("PWM failed to start!");
  195. }
  196. if (CY_RSLT_SUCCESS != cyhal_pwm_stop(&pwm_blue))
  197. {
  198. printf("PWM failed to start!");
  199. }
  200. mState = 0;
  201. }
  202. }
  203. }
  204. void LEDWidget::SetBrightness(uint32_t led_brightness)
  205. {
  206. mbrightness = (led_brightness < LED_MIN_BRIGHTNESS) ? LED_MIN_BRIGHTNESS
  207. : static_cast<uint16_t>(led_brightness) * 100 / CY_RGB_LED_PWM_PERIOD_US;
  208. /* Set Brightness for RGB LED */
  209. if (pwm_red.pin)
  210. {
  211. HSB2rgb(mHue, mSaturation, mbrightness);
  212. }
  213. else
  214. {
  215. /* Drive the LED with brightness */
  216. if (CY_RSLT_SUCCESS != cyhal_pwm_set_duty_cycle(&pwm_led, GET_DUTY_CYCLE(mbrightness), PWM_LED_FREQ_HZ))
  217. {
  218. printf("PWM failed to set dutycycle!");
  219. }
  220. PWM_start();
  221. }
  222. }
  223. void LEDWidget::SetColor(uint8_t Hue, uint8_t Saturation)
  224. {
  225. uint8_t brightness = (mState) ? mbrightness : 0;
  226. mHue = static_cast<uint16_t>(Hue) * 360 / 254; // mHue [0, 360]
  227. mSaturation = static_cast<uint16_t>(Saturation) * 100 / 254; // mSaturation [0 , 100]
  228. HSB2rgb(mHue, mSaturation, brightness);
  229. }
  230. void LEDWidget::HSB2rgb(uint16_t Hue, uint8_t Saturation, uint8_t brightness)
  231. {
  232. uint8_t red, green, blue;
  233. uint16_t i = Hue / 60;
  234. brightness = static_cast<uint16_t>(brightness) * CY_RGB_LED_PWM_PERIOD_US / 100;
  235. uint16_t rgb_max = brightness;
  236. uint16_t rgb_min = rgb_max * (100 - Saturation) / 100;
  237. uint16_t diff = Hue % 60;
  238. uint16_t rgb_adj = (rgb_max - rgb_min) * diff / 60;
  239. switch (i)
  240. {
  241. case 0:
  242. red = rgb_max;
  243. green = rgb_min + rgb_adj;
  244. blue = rgb_min;
  245. break;
  246. case 1:
  247. red = rgb_max - rgb_adj;
  248. green = rgb_max;
  249. blue = rgb_min;
  250. break;
  251. case 2:
  252. red = rgb_min;
  253. green = rgb_max;
  254. blue = rgb_min + rgb_adj;
  255. break;
  256. case 3:
  257. red = rgb_min;
  258. green = rgb_max - rgb_adj;
  259. blue = rgb_max;
  260. break;
  261. case 4:
  262. red = rgb_min + rgb_adj;
  263. green = rgb_min;
  264. blue = rgb_max;
  265. break;
  266. default:
  267. red = rgb_max;
  268. green = rgb_min;
  269. blue = rgb_max - rgb_adj;
  270. break;
  271. }
  272. /* LED is configured as ACTIVE LOW */
  273. red = CY_RGB_LED_PWM_PERIOD_US - red;
  274. green = CY_RGB_LED_PWM_PERIOD_US - green;
  275. blue = CY_RGB_LED_PWM_PERIOD_US - blue;
  276. /* Set Period to control color setting */
  277. cyhal_pwm_set_period(&pwm_red, CY_RGB_LED_PWM_PERIOD_US, red);
  278. cyhal_pwm_set_period(&pwm_green, CY_RGB_LED_PWM_PERIOD_US, green);
  279. cyhal_pwm_set_period(&pwm_blue, CY_RGB_LED_PWM_PERIOD_US, blue);
  280. }