console.c 4.0 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
#include <rtthread.h>

#include <serial.h>

#define RT_CONSOLE_WIDTH		240
#define RT_CONSOLE_HEIGHT		320

#define RT_CONSOLE_FONT_WIDTH	8
#define RT_CONSOLE_FONT_HEIGHT	16

#define RT_CONSOLE_COL			(RT_CONSOLE_WIDTH/RT_CONSOLE_FONT_WIDTH)
#define RT_CONSOLE_ROW			(RT_CONSOLE_HEIGHT/RT_CONSOLE_FONT_HEIGHT)

#define RT_CONSOLE_TAB			4

#define RT_CONSOLE_FOREPIXEL	(0x001f)

extern struct serial_device uart2;

struct rt_console
{
	rt_uint8_t* video_ptr;
	rt_uint8_t* font_ptr;

	/* bpp and pixel of width */
	rt_uint8_t bpp;
	rt_uint32_t pitch;

	/* current cursor */
	rt_uint8_t current_col;
	rt_uint8_t current_row;
};
struct rt_console console;

void rt_hw_console_init(rt_uint8_t* video_ptr, rt_uint8_t* font_ptr, rt_uint8_t bpp);
void rt_hw_console_newline(void);
void rt_hw_console_putc(char c);
void rt_hw_console_clear(void);

void rt_hw_console_init(rt_uint8_t* video_ptr, rt_uint8_t* font_ptr, rt_uint8_t bpp)
{
	rt_memset(&console, 0, sizeof(struct rt_console));

	console.video_ptr = video_ptr;
	console.font_ptr = font_ptr;
	console.bpp = bpp;
	console.pitch = console.bpp * RT_CONSOLE_WIDTH;

	rt_hw_console_clear();
}

void rt_hw_console_putc(char c)
{
	switch (c)
	{
        case 10:
        case 11:
        case 12:
        case 13:
			/* to next line */
            rt_hw_console_newline();
            console.current_col = 0;
            break;

        case 9:
            console.current_col += RT_CONSOLE_TAB;
            break;

        default:
			{
				rt_uint8_t* font_ptr;
				register rt_uint32_t cursor;
				register rt_uint32_t i, j;

				if (console.current_col == RT_CONSOLE_COL)
				{
					rt_hw_console_newline();
					console.current_col = 0;

					rt_hw_console_putc(c);
					return;
				}

				font_ptr = console.font_ptr + c * RT_CONSOLE_FONT_HEIGHT;
				cursor = (console.current_row * RT_CONSOLE_FONT_HEIGHT) * console.pitch
					+ console.current_col * RT_CONSOLE_FONT_WIDTH * console.bpp;

				for (i = 0; i < RT_CONSOLE_FONT_HEIGHT; i ++ )
				{
					for (j = 0; j < RT_CONSOLE_FONT_WIDTH; j ++)
					{
						if ( ((font_ptr[i] >> (7-j)) & 0x01) != 0 )
						{
							/* draw a pixel */
							rt_uint8_t *ptr = &(console.video_ptr[cursor + i * console.pitch + j * console.bpp]);
							switch(console.bpp)
							{
							case 1:
								*ptr = RT_CONSOLE_FOREPIXEL;
								break;
							case 2:
								*(rt_uint16_t*)ptr = RT_CONSOLE_FOREPIXEL;
								break;
							case 3:
								ptr[0] = RT_CONSOLE_FOREPIXEL & 0xff;
								ptr[1] = (RT_CONSOLE_FOREPIXEL >> 8) & 0xff;
								ptr[2] = (RT_CONSOLE_FOREPIXEL >> 16) & 0xff;
								break;
							case 4:
								*(rt_uint32_t*)ptr = RT_CONSOLE_FOREPIXEL;
								break;
							}
						}
					}
				}

				console.current_col ++;
			}
			break;
	}
}

void rt_hw_console_newline()
{
	console.current_row ++;
	if (console.current_row >= RT_CONSOLE_ROW)
	{
		rt_uint32_t i;

		/* scroll to next line */
		for (i = 0; i < RT_CONSOLE_ROW - 1; i ++)
		{
			rt_memcpy(console.video_ptr + i * RT_CONSOLE_FONT_HEIGHT * console.pitch,
				console.video_ptr + (i + 1) * RT_CONSOLE_FONT_HEIGHT * console.pitch,
				RT_CONSOLE_FONT_HEIGHT * console.pitch);
		}

		/* clear last line */
		rt_memset(console.video_ptr + (RT_CONSOLE_ROW - 1) * RT_CONSOLE_FONT_HEIGHT * console.pitch,
			0,
			RT_CONSOLE_FONT_HEIGHT * console.pitch);

		console.current_row = RT_CONSOLE_ROW - 1;
	}
}

void rt_hw_console_clear()
{
	console.current_col = 0;
	console.current_row = 0;

	rt_memset(console.video_ptr, 0, RT_CONSOLE_HEIGHT * console.pitch);
}

/* write one character to serial, must not trigger interrupt */
void rt_hw_serial_putc(const char c)
{
	/*
		to be polite with serial console add a line feed
		to the carriage return character
	*/
	if (c=='\n')rt_hw_serial_putc('\r');

	while (!(uart2.uart_device->SSR & SSR_TDRE));
	uart2.uart_device->TDR = (c & 0x1FF);
}

/**
 * This function is used by rt_kprintf to display a string on console.
 *
 * @param str the displayed string
 */
void rt_hw_console_output(const char* str)
{
	while (*str)
	{
		rt_hw_serial_putc(*str++);
	}
}