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