636 lines
13 KiB
C
636 lines
13 KiB
C
/** @file
|
|
* @brief Monochrome Character Framebuffer shell module
|
|
*
|
|
* Provide some Character Framebuffer shell commands that can be useful for
|
|
* testing.
|
|
*/
|
|
|
|
/*
|
|
* Copyright (c) 2018 Diego Sueiro
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <zephyr/shell/shell.h>
|
|
#include <zephyr/display/cfb.h>
|
|
|
|
#define HELP_NONE "[none]"
|
|
#define HELP_INIT "call \"cfb init\" first"
|
|
#define HELP_PRINT "<col: pos> <row: pos> \"<text>\""
|
|
#define HELP_DRAW_POINT "<x> <y0>"
|
|
#define HELP_DRAW_LINE "<x0> <y0> <x1> <y1>"
|
|
#define HELP_DRAW_RECT "<x0> <y0> <x1> <y1>"
|
|
#define HELP_INVERT "[<x> <y> <width> <height>]"
|
|
|
|
static const struct device *const dev =
|
|
DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
|
|
static const char * const param_name[] = {
|
|
"height", "width", "ppt", "rows", "cols"};
|
|
|
|
static int cmd_clear(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
int err;
|
|
|
|
ARG_UNUSED(argc);
|
|
ARG_UNUSED(argv);
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
err = cfb_framebuffer_clear(dev, true);
|
|
if (err) {
|
|
shell_error(sh, "Framebuffer clear error=%d", err);
|
|
return err;
|
|
}
|
|
|
|
err = cfb_framebuffer_finalize(dev);
|
|
if (err) {
|
|
shell_error(sh, "Framebuffer finalize error=%d", err);
|
|
return err;
|
|
}
|
|
|
|
shell_print(sh, "Display Cleared");
|
|
|
|
return err;
|
|
}
|
|
|
|
static int cmd_cfb_print(const struct shell *sh, int col, int row, char *str)
|
|
{
|
|
int err;
|
|
uint8_t ppt;
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
ppt = cfb_get_display_parameter(dev, CFB_DISPLAY_PPT);
|
|
|
|
err = cfb_framebuffer_clear(dev, false);
|
|
if (err) {
|
|
shell_error(sh, "Framebuffer clear failed error=%d", err);
|
|
return err;
|
|
}
|
|
|
|
err = cfb_print(dev, str, col, row * ppt);
|
|
if (err) {
|
|
shell_error(sh, "Failed to print the string %s error=%d",
|
|
str, err);
|
|
return err;
|
|
}
|
|
|
|
err = cfb_framebuffer_finalize(dev);
|
|
if (err) {
|
|
shell_error(sh,
|
|
"Failed to finalize the Framebuffer error=%d", err);
|
|
return err;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int cmd_print(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
int err;
|
|
int col, row;
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
col = strtol(argv[1], NULL, 10);
|
|
if (col > cfb_get_display_parameter(dev, CFB_DISPLAY_COLS)) {
|
|
shell_error(sh, "Invalid col=%d position", col);
|
|
return -EINVAL;
|
|
}
|
|
|
|
row = strtol(argv[2], NULL, 10);
|
|
if (row > cfb_get_display_parameter(dev, CFB_DISPLAY_ROWS)) {
|
|
shell_error(sh, "Invalid row=%d position", row);
|
|
return -EINVAL;
|
|
}
|
|
|
|
err = cmd_cfb_print(sh, col, row, argv[3]);
|
|
if (err) {
|
|
shell_error(sh, "Failed printing to Framebuffer error=%d",
|
|
err);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int cmd_draw_text(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
int err;
|
|
int x, y;
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
x = strtol(argv[1], NULL, 10);
|
|
y = strtol(argv[2], NULL, 10);
|
|
err = cfb_draw_text(dev, argv[3], x, y);
|
|
if (err) {
|
|
shell_error(sh, "Failed text drawing to Framebuffer error=%d", err);
|
|
return err;
|
|
}
|
|
|
|
err = cfb_framebuffer_finalize(dev);
|
|
|
|
return err;
|
|
}
|
|
|
|
static int cmd_draw_point(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
int err;
|
|
struct cfb_position pos;
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
pos.x = strtol(argv[1], NULL, 10);
|
|
pos.y = strtol(argv[2], NULL, 10);
|
|
|
|
err = cfb_draw_point(dev, &pos);
|
|
if (err) {
|
|
shell_error(sh, "Failed point drawing to Framebuffer error=%d", err);
|
|
return err;
|
|
}
|
|
|
|
err = cfb_framebuffer_finalize(dev);
|
|
|
|
return err;
|
|
}
|
|
|
|
static int cmd_draw_line(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
int err;
|
|
struct cfb_position start, end;
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
start.x = strtol(argv[1], NULL, 10);
|
|
start.y = strtol(argv[2], NULL, 10);
|
|
end.x = strtol(argv[3], NULL, 10);
|
|
end.y = strtol(argv[4], NULL, 10);
|
|
|
|
err = cfb_draw_line(dev, &start, &end);
|
|
if (err) {
|
|
shell_error(sh, "Failed text drawing to Framebuffer error=%d", err);
|
|
return err;
|
|
}
|
|
|
|
err = cfb_framebuffer_finalize(dev);
|
|
|
|
return err;
|
|
}
|
|
|
|
static int cmd_draw_rect(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
int err;
|
|
struct cfb_position start, end;
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
start.x = strtol(argv[1], NULL, 10);
|
|
start.y = strtol(argv[2], NULL, 10);
|
|
end.x = strtol(argv[3], NULL, 10);
|
|
end.y = strtol(argv[4], NULL, 10);
|
|
|
|
err = cfb_draw_rect(dev, &start, &end);
|
|
if (err) {
|
|
shell_error(sh, "Failed rectanble drawing to Framebuffer error=%d", err);
|
|
return err;
|
|
}
|
|
|
|
err = cfb_framebuffer_finalize(dev);
|
|
|
|
return err;
|
|
}
|
|
|
|
static int cmd_scroll_vert(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
int err = 0;
|
|
int col, row;
|
|
int boundary;
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
col = strtol(argv[1], NULL, 10);
|
|
if (col > cfb_get_display_parameter(dev, CFB_DISPLAY_COLS)) {
|
|
shell_error(sh, "Invalid col=%d position", col);
|
|
return -EINVAL;
|
|
}
|
|
|
|
row = strtol(argv[2], NULL, 10);
|
|
if (row > cfb_get_display_parameter(dev, CFB_DISPLAY_ROWS)) {
|
|
shell_error(sh, "Invalid row=%d position", row);
|
|
return -EINVAL;
|
|
}
|
|
|
|
boundary = cfb_get_display_parameter(dev, CFB_DISPLAY_ROWS) - row;
|
|
|
|
for (int i = 0; i < boundary; i++) {
|
|
err = cmd_cfb_print(sh, col, row, argv[3]);
|
|
if (err) {
|
|
shell_error(sh,
|
|
"Failed printing to Framebuffer error=%d",
|
|
err);
|
|
break;
|
|
}
|
|
row++;
|
|
}
|
|
|
|
cmd_cfb_print(sh, 0, 0, "");
|
|
|
|
return err;
|
|
}
|
|
|
|
static int cmd_scroll_horz(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
int err = 0;
|
|
int col, row;
|
|
int boundary;
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
col = strtol(argv[1], NULL, 10);
|
|
if (col > cfb_get_display_parameter(dev, CFB_DISPLAY_COLS)) {
|
|
shell_error(sh, "Invalid col=%d position", col);
|
|
return -EINVAL;
|
|
}
|
|
|
|
row = strtol(argv[2], NULL, 10);
|
|
if (row > cfb_get_display_parameter(dev, CFB_DISPLAY_ROWS)) {
|
|
shell_error(sh, "Invalid row=%d position", row);
|
|
return -EINVAL;
|
|
}
|
|
|
|
col++;
|
|
boundary = cfb_get_display_parameter(dev, CFB_DISPLAY_COLS) - col;
|
|
|
|
for (int i = 0; i < boundary; i++) {
|
|
err = cmd_cfb_print(sh, col, row, argv[3]);
|
|
if (err) {
|
|
shell_error(sh,
|
|
"Failed printing to Framebuffer error=%d",
|
|
err);
|
|
break;
|
|
}
|
|
col++;
|
|
}
|
|
|
|
cmd_cfb_print(sh, 0, 0, "");
|
|
|
|
return err;
|
|
}
|
|
|
|
static int cmd_set_font(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
int err;
|
|
int idx;
|
|
uint8_t height;
|
|
uint8_t width;
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
idx = strtol(argv[1], NULL, 10);
|
|
|
|
err = cfb_get_font_size(dev, idx, &width, &height);
|
|
if (err) {
|
|
shell_error(sh, "Invalid font idx=%d err=%d\n", idx, err);
|
|
return err;
|
|
}
|
|
|
|
err = cfb_framebuffer_set_font(dev, idx);
|
|
if (err) {
|
|
shell_error(sh, "Failed setting font idx=%d err=%d", idx,
|
|
err);
|
|
return err;
|
|
}
|
|
|
|
shell_print(sh, "Font idx=%d height=%d widht=%d set", idx, height,
|
|
width);
|
|
|
|
return err;
|
|
}
|
|
|
|
static int cmd_set_kerning(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
int err;
|
|
char *ep = NULL;
|
|
long kerning;
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
errno = 0;
|
|
kerning = strtol(argv[1], &ep, 10);
|
|
if (errno || ep == argv[1]) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -EINVAL;
|
|
}
|
|
|
|
err = cfb_set_kerning(dev, kerning);
|
|
if (err) {
|
|
shell_error(sh, "Failed to set kerning err=%d", err);
|
|
return err;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int cmd_invert(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
int err;
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
if (argc == 1) {
|
|
err = cfb_framebuffer_invert(dev);
|
|
if (err) {
|
|
shell_error(sh, "Error inverting Framebuffer");
|
|
return err;
|
|
}
|
|
} else if (argc == 5) {
|
|
int x, y, w, h;
|
|
|
|
x = strtol(argv[1], NULL, 10);
|
|
y = strtol(argv[2], NULL, 10);
|
|
w = strtol(argv[3], NULL, 10);
|
|
h = strtol(argv[4], NULL, 10);
|
|
|
|
err = cfb_invert_area(dev, x, y, w, h);
|
|
if (err) {
|
|
shell_error(sh, "Error invert area");
|
|
return err;
|
|
}
|
|
} else {
|
|
shell_help(sh);
|
|
return 0;
|
|
}
|
|
|
|
cfb_framebuffer_finalize(dev);
|
|
|
|
shell_print(sh, "Framebuffer Inverted");
|
|
|
|
return err;
|
|
}
|
|
|
|
static int cmd_get_fonts(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
int err = 0;
|
|
uint8_t font_height;
|
|
uint8_t font_width;
|
|
|
|
ARG_UNUSED(argc);
|
|
ARG_UNUSED(argv);
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
for (int idx = 0; idx < cfb_get_numof_fonts(dev); idx++) {
|
|
if (cfb_get_font_size(dev, idx, &font_width, &font_height)) {
|
|
break;
|
|
}
|
|
shell_print(sh, "idx=%d height=%d width=%d", idx,
|
|
font_height, font_width);
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
static int cmd_get_device(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
int err = 0;
|
|
|
|
ARG_UNUSED(argc);
|
|
ARG_UNUSED(argv);
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
shell_print(sh, "Framebuffer Device: %s", dev->name);
|
|
|
|
return err;
|
|
}
|
|
|
|
static int cmd_get_param_all(const struct shell *sh, size_t argc,
|
|
char *argv[])
|
|
{
|
|
ARG_UNUSED(argc);
|
|
ARG_UNUSED(argv);
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
for (unsigned int i = 0; i <= CFB_DISPLAY_COLS; i++) {
|
|
shell_print(sh, "param: %s=%d", param_name[i],
|
|
cfb_get_display_parameter(dev, i));
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cmd_get_param_height(const struct shell *sh, size_t argc,
|
|
char *argv[])
|
|
{
|
|
ARG_UNUSED(argc);
|
|
ARG_UNUSED(argv);
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
shell_print(sh, "param: %s=%d", param_name[CFB_DISPLAY_HEIGH],
|
|
cfb_get_display_parameter(dev, CFB_DISPLAY_HEIGH));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cmd_get_param_width(const struct shell *sh, size_t argc,
|
|
char *argv[])
|
|
{
|
|
ARG_UNUSED(argc);
|
|
ARG_UNUSED(argv);
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
shell_print(sh, "param: %s=%d", param_name[CFB_DISPLAY_WIDTH],
|
|
cfb_get_display_parameter(dev, CFB_DISPLAY_WIDTH));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cmd_get_param_ppt(const struct shell *sh, size_t argc,
|
|
char *argv[])
|
|
{
|
|
ARG_UNUSED(argc);
|
|
ARG_UNUSED(argv);
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
shell_print(sh, "param: %s=%d", param_name[CFB_DISPLAY_PPT],
|
|
cfb_get_display_parameter(dev, CFB_DISPLAY_PPT));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cmd_get_param_rows(const struct shell *sh, size_t argc,
|
|
char *argv[])
|
|
{
|
|
ARG_UNUSED(argc);
|
|
ARG_UNUSED(argv);
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
shell_print(sh, "param: %s=%d", param_name[CFB_DISPLAY_ROWS],
|
|
cfb_get_display_parameter(dev, CFB_DISPLAY_ROWS));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cmd_get_param_cols(const struct shell *sh, size_t argc,
|
|
char *argv[])
|
|
{
|
|
ARG_UNUSED(argc);
|
|
ARG_UNUSED(argv);
|
|
|
|
if (!dev) {
|
|
shell_error(sh, HELP_INIT);
|
|
return -ENODEV;
|
|
}
|
|
|
|
shell_print(sh, "param: %s=%d", param_name[CFB_DISPLAY_COLS],
|
|
cfb_get_display_parameter(dev, CFB_DISPLAY_COLS));
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int cmd_init(const struct shell *sh, size_t argc, char *argv[])
|
|
{
|
|
int err;
|
|
|
|
if (!device_is_ready(dev)) {
|
|
shell_error(sh, "Display device not ready");
|
|
return -ENODEV;
|
|
}
|
|
|
|
err = display_set_pixel_format(dev, PIXEL_FORMAT_MONO10);
|
|
if (err) {
|
|
err = display_set_pixel_format(dev, PIXEL_FORMAT_MONO01);
|
|
if (err) {
|
|
shell_error(sh, "Failed to set required pixel format: %d", err);
|
|
return err;
|
|
}
|
|
}
|
|
|
|
err = display_blanking_off(dev);
|
|
if (err) {
|
|
shell_error(sh, "Failed to turn off display blanking: %d", err);
|
|
return err;
|
|
}
|
|
|
|
err = cfb_framebuffer_init(dev);
|
|
if (err) {
|
|
shell_error(sh, "Framebuffer initialization failed!");
|
|
return err;
|
|
}
|
|
|
|
shell_print(sh, "Framebuffer initialized: %s", dev->name);
|
|
cmd_clear(sh, argc, argv);
|
|
|
|
return err;
|
|
}
|
|
|
|
SHELL_STATIC_SUBCMD_SET_CREATE(sub_cmd_get_param,
|
|
|
|
SHELL_CMD_ARG(all, NULL, NULL, cmd_get_param_all, 1, 0),
|
|
SHELL_CMD_ARG(height, NULL, NULL, cmd_get_param_height, 1, 0),
|
|
SHELL_CMD_ARG(width, NULL, NULL, cmd_get_param_width, 1, 0),
|
|
SHELL_CMD_ARG(ppt, NULL, NULL, cmd_get_param_ppt, 1, 0),
|
|
SHELL_CMD_ARG(rows, NULL, NULL, cmd_get_param_rows, 1, 0),
|
|
SHELL_CMD_ARG(cols, NULL, NULL, cmd_get_param_cols, 1, 0),
|
|
SHELL_SUBCMD_SET_END
|
|
);
|
|
|
|
SHELL_STATIC_SUBCMD_SET_CREATE(sub_cmd_scroll,
|
|
|
|
SHELL_CMD_ARG(vertical, NULL, HELP_PRINT, cmd_scroll_vert, 4, 0),
|
|
SHELL_CMD_ARG(horizontal, NULL, HELP_PRINT, cmd_scroll_horz, 4, 0),
|
|
SHELL_SUBCMD_SET_END
|
|
);
|
|
|
|
SHELL_STATIC_SUBCMD_SET_CREATE(sub_cmd_draw,
|
|
SHELL_CMD_ARG(text, NULL, HELP_PRINT, cmd_draw_text, 4, 0),
|
|
SHELL_CMD_ARG(point, NULL, HELP_DRAW_POINT, cmd_draw_point, 3, 0),
|
|
SHELL_CMD_ARG(line, NULL, HELP_DRAW_LINE, cmd_draw_line, 5, 0),
|
|
SHELL_CMD_ARG(rect, NULL, HELP_DRAW_RECT, cmd_draw_rect, 5, 0),
|
|
SHELL_SUBCMD_SET_END
|
|
);
|
|
|
|
SHELL_STATIC_SUBCMD_SET_CREATE(cfb_cmds,
|
|
SHELL_CMD_ARG(init, NULL, HELP_NONE, cmd_init, 1, 0),
|
|
SHELL_CMD_ARG(get_device, NULL, HELP_NONE, cmd_get_device, 1, 0),
|
|
SHELL_CMD(get_param, &sub_cmd_get_param,
|
|
"<all, height, width, ppt, rows, cols>", NULL),
|
|
SHELL_CMD_ARG(get_fonts, NULL, HELP_NONE, cmd_get_fonts, 1, 0),
|
|
SHELL_CMD_ARG(set_font, NULL, "<idx>", cmd_set_font, 2, 0),
|
|
SHELL_CMD_ARG(set_kerning, NULL, "<kerning>", cmd_set_kerning, 2, 0),
|
|
SHELL_CMD_ARG(invert, NULL, HELP_INVERT, cmd_invert, 1, 5),
|
|
SHELL_CMD_ARG(print, NULL, HELP_PRINT, cmd_print, 4, 0),
|
|
SHELL_CMD(scroll, &sub_cmd_scroll, "scroll a text in vertical or "
|
|
"horizontal direction", NULL),
|
|
SHELL_CMD(draw, &sub_cmd_draw, "drawing text", NULL),
|
|
SHELL_CMD_ARG(clear, NULL, HELP_NONE, cmd_clear, 1, 0),
|
|
SHELL_SUBCMD_SET_END
|
|
);
|
|
|
|
SHELL_CMD_REGISTER(cfb, &cfb_cmds, "Character Framebuffer shell commands",
|
|
NULL);
|