10static 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++)
97 for (
int i =
y; i <
y + height; i++)
110 for (
int i = y1; i < y1 + height; i++) {
118 int err = 2 - 2 * radius;
129 if (-dx == dy && e2 <= dx) {
140 int dx = -int32_t(radius);
142 int err = 2 - 2 * radius;
150 int hline_width = 2 * (-dx) + 1;
151 this->
horizontal_line(center_x + dx, center_y + dy, hline_width, color);
152 this->
horizontal_line(center_x + dx, center_y - dy, hline_width, color);
156 if (-dx == dy && e2 <= dx) {
167 int rmax = radius1 > radius2 ? radius1 : radius2;
168 int rmin = radius1 < radius2 ? radius1 : radius2;
169 int dxmax = -int32_t(rmax), dxmin = -int32_t(rmin);
170 int dymax = 0, dymin = 0;
171 int errmax = 2 - 2 * rmax, errmin = 2 - 2 * rmin;
175 this->
draw_pixel_at(center_x - dxmax, center_y + dymax, color);
176 this->
draw_pixel_at(center_x + dxmax, center_y + dymax, color);
177 this->
draw_pixel_at(center_x - dxmin, center_y + dymin, color);
178 this->
draw_pixel_at(center_x + dxmin, center_y + dymin, color);
179 this->
draw_pixel_at(center_x + dxmax, center_y - dymax, color);
180 this->
draw_pixel_at(center_x - dxmax, center_y - dymax, color);
181 this->
draw_pixel_at(center_x + dxmin, center_y - dymin, color);
182 this->
draw_pixel_at(center_x - dxmin, center_y - dymin, color);
185 int hline_width = -(dxmax - dxmin) + 1;
186 this->
horizontal_line(center_x + dxmax, center_y + dymax, hline_width, color);
187 this->
horizontal_line(center_x - dxmin, center_y + dymax, hline_width, color);
188 this->
horizontal_line(center_x + dxmax, center_y - dymax, hline_width, color);
189 this->
horizontal_line(center_x - dxmin, center_y - dymax, hline_width, color);
192 int hline_width = 2 * (-dxmax) + 1;
193 this->
horizontal_line(center_x + dxmax, center_y + dymax, hline_width, color);
194 this->
horizontal_line(center_x + dxmax, center_y - dymax, hline_width, color);
199 errmax += ++dymax * 2 + 1;
200 if (-dxmax == dymax && e2max <= dxmax) {
205 errmax += ++dxmax * 2 + 1;
208 while (dymin < dymax && dymin < rmin) {
211 errmin += ++dymin * 2 + 1;
212 if (-dxmin == dymin && e2min <= dxmin) {
217 errmin += ++dxmin * 2 + 1;
220 }
while (dxmax <= 0);
224 int rmax = radius1 > radius2 ? radius1 : radius2;
225 int rmin = radius1 < radius2 ? radius1 : radius2;
226 int dxmax = -int32_t(rmax), dxmin = -int32_t(rmin), upd_dxmax, upd_dxmin;
227 int dymax = 0, dymin = 0;
228 int errmax = 2 - 2 * rmax, errmin = 2 - 2 * rmin;
230 progress = std::max(0, std::min(progress, 100));
231 int draw_progress = progress > 50 ? (100 - progress) : progress;
232 float tan_a = (progress == 50) ? 65535 : tan(
float(draw_progress) * M_PI / 100);
236 this->
draw_pixel_at(center_x + dxmax, center_y - dymax, color);
237 this->
draw_pixel_at(center_x - dxmax, center_y - dymax, color);
240 int lhline_width = -(dxmax - dxmin) + 1;
241 if (progress >= 50) {
242 if (
float(dymax) <
float(-dxmax) * tan_a) {
243 upd_dxmax = ceil(
float(dymax) / tan_a);
247 this->
horizontal_line(center_x + dxmax, center_y - dymax, lhline_width, color);
249 this->
horizontal_line(center_x - dxmin, center_y, lhline_width, color);
250 if (upd_dxmax > -dxmin) {
252 int rhline_width = (upd_dxmax + dxmin) + 1;
254 rhline_width > lhline_width ? lhline_width : rhline_width, color);
257 if (
float(dymin) >
float(-dxmin) * tan_a) {
258 upd_dxmin = ceil(
float(dymin) / tan_a);
262 lhline_width = -(dxmax + upd_dxmin) + 1;
264 this->
horizontal_line(center_x - dxmin, center_y, lhline_width, color);
265 if (lhline_width > 0)
266 this->
horizontal_line(center_x + dxmax, center_y - dymax, lhline_width, color);
270 int hline_width = 2 * (-dxmax) + 1;
271 if (progress >= 50) {
272 if (dymax <
float(-dxmax) * tan_a) {
273 upd_dxmax = ceil(
float(dymax) / tan_a);
274 hline_width = -dxmax + upd_dxmax + 1;
277 if (dymax <
float(-dxmax) * tan_a) {
278 upd_dxmax = ceil(
float(dymax) / tan_a);
279 hline_width = -dxmax - upd_dxmax + 1;
285 this->
horizontal_line(center_x + dxmax, center_y - dymax, hline_width, color);
289 errmax += ++dymax * 2 + 1;
290 if (-dxmax == dymax && e2max <= dxmax) {
295 errmax += ++dxmax * 2 + 1;
297 while (dymin <= dymax && dymin <= rmin && dxmin <= 0) {
298 this->
draw_pixel_at(center_x + dxmin, center_y - dymin, color);
299 this->
draw_pixel_at(center_x - dxmin, center_y - dymin, color);
302 errmin += ++dymin * 2 + 1;
303 if (-dxmin == dymin && e2min <= dxmin) {
308 errmin += ++dxmin * 2 + 1;
311 }
while (dxmax <= 0);
315 this->
line(x1, y1, x2, y2, color);
316 this->
line(x1, y1, x3, y3, color);
317 this->
line(x2, y2, x3, y3, color);
322 int x_temp = *x1, y_temp = *y1;
323 *x1 = *x2, *y1 = *y2;
324 *x2 = x_temp, *y2 = y_temp;
327 int x_temp = *x1, y_temp = *y1;
328 *x1 = *x3, *y1 = *y3;
329 *x3 = x_temp, *y3 = y_temp;
332 int x_temp = *x2, y_temp = *y2;
333 *x2 = *x3, *y2 = *y3;
334 *x3 = x_temp, *y3 = y_temp;
342 int s1_current_x = x1;
343 int s1_current_y = y1;
344 bool s1_axis_swap =
false;
345 int s1_dx = abs(x2 - x1);
346 int s1_dy = abs(y2 - y1);
347 int s1_sign_x = ((x2 - x1) >= 0) ? 1 : -1;
348 int s1_sign_y = ((y2 - y1) >= 0) ? 1 : -1;
356 int s1_error = 2 * s1_dy - s1_dx;
359 int s2_current_x = x1;
360 int s2_current_y = y1;
361 bool s2_axis_swap =
false;
362 int s2_dx = abs(x3 - x1);
363 int s2_dy = abs(y3 - y1);
364 int s2_sign_x = ((x3 - x1) >= 0) ? 1 : -1;
365 int s2_sign_y = ((y3 - y1) >= 0) ? 1 : -1;
373 int s2_error = 2 * s2_dy - s2_dx;
376 for (
int i = 0; i <= s1_dx; i++) {
377 if (s1_current_x <= s2_current_x) {
378 this->
horizontal_line(s1_current_x, s1_current_y, s2_current_x - s1_current_x + 1, color);
380 this->
horizontal_line(s2_current_x, s2_current_y, s1_current_x - s2_current_x + 1, color);
385 while (s1_error >= 0) {
387 s1_current_x += s1_sign_x;
389 s1_current_y += s1_sign_y;
391 s1_error = s1_error - 2 * s1_dx;
394 s1_current_y += s1_sign_y;
396 s1_current_x += s1_sign_x;
398 s1_error = s1_error + 2 * s1_dy;
402 while (s2_current_y != s1_current_y) {
403 while (s2_error >= 0) {
405 s2_current_x += s2_sign_x;
407 s2_current_y += s2_sign_y;
409 s2_error = s2_error - 2 * s2_dx;
412 s2_current_y += s2_sign_y;
414 s2_current_x += s2_sign_x;
416 s2_error = s2_error + 2 * s2_dy;
428 }
else if (y1 == y2) {
433 int x_temp = (int) (x1 + ((
float) (y2 - y1) / (
float) (y3 - y1)) * (x3 - x1)), y_temp = y2;
441 float rotation_degrees) {
448 float rotation_radians = rotation_degrees * std::numbers::pi / 180;
454 rotation_radians -= (variation ==
VARIATION_FLAT_TOP) ? std::numbers::pi / edges : 0.0;
456 float vertex_angle = ((float) vertex_id) / edges * 2 * std::numbers::pi + rotation_radians;
457 *vertex_x = (int) round(cos(vertex_angle) * radius) + center_x;
458 *vertex_y = (int) round(sin(vertex_angle) * radius) + center_y;
465 int previous_vertex_x, previous_vertex_y;
466 for (
int current_vertex_id = 0; current_vertex_id <= edges; current_vertex_id++) {
467 int current_vertex_x, current_vertex_y;
469 variation, rotation_degrees);
470 if (current_vertex_id > 0) {
473 this->
filled_triangle(x,
y, previous_vertex_x, previous_vertex_y, current_vertex_x, current_vertex_y, color);
475 this->
line(previous_vertex_x, previous_vertex_y, current_vertex_x, current_vertex_y, color);
478 previous_vertex_x = current_vertex_x;
479 previous_vertex_y = current_vertex_y;
494 float rotation_degrees,
Color color) {
508 int x_start, y_start;
510 this->
get_text_bounds(x,
y, text, font, align, &x_start, &y_start, &width, &height);
511 font->
print(x_start, y_start,
this, color, text, background);
517 int ret = vsnprintf(buffer,
sizeof(buffer), format, arg);
519 this->
print(x,
y, font, color, align, buffer, background);
554 image->
draw(
x,
y,
this, color_on, color_off);
564 qr_code->
draw(
this,
x,
y, color_on, scale);
568#ifdef USE_GRAPHICAL_DISPLAY_MENU
570 Rect rect(
x,
y, width, height);
571 menu->draw(
this, &rect);
576 int *width,
int *height) {
577 int x_offset, baseline;
578 font->
measure(text, width, &x_offset, &baseline, height);
580 auto x_align =
TextAlign(
int(align) & 0x18);
581 auto y_align =
TextAlign(
int(align) & 0x07);
585 *x1 =
x - *width - x_offset;
588 *x1 =
x - (*width + x_offset) / 2;
605 *y1 =
y - (*height) / 2;
629 va_start(arg, format);
630 this->
vprintf_(x,
y, font, color, background, align, format, arg);
636 va_start(arg, format);
643 va_start(arg, format);
650 va_start(arg, format);
657 va_start(arg, format);
665 for (
auto *page : pages)
666 page->set_parent(
this);
668 for (uint32_t i = 0; i < pages.size() - 1; i++) {
669 pages[i]->set_next(pages[i + 1]);
670 pages[i + 1]->set_prev(pages[i]);
672 pages[0]->set_prev(pages[pages.size() - 1]);
673 pages[pages.size() - 1]->set_next(pages[0]);
695 }
else if (this->
page_ !=
nullptr) {
704 if ((this->
from_ ==
nullptr || this->
from_ == from) && (this->
to_ ==
nullptr || this->
to_ == to))
711 size_t ret = time.
strftime(buffer,
sizeof(buffer), format);
713 this->
print(x,
y, font, color, align, buffer, background);
742 ESP_LOGE(TAG,
"clear: Clipping is not set.");
750 ESP_LOGE(TAG,
"add: Clipping is not set.");
758 ESP_LOGE(TAG,
"add: Clipping is not set.");
783 min_x = std::max(
x, 0);
791 min_x = std::max(min_x, (
int) rect.x);
792 max_x = std::min(max_x, (
int) rect.x2());
795 return min_x < max_x;
799 min_y = std::max(
y, 0);
807 min_y = std::max(min_y, (
int) rect.y);
808 max_y = std::min(max_y, (
int) rect.y2());
811 return min_y < max_y;
814const uint8_t TESTCARD_FONT[3][8]
PROGMEM = {{0x41, 0x7F, 0x7F, 0x09, 0x19, 0x7F, 0x66, 0x00},
815 {0x1C, 0x3E, 0x63, 0x41, 0x51, 0x73, 0x72, 0x00},
816 {0x41, 0x7F, 0x7F, 0x49, 0x49, 0x7F, 0x36, 0x00}};
822 image_w = std::min(w - 20, 310);
823 image_h = std::min(
h - 20, 255);
824 int shift_x = (w - image_w) / 2;
825 int shift_y = (
h - image_h) / 2;
826 int line_w = (image_w - 6) / 6;
827 int image_c = image_w / 2;
829 Color r(255, 0, 0), g(0, 255, 0), b(0, 0, 255);
831 for (
auto i = 0; i != image_h; i++) {
832 int c = esp_scale(i, image_h);
833 this->
horizontal_line(shift_x + 0, shift_y + i, line_w, r.fade_to_white(c));
834 this->
horizontal_line(shift_x + line_w, shift_y + i, line_w, r.fade_to_black(c));
836 this->
horizontal_line(shift_x + image_c - line_w, shift_y + i, line_w, g.fade_to_white(c));
837 this->
horizontal_line(shift_x + image_c, shift_y + i, line_w, g.fade_to_black(c));
843 this->
rectangle(shift_x, shift_y, image_w, image_h,
Color(127, 127, 0));
845 uint16_t shift_r = shift_x + line_w - (8 * 3);
846 uint16_t shift_g = shift_x + image_c - (8 * 3);
847 uint16_t shift_b = shift_x + image_w - line_w - (8 * 3);
848 shift_y =
h / 2 - (8 * 3);
849 for (
auto i = 0; i < 8; i++) {
853 for (
auto k = 0; k < 8; k++) {
854 if ((ftr & (1 << k)) != 0) {
857 if ((ftg & (1 << k)) != 0) {
860 if ((ftb & (1 << k)) != 0) {
878 if (this->
next_ ==
nullptr) {
879 ESP_LOGE(TAG,
"no next page");
886 if (this->
prev_ ==
nullptr) {
887 ESP_LOGE(TAG,
"no previous page");
901 return LOG_STR(
"TOP_LEFT");
903 return LOG_STR(
"TOP_CENTER");
905 return LOG_STR(
"TOP_RIGHT");
907 return LOG_STR(
"CENTER_LEFT");
909 return LOG_STR(
"CENTER");
911 return LOG_STR(
"CENTER_RIGHT");
913 return LOG_STR(
"BASELINE_LEFT");
915 return LOG_STR(
"BASELINE_CENTER");
917 return LOG_STR(
"BASELINE_RIGHT");
919 return LOG_STR(
"BOTTOM_LEFT");
921 return LOG_STR(
"BOTTOM_CENTER");
923 return LOG_STR(
"BOTTOM_RIGHT");
925 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.