11static const char *
const TAG =
"display";
20 const int32_t dx = abs(x2 - x1), sx = x1 < x2 ? 1 : -1;
21 const int32_t dy = -abs(y2 - y1), sy = y1 < y2 ? 1 : -1;
22 int32_t err = dx + dy;
26 if (x1 == x2 && y1 == y2)
46 int x1 = (start_radius * cos(angle * M_PI / 180)) +
x;
47 int y1 = (start_radius * sin(angle * M_PI / 180)) +
y;
48 int x2 = (stop_radius * cos(angle * M_PI / 180)) +
x;
49 int y2 = (stop_radius * sin(angle * M_PI / 180)) +
y;
52 this->
line(x1, y1, x2, y2, color);
56 ColorBitness bitness,
bool big_endian,
int x_offset,
int y_offset,
int x_pad) {
57 size_t line_stride = x_offset + w + x_pad;
59 for (
int y = 0;
y !=
h;
y++) {
60 size_t source_idx = (y_offset +
y) * line_stride + x_offset;
61 size_t source_idx_mod;
62 for (
int x = 0;
x != w;
x++, source_idx++) {
65 color_value = ptr[source_idx];
68 source_idx_mod = source_idx * 2;
70 color_value = (ptr[source_idx_mod] << 8) + ptr[source_idx_mod + 1];
72 color_value = ptr[source_idx_mod] + (ptr[source_idx_mod + 1] << 8);
76 source_idx_mod = source_idx * 3;
78 color_value = (ptr[source_idx_mod + 0] << 16) + (ptr[source_idx_mod + 1] << 8) + ptr[source_idx_mod + 2];
80 color_value = ptr[source_idx_mod + 0] + (ptr[source_idx_mod + 1] << 8) + (ptr[source_idx_mod + 2] << 16);
91 for (
int i =
x; i <
x + width; i++)
96 for (
int i =
y; i <
y + height; i++)
107 for (
int i = y1; i < y1 + height; i++) {
114 int err = 2 - 2 * radius;
125 if (-dx == dy && e2 <= dx) {
135 int dx = -int32_t(radius);
137 int err = 2 - 2 * radius;
145 int hline_width = 2 * (-dx) + 1;
146 this->
horizontal_line(center_x + dx, center_y + dy, hline_width, color);
147 this->
horizontal_line(center_x + dx, center_y - dy, hline_width, color);
151 if (-dx == dy && e2 <= dx) {
161 int rmax = radius1 > radius2 ? radius1 : radius2;
162 int rmin = radius1 < radius2 ? radius1 : radius2;
163 int dxmax = -int32_t(rmax), dxmin = -int32_t(rmin);
164 int dymax = 0, dymin = 0;
165 int errmax = 2 - 2 * rmax, errmin = 2 - 2 * rmin;
169 this->
draw_pixel_at(center_x - dxmax, center_y + dymax, color);
170 this->
draw_pixel_at(center_x + dxmax, center_y + dymax, color);
171 this->
draw_pixel_at(center_x - dxmin, center_y + dymin, color);
172 this->
draw_pixel_at(center_x + dxmin, center_y + dymin, color);
173 this->
draw_pixel_at(center_x + dxmax, center_y - dymax, color);
174 this->
draw_pixel_at(center_x - dxmax, center_y - dymax, color);
175 this->
draw_pixel_at(center_x + dxmin, center_y - dymin, color);
176 this->
draw_pixel_at(center_x - dxmin, center_y - dymin, color);
179 int hline_width = -(dxmax - dxmin) + 1;
180 this->
horizontal_line(center_x + dxmax, center_y + dymax, hline_width, color);
181 this->
horizontal_line(center_x - dxmin, center_y + dymax, hline_width, color);
182 this->
horizontal_line(center_x + dxmax, center_y - dymax, hline_width, color);
183 this->
horizontal_line(center_x - dxmin, center_y - dymax, hline_width, color);
186 int hline_width = 2 * (-dxmax) + 1;
187 this->
horizontal_line(center_x + dxmax, center_y + dymax, hline_width, color);
188 this->
horizontal_line(center_x + dxmax, center_y - dymax, hline_width, color);
193 errmax += ++dymax * 2 + 1;
194 if (-dxmax == dymax && e2max <= dxmax) {
199 errmax += ++dxmax * 2 + 1;
202 while (dymin < dymax && dymin < rmin) {
205 errmin += ++dymin * 2 + 1;
206 if (-dxmin == dymin && e2min <= dxmin) {
211 errmin += ++dxmin * 2 + 1;
214 }
while (dxmax <= 0);
217 int rmax = radius1 > radius2 ? radius1 : radius2;
218 int rmin = radius1 < radius2 ? radius1 : radius2;
219 int dxmax = -int32_t(rmax), dxmin = -int32_t(rmin), upd_dxmax, upd_dxmin;
220 int dymax = 0, dymin = 0;
221 int errmax = 2 - 2 * rmax, errmin = 2 - 2 * rmin;
223 progress = std::max(0, std::min(progress, 100));
224 int draw_progress = progress > 50 ? (100 - progress) : progress;
225 float tan_a = (progress == 50) ? 65535 : tan(
float(draw_progress) * M_PI / 100);
229 this->
draw_pixel_at(center_x + dxmax, center_y - dymax, color);
230 this->
draw_pixel_at(center_x - dxmax, center_y - dymax, color);
232 int lhline_width = -(dxmax - dxmin) + 1;
233 if (progress >= 50) {
234 if (
float(dymax) <
float(-dxmax) * tan_a) {
235 upd_dxmax = ceil(
float(dymax) / tan_a);
239 this->
horizontal_line(center_x + dxmax, center_y - dymax, lhline_width, color);
241 this->
horizontal_line(center_x - dxmin, center_y, lhline_width, color);
242 if (upd_dxmax > -dxmin) {
243 int rhline_width = (upd_dxmax + dxmin) + 1;
245 rhline_width > lhline_width ? lhline_width : rhline_width, color);
248 if (
float(dymin) >
float(-dxmin) * tan_a) {
249 upd_dxmin = ceil(
float(dymin) / tan_a);
253 lhline_width = -(dxmax + upd_dxmin) + 1;
255 this->
horizontal_line(center_x - dxmin, center_y, lhline_width, color);
256 if (lhline_width > 0)
257 this->
horizontal_line(center_x + dxmax, center_y - dymax, lhline_width, color);
260 int hline_width = 2 * (-dxmax) + 1;
261 if (progress >= 50) {
262 if (dymax <
float(-dxmax) * tan_a) {
263 upd_dxmax = ceil(
float(dymax) / tan_a);
264 hline_width = -dxmax + upd_dxmax + 1;
267 if (dymax <
float(-dxmax) * tan_a) {
268 upd_dxmax = ceil(
float(dymax) / tan_a);
269 hline_width = -dxmax - upd_dxmax + 1;
275 this->
horizontal_line(center_x + dxmax, center_y - dymax, hline_width, color);
279 errmax += ++dymax * 2 + 1;
280 if (-dxmax == dymax && e2max <= dxmax) {
285 errmax += ++dxmax * 2 + 1;
287 while (dymin <= dymax && dymin <= rmin && dxmin <= 0) {
288 this->
draw_pixel_at(center_x + dxmin, center_y - dymin, color);
289 this->
draw_pixel_at(center_x - dxmin, center_y - dymin, color);
292 errmin += ++dymin * 2 + 1;
293 if (-dxmin == dymin && e2min <= dxmin) {
298 errmin += ++dxmin * 2 + 1;
301 }
while (dxmax <= 0);
304 this->
line(x1, y1, x2, y2, color);
305 this->
line(x1, y1, x3, y3, color);
306 this->
line(x2, y2, x3, y3, color);
310 int x_temp = *x1, y_temp = *y1;
311 *x1 = *x2, *y1 = *y2;
312 *x2 = x_temp, *y2 = y_temp;
315 int x_temp = *x1, y_temp = *y1;
316 *x1 = *x3, *y1 = *y3;
317 *x3 = x_temp, *y3 = y_temp;
320 int x_temp = *x2, y_temp = *y2;
321 *x2 = *x3, *y2 = *y3;
322 *x3 = x_temp, *y3 = y_temp;
329 int s1_current_x = x1;
330 int s1_current_y = y1;
331 bool s1_axis_swap =
false;
332 int s1_dx = abs(x2 - x1);
333 int s1_dy = abs(y2 - y1);
334 int s1_sign_x = ((x2 - x1) >= 0) ? 1 : -1;
335 int s1_sign_y = ((y2 - y1) >= 0) ? 1 : -1;
342 int s1_error = 2 * s1_dy - s1_dx;
345 int s2_current_x = x1;
346 int s2_current_y = y1;
347 bool s2_axis_swap =
false;
348 int s2_dx = abs(x3 - x1);
349 int s2_dy = abs(y3 - y1);
350 int s2_sign_x = ((x3 - x1) >= 0) ? 1 : -1;
351 int s2_sign_y = ((y3 - y1) >= 0) ? 1 : -1;
358 int s2_error = 2 * s2_dy - s2_dx;
361 for (
int i = 0; i <= s1_dx; i++) {
362 if (s1_current_x <= s2_current_x) {
363 this->
horizontal_line(s1_current_x, s1_current_y, s2_current_x - s1_current_x + 1, color);
365 this->
horizontal_line(s2_current_x, s2_current_y, s1_current_x - s2_current_x + 1, color);
370 while (s1_error >= 0) {
372 s1_current_x += s1_sign_x;
374 s1_current_y += s1_sign_y;
376 s1_error = s1_error - 2 * s1_dx;
379 s1_current_y += s1_sign_y;
381 s1_current_x += s1_sign_x;
383 s1_error = s1_error + 2 * s1_dy;
387 while (s2_current_y != s1_current_y) {
388 while (s2_error >= 0) {
390 s2_current_x += s2_sign_x;
392 s2_current_y += s2_sign_y;
394 s2_error = s2_error - 2 * s2_dx;
397 s2_current_y += s2_sign_y;
399 s2_current_x += s2_sign_x;
401 s2_error = s2_error + 2 * s2_dy;
411 }
else if (y1 == y2) {
414 int x_temp = (int) (x1 + ((
float) (y2 - y1) / (
float) (y3 - y1)) * (x3 - x1)), y_temp = y2;
421 float rotation_degrees) {
428 float rotation_radians = rotation_degrees * std::numbers::pi / 180;
434 rotation_radians -= (variation ==
VARIATION_FLAT_TOP) ? std::numbers::pi / edges : 0.0;
436 float vertex_angle = ((float) vertex_id) / edges * 2 * std::numbers::pi + rotation_radians;
437 *vertex_x = (int) round(cos(vertex_angle) * radius) + center_x;
438 *vertex_y = (int) round(sin(vertex_angle) * radius) + center_y;
445 int previous_vertex_x, previous_vertex_y;
446 for (
int current_vertex_id = 0; current_vertex_id <= edges; current_vertex_id++) {
447 int current_vertex_x, current_vertex_y;
449 variation, rotation_degrees);
450 if (current_vertex_id > 0) {
452 this->
filled_triangle(x,
y, previous_vertex_x, previous_vertex_y, current_vertex_x, current_vertex_y, color);
454 this->
line(previous_vertex_x, previous_vertex_y, current_vertex_x, current_vertex_y, color);
457 previous_vertex_x = current_vertex_x;
458 previous_vertex_y = current_vertex_y;
470 float rotation_degrees,
Color color) {
482 int x_start, y_start;
484 this->
get_text_bounds(x,
y, text, font, align, &x_start, &y_start, &width, &height);
485 font->
print(x_start, y_start,
this, color, text, background);
491 int ret = vsnprintf(buffer,
sizeof(buffer), format, arg);
493 this->
print(x,
y, font, color, align, buffer, background);
528 image->
draw(
x,
y,
this, color_on, color_off);
538 qr_code->
draw(
this,
x,
y, color_on, scale);
542#ifdef USE_GRAPHICAL_DISPLAY_MENU
544 Rect rect(
x,
y, width, height);
545 menu->draw(
this, &rect);
550 int *width,
int *height) {
551 int x_offset, baseline;
552 font->
measure(text, width, &x_offset, &baseline, height);
554 auto x_align =
TextAlign(
int(align) & 0x18);
555 auto y_align =
TextAlign(
int(align) & 0x07);
559 *x1 =
x - *width - x_offset;
562 *x1 =
x - (*width + x_offset) / 2;
579 *y1 =
y - (*height) / 2;
599 va_start(arg, format);
600 this->
vprintf_(x,
y, font, color, background, align, format, arg);
605 va_start(arg, format);
611 va_start(arg, format);
617 va_start(arg, format);
623 va_start(arg, format);
629 for (
auto *page : pages)
630 page->set_parent(
this);
632 for (uint32_t i = 0; i < pages.size() - 1; i++) {
633 pages[i]->set_next(pages[i + 1]);
634 pages[i + 1]->set_prev(pages[i]);
636 pages[0]->set_prev(pages[pages.size() - 1]);
637 pages[pages.size() - 1]->set_next(pages[0]);
656 }
else if (this->
page_ !=
nullptr) {
664 if ((this->
from_ ==
nullptr || this->
from_ == from) && (this->
to_ ==
nullptr || this->
to_ == to))
670 size_t ret = time.
strftime(buffer,
sizeof(buffer), format);
672 this->
print(x,
y, font, color, align, buffer, background);
696 ESP_LOGE(TAG,
"clear: Clipping is not set.");
703 ESP_LOGE(TAG,
"add: Clipping is not set.");
710 ESP_LOGE(TAG,
"add: Clipping is not set.");
731 min_x = std::max(
x, 0);
739 min_x = std::max(min_x, (
int) rect.x);
740 max_x = std::min(max_x, (
int) rect.x2());
743 return min_x < max_x;
746 min_y = std::max(
y, 0);
754 min_y = std::max(min_y, (
int) rect.y);
755 max_y = std::min(max_y, (
int) rect.y2());
758 return min_y < max_y;
761const uint8_t TESTCARD_FONT[3][8]
PROGMEM = {{0x41, 0x7F, 0x7F, 0x09, 0x19, 0x7F, 0x66, 0x00},
762 {0x1C, 0x3E, 0x63, 0x41, 0x51, 0x73, 0x72, 0x00},
763 {0x41, 0x7F, 0x7F, 0x49, 0x49, 0x7F, 0x36, 0x00}};
770 Color r(255, 0, 0), g(0, 255, 0), b(0, 0, 255);
771 image_w = std::min(w - 20, 310);
772 image_h = std::min(
h - 20, 255);
774 int shift_x = (w - image_w) / 2;
775 int shift_y = (
h - image_h) / 2;
776 int line_w = (image_w - 6) / 6;
777 int image_c = image_w / 2;
778 for (
auto i = 0; i != image_h; i++) {
779 int c = esp_scale(i, image_h);
780 this->
horizontal_line(shift_x + 0, shift_y + i, line_w, r.fade_to_white(c));
781 this->
horizontal_line(shift_x + line_w, shift_y + i, line_w, r.fade_to_black(c));
783 this->
horizontal_line(shift_x + image_c - line_w, shift_y + i, line_w, g.fade_to_white(c));
784 this->
horizontal_line(shift_x + image_c, shift_y + i, line_w, g.fade_to_black(c));
789 this->
rectangle(shift_x, shift_y, image_w, image_h,
Color(127, 127, 0));
791 uint16_t shift_r = shift_x + line_w - (8 * 3);
792 uint16_t shift_g = shift_x + image_c - (8 * 3);
793 uint16_t shift_b = shift_x + image_w - line_w - (8 * 3);
794 shift_y =
h / 2 - (8 * 3);
795 for (
auto i = 0; i < 8; i++) {
799 for (
auto k = 0; k < 8; k++) {
800 if ((ftr & (1 << k)) != 0) {
803 if ((ftg & (1 << k)) != 0) {
806 if ((ftb & (1 << k)) != 0) {
823 if (this->
next_ ==
nullptr) {
824 ESP_LOGE(TAG,
"no next page");
830 if (this->
prev_ ==
nullptr) {
831 ESP_LOGE(TAG,
"no previous page");
844 return LOG_STR(
"TOP_LEFT");
846 return LOG_STR(
"TOP_CENTER");
848 return LOG_STR(
"TOP_RIGHT");
850 return LOG_STR(
"CENTER_LEFT");
852 return LOG_STR(
"CENTER");
854 return LOG_STR(
"CENTER_RIGHT");
856 return LOG_STR(
"BASELINE_LEFT");
858 return LOG_STR(
"BASELINE_CENTER");
860 return LOG_STR(
"BASELINE_RIGHT");
862 return LOG_STR(
"BOTTOM_LEFT");
864 return LOG_STR(
"BOTTOM_CENTER");
866 return LOG_STR(
"BOTTOM_RIGHT");
868 return LOG_STR(
"UNKNOWN");
void trigger(const Ts &...x)
virtual void measure(const char *str, int *width, int *x_offset, int *baseline, int *height)=0
virtual void print(int x, int y, Display *display, Color color, const char *text, Color background)=0
virtual int get_height() const =0
virtual int get_width() const =0
virtual void draw(int x, int y, Display *display, Color color_on, Color color_off)=0
static Color to_color(uint32_t colorcode, ColorOrder color_order, ColorBitness color_bitness=ColorBitness::COLOR_BITNESS_888, bool right_bit_aligned=true)
void show_page(DisplayPage *page)
bool clip(int x, int y)
Check if pixel is within region of display.
void get_regular_polygon_vertex(int vertex_id, int *vertex_x, int *vertex_y, int center_x, int center_y, int radius, int edges, RegularPolygonVariation variation=VARIATION_POINTY_TOP, float rotation_degrees=ROTATION_0_DEGREES)
Get the specified vertex (x,y) coordinates for the regular polygon inscribed in the circle centered o...
virtual void clear()
Clear the entire screen by filling it with OFF pixels.
void end_clipping()
Reset the invalidation region.
void start_clipping(Rect rect)
Set the clipping rectangle for further drawing.
void set_pages(std::vector< DisplayPage * > pages)
void vprintf_(int x, int y, BaseFont *font, Color color, Color background, TextAlign align, const char *format, va_list arg)
virtual int get_height()
Get the calculated height of the display in pixels with rotation applied.
virtual void fill(Color color)
Fill the entire screen with the given color.
void horizontal_line(int x, int y, int width, Color color=COLOR_ON)
Draw a horizontal line from the point [x,y] to [x+width,y] with the given color.
void sort_triangle_points_by_y_(int *x1, int *y1, int *x2, int *y2, int *x3, int *y3)
virtual int get_width()
Get the calculated width of the display in pixels with rotation applied.
void circle(int center_x, int center_xy, int radius, Color color=COLOR_ON)
Draw the outline of a circle centered around [center_x,center_y] with the radius radius with the give...
void filled_triangle(int x1, int y1, int x2, int y2, int x3, int y3, Color color=COLOR_ON)
Fill a triangle contained between the points [x1,y1], [x2,y2] and [x3,y3] with the given color.
void print(int x, int y, BaseFont *font, Color color, TextAlign align, const char *text, Color background=COLOR_OFF)
Print text with the anchor point at [x,y] with font.
void set_rotation(DisplayRotation rotation)
Internal method to set the display rotation with.
void filled_regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation=VARIATION_POINTY_TOP, float rotation_degrees=ROTATION_0_DEGREES, Color color=COLOR_ON)
Fill a regular polygon inscribed in the circle centered on [x,y] with the given radius and color.
void qr_code(int x, int y, qr_code::QrCode *qr_code, Color color_on=COLOR_ON, int scale=1)
Draw the qr_code with the top-left corner at [x,y] to the screen.
bool clamp_x_(int x, int w, int &min_x, int &max_x)
void line(int x1, int y1, int x2, int y2, Color color=COLOR_ON)
Draw a straight line from the point [x1,y1] to [x2,y2] with the given color.
bool clamp_y_(int y, int h, int &min_y, int &max_y)
void filled_gauge(int center_x, int center_y, int radius1, int radius2, int progress, Color color=COLOR_ON)
Fill a half-ring "gauge" centered around [center_x,center_y] between two circles with the radius1 and...
virtual DisplayType get_display_type()=0
Get the type of display that the buffer corresponds to.
void void void void void void void void void void void image(int x, int y, BaseImage *image, Color color_on=COLOR_ON, Color color_off=COLOR_OFF)
Draw the image with the top-left corner at [x,y] to the screen.
void legend(int x, int y, graph::Graph *graph, Color color_on=COLOR_ON)
Draw the legend for graph with the top-left corner at [x,y] to the screen.
void rectangle(int x1, int y1, int width, int height, Color color=COLOR_ON)
Draw the outline of a rectangle with the top left point at [x1,y1] and the bottom right point at [x1+...
DisplayPage * previous_page_
void filled_circle(int center_x, int center_y, int radius, Color color=COLOR_ON)
Fill a circle centered around [center_x,center_y] with the radius radius with the given color.
void void void void void void strftime(int x, int y, BaseFont *font, Color color, Color background, TextAlign align, const char *format, ESPTime time) __attribute__((format(strftime
Evaluate the strftime-format format and print the result with the anchor point at [x,...
void triangle(int x1, int y1, int x2, int y2, int x3, int y3, Color color=COLOR_ON)
Draw the outline of a triangle contained between the points [x1,y1], [x2,y2] and [x3,...
void printf(int x, int y, BaseFont *font, Color color, Color background, TextAlign align, const char *format,...) __attribute__((format(printf
Evaluate the printf-format format and print the result with the anchor point at [x,...
void set_writer(display_writer_t &&writer)
Internal method to set the display writer lambda.
void draw_pixel_at(int x, int y)
Set a single pixel at the specified coordinates to default color.
void vertical_line(int x, int y, int height, Color color=COLOR_ON)
Draw a vertical line from the point [x,y] to [x,y+width] with the given color.
void graph(int x, int y, graph::Graph *graph, Color color_on=COLOR_ON)
Draw the graph with the top-left corner at [x,y] to the screen.
Rect get_clipping() const
Get the current the clipping rectangle.
void filled_ring(int center_x, int center_y, int radius1, int radius2, Color color=COLOR_ON)
Fill a ring centered around [center_x,center_y] between two circles with the radius1 and radius2 with...
void extend_clipping(Rect rect)
Add a rectangular region to the invalidation region.
void menu(int x, int y, graphical_display_menu::GraphicalDisplayMenu *menu, int width, int height)
void line_at_angle(int x, int y, int angle, int length, Color color=COLOR_ON)
Draw a straight line at the given angle based on the origin [x, y] for a specified length with the gi...
void get_text_bounds(int x, int y, const char *text, BaseFont *font, TextAlign align, int *x1, int *y1, int *width, int *height)
Get the text bounds of the given string.
DisplayRotation rotation_
std::vector< DisplayOnPageChangeTrigger * > on_page_change_triggers_
virtual void draw_pixels_at(int x_start, int y_start, int w, int h, const uint8_t *ptr, ColorOrder order, ColorBitness bitness, bool big_endian, int x_offset, int y_offset, int x_pad)
Given an array of pixels encoded in the nominated format, draw these into the display's buffer.
void regular_polygon(int x, int y, int radius, int edges, RegularPolygonVariation variation=VARIATION_POINTY_TOP, float rotation_degrees=ROTATION_0_DEGREES, Color color=COLOR_ON, RegularPolygonDrawing drawing=DRAWING_OUTLINE)
Draw the outline of a regular polygon inscribed in the circle centered on [x,y] with the given radius...
void filled_flat_side_triangle_(int x1, int y1, int x2, int y2, int x3, int y3, Color color)
This method fills a triangle using only integer variables by using a modified bresenham algorithm.
void shrink_clipping(Rect rect)
substract a rectangular region to the invalidation region
void filled_rectangle(int x1, int y1, int width, int height, Color color=COLOR_ON)
Fill a rectangle with the top left point at [x1,y1] and the bottom right point at [x1+width,...
std::vector< Rect > clipping_rectangle_
void process(DisplayPage *from, DisplayPage *to)
void set_next(DisplayPage *next)
const display_writer_t & get_writer() const
void set_parent(Display *parent)
DisplayPage(display_writer_t writer)
void set_prev(DisplayPage *prev)
void draw(display::Display *buff, uint16_t x_offset, uint16_t y_offset, Color color)
void draw_legend(display::Display *buff, uint16_t x_offset, uint16_t y_offset, Color color)
void draw(display::Display *buff, uint16_t x_offset, uint16_t y_offset, Color color, int scale)
const Color COLOR_ON(255, 255, 255, 255)
Turn the pixel ON.
const LogString * text_align_to_string(TextAlign textalign)
ImageAlign
ImageAlign is used to tell the display class how to position a image.
const float ROTATION_270_DEGREES
TextAlign
TextAlign is used to tell the display class how to position a piece of text.
const uint8_t TESTCARD_FONT[3][8] PROGMEM
const Color COLOR_OFF(0, 0, 0, 0)
Turn the pixel OFF.
const float ROTATION_0_DEGREES
Providing packet encoding functions for exchanging data with a remote host.
uint8_t progmem_read_byte(const uint8_t *addr)
Color fade_to_white(uint8_t amnt)
Color fade_to_black(uint8_t amnt)
A more user-friendly version of struct tm from time.h.
size_t strftime(char *buffer, size_t buffer_len, const char *format)
Convert this ESPTime struct to a null-terminated c string buffer as specified by the format argument.