ws2812_effects.c 26 KB

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