summaryrefslogtreecommitdiffstats
path: root/common/lcd_console.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/lcd_console.c')
-rw-r--r--common/lcd_console.c215
1 files changed, 215 insertions, 0 deletions
diff --git a/common/lcd_console.c b/common/lcd_console.c
new file mode 100644
index 0000000000..f948e5a113
--- /dev/null
+++ b/common/lcd_console.c
@@ -0,0 +1,215 @@
+/*
+ * (C) Copyright 2001-2014
+ * DENX Software Engineering -- wd@denx.de
+ * Compulab Ltd - http://compulab.co.il/
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <lcd.h>
+#include <video_font.h> /* Get font data, width and height */
+
+#define CONSOLE_ROW_SIZE (VIDEO_FONT_HEIGHT * lcd_line_length)
+#define CONSOLE_ROW_FIRST lcd_console_address
+#define CONSOLE_ROW_SECOND (lcd_console_address + CONSOLE_ROW_SIZE)
+#define CONSOLE_ROW_LAST (lcd_console_address + CONSOLE_SIZE \
+ - CONSOLE_ROW_SIZE)
+#define CONSOLE_SIZE (CONSOLE_ROW_SIZE * console_rows)
+#define CONSOLE_SCROLL_SIZE (CONSOLE_SIZE - CONSOLE_ROW_SIZE)
+
+static short console_curr_col;
+static short console_curr_row;
+static short console_cols;
+static short console_rows;
+static void *lcd_console_address;
+
+void lcd_init_console(void *address, int rows, int cols)
+{
+ console_curr_col = 0;
+ console_curr_row = 0;
+ console_cols = cols;
+ console_rows = rows;
+ lcd_console_address = address;
+}
+
+void lcd_set_col(short col)
+{
+ console_curr_col = col;
+}
+
+void lcd_set_row(short row)
+{
+ console_curr_row = row;
+}
+
+void lcd_position_cursor(unsigned col, unsigned row)
+{
+ console_curr_col = min_t(short, col, console_cols - 1);
+ console_curr_row = min_t(short, row, console_rows - 1);
+}
+
+int lcd_get_screen_rows(void)
+{
+ return console_rows;
+}
+
+int lcd_get_screen_columns(void)
+{
+ return console_cols;
+}
+
+static void lcd_drawchars(ushort x, ushort y, uchar *str, int count)
+{
+ uchar *dest;
+ ushort row;
+ int fg_color, bg_color;
+
+ dest = (uchar *)(lcd_console_address +
+ y * lcd_line_length + x * NBITS(LCD_BPP) / 8);
+
+ for (row = 0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) {
+ uchar *s = str;
+ int i;
+#if LCD_BPP == LCD_COLOR16
+ ushort *d = (ushort *)dest;
+#elif LCD_BPP == LCD_COLOR32
+ u32 *d = (u32 *)dest;
+#else
+ uchar *d = dest;
+#endif
+
+ fg_color = lcd_getfgcolor();
+ bg_color = lcd_getbgcolor();
+ for (i = 0; i < count; ++i) {
+ uchar c, bits;
+
+ c = *s++;
+ bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row];
+
+ for (c = 0; c < 8; ++c) {
+ *d++ = (bits & 0x80) ? fg_color : bg_color;
+ bits <<= 1;
+ }
+ }
+ }
+}
+
+static inline void lcd_putc_xy(ushort x, ushort y, uchar c)
+{
+ lcd_drawchars(x, y, &c, 1);
+}
+
+static void console_scrollup(void)
+{
+ const int rows = CONFIG_CONSOLE_SCROLL_LINES;
+ int bg_color = lcd_getbgcolor();
+
+ /* Copy up rows ignoring those that will be overwritten */
+ memcpy(CONSOLE_ROW_FIRST,
+ lcd_console_address + CONSOLE_ROW_SIZE * rows,
+ CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows);
+
+ /* Clear the last rows */
+#if (LCD_BPP != LCD_COLOR32)
+ memset(lcd_console_address + CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows,
+ bg_color, CONSOLE_ROW_SIZE * rows);
+#else
+ u32 *ppix = lcd_console_address +
+ CONSOLE_SIZE - CONSOLE_ROW_SIZE * rows;
+ u32 i;
+ for (i = 0;
+ i < (CONSOLE_ROW_SIZE * rows) / NBYTES(panel_info.vl_bpix);
+ i++) {
+ *ppix++ = bg_color;
+ }
+#endif
+ lcd_sync();
+ console_curr_row -= rows;
+}
+
+static inline void console_back(void)
+{
+ if (--console_curr_col < 0) {
+ console_curr_col = console_cols - 1;
+ if (--console_curr_row < 0)
+ console_curr_row = 0;
+ }
+
+ lcd_putc_xy(console_curr_col * VIDEO_FONT_WIDTH,
+ console_curr_row * VIDEO_FONT_HEIGHT, ' ');
+}
+
+static inline void console_newline(void)
+{
+ console_curr_col = 0;
+
+ /* Check if we need to scroll the terminal */
+ if (++console_curr_row >= console_rows)
+ console_scrollup();
+ else
+ lcd_sync();
+}
+
+void lcd_putc(const char c)
+{
+ if (!lcd_is_enabled) {
+ serial_putc(c);
+
+ return;
+ }
+
+ switch (c) {
+ case '\r':
+ console_curr_col = 0;
+
+ return;
+ case '\n':
+ console_newline();
+
+ return;
+ case '\t': /* Tab (8 chars alignment) */
+ console_curr_col += 8;
+ console_curr_col &= ~7;
+
+ if (console_curr_col >= console_cols)
+ console_newline();
+
+ return;
+ case '\b':
+ console_back();
+
+ return;
+ default:
+ lcd_putc_xy(console_curr_col * VIDEO_FONT_WIDTH,
+ console_curr_row * VIDEO_FONT_HEIGHT, c);
+ if (++console_curr_col >= console_cols)
+ console_newline();
+ }
+}
+
+void lcd_puts(const char *s)
+{
+ if (!lcd_is_enabled) {
+ serial_puts(s);
+
+ return;
+ }
+
+ while (*s)
+ lcd_putc(*s++);
+
+ lcd_sync();
+}
+
+void lcd_printf(const char *fmt, ...)
+{
+ va_list args;
+ char buf[CONFIG_SYS_PBSIZE];
+
+ va_start(args, fmt);
+ vsprintf(buf, fmt, args);
+ va_end(args);
+
+ lcd_puts(buf);
+}
OpenPOWER on IntegriCloud