1 #include <twr_led_strip.h>
3 #define TWR_LED_STRIP_NULL_TASK TWR_SCHEDULER_MAX_TASKS + 1
5 static uint32_t _twr_led_strip_wheel(
int position);
6 static void _twr_led_strip_get_heat_map_color(
float value,
float *red,
float *green,
float *blue);
11 self->_buffer = buffer;
12 self->_driver = driver;
13 self->_effect.task_id = TWR_LED_STRIP_NULL_TASK;
14 self->_driver->init(self->_buffer);
15 self->_brightness = 255;
18 void twr_led_strip_set_event_handler(
twr_led_strip_t *
self,
void (*event_handler)(
twr_led_strip_t *, twr_led_strip_event_t,
void *),
void *event_param)
20 self->_event_handler = event_handler;
21 self->_event_param = event_param;
26 return self->_buffer->count;
29 twr_led_strip_type_t twr_led_strip_get_strip_type(
twr_led_strip_t *
self)
31 return self->_buffer->type;
34 void twr_led_strip_set_pixel(
twr_led_strip_t *
self,
int position, uint32_t color)
36 if (position < 0 || position >= self->_buffer->count)
41 if (self->_brightness != 255)
43 twr_led_strip_set_pixel_rgbw(
self, position, color >> 24, color >> 16, color >> 8, color);
47 self->_driver->set_pixel(position, color);
51 void twr_led_strip_set_pixel_rgbw(
twr_led_strip_t *
self,
int position, uint8_t r, uint8_t g, uint8_t b, uint8_t w)
53 if (position < 0 || position >= self->_buffer->count)
58 if (self->_brightness != 255)
60 r = ((uint16_t) r * self->_brightness) >> 8;
61 g = ((uint16_t) g * self->_brightness) >> 8;
62 b = ((uint16_t) b * self->_brightness) >> 8;
63 w = ((uint16_t) w * self->_brightness) >> 8;
65 self->_driver->set_pixel_rgbw(position, r, g, b, w);
68 bool twr_led_strip_set_rgbw_framebuffer(
twr_led_strip_t *
self, uint8_t *framebuffer,
size_t length)
70 if (length > (
size_t) (self->_buffer->type * self->_buffer->count))
77 if (self->_buffer->type == TWR_LED_STRIP_TYPE_RGBW)
79 for (
size_t i = 0; i < length; i +=
self->_buffer->type)
81 self->_driver->set_pixel_rgbw(position++, framebuffer[i], framebuffer[i + 1], framebuffer[i + 2], framebuffer[i + 3]);
86 for (
size_t i = 0; i < length; i +=
self->_buffer->type)
88 self->_driver->set_pixel_rgbw(position++, framebuffer[i], framebuffer[i + 1], framebuffer[i + 2], 0);
97 for (
int i = 0; i <
self->_buffer->count; i++)
99 twr_led_strip_set_pixel(
self, i, color);
105 return self->_driver->write();
110 return self->_driver->is_ready();
113 void twr_led_strip_set_brightness(
twr_led_strip_t *
self, uint8_t brightness)
115 self->_brightness = brightness;
120 if (self->_effect.task_id != TWR_LED_STRIP_NULL_TASK)
124 self->_effect.task_id = TWR_LED_STRIP_NULL_TASK;
130 twr_led_strip_effect_stop(
self);
132 if (self->_event_handler != NULL)
134 self->_event_handler(
self, TWR_LED_STRIP_EVENT_EFFECT_DONE, self->_event_param);
138 static void _twr_led_strip_effect_test_task(
void *param)
142 if (!self->_driver->is_ready())
149 uint8_t intensity = 255 * (
self->_effect.led + 1) / (self->_buffer->count + 1);
151 if (self->_effect.round == 0)
153 self->_driver->set_pixel_rgbw(self->_effect.led, intensity, 0, 0, 0);
155 else if (self->_effect.round == 1)
157 self->_driver->set_pixel_rgbw(self->_effect.led, 0, intensity, 0, 0);
159 else if (self->_effect.round == 2)
161 self->_driver->set_pixel_rgbw(self->_effect.led, 0, 0, intensity, 0);
163 else if (self->_effect.round == 3)
165 if (self->_buffer->type == TWR_LED_STRIP_TYPE_RGBW)
167 self->_driver->set_pixel_rgbw(self->_effect.led, 0, 0, 0, intensity);
171 self->_driver->set_pixel_rgbw(self->_effect.led, intensity, intensity, intensity, 0);
176 self->_driver->set_pixel_rgbw(self->_effect.led, 0, 0, 0, 0);
181 if (self->_effect.led == self->_buffer->count)
183 self->_effect.led = 0;
185 self->_effect.round++;
188 self->_driver->write();
190 if (self->_effect.round == 5)
192 _twr_led_strip_effect_done(
self);
201 twr_led_strip_effect_stop(
self);
203 self->_effect.led = 0;
204 self->_effect.round = 0;
205 self->_effect.wait = 2000 /
self->_buffer->count;
207 twr_led_strip_fill(
self, 0x00000000);
212 static void _twr_led_strip_effect_rainbow_task(
void *param)
216 if (!self->_driver->is_ready())
223 for(
int i = 0; i<
self->_buffer->count; i++) {
224 twr_led_strip_set_pixel(
self, i, _twr_led_strip_wheel((i + self->_effect.round) & 255));
227 self->_effect.round++;
229 self->_driver->write();
236 twr_led_strip_effect_stop(
self);
238 self->_effect.round = 0;
239 self->_effect.wait = wait;
244 static void _twr_led_strip_effect_rainbow_cycle_task(
void *param)
248 if (!self->_driver->is_ready())
255 for(
int i = 0; i<
self->_buffer->count; i++) {
256 twr_led_strip_set_pixel(
self, i, _twr_led_strip_wheel(((i * 256 / self->_buffer->count) + self->_effect.round) & 255));
259 self->_effect.round++;
261 self->_driver->write();
268 twr_led_strip_effect_stop(
self);
270 self->_effect.round = 0;
271 self->_effect.wait = wait;
276 static void _twr_led_strip_effect_color_wipe_task(
void *param)
280 if (!self->_driver->is_ready())
287 twr_led_strip_set_pixel(
self, self->_effect.led++, self->_effect.color);
289 if (self->_effect.led == self->_buffer->count)
291 _twr_led_strip_effect_done(
self);
295 self->_driver->write();
303 twr_led_strip_effect_stop(
self);
305 self->_effect.led = 0;
306 self->_effect.wait = wait;
307 self->_effect.color = color;
312 static void _twr_led_strip_effect_theater_chase_task(
void *param)
316 if (!self->_driver->is_ready())
323 for (
int i = self->_effect.led; i < self->_buffer->count; i += 3) {
324 self->_driver->set_pixel(i, 0);
329 if (self->_effect.led == 3)
331 self->_effect.led = 0;
334 for (
int i = self->_effect.led ; i < self->_buffer->count; i += 3) {
335 twr_led_strip_set_pixel(
self, i, self->_effect.color);
338 self->_driver->write();
346 twr_led_strip_effect_stop(
self);
348 self->_effect.led = 0;
349 self->_effect.round = 0;
350 self->_effect.color = color;
351 self->_effect.wait = wait;
356 static void _twr_led_strip_effect_theater_chase_rainbow_task(
void *param)
360 if (!self->_driver->is_ready())
367 for (
int i = self->_effect.led; i < self->_buffer->count; i += 3) {
368 self->_driver->set_pixel(i, 0);
373 if (self->_effect.led == 3)
375 self->_effect.led = 0;
378 for (
int i = self->_effect.led; i < self->_buffer->count; i += 3) {
379 twr_led_strip_set_pixel(
self, i, _twr_led_strip_wheel((i + self->_effect.round) % 255) );
382 self->_driver->write();
384 self->_effect.round++;
392 twr_led_strip_effect_stop(
self);
394 self->_effect.led = 0;
395 self->_effect.round = 0;
396 self->_effect.wait = wait;
398 self->_effect.task_id =
twr_scheduler_register(_twr_led_strip_effect_theater_chase_rainbow_task,
self, 0);
401 static void twr_led_strip_effect_stroboscope_task(
void *param)
405 if (!self->_driver->is_ready())
412 uint32_t color = (
self->_effect.round & 1) == 0 ? self->_effect.color : 0;
414 twr_led_strip_fill(
self, color);
416 twr_led_strip_write(
self);
418 self->_effect.round++;
425 twr_led_strip_effect_stop(
self);
427 self->_effect.wait = wait;
429 self->_effect.round = 0;
431 self->_effect.color = color;
436 void _twr_led_strip_effect_icicle_task(
void *param)
440 if (!self->_driver->is_ready())
447 const int length = 10;
449 for (
int i = self->_effect.led; (i < self->_effect.led + length) && i < self->_buffer->count; i++) {
456 twr_led_strip_set_pixel(
self, i, 0x00);
461 if (self->_effect.led == self->_buffer->count)
463 self->_effect.led = -length;
467 uint8_t r, g, b, w, dr, dg, db, dw;
469 dr = ((uint8_t) (self->_effect.color >> 24)) / length;
470 dg = ((uint8_t) (self->_effect.color >> 16)) / length;
471 db = ((uint8_t) (self->_effect.color >> 8)) / length;
472 dw = ((uint8_t) (self->_effect.color)) / length;
479 for (
int i = self->_effect.led; (i < self->_effect.led + length) && i <
self->_buffer->count; i++) {
486 twr_led_strip_set_pixel_rgbw(
self, i, r, g, b, w);
494 twr_led_strip_write(
self);
501 twr_led_strip_effect_stop(
self);
503 self->_effect.color = color;
505 self->_effect.wait = wait;
507 self->_effect.led = -10;
512 static void _twr_led_strip_effect_pulse_color_task(
void *param)
516 if (!self->_driver->is_ready())
523 uint8_t r =
self->_effect.color >> 24;
524 uint8_t g =
self->_effect.color >> 16;
525 uint8_t b =
self->_effect.color >> 8;
526 uint8_t w =
self->_effect.color;
528 uint8_t brightness = (abs(19 - self->_effect.round) + 1) * (255 / 20);
530 if (++self->_effect.round == 38)
532 self->_effect.round = 0;
535 r = ((uint16_t) r * brightness) >> 8;
536 g = ((uint16_t) g * brightness) >> 8;
537 b = ((uint16_t) b * brightness) >> 8;
538 w = ((uint16_t) w * brightness) >> 8;
540 for (
int i = 0; i <
self->_buffer->count; i++)
542 twr_led_strip_set_pixel_rgbw(
self, i, r, g, b, w);
545 self->_driver->write();
552 twr_led_strip_effect_stop(
self);
554 self->_effect.round = 0;
555 self->_effect.wait = wait;
556 self->_effect.color = color;
561 void twr_led_strip_thermometer(
twr_led_strip_t *
self,
float temperature,
float min,
float max, uint8_t white_dots,
float set_point, uint32_t color)
565 int max_i = ((float)self->_buffer->count / (
float)(fabs(max) + fabs(min))) * temperature;
567 if (max_i > self->_buffer->count)
569 max_i =
self->_buffer->count;
581 for (
int i = 0; i < max_i; i++)
583 _twr_led_strip_get_heat_map_color((
float)i / self->_buffer->count, &red, &green, &blue);
585 self->_driver->set_pixel_rgbw(i, self->_brightness * red, self->_brightness * green, self->_brightness * blue, 0);
588 if (self->_buffer->type == TWR_LED_STRIP_TYPE_RGBW)
590 for (
int i = max_i; i <
self->_buffer->count; i++)
592 self->_driver->set_pixel_rgbw(i, 0, 0, 0, white_dots);
597 for (
int i = max_i; i <
self->_buffer->count; i++)
599 self->_driver->set_pixel_rgbw(i, white_dots, white_dots, white_dots, 0);
603 if ((min < set_point) && (max > set_point))
607 int color_i = ((float)self->_buffer->count / (
float)(fabs(max) + fabs(min))) * set_point;
609 self->_driver->set_pixel(color_i, color);
612 twr_led_strip_write(
self);
615 static uint32_t _twr_led_strip_wheel(
int position) {
618 return ((position * 3) << 24) | ((255 - position * 3) << 16);
620 else if (position < 170)
623 return ((255 - position * 3) << 24) | ((position * 3) << 8);
628 return ((position * 3) << 16) | ((255 - position * 3) << 8);
632 static void _twr_led_strip_get_heat_map_color(
float value,
float *red,
float *green,
float *blue)
634 const int NUM_COLORS = 4;
635 const float color[4][3] = { {0,0,1}, {0,1,0}, {1,1,0}, {1,0,0} };
639 float fractBetween = 0;
647 idx1 = idx2 = NUM_COLORS - 1;
651 value = value * (NUM_COLORS - 1);
654 fractBetween = value - (float)idx1;
657 *red = (color[idx2][0] - color[idx1][0]) * fractBetween + color[idx1][0];
658 *green = (color[idx2][1] - color[idx1][1]) * fractBetween + color[idx1][1];
659 *blue = (color[idx2][2] - color[idx1][2]) * fractBetween + color[idx1][2];
void twr_scheduler_plan_current_relative(twr_tick_t tick)
Schedule current task to tick relative from current spin.
void twr_scheduler_unregister(twr_scheduler_task_id_t task_id)
Unregister specified task.
void twr_scheduler_plan_current_now(void)
Schedule current task for immediate execution.
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
uint64_t twr_tick_t
Timestamp data type.