ws2812_effects.c 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057
  1. #include "module.h"
  2. #include "lauxlib.h"
  3. #include "lmem.h"
  4. #include "platform.h"
  5. #include <stdlib.h>
  6. #include <math.h>
  7. #include <string.h>
  8. #include "user_interface.h"
  9. #include "driver/uart.h"
  10. #include "osapi.h"
  11. #include "pm/swtimer.h"
  12. #include "pixbuf.h"
  13. #include "color_utils.h"
  14. #ifdef LUA_USE_MODULES_WS2812_EFFECTS
  15. #ifndef LUA_USE_MODULES_PIXBUF
  16. # error module pixbuf is required for ws2812_effects
  17. #endif
  18. #ifndef LUA_USE_MODULES_COLOR_UTILS
  19. # error module color_utilsf is required for ws2812_effects
  20. #endif
  21. #endif
  22. #define CANARY_VALUE 0x32372132
  23. #define DEFAULT_MODE 0
  24. #define DEFAULT_COLOR 0xFF0000
  25. #define SPEED_MIN 0
  26. #define SPEED_MAX 255
  27. #define SPEED_DEFAULT 150
  28. #define DELAY_DEFAULT 100
  29. #define BRIGHTNESS_MIN 0
  30. #define BRIGHTNESS_MAX 255
  31. #define BRIGHTNESS_DEFAULT 100
  32. #define EFFECT_PARAM_INVALID -10000
  33. #define LIBRARY_NOT_INITIALIZED_ERROR_MSG "please call init() first"
  34. #define min(a,b) ((a) < (b) ? (a) : (b))
  35. #define max(a,b) ((a) > (b) ? (a) : (b))
  36. #define abs(a) ((a) > 0 ? (a) : (0-a))
  37. #define min3(a,b, c) min((a), min((b), (c)))
  38. #define max3(a,b, c) max((a), max((b), (c)))
  39. #define IDX_R 1
  40. #define IDX_G 0
  41. #define IDX_B 2
  42. #define IDX_W 3
  43. typedef struct {
  44. pixbuf *buffer;
  45. int buffer_ref;
  46. uint32_t mode_delay;
  47. uint32_t counter_mode_call;
  48. uint32_t counter_mode_step;
  49. uint8_t mode_color_index;
  50. uint8_t speed;
  51. uint8_t brightness;
  52. os_timer_t os_t;
  53. uint8_t running;
  54. uint8_t effect_type;
  55. uint8_t color[4];
  56. int effect_int_param1;
  57. struct pixbuf_shift_params shift;
  58. } ws2812_effects;
  59. enum ws2812_effects_type {
  60. WS2812_EFFECT_STATIC,
  61. WS2812_EFFECT_BLINK,
  62. WS2812_EFFECT_GRADIENT,
  63. WS2812_EFFECT_GRADIENT_RGB,
  64. WS2812_EFFECT_RANDOM_COLOR,
  65. WS2812_EFFECT_RAINBOW,
  66. WS2812_EFFECT_RAINBOW_CYCLE,
  67. WS2812_EFFECT_FLICKER,
  68. WS2812_EFFECT_FIRE_FLICKER,
  69. WS2812_EFFECT_FIRE_FLICKER_SOFT,
  70. WS2812_EFFECT_FIRE_FLICKER_INTENSE,
  71. WS2812_EFFECT_HALLOWEEN,
  72. WS2812_EFFECT_CIRCUS_COMBUSTUS,
  73. WS2812_EFFECT_LARSON_SCANNER,
  74. WS2812_EFFECT_CYCLE,
  75. WS2812_EFFECT_COLOR_WIPE,
  76. WS2812_EFFECT_RANDOM_DOT
  77. };
  78. static ws2812_effects *state;
  79. //-----------------
  80. // UTILITY METHODS
  81. //-----------------
  82. // XXX Not exported because this module is its sole non-Lua consumer and we
  83. // should be going away soon! Deprecated, 'n all that.
  84. extern void ICACHE_RAM_ATTR ws2812_write_data(
  85. const uint8_t *pixels, uint32_t length,
  86. const uint8_t *pixels2, uint32_t length2);
  87. static int ws2812_effects_write(pixbuf* buffer) {
  88. ws2812_write_data(buffer->values, pixbuf_size(buffer), 0, 0);
  89. return 0;
  90. }
  91. // :opens_boxes -1
  92. static void ws2812_set_pixel(int pixel, uint32_t color) {
  93. pixbuf * buffer = state->buffer;
  94. uint8_t g = ((color & 0x00FF0000) >> 16);
  95. uint8_t r = ((color & 0x0000FF00) >> 8);
  96. uint8_t b = (color & 0x000000FF);
  97. uint8_t w = pixbuf_channels(buffer) == 4 ? ((color & 0xFF000000) >> 24) : 0;
  98. int offset = pixel * pixbuf_channels(buffer);
  99. buffer->values[offset+IDX_R] = r;
  100. buffer->values[offset+IDX_G] = g;
  101. buffer->values[offset+IDX_B] = b;
  102. if (pixbuf_channels(buffer) == 4) {
  103. buffer->values[offset+IDX_W] = w;
  104. }
  105. }
  106. /*
  107. * Returns a new, random color wheel index with a minimum distance of 42 from pos.
  108. */
  109. static uint8_t get_random_wheel_index(uint8_t pos)
  110. {
  111. uint8_t r = 0;
  112. uint8_t x = 0;
  113. uint8_t y = 0;
  114. uint8_t d = 0;
  115. while(d < 42) {
  116. r = rand() % 360;
  117. x = abs(pos - r);
  118. y = 360 - x;
  119. d = min(x, y);
  120. }
  121. return r;
  122. }
  123. //-----------------
  124. // EFFECTS LIBRARY
  125. //-----------------
  126. /**
  127. * initialized ws2812_effects with the buffer to use
  128. */
  129. static int ws2812_effects_init(lua_State *L) {
  130. platform_print_deprecation_note("ws2812_effects",
  131. "soon; please see https://github.com/nodemcu/nodemcu-firmware/issues/3122");
  132. pixbuf * buffer = pixbuf_from_lua_arg(L, 1);
  133. // get rid of old state
  134. if (state != NULL) {
  135. luaL_unref(L, LUA_REGISTRYINDEX, state->buffer_ref);
  136. free((void *) state);
  137. }
  138. // Allocate memory and set all to zero
  139. state = (ws2812_effects *) calloc(1,sizeof(ws2812_effects));
  140. // initialize
  141. state->speed = SPEED_DEFAULT;
  142. state->mode_delay = DELAY_DEFAULT;
  143. state->brightness = BRIGHTNESS_DEFAULT;
  144. state->buffer = buffer;
  145. state->buffer_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  146. return 0;
  147. }
  148. /*
  149. * set color for single color effects
  150. */
  151. static int ws2812_effects_set_color(lua_State* L) {
  152. luaL_argcheck(L, state != NULL, 1, LIBRARY_NOT_INITIALIZED_ERROR_MSG);
  153. uint8_t g = luaL_checkinteger(L, 1);
  154. uint8_t r = luaL_checkinteger(L, 2);
  155. uint8_t b = luaL_checkinteger(L, 3);
  156. uint8_t w = luaL_optinteger(L, 4, 0 );
  157. state->color[0] = g;
  158. state->color[1] = r;
  159. state->color[2] = b;
  160. state->color[3] = w;
  161. return 0;
  162. }
  163. static int ws2812_effects_get_speed(lua_State* L) {
  164. luaL_argcheck(L, state != NULL, 1, LIBRARY_NOT_INITIALIZED_ERROR_MSG);
  165. lua_pushinteger(L, state->speed);
  166. return 1;
  167. }
  168. static int ws2812_effects_set_speed(lua_State* L) {
  169. int speed = luaL_checkinteger(L, 1);
  170. luaL_argcheck(L, state != NULL, 1, LIBRARY_NOT_INITIALIZED_ERROR_MSG);
  171. luaL_argcheck(L, speed >= SPEED_MIN && speed <= SPEED_MAX, 1, "should be 0-255");
  172. state->speed = (uint8_t)speed;
  173. state->mode_delay = 10;
  174. return 0;
  175. }
  176. static int ws2812_effects_get_delay(lua_State* L) {
  177. luaL_argcheck(L, state != NULL, 1, LIBRARY_NOT_INITIALIZED_ERROR_MSG);
  178. lua_pushinteger(L, state->mode_delay);
  179. return 1;
  180. }
  181. static int ws2812_effects_set_delay(lua_State* L) {
  182. luaL_argcheck(L, state != NULL, 1, LIBRARY_NOT_INITIALIZED_ERROR_MSG);
  183. const int delay = luaL_checkinteger(L, 1);
  184. luaL_argcheck(L, delay >= 10, 1, "must be equal / larger than 10");
  185. state->mode_delay = delay;
  186. state->speed = 0;
  187. return 1;
  188. }
  189. static int ws2812_effects_set_brightness(lua_State* L) {
  190. int brightness = luaL_checkint(L, 1);
  191. luaL_argcheck(L, state != NULL, 1, LIBRARY_NOT_INITIALIZED_ERROR_MSG);
  192. luaL_argcheck(L, brightness >= BRIGHTNESS_MIN && brightness <= BRIGHTNESS_MAX, 1, "should be 0-255");
  193. state->brightness = (uint8_t) brightness;
  194. return 0;
  195. }
  196. // :opens_boxes -1
  197. static void ws2812_effects_fill_buffer(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
  198. pixbuf * buffer = state->buffer;
  199. uint8_t bright_g = g * state->brightness / BRIGHTNESS_MAX;
  200. uint8_t bright_r = r * state->brightness / BRIGHTNESS_MAX;
  201. uint8_t bright_b = b * state->brightness / BRIGHTNESS_MAX;
  202. uint8_t bright_w = w * state->brightness / BRIGHTNESS_MAX;
  203. // Fill buffer
  204. int i;
  205. uint8_t * p = &buffer->values[0];
  206. for(i = 0; i < buffer->npix; i++) {
  207. *p++ = bright_g;
  208. *p++ = bright_r;
  209. *p++ = bright_b;
  210. if (pixbuf_channels(buffer) == 4) {
  211. *p++ = bright_w;
  212. }
  213. }
  214. }
  215. //------------------
  216. // basic methods
  217. //------------------
  218. /*
  219. * Cycles all LEDs at once through a rainbow.
  220. */
  221. static int ws2812_effects_fill_color() {
  222. uint8_t g = state->color[0];
  223. uint8_t r = state->color[1];
  224. uint8_t b = state->color[2];
  225. uint8_t w = state->color[3];
  226. ws2812_effects_fill_buffer(r, g, b, w);
  227. return 0;
  228. }
  229. //-----------------
  230. // EFFECFTS
  231. //-----------------
  232. /*
  233. * blink with set color
  234. */
  235. static int ws2812_effects_mode_blink() {
  236. if(state->counter_mode_call % 2 == 1) {
  237. // on
  238. ws2812_effects_fill_color();
  239. }
  240. else {
  241. // off
  242. pixbuf * buffer = state->buffer;
  243. memset(&buffer->values[0], 0, pixbuf_size(buffer));
  244. }
  245. return 0;
  246. }
  247. static int ws2812_effects_gradient(const char *gradient_spec, size_t length1) {
  248. pixbuf * buffer = state->buffer;
  249. int segments = (length1 / pixbuf_channels(buffer)) - 1;
  250. int segmentSize = buffer->npix / segments;
  251. uint8_t g1, r1, b1, g2, r2, b2;
  252. int i,j,k;
  253. g2 = *gradient_spec++;
  254. r2 = *gradient_spec++;
  255. b2 = *gradient_spec++;
  256. // skip non-rgb components
  257. for (j = 3; j < pixbuf_channels(buffer); j++)
  258. {
  259. *gradient_spec++;
  260. }
  261. // reference to buffer memory
  262. uint8_t * p = &buffer->values[0];
  263. uint16_t h1,h2;
  264. uint8_t s,v,s1,v1,s2,v2;
  265. for (k = 0; k < segments; k++) {
  266. g1 = g2;
  267. r1 = r2;
  268. b1 = b2;
  269. uint32_t hsv1 = grb2hsv(g1, r1, b1);
  270. h1 = (hsv1 & 0xFFFF0000) >> 16;
  271. s1 = (hsv1 & 0x0000FF00) >> 8;
  272. v1 = (hsv1 & 0x000000FF);
  273. g2 = *gradient_spec++;
  274. r2 = *gradient_spec++;
  275. b2 = *gradient_spec++;
  276. for (j = 3; j < pixbuf_channels(buffer); j++)
  277. {
  278. *gradient_spec++;
  279. }
  280. uint32_t hsv2 = grb2hsv(g2, r2, b2);
  281. h2 = (hsv2 & 0xFFFF0000) >> 16;
  282. s2 = (hsv1 & 0x0000FF00) >> 8;
  283. v2 = (hsv1 & 0x000000FF);
  284. // get distance and direction to use
  285. int maxCCW = h1 > h2 ? h1 - h2 : 360 + h1 - h2;
  286. int maxCW = h1 > h2 ? 360 + h2 - h1 : h2 - h1;
  287. // Fill buffer
  288. int numPixels = segmentSize;
  289. // make sure we fill the strip correctly in case of rounding errors
  290. if (k == segments - 1) {
  291. numPixels = buffer->npix - (segmentSize * (segments - 1));
  292. }
  293. int steps = numPixels - 1;
  294. for(i = 0; i < numPixels; i++) {
  295. // calculate HSV values
  296. //h = h1 + ((h2-h1) * i / fillSize);
  297. int h = maxCCW > maxCW ? h1 + ((maxCW * i / steps) % 360) : h1 - (maxCCW * i / steps);
  298. if (h < 0) h = h + 360;
  299. if (h > 359) h = h - 360;
  300. s = s1 + ((s2-s1) * i / steps);
  301. v = v1 + ((v2-v1) * i / steps);
  302. // convert to RGB
  303. uint32_t grb = hsv2grb(h, s, v);
  304. *p++ = ((grb & 0x00FF0000) >> 16) * state->brightness / BRIGHTNESS_MAX;
  305. *p++ = ((grb & 0x0000FF00) >> 8) * state->brightness / BRIGHTNESS_MAX;
  306. *p++ = (grb & 0x000000FF) * state->brightness / BRIGHTNESS_MAX;
  307. for (j = 3; j < pixbuf_channels(buffer); j++) {
  308. *p++ = 0;
  309. }
  310. }
  311. }
  312. return 0;
  313. }
  314. static int ws2812_effects_gradient_rgb(const char *buffer1, size_t length1) {
  315. pixbuf * buffer = state->buffer;
  316. int segments = (length1 / pixbuf_channels(buffer)) - 1;
  317. int segmentSize = buffer->npix / segments;
  318. uint8_t g1, r1, b1, g2, r2, b2;
  319. int i,j,k;
  320. g2 = *buffer1++;
  321. r2 = *buffer1++;
  322. b2 = *buffer1++;
  323. // skip non-rgb components
  324. for (j = 3; j < pixbuf_channels(buffer); j++)
  325. {
  326. *buffer1++;
  327. }
  328. // reference to buffer memory
  329. uint8_t * p = &buffer->values[0];
  330. for (k = 0; k < segments; k++) {
  331. g1 = g2;
  332. r1 = r2;
  333. b1 = b2;
  334. g2 = *buffer1++;
  335. r2 = *buffer1++;
  336. b2 = *buffer1++;
  337. for (j = 3; j < pixbuf_channels(buffer); j++) {
  338. *buffer1++;
  339. }
  340. // Fill buffer
  341. int numPixels = segmentSize;
  342. // make sure we fill the strip correctly in case of rounding errors
  343. if (k == segments - 1) {
  344. numPixels = buffer->npix - (segmentSize * (segments - 1));
  345. }
  346. int steps = numPixels - 1;
  347. for(i = 0; i < numPixels; i++) {
  348. *p++ = (g1 + ((g2-g1) * i / steps)) * state->brightness / BRIGHTNESS_MAX;
  349. *p++ = (r1 + ((r2-r1) * i / steps)) * state->brightness / BRIGHTNESS_MAX;
  350. *p++ = (b1 + ((b2-b1) * i / steps)) * state->brightness / BRIGHTNESS_MAX;
  351. for (j = 3; j < pixbuf_channels(buffer); j++)
  352. {
  353. *p++ = 0;
  354. }
  355. }
  356. }
  357. return 0;
  358. }
  359. /*
  360. * Lights all LEDs in one random color up. Then switches them
  361. * to the next random color.
  362. */
  363. static int ws2812_effects_mode_random_color() {
  364. state->mode_color_index = get_random_wheel_index(state->mode_color_index);
  365. pixbuf * buffer = state->buffer;
  366. uint32_t color = color_wheel(state->mode_color_index);
  367. uint8_t r = ((color & 0x00FF0000) >> 16) * state->brightness / BRIGHTNESS_MAX;
  368. uint8_t g = ((color & 0x0000FF00) >> 8) * state->brightness / BRIGHTNESS_MAX;
  369. uint8_t b = ((color & 0x000000FF) >> 0) * state->brightness / BRIGHTNESS_MAX;
  370. // Fill buffer
  371. int i,j;
  372. uint8_t * p = &buffer->values[0];
  373. for(i = 0; i < buffer->npix; i++) {
  374. *p++ = g;
  375. *p++ = r;
  376. *p++ = b;
  377. for (j = 3; j < pixbuf_channels(buffer); j++)
  378. {
  379. *p++ = 0;
  380. }
  381. }
  382. }
  383. /*
  384. * Cycles all LEDs at once through a rainbow.
  385. */
  386. static int ws2812_effects_mode_rainbow() {
  387. pixbuf * buffer = state->buffer;
  388. uint32_t color = color_wheel(state->counter_mode_step);
  389. uint8_t r = (color & 0x00FF0000) >> 16;
  390. uint8_t g = (color & 0x0000FF00) >> 8;
  391. uint8_t b = (color & 0x000000FF) >> 0;
  392. // Fill buffer
  393. int i,j;
  394. uint8_t * p = &buffer->values[0];
  395. for(i = 0; i < buffer->npix; i++) {
  396. *p++ = g * state->brightness / BRIGHTNESS_MAX;
  397. *p++ = r * state->brightness / BRIGHTNESS_MAX;
  398. *p++ = b * state->brightness / BRIGHTNESS_MAX;
  399. for (j = 3; j < pixbuf_channels(buffer); j++)
  400. {
  401. *p++ = 0;
  402. }
  403. }
  404. state->counter_mode_step = (state->counter_mode_step + 1) % 360;
  405. return 0;
  406. }
  407. /*
  408. * Cycles a rainbow over the entire string of LEDs.
  409. */
  410. static int ws2812_effects_mode_rainbow_cycle(int repeat_count) {
  411. pixbuf * buffer = state->buffer;
  412. int i,j;
  413. uint8_t * p = &buffer->values[0];
  414. for(i = 0; i < buffer->npix; i++) {
  415. uint16_t wheel_index = (i * 360 / buffer->npix * repeat_count) % 360;
  416. uint32_t color = color_wheel(wheel_index);
  417. uint8_t r = ((color & 0x00FF0000) >> 16) * state->brightness / BRIGHTNESS_MAX;
  418. uint8_t g = ((color & 0x0000FF00) >> 8) * state->brightness / BRIGHTNESS_MAX;
  419. uint8_t b = ((color & 0x000000FF) >> 0) * state->brightness / BRIGHTNESS_MAX;
  420. *p++ = g;
  421. *p++ = r;
  422. *p++ = b;
  423. for (j = 3; j < pixbuf_channels(buffer); j++)
  424. {
  425. *p++ = 0;
  426. }
  427. }
  428. return 0;
  429. }
  430. /*
  431. * Random flickering.
  432. */
  433. static int ws2812_effects_mode_flicker_int(uint8_t max_flicker) {
  434. pixbuf * buffer = state->buffer;
  435. uint8_t p_g = state->color[0];
  436. uint8_t p_r = state->color[1];
  437. uint8_t p_b = state->color[2];
  438. // Fill buffer
  439. int i,j;
  440. uint8_t * p = &buffer->values[0];
  441. for(i = 0; i < buffer->npix; i++) {
  442. int flicker = rand() % (max_flicker > 0 ? max_flicker : 1);
  443. int r1 = p_r-flicker;
  444. int g1 = p_g-flicker;
  445. int b1 = p_b-flicker;
  446. if(g1<0) g1=0;
  447. if(r1<0) r1=0;
  448. if(b1<0) b1=0;
  449. *p++ = g1 * state->brightness / BRIGHTNESS_MAX;
  450. *p++ = r1 * state->brightness / BRIGHTNESS_MAX;
  451. *p++ = b1 * state->brightness / BRIGHTNESS_MAX;
  452. for (j = 3; j < pixbuf_channels(buffer); j++) {
  453. *p++ = 0;
  454. }
  455. }
  456. return 0;
  457. }
  458. /**
  459. * Halloween effect
  460. */
  461. static int ws2812_effects_mode_halloween() {
  462. pixbuf * buffer = state->buffer;
  463. int g1 = 50 * state->brightness / BRIGHTNESS_MAX;
  464. int r1 = 255 * state->brightness / BRIGHTNESS_MAX;
  465. int b1 = 0 * state->brightness / BRIGHTNESS_MAX;
  466. int g2 = 0 * state->brightness / BRIGHTNESS_MAX;
  467. int r2 = 255 * state->brightness / BRIGHTNESS_MAX;
  468. int b2 = 130 * state->brightness / BRIGHTNESS_MAX;
  469. // Fill buffer
  470. int i,j;
  471. uint8_t * p = &buffer->values[0];
  472. for(i = 0; i < buffer->npix; i++) {
  473. *p++ = (i % 4 < 2) ? g1 : g2;
  474. *p++ = (i % 4 < 2) ? r1 : r2;
  475. *p++ = (i % 4 < 2) ? b1 : b2;
  476. for (j = 3; j < pixbuf_channels(buffer); j++)
  477. {
  478. *p++ = 0;
  479. }
  480. }
  481. return 0;
  482. }
  483. static int ws2812_effects_mode_circus_combustus() {
  484. pixbuf * buffer = state->buffer;
  485. int g1 = 0 * state->brightness / BRIGHTNESS_MAX;
  486. int r1 = 255 * state->brightness / BRIGHTNESS_MAX;
  487. int b1 = 0 * state->brightness / BRIGHTNESS_MAX;
  488. int g2 = 255 * state->brightness / BRIGHTNESS_MAX;
  489. int r2 = 255 * state->brightness / BRIGHTNESS_MAX;
  490. int b2 = 255 * state->brightness / BRIGHTNESS_MAX;
  491. // Fill buffer
  492. int i,j;
  493. uint8_t * p = &buffer->values[0];
  494. for(i = 0; i < buffer->npix; i++) {
  495. if (i % 6 < 2) {
  496. *p++ = g1;
  497. *p++ = r1;
  498. *p++ = b1;
  499. }
  500. else if (i % 6 < 4) {
  501. *p++ = g2;
  502. *p++ = r2;
  503. *p++ = b2;
  504. }
  505. else {
  506. *p++ = 0;
  507. *p++ = 0;
  508. *p++ = 0;
  509. }
  510. for (j = 3; j < pixbuf_channels(buffer); j++)
  511. {
  512. *p++ = 0;
  513. }
  514. }
  515. return 0;
  516. }
  517. /*
  518. * K.I.T.T.
  519. */
  520. static int ws2812_effects_mode_larson_scanner() {
  521. pixbuf * buffer = state->buffer;
  522. int led_index = 0;
  523. for(int i=0; i < pixbuf_size(buffer); i++) {
  524. buffer->values[i] = buffer->values[i] >> 2;
  525. }
  526. uint16_t pos = 0;
  527. if(state->counter_mode_step < buffer->npix) {
  528. pos = state->counter_mode_step;
  529. } else {
  530. pos = (buffer->npix * 2) - state->counter_mode_step - 2;
  531. }
  532. pos = pos * pixbuf_channels(buffer);
  533. buffer->values[pos + 1] = state->color[1];
  534. buffer->values[pos] = state->color[0];
  535. buffer->values[pos + 2] = state->color[2];
  536. state->counter_mode_step = (state->counter_mode_step + 1) % ((buffer->npix * 2) - 2);
  537. }
  538. static int ws2812_effects_mode_color_wipe() {
  539. pixbuf * buffer = state->buffer;
  540. int led_index = (state->counter_mode_step % buffer->npix) * pixbuf_channels(buffer);
  541. if (state->counter_mode_step >= buffer->npix)
  542. {
  543. buffer->values[led_index] = 0;
  544. buffer->values[led_index + 1] = 0;
  545. buffer->values[led_index + 2] = 0;
  546. }
  547. else
  548. {
  549. uint8_t px_r = state->color[1] * state->brightness / BRIGHTNESS_MAX;
  550. uint8_t px_g = state->color[0] * state->brightness / BRIGHTNESS_MAX;
  551. uint8_t px_b = state->color[2] * state->brightness / BRIGHTNESS_MAX;
  552. buffer->values[led_index] = px_g;
  553. buffer->values[led_index + 1] = px_r;
  554. buffer->values[led_index + 2] = px_b;
  555. }
  556. state->counter_mode_step = (state->counter_mode_step + 1) % (buffer->npix * 2);
  557. }
  558. static int ws2812_effects_mode_random_dot(uint8_t dots) {
  559. pixbuf * buffer = state->buffer;
  560. // fade out
  561. for(int i=0; i < pixbuf_size(buffer); i++) {
  562. buffer->values[i] = buffer->values[i] >> 1;
  563. }
  564. for(int i=0; i < dots; i++) {
  565. // pick random pixel
  566. int led_index = rand() % buffer->npix;
  567. uint32_t color = (state->color[0] << 16) | (state->color[1] << 8) | state->color[2];
  568. if (pixbuf_channels(buffer) == 4) {
  569. color = color | (state->color[3] << 24);
  570. }
  571. ws2812_set_pixel(led_index, color);
  572. }
  573. state->counter_mode_step = (state->counter_mode_step + 1) % ((buffer->npix * 2) - 2);
  574. }
  575. static uint32_t ws2812_effects_mode_delay()
  576. {
  577. // check if delay has been set explicitly
  578. if (state->speed == 0 && state->mode_delay > 0)
  579. {
  580. return state->mode_delay;
  581. }
  582. uint32_t delay = 10;
  583. switch (state->effect_type) {
  584. case WS2812_EFFECT_BLINK:
  585. case WS2812_EFFECT_RAINBOW:
  586. case WS2812_EFFECT_RAINBOW_CYCLE:
  587. delay = 10 + ((1000 * (uint32_t)(SPEED_MAX - state->speed)) / SPEED_MAX);
  588. break;
  589. case WS2812_EFFECT_FLICKER:
  590. case WS2812_EFFECT_FIRE_FLICKER:
  591. case WS2812_EFFECT_FIRE_FLICKER_SOFT:
  592. case WS2812_EFFECT_FIRE_FLICKER_INTENSE:
  593. delay = 30 + (rand() % 100) + (200 * (SPEED_MAX - state->speed) / SPEED_MAX);
  594. break;
  595. case WS2812_EFFECT_RANDOM_COLOR:
  596. case WS2812_EFFECT_HALLOWEEN:
  597. case WS2812_EFFECT_CIRCUS_COMBUSTUS:
  598. case WS2812_EFFECT_LARSON_SCANNER:
  599. case WS2812_EFFECT_CYCLE:
  600. case WS2812_EFFECT_COLOR_WIPE:
  601. case WS2812_EFFECT_RANDOM_DOT:
  602. delay = 10 + ((1000 * (uint32_t)(SPEED_MAX - state->speed)) / SPEED_MAX);
  603. break;
  604. }
  605. return delay;
  606. }
  607. static void ws2812_effects_do_shift(void)
  608. {
  609. pixbuf_shift(state->buffer, &state->shift);
  610. ws2812_effects_write(state->buffer);
  611. }
  612. /**
  613. * run loop for the effects.
  614. */
  615. static void ws2812_effects_loop(void* p)
  616. {
  617. if (state->effect_type == WS2812_EFFECT_BLINK)
  618. {
  619. ws2812_effects_mode_blink();
  620. }
  621. else if (state->effect_type == WS2812_EFFECT_RAINBOW)
  622. {
  623. ws2812_effects_mode_rainbow();
  624. }
  625. else if (state->effect_type == WS2812_EFFECT_RAINBOW_CYCLE)
  626. {
  627. // the rainbow cycle effect can be achieved by shifting the buffer
  628. ws2812_effects_do_shift();
  629. }
  630. else if (state->effect_type == WS2812_EFFECT_FLICKER)
  631. {
  632. int flicker_value = state->effect_int_param1 != EFFECT_PARAM_INVALID ? state->effect_int_param1 : 100;
  633. if (flicker_value == 0) {
  634. flicker_value = 50;
  635. }
  636. ws2812_effects_mode_flicker_int(flicker_value);
  637. state->counter_mode_step = (state->counter_mode_step + 1) % 256;
  638. }
  639. else if (state->effect_type == WS2812_EFFECT_FIRE_FLICKER)
  640. {
  641. ws2812_effects_mode_flicker_int(110);
  642. state->counter_mode_step = (state->counter_mode_step + 1) % 256;
  643. }
  644. else if (state->effect_type == WS2812_EFFECT_FIRE_FLICKER_SOFT)
  645. {
  646. ws2812_effects_mode_flicker_int(70);
  647. state->counter_mode_step = (state->counter_mode_step + 1) % 256;
  648. }
  649. else if (state->effect_type == WS2812_EFFECT_FIRE_FLICKER_INTENSE)
  650. {
  651. ws2812_effects_mode_flicker_int(170);
  652. state->counter_mode_step = (state->counter_mode_step + 1) % 256;
  653. }
  654. else if (state->effect_type == WS2812_EFFECT_RANDOM_COLOR)
  655. {
  656. ws2812_effects_mode_random_color();
  657. }
  658. else if (state->effect_type == WS2812_EFFECT_HALLOWEEN)
  659. {
  660. ws2812_effects_do_shift();
  661. }
  662. else if (state->effect_type == WS2812_EFFECT_CIRCUS_COMBUSTUS)
  663. {
  664. ws2812_effects_do_shift();
  665. }
  666. else if (state->effect_type == WS2812_EFFECT_LARSON_SCANNER)
  667. {
  668. ws2812_effects_mode_larson_scanner();
  669. }
  670. else if (state->effect_type == WS2812_EFFECT_CYCLE)
  671. {
  672. ws2812_effects_do_shift();
  673. }
  674. else if (state->effect_type == WS2812_EFFECT_COLOR_WIPE)
  675. {
  676. ws2812_effects_mode_color_wipe();
  677. }
  678. else if (state->effect_type == WS2812_EFFECT_RANDOM_DOT)
  679. {
  680. uint8_t dots = state->effect_int_param1 != EFFECT_PARAM_INVALID ? state->effect_int_param1 : 1;
  681. ws2812_effects_mode_random_dot(dots);
  682. }
  683. // set the new delay for this effect
  684. state->mode_delay = ws2812_effects_mode_delay();
  685. // call count
  686. state->counter_mode_call = (state->counter_mode_call + 1) % UINT32_MAX;
  687. // write the buffer
  688. ws2812_effects_write(state->buffer);
  689. // set the timer
  690. if (state->running == 1 && state->mode_delay >= 10)
  691. if (state->running == 1 && state->mode_delay >= 10)
  692. {
  693. os_timer_disarm(&(state->os_t));
  694. os_timer_arm(&(state->os_t), state->mode_delay, FALSE);
  695. }
  696. }
  697. /**
  698. * Set the active effect mode
  699. */
  700. static int ws2812_effects_set_mode(lua_State* L) {
  701. luaL_argcheck(L, state != NULL, 1, LIBRARY_NOT_INITIALIZED_ERROR_MSG);
  702. // opts must be same order as effect type enum
  703. static const char * const opts[] = {"static", "blink", "gradient", "gradient_rgb", "random_color", "rainbow",
  704. "rainbow_cycle", "flicker", "fire", "fire_soft", "fire_intense", "halloween", "circus_combustus",
  705. "larson_scanner", "cycle", "color_wipe", "random_dot", NULL};
  706. int type = luaL_checkoption(L, 1, NULL, opts);
  707. state->effect_type = type;
  708. int effect_param = EFFECT_PARAM_INVALID;
  709. // check additional int parameter
  710. // First mandatory parameter
  711. int arg_type = lua_type(L, 2);
  712. if (arg_type == LUA_TNONE || arg_type == LUA_TNIL)
  713. {
  714. // we don't have a second parameter
  715. }
  716. else if(arg_type == LUA_TNUMBER)
  717. {
  718. effect_param = luaL_optinteger( L, 2, EFFECT_PARAM_INVALID );
  719. }
  720. // initialize the effect
  721. state->counter_mode_step = 0;
  722. switch (state->effect_type) {
  723. case WS2812_EFFECT_STATIC:
  724. // fill with currently set color
  725. ws2812_effects_fill_color();
  726. state->mode_delay = 250;
  727. break;
  728. case WS2812_EFFECT_BLINK:
  729. ws2812_effects_mode_blink();
  730. break;
  731. case WS2812_EFFECT_GRADIENT:
  732. if(arg_type == LUA_TSTRING)
  733. {
  734. size_t length1;
  735. const char *buffer1 = lua_tolstring(L, 2, &length1);
  736. if ((length1 / pixbuf_channels(state->buffer) < 2) || (length1 % pixbuf_channels(state->buffer) != 0))
  737. {
  738. luaL_argerror(L, 2, "must be at least two colors and same size as buffer colors");
  739. }
  740. ws2812_effects_gradient(buffer1, length1);
  741. ws2812_effects_write(state->buffer);
  742. }
  743. else
  744. {
  745. luaL_argerror(L, 2, "string expected");
  746. }
  747. break;
  748. case WS2812_EFFECT_GRADIENT_RGB:
  749. if(arg_type == LUA_TSTRING)
  750. {
  751. size_t length1;
  752. const char *buffer1 = lua_tolstring(L, 2, &length1);
  753. if ((length1 / pixbuf_channels(state->buffer) < 2) || (length1 % pixbuf_channels(state->buffer) != 0))
  754. {
  755. luaL_argerror(L, 2, "must be at least two colors and same size as buffer colors");
  756. }
  757. ws2812_effects_gradient_rgb(buffer1, length1);
  758. ws2812_effects_write(state->buffer);
  759. }
  760. else
  761. {
  762. luaL_argerror(L, 2, "string expected");
  763. }
  764. break;
  765. case WS2812_EFFECT_RANDOM_COLOR:
  766. ws2812_effects_mode_random_color();
  767. break;
  768. case WS2812_EFFECT_RAINBOW:
  769. ws2812_effects_mode_rainbow();
  770. break;
  771. case WS2812_EFFECT_RAINBOW_CYCLE:
  772. ws2812_effects_mode_rainbow_cycle(effect_param != EFFECT_PARAM_INVALID ? effect_param : 1);
  773. pixbuf_prepare_shift(state->buffer, &state->shift, 1, PIXBUF_SHIFT_CIRCULAR, 1, -1);
  774. break;
  775. case WS2812_EFFECT_FLICKER:
  776. state->effect_int_param1 = effect_param;
  777. break;
  778. case WS2812_EFFECT_FIRE_FLICKER:
  779. case WS2812_EFFECT_FIRE_FLICKER_SOFT:
  780. case WS2812_EFFECT_FIRE_FLICKER_INTENSE:
  781. state->color[0] = 255-40;
  782. state->color[1] = 255;
  783. state->color[2] = 40;
  784. state->color[3] = 0;
  785. break;
  786. case WS2812_EFFECT_HALLOWEEN:
  787. ws2812_effects_mode_halloween();
  788. pixbuf_prepare_shift(state->buffer, &state->shift, 1, PIXBUF_SHIFT_CIRCULAR, 1, -1);
  789. break;
  790. case WS2812_EFFECT_CIRCUS_COMBUSTUS:
  791. ws2812_effects_mode_circus_combustus();
  792. pixbuf_prepare_shift(state->buffer, &state->shift, 1, PIXBUF_SHIFT_CIRCULAR, 1, -1);
  793. break;
  794. case WS2812_EFFECT_LARSON_SCANNER:
  795. ws2812_effects_mode_larson_scanner();
  796. break;
  797. case WS2812_EFFECT_CYCLE:
  798. if (effect_param != EFFECT_PARAM_INVALID) {
  799. state->effect_int_param1 = effect_param;
  800. }
  801. pixbuf_prepare_shift(state->buffer, &state->shift, state->effect_int_param1, PIXBUF_SHIFT_CIRCULAR, 1, -1);
  802. break;
  803. case WS2812_EFFECT_COLOR_WIPE:
  804. // fill buffer with black. r,g,b,w = 0
  805. ws2812_effects_fill_buffer(0, 0, 0, 0);
  806. ws2812_effects_mode_color_wipe();
  807. break;
  808. case WS2812_EFFECT_RANDOM_DOT:
  809. // check if more than 1 dot shall be set
  810. state->effect_int_param1 = effect_param;
  811. // fill buffer with black. r,g,b,w = 0
  812. ws2812_effects_fill_buffer(0, 0, 0, 0);
  813. break;
  814. }
  815. }
  816. /*
  817. * Start the effect execution
  818. */
  819. static int ws2812_effects_start(lua_State* L) {
  820. //NODE_DBG("pin:%d, level:%d \n", pin, level);
  821. luaL_argcheck(L, state != NULL, 1, LIBRARY_NOT_INITIALIZED_ERROR_MSG);
  822. if (state != NULL) {
  823. os_timer_disarm(&(state->os_t));
  824. state->running = 1;
  825. state->counter_mode_call = 0;
  826. state->counter_mode_step = 0;
  827. // set the timer
  828. os_timer_setfn(&(state->os_t), ws2812_effects_loop, NULL);
  829. os_timer_arm(&(state->os_t), state->mode_delay, FALSE);
  830. }
  831. return 0;
  832. }
  833. /*
  834. * Stop the effect execution
  835. */
  836. static int ws2812_effects_stop(lua_State* L) {
  837. luaL_argcheck(L, state != NULL, 1, LIBRARY_NOT_INITIALIZED_ERROR_MSG);
  838. if (state != NULL) {
  839. os_timer_disarm(&(state->os_t));
  840. state->running = 0;
  841. }
  842. return 0;
  843. }
  844. static int ws2812_effects_tostring(lua_State* L) {
  845. luaL_Buffer result;
  846. luaL_buffinit(L, &result);
  847. luaL_addchar(&result, '[');
  848. luaL_addstring(&result, "effects");
  849. luaL_addchar(&result, ']');
  850. luaL_pushresult(&result);
  851. return 1;
  852. }
  853. LROT_BEGIN(ws2812_effects_map, NULL, 0)
  854. LROT_FUNCENTRY( __tostring, ws2812_effects_tostring )
  855. LROT_FUNCENTRY( init, ws2812_effects_init )
  856. LROT_FUNCENTRY( set_brightness, ws2812_effects_set_brightness )
  857. LROT_FUNCENTRY( set_color, ws2812_effects_set_color )
  858. LROT_FUNCENTRY( set_speed, ws2812_effects_set_speed )
  859. LROT_FUNCENTRY( set_delay, ws2812_effects_set_delay )
  860. LROT_FUNCENTRY( set_mode, ws2812_effects_set_mode )
  861. LROT_FUNCENTRY( start, ws2812_effects_start )
  862. LROT_FUNCENTRY( stop, ws2812_effects_stop )
  863. LROT_FUNCENTRY( get_delay, ws2812_effects_get_delay )
  864. LROT_FUNCENTRY( get_speed, ws2812_effects_get_speed )
  865. LROT_END(ws2812_effects_map, NULL, 0)
  866. NODEMCU_MODULE(WS2812_EFFECTS, "ws2812_effects", ws2812_effects_map, NULL);