ws2812.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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 = 7; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1 );
  28. time = 28; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 0 );
  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 = 15; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 1 );
  39. time = 16; while(time--) WRITE_PERI_REG( PERIPHS_GPIO_BASEADDR + GPIO_ID_PIN(WSGPIO), 0 );
  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. ws2812_config.color = color; // store color
  65. ws2812_config.pattern = pattern; // store pattern
  66. ws2812_config.led_state = 1; // reset led update timer state
  67. ws2812_config.direction = WS2812_UP; // set direction for pulse
  68. os_timer_disarm(&ws2812_timer); // disarm health publish timer
  69. switch (ws2812_config.color)
  70. {
  71. case WS2812_OFF:
  72. {
  73. ws2812_config.color_mask[WS2812_RED_INDEX] = 0x00;
  74. ws2812_config.color_mask[WS2812_GREEN_INDEX] = 0x00;
  75. ws2812_config.color_mask[WS2812_BLUE_INDEX] = 0x00;
  76. break;
  77. }
  78. case WS2812_RED:
  79. {
  80. ws2812_config.color_mask[WS2812_RED_INDEX] = 0xFF;
  81. ws2812_config.color_mask[WS2812_GREEN_INDEX] = 0x00;
  82. ws2812_config.color_mask[WS2812_BLUE_INDEX] = 0x00;
  83. break;
  84. }
  85. case WS2812_BLUE:
  86. {
  87. ws2812_config.color_mask[WS2812_RED_INDEX] = 0x00;
  88. ws2812_config.color_mask[WS2812_GREEN_INDEX] = 0x00;
  89. ws2812_config.color_mask[WS2812_BLUE_INDEX] = 0xFF;
  90. break;
  91. }
  92. case WS2812_GREEN:
  93. {
  94. ws2812_config.color_mask[WS2812_RED_INDEX] = 0x00;
  95. ws2812_config.color_mask[WS2812_GREEN_INDEX] = 0xFF;
  96. ws2812_config.color_mask[WS2812_BLUE_INDEX] = 0x00;
  97. break;
  98. }
  99. case WS2812_MAGENTA:
  100. {
  101. ws2812_config.color_mask[WS2812_RED_INDEX] = 0xFF;
  102. ws2812_config.color_mask[WS2812_GREEN_INDEX] = 0x00;
  103. ws2812_config.color_mask[WS2812_BLUE_INDEX] = 0xFF;
  104. break;
  105. }
  106. case WS2812_ORANGE:
  107. {
  108. ws2812_config.color_mask[WS2812_RED_INDEX] = 0xFF;
  109. ws2812_config.color_mask[WS2812_GREEN_INDEX] = 0xA5;
  110. ws2812_config.color_mask[WS2812_BLUE_INDEX] = 0x00;
  111. break;
  112. }
  113. default:
  114. {
  115. ws2812_config.color_mask[WS2812_RED_INDEX] = 0x00;
  116. ws2812_config.color_mask[WS2812_GREEN_INDEX] = 0x00;
  117. ws2812_config.color_mask[WS2812_BLUE_INDEX] = 0x00;
  118. break;
  119. }
  120. }
  121. switch (ws2812_config.pattern)
  122. {
  123. case(WS2812_SOLID):
  124. {
  125. //WS2812_OutBuffer(init_buffer, 3);
  126. //os_delay_us(70);
  127. WS2812_OutBuffer(ws2812_config.color_mask, 3); //
  128. break;
  129. }
  130. case(WS2812_PULSE):
  131. {
  132. os_timer_setfn(&ws2812_timer, (os_timer_func_t *)ws2812_timer_cb, NULL);
  133. os_timer_arm(&ws2812_timer, WS2812_REFRESH_INTERVAL, 1);
  134. break;
  135. }
  136. default:
  137. {
  138. break;
  139. }
  140. }
  141. return;
  142. }
  143. void ws2812_timer_cb(void)
  144. {
  145. // calculate color fade
  146. uint8_t led_state = ws2812_config.led_state;
  147. uint8_t tempBuffer[3] = {ws2812_config.color_mask[WS2812_GREEN_INDEX] / led_state,
  148. ws2812_config.color_mask[WS2812_RED_INDEX] / led_state,
  149. ws2812_config.color_mask[WS2812_BLUE_INDEX] / led_state};
  150. // Debuging Information
  151. //ESP_LOGV(TAG, "WS2812 Timer [led_state]: %d", ws2812_config.led_state);
  152. //ESP_LOGV(TAG, "WS2812 Timer [tempBuffer] %d:%d:%d", tempBuffer[0], tempBuffer[1], tempBuffer[2]);
  153. WS2812_OutBuffer(tempBuffer, 3); // send color to LED
  154. // increase / decrease scaling factor for LED color
  155. if (ws2812_config.direction == WS2812_UP)
  156. {
  157. ws2812_config.led_state++;
  158. if (ws2812_config.led_state == 50)
  159. ws2812_config.direction = WS2812_DOWN;
  160. }
  161. else
  162. {
  163. ws2812_config.led_state--;
  164. if (ws2812_config.led_state == 1)
  165. ws2812_config.direction = WS2812_UP;
  166. }
  167. }