1 /** @file
2 * @brief Monochrome Character Framebuffer shell module
3 *
4 * Provide some Character Framebuffer shell commands that can be useful for
5 * testing.
6 */
7
8 /*
9 * Copyright (c) 2018 Diego Sueiro
10 *
11 * SPDX-License-Identifier: Apache-2.0
12 */
13
14 #include <stdlib.h>
15 #include <zephyr/shell/shell.h>
16 #include <zephyr/display/cfb.h>
17
18 #define HELP_NONE "[none]"
19 #define HELP_INIT "call \"cfb init\" first"
20 #define HELP_PRINT "<col: pos> <row: pos> \"<text>\""
21 #define HELP_DRAW_POINT "<x> <y>"
22 #define HELP_DRAW_LINE "<x0> <y0> <x1> <y1>"
23 #define HELP_DRAW_RECT "<x0> <y0> <x1> <y1>"
24 #define HELP_DRAW_CIRCLE "<x> <y> <radius>"
25 #define HELP_INVERT "[<x> <y> <width> <height>]"
26
27 static const struct device *const dev =
28 DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
29 static const char * const param_name[] = {
30 "height", "width", "ppt", "rows", "cols"};
31
cmd_clear(const struct shell * sh,size_t argc,char * argv[])32 static int cmd_clear(const struct shell *sh, size_t argc, char *argv[])
33 {
34 int err;
35
36 ARG_UNUSED(argc);
37 ARG_UNUSED(argv);
38
39 err = cfb_framebuffer_clear(dev, true);
40 if (err) {
41 shell_error(sh, "Framebuffer clear error=%d", err);
42 return err;
43 }
44
45 err = cfb_framebuffer_finalize(dev);
46 if (err) {
47 shell_error(sh, "Framebuffer finalize error=%d", err);
48 return err;
49 }
50
51 shell_print(sh, "Display Cleared");
52
53 return err;
54 }
55
cmd_cfb_print(const struct shell * sh,int col,int row,char * str)56 static int cmd_cfb_print(const struct shell *sh, int col, int row, char *str)
57 {
58 int err;
59 uint8_t ppt;
60
61 ppt = cfb_get_display_parameter(dev, CFB_DISPLAY_PPT);
62
63 err = cfb_framebuffer_clear(dev, false);
64 if (err) {
65 shell_error(sh, "Framebuffer clear failed error=%d", err);
66 return err;
67 }
68
69 err = cfb_print(dev, str, col, row * ppt);
70 if (err) {
71 shell_error(sh, "Failed to print the string %s error=%d",
72 str, err);
73 return err;
74 }
75
76 err = cfb_framebuffer_finalize(dev);
77 if (err) {
78 shell_error(sh,
79 "Failed to finalize the Framebuffer error=%d", err);
80 return err;
81 }
82
83 return err;
84 }
85
cmd_print(const struct shell * sh,size_t argc,char * argv[])86 static int cmd_print(const struct shell *sh, size_t argc, char *argv[])
87 {
88 int err;
89 int col, row;
90
91 col = strtol(argv[1], NULL, 10);
92 if (col > cfb_get_display_parameter(dev, CFB_DISPLAY_COLS)) {
93 shell_error(sh, "Invalid col=%d position", col);
94 return -EINVAL;
95 }
96
97 row = strtol(argv[2], NULL, 10);
98 if (row > cfb_get_display_parameter(dev, CFB_DISPLAY_ROWS)) {
99 shell_error(sh, "Invalid row=%d position", row);
100 return -EINVAL;
101 }
102
103 err = cmd_cfb_print(sh, col, row, argv[3]);
104 if (err) {
105 shell_error(sh, "Failed printing to Framebuffer error=%d",
106 err);
107 }
108
109 return err;
110 }
111
cmd_draw_text(const struct shell * sh,size_t argc,char * argv[])112 static int cmd_draw_text(const struct shell *sh, size_t argc, char *argv[])
113 {
114 int err;
115 int x, y;
116
117 x = strtol(argv[1], NULL, 10);
118 y = strtol(argv[2], NULL, 10);
119 err = cfb_draw_text(dev, argv[3], x, y);
120 if (err) {
121 shell_error(sh, "Failed text drawing to Framebuffer error=%d", err);
122 return err;
123 }
124
125 err = cfb_framebuffer_finalize(dev);
126
127 return err;
128 }
129
cmd_draw_point(const struct shell * sh,size_t argc,char * argv[])130 static int cmd_draw_point(const struct shell *sh, size_t argc, char *argv[])
131 {
132 int err;
133 struct cfb_position pos;
134
135 pos.x = strtol(argv[1], NULL, 10);
136 pos.y = strtol(argv[2], NULL, 10);
137
138 err = cfb_draw_point(dev, &pos);
139 if (err) {
140 shell_error(sh, "Failed point drawing to Framebuffer error=%d", err);
141 return err;
142 }
143
144 err = cfb_framebuffer_finalize(dev);
145
146 return err;
147 }
148
cmd_draw_line(const struct shell * sh,size_t argc,char * argv[])149 static int cmd_draw_line(const struct shell *sh, size_t argc, char *argv[])
150 {
151 int err;
152 struct cfb_position start, end;
153
154 start.x = strtol(argv[1], NULL, 10);
155 start.y = strtol(argv[2], NULL, 10);
156 end.x = strtol(argv[3], NULL, 10);
157 end.y = strtol(argv[4], NULL, 10);
158
159 err = cfb_draw_line(dev, &start, &end);
160 if (err) {
161 shell_error(sh, "Failed text drawing to Framebuffer error=%d", err);
162 return err;
163 }
164
165 err = cfb_framebuffer_finalize(dev);
166
167 return err;
168 }
169
cmd_draw_rect(const struct shell * sh,size_t argc,char * argv[])170 static int cmd_draw_rect(const struct shell *sh, size_t argc, char *argv[])
171 {
172 int err;
173 struct cfb_position start, end;
174
175 start.x = strtol(argv[1], NULL, 10);
176 start.y = strtol(argv[2], NULL, 10);
177 end.x = strtol(argv[3], NULL, 10);
178 end.y = strtol(argv[4], NULL, 10);
179
180 err = cfb_draw_rect(dev, &start, &end);
181 if (err) {
182 shell_error(sh, "Failed rectanble drawing to Framebuffer error=%d", err);
183 return err;
184 }
185
186 err = cfb_framebuffer_finalize(dev);
187
188 return err;
189 }
190
cmd_draw_circle(const struct shell * sh,size_t argc,char * argv[])191 static int cmd_draw_circle(const struct shell *sh, size_t argc, char *argv[])
192 {
193 int err;
194 struct cfb_position center;
195 uint16_t radius;
196
197 center.x = strtol(argv[1], NULL, 10);
198 center.y = strtol(argv[2], NULL, 10);
199 radius = strtol(argv[3], NULL, 10);
200
201 err = cfb_draw_circle(dev, ¢er, radius);
202 if (err) {
203 shell_error(sh, "Failed circle drawing to Framebuffer error=%d", err);
204 return err;
205 }
206
207 err = cfb_framebuffer_finalize(dev);
208
209 return err;
210 }
211
cmd_scroll_vert(const struct shell * sh,size_t argc,char * argv[])212 static int cmd_scroll_vert(const struct shell *sh, size_t argc, char *argv[])
213 {
214 int err = 0;
215 int col, row;
216 int boundary;
217
218 col = strtol(argv[1], NULL, 10);
219 if (col > cfb_get_display_parameter(dev, CFB_DISPLAY_COLS)) {
220 shell_error(sh, "Invalid col=%d position", col);
221 return -EINVAL;
222 }
223
224 row = strtol(argv[2], NULL, 10);
225 if (row > cfb_get_display_parameter(dev, CFB_DISPLAY_ROWS)) {
226 shell_error(sh, "Invalid row=%d position", row);
227 return -EINVAL;
228 }
229
230 boundary = cfb_get_display_parameter(dev, CFB_DISPLAY_ROWS) - row;
231
232 for (int i = 0; i < boundary; i++) {
233 err = cmd_cfb_print(sh, col, row, argv[3]);
234 if (err) {
235 shell_error(sh,
236 "Failed printing to Framebuffer error=%d",
237 err);
238 break;
239 }
240 row++;
241 }
242
243 cmd_cfb_print(sh, 0, 0, "");
244
245 return err;
246 }
247
cmd_scroll_horz(const struct shell * sh,size_t argc,char * argv[])248 static int cmd_scroll_horz(const struct shell *sh, size_t argc, char *argv[])
249 {
250 int err = 0;
251 int col, row;
252 int boundary;
253
254 col = strtol(argv[1], NULL, 10);
255 if (col > cfb_get_display_parameter(dev, CFB_DISPLAY_COLS)) {
256 shell_error(sh, "Invalid col=%d position", col);
257 return -EINVAL;
258 }
259
260 row = strtol(argv[2], NULL, 10);
261 if (row > cfb_get_display_parameter(dev, CFB_DISPLAY_ROWS)) {
262 shell_error(sh, "Invalid row=%d position", row);
263 return -EINVAL;
264 }
265
266 col++;
267 boundary = cfb_get_display_parameter(dev, CFB_DISPLAY_COLS) - col;
268
269 for (int i = 0; i < boundary; i++) {
270 err = cmd_cfb_print(sh, col, row, argv[3]);
271 if (err) {
272 shell_error(sh,
273 "Failed printing to Framebuffer error=%d",
274 err);
275 break;
276 }
277 col++;
278 }
279
280 cmd_cfb_print(sh, 0, 0, "");
281
282 return err;
283 }
284
cmd_set_font(const struct shell * sh,size_t argc,char * argv[])285 static int cmd_set_font(const struct shell *sh, size_t argc, char *argv[])
286 {
287 int err;
288 int idx;
289 uint8_t height;
290 uint8_t width;
291
292 idx = strtol(argv[1], NULL, 10);
293
294 err = cfb_get_font_size(dev, idx, &width, &height);
295 if (err) {
296 shell_error(sh, "Invalid font idx=%d err=%d\n", idx, err);
297 return err;
298 }
299
300 err = cfb_framebuffer_set_font(dev, idx);
301 if (err) {
302 shell_error(sh, "Failed setting font idx=%d err=%d", idx,
303 err);
304 return err;
305 }
306
307 shell_print(sh, "Font idx=%d height=%d width=%d set", idx, height,
308 width);
309
310 return err;
311 }
312
cmd_set_kerning(const struct shell * sh,size_t argc,char * argv[])313 static int cmd_set_kerning(const struct shell *sh, size_t argc, char *argv[])
314 {
315 int err = 0;
316 long kerning;
317
318 kerning = shell_strtol(argv[1], 10, &err);
319 if (err) {
320 shell_error(sh, HELP_INIT);
321 return -EINVAL;
322 }
323
324 err = cfb_set_kerning(dev, kerning);
325 if (err) {
326 shell_error(sh, "Failed to set kerning err=%d", err);
327 return err;
328 }
329
330 return err;
331 }
332
cmd_invert(const struct shell * sh,size_t argc,char * argv[])333 static int cmd_invert(const struct shell *sh, size_t argc, char *argv[])
334 {
335 int err;
336
337 if (argc == 1) {
338 err = cfb_framebuffer_invert(dev);
339 if (err) {
340 shell_error(sh, "Error inverting Framebuffer");
341 return err;
342 }
343 } else if (argc == 5) {
344 int x, y, w, h;
345
346 x = strtol(argv[1], NULL, 10);
347 y = strtol(argv[2], NULL, 10);
348 w = strtol(argv[3], NULL, 10);
349 h = strtol(argv[4], NULL, 10);
350
351 err = cfb_invert_area(dev, x, y, w, h);
352 if (err) {
353 shell_error(sh, "Error invert area");
354 return err;
355 }
356 } else {
357 shell_help(sh);
358 return 0;
359 }
360
361 cfb_framebuffer_finalize(dev);
362
363 shell_print(sh, "Framebuffer Inverted");
364
365 return err;
366 }
367
cmd_get_fonts(const struct shell * sh,size_t argc,char * argv[])368 static int cmd_get_fonts(const struct shell *sh, size_t argc, char *argv[])
369 {
370 int err = 0;
371 uint8_t font_height;
372 uint8_t font_width;
373
374 ARG_UNUSED(argc);
375 ARG_UNUSED(argv);
376
377 for (int idx = 0; idx < cfb_get_numof_fonts(dev); idx++) {
378 if (cfb_get_font_size(dev, idx, &font_width, &font_height)) {
379 break;
380 }
381 shell_print(sh, "idx=%d height=%d width=%d", idx,
382 font_height, font_width);
383 }
384
385 return err;
386 }
387
cmd_get_device(const struct shell * sh,size_t argc,char * argv[])388 static int cmd_get_device(const struct shell *sh, size_t argc, char *argv[])
389 {
390 int err = 0;
391
392 ARG_UNUSED(argc);
393 ARG_UNUSED(argv);
394
395 shell_print(sh, "Framebuffer Device: %s", dev->name);
396
397 return err;
398 }
399
cmd_get_param_all(const struct shell * sh,size_t argc,char * argv[])400 static int cmd_get_param_all(const struct shell *sh, size_t argc,
401 char *argv[])
402 {
403 ARG_UNUSED(argc);
404 ARG_UNUSED(argv);
405
406 for (unsigned int i = 0; i <= CFB_DISPLAY_COLS; i++) {
407 shell_print(sh, "param: %s=%d", param_name[i],
408 cfb_get_display_parameter(dev, i));
409
410 }
411
412 return 0;
413 }
414
cmd_get_param_height(const struct shell * sh,size_t argc,char * argv[])415 static int cmd_get_param_height(const struct shell *sh, size_t argc,
416 char *argv[])
417 {
418 ARG_UNUSED(argc);
419 ARG_UNUSED(argv);
420
421 shell_print(sh, "param: %s=%d", param_name[CFB_DISPLAY_HEIGHT],
422 cfb_get_display_parameter(dev, CFB_DISPLAY_HEIGHT));
423
424 return 0;
425 }
426
cmd_get_param_width(const struct shell * sh,size_t argc,char * argv[])427 static int cmd_get_param_width(const struct shell *sh, size_t argc,
428 char *argv[])
429 {
430 ARG_UNUSED(argc);
431 ARG_UNUSED(argv);
432
433 shell_print(sh, "param: %s=%d", param_name[CFB_DISPLAY_WIDTH],
434 cfb_get_display_parameter(dev, CFB_DISPLAY_WIDTH));
435
436 return 0;
437 }
438
cmd_get_param_ppt(const struct shell * sh,size_t argc,char * argv[])439 static int cmd_get_param_ppt(const struct shell *sh, size_t argc,
440 char *argv[])
441 {
442 ARG_UNUSED(argc);
443 ARG_UNUSED(argv);
444
445 shell_print(sh, "param: %s=%d", param_name[CFB_DISPLAY_PPT],
446 cfb_get_display_parameter(dev, CFB_DISPLAY_PPT));
447
448 return 0;
449 }
450
cmd_get_param_rows(const struct shell * sh,size_t argc,char * argv[])451 static int cmd_get_param_rows(const struct shell *sh, size_t argc,
452 char *argv[])
453 {
454 ARG_UNUSED(argc);
455 ARG_UNUSED(argv);
456
457 shell_print(sh, "param: %s=%d", param_name[CFB_DISPLAY_ROWS],
458 cfb_get_display_parameter(dev, CFB_DISPLAY_ROWS));
459
460 return 0;
461 }
462
cmd_get_param_cols(const struct shell * sh,size_t argc,char * argv[])463 static int cmd_get_param_cols(const struct shell *sh, size_t argc,
464 char *argv[])
465 {
466 ARG_UNUSED(argc);
467 ARG_UNUSED(argv);
468
469 shell_print(sh, "param: %s=%d", param_name[CFB_DISPLAY_COLS],
470 cfb_get_display_parameter(dev, CFB_DISPLAY_COLS));
471
472 return 0;
473 }
474
cmd_init(const struct shell * sh,size_t argc,char * argv[])475 static int cmd_init(const struct shell *sh, size_t argc, char *argv[])
476 {
477 int err;
478
479 if (!device_is_ready(dev)) {
480 shell_error(sh, "Display device not ready");
481 return -ENODEV;
482 }
483
484 err = display_set_pixel_format(dev, PIXEL_FORMAT_MONO10);
485 if (err) {
486 err = display_set_pixel_format(dev, PIXEL_FORMAT_MONO01);
487 if (err) {
488 shell_error(sh, "Failed to set required pixel format: %d", err);
489 return err;
490 }
491 }
492
493 err = display_blanking_off(dev);
494 if (err) {
495 shell_error(sh, "Failed to turn off display blanking: %d", err);
496 return err;
497 }
498
499 err = cfb_framebuffer_init(dev);
500 if (err) {
501 shell_error(sh, "Framebuffer initialization failed!");
502 return err;
503 }
504
505 shell_print(sh, "Framebuffer initialized: %s", dev->name);
506 cmd_clear(sh, argc, argv);
507
508 return err;
509 }
510
511 SHELL_STATIC_SUBCMD_SET_CREATE(sub_cmd_get_param,
512
513 SHELL_CMD_ARG(all, NULL, NULL, cmd_get_param_all, 1, 0),
514 SHELL_CMD_ARG(height, NULL, NULL, cmd_get_param_height, 1, 0),
515 SHELL_CMD_ARG(width, NULL, NULL, cmd_get_param_width, 1, 0),
516 SHELL_CMD_ARG(ppt, NULL, NULL, cmd_get_param_ppt, 1, 0),
517 SHELL_CMD_ARG(rows, NULL, NULL, cmd_get_param_rows, 1, 0),
518 SHELL_CMD_ARG(cols, NULL, NULL, cmd_get_param_cols, 1, 0),
519 SHELL_SUBCMD_SET_END
520 );
521
522 SHELL_STATIC_SUBCMD_SET_CREATE(sub_cmd_scroll,
523
524 SHELL_CMD_ARG(vertical, NULL, HELP_PRINT, cmd_scroll_vert, 4, 0),
525 SHELL_CMD_ARG(horizontal, NULL, HELP_PRINT, cmd_scroll_horz, 4, 0),
526 SHELL_SUBCMD_SET_END
527 );
528
529 SHELL_STATIC_SUBCMD_SET_CREATE(sub_cmd_draw,
530 SHELL_CMD_ARG(text, NULL, HELP_PRINT, cmd_draw_text, 4, 0),
531 SHELL_CMD_ARG(point, NULL, HELP_DRAW_POINT, cmd_draw_point, 3, 0),
532 SHELL_CMD_ARG(line, NULL, HELP_DRAW_LINE, cmd_draw_line, 5, 0),
533 SHELL_CMD_ARG(rect, NULL, HELP_DRAW_RECT, cmd_draw_rect, 5, 0),
534 SHELL_CMD_ARG(circle, NULL, HELP_DRAW_RECT, cmd_draw_circle, 4, 0),
535 SHELL_SUBCMD_SET_END
536 );
537
538 SHELL_STATIC_SUBCMD_SET_CREATE(cfb_cmds,
539 SHELL_CMD_ARG(init, NULL, HELP_NONE, cmd_init, 1, 0),
540 SHELL_CMD_ARG(get_device, NULL, HELP_NONE, cmd_get_device, 1, 0),
541 SHELL_CMD(get_param, &sub_cmd_get_param,
542 "<all, height, width, ppt, rows, cols>", NULL),
543 SHELL_CMD_ARG(get_fonts, NULL, HELP_NONE, cmd_get_fonts, 1, 0),
544 SHELL_CMD_ARG(set_font, NULL, "<idx>", cmd_set_font, 2, 0),
545 SHELL_CMD_ARG(set_kerning, NULL, "<kerning>", cmd_set_kerning, 2, 0),
546 SHELL_CMD_ARG(invert, NULL, HELP_INVERT, cmd_invert, 1, 5),
547 SHELL_CMD_ARG(print, NULL, HELP_PRINT, cmd_print, 4, 0),
548 SHELL_CMD(scroll, &sub_cmd_scroll, "scroll a text in vertical or "
549 "horizontal direction", NULL),
550 SHELL_CMD(draw, &sub_cmd_draw, "drawing text", NULL),
551 SHELL_CMD_ARG(clear, NULL, HELP_NONE, cmd_clear, 1, 0),
552 SHELL_SUBCMD_SET_END
553 );
554
555 SHELL_CMD_REGISTER(cfb, &cfb_cmds, "Character Framebuffer shell commands",
556 NULL);
557