Прошло 2 года.
This commit is contained in:
375
lib/epdiy/examples/screen_diag/main/commands/graphics.c
Normal file
375
lib/epdiy/examples/screen_diag/main/commands/graphics.c
Normal file
@@ -0,0 +1,375 @@
|
||||
#include "graphics.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <argtable3/argtable3.h>
|
||||
#include <esp_console.h>
|
||||
|
||||
#include "../commands.h"
|
||||
#include "../epd.h"
|
||||
#include "fonts.h"
|
||||
|
||||
static struct {
|
||||
struct arg_int *x, *y;
|
||||
struct arg_int* len;
|
||||
struct arg_int* color;
|
||||
struct arg_end* end;
|
||||
} draw_hvline_args;
|
||||
|
||||
static struct {
|
||||
struct arg_int *from_x, *from_y;
|
||||
struct arg_int *to_x, *to_y;
|
||||
struct arg_int* color;
|
||||
struct arg_end* end;
|
||||
} draw_line_args;
|
||||
|
||||
static struct {
|
||||
struct arg_int *x, *y;
|
||||
struct arg_int *width, *height;
|
||||
struct arg_int* color;
|
||||
struct arg_end* end;
|
||||
} draw_rect_args;
|
||||
|
||||
static struct {
|
||||
struct arg_int *x, *y;
|
||||
struct arg_int* radius;
|
||||
struct arg_int* color;
|
||||
struct arg_end* end;
|
||||
} draw_circle_args;
|
||||
|
||||
static struct {
|
||||
struct arg_int *x0, *y0;
|
||||
struct arg_int *x1, *y1;
|
||||
struct arg_int *x2, *y2;
|
||||
struct arg_int* color;
|
||||
struct arg_end* end;
|
||||
} draw_triangle_args;
|
||||
|
||||
static struct {
|
||||
struct arg_int *x, *y;
|
||||
struct arg_int* color;
|
||||
struct arg_lit* serif;
|
||||
struct arg_str* msg;
|
||||
struct arg_end* end;
|
||||
} write_text_args;
|
||||
|
||||
static int draw_hline(int argc, char* argv[]);
|
||||
static int draw_vline(int argc, char* argv[]);
|
||||
static int draw_line(int argc, char* argv[]);
|
||||
static int draw_rect(int argc, char* argv[]);
|
||||
static int fill_rect(int argc, char* argv[]);
|
||||
static int draw_circle(int argc, char* argv[]);
|
||||
static int fill_circle(int argc, char* argv[]);
|
||||
static int draw_triangle(int argc, char* argv[]);
|
||||
static int fill_triangle(int argc, char* argv[]);
|
||||
static int write_text(int argc, char* argv[]);
|
||||
|
||||
void register_graphics_commands(void) {
|
||||
// setup args
|
||||
draw_hvline_args.x = arg_intn(NULL, NULL, "<x>", 1, 1, "start x position");
|
||||
draw_hvline_args.y = arg_intn(NULL, NULL, "<y>", 1, 1, "start y position");
|
||||
draw_hvline_args.len = arg_intn(NULL, NULL, "<len>", 1, 1, "length of the line");
|
||||
draw_hvline_args.color = arg_intn(NULL, NULL, "<color>", 0, 1, "default value: 0x00");
|
||||
draw_hvline_args.end = arg_end(NARGS(draw_hvline_args));
|
||||
|
||||
draw_line_args.from_x = arg_intn(NULL, NULL, "<start_x>", 1, 1, "start x position");
|
||||
draw_line_args.from_y = arg_intn(NULL, NULL, "<start_y>", 1, 1, "start y position");
|
||||
draw_line_args.to_x = arg_intn(NULL, NULL, "<end_x>", 1, 1, "end x position");
|
||||
draw_line_args.to_y = arg_intn(NULL, NULL, "<end_y>", 1, 1, "end y position");
|
||||
draw_line_args.color = arg_intn(NULL, NULL, "<color>", 0, 1, "default value: 0x00");
|
||||
draw_line_args.end = arg_end(NARGS(draw_line_args));
|
||||
|
||||
draw_rect_args.x = arg_intn(NULL, NULL, "<x>", 1, 1, "top left x position");
|
||||
draw_rect_args.y = arg_intn(NULL, NULL, "<y>", 1, 1, "top left y position");
|
||||
draw_rect_args.width = arg_intn(NULL, NULL, "<width>", 1, 1, "square width");
|
||||
draw_rect_args.height = arg_intn(NULL, NULL, "<height>", 1, 1, "square height");
|
||||
draw_rect_args.color = arg_intn(NULL, NULL, "<color>", 0, 1, "default value: 0x00");
|
||||
draw_rect_args.end = arg_end(NARGS(draw_rect_args));
|
||||
|
||||
draw_circle_args.x = arg_intn(NULL, NULL, "<center_x>", 1, 1, "center x position");
|
||||
draw_circle_args.y = arg_intn(NULL, NULL, "<center_y>", 1, 1, "center y position");
|
||||
draw_circle_args.radius = arg_intn(NULL, NULL, "<radius>", 1, 1, "circle radius");
|
||||
draw_circle_args.color = arg_intn(NULL, NULL, "<color>", 0, 1, "default value: 0x00");
|
||||
draw_circle_args.end = arg_end(NARGS(draw_circle_args));
|
||||
|
||||
draw_triangle_args.x0 = arg_intn(NULL, NULL, "<x0>", 1, 1, "first edge x position");
|
||||
draw_triangle_args.y0 = arg_intn(NULL, NULL, "<y0>", 1, 1, "first edge y position");
|
||||
draw_triangle_args.x1 = arg_intn(NULL, NULL, "<x1>", 1, 1, "second edge x position");
|
||||
draw_triangle_args.y1 = arg_intn(NULL, NULL, "<y1>", 1, 1, "second edge y position");
|
||||
draw_triangle_args.x2 = arg_intn(NULL, NULL, "<x0>", 1, 1, "third edge x position");
|
||||
draw_triangle_args.y2 = arg_intn(NULL, NULL, "<y0>", 1, 1, "third edge y position");
|
||||
draw_triangle_args.color = arg_intn(NULL, NULL, "<color>", 0, 1, "default value: 0x00");
|
||||
draw_triangle_args.end = arg_end(NARGS(draw_triangle_args));
|
||||
|
||||
write_text_args.x = arg_intn(NULL, NULL, "<x>", 1, 1, "x position");
|
||||
write_text_args.y = arg_intn(NULL, NULL, "<y>", 1, 1, "y position");
|
||||
write_text_args.color = arg_intn(NULL, NULL, "<color>", 0, 1, "default value: 0x00");
|
||||
write_text_args.serif = arg_litn("s", "serif", 0, 1, "Use serif font rather than sans-serif.");
|
||||
write_text_args.msg = arg_strn(NULL, NULL, "<msg>", 1, 1, "Text to be printed.");
|
||||
write_text_args.end = arg_end(NARGS(write_text_args));
|
||||
|
||||
// register commands
|
||||
const esp_console_cmd_t commands[]
|
||||
= { { .command = "draw_hline",
|
||||
.help = "Draw horizontal line.",
|
||||
.hint = NULL,
|
||||
.func = &draw_hline,
|
||||
.argtable = &draw_hvline_args },
|
||||
{ .command = "draw_vline",
|
||||
.help = "Draw vertical line.",
|
||||
.hint = NULL,
|
||||
.func = &draw_vline,
|
||||
.argtable = &draw_hvline_args },
|
||||
{ .command = "draw_line",
|
||||
.help = "Draw line between two points.",
|
||||
.hint = NULL,
|
||||
.func = &draw_line,
|
||||
.argtable = &draw_line_args },
|
||||
{ .command = "draw_rect",
|
||||
.help = "Draw a rectangle.",
|
||||
.hint = NULL,
|
||||
.func = &draw_rect,
|
||||
.argtable = &draw_rect_args },
|
||||
{ .command = "fill_rect",
|
||||
.help = "Draw a filled rectangle.",
|
||||
.hint = NULL,
|
||||
.func = &fill_rect,
|
||||
.argtable = &draw_rect_args },
|
||||
{ .command = "draw_circle",
|
||||
.help = "Draw a circle.",
|
||||
.hint = NULL,
|
||||
.func = &draw_circle,
|
||||
.argtable = &draw_circle_args },
|
||||
{ .command = "fill_circle",
|
||||
.help = "Draw a filled circle.",
|
||||
.hint = NULL,
|
||||
.func = &fill_circle,
|
||||
.argtable = &draw_circle_args },
|
||||
{ .command = "draw_triangle",
|
||||
.help = "Draw a triangle from three different points.",
|
||||
.hint = NULL,
|
||||
.func = &draw_triangle,
|
||||
.argtable = &draw_triangle_args },
|
||||
{ .command = "fill_triangle",
|
||||
.help = "Draw a filled triangle from three different points.",
|
||||
.hint = NULL,
|
||||
.func = &fill_triangle,
|
||||
.argtable = &draw_triangle_args },
|
||||
{ .command = "write_text",
|
||||
.help = "Write text message to the screen using the sans-serif font by default.",
|
||||
.hint = NULL,
|
||||
.func = &write_text,
|
||||
.argtable = &write_text_args } };
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(commands); ++i)
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&commands[i]));
|
||||
}
|
||||
|
||||
static int draw_hline(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(draw_hvline_args)
|
||||
|
||||
uint8_t color = 0x00;
|
||||
if (!validate_color(&color, draw_hvline_args.color))
|
||||
return 1;
|
||||
|
||||
epd_draw_hline(
|
||||
draw_hvline_args.x->ival[0],
|
||||
draw_hvline_args.y->ival[0],
|
||||
draw_hvline_args.len->ival[0],
|
||||
color,
|
||||
g_framebuffer
|
||||
);
|
||||
|
||||
update_screen();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int draw_vline(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(draw_hvline_args)
|
||||
|
||||
uint8_t color = 0x00;
|
||||
if (!validate_color(&color, draw_hvline_args.color))
|
||||
return 1;
|
||||
|
||||
epd_draw_vline(
|
||||
draw_hvline_args.x->ival[0],
|
||||
draw_hvline_args.y->ival[0],
|
||||
draw_hvline_args.len->ival[0],
|
||||
color,
|
||||
g_framebuffer
|
||||
);
|
||||
|
||||
update_screen();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int draw_line(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(draw_line_args)
|
||||
|
||||
uint8_t color = 0x00;
|
||||
if (!validate_color(&color, draw_line_args.color))
|
||||
return 1;
|
||||
|
||||
epd_draw_line(
|
||||
draw_line_args.from_x->ival[0],
|
||||
draw_line_args.from_y->ival[0],
|
||||
draw_line_args.to_x->ival[0],
|
||||
draw_line_args.to_y->ival[0],
|
||||
color,
|
||||
g_framebuffer
|
||||
);
|
||||
|
||||
update_screen();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int draw_rect(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(draw_rect_args)
|
||||
|
||||
uint8_t color = 0x00;
|
||||
if (!validate_color(&color, draw_rect_args.color))
|
||||
return 1;
|
||||
|
||||
EpdRect rect = { .x = draw_rect_args.x->ival[0],
|
||||
.y = draw_rect_args.y->ival[0],
|
||||
.width = draw_rect_args.width->ival[0],
|
||||
.height = draw_rect_args.height->ival[0] };
|
||||
|
||||
epd_draw_rect(rect, color, g_framebuffer);
|
||||
|
||||
update_screen();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fill_rect(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(draw_rect_args)
|
||||
|
||||
uint8_t color = 0x00;
|
||||
if (!validate_color(&color, draw_rect_args.color))
|
||||
return 1;
|
||||
|
||||
EpdRect rect = { .x = draw_rect_args.x->ival[0],
|
||||
.y = draw_rect_args.y->ival[0],
|
||||
.width = draw_rect_args.width->ival[0],
|
||||
.height = draw_rect_args.height->ival[0] };
|
||||
|
||||
epd_fill_rect(rect, color, g_framebuffer);
|
||||
|
||||
update_screen();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int draw_circle(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(draw_circle_args)
|
||||
|
||||
uint8_t color = 0x00;
|
||||
if (!validate_color(&color, draw_circle_args.color))
|
||||
return 1;
|
||||
|
||||
epd_draw_circle(
|
||||
draw_circle_args.x->ival[0],
|
||||
draw_circle_args.y->ival[0],
|
||||
draw_circle_args.radius->ival[0],
|
||||
color,
|
||||
g_framebuffer
|
||||
);
|
||||
|
||||
update_screen();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fill_circle(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(draw_circle_args)
|
||||
|
||||
uint8_t color = 0x00;
|
||||
if (!validate_color(&color, draw_circle_args.color))
|
||||
return 1;
|
||||
|
||||
epd_fill_circle(
|
||||
draw_circle_args.x->ival[0],
|
||||
draw_circle_args.y->ival[0],
|
||||
draw_circle_args.radius->ival[0],
|
||||
color,
|
||||
g_framebuffer
|
||||
);
|
||||
|
||||
update_screen();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int draw_triangle(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(draw_triangle_args)
|
||||
|
||||
uint8_t color = 0x00;
|
||||
if (!validate_color(&color, draw_triangle_args.color))
|
||||
return 1;
|
||||
|
||||
epd_draw_triangle(
|
||||
draw_triangle_args.x0->ival[0],
|
||||
draw_triangle_args.y0->ival[0],
|
||||
draw_triangle_args.x1->ival[0],
|
||||
draw_triangle_args.y1->ival[0],
|
||||
draw_triangle_args.x2->ival[0],
|
||||
draw_triangle_args.y2->ival[0],
|
||||
color,
|
||||
g_framebuffer
|
||||
);
|
||||
|
||||
update_screen();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int fill_triangle(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(draw_triangle_args)
|
||||
|
||||
uint8_t color = 0x00;
|
||||
if (!validate_color(&color, draw_triangle_args.color))
|
||||
return 1;
|
||||
|
||||
epd_fill_triangle(
|
||||
draw_triangle_args.x0->ival[0],
|
||||
draw_triangle_args.y0->ival[0],
|
||||
draw_triangle_args.x1->ival[0],
|
||||
draw_triangle_args.y1->ival[0],
|
||||
draw_triangle_args.x2->ival[0],
|
||||
draw_triangle_args.y2->ival[0],
|
||||
color,
|
||||
g_framebuffer
|
||||
);
|
||||
|
||||
update_screen();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int write_text(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(write_text_args)
|
||||
|
||||
uint8_t color = 0x00;
|
||||
if (!validate_color(&color, draw_triangle_args.color))
|
||||
return 1;
|
||||
|
||||
const EpdFont* font = &Alexandria;
|
||||
if (write_text_args.serif->count)
|
||||
font = &Amiri;
|
||||
|
||||
EpdFontProperties props = { .bg_color = 0x00, .fg_color = color };
|
||||
|
||||
int pos_x = write_text_args.x->ival[0];
|
||||
int pos_y = write_text_args.y->ival[0];
|
||||
|
||||
epd_write_string(font, write_text_args.msg->sval[0], &pos_x, &pos_y, g_framebuffer, &props);
|
||||
|
||||
update_screen();
|
||||
|
||||
return 0;
|
||||
}
|
||||
3
lib/epdiy/examples/screen_diag/main/commands/graphics.h
Normal file
3
lib/epdiy/examples/screen_diag/main/commands/graphics.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void register_graphics_commands(void);
|
||||
286
lib/epdiy/examples/screen_diag/main/commands/screen.c
Normal file
286
lib/epdiy/examples/screen_diag/main/commands/screen.c
Normal file
@@ -0,0 +1,286 @@
|
||||
#include "screen.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <argtable3/argtable3.h>
|
||||
#include <esp_console.h>
|
||||
|
||||
#include "../commands.h"
|
||||
#include "../epd.h"
|
||||
|
||||
static struct {
|
||||
struct arg_str* rotation;
|
||||
struct arg_lit* inverted;
|
||||
struct arg_end* end;
|
||||
} set_rotation_args;
|
||||
|
||||
static struct {
|
||||
struct arg_int *posx, *posy;
|
||||
struct arg_end* end;
|
||||
} get_pixel_args;
|
||||
|
||||
static struct {
|
||||
struct arg_int *posx, *posy, *color;
|
||||
struct arg_end* end;
|
||||
} set_pixel_args;
|
||||
|
||||
static int get_rotation(int argc, char* argv[]);
|
||||
static int set_rotation(int argc, char* argv[]);
|
||||
static int get_width(int argc, char* argv[]);
|
||||
static int get_height(int argc, char* argv[]);
|
||||
static int get_pixel(int argc, char* argv[]);
|
||||
static int set_pixel(int argc, char* argv[]);
|
||||
static int clear_screen_cmd(int argc, char* argv[]);
|
||||
static int full_clear_screen_cmd(int argc, char* argv[]);
|
||||
static int get_temp(int argc, char* argv[]);
|
||||
static int power_on(int argc, char* argv[]);
|
||||
static int power_off(int argc, char* argv[]);
|
||||
|
||||
void register_screen_commands(void) {
|
||||
// setup arguments
|
||||
set_rotation_args.rotation = arg_strn(
|
||||
NULL, NULL, "<rotation>", 1, 1, "screen rotation: \"horizontal\" or \"portrait\""
|
||||
);
|
||||
set_rotation_args.inverted = arg_litn(NULL, "inverted", 0, 1, "");
|
||||
set_rotation_args.end = arg_end(NARGS(set_rotation_args));
|
||||
|
||||
get_pixel_args.posx = arg_intn(NULL, NULL, "<posx>", 1, 1, "x position");
|
||||
get_pixel_args.posy = arg_intn(NULL, NULL, "<posy>", 1, 1, "y position");
|
||||
get_pixel_args.end = arg_end(NARGS(get_pixel_args));
|
||||
|
||||
set_pixel_args.posx = arg_intn(NULL, NULL, "<posx>", 1, 1, "x position");
|
||||
set_pixel_args.posy = arg_intn(NULL, NULL, "<posy>", 1, 1, "y position");
|
||||
set_pixel_args.color = arg_intn(NULL, NULL, "<color>", 0, 1, "color. default value: 0 (0x00)");
|
||||
set_pixel_args.end = arg_end(NARGS(set_pixel_args));
|
||||
|
||||
const esp_console_cmd_t commands[] = {
|
||||
{ .command = "get_rotation",
|
||||
.help = "Get current screen rotation.",
|
||||
.hint = NULL,
|
||||
.func = &get_rotation },
|
||||
{ .command = "set_rotation",
|
||||
.help = "Changes screen rotation.",
|
||||
.hint = NULL,
|
||||
.func = &set_rotation,
|
||||
.argtable = &set_rotation_args },
|
||||
{ .command = "get_width", .help = "Print screen width.", .hint = NULL, .func = &get_width },
|
||||
{ .command = "get_height",
|
||||
.help = "Print screen height.",
|
||||
.hint = NULL,
|
||||
.func = &get_height },
|
||||
{ .command = "get_pixel",
|
||||
.help = "Get pixel color in front buffer.",
|
||||
.hint = NULL,
|
||||
.func = &get_pixel,
|
||||
.argtable = &get_pixel_args },
|
||||
{ .command = "set_pixel",
|
||||
.help = "Set pixel color in front buffer.",
|
||||
.hint = NULL,
|
||||
.func = &set_pixel,
|
||||
.argtable = &set_pixel_args },
|
||||
{ .command = "clear_screen",
|
||||
.help = "Clear the entire screen and reset the front buffer to white.",
|
||||
.hint = NULL,
|
||||
.func = &clear_screen_cmd },
|
||||
{ .command = "full_clear_screen",
|
||||
.help = "Same as clear_screen, but also tries to get rid of any artifacts by cycling "
|
||||
"through colors on the screen.",
|
||||
.hint = NULL,
|
||||
.func = &full_clear_screen_cmd },
|
||||
{ .command = "get_temp",
|
||||
.help = "Returns the ambient temperature.",
|
||||
.hint = NULL,
|
||||
.func = &get_temp },
|
||||
{ .command = "power_on",
|
||||
.help = "Turns on the power of the display.",
|
||||
.hint = NULL,
|
||||
.func = &power_on },
|
||||
{ .command = "power_off",
|
||||
.help = "Turns off the power of the display.",
|
||||
.hint = NULL,
|
||||
.func = &power_off }
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(commands); ++i)
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&commands[i]));
|
||||
}
|
||||
|
||||
static int get_rotation(int argc, char* argv[]) {
|
||||
enum EpdRotation rot = epd_get_rotation();
|
||||
if (rot == EPD_ROT_INVERTED_LANDSCAPE || rot == EPD_ROT_INVERTED_PORTRAIT)
|
||||
printf("inverted ");
|
||||
|
||||
if (rot == EPD_ROT_LANDSCAPE)
|
||||
printf("landscape\r\n");
|
||||
else if (rot == EPD_ROT_PORTRAIT)
|
||||
printf("portrait\r\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_rotation(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(set_rotation_args)
|
||||
|
||||
const char* rot_str = set_rotation_args.rotation->sval[0];
|
||||
const bool invert = set_rotation_args.inverted->count == 1;
|
||||
|
||||
enum EpdRotation rot = EPD_ROT_LANDSCAPE;
|
||||
if (!strcmp(rot_str, "landscape")) {
|
||||
if (invert)
|
||||
rot = EPD_ROT_INVERTED_LANDSCAPE;
|
||||
else
|
||||
rot = EPD_ROT_LANDSCAPE;
|
||||
} else if (!strcmp(rot_str, "portrait")) {
|
||||
if (invert)
|
||||
rot = EPD_ROT_INVERTED_PORTRAIT;
|
||||
else
|
||||
rot = EPD_ROT_PORTRAIT;
|
||||
}
|
||||
|
||||
epd_set_rotation(rot);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_width(int argc, char* argv[]) {
|
||||
printf("%d\r\n", epd_rotated_display_width());
|
||||
return 0;
|
||||
}
|
||||
static int get_height(int argc, char* argv[]) {
|
||||
printf("%d\r\n", epd_rotated_display_height());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void swap(int* lhs, int* rhs) {
|
||||
const int tmp = *lhs;
|
||||
*lhs = *rhs;
|
||||
*rhs = tmp;
|
||||
}
|
||||
|
||||
struct coords {
|
||||
int x, y;
|
||||
};
|
||||
|
||||
/* Basically the _rotate() function from epd_driver.c */
|
||||
static struct coords map_to_screen(int x, int y) {
|
||||
switch (epd_get_rotation()) {
|
||||
case EPD_ROT_LANDSCAPE:
|
||||
break;
|
||||
case EPD_ROT_PORTRAIT:
|
||||
swap(&x, &y);
|
||||
x = epd_width() - x - 1;
|
||||
break;
|
||||
case EPD_ROT_INVERTED_LANDSCAPE:
|
||||
x = epd_width() - x - 1;
|
||||
y = epd_height() - y - 1;
|
||||
break;
|
||||
case EPD_ROT_INVERTED_PORTRAIT:
|
||||
swap(&x, &y);
|
||||
y = epd_height() - y - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return (struct coords){ x, y };
|
||||
}
|
||||
|
||||
/* Read the pixel data from the front buffer, because there is no function provided by the driver.
|
||||
* Most importantly, we need to adjust the rotation of the incoming coordinates.
|
||||
*/
|
||||
static int get_pixel_color(int x, int y) {
|
||||
const struct coords adjusted = map_to_screen(x, y);
|
||||
|
||||
if (adjusted.x < 0 || adjusted.x >= epd_width() || adjusted.y < 0
|
||||
|| adjusted.y >= epd_height()) {
|
||||
printf(
|
||||
"Invalid coordinates (%d,%d): Must be withing the screen size (%d,%d).\r\n",
|
||||
adjusted.x,
|
||||
adjusted.y,
|
||||
epd_width(),
|
||||
epd_height()
|
||||
);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t pixel = g_framebuffer[adjusted.y * epd_width() / 2 + adjusted.x / 2];
|
||||
uint8_t color = (adjusted.x % 2) ? (pixel & 0xF0) : (pixel & 0x0F);
|
||||
|
||||
// repeat color pattern
|
||||
color |= (adjusted.x % 2) ? (color >> 4) : (color << 4);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
static int get_pixel(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(get_pixel_args)
|
||||
|
||||
const int pos_x = get_pixel_args.posx->ival[0];
|
||||
const int pos_y = get_pixel_args.posy->ival[0];
|
||||
|
||||
const int color = get_pixel_color(pos_x, pos_y);
|
||||
if (color == -1) {
|
||||
printf(
|
||||
"Invalid coordinates (%d,%d): Must be withing the screen size (%d,%d).\r\n",
|
||||
pos_x,
|
||||
pos_y,
|
||||
epd_rotated_display_width(),
|
||||
epd_rotated_display_height()
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Pixel (%d,%d) has color %d (0x%02x)\r\n", pos_x, pos_y, color, (uint8_t)color);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int set_pixel(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(set_pixel_args)
|
||||
|
||||
const int pos_x = set_pixel_args.posx->ival[0];
|
||||
const int pos_y = set_pixel_args.posy->ival[0];
|
||||
|
||||
uint8_t color = 0x00;
|
||||
if (!validate_color(&color, set_pixel_args.color))
|
||||
return 1;
|
||||
|
||||
epd_draw_pixel(pos_x, pos_y, color, g_framebuffer);
|
||||
printf("Set pixel (%d,%d) to color %d (0x%02x)\r\n", pos_x, pos_y, color, color);
|
||||
|
||||
update_screen();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int clear_screen_cmd(int argc, char* argv[]) {
|
||||
clear_screen();
|
||||
printf("Cleared screen.\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int full_clear_screen_cmd(int argc, char* argv[]) {
|
||||
full_clear_screen();
|
||||
printf("Cleared screen.\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int get_temp(int argc, char* argv[]) {
|
||||
epd_poweron();
|
||||
const float temp = epd_ambient_temperature();
|
||||
epd_poweroff();
|
||||
|
||||
printf("%.2f\r\n", temp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int power_on(int argc, char* argv[]) {
|
||||
epd_poweron();
|
||||
printf("Power turned on.\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int power_off(int argc, char* argv[]) {
|
||||
epd_poweroff();
|
||||
printf("Power turned off.\r\n");
|
||||
return 0;
|
||||
}
|
||||
3
lib/epdiy/examples/screen_diag/main/commands/screen.h
Normal file
3
lib/epdiy/examples/screen_diag/main/commands/screen.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void register_screen_commands(void);
|
||||
236
lib/epdiy/examples/screen_diag/main/commands/system.c
Normal file
236
lib/epdiy/examples/screen_diag/main/commands/system.c
Normal file
@@ -0,0 +1,236 @@
|
||||
#include "system.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
#include <argtable3/argtable3.h>
|
||||
#include <esp_app_desc.h>
|
||||
#include <esp_chip_info.h>
|
||||
#include <esp_console.h>
|
||||
#include <esp_heap_caps.h>
|
||||
#include <esp_mac.h>
|
||||
#include <esp_system.h>
|
||||
#include <esp_timer.h>
|
||||
|
||||
#include "../commands.h"
|
||||
|
||||
static struct {
|
||||
struct arg_int* caps;
|
||||
struct arg_end* end;
|
||||
} dump_heaps_args;
|
||||
|
||||
static struct {
|
||||
struct arg_str* interface;
|
||||
struct arg_end* end;
|
||||
} get_mac_args;
|
||||
|
||||
static int system_restart(int argc, char* argv[]);
|
||||
static int system_get_free_heap_size(int argc, char* argv[]);
|
||||
static int system_dump_heaps_info(int argc, char* argv[]);
|
||||
static int system_dump_chip_info(int argc, char* argv[]);
|
||||
static int system_dump_firmware_info(int argc, char* argv[]);
|
||||
static int system_get_time(int argc, char* argv[]);
|
||||
static int system_get_mac(int argc, char* argv[]);
|
||||
|
||||
void register_system_commands(void) {
|
||||
dump_heaps_args.caps
|
||||
= arg_intn(NULL, NULL, "<caps>", 0, 1, "Heap caps to print. Default: MALLOC_CAP_DEFAULT");
|
||||
dump_heaps_args.end = arg_end(NARGS(dump_heaps_args));
|
||||
|
||||
get_mac_args.interface = arg_strn(
|
||||
NULL,
|
||||
NULL,
|
||||
"<interface>",
|
||||
0,
|
||||
1,
|
||||
"Either \"wifi_station\", \"wifi_ap\", \"bluetooth\" or \"ethernet\""
|
||||
);
|
||||
get_mac_args.end = arg_end(NARGS(get_mac_args));
|
||||
|
||||
// register commands
|
||||
const esp_console_cmd_t commands[] = {
|
||||
{ .command = "system_restart",
|
||||
.help = "Restarts the system.",
|
||||
.hint = NULL,
|
||||
.func = &system_restart },
|
||||
{ .command = "free_heap_size",
|
||||
.help = "Returns the free heap size.",
|
||||
.hint = NULL,
|
||||
.func = &system_get_free_heap_size },
|
||||
{ .command = "dump_heaps_info",
|
||||
.help = "Dumps heap information of all heaps matching the capability.",
|
||||
.hint = NULL,
|
||||
.func = &system_dump_heaps_info,
|
||||
.argtable = &dump_heaps_args },
|
||||
{ .command = "chip_info",
|
||||
.help = "Dumps chip information.",
|
||||
.hint = NULL,
|
||||
.func = &system_dump_chip_info },
|
||||
{ .command = "firmware_info",
|
||||
.help = "Dumps information about the ESP-IDF and the firmware.",
|
||||
.hint = NULL,
|
||||
.func = &system_dump_firmware_info },
|
||||
{ .command = "get_time",
|
||||
.help = "Returns the time in microseconds since boot.",
|
||||
.hint = NULL,
|
||||
.func = &system_get_time },
|
||||
{ .command = "get_mac",
|
||||
.help
|
||||
= "Returns the MAC address for the given interface or the pre-programmed base address.",
|
||||
.hint = NULL,
|
||||
.func = &system_get_mac,
|
||||
.argtable = &get_mac_args }
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(commands); ++i)
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&commands[i]));
|
||||
}
|
||||
|
||||
static int system_restart(int argc, char* argv[]) {
|
||||
esp_restart();
|
||||
// unreachable
|
||||
}
|
||||
|
||||
static int system_get_free_heap_size(int argc, char* argv[]) {
|
||||
printf("Free heap size: %lu bytes.\r\n", esp_get_free_heap_size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int system_dump_heaps_info(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(dump_heaps_args);
|
||||
|
||||
uint32_t caps
|
||||
= dump_heaps_args.caps->count == 1 ? dump_heaps_args.caps->ival[0] : MALLOC_CAP_DEFAULT;
|
||||
|
||||
heap_caps_print_heap_info(caps);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char* chip_model_str(esp_chip_model_t model) {
|
||||
switch (model) {
|
||||
case CHIP_ESP32:
|
||||
return "ESP32";
|
||||
case CHIP_ESP32S2:
|
||||
return "ESP32S2";
|
||||
case CHIP_ESP32S3:
|
||||
return "ESP32S3";
|
||||
case CHIP_ESP32C3:
|
||||
return "ESP32C3";
|
||||
case CHIP_ESP32H2:
|
||||
return "ESP32H2";
|
||||
case CHIP_ESP32C2:
|
||||
return "ESP32C2";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static int system_dump_chip_info(int argc, char* argv[]) {
|
||||
esp_chip_info_t info;
|
||||
esp_chip_info(&info);
|
||||
|
||||
printf(
|
||||
"model: %s\r\n"
|
||||
"features (0x%lX):\r\n"
|
||||
"\tEMB_FLASH: %d\r\n"
|
||||
"\tWIFI_BGN: %d\r\n"
|
||||
"\tBLE:\t%d\r\n"
|
||||
"\tBT:\t%d\r\n"
|
||||
"\tIEEE802154: %d\r\n"
|
||||
"\tEMB_PSRAM: %d\r\n"
|
||||
"revision: %d.%d\r\n"
|
||||
"cores: %d\r\n",
|
||||
chip_model_str(info.model),
|
||||
info.features,
|
||||
(info.features & CHIP_FEATURE_EMB_PSRAM) != 0,
|
||||
(info.features & CHIP_FEATURE_WIFI_BGN) != 0,
|
||||
(info.features & CHIP_FEATURE_BLE) != 0,
|
||||
(info.features & CHIP_FEATURE_BT) != 0,
|
||||
(info.features & CHIP_FEATURE_IEEE802154) != 0,
|
||||
(info.features & CHIP_FEATURE_EMB_PSRAM) != 0,
|
||||
(info.revision / 100),
|
||||
(info.revision % 100),
|
||||
info.cores
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int system_dump_firmware_info(int argc, char* argv[]) {
|
||||
char hash[64];
|
||||
esp_app_get_elf_sha256(hash, 64);
|
||||
|
||||
const esp_app_desc_t* app = esp_app_get_description();
|
||||
|
||||
printf(
|
||||
"ESP-IDF version: %s\r\n"
|
||||
"Firmware info:\r\n"
|
||||
"\tmagic: 0x%lX\r\n"
|
||||
"\tsecure_version: 0x%lX\r\n"
|
||||
"\tversion: %s\r\n"
|
||||
"\tproject_name: %s\r\n"
|
||||
"\tcompile time/date: %s %s\r\n"
|
||||
"\telf sha256: %s\r\n",
|
||||
esp_get_idf_version(),
|
||||
app->magic_word,
|
||||
app->secure_version,
|
||||
app->version,
|
||||
app->project_name,
|
||||
app->time,
|
||||
app->date,
|
||||
hash
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int system_get_time(int argc, char* argv[]) {
|
||||
printf("Time in microseconds since boot: %llu\r\n", esp_timer_get_time());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_mac(uint8_t mac[8]) {
|
||||
// only print MAC-48 types
|
||||
printf("%02X:%02X:%02X:%02X:%02X:%02X\r\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
}
|
||||
|
||||
static int system_get_mac(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(get_mac_args);
|
||||
|
||||
uint8_t mac[8];
|
||||
|
||||
if (get_mac_args.interface->count == 0) {
|
||||
esp_base_mac_addr_get(mac);
|
||||
print_mac(mac);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
esp_mac_type_t type;
|
||||
const char* arg = get_mac_args.interface->sval[0];
|
||||
if (!strcmp(arg, "wifi_station"))
|
||||
type = ESP_MAC_WIFI_STA;
|
||||
else if (!strcmp(arg, "wifi_ap"))
|
||||
type = ESP_MAC_WIFI_SOFTAP;
|
||||
else if (!strcmp(arg, "bluetooth"))
|
||||
type = ESP_MAC_BT;
|
||||
else if (!strcmp(arg, "ethernet"))
|
||||
type = ESP_MAC_ETH;
|
||||
else {
|
||||
printf(
|
||||
"Invalid interface: \"%s\". Must be one of \"wifi_station\", \"wifi_ap\", "
|
||||
"\"bluetooth\" or \"ethernet\".\r\n",
|
||||
arg
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
|
||||
esp_read_mac(mac, type);
|
||||
print_mac(mac);
|
||||
|
||||
return 0;
|
||||
}
|
||||
3
lib/epdiy/examples/screen_diag/main/commands/system.h
Normal file
3
lib/epdiy/examples/screen_diag/main/commands/system.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void register_system_commands(void);
|
||||
138
lib/epdiy/examples/screen_diag/main/commands/tests.c
Normal file
138
lib/epdiy/examples/screen_diag/main/commands/tests.c
Normal file
@@ -0,0 +1,138 @@
|
||||
#include "tests.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <argtable3/argtable3.h>
|
||||
#include <esp_console.h>
|
||||
|
||||
#include "../commands.h"
|
||||
#include "../epd.h"
|
||||
#include "fonts.h"
|
||||
|
||||
static struct {
|
||||
struct arg_int* slope;
|
||||
struct arg_int* width;
|
||||
struct arg_int* color;
|
||||
struct arg_end* end;
|
||||
} render_stairs_args;
|
||||
|
||||
static struct {
|
||||
struct arg_int* gutter;
|
||||
struct arg_int* color;
|
||||
struct arg_end* end;
|
||||
} render_grid_args;
|
||||
|
||||
static int render_stairs_cmd(int argc, char* argv[]);
|
||||
static int render_grid_cmd(int argc, char* argv[]);
|
||||
|
||||
void register_tests_commands(void) {
|
||||
// setup args
|
||||
render_stairs_args.slope = arg_intn(
|
||||
NULL, NULL, "<slope>", 0, 1, "angle by which each diagonal line is drawn. default value: 3"
|
||||
);
|
||||
render_stairs_args.width = arg_intn(
|
||||
NULL, NULL, "<width>", 0, 1, "thickness of each diagonal line. default value: 100"
|
||||
);
|
||||
render_stairs_args.color = arg_intn(NULL, NULL, "<color>", 0, 1, "default value: 0x00");
|
||||
render_stairs_args.end = arg_end(NARGS(render_stairs_args));
|
||||
|
||||
render_grid_args.gutter
|
||||
= arg_intn(NULL, NULL, "<gutter>", 0, 1, "default value: 75"); // gcd(1200, 825) = 75
|
||||
render_grid_args.color = arg_intn(NULL, NULL, "<color>", 0, 1, "default value: 0x00");
|
||||
render_grid_args.end = arg_end(NARGS(render_grid_args));
|
||||
|
||||
// register commands
|
||||
const esp_console_cmd_t commands[] = {
|
||||
{ .command = "render_stairs",
|
||||
.help = "Render multiple diagonal lines across the screen.",
|
||||
.hint = NULL,
|
||||
.func = &render_stairs_cmd,
|
||||
.argtable = &render_stairs_args },
|
||||
{ .command = "render_grid",
|
||||
.help
|
||||
= "Renders a grid across the whole screen. At a certain gutter size, cell info will "
|
||||
"be printed as well.",
|
||||
.hint = NULL,
|
||||
.func = &render_grid_cmd,
|
||||
.argtable = &render_grid_args },
|
||||
};
|
||||
|
||||
for (size_t i = 0; i < ARRAY_SIZE(commands); ++i)
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&commands[i]));
|
||||
}
|
||||
|
||||
static void render_stairs(int slope, int width, uint8_t color) {
|
||||
for (int y = 0, x = 0; y < epd_rotated_display_height(); y++) {
|
||||
epd_draw_hline(x, y, width, color, g_framebuffer);
|
||||
x += slope;
|
||||
if (x + width > epd_rotated_display_width())
|
||||
x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int render_stairs_cmd(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(render_stairs_args)
|
||||
|
||||
uint8_t color = 0x00;
|
||||
if (!validate_color(&color, render_stairs_args.color))
|
||||
return 1;
|
||||
|
||||
const int slope = GET_INT_ARG(render_stairs_args.slope, 3);
|
||||
const int width = GET_INT_ARG(render_stairs_args.width, 100);
|
||||
|
||||
if (slope < 1 || slope > width) {
|
||||
printf("Slope %d is too steep: Must be between 1 and width (%d)\r\n", slope, width);
|
||||
return 1;
|
||||
}
|
||||
|
||||
render_stairs(slope, width, color);
|
||||
update_screen();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void render_grid(int gutter, uint8_t color) {
|
||||
const int width = epd_rotated_display_width();
|
||||
const int height = epd_rotated_display_height();
|
||||
|
||||
// draw lines
|
||||
for (int row = gutter; row < height; row += gutter)
|
||||
epd_draw_hline(0, row, width, color, g_framebuffer);
|
||||
|
||||
for (int col = gutter; col < width; col += gutter)
|
||||
epd_draw_vline(col, 0, height, color, g_framebuffer);
|
||||
|
||||
// skip printing info if it wouldn't fit
|
||||
if (gutter < Alexandria.advance_y * 2)
|
||||
return;
|
||||
|
||||
// prepare info
|
||||
static char label[32];
|
||||
int col = 0, row;
|
||||
|
||||
for (int y = 0; y < height; y += gutter, ++col) {
|
||||
row = 0;
|
||||
for (int x = 0; x < width; x += gutter, ++row) {
|
||||
// print info
|
||||
snprintf(label, sizeof(label), "(%d,%d)", row, col);
|
||||
int rx = y + Alexandria.advance_y;
|
||||
int cx = x + 4; // margin
|
||||
epd_write_default(&Alexandria, label, &cx, &rx, g_framebuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int render_grid_cmd(int argc, char* argv[]) {
|
||||
HANDLE_ARGUMENTS(render_grid_args)
|
||||
|
||||
uint8_t color = 0x00;
|
||||
if (!validate_color(&color, render_grid_args.color))
|
||||
return 1;
|
||||
|
||||
const int gutter = GET_INT_ARG(render_grid_args.gutter, 75);
|
||||
|
||||
render_grid(gutter, color);
|
||||
update_screen();
|
||||
|
||||
return 0;
|
||||
}
|
||||
3
lib/epdiy/examples/screen_diag/main/commands/tests.h
Normal file
3
lib/epdiy/examples/screen_diag/main/commands/tests.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void register_tests_commands(void);
|
||||
Reference in New Issue
Block a user