ws2812.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. /*******************************************************************************
  2. * WS2812 Driver for IdeasX
  3. * Author: curiousmuch
  4. * Description: LED driver for v0.3.X encoder
  5. * Todo: Improve pulse mode to use less CPU cycles and fluidity of cycle.
  6. *******************************************************************************/
  7. #include "hal/ws2812.h"
  8. static const char* TAG = "ws2812 driver";
  9. // static uint8_t pulseBuffer[100] = { 127, 135, 143, 151, 159, 166, 174, 181, 188,
  10. // 195, 202, 208, 214, 220, 225, 230, 235, 239,
  11. // 242, 246, 248, 250, 252, 253, 254, 255, 254,
  12. // 253, 252, 250, 248, 246, 242, 239, 235, 230,
  13. // 225, 220, 214, 208, 202, 195, 188, 181, 174,
  14. // 166, 159, 151, 143, 135, 127, 119, 111, 103,
  15. // 95, 88, 80, 73, 66, 59, 52, 46, 40, 34, 29,
  16. // 24, 19, 15, 12, 8, 6, 4, 2, 1, 0, 0, 0, 1, 2,
  17. // 4, 6, 8, 12, 15, 19, 24, 29, 34, 40, 46, 52,
  18. // 59, 66, 73, 80, 88, 95, 103, 111, 119};
  19. static os_timer_t ws2812_timer;
  20. static WS2812_CONFIG_t ws2812_config;
  21. static void ws2812_timer_cb(void);
  22. static uint8_t init_buffer[3] = {0x00, 0x00, 0x00};
  23. static void send_ws_0(void)
  24. {
  25. uint8_t time;
  26. #if WS2811_COMPATIBLE
  27. time = 6; while(time--) GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, BIT(WSGPIO));
  28. time = 10; while(time--) GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, BIT(WSGPIO));
  29. #else
  30. time = 2; while(time--) GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, BIT(WSGPIO));
  31. time = 3; while(time--) GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, BIT(WSGPIO));
  32. #endif
  33. }
  34. static void send_ws_1(void)
  35. {
  36. uint8_t time;
  37. #if WS2811_COMPATIBLE
  38. time = 10; while(time--) GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, BIT(WSGPIO));
  39. time = 6; while(time--) GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, BIT(WSGPIO));
  40. #else
  41. time = 5; while(time--) GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, BIT(WSGPIO));
  42. time = 4; while(time--) GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, BIT(WSGPIO));
  43. #endif
  44. }
  45. void WS2812_OutBuffer(int8_t * buffer, uint16_t length)
  46. {
  47. ETS_INTR_LOCK(); // why is this different than a normal disable interupts again?
  48. uint16_t i;
  49. GPIO_OUTPUT_SET(GPIO_ID_PIN(WSGPIO), 0); // set gpio as output (redundent?)
  50. for( i = 0; i < length; i++ )
  51. {
  52. uint8_t mask = 0x80;
  53. uint8_t byte = buffer[i];
  54. while (mask)
  55. {
  56. if( byte & mask ) send_ws_1(); else send_ws_0();
  57. mask >>= 1;
  58. }
  59. }
  60. ETS_INTR_UNLOCK();
  61. }
  62. void ICACHE_FLASH_ATTR WS2812_SetColor(WS2812_COLOR_et color, WS2812_PATTERN_et pattern)
  63. {
  64. // return if the color is already set
  65. if (color == ws2812_config.color && pattern == ws2812_config.pattern)
  66. {
  67. return;
  68. }
  69. ws2812_config.color = color; // store color
  70. ws2812_config.pattern = pattern; // store pattern
  71. ws2812_config.led_state = 1; // reset led update timer state
  72. ws2812_config.direction = WS2812_UP; // set direction for pulse
  73. os_timer_disarm(&ws2812_timer); // disarm health publish timer
  74. switch (ws2812_config.color)
  75. {
  76. case WS2812_OFF:
  77. {
  78. ws2812_config.color_mask[WS2812_RED_INDEX] = 0x00;
  79. ws2812_config.color_mask[WS2812_GREEN_INDEX] = 0x00;
  80. ws2812_config.color_mask[WS2812_BLUE_INDEX] = 0x00;
  81. break;
  82. }
  83. case WS2812_RED:
  84. {
  85. ws2812_config.color_mask[WS2812_RED_INDEX] = 0xFF;
  86. ws2812_config.color_mask[WS2812_GREEN_INDEX] = 0x00;
  87. ws2812_config.color_mask[WS2812_BLUE_INDEX] = 0x00;
  88. break;
  89. }
  90. case WS2812_BLUE:
  91. {
  92. ws2812_config.color_mask[WS2812_RED_INDEX] = 0x00;
  93. ws2812_config.color_mask[WS2812_GREEN_INDEX] = 0x00;
  94. ws2812_config.color_mask[WS2812_BLUE_INDEX] = 0xFF;
  95. break;
  96. }
  97. case WS2812_GREEN:
  98. {
  99. ws2812_config.color_mask[WS2812_RED_INDEX] = 0x00;
  100. ws2812_config.color_mask[WS2812_GREEN_INDEX] = 0xFF;
  101. ws2812_config.color_mask[WS2812_BLUE_INDEX] = 0x00;
  102. break;
  103. }
  104. case WS2812_MAGENTA:
  105. {
  106. ws2812_config.color_mask[WS2812_RED_INDEX] = 0xFF;
  107. ws2812_config.color_mask[WS2812_GREEN_INDEX] = 0x00;
  108. ws2812_config.color_mask[WS2812_BLUE_INDEX] = 0xFF;
  109. break;
  110. }
  111. case WS2812_ORANGE:
  112. {
  113. ws2812_config.color_mask[WS2812_RED_INDEX] = 0xFF;
  114. ws2812_config.color_mask[WS2812_GREEN_INDEX] = 0xA5;
  115. ws2812_config.color_mask[WS2812_BLUE_INDEX] = 0x00;
  116. break;
  117. }
  118. default:
  119. {
  120. ws2812_config.color_mask[WS2812_RED_INDEX] = 0x00;
  121. ws2812_config.color_mask[WS2812_GREEN_INDEX] = 0x00;
  122. ws2812_config.color_mask[WS2812_BLUE_INDEX] = 0x00;
  123. break;
  124. }
  125. }
  126. switch (ws2812_config.pattern)
  127. {
  128. case(WS2812_SOLID):
  129. {
  130. //WS2812_OutBuffer(init_buffer, 3);
  131. //os_delay_us(70);
  132. WS2812_OutBuffer(ws2812_config.color_mask, 3); //
  133. break;
  134. }
  135. case(WS2812_PULSE):
  136. {
  137. os_timer_setfn(&ws2812_timer, (os_timer_func_t *)ws2812_timer_cb, NULL);
  138. os_timer_arm(&ws2812_timer, WS2812_REFRESH_INTERVAL, 1);
  139. break;
  140. }
  141. default:
  142. {
  143. break;
  144. }
  145. }
  146. return;
  147. }
  148. void ws2812_timer_cb(void)
  149. {
  150. // calculate color fade
  151. uint8_t led_state = ws2812_config.led_state;
  152. uint8_t tempBuffer[3] = {ws2812_config.color_mask[WS2812_GREEN_INDEX] / led_state,
  153. ws2812_config.color_mask[WS2812_RED_INDEX] / led_state,
  154. ws2812_config.color_mask[WS2812_BLUE_INDEX] / led_state};
  155. // Debuging Information
  156. //ESP_LOGV(TAG, "WS2812 Timer [led_state]: %d", ws2812_config.led_state);
  157. //ESP_LOGV(TAG, "WS2812 Timer [tempBuffer] %d:%d:%d", tempBuffer[0], tempBuffer[1], tempBuffer[2]);
  158. WS2812_OutBuffer(tempBuffer, 3); // send color to LED
  159. // increase / decrease scaling factor for LED color
  160. if (ws2812_config.direction == WS2812_UP)
  161. {
  162. ws2812_config.led_state++;
  163. if (ws2812_config.led_state == 50)
  164. ws2812_config.direction = WS2812_DOWN;
  165. }
  166. else
  167. {
  168. ws2812_config.led_state--;
  169. if (ws2812_config.led_state == 1)
  170. ws2812_config.direction = WS2812_UP;
  171. }
  172. }