Commit b6a3bf7c authored by Léo Grange's avatar Léo Grange

move VTs cursor management to text_display interface

parent 5f2fc986
......@@ -9,6 +9,14 @@ size_t disp_mono_height() {
return 64;
}
// TODO find a way to inline these functions AND to keep generic aspect
uint32 disp_mono_get_pixel(int x, int y, void *vram) {
// no check on (x;y) to keep performances...
return !!( ((char*)vram)[y*16 + x/8] & (1 << x%8));
}
void disp_mono_draw_bitmap(int x, int y, unsigned char *bitmap, short w, short h, void *vvram)
{
unsigned char *vram = vvram;
......
#ifndef DISPLAY_T6K11_H
#define DISPLAY_T6K11_H
// real type of vram_t
typedef unsigned char *vram_t;
typedef int color_t;
struct _mono_bitmap {
unsigned char *bitmap;
int w;
int h;
};
typedef struct _mono_bitmap bitmap_t;
// Colors Typedef :
#define PIXEL_WHITE 0
#define PIXEL_BLACK 1
#define PIXEL_XOR 2
// Return 0xFFFFFFFF if it's a dark color, 0x00000000 else
unsigned int mask_color();
#endif //DISPLAY_T6K11_H
......@@ -29,6 +29,11 @@ void disp_mono_copy_to_dd(void *vram);
*/
void disp_mono_set_pixel(int x, int y, uint32 color, void *vram);
/**
* Read a pixel from the VRAM, and return its color.
*/
uint32 disp_mono_get_pixel(int x, int y, void *vram);
/**
* Returns width/height of the display, in pixels.
*/
......
......@@ -140,6 +140,18 @@ static const unsigned char _font_3x5[129][5] = {
};
// union used to be sure char_bmp is 4-bytes aligned
union bmp_fast_4x6{
unsigned char char_bmp[6]; // 4*6 bitmap, containing character and borders
unsigned int fast[2]; // for fast operations
};
// used to store/restore a single character area
static union bmp_fast_4x6 _stored_char;
void term_prim_write_character(unsigned int posx, unsigned int posy, int front_c, int back_c, char c, void *vram) {
unsigned int backcolor, frontcolor;
......@@ -152,11 +164,7 @@ void term_prim_write_character(unsigned int posx, unsigned int posy, int front_c
&& (y>-5) && (y<64))
{
const unsigned char *raw_char;
// union used to be sure char_bmp is 4-bytes aligned
union {
unsigned char char_bmp[6]; // 6*4 bitmap, containing character and borders
unsigned int fast[2]; // for fast operations
} bmp;
union bmp_fast_4x6 bmp;
if(c>=0)
raw_char = _font_3x5[(int)c];
......@@ -178,6 +186,33 @@ void term_prim_write_character(unsigned int posx, unsigned int posy, int front_c
}
void term_prim_store_character(unsigned int posx, unsigned int posy,
void *vram)
{
int x = posx * 4;
int y = posy * 6;
int i, j;
// the algorithm used here is... hum... a bit stupid and slow?
for(j=0; j<6; j++) {
char curline = 0x00;
for(i=0; i<4; i++) {
curline |= (disp_mono_get_pixel(x+i, y+j, vram)) << i;
}
_stored_char.char_bmp[j] = curline;
}
}
void term_prim_restore_character(unsigned int posx, unsigned int posy,
void *vram)
{
int x = posx * 4;
int y = posy * 6;
disp_mono_draw_bitmap(x, y, _stored_char.char_bmp, 4, 6, vram);
}
void term_prim_scroll_up(void *vram, int back_c) {
int i;
unsigned int *l_vram = (unsigned int*)vram;
......
......@@ -7,11 +7,25 @@
#define FX9860_TERM_CURSOR_CHAR ((char)177)
/**
* write a character with the terminal font
*/
void term_prim_write_character(unsigned int posx, unsigned int posy, int front_c, int back_c, char c, void *vram);
void term_prim_write_character(unsigned int posx, unsigned int posy,
int front_c, int back_c, char c, void *vram);
/**
* Special set of functions designed for cursor implementation.
* Save/restore the VRAM content of a character location (saved internally
* in a single slot, so each call to term_prim_store_character() destroy the
* previously stored data).
*/
void term_prim_store_character(unsigned int posx, unsigned int posy,
void *vram);
void term_prim_restore_character(unsigned int posx, unsigned int posy,
void *vram);
/**
* Scroll up the terminal display from 1 character high
......
......@@ -15,7 +15,10 @@ const struct text_display fx9860_text_display = {
.scroll = &fx9860_tdisp_scroll,
.set_color = &fx9860_tdisp_set_color,
.set_active = &fx9860_tdisp_set_active,
.flush = &fx9860_tdisp_flush
.flush = &fx9860_tdisp_flush,
.set_cursor_pos = &fx9860_tdisp_set_cursor_pos,
.set_cursor = &fx9860_tdisp_set_cursor
};
......@@ -23,6 +26,10 @@ const struct text_display fx9860_text_display = {
void fx9860_tdisp_init_disp(struct tdisp_data *disp) {
disp->back = 0; //TODO white
disp->front = 1; //TODO black
disp->cursx = 0;
disp->cursy = 0;
disp->cursor = TEXT_CURSOR_NORMAL;
disp->vram = arch_pm_get_free_page(MEM_PM_CACHED);
memset(disp->vram, 0, 1024);
......@@ -68,11 +75,43 @@ void fx9860_tdisp_set_color(struct tdisp_data *disp, enum text_color front,
void fx9860_tdisp_set_active(struct tdisp_data *disp, int active) {
// not a lot of stuff to do here, only update the display after activation
if(active == 1) {
disp_mono_copy_to_dd(disp->vram);
fx9860_tdisp_flush(disp);
}
}
void fx9860_tdisp_flush(struct tdisp_data *disp) {
// here is the little trick for cursor display : we display it only before
// flushing, and remove it juste before (so the VRAM is always "clean")
int cursor_displayed = 0;
if(disp->cursor != TEXT_CURSOR_DISABLE && disp->cursx < FX9860_TERM_WIDTH
&& disp->cursy < FX9860_TERM_HEIGHT)
{
cursor_displayed = 1;
term_prim_store_character(disp->cursx, disp->cursy, disp->vram);
// TODO display other kind of cursors (alpha/shift...)
term_prim_write_character(disp->cursx, disp->cursy,
DISPLAY_COLOR_BLACK, DISPLAY_COLOR_WHITE,
FX9860_TERM_CURSOR_CHAR, disp->vram);
}
disp_mono_copy_to_dd(disp->vram);
if(cursor_displayed)
term_prim_restore_character(disp->cursx, disp->cursy, disp->vram);
}
// cursor related functions are not very useful because of some tricks done
// to display it just before a display flush, but may be useful
void fx9860_tdisp_set_cursor_pos(struct tdisp_data *disp, size_t posx,
size_t posy)
{
disp->cursx = posx;
disp->cursy = posy;
}
void fx9860_tdisp_set_cursor(struct tdisp_data *disp, enum text_cursor curs) {
disp->cursor = curs;
}
......@@ -6,6 +6,12 @@
struct tdisp_data {
int front;
int back;
// data to handle the visual cursor
size_t cursx;
size_t cursy;
enum text_cursor cursor;
unsigned char *vram;
};
......@@ -26,6 +32,10 @@ void fx9860_tdisp_set_active(struct tdisp_data *disp, int active);
void fx9860_tdisp_flush(struct tdisp_data *disp);
void fx9860_tdisp_set_cursor_pos(struct tdisp_data *disp, size_t posx,
size_t posy);
void fx9860_tdisp_set_cursor(struct tdisp_data *disp, enum text_cursor curs);
#endif //_DEVICE_TERMINAL_FX9860_TEXT_DISPLAY_H
......@@ -18,6 +18,12 @@ enum text_color {
TEXT_COLOR_WHITE
};
// possible kind of cursor (will be extended to display shift/alpha modes)
enum text_cursor {
TEXT_CURSOR_DISABLE,
TEXT_CURSOR_NORMAL
};
struct text_display {
size_t cwidth;
size_t cheight;
......@@ -61,6 +67,18 @@ struct text_display {
* Should be call each time we need to be sure the display is up to date.
*/
void (*flush)(struct tdisp_data *disp);
/**
* Set cursor position, if supported.
* Cursor in text_display interface is only a visual hint, it does nothing
* like controlling where characters are displayed!
*/
void (*set_cursor_pos)(struct tdisp_data *disp, size_t posx, size_t posy);
/**
* Set cursor type, if supported.
*/
void (*set_cursor)(struct tdisp_data *disp, enum text_cursor curs);
};
......
......@@ -146,20 +146,15 @@ void vt_init() {
/**
* Move the cursor from its current position to (newx, newy), after checking
* screen boundaries.
* TODO the cursor should be implemented in terminal_disp directly to avoid
* overwriting characters when moving it using VT100 sequences!
*/
static void vt_move_cursor(struct vt_instance *term, int newx, int newy) {
_tdisp->print_char(& term->disp, term->posx, term->posy, ' ');
term->posx = newx > _tdisp->cwidth-1 ? _tdisp->cwidth-1
: (newx < 0 ? 0 : newx);
term->posy = newy > _tdisp->cheight-1 ? _tdisp->cheight-1
: (newy < 0 ? 0 : newy);
// print cursor at current position
_tdisp->print_char(& term->disp, term->posx, term->posy,
VT_CURSOR_CHAR);
_tdisp->set_cursor_pos(& term->disp, term->posx, term->posy);
_tdisp->flush(& term->disp);
}
......@@ -362,47 +357,40 @@ static void vt_read_escape_code(struct vt_instance *term, char str_char) {
/**
* Echo a character to the screen, without flushing to display driver
*/
static void vt_echo_char(struct vt_instance *term, char c, int mayesc) {
if(!mayesc || (term->esc_state.discovery_state == VT100_STATE_NONE
&& c != '\x1B'))
{
static void vt_echo_char(struct vt_instance *term, char c) {
if((term->esc_state.discovery_state == VT100_STATE_NONE && c != '\x1B')) {
// We aren't in a vt100 escape code
if(c == '\b') {
// backspace, should only go back (non destructive)
_tdisp->print_char(& term->disp, term->posx, term->posy, ' ');
term->posx--;
if(term->posx < 0) {
// this behavior is not POSIX, but (very?) useful
term->posx = _tdisp->cwidth - 1;
term->posy--;
}
// print cursor at current position
_tdisp->print_char(& term->disp, term->posx, term->posy,
VT_CURSOR_CHAR);
}
else if(c == '\n') {
// remove the current cursor display before line feed
_tdisp->print_char(& term->disp, term->posx, term->posy, ' ');
term->posx = 0;
term->posy++;
}
else if(c == '\r') term->posx=0;
else {
// any other character should just be displayed
_tdisp->print_char(& term->disp, term->posx, term->posy, c);
term->posx++;
}
if(term->posx >= _tdisp->cwidth) {
term->posx = 0;
term->posy++;
}
if(term->posy >= _tdisp->cheight) {
_tdisp->scroll(&term->disp);
term->posy = _tdisp->cheight - 1;
}
}
_tdisp->set_cursor_pos(& term->disp, term->posx, term->posy);
}
else {
// parse the character as a part of a VT100-like escape sequence
......@@ -411,25 +399,18 @@ static void vt_echo_char(struct vt_instance *term, char c, int mayesc) {
}
/**
* Function used to print characters (as well written to term and echoed input from
* keyboard).
* If mayesc is not-zero, try to check VT100-like escape sequences from source data.
* Function used to print characters (as well written to term and echoed input
* from keyboard).
*/
static void vt_term_print(struct vt_instance *term, const void *source, size_t len,
int mayesc)
static void vt_term_print(struct vt_instance *term, const void *source,
size_t len)
{
int i;
const unsigned char *str = source;
for(i=0; i<len; i++) {
vt_echo_char(term, str[i], mayesc);
vt_echo_char(term, str[i]);
}
// print cursor at current position
_tdisp->print_char(& term->disp, term->posx, term->posy, VT_CURSOR_CHAR);
// TODO flush only if active!
//disp_mono_copy_to_dd(_term_vram);
}
......@@ -437,10 +418,8 @@ static void vt_term_print(struct vt_instance *term, const void *source, size_t l
// called by TTY driver to display a single character, be kind and flush disp
static int vt_tty_putchar(struct tty *tty, char c) {
struct vt_instance *term = tty->private;
vt_echo_char((struct vt_instance *)(tty->private), c, 1);
vt_echo_char(term, c);
// TODO flush only if active?
_tdisp->print_char(& term->disp, term->posx, term->posy, VT_CURSOR_CHAR);
_tdisp->flush(& term->disp);
return 0;
}
......@@ -493,7 +472,7 @@ static struct tty *vt_get_tty(uint16 minor) {
static ssize_t vt_prim_write(struct vt_instance *term, const void *source, size_t len) {
vt_term_print(term, source, len, 1);
vt_term_print(term, source, len);
// screen should be flushed only if it's the current active
if(term == &_vts[_vt_current])
......
#include "tests.h"
#include "device/display/T6K11/T6K11.h"
#include "device/terminal/generic_early_term.h"
#include "arch/sh/interrupt.h"
#include "arch/sh/mmu.h"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment