uboot/common/lcd_console.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2001-2015
   4 * DENX Software Engineering -- wd@denx.de
   5 * Compulab Ltd - http://compulab.co.il/
   6 * Bernecker & Rainer Industrieelektronik GmbH - http://www.br-automation.com
   7 */
   8
   9#include <common.h>
  10#include <command.h>
  11#include <lcd.h>
  12#include <log.h>
  13#include <serial.h>
  14#include <video_font.h>         /* Get font data, width and height */
  15#if defined(CONFIG_LCD_LOGO)
  16#include <bmp_logo.h>
  17#endif
  18
  19static struct console_t cons;
  20
  21void lcd_set_col(short col)
  22{
  23        cons.curr_col = col;
  24}
  25
  26void lcd_set_row(short row)
  27{
  28        cons.curr_row = row;
  29}
  30
  31void lcd_position_cursor(unsigned col, unsigned row)
  32{
  33        cons.curr_col = min_t(short, col, cons.cols - 1);
  34        cons.curr_row = min_t(short, row, cons.rows - 1);
  35}
  36
  37int lcd_get_screen_rows(void)
  38{
  39        return cons.rows;
  40}
  41
  42int lcd_get_screen_columns(void)
  43{
  44        return cons.cols;
  45}
  46
  47static void lcd_putc_xy0(struct console_t *pcons, ushort x, ushort y, char c)
  48{
  49        int fg_color = lcd_getfgcolor();
  50        int bg_color = lcd_getbgcolor();
  51        int i, row;
  52        fbptr_t *dst = (fbptr_t *)pcons->fbbase +
  53                                  y * pcons->lcdsizex +
  54                                  x;
  55
  56        for (row = 0; row < VIDEO_FONT_HEIGHT; row++) {
  57                uchar bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
  58                for (i = 0; i < VIDEO_FONT_WIDTH; ++i) {
  59                        *dst++ = (bits & 0x80) ? fg_color : bg_color;
  60                        bits <<= 1;
  61                }
  62                dst += (pcons->lcdsizex - VIDEO_FONT_WIDTH);
  63        }
  64}
  65
  66static inline void console_setrow0(struct console_t *pcons, u32 row, int clr)
  67{
  68        int i;
  69        fbptr_t *dst = (fbptr_t *)pcons->fbbase +
  70                                  row * VIDEO_FONT_HEIGHT *
  71                                  pcons->lcdsizex;
  72
  73        for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++)
  74                *dst++ = clr;
  75}
  76
  77static inline void console_moverow0(struct console_t *pcons,
  78                                    u32 rowdst, u32 rowsrc)
  79{
  80        int i;
  81        fbptr_t *dst = (fbptr_t *)pcons->fbbase +
  82                                  rowdst * VIDEO_FONT_HEIGHT *
  83                                  pcons->lcdsizex;
  84
  85        fbptr_t *src = (fbptr_t *)pcons->fbbase +
  86                                  rowsrc * VIDEO_FONT_HEIGHT *
  87                                  pcons->lcdsizex;
  88
  89        for (i = 0; i < (VIDEO_FONT_HEIGHT * pcons->lcdsizex); i++)
  90                *dst++ = *src++;
  91}
  92
  93static inline void console_back(void)
  94{
  95        if (--cons.curr_col < 0) {
  96                cons.curr_col = cons.cols - 1;
  97                if (--cons.curr_row < 0)
  98                        cons.curr_row = 0;
  99        }
 100
 101        cons.fp_putc_xy(&cons,
 102                        cons.curr_col * VIDEO_FONT_WIDTH,
 103                        cons.curr_row * VIDEO_FONT_HEIGHT, ' ');
 104}
 105
 106static inline void console_newline(void)
 107{
 108        const int rows = CONFIG_CONSOLE_SCROLL_LINES;
 109        int bg_color = lcd_getbgcolor();
 110        int i;
 111
 112        cons.curr_col = 0;
 113
 114        /* Check if we need to scroll the terminal */
 115        if (++cons.curr_row >= cons.rows) {
 116                for (i = 0; i < cons.rows-rows; i++)
 117                        cons.fp_console_moverow(&cons, i, i+rows);
 118                for (i = 0; i < rows; i++)
 119                        cons.fp_console_setrow(&cons, cons.rows-i-1, bg_color);
 120                cons.curr_row -= rows;
 121        }
 122        lcd_sync();
 123}
 124
 125void console_calc_rowcol(struct console_t *pcons, u32 sizex, u32 sizey)
 126{
 127        pcons->cols = sizex / VIDEO_FONT_WIDTH;
 128#if defined(CONFIG_LCD_LOGO) && !defined(CONFIG_LCD_INFO_BELOW_LOGO)
 129        pcons->rows = (pcons->lcdsizey - BMP_LOGO_HEIGHT);
 130        pcons->rows /= VIDEO_FONT_HEIGHT;
 131#else
 132        pcons->rows = sizey / VIDEO_FONT_HEIGHT;
 133#endif
 134}
 135
 136void __weak lcd_init_console_rot(struct console_t *pcons)
 137{
 138        return;
 139}
 140
 141void lcd_init_console(void *address, int vl_cols, int vl_rows, int vl_rot)
 142{
 143        memset(&cons, 0, sizeof(cons));
 144        cons.fbbase = address;
 145
 146        cons.lcdsizex = vl_cols;
 147        cons.lcdsizey = vl_rows;
 148        cons.lcdrot = vl_rot;
 149
 150        cons.fp_putc_xy = &lcd_putc_xy0;
 151        cons.fp_console_moverow = &console_moverow0;
 152        cons.fp_console_setrow = &console_setrow0;
 153        console_calc_rowcol(&cons, cons.lcdsizex, cons.lcdsizey);
 154
 155        lcd_init_console_rot(&cons);
 156
 157        debug("lcd_console: have %d/%d col/rws on scr %dx%d (%d deg rotated)\n",
 158              cons.cols, cons.rows, cons.lcdsizex, cons.lcdsizey, vl_rot);
 159}
 160
 161void lcd_putc(const char c)
 162{
 163        if (!lcd_is_enabled) {
 164                serial_putc(c);
 165
 166                return;
 167        }
 168
 169        switch (c) {
 170        case '\r':
 171                cons.curr_col = 0;
 172                return;
 173        case '\n':
 174                console_newline();
 175
 176                return;
 177        case '\t':      /* Tab (8 chars alignment) */
 178                cons.curr_col +=  8;
 179                cons.curr_col &= ~7;
 180
 181                if (cons.curr_col >= cons.cols)
 182                        console_newline();
 183
 184                return;
 185        case '\b':
 186                console_back();
 187
 188                return;
 189        default:
 190                cons.fp_putc_xy(&cons,
 191                                cons.curr_col * VIDEO_FONT_WIDTH,
 192                                cons.curr_row * VIDEO_FONT_HEIGHT, c);
 193                if (++cons.curr_col >= cons.cols)
 194                        console_newline();
 195        }
 196}
 197
 198void lcd_puts(const char *s)
 199{
 200        if (!lcd_is_enabled) {
 201                serial_puts(s);
 202
 203                return;
 204        }
 205
 206        while (*s)
 207                lcd_putc(*s++);
 208
 209        lcd_sync();
 210}
 211
 212void lcd_printf(const char *fmt, ...)
 213{
 214        va_list args;
 215        char buf[CONFIG_SYS_PBSIZE];
 216
 217        va_start(args, fmt);
 218        vsprintf(buf, fmt, args);
 219        va_end(args);
 220
 221        lcd_puts(buf);
 222}
 223
 224static int do_lcd_setcursor(struct cmd_tbl *cmdtp, int flag, int argc,
 225                            char *const argv[])
 226{
 227        unsigned int col, row;
 228
 229        if (argc != 3)
 230                return CMD_RET_USAGE;
 231
 232        col = dectoul(argv[1], NULL);
 233        row = dectoul(argv[2], NULL);
 234        lcd_position_cursor(col, row);
 235
 236        return 0;
 237}
 238
 239static int do_lcd_puts(struct cmd_tbl *cmdtp, int flag, int argc,
 240                       char *const argv[])
 241{
 242        if (argc != 2)
 243                return CMD_RET_USAGE;
 244
 245        lcd_puts(argv[1]);
 246
 247        return 0;
 248}
 249
 250U_BOOT_CMD(
 251        setcurs, 3,     1,      do_lcd_setcursor,
 252        "set cursor position within screen",
 253        "    <col> <row> in character"
 254);
 255
 256U_BOOT_CMD(
 257        lcdputs, 2,     1,      do_lcd_puts,
 258        "print string on lcd-framebuffer",
 259        "    <string>"
 260);
 261
 262